diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 271417e..f13aabc 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -34,6 +34,7 @@ 9.0.1.jre7 7.0.0-RC3-og 3.9.2 + 2.0.8 2.3.6 @@ -58,7 +59,7 @@ 1.7.0.Beta2 5.8.47 6.0.0-M22 - 1.3.0 + 2.1.0-incubating 5.4.4 2.4.1 2.0.65 @@ -312,6 +313,12 @@ ${taos.version} + + org.apache.iotdb + iotdb-jdbc + ${iotdb.version} + + cn.iocoder.boot @@ -509,9 +516,9 @@ - cn.idev.excel - fastexcel - ${fastexcel.version} + org.apache.fesod + fesod-sheet + ${fesod.version} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml index b121818..b080e3b 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml @@ -42,8 +42,8 @@ - cn.idev.excel - fastexcel + org.apache.fesod + fesod-sheet diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java index 1875675..c1ed09d 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java @@ -3,13 +3,13 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.hutool.core.convert.Convert; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; import lombok.extern.slf4j.Slf4j; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; /** * Excel 数据地区转换器 diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java index b9e0dcb..0489ca2 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java @@ -3,13 +3,13 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.hutool.core.convert.Convert; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; import lombok.extern.slf4j.Slf4j; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; /** * Excel 数据字典转换器 diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java index 6958c32..e8949b9 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; /** * Excel Json 转换器 diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java index 9ed0bd5..bbccc8d 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.excel.core.convert; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import java.math.BigDecimal; import java.math.RoundingMode; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvert.java index a0678a7..ebf001b 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvert.java @@ -4,13 +4,13 @@ import cn.hutool.core.convert.Convert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; import lombok.extern.slf4j.Slf4j; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import java.lang.reflect.Array; import java.lang.reflect.Field; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/StringListConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/StringListConvert.java index 5d391b0..f4ce930 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/StringListConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/StringListConvert.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; -import cn.idev.excel.converters.Converter; -import cn.idev.excel.metadata.GlobalConfiguration; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.metadata.GlobalConfiguration; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import java.util.Collections; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java index 33344da..ece2873 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.framework.excel.core.handler; import cn.hutool.core.collection.CollUtil; -import cn.idev.excel.enums.CellDataTypeEnum; -import cn.idev.excel.metadata.Head; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.util.MapUtils; -import cn.idev.excel.write.metadata.holder.WriteSheetHolder; -import cn.idev.excel.write.style.column.AbstractColumnWidthStyleStrategy; -import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import org.apache.fesod.common.util.MapUtils; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.metadata.Head; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.write.metadata.holder.WriteSheetHolder; +import org.apache.fesod.sheet.write.style.column.AbstractColumnWidthStyleStrategy; +import org.apache.fesod.sheet.write.style.column.LongestMatchColumnWidthStyleStrategy; import org.apache.poi.ss.usermodel.Cell; import java.nio.charset.StandardCharsets; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java index dbbda2d..4849067 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java @@ -10,13 +10,13 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction; -import cn.idev.excel.annotation.ExcelIgnore; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; -import cn.idev.excel.write.handler.SheetWriteHandler; -import cn.idev.excel.write.metadata.holder.WriteSheetHolder; -import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder; import lombok.extern.slf4j.Slf4j; +import org.apache.fesod.sheet.annotation.ExcelIgnore; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; +import org.apache.fesod.sheet.write.handler.SheetWriteHandler; +import org.apache.fesod.sheet.write.metadata.holder.WriteSheetHolder; +import org.apache.fesod.sheet.write.metadata.holder.WriteWorkbookHolder; import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.ss.usermodel.*; import org.apache.poi.ss.util.CellRangeAddressList; @@ -86,7 +86,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { /** * 判断字段是否是静态的、最终的、 transient 的 - * 原因:FastExcel 默认是忽略 static final 或 transient 的字段,所以需要判断 + * 原因:Fesod 默认是忽略 static final 或 transient 的字段,所以需要判断 * * @param field 字段 * @return 是否是静态的、最终的、transient 的 diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index d771d18..c40bfbd 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,13 +1,15 @@ package cn.iocoder.yudao.framework.excel.core.util; -import cn.idev.excel.FastExcelFactory; -import cn.idev.excel.context.AnalysisContext; -import cn.idev.excel.converters.longconverter.LongStringConverter; -import cn.idev.excel.read.listener.ReadListener; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; import jakarta.servlet.http.HttpServletResponse; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.context.AnalysisContext; +import org.apache.fesod.sheet.converters.Converter; +import org.apache.fesod.sheet.converters.longconverter.LongStringConverter; +import org.apache.fesod.sheet.enums.CellDataTypeEnum; +import org.apache.fesod.sheet.read.listener.ReadListener; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -25,6 +27,21 @@ import java.util.Map; public class ExcelUtils { /** + * Long 转 String 的转换器,避免 Long 类型丢失精度 + * + * 参考 https://t.zsxq.com/a0w1V 帖子:Fesod 写入 xlsx 时,按 supportExcelTypeKey 为 null 查找全局转换器, + * 所以需要返回 null,否则 registerConverter 的 LongStringConverter 不生效。关联 https://github.com/apache/fesod/issues/648 + */ + private static final Converter LONG_STRING_CONVERTER = new LongStringConverter() { + + @Override + public CellDataTypeEnum supportExcelTypeKey() { + return null; + } + + }; + + /** * 将列表以 Excel 响应给前端 * * @param response 响应 @@ -38,11 +55,11 @@ public class ExcelUtils { public static void write(HttpServletResponse response, String filename, String sheetName, Class head, List data) throws IOException { // 输出 Excel - FastExcelFactory.write(response.getOutputStream(), head) + FesodSheet.write(response.getOutputStream(), head) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .registerWriteHandler(new ColumnWidthMatchStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框 - .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 + .registerConverter(LONG_STRING_CONVERTER) // 避免 Long 类型丢失精度 .sheet(sheetName).doWrite(data); // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename)); @@ -62,10 +79,10 @@ public class ExcelUtils { public static void write(HttpServletResponse response, String filename, String sheetName, List> head, List> data) throws IOException { // 输出 Excel - FastExcelFactory.write(response.getOutputStream()) + FesodSheet.write(response.getOutputStream()) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .registerWriteHandler(new ColumnWidthMatchStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 - .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 + .registerConverter(LONG_STRING_CONVERTER) // 避免 Long 类型丢失精度 .head(head).sheet(sheetName).doWrite(data); // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了 response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename)); @@ -78,7 +95,7 @@ public class ExcelUtils { } // 参考 https://t.zsxq.com/zM77F 帖子,增加 try 处理,兼容 windows 场景 try (InputStream inputStream = file.getInputStream()) { - return FastExcelFactory.read(inputStream, head, null) + return FesodSheet.read(inputStream, head, null) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .doReadAllSync(); } @@ -101,7 +118,7 @@ public class ExcelUtils { } List rows = new ArrayList<>(Math.min(maxRowCount, 1024)); try (InputStream inputStream = file.getInputStream()) { - FastExcelFactory.read(inputStream, head, new ReadListener() { + FesodSheet.read(inputStream, head, new ReadListener() { @Override public void invoke(T data, AnalysisContext context) { @@ -136,7 +153,7 @@ public class ExcelUtils { } // 参考 https://t.zsxq.com/zM77F 帖子,增加 try 处理,兼容 windows 场景 try (InputStream inputStream = file.getInputStream()) { - return FastExcelFactory.read(inputStream) + return FesodSheet.read(inputStream) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .headRowNumber(1) .sheet() diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/PoiExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/PoiExcelUtils.java index 933d348..331d97d 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/PoiExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/PoiExcelUtils.java @@ -27,7 +27,7 @@ import java.util.Collection; /** * 原生 POI 的 Excel 工具类 * - * 全局 {@link ExcelUtils}(FastExcel)无法表达单元格锁定、公式、动态列等复杂模板时,各模块基于本类实现自定义 Excel 读写 + * 全局 {@link ExcelUtils}(Fesod)无法表达单元格锁定、公式、动态列等复杂模板时,各模块基于本类实现自定义 Excel 读写 * * @author 芋道源码 */ diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java index 72c3ac4..2bdf216 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java @@ -1,4 +1,4 @@ /** - * 基于 FastExcel 实现 Excel 相关的操作 + * 基于 Fesod 实现 Excel 相关的操作 */ package cn.iocoder.yudao.framework.excel; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvertTest.java b/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvertTest.java index 202695c..1b03ad1 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvertTest.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvertTest.java @@ -1,14 +1,14 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.hutool.core.collection.ListUtil; -import cn.idev.excel.metadata.data.ReadCellData; -import cn.idev.excel.metadata.data.WriteCellData; -import cn.idev.excel.metadata.property.ExcelContentProperty; import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi; import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import org.apache.fesod.sheet.metadata.data.ReadCellData; +import org.apache.fesod.sheet.metadata.data.WriteCellData; +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.Mock; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategyTest.java b/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategyTest.java index c45383c..19824ac 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategyTest.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategyTest.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.excel.core.handler; -import cn.idev.excel.FastExcelFactory; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.annotation.ExcelProperty; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.jupiter.api.Test; @@ -59,7 +59,7 @@ public class ColumnWidthMatchStyleStrategyTest { private XSSFWorkbook write(List rows) throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - FastExcelFactory.write(outputStream, TestRow.class) + FesodSheet.write(outputStream, TestRow.class) .registerWriteHandler(new ColumnWidthMatchStyleStrategy()).sheet().doWrite(rows); return new XSSFWorkbook(new ByteArrayInputStream(outputStream.toByteArray())); } diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtilsTest.java b/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtilsTest.java index c6964d5..d8f30b6 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtilsTest.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtilsTest.java @@ -1,28 +1,122 @@ package cn.iocoder.yudao.framework.excel.core.util; -import cn.idev.excel.FastExcelFactory; -import cn.idev.excel.annotation.ExcelProperty; +import cn.hutool.core.collection.ListUtil; +import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi; +import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO; +import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import lombok.Data; +import lombok.experimental.Accessors; +import org.apache.fesod.sheet.FesodSheet; +import org.apache.fesod.sheet.annotation.ExcelProperty; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; +import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import org.mockito.Mock; +import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.mock.web.MockMultipartFile; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.Arrays; +import java.util.Collections; import java.util.List; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.when; /** * {@link ExcelUtils} 的单元测试 * * @author 芋道源码 */ -public class ExcelUtilsTest { +public class ExcelUtilsTest extends BaseMockitoUnitTest { + + private static final String DICT_TYPE = "test_status"; + + @Mock + private DictDataCommonApi dictDataApi; + + @BeforeEach + public void setUp() { + DictFrameworkUtils.init(dictDataApi); + DictFrameworkUtils.clearCache(); + } + + /** + * 字段未配置 converter 的 Long 编号,需要导出为文本,避免丢失精度 + */ + @Test + public void testWrite_class() throws Exception { + // mock 数据 + mockDictDatas(); + // 准备参数 + MockHttpServletResponse response = new MockHttpServletResponse(); + List list = Arrays.asList( + new TestUser().setId(1981234567890123456L).setAge(18).setStatus(0), + new TestUser().setId(Long.MAX_VALUE).setAge(20).setStatus(1)); + + // 调用 + ExcelUtils.write(response, "用户.xls", "数据", TestUser.class, list); + // 断言 + try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) { + Sheet sheet = workbook.getSheet("数据"); + // 断言 Long 编号 + assertStringCell("1981234567890123456", sheet.getRow(1).getCell(0)); + assertStringCell("9223372036854775807", sheet.getRow(2).getCell(0)); + // 断言普通数值 + assertNumericCell(18, sheet.getRow(1).getCell(1)); + assertNumericCell(20, sheet.getRow(2).getCell(1)); + // 断言字典转换 + assertStringCell("开启", sheet.getRow(1).getCell(2)); + assertStringCell("关闭", sheet.getRow(2).getCell(2)); + // 断言下拉框 + assertNotNull(workbook.getSheet("字典sheet")); + assertEquals(1, sheet.getDataValidations().size()); + // 断言列宽:19 位 Long 字符串,加上 2 个字符的留白 + assertEquals((19 + 2) * 256, sheet.getColumnWidth(0)); + } + } + + @Test + public void testWrite_dynamicHead() throws Exception { + // 准备参数 + MockHttpServletResponse response = new MockHttpServletResponse(); + List> head = Arrays.asList(Collections.singletonList("编号"), Collections.singletonList("年龄")); + List> list = Arrays.asList( + Arrays.asList(1981234567890123456L, 18), + Arrays.asList(Long.MAX_VALUE, 20)); + + // 调用 + ExcelUtils.write(response, "用户.xls", "数据", head, list); + // 断言 + try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) { + Sheet sheet = workbook.getSheet("数据"); + assertStringCell("编号", sheet.getRow(0).getCell(0)); + // 断言 Long 编号 + assertStringCell("1981234567890123456", sheet.getRow(1).getCell(0)); + assertStringCell("9223372036854775807", sheet.getRow(2).getCell(0)); + // 断言普通数值 + assertNumericCell(18, sheet.getRow(1).getCell(1)); + assertNumericCell(20, sheet.getRow(2).getCell(1)); + } + } @Test public void testRead_maxRowCount() throws Exception { // mock 数据 ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - FastExcelFactory.write(outputStream, TestRow.class).sheet().doWrite(Arrays.asList( + FesodSheet.write(outputStream, TestRow.class).sheet().doWrite(Arrays.asList( new TestRow("员工一"), new TestRow("员工二"), new TestRow("员工三"))); MockMultipartFile file = new MockMultipartFile( "file", "employees.xlsx", null, outputStream.toByteArray()); @@ -36,6 +130,41 @@ public class ExcelUtilsTest { assertEquals("员工二", rows.get(1).getName()); } + private void mockDictDatas() { + List dictDatas = ListUtil.of( + randomPojo(DictDataRespDTO.class, o -> o.setDictType(DICT_TYPE).setValue("0").setLabel("开启")), + randomPojo(DictDataRespDTO.class, o -> o.setDictType(DICT_TYPE).setValue("1").setLabel("关闭")) + ); + when(dictDataApi.getDictDataList(eq(DICT_TYPE))).thenReturn(dictDatas); + } + + private static void assertStringCell(String expected, Cell cell) { + assertEquals(CellType.STRING, cell.getCellType()); + assertEquals(expected, cell.getStringCellValue()); + } + + private static void assertNumericCell(double expected, Cell cell) { + assertEquals(CellType.NUMERIC, cell.getCellType()); + assertEquals(expected, cell.getNumericCellValue()); + } + + @Data + @Accessors(chain = true) + public static class TestUser { + + @ExcelProperty("编号") + private Long id; + + @ExcelProperty("年龄") + private Integer age; + + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(DICT_TYPE) + @ExcelColumnSelect(dictType = DICT_TYPE) + private Integer status; + + } + public static class TestRow { @ExcelProperty("姓名") diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java index 775447a..72a10e0 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/config/YudaoMybatisAutoConfiguration.java @@ -4,11 +4,15 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler; +import cn.iocoder.yudao.framework.mybatis.core.injector.YudaoSqlInjector; +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap; import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer; import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration; import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator; +import com.baomidou.mybatisplus.core.injector.ISqlInjector; import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler; import com.baomidou.mybatisplus.extension.incrementer.*; import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal; @@ -17,12 +21,15 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import com.fasterxml.jackson.databind.ObjectMapper; import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.mapping.ResultMap; import org.mybatis.spring.annotation.MapperScan; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Primary; import org.springframework.core.env.ConfigurableEnvironment; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeUnit; @@ -59,6 +66,19 @@ public class YudaoMybatisAutoConfiguration { } @Bean + @Primary // 特殊:使用 @Primary 的原因,避免 MyBatis Plus Join 再创建 MPJSqlInjector 包装它 + public ISqlInjector yudaoSqlInjector() { + return new YudaoSqlInjector(); // selectMaps 的结果行,使用 CaseInsensitiveResultMap + } + + @Bean + public ConfigurationCustomizer caseInsensitiveResultMapConfigurationCustomizer() { + // 注册 CaseInsensitiveResultMap 的 resultMap,用于注解 SQL 的 @ResultMap + return configuration -> configuration.addResultMap(new ResultMap.Builder(configuration, + CaseInsensitiveResultMap.RESULT_MAP_ID, CaseInsensitiveResultMap.class, new ArrayList<>()).build()); + } + + @Bean @ConditionalOnProperty(prefix = "mybatis-plus.global-config.db-config", name = "id-type", havingValue = "INPUT") public IKeyGenerator keyGenerator(ConfigurableEnvironment environment) { DbType dbType = IdTypeEnvironmentPostProcessor.getDbType(environment); diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/injector/YudaoSqlInjector.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/injector/YudaoSqlInjector.java new file mode 100644 index 0000000..2fc1f72 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/injector/YudaoSqlInjector.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.framework.mybatis.core.injector; + +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap; +import com.baomidou.mybatisplus.core.injector.AbstractMethod; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.github.yulichang.injector.MPJSqlInjector; +import com.github.yulichang.method.mp.SelectMaps; +import org.apache.ibatis.mapping.MappedStatement; +import org.apache.ibatis.mapping.SqlSource; +import org.apache.ibatis.session.Configuration; + +import java.util.List; + +/** + * 自定义 SQL 注入器 + * + * 在 MyBatis Plus Join 的 {@link MPJSqlInjector} 基础上,将 selectMaps 的结果行替换为 {@link CaseInsensitiveResultMap}, + * 解决 PostgreSQL、Oracle 等数据库列标签大小写折叠,导致按固定 key 取不到值的问题 + * + * @author 芋道源码 + */ +public class YudaoSqlInjector extends MPJSqlInjector { + + @Override + public List getMethodList(Configuration configuration, Class> mapperClass, TableInfo tableInfo) { + List methods = super.getMethodList(configuration, mapperClass, tableInfo); + methods.replaceAll(method -> method instanceof SelectMaps ? new CaseInsensitiveSelectMaps() : method); + return methods; + } + + /** + * 结果行为 {@link CaseInsensitiveResultMap} 的 selectMaps + * + * 仅修改结果类型,SQL 仍由 MyBatis Plus Join 的 {@link SelectMaps} 生成,兼容 MPJ 的 Wrapper + */ + private static class CaseInsensitiveSelectMaps extends SelectMaps { + + @Override + protected MappedStatement addSelectMappedStatementForOther(Class> mapperClass, String id, SqlSource sqlSource, + Class> resultType) { + return super.addSelectMappedStatementForOther(mapperClass, id, sqlSource, CaseInsensitiveResultMap.class); + } + + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index 7dfb518..3b02c54 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.SortablePageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.common.util.object.PageUtils; +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap; import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils; import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils; import com.baomidou.mybatisplus.annotation.DbType; @@ -14,6 +15,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.core.toolkit.Constants; import com.baomidou.mybatisplus.core.toolkit.support.SFunction; import com.baomidou.mybatisplus.extension.toolkit.Db; import com.github.yulichang.base.MPJBaseMapper; @@ -23,6 +25,7 @@ import org.apache.ibatis.annotations.Param; import java.util.Collection; import java.util.List; +import java.util.Map; /** * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力 @@ -99,6 +102,24 @@ public interface BaseMapperX extends MPJBaseMapper { return new PageResult<>(mpPage.getRecords(), mpPage.getTotal()); } + @Override + @SuppressWarnings("unchecked") + default Map selectJoinMap(@Param(Constants.WRAPPER) MPJBaseJoin wrapper) { + return selectJoinOne(CaseInsensitiveResultMap.class, wrapper); + } + + @Override + @SuppressWarnings("unchecked") + default List> selectJoinMaps(@Param(Constants.WRAPPER) MPJBaseJoin wrapper) { + return (List>) ((Object) selectJoinList(CaseInsensitiveResultMap.class, wrapper)); + } + + @Override + @SuppressWarnings({"unchecked", "rawtypes"}) + default >> P selectJoinMapsPage(P page, @Param(Constants.WRAPPER) MPJBaseJoin wrapper) { + return (P) selectJoinPage((IPage) page, CaseInsensitiveResultMap.class, wrapper); + } + default T selectOne(String field, Object value) { return selectOne(new QueryWrapper().eq(field, value)); } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMap.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMap.java new file mode 100644 index 0000000..2d1243b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMap.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import org.springframework.util.LinkedCaseInsensitiveMap; + +import java.util.Locale; + +/** + * key 大小写不敏感的 MyBatis 查询结果 Map + * + * 背景:使用 Map 接收查询结果时,key 为 JDBC 返回的列标签。PostgreSQL 等会将未加引号的列名、别名折叠为小写, + * Oracle、达梦等会折叠为大写,导致 map.get("conversationId") 这类按固定 key 取值的代码,在 MySQL 以外的数据库取不到值。 + * + * 实现:基于 {@link LinkedCaseInsensitiveMap},get / containsKey / remove 时忽略 key 的大小写, + * 同时保留原始的列标签作为 key(遍历、序列化时不变)。固定使用 {@link Locale#ROOT},避免服务器默认 Locale(例如土耳其语)影响 key 的匹配。 + * + * 使用方式:由 MyBatis 直接创建结果行,Mapper 的返回类型仍声明为 Map,业务无需感知该类 + * 1. MyBatis Plus 的 selectMaps:由 YudaoSqlInjector 注入,自动使用该类 + * 2. MyBatis Plus Join 的 selectJoinMaps 等:由 BaseMapperX 覆盖,自动使用该类 + * 3. XML SQL:将 resultType 设置为该类 + * 4. 注解 SQL:添加 @ResultMap({@link #RESULT_MAP_ID}) + * + * 注意:仅大小写不同的多个 key,会合并为一个,保留后写入的 key 和值 + * + * @author 芋道源码 + * @see 星球讨论:Map 查询结果的跨数据库兼容问题 + */ +public class CaseInsensitiveResultMap extends LinkedCaseInsensitiveMap { + + /** + * 注解 SQL 使用的 resultMap 编号 + * + * 由 YudaoMybatisAutoConfiguration 注册到 MyBatis 全局配置;包含“.”,所以不会拼接 Mapper 的 namespace + */ + public static final String RESULT_MAP_ID = "cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap"; + + /** + * 创建空的结果 Map + * + * 用途:MyBatis 通过无参构造方法,实例化结果行 + */ + public CaseInsensitiveResultMap() { + super(Locale.ROOT); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMapTest.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMapTest.java new file mode 100644 index 0000000..700a340 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMapTest.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import org.junit.jupiter.api.Test; +import org.springframework.util.LinkedCaseInsensitiveMap; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link CaseInsensitiveResultMap} 的单元测试 + * + * @author 芋道源码 + */ +public class CaseInsensitiveResultMapTest { + + @Test + public void testGet_ignoreCase() { + // 准备参数 + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + map.put("conversationId", 1024L); + + // 调用,并断言:PostgreSQL 小写、Oracle 大写,都可以取到值 + assertEquals(1024L, map.get("conversationId")); + assertEquals(1024L, map.get("conversationid")); + assertEquals(1024L, map.get("CONVERSATIONID")); + assertTrue(map.containsKey("CONVERSATIONID")); + assertEquals(1024L, MapUtil.getLong(map, "conversationid")); + // 断言:保留原始的 key + assertEquals(Collections.singletonList("conversationId"), new ArrayList<>(map.keySet())); + } + + @Test + public void testPut_nullValue() { + // 准备参数 + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + map.put("sum_count", null); + + // 调用,并断言 + assertTrue(map.containsKey("SUM_COUNT")); + assertNull(map.get("SUM_COUNT")); + assertEquals(0, MapUtil.getInt(map, "SUM_COUNT", 0)); + } + + @Test + public void testPut_sameKeyIgnoreCase() { + // 准备参数 + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + + // 调用:仅大小写不同的 key + map.put("id", 1L); + map.put("ID", 2L); + + // 断言:合并为一个,保留后写入的 key 和值 + assertEquals(1, map.size()); + assertEquals(2L, map.get("id")); + assertEquals(Collections.singletonList("ID"), new ArrayList<>(map.keySet())); + } + + @Test + public void testGet_turkishDefaultLocale() { + Locale defaultLocale = Locale.getDefault(); + try { + // 准备参数:土耳其语下,大写 I 转小写为无点的 ı + Locale.setDefault(Locale.forLanguageTag("tr-TR")); + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + map.put("CONVERSATIONID", 1024L); + LinkedCaseInsensitiveMap defaultLocaleMap = new LinkedCaseInsensitiveMap<>(); + defaultLocaleMap.put("CONVERSATIONID", 1024L); + + // 调用,并断言:固定 Locale.ROOT,不受默认 Locale 影响 + assertEquals(1024L, map.get("conversationId")); + // 断言:使用默认 Locale 时,取不到值 + assertNull(defaultLocaleMap.get("conversationId")); + } finally { + Locale.setDefault(defaultLocale); + } + } + + @Test + public void testConvertMap_numberKey() { + // 准备参数:模拟 Oracle 返回的结果行 + List> rows = Arrays.asList(buildRow(1024L, 3), buildRow(2048L, 5)); + + // 调用:业务转换为数字 key 的 Map + Map result = CollectionUtils.convertMap(rows, + row -> MapUtil.getLong(row, "conversationId"), + row -> MapUtil.getInt(row, "count")); + + // 断言:数字 key 的业务 Map 不受影响 + assertInstanceOf(HashMap.class, result); + assertEquals(3, result.get(1024L)); + assertEquals(5, result.get(2048L)); + } + + private static Map buildRow(Long conversationId, Integer count) { + CaseInsensitiveResultMap row = new CaseInsensitiveResultMap<>(); + row.put("CONVERSATIONID", conversationId); + row.put("COUNT", count); + return row; + } + +} diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImplTest.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImplTest.java new file mode 100644 index 0000000..b1d0f02 --- /dev/null +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImplTest.java @@ -0,0 +1,387 @@ +package cn.iocoder.yudao.module.ai.service.chat; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO; +import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; +import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; +import cn.iocoder.yudao.module.ai.service.model.AiModelService; +import cn.iocoder.yudao.module.ai.service.model.AiToolService; +import lombok.Data; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.ai.chat.model.ToolContext; +import org.springframework.ai.deepseek.DeepSeekChatModel; +import org.springframework.ai.deepseek.api.DeepSeekApi; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletion; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionChunk; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionFinishReason; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.ChatCompletionFunction; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.Role; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.ToolCall; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionRequest; +import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.tool.resolution.ToolCallbackResolver; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.core.context.SecurityContextHolder; +import reactor.core.publisher.Flux; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_STREAM_ERROR; +import static cn.iocoder.yudao.module.ai.util.AiUtils.TOOL_CONTEXT_LOGIN_USER; +import static cn.iocoder.yudao.module.ai.util.AiUtils.TOOL_CONTEXT_TENANT_ID; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +/** + * {@link AiChatMessageServiceImpl} 的单元测试类 + * + * 使用真实的 {@link DeepSeekChatModel} 和工具调用,仅 mock 底层的 {@link DeepSeekApi} + * + * @author 芋道源码 + */ +public class AiChatMessageServiceImplTest extends BaseMockitoUnitTest { + + private static final String MODEL_NAME = "deepseek-test"; + private static final Double TEMPERATURE = 0.5; + private static final Integer MAX_TOKENS = 1024; + + private static final String TOOL_NAME = "query_weather"; + private static final String TOOL_RESULT = "杭州:晴,25℃"; + private static final ChatCompletionMessage TOOL_CALL_MESSAGE = new ChatCompletionMessage("我来查询一下杭州的天气", + Role.ASSISTANT, null, null, singletonList(new ToolCall("call_1", "function", + new ChatCompletionFunction(TOOL_NAME, "{\"city\":\"杭州\"}")))); + + private static final List TOOL_ANSWER_CHUNKS = asList("杭州今天", "晴,25℃"); + private static final String TOOL_ANSWER = String.join("", TOOL_ANSWER_CHUNKS); + private static final List PLAIN_ANSWER_CHUNKS = asList("你好,", "我是 AI 助手"); + private static final String PLAIN_ANSWER = String.join("", PLAIN_ANSWER_CHUNKS); + + /** + * assistant 消息编号:先插入 user 消息(编号 1),再插入 assistant 消息(编号 2) + */ + private static final Long ASSISTANT_MESSAGE_ID = 2L; + + @InjectMocks + private AiChatMessageServiceImpl chatMessageService; + + @Mock + private AiChatMessageMapper chatMessageMapper; + @Mock + private AiChatConversationService chatConversationService; + @Mock + private AiChatRoleService chatRoleService; + @Mock + private AiModelService modalService; + @Mock + private AiKnowledgeDocumentService knowledgeDocumentService; + @Mock + private AiToolService toolService; + @Mock + private ToolCallbackResolver toolCallbackResolver; + @Mock + private DeepSeekApi deepSeekApi; + + @AfterEach + public void after() { + SecurityContextHolder.clearContext(); + TenantContextHolder.clear(); + } + + @Test + public void testSendMessage_toolCall() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + Long tenantId = randomLongId(); + mockLoginUser(userId, tenantId); + // mock deepSeekApi 的方法:先请求工具,再返回回答 + when(deepSeekApi.chatCompletionEntity(any())).thenReturn(buildChatCompletion(TOOL_CALL_MESSAGE), + buildChatCompletion(new ChatCompletionMessage(TOOL_ANSWER, Role.ASSISTANT))); + + // 调用 + AiChatMessageSendRespVO respVO = chatMessageService.sendMessage(reqVO, userId); + // 断言 + assertEquals(TOOL_ANSWER, respVO.getReceive().getContent()); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ChatCompletionRequest.class); + verify(deepSeekApi, times(2)).chatCompletionEntity(requestCaptor.capture()); + assertToolExecuted(requestCaptor.getAllValues(), toolContexts, userId, tenantId); + // 断言模型参数 + ChatCompletionRequest request = requestCaptor.getAllValues().get(0); + assertEquals(MODEL_NAME, request.model()); + assertEquals(TEMPERATURE, request.temperature()); + assertEquals(MAX_TOKENS, request.maxTokens()); + // 断言消息保存 + assertAssistantMessageUpdated(TOOL_ANSWER); + } + + @Test + public void testSendMessage_withoutTool() { + // 准备参数 + Long userId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("你好"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, null); + // mock deepSeekApi 的方法 + when(deepSeekApi.chatCompletionEntity(any())) + .thenReturn(buildChatCompletion(new ChatCompletionMessage(PLAIN_ANSWER, Role.ASSISTANT))); + + // 调用 + AiChatMessageSendRespVO respVO = chatMessageService.sendMessage(reqVO, userId); + // 断言 + assertEquals(PLAIN_ANSWER, respVO.getReceive().getContent()); + verify(deepSeekApi).chatCompletionEntity(any()); + // 断言消息保存 + assertAssistantMessageUpdated(PLAIN_ANSWER); + } + + @Test + public void testSendMessage_toolCallThenModelError() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + mockLoginUser(userId, randomLongId()); + // mock deepSeekApi 的方法:先请求工具,再抛出异常 + RuntimeException modelException = new IllegalStateException("模型服务异常"); + when(deepSeekApi.chatCompletionEntity(any())).thenReturn(buildChatCompletion(TOOL_CALL_MESSAGE)) + .thenThrow(modelException); + + // 调用,并断言异常 + RuntimeException exception = assertThrows(RuntimeException.class, + () -> chatMessageService.sendMessage(reqVO, userId)); + assertSame(modelException, exception); + // 断言工具已执行、消息未保存 + verify(deepSeekApi, times(2)).chatCompletionEntity(any()); + assertEquals(1, toolContexts.size()); + verify(chatMessageMapper, never()).updateById(any(AiChatMessageDO.class)); + } + + @Test + public void testSendChatMessageStream_toolCall() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + Long tenantId = randomLongId(); + mockLoginUser(userId, tenantId); + // mock deepSeekApi 的方法:先请求工具,再流式返回回答 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(Flux.just(buildChatCompletionChunk(TOOL_CALL_MESSAGE)), + buildAnswerChunks(TOOL_ANSWER_CHUNKS)); + + // 调用 + List> results = chatMessageService + .sendChatMessageStream(reqVO, userId).collectList().block(); + // 断言(工具调用轮次不下发) + assertNotNull(results); + assertTrue(results.stream().allMatch(CommonResult::isSuccess)); + assertEquals(TOOL_ANSWER, joinContent(results)); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ChatCompletionRequest.class); + verify(deepSeekApi, times(2)).chatCompletionStream(requestCaptor.capture()); + assertToolExecuted(requestCaptor.getAllValues(), toolContexts, userId, tenantId); + // 断言消息保存 + assertAssistantMessageUpdated(TOOL_ANSWER); + } + + @Test + public void testSendChatMessageStream_withoutTool() { + // 准备参数 + Long userId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("你好"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, null); + // mock deepSeekApi 的方法 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(buildAnswerChunks(PLAIN_ANSWER_CHUNKS)); + + // 调用 + List> results = chatMessageService + .sendChatMessageStream(reqVO, userId).collectList().block(); + // 断言 + assertNotNull(results); + assertTrue(results.stream().allMatch(CommonResult::isSuccess)); + assertEquals(PLAIN_ANSWER, joinContent(results)); + verify(deepSeekApi).chatCompletionStream(any()); + // 断言消息保存 + assertAssistantMessageUpdated(PLAIN_ANSWER); + } + + @Test + public void testSendChatMessageStream_toolCallThenModelError() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + mockLoginUser(userId, randomLongId()); + // mock deepSeekApi 的方法:先请求工具,再返回异常 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(Flux.just(buildChatCompletionChunk(TOOL_CALL_MESSAGE)), + Flux.error(new IllegalStateException("模型服务异常"))); + + // 调用 + List> results = chatMessageService + .sendChatMessageStream(reqVO, userId).collectList().block(); + // 断言 + assertNotNull(results); + assertEquals(CHAT_STREAM_ERROR.getCode(), CollUtil.getLast(results).getCode()); + verify(deepSeekApi, times(2)).chatCompletionStream(any()); + assertEquals(1, toolContexts.size()); + // 断言消息删除(无内容) + verify(chatMessageMapper).deleteById(ASSISTANT_MESSAGE_ID); + verify(chatMessageMapper, never()).updateById(any(AiChatMessageDO.class)); + } + + private void mockConversation(Long conversationId, Long userId, Long roleId) { + // mock 对话 + AiChatConversationDO conversation = new AiChatConversationDO().setId(conversationId).setUserId(userId) + .setRoleId(roleId).setModelId(randomLongId()).setTemperature(TEMPERATURE).setMaxTokens(MAX_TOKENS); + when(chatConversationService.validateChatConversationExists(eq(conversationId))).thenReturn(conversation); + // mock 模型:真实的 DeepSeekChatModel + AiModelDO model = new AiModelDO().setId(conversation.getModelId()).setModel(MODEL_NAME) + .setPlatform(AiPlatformEnum.DEEP_SEEK.getPlatform()); + when(modalService.validateModel(eq(model.getId()))).thenReturn(model); + when(modalService.getChatModel(eq(model.getId()))) + .thenReturn(DeepSeekChatModel.builder().deepSeekApi(deepSeekApi).build()); + // mock 消息插入:依次分配编号 + AtomicLong messageId = new AtomicLong(); + doAnswer(invocation -> { + invocation.getArgument(0).setId(messageId.incrementAndGet()); + return 1; + }).when(chatMessageMapper).insert(any(AiChatMessageDO.class)); + } + + private void mockWeatherTool(Long roleId, List toolContexts) { + // mock 工具:真实的 FunctionToolCallback + Long toolId = randomLongId(); + ToolCallback toolCallback = FunctionToolCallback.builder(TOOL_NAME, + (request, toolContext) -> { + toolContexts.add(toolContext); + return request.getCity() + ":晴,25℃"; + }).description("查询城市天气").inputType(WeatherRequest.class).build(); + when(chatRoleService.getChatRole(eq(roleId))).thenReturn(new AiChatRoleDO().setId(roleId) + .setToolIds(singletonList(toolId))); + when(toolService.getToolList(eq(singletonList(toolId)))) + .thenReturn(singletonList(new AiToolDO().setId(toolId).setName(TOOL_NAME))); + when(toolCallbackResolver.resolve(eq(TOOL_NAME))).thenReturn(toolCallback); + } + + private static void mockLoginUser(Long userId, Long tenantId) { + SecurityFrameworkUtils.setLoginUser(new LoginUser().setId(userId), new MockHttpServletRequest()); + TenantContextHolder.setTenantId(tenantId); + } + + private static void assertToolExecuted(List requests, List toolContexts, + Long userId, Long tenantId) { + // 断言首轮请求带上工具 + assertEquals(1, requests.get(0).tools().size()); + // 断言工具执行,并拿到登录用户、租户 + assertEquals(1, toolContexts.size()); + Map context = toolContexts.get(0).getContext(); + assertEquals(userId, ((LoginUser) context.get(TOOL_CONTEXT_LOGIN_USER)).getId()); + assertEquals(tenantId, context.get(TOOL_CONTEXT_TENANT_ID)); + // 断言次轮请求回传工具结果 + ChatCompletionMessage toolMessage = CollUtil.getLast(requests.get(1).messages()); + assertEquals(Role.TOOL, toolMessage.role()); + assertTrue(toolMessage.content().contains(TOOL_RESULT)); + } + + private void assertAssistantMessageUpdated(String content) { + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(AiChatMessageDO.class); + verify(chatMessageMapper).updateById(messageCaptor.capture()); + assertEquals(ASSISTANT_MESSAGE_ID, messageCaptor.getValue().getId()); + assertEquals(content, messageCaptor.getValue().getContent()); + } + + private static String joinContent(List> results) { + return results.stream().map(result -> result.getData().getReceive().getContent()) + .collect(Collectors.joining()); + } + + private static ResponseEntity buildChatCompletion(ChatCompletionMessage message) { + ChatCompletion.Choice choice = new ChatCompletion.Choice(buildFinishReason(message), 0, message, null); + return ResponseEntity.ok(new ChatCompletion("chatcmpl-1", singletonList(choice), null, MODEL_NAME, + null, null, null)); + } + + private static Flux buildAnswerChunks(List contents) { + return Flux.fromIterable(contents) + .map(content -> buildChatCompletionChunk(new ChatCompletionMessage(content, Role.ASSISTANT))); + } + + private static ChatCompletionChunk buildChatCompletionChunk(ChatCompletionMessage delta) { + ChatCompletionChunk.ChunkChoice choice = new ChatCompletionChunk.ChunkChoice(buildFinishReason(delta), + 0, delta, null); + return new ChatCompletionChunk("chatcmpl-1", singletonList(choice), null, MODEL_NAME, + null, null, null, null); + } + + private static ChatCompletionFinishReason buildFinishReason(ChatCompletionMessage message) { + return CollUtil.isNotEmpty(message.toolCalls()) ? ChatCompletionFinishReason.TOOL_CALLS + : ChatCompletionFinishReason.STOP; + } + + @Data + public static class WeatherRequest { + + private String city; + + } + +} diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java index 7ce45b3..4ea4df3 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.expression; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index 644c95a..e5a76ad 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index 911f48d..8fdfac2 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java index e198531..6205cba 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java index 170b8a1..5dd09ef 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java index 884ba3a..8bad952 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java @@ -5,11 +5,11 @@ import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction; -import cn.idev.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java index 1b33728..73e7373 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java index 075c3b3..eafb5e5 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.followup.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java index a9c2a7a..d85e98d 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java index c8e181e..7c5a2bb 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java index aeca925..e5c4a98 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import org.dromara.core.trans.anno.Trans; import org.dromara.core.trans.constant.TransType; import org.dromara.core.trans.vo.VO; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java index 5feb99c..830b9bc 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java index 75827db..b6a3ee1 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java index 3e03169..5a16048 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java index df89465..e5472c9 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java index 2398e06..5c0e267 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java index 29d4c2f..bb25768 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java index 8dcc9f8..d8f0bca 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java index 3044d5a..a1ec7fe 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java index 03c446e..4562649 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java index e6a6aa4..302ef79 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java index 6762419..bd86fdd 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java index 538a3b1..1d85685 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java index c75a99a..c079635 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; +import org.apache.fesod.sheet.annotation.*; + import java.math.BigDecimal; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @Schema(description = "管理后台 - ERP 客户 Response VO") @Data diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index b1374e8..49c0d09 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index a004ed3..cbbe1a1 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java index 6a1ade0..fae4f6a 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java index 6f9b8da..6a2ea80 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index 1d23f36..9a2aff1 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java index f5f7650..0c4350e 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java index a1d0f51..35bd849 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java index 47e1261..77d82e8 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.erp.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java index 8d84789..b4e7482 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java index 06825b8..00e97e3 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java index 6a15e3c..f2ab852 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem; -import cn.idev.excel.annotation.ExcelProperty; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * FMS 辅助核算项目 Excel 导入 VO diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java index f41a550..ffbaf69 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java index df1e229..4ddefd8 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java index 07a8dcf..2950ca4 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject; -import cn.idev.excel.annotation.ExcelProperty; import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * FMS 科目 Excel 导入 VO diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java index 9a4bf25..d059f3d 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java @@ -4,11 +4,11 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.StringListConvert; import cn.iocoder.yudao.module.fms.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java index c4f53e0..14c979b 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarybalance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java index 5b8aee3..628cde8 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarydetail; import com.fasterxml.jackson.annotation.JsonFormat; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java index 3dd6606..3e1be63 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java index a0f67ec..1efc363 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail; import com.fasterxml.jackson.annotation.JsonFormat; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java index 12afe27..bb47e66 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.general; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java index 3317ccb..78b01ef 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitydetail; import com.fasterxml.jackson.annotation.JsonFormat; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java index 2f44668..5ae486c 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitygeneral; -import cn.idev.excel.annotation.ExcelIgnore; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnore; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.util.ArrayList; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java index 5249b9d..6f28079 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.subjectbalance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.util.ArrayList; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java index 2820415..f852d0c 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.report.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java index 18fe2ca..a77f1d7 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java index db12e3b..900e163 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.voucher.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; -import cn.idev.excel.annotation.format.DateTimeFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.format.DateTimeFormat; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java index 9bdf07b..7158199 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.voucher.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java index 35c178d..be332f7 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.clock; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java index d21dc36..4a1a0f0 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.leave; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java index 4708af0..208e9d3 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.statistics; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.clock.HrmAttendanceClockRespVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java index 5aa1eb7..a3a48a6 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.statistics; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java index 87b37db..60f2538 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java @@ -1,7 +1,5 @@ package cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.employee; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; @@ -14,6 +12,8 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java index d7e0319..f194938 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.employee; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java index c02b1f5..558c55b 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.changerecord; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.option.HrmSalaryOptionValueVO; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java index c1969c0..a0df917 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.employeeinfo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.option.HrmSalaryOptionValueVO; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java index 26e3d98..c847e1c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.im.dal.mysql.statistics; +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Select; import java.time.LocalDateTime; @@ -59,6 +61,7 @@ public interface ImStatisticsManagerMapper { @Select("SELECT DATE(create_time) AS date, COUNT(*) AS count FROM system_users " + "WHERE deleted = 0 AND create_time >= #{beginTime} AND create_time < #{endTime} " + "GROUP BY DATE(create_time)") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectNewUserDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -74,6 +77,7 @@ public interface ImStatisticsManagerMapper { " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY day") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectActiveUserDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); // ==================== 群 ==================== @@ -111,6 +115,7 @@ public interface ImStatisticsManagerMapper { " GROUP BY g.id" + ") t " + "GROUP BY `range`") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectGroupSizeDistribution(); // ==================== 消息 ==================== @@ -140,6 +145,7 @@ public interface ImStatisticsManagerMapper { "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime} " + "GROUP BY DATE(send_time)") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectPrivateMessageDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -150,6 +156,7 @@ public interface ImStatisticsManagerMapper { "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime} " + "GROUP BY DATE(send_time)") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectGroupMessageDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -167,6 +174,7 @@ public interface ImStatisticsManagerMapper { " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY type") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectMessageTypeDistribution(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -184,6 +192,7 @@ public interface ImStatisticsManagerMapper { " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY user_id ORDER BY messageCount DESC LIMIT #{limit}") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectTopSenders(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime, @Param("limit") int limit); diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java index 7c50033..effc562 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java +++ b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java @@ -228,6 +228,9 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest { assertEquals(3L, ((Number) tops.get(0).get("messageCount")).longValue()); assertEquals(2L, ((Number) tops.get(1).get("userId")).longValue()); assertEquals(2L, ((Number) tops.get(1).get("messageCount")).longValue()); + // 断言:key 大小写不敏感,兼容 PostgreSQL 小写、Oracle 大写的列标签 + assertEquals(1L, ((Number) tops.get(0).get("userid")).longValue()); + assertEquals(3L, ((Number) tops.get(0).get("MESSAGECOUNT")).longValue()); } // ========== 工具方法 ========== diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java index 622bb04..26c72df 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java index df0ef60..8cc9b8a 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java index bac533b..acc295f 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java index 3094484..b429a3e 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.erp.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java index 3db315b..737fe46 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java index f100c80..f9cd803 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java index 9a4be2e..4779502 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java index 1d33cdf..d7929ad 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java index 1b3dc0f..a730b42 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java index 7097924..ef4f2fb 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm index 51b0751..4164283 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm @@ -1,6 +1,6 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm index eae083a..77a9927 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm @@ -19,7 +19,7 @@ import java.time.LocalDateTime; #end #end ## 处理 Excel 导出 -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; #foreach ($column in $columns) #if ("$!column.dictType" != "")## 有设置数据字典 import ${DictFormatClassName}; diff --git a/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm b/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm index f15ada4..bb2914d 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm @@ -15,7 +15,7 @@ import ${BaseDOClassName}; ## 处理 Excel 导出 + Schema 注解(仅 DO 模式) #if ($voType == 20) import io.swagger.v3.oas.annotations.media.Schema; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; #foreach ($column in $columns) #if ("$!column.dictType" != "")## 有设置数据字典 import ${DictFormatClassName}; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-iot/yudao-module-iot-biz/pom.xml b/yudao-module-iot/yudao-module-iot-biz/pom.xml index 75cdd32..b671a62 100644 --- a/yudao-module-iot/yudao-module-iot-biz/pom.xml +++ b/yudao-module-iot/yudao-module-iot-biz/pom.xml @@ -50,6 +50,10 @@ com.taosdata.jdbc taos-jdbcdriver + + org.apache.iotdb + iotdb-jdbc + cn.iocoder.boot diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceMessageController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceMessageController.java index 03461d5..61d936a 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceMessageController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/IotDeviceMessageController.java @@ -10,7 +10,6 @@ import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceM import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessageSendReqVO; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceMessageMapper; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; @@ -41,8 +40,6 @@ public class IotDeviceMessageController { private IotDeviceService deviceService; @Resource private IotThingModelService thingModelService; - @Resource - private IotDeviceMessageMapper deviceMessageMapper; @GetMapping("/page") @Operation(summary = "获得设备消息分页") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java index 6ea15a1..2792065 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * 设备 Excel 导入 VO diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java index 0d4a9d8..9fa769d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java index 302b072..aec1bb5 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.iot.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceMessageDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceMessageDO.java index 233b2c1..3b24aa9 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceMessageDO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/device/IotDeviceMessageDO.java @@ -11,7 +11,7 @@ import lombok.NoArgsConstructor; /** * IoT 设备消息数据 DO * - * 目前使用 TDengine 存储 + * 支持 TDengine、IoTDB 存储,由 yudao.iot.storage.type 选择 * * @author alwayssuper */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thingmodel/model/ThingModelProperty.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thingmodel/model/ThingModelProperty.java index 2fe103a..96d3cfd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thingmodel/model/ThingModelProperty.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thingmodel/model/ThingModelProperty.java @@ -21,6 +21,16 @@ import java.util.List; public class ThingModelProperty { /** + * STRUCT、ARRAY 等 JSON 属性值的长度上限:按 UTF-8 编码后的字节数计算,不是字符数 + * + * 1. 写入前:JSON 字符串超过该长度时,转换为 null,不写入该属性 + * 2. 各存储后端共用,例如说 TDengine 的 VARCHAR 长度 + * + * 注意:TDengine 一行(所有列)有总长度上限,调大该长度,会减少一个产品可以定义的 STRUCT、ARRAY 属性数量 + */ + public static final int LENGTH_JSON = 1024; + + /** * 属性标识符 */ @NotEmpty(message = "属性标识符不能为空") diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IoTDBSystemMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IoTDBSystemMapper.java new file mode 100644 index 0000000..4c5c55b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IoTDBSystemMapper.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.iot.dal.iotdb; + +import cn.iocoder.yudao.module.iot.framework.iotdb.core.IoTDBUtils; +import cn.iocoder.yudao.module.iot.framework.iotdb.core.annotation.IoTDBDS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +import java.util.List; +import java.util.Map; + +/** + * IoTDB 系统信息 Mapper:只读取配置,用于启动前提检查 + * + * @author 芋道源码 + */ +@Mapper +@IoTDBDS +@InterceptorIgnore(tenantLine = "true", dataPermission = "true") // 避免 SQL 解析,因为 JSqlParser 对 IoTDB 的 SQL 解析会报错 +public interface IoTDBSystemMapper { + + @Select("SHOW VARIABLES") + List> selectVariableList(); + + @Select("SHOW DATANODES") + List> selectDataNodeList(); + + /** + * 获得指定 DataNode 的全部配置 + * + * @param nodeId DataNode 编号,来自 SHOW DATANODES 的结果,不接收外部输入 + * @return 配置列表 + */ + @Select("SHOW ALL CONFIGURATION ON ${nodeId}") + List> selectAllConfigurationList(@Param("nodeId") Integer nodeId); + + /** + * 校验 IoTDB 的前提条件,不满足时抛出异常。只检查,不修改任何配置: + * 1. 数据库已预建:连接 URL 中的数据库不存在时,获取连接即失败 + * 2. TimestampPrecision 为 ms + * 3. 所有 DataNode 为 Running,且 enable_partial_insert=false + */ + default void verifyPrerequisites() { + IoTDBUtils.validateTimestampPrecision(selectVariableList()); + List nodeIds = IoTDBUtils.validateDataNodes(selectDataNodeList()); + for (Integer nodeId : nodeIds) { + IoTDBUtils.validatePartialInsertDisabled(nodeId, selectAllConfigurationList(nodeId)); + } + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBCodec.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBCodec.java new file mode 100644 index 0000000..95afc90 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBCodec.java @@ -0,0 +1,128 @@ +package cn.iocoder.yudao.module.iot.dal.iotdb; + +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; + +/** + * IoTDB 设备消息的编解码器 + * + * 为什么需要编码?IoTDB 相同 (device_id, time) 再次写入时,NULL 值不会清空旧值,导致“整行替换”的语义不成立, + * 例如说同一设备、同一毫秒的两条消息(id 不同),会混合成一行。因此,所有 FIELD 都编码为非 NULL 值,每次写入都设置全部 FIELD + * (id 为 FIELD,原样存储,不编码): + * 1. Boolean:-1 为 null,0 为 false,1 为 true + * 2. 其它:n: 为 null,v: + 字符串为非 null 值。例如说:null -> "n:","" -> "v:",123 -> "v:123" + * + * 查询条件中的值,也需要使用相同的编码 + * + * @author 芋道源码 + */ +public class IotDeviceMessageIoTDBCodec { + + public static final int BOOLEAN_NULL = -1; + public static final int BOOLEAN_FALSE = 0; + public static final int BOOLEAN_TRUE = 1; + + public static final String PREFIX_NULL = "n:"; + public static final String PREFIX_VALUE = "v:"; + + // ========== 消息 ========== + + public static IotDeviceMessageIoTDBRow encode(IotDeviceMessageDO message) { + Assert.notNull(message.getTs(), "消息的 ts 不能为空"); + Assert.notNull(message.getDeviceId(), "消息的 deviceId 不能为空"); + Assert.notEmpty(message.getId(), "消息的 id 不能为空"); + return new IotDeviceMessageIoTDBRow().setTs(message.getTs()) + .setDeviceId(encodeDeviceId(message.getDeviceId())).setId(message.getId()) + .setUpstream(encodeBoolean(message.getUpstream())).setReply(encodeBoolean(message.getReply())) + .setMethod(encodeString(message.getMethod())).setIdentifier(encodeString(message.getIdentifier())) + .setRequestId(encodeString(message.getRequestId())).setServerId(encodeString(message.getServerId())) + .setParams(encodeString(toJsonString(message.getParams()))) + .setData(encodeString(toJsonString(message.getData()))) + .setMsg(encodeString(message.getMsg())).setReportTime(encodeString(message.getReportTime())) + .setTenantId(encodeString(message.getTenantId())).setCode(encodeString(message.getCode())); + } + + public static IotDeviceMessageDO decode(IotDeviceMessageIoTDBRow row) { + String reportTime = decodeString(row.getReportTime()); + String tenantId = decodeString(row.getTenantId()); + String code = decodeString(row.getCode()); + return new IotDeviceMessageDO().setTs(row.getTs()) + .setDeviceId(row.getDeviceId() != null ? Long.valueOf(row.getDeviceId()) : null).setId(row.getId()) + .setUpstream(decodeBoolean(row.getUpstream())).setReply(decodeBoolean(row.getReply())) + .setMethod(decodeString(row.getMethod())).setIdentifier(decodeString(row.getIdentifier())) + .setRequestId(decodeString(row.getRequestId())).setServerId(decodeString(row.getServerId())) + .setParams(decodeString(row.getParams())).setData(decodeString(row.getData())) + .setMsg(decodeString(row.getMsg())) + .setReportTime(reportTime != null ? Long.valueOf(reportTime) : null) + .setTenantId(tenantId != null ? Long.valueOf(tenantId) : null) + .setCode(code != null ? Integer.valueOf(code) : null); + } + + /** + * 转换 params、data 为字符串:Service 写入前已转为 JSON 字符串,这里兼容其它对象 + */ + private static String toJsonString(Object value) { + if (value == null || value instanceof String) { + return (String) value; + } + return JsonUtils.toJsonString(value); + } + + // ========== 单个值 ========== + + public static String encodeDeviceId(Long deviceId) { + return deviceId != null ? deviceId.toString() : null; + } + + public static int encodeBoolean(Boolean value) { + if (value == null) { + return BOOLEAN_NULL; + } + return value ? BOOLEAN_TRUE : BOOLEAN_FALSE; + } + + /** + * 解码 Boolean + * + * @param value 存储值;为 null 时,说明该行不是本系统写入的,按 null 处理 + * @return Boolean + */ + public static Boolean decodeBoolean(Integer value) { + if (value == null || value == BOOLEAN_NULL) { + return null; + } + if (value == BOOLEAN_TRUE) { + return true; + } + if (value == BOOLEAN_FALSE) { + return false; + } + throw new IllegalArgumentException(StrUtil.format("无法解码 Boolean 存储值({})", value)); + } + + public static String encodeString(Object value) { + if (value == null) { + return PREFIX_NULL; + } + return PREFIX_VALUE + value; + } + + /** + * 解码字符串 + * + * @param value 存储值;为 null 时,说明该行不是本系统写入的,按 null 处理 + * @return 字符串 + */ + public static String decodeString(String value) { + if (value == null || PREFIX_NULL.equals(value)) { + return null; + } + if (value.startsWith(PREFIX_VALUE)) { + return value.substring(PREFIX_VALUE.length()); + } + throw new IllegalArgumentException(StrUtil.format("无法解码字符串存储值({})", value)); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBDAO.java new file mode 100644 index 0000000..1af22d9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBDAO.java @@ -0,0 +1,208 @@ +package cn.iocoder.yudao.module.iot.dal.iotdb; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.PageUtils; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; +import cn.iocoder.yudao.module.iot.dal.storage.IotDeviceMessageDAO; +import cn.iocoder.yudao.module.iot.framework.iotdb.core.IoTDBUtils; +import cn.iocoder.yudao.module.iot.framework.storage.config.IotStorageProperties; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.iot.dal.iotdb.IotDeviceMessageIoTDBCodec.*; + +/** + * 基于 IoTDB(表模型)的 {@link IotDeviceMessageDAO} 实现类 + * + * 一张全局表 device_message,身份为 (device_id, time),编解码见 {@link IotDeviceMessageIoTDBCodec} + * + * @author 芋道源码 + */ +@Repository +@ConditionalOnProperty(prefix = IotStorageProperties.PREFIX, name = "type", havingValue = "iotdb") +@Slf4j +public class IotDeviceMessageIoTDBDAO implements IotDeviceMessageDAO { + + private static final String CATEGORY_TAG = "TAG"; + private static final String CATEGORY_FIELD = "FIELD"; + + /** + * 唯一的 TAG 列 + */ + private static final String COLUMN_DEVICE_ID = "device_id"; + /** + * 消息表的列:列名 -> 数据类型。除 {@link #COLUMN_DEVICE_ID} 为 TAG 外,其它都是 FIELD + */ + private static final Map COLUMN_TYPES = MapUtil.builder(new LinkedHashMap()) + .put(COLUMN_DEVICE_ID, "STRING").put("id", "STRING") + .put("upstream", "INT32").put("reply", "INT32") + .put("method", "STRING").put("identifier", "STRING").put("request_id", "STRING").put("server_id", "STRING") + .put("params", "STRING").put("data", "STRING").put("msg", "STRING") + .put("report_time", "STRING").put("tenant_id", "STRING").put("code", "STRING") + .build(); + + @Resource + private IotDeviceMessageIoTDBMapper deviceMessageMapper; + @Resource + private IoTDBSystemMapper systemMapper; + + @Override + public void initialize() { + // 1. 校验前提条件:只读取配置,不修改 + systemMapper.verifyPrerequisites(); + // 2. 获得消息表的列:表不存在时,创建后再读取 + List> columns = getColumnList(); + if (columns == null) { + deviceMessageMapper.createTable(); + log.info("[initialize][设备消息表不存在,创建成功]"); + columns = deviceMessageMapper.selectColumnList(); + } + // 3. 校验表结构:不兼容时,需要人工处理,不会自动修改、删除 + validateColumns(columns); + log.info("[initialize][设备消息表已就绪]"); + } + + /** + * 获得消息表的列 + * + * @return 列列表;表不存在时,返回 null + */ + private List> getColumnList() { + try { + return deviceMessageMapper.selectColumnList(); + } catch (Exception exception) { + // 只有表不存在(550)返回 null;权限、连接等其它错误原样抛出 + if (IoTDBUtils.isTableNotExists(exception)) { + return null; + } + throw exception; + } + } + + /** + * 校验消息表的结构:device_id 为唯一的 TAG,其它列都是类型一致的 FIELD + * + * 例如说,旧结构的 id 为 TAG,身份不同,且每条消息会产生一个 IoTDB 设备,所以不兼容 + * + * @param columns DESC 的结果,包括 ColumnName、DataType、Category + */ + private static void validateColumns(List> columns) { + // 1. 解析 DB 里的列:列名 -> 类别、类型 + Map categories = new HashMap<>(); + Map types = new HashMap<>(); + for (Map column : columns) { + String name = StrUtil.toStringOrNull(IoTDBUtils.getIgnoreCase(column, "ColumnName")); + categories.put(name, StrUtil.toStringOrNull(IoTDBUtils.getIgnoreCase(column, "Category"))); + types.put(name, StrUtil.toStringOrNull(IoTDBUtils.getIgnoreCase(column, "DataType"))); + } + + // 2.1 TAG 只能是 device_id:多出的 TAG 会改变身份 + List errors = new ArrayList<>(); + Set tags = new TreeSet<>(); + categories.forEach((name, category) -> { + if (StrUtil.equalsIgnoreCase(category, CATEGORY_TAG)) { + tags.add(name); + } + }); + if (!tags.equals(Collections.singleton(COLUMN_DEVICE_ID))) { + errors.add(StrUtil.format("TAG 只能为 {},当前为 {}", COLUMN_DEVICE_ID, tags)); + } + // 2.2 各列的类别、类型 + COLUMN_TYPES.forEach((name, type) -> { + if (!categories.containsKey(name)) { + errors.add(StrUtil.format("缺少列 {}", name)); + return; + } + String category = COLUMN_DEVICE_ID.equals(name) ? CATEGORY_TAG : CATEGORY_FIELD; + if (!StrUtil.equalsIgnoreCase(categories.get(name), category) + || !StrUtil.equalsIgnoreCase(types.get(name), type)) { + errors.add(StrUtil.format("列 {} 应为 {} {},当前为 {} {}", + name, type, category, types.get(name), categories.get(name))); + } + }); + if (errors.isEmpty()) { + return; + } + throw new IllegalStateException(StrUtil.format("[IoTDB 设备消息表] device_message 的结构与当前版本不兼容:{}。" + + "请人工处理(例如说,导出需要保留的数据后删除该表,或者更换数据库),应用不会自动修改、删除表", + String.join(";", errors))); + } + + @Override + public void insert(IotDeviceMessageDO message) { + deviceMessageMapper.insert(encode(message)); + } + + @Override + public PageResult selectPage(IotDeviceMessagePageReqVO reqVO) { + // 1. 编码查询条件:空字符串与 TDengine 保持一致,视为不过滤 + String deviceId = encodeDeviceId(reqVO.getDeviceId()); + String method = StrUtil.isNotEmpty(reqVO.getMethod()) ? encodeString(reqVO.getMethod()) : null; + Integer upstream = reqVO.getUpstream() != null ? encodeBoolean(reqVO.getUpstream()) : null; + Integer reply = reqVO.getReply() != null ? encodeBoolean(reqVO.getReply()) : null; + String identifier = StrUtil.isNotEmpty(reqVO.getIdentifier()) ? encodeString(reqVO.getIdentifier()) : null; + try { + // 2.1 查询总数 + Long total = deviceMessageMapper.selectCount(deviceId, method, upstream, reply, identifier); + if (total == null || total == 0) { + return PageResult.empty(); + } + // 2.2 查询列表:pageSize 为 -1 时,不分页 + boolean pageable = ObjUtil.notEqual(reqVO.getPageSize(), PageParam.PAGE_SIZE_NONE); + List rows = deviceMessageMapper.selectList(deviceId, method, upstream, reply, identifier, + pageable ? PageUtils.getStart(reqVO) : null, pageable ? reqVO.getPageSize() : null); + return new PageResult<>(convertList(rows, IotDeviceMessageIoTDBCodec::decode), total); + } catch (Exception exception) { + if (IoTDBUtils.isTableNotExists(exception)) { + return PageResult.empty(); + } + throw exception; + } + } + + @Override + public List selectListByRequestIdsAndReply(Long deviceId, Collection requestIds, Boolean reply) { + // reply 为空时,与 TDengine 的 reply = NULL 一致,匹配不到任何消息 + if (reply == null) { + return Collections.emptyList(); + } + // requestId 为空的消息,存储值为 n:,不应被 null 匹配到,所以过滤掉 + List encodedRequestIds = new ArrayList<>(); + if (requestIds != null) { + requestIds.stream().filter(Objects::nonNull).distinct() + .forEach(requestId -> encodedRequestIds.add(encodeString(requestId))); + } + if (CollUtil.isEmpty(encodedRequestIds)) { + return Collections.emptyList(); + } + List rows = deviceMessageMapper.selectListByRequestIdsAndReply( + encodeDeviceId(deviceId), encodedRequestIds, encodeBoolean(reply)); + return convertList(rows, IotDeviceMessageIoTDBCodec::decode); + } + + @Override + public Long selectCountByCreateTime(Long createTime) { + return deviceMessageMapper.selectCountByCreateTime(createTime); + } + + @Override + public List> selectDeviceMessageCountGroupByDate(Long startTime, Long endTime) { + List> counts = deviceMessageMapper.selectCountGroupByHour(startTime, endTime); + return convertList(counts, count -> IotDeviceMessageDAO.buildMessageCount( + IoTDBUtils.getIgnoreCase(count, COUNT_TIME), + IoTDBUtils.getIgnoreCase(count, COUNT_UPSTREAM), + IoTDBUtils.getIgnoreCase(count, COUNT_DOWNSTREAM))); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBMapper.java new file mode 100644 index 0000000..f64156c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBMapper.java @@ -0,0 +1,58 @@ +package cn.iocoder.yudao.module.iot.dal.iotdb; + +import cn.iocoder.yudao.module.iot.framework.iotdb.core.annotation.IoTDBDS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * IoTDB 设备消息 Mapper + * + * 注意:参数均为 {@link IotDeviceMessageIoTDBCodec} 编码后的存储值;分页通过手写 LIMIT/OFFSET 实现,不依赖 MyBatis Plus 分页插件 + * + * @author 芋道源码 + */ +@Mapper +@IoTDBDS +@InterceptorIgnore(tenantLine = "true", dataPermission = "true") // 避免 SQL 解析,因为 JSqlParser 对 IoTDB 的 SQL 解析会报错;租户由 Service 层控制 +public interface IotDeviceMessageIoTDBMapper { + + /** + * 获得消息表的列 + * + * @return 列列表,包括 ColumnName、DataType、Category 等 + */ + List> selectColumnList(); + + void createTable(); + + void insert(IotDeviceMessageIoTDBRow row); + + List selectList(@Param("deviceId") String deviceId, + @Param("method") String method, + @Param("upstream") Integer upstream, + @Param("reply") Integer reply, + @Param("identifier") String identifier, + @Param("offset") Integer offset, + @Param("limit") Integer limit); + + Long selectCount(@Param("deviceId") String deviceId, + @Param("method") String method, + @Param("upstream") Integer upstream, + @Param("reply") Integer reply, + @Param("identifier") String identifier); + + List selectListByRequestIdsAndReply(@Param("deviceId") String deviceId, + @Param("requestIds") Collection requestIds, + @Param("reply") Integer reply); + + Long selectCountByCreateTime(@Param("createTime") Long createTime); + + List> selectCountGroupByHour(@Param("startTime") Long startTime, + @Param("endTime") Long endTime); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBRow.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBRow.java new file mode 100644 index 0000000..1cc9eb6 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDeviceMessageIoTDBRow.java @@ -0,0 +1,52 @@ +package cn.iocoder.yudao.module.iot.dal.iotdb; + +import lombok.Data; +import lombok.experimental.Accessors; + +/** + * IoTDB 设备消息表 device_message 的一行,字段为编码后的存储值 + * + * 身份为 (deviceId, ts);编解码见 {@link IotDeviceMessageIoTDBCodec} + * + * @author 芋道源码 + */ +@Data +@Accessors(chain = true) +public class IotDeviceMessageIoTDBRow { + + /** + * 存储时间(毫秒),对应隐式 time 列 + */ + private Long ts; + /** + * 设备编号,唯一的 TAG + */ + private String deviceId; + /** + * 消息编号,FIELD,原样存储 + */ + private String id; + + /** + * 是否上行:-1 为空,0 为否,1 为是 + */ + private Integer upstream; + /** + * 是否回复:-1 为空,0 为否,1 为是 + */ + private Integer reply; + + // ========== 以下字段,统一使用 n:/v: 编码 ========== + + private String method; + private String identifier; + private String requestId; + private String serverId; + private String params; + private String data; + private String msg; + private String reportTime; + private String tenantId; + private String code; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDevicePropertyIoTDBDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDevicePropertyIoTDBDAO.java new file mode 100644 index 0000000..403237a --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDevicePropertyIoTDBDAO.java @@ -0,0 +1,220 @@ +package cn.iocoder.yudao.module.iot.dal.iotdb; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; +import cn.iocoder.yudao.module.iot.dal.storage.IotDevicePropertyDAO; +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; +import cn.iocoder.yudao.module.iot.framework.iotdb.core.IoTDBUtils; +import cn.iocoder.yudao.module.iot.framework.storage.config.IotStorageProperties; +import cn.iocoder.yudao.module.iot.framework.storage.core.util.IotStorageFieldUtils; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +/** + * 基于 IoTDB(表模型)的 {@link IotDevicePropertyDAO} 实现类 + * + * 每个产品一张表 product_property_{productId},设备共用产品表,通过 device_id TAG 区分。 + * 用户属性列统一为 p_ + 中立字段名,避免与 time、device_id、report_time 等内置列冲突。 + * + * 与 TDengine 的差异: + * 1. STRING 没有长度,物模型 TEXT 的长度变化不会改表;长度由写入前的业务转换校验 + * 2. INT、ENUM、BOOL 都映射为 INT32,三者之间的逻辑类型变化不会改表,历史数据保留 + * 3. 物理类型变化通过 DROP + ADD 完成,旧列的历史数据不会保留 + * 4. IoTDB 的 DDL 不参与事务,也无法回滚;执行中途失败时,再次定义即可收敛(ADD/DROP 均为幂等语句) + * + * @author 芋道源码 + */ +@Repository +@ConditionalOnProperty(prefix = IotStorageProperties.PREFIX, name = "type", havingValue = "iotdb") +@Slf4j +public class IotDevicePropertyIoTDBDAO implements IotDevicePropertyDAO { + + /** + * 用户属性列的前缀 + */ + public static final String COLUMN_PREFIX = "p_"; + + public static final String TYPE_INT32 = "INT32"; + public static final String TYPE_FLOAT = "FLOAT"; + public static final String TYPE_DOUBLE = "DOUBLE"; + public static final String TYPE_STRING = "STRING"; + public static final String TYPE_TIMESTAMP = "TIMESTAMP"; + + /** + * DESC 结果中,FIELD 列的类别 + */ + private static final String CATEGORY_FIELD = "FIELD"; + + /** + * 物模型的数据类型,与 IoTDB 数据类型的映射关系 + * + * @see IoTDB 数据类型 + */ + private static final Map TYPE_MAPPING = MapUtil.builder() + .put(IotDataSpecsDataTypeEnum.INT.getDataType(), TYPE_INT32) + .put(IotDataSpecsDataTypeEnum.FLOAT.getDataType(), TYPE_FLOAT) + .put(IotDataSpecsDataTypeEnum.DOUBLE.getDataType(), TYPE_DOUBLE) + .put(IotDataSpecsDataTypeEnum.ENUM.getDataType(), TYPE_INT32) + .put(IotDataSpecsDataTypeEnum.BOOL.getDataType(), TYPE_INT32) + .put(IotDataSpecsDataTypeEnum.TEXT.getDataType(), TYPE_STRING) + .put(IotDataSpecsDataTypeEnum.DATE.getDataType(), TYPE_TIMESTAMP) + .put(IotDataSpecsDataTypeEnum.STRUCT.getDataType(), TYPE_STRING) + .put(IotDataSpecsDataTypeEnum.ARRAY.getDataType(), TYPE_STRING) + .build(); + + @Resource + private IotDevicePropertyIoTDBMapper devicePropertyMapper; + @Resource + private IoTDBSystemMapper systemMapper; + + @Override + public void initialize() { + // 产品属性表在产品发布、手动同步时创建,启动时只校验前提条件 + systemMapper.verifyPrerequisites(); + } + + @Override + public void defineProductPropertyTable(Long productId, List propertyThingModels) { + // 1.1 校验属性标识符,可以作为列名 + IotStorageFieldUtils.validatePropertyIdentifiers(convertList(propertyThingModels, IotThingModelDO::getIdentifier)); + List newColumns = buildColumnList(propertyThingModels); + // 1.2 解析 DB 里的用户属性列 + Map oldColumns = getUserColumnTypes(productId); + + // 2.1 情况一:如果是新增的时候,需要创建表 + if (oldColumns == null) { + if (CollUtil.isEmpty(newColumns)) { + log.info("[defineProductPropertyTable][productId({}) 没有需要定义的属性]", productId); + return; + } + devicePropertyMapper.createTable(productId, newColumns); + return; + } + // 2.2 情况二:如果是修改的时候,需要更新表 + Set newColumnNames = new HashSet<>(convertList(newColumns, IotDevicePropertyIoTDBMapper.Column::getName)); + // 2.2.1 删除不再需要的列 + oldColumns.keySet().stream().filter(name -> !newColumnNames.contains(name)) + .forEach(name -> devicePropertyMapper.dropColumn(productId, name)); + for (IotDevicePropertyIoTDBMapper.Column column : newColumns) { + String oldType = oldColumns.get(column.getName()); + // 2.2.2 新增的列 + if (oldType == null) { + devicePropertyMapper.addColumn(productId, column); + continue; + } + // 2.2.3 物理类型变化的列:IoTDB 不支持修改列类型,只能 DROP + ADD,旧列的数据不会保留 + if (!StrUtil.equalsIgnoreCase(oldType, column.getType())) { + log.warn("[defineProductPropertyTable][productId({}) 列({}) 类型从 {} 变为 {},删除后重建,历史数据不保留]", + productId, column.getName(), oldType, column.getType()); + devicePropertyMapper.dropColumn(productId, column.getName()); + devicePropertyMapper.addColumn(productId, column); + } + } + } + + /** + * 获得产品属性表的用户属性列 + * + * @param productId 产品编号 + * @return 列名与类型的映射;表不存在时,返回 null + */ + private Map getUserColumnTypes(Long productId) { + List> columns; + try { + columns = devicePropertyMapper.selectColumnList(productId); + } catch (Exception exception) { + if (IoTDBUtils.isTableNotExists(exception)) { + return null; + } + throw exception; + } + // 只比较 p_ 开头的 FIELD 列:time、device_id、report_time 由系统维护,不参与差异 + Map userColumns = new LinkedHashMap<>(); + for (Map column : columns) { + String name = StrUtil.toStringOrNull(IoTDBUtils.getIgnoreCase(column, "ColumnName")); + String category = StrUtil.toStringOrNull(IoTDBUtils.getIgnoreCase(column, "Category")); + if (StrUtil.startWith(name, COLUMN_PREFIX) && StrUtil.equalsIgnoreCase(category, CATEGORY_FIELD)) { + userColumns.put(name, StrUtil.toStringOrNull(IoTDBUtils.getIgnoreCase(column, "DataType"))); + } + } + return userColumns; + } + + private List buildColumnList(List thingModels) { + return convertList(thingModels, thingModel -> { + String type = TYPE_MAPPING.get(thingModel.getProperty().getDataType()); + if (type == null) { + throw new IllegalArgumentException(StrUtil.format("属性({}) 的数据类型({}) 不支持存储", + thingModel.getIdentifier(), thingModel.getProperty().getDataType())); + } + return new IotDevicePropertyIoTDBMapper.Column(buildColumnName(thingModel.getIdentifier()), type, null); + }); + } + + @Override + public void insert(IotDeviceDO device, Map properties, Long ts, Long reportTime) { + // 校验属性标识符:在拼接 SQL 之前,避免保留字段、归一化后重名的属性写入 + IotStorageFieldUtils.validatePropertyIdentifiers(properties.keySet()); + if (CollUtil.isEmpty(properties)) { + return; + } + List columns = new ArrayList<>(properties.size()); + properties.forEach((identifier, value) -> columns.add( + new IotDevicePropertyIoTDBMapper.Column(buildColumnName(identifier), null, convertValue(value)))); + devicePropertyMapper.insert(device.getProductId(), String.valueOf(device.getId()), ts, reportTime, columns); + } + + /** + * 转换属性值为 IoTDB 驱动支持的类型 + * + * 原因:ENUM、BOOL 业务转换后为 Byte(对应 TDengine 的 TINYINT),而 IoTDB 驱动不支持 setByte,需要转为 INT32 对应的 Integer + */ + private static Object convertValue(Object value) { + if (value instanceof Byte) { + return ((Byte) value).intValue(); + } + return value; + } + + @Override + public List selectHistoryList(Long productId, IotDevicePropertyHistoryListReqVO reqVO) { + try { + return devicePropertyMapper.selectHistoryList(productId, buildColumnName(reqVO.getIdentifier()), + String.valueOf(reqVO.getDeviceId()), + LocalDateTimeUtil.toEpochMilli(reqVO.getTimes()[0]), + LocalDateTimeUtil.toEpochMilli(reqVO.getTimes()[1])); + } catch (Exception exception) { + // 只有表不存在(产品尚未定义属性)返回空;列不存在等其它错误原样抛出 + if (IoTDBUtils.isTableNotExists(exception)) { + return Collections.emptyList(); + } + throw exception; + } + } + + /** + * 构建属性列名:p_ + 中立字段名 + * + * @param identifier 属性标识符,调用前需已通过 {@link IotStorageFieldUtils#validatePropertyIdentifiers(Collection)} 校验 + * @return 列名 + */ + public static String buildColumnName(String identifier) { + if (!IotStorageFieldUtils.isPropertyFieldName(identifier)) { + throw new IllegalArgumentException(StrUtil.format("属性标识符({}) 不能作为存储列", identifier)); + } + return COLUMN_PREFIX + IotStorageFieldUtils.buildFieldName(identifier); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDevicePropertyIoTDBMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDevicePropertyIoTDBMapper.java new file mode 100644 index 0000000..bbbb44b --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/iotdb/IotDevicePropertyIoTDBMapper.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.iot.dal.iotdb; + +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO; +import cn.iocoder.yudao.module.iot.framework.iotdb.core.annotation.IoTDBDS; +import com.baomidou.mybatisplus.annotation.InterceptorIgnore; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; +import java.util.Map; + +/** + * IoTDB 设备属性 Mapper + * + * 注意:表名、列名需要动态拼接,只允许传入 Long 产品编号、DAO 归一化并校验后的列名、白名单内的类型;值统一使用 #{} 绑定 + * + * @author 芋道源码 + */ +@Mapper +@IoTDBDS +@InterceptorIgnore(tenantLine = "true", dataPermission = "true") // 避免 SQL 解析,因为 JSqlParser 对 IoTDB 的 SQL 解析会报错;租户由 Service 层控制 +public interface IotDevicePropertyIoTDBMapper { + + /** + * 获得产品属性表的列 + * + * @param productId 产品编号 + * @return 列列表,包括 ColumnName、DataType、Category 等 + */ + List> selectColumnList(@Param("productId") Long productId); + + void createTable(@Param("productId") Long productId, + @Param("columns") List columns); + + void addColumn(@Param("productId") Long productId, + @Param("column") Column column); + + void dropColumn(@Param("productId") Long productId, + @Param("columnName") String columnName); + + void insert(@Param("productId") Long productId, + @Param("deviceId") String deviceId, + @Param("ts") Long ts, + @Param("reportTime") Long reportTime, + @Param("columns") List columns); + + List selectHistoryList(@Param("productId") Long productId, + @Param("columnName") String columnName, + @Param("deviceId") String deviceId, + @Param("startTime") Long startTime, + @Param("endTime") Long endTime); + + /** + * 属性列 + */ + @Data + @NoArgsConstructor + @AllArgsConstructor + class Column { + + /** + * 列名,格式为 p_ + 中立字段名 + */ + private String name; + /** + * 数据类型,例如说 INT32、STRING;写入时为空 + */ + private String type; + /** + * 值;DDL 时为空 + */ + private Object value; + + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/IotDeviceMessageDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/IotDeviceMessageDAO.java new file mode 100644 index 0000000..084016d --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/IotDeviceMessageDAO.java @@ -0,0 +1,121 @@ +package cn.iocoder.yudao.module.iot.dal.storage; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; + +import javax.annotation.Nullable; +import java.sql.Timestamp; +import java.util.*; + +/** + * IoT 设备【消息】日志的存储 DAO 接口 + * + * 由 yudao.iot.storage.type 选择 TDengine、IoTDB 其中一个实现。各实现的消息身份不同: + * 1. TDengine:(deviceId, ts, id),按 ts DESC, id DESC 排序。同一设备、同一毫秒、不同 id 的消息都会保留 + * 2. IoTDB:(deviceId, ts),id 为普通字段,按 ts DESC 排序。同一设备、同一毫秒再次写入时,后写的整行替换先写的,即使 id 不同。 + * 原因:id 作为 TAG 时,每个设备下每出现一个新的消息 id,就产生一个 IoTDB 元数据设备,元数据随消息量无限增长 + * + * 重复写入时: + * 1. 相同 (deviceId, ts, id):两者都只保留一行。IoTDB 由编码保证整行替换(null 字段也会清空旧值);TDengine 沿用原有写入语义 + * 2. 重投、重发等重新获取 ts 的写入,按各自的物理键判断:TDengine 为 (deviceId, ts, id),与已有行都不同时新增,否则覆盖该行; + * IoTDB 为 (deviceId, ts),该设备该毫秒没有行时新增,已有行时覆盖该行(可能是另一条消息) + * + * @author 芋道源码 + */ +public interface IotDeviceMessageDAO { + + /** + * 按小时统计结果的 key:整点时间,类型为 {@link Timestamp} + */ + String COUNT_TIME = "time"; + /** + * 按小时统计结果的 key:上行消息数,类型为 {@link Long} + */ + String COUNT_UPSTREAM = "upstream_count"; + /** + * 按小时统计结果的 key:下行消息数,类型为 {@link Long} + */ + String COUNT_DOWNSTREAM = "downstream_count"; + + /** + * 初始化:系统启动时,校验存储后端的前提条件,并创建消息表 + */ + void initialize(); + + /** + * 写入设备消息 + * + * @param message 设备消息 + */ + void insert(IotDeviceMessageDO message); + + /** + * 获得设备消息分页 + * + * 注意:与现有行为保持一致,不按 reqVO.times 过滤 + * + * @param reqVO 分页查询条件 + * @return 设备消息分页;消息表不存在时,返回空分页 + */ + PageResult selectPage(IotDeviceMessagePageReqVO reqVO); + + /** + * 按照 requestIds 批量查询消息 + * + * 各存储后端保持一致:requestIds 中的 null 忽略、重复去重;忽略后为空,或 reply 为 null 时,返回空列表 + * + * @param deviceId 设备编号 + * @param requestIds 请求编号集合 + * @param reply 是否回复消息 + * @return 消息列表 + */ + List selectListByRequestIdsAndReply(Long deviceId, Collection requestIds, Boolean reply); + + /** + * 统计设备消息数量 + * + * @param createTime 创建时间(毫秒),如果为空,则统计所有消息数量 + * @return 消息数量 + */ + Long selectCountByCreateTime(@Nullable Long createTime); + + /** + * 按照时间范围(小时),统计设备的消息数量 + * + * @param startTime 开始时间(毫秒),包含 + * @param endTime 结束时间(毫秒),包含 + * @return 每个整点的统计,key 见 {@link #COUNT_TIME}、{@link #COUNT_UPSTREAM}、{@link #COUNT_DOWNSTREAM} + */ + List> selectDeviceMessageCountGroupByDate(Long startTime, Long endTime); + + /** + * 构建按小时统计的一行结果,统一各存储后端的 key 与 Java 类型 + * + * @param time 整点时间,支持 Timestamp、毫秒数值 + * @param upstreamCount 上行消息数,支持任意 Number + * @param downstreamCount 下行消息数,支持任意 Number + * @return 统计结果 + */ + @SuppressWarnings("PatternVariableCanBeUsed") // 保持 JDK8 兼容性 + static Map buildMessageCount(Object time, Object upstreamCount, Object downstreamCount) { + // 1. 整点时间 + Timestamp timestamp; + if (time instanceof Timestamp) { + timestamp = (Timestamp) time; + } else if (time instanceof Date) { + timestamp = new Timestamp(((Date) time).getTime()); + } else if (time instanceof Number) { + timestamp = new Timestamp(((Number) time).longValue()); + } else { + throw new IllegalArgumentException("无法转换为整点时间:" + time); + } + // 2. 上下行数量:SUM、COUNT 等聚合结果的 Number 子类因库而异,统一转为 Long + Map count = new HashMap<>(); + count.put(COUNT_TIME, timestamp); + count.put(COUNT_UPSTREAM, upstreamCount != null ? ((Number) upstreamCount).longValue() : 0L); + count.put(COUNT_DOWNSTREAM, downstreamCount != null ? ((Number) downstreamCount).longValue() : 0L); + return count; + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/IotDevicePropertyDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/IotDevicePropertyDAO.java new file mode 100644 index 0000000..2f72214 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/IotDevicePropertyDAO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.iot.dal.storage; + +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; + +import java.util.List; +import java.util.Map; + +// TODO DONE @AI:storage 包下,是不是加个 package-info.java,说明这个包的作用?已新增 package-info.java +/** + * IoT 设备【属性】历史数据的存储 DAO 接口 + * + * 由 yudao.iot.storage.type 选择 TDengine、IoTDB 其中一个实现。 + * 厂商相关的字段映射、DDL、字段差异、缺表判断等,都在实现类中处理。 + * + * @author 芋道源码 + */ +public interface IotDevicePropertyDAO { + + /** + * 初始化:系统启动时,校验存储后端的前提条件 + */ + void initialize(); + + /** + * 定义(创建或修改)产品的属性表结构 + * + * @param productId 产品编号 + * @param propertyThingModels 产品的属性类物模型列表 + */ + void defineProductPropertyTable(Long productId, List propertyThingModels); + + /** + * 写入设备属性。只记录本次上报的属性 + * + * @param device 设备 + * @param properties 属性,key 为物模型 identifier,value 为 Service 转换后的值 + * @param ts 存储时间(毫秒) + * @param reportTime 上报时间(毫秒) + */ + void insert(IotDeviceDO device, Map properties, Long ts, Long reportTime); + + /** + * 查询设备属性的历史数据,按存储时间倒序 + * + * 调用前,Service 已经校验:设备存在(包括逻辑删除)、属性标识符合法、时间范围完整 + * + * @param productId 产品编号 + * @param reqVO 查询条件 + * @return 历史数据;属性表不存在时,返回空列表 + */ + List selectHistoryList(Long productId, IotDevicePropertyHistoryListReqVO reqVO); + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/package-info.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/package-info.java new file mode 100644 index 0000000..d962086 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/storage/package-info.java @@ -0,0 +1,7 @@ +/** + * iot 模块的时序数据存储 DAO 接口:设备属性、设备消息的统一契约,与具体的时序库无关 + * + * 1. Service 只依赖本包的 DAO 接口 + * 2. 实现类分别在 dal/tdengine、dal/iotdb 包下,由 yudao.iot.storage.type 统一选择其中一个 + */ +package cn.iocoder.yudao.module.iot.dal.storage; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceMessageTDengineDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceMessageTDengineDAO.java new file mode 100644 index 0000000..b6d02b0 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDeviceMessageTDengineDAO.java @@ -0,0 +1,114 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; +import cn.iocoder.yudao.module.iot.dal.storage.IotDeviceMessageDAO; +import cn.iocoder.yudao.module.iot.framework.storage.config.IotStorageProperties; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +/** + * 基于 TDengine 的 {@link IotDeviceMessageDAO} 实现类 + * + * 一张超级表 device_message,每个设备一张子表 device_message_{deviceId} + * + * @author 芋道源码 + */ +@Repository +@ConditionalOnProperty(prefix = IotStorageProperties.PREFIX, name = "type", havingValue = "tdengine", matchIfMissing = true) +@Slf4j +public class IotDeviceMessageTDengineDAO implements IotDeviceMessageDAO { + + @Resource + private IotDeviceMessageMapper deviceMessageMapper; + + @Override + public void initialize() { + if (StrUtil.isNotEmpty(deviceMessageMapper.showSTable())) { + log.info("[initialize][设备消息超级表已存在,创建跳过]"); + return; + } + log.info("[initialize][设备消息超级表不存在,创建开始...]"); + deviceMessageMapper.createSTable(); + log.info("[initialize][设备消息超级表不存在,创建成功]"); + } + + @Override + public void insert(IotDeviceMessageDO message) { + deviceMessageMapper.insert(message); + } + + @Override + public PageResult selectPage(IotDeviceMessagePageReqVO reqVO) { + try { + IPage page = deviceMessageMapper.selectPage( + new Page<>(reqVO.getPageNo(), reqVO.getPageSize()), reqVO); + return new PageResult<>(fillDeviceId(page.getRecords(), reqVO.getDeviceId()), page.getTotal()); + } catch (Exception exception) { + if (StrUtil.contains(exception.getMessage(), "Table does not exist")) { + return PageResult.empty(); + } + throw exception; + } + } + + @Override + public List selectListByRequestIdsAndReply(Long deviceId, Collection requestIds, Boolean reply) { + // reply 为空时,reply = NULL 匹配不到任何消息,无需查询 + if (reply == null || requestIds == null) { + return Collections.emptyList(); + } + // 与 IoTDB 保持一致:忽略 null、去重,避免 IN 列表中绑定 NULL + List validRequestIds = requestIds.stream().filter(Objects::nonNull).distinct() + .collect(Collectors.toList()); + if (CollUtil.isEmpty(validRequestIds)) { + return Collections.emptyList(); + } + return fillDeviceId(deviceMessageMapper.selectListByRequestIdsAndReply(deviceId, validRequestIds, reply), deviceId); + } + + /** + * 补全消息的设备编号 + * + * 原因:查询的是设备子表 device_message_{deviceId},SELECT 未包含 device_id 标签,读出的 deviceId 为空 + * + * @param messages 消息列表 + * @param deviceId 设备编号 + * @return 消息列表 + */ + private static List fillDeviceId(List messages, Long deviceId) { + if (messages != null) { + messages.forEach(message -> message.setDeviceId(deviceId)); + } + return messages; + } + + @Override + public Long selectCountByCreateTime(Long createTime) { + return deviceMessageMapper.selectCountByCreateTime(createTime); + } + + @Override + public List> selectDeviceMessageCountGroupByDate(Long startTime, Long endTime) { + List> counts = deviceMessageMapper.selectDeviceMessageCountGroupByDate(startTime, endTime); + return convertList(counts, count -> IotDeviceMessageDAO.buildMessageCount( + count.get(COUNT_TIME), count.get(COUNT_UPSTREAM), count.get(COUNT_DOWNSTREAM))); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyTDengineDAO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyTDengineDAO.java new file mode 100644 index 0000000..4b017f5 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/tdengine/IotDevicePropertyTDengineDAO.java @@ -0,0 +1,131 @@ +package cn.iocoder.yudao.module.iot.dal.tdengine; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO; +import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.ThingModelProperty; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; +import cn.iocoder.yudao.module.iot.dal.storage.IotDevicePropertyDAO; +import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; +import cn.iocoder.yudao.module.iot.framework.storage.config.IotStorageProperties; +import cn.iocoder.yudao.module.iot.framework.storage.core.util.IotStorageFieldUtils; +import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.stereotype.Repository; + +import java.util.*; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +/** + * 基于 TDengine 的 {@link IotDevicePropertyDAO} 实现类 + * + * 每个产品一张超级表 product_property_{productId},每个设备一张子表 device_property_{deviceId} + * + * @author 芋道源码 + */ +@Repository +@ConditionalOnProperty(prefix = IotStorageProperties.PREFIX, name = "type", havingValue = "tdengine", matchIfMissing = true) +@Slf4j +public class IotDevicePropertyTDengineDAO implements IotDevicePropertyDAO { + + /** + * 物模型的数据类型,与 TDengine 数据类型的映射关系 + * + * @see TDEngine 数据类型 + */ + private static final Map TYPE_MAPPING = MapUtil.builder() + .put(IotDataSpecsDataTypeEnum.INT.getDataType(), TDengineTableField.TYPE_INT) + .put(IotDataSpecsDataTypeEnum.FLOAT.getDataType(), TDengineTableField.TYPE_FLOAT) + .put(IotDataSpecsDataTypeEnum.DOUBLE.getDataType(), TDengineTableField.TYPE_DOUBLE) + .put(IotDataSpecsDataTypeEnum.ENUM.getDataType(), TDengineTableField.TYPE_TINYINT) + .put(IotDataSpecsDataTypeEnum.BOOL.getDataType(), TDengineTableField.TYPE_TINYINT) + .put(IotDataSpecsDataTypeEnum.TEXT.getDataType(), TDengineTableField.TYPE_VARCHAR) + .put(IotDataSpecsDataTypeEnum.DATE.getDataType(), TDengineTableField.TYPE_TIMESTAMP) + .put(IotDataSpecsDataTypeEnum.STRUCT.getDataType(), TDengineTableField.TYPE_VARCHAR) + .put(IotDataSpecsDataTypeEnum.ARRAY.getDataType(), TDengineTableField.TYPE_VARCHAR) + .build(); + + @Resource + private IotDevicePropertyMapper devicePropertyMapper; + + @Override + public void initialize() { + // 产品属性表在产品发布、手动同步时创建,启动时无需初始化 + } + + @Override + public void defineProductPropertyTable(Long productId, List propertyThingModels) { + // 1.1 校验属性标识符,可以作为字段名 + IotStorageFieldUtils.validatePropertyIdentifiers(convertList(propertyThingModels, IotThingModelDO::getIdentifier)); + // 1.2 解析 DB 里的字段 + List oldFields = new ArrayList<>(); + try { + oldFields.addAll(devicePropertyMapper.getProductPropertySTableFieldList(productId)); + } catch (Exception e) { + if (!isTableNotExists(e)) { + throw e; + } + } + + // 2.1 情况一:如果是新增的时候,需要创建表 + List newFields = buildTableFieldList(propertyThingModels); + if (CollUtil.isEmpty(oldFields)) { + if (CollUtil.isEmpty(newFields)) { + log.info("[defineProductPropertyTable][productId({}) 没有需要定义的属性]", productId); + return; + } + devicePropertyMapper.createProductPropertySTable(productId, newFields); + return; + } + // 2.2 情况二:如果是修改的时候,需要更新表 + devicePropertyMapper.alterProductPropertySTable(productId, oldFields, newFields); + } + + private List buildTableFieldList(List thingModels) { + return convertList(thingModels, thingModel -> { + TDengineTableField field = new TDengineTableField( + IotStorageFieldUtils.buildFieldName(thingModel.getIdentifier()), + TYPE_MAPPING.get(thingModel.getProperty().getDataType())); + String dataType = thingModel.getProperty().getDataType(); + if (Objects.equals(dataType, IotDataSpecsDataTypeEnum.TEXT.getDataType())) { + field.setLength(((ThingModelDateOrTextDataSpecs) thingModel.getProperty().getDataSpecs()).getLength()); + } else if (ObjectUtils.equalsAny(dataType, IotDataSpecsDataTypeEnum.STRUCT.getDataType(), + IotDataSpecsDataTypeEnum.ARRAY.getDataType())) { + field.setLength(ThingModelProperty.LENGTH_JSON); + } + return field; + }); + } + + @Override + public void insert(IotDeviceDO device, Map properties, Long ts, Long reportTime) { + // 校验属性标识符:在拼接 SQL 之前,避免保留字段、归一化后重名的属性写入 + IotStorageFieldUtils.validatePropertyIdentifiers(properties.keySet()); + devicePropertyMapper.insert(device, properties, ts, reportTime); + } + + @Override + public List selectHistoryList(Long productId, IotDevicePropertyHistoryListReqVO reqVO) { + try { + return devicePropertyMapper.selectListByHistory(reqVO); + } catch (Exception exception) { + if (isTableNotExists(exception)) { + return Collections.emptyList(); + } + throw exception; + } + } + + private static boolean isTableNotExists(Exception exception) { + return StrUtil.contains(exception.getMessage(), "Table does not exist"); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java index a3bb1f2..1afd0fb 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java @@ -46,6 +46,11 @@ public interface ErrorCodeConstants { ErrorCode DEVICE_REGISTER_DISABLED = new ErrorCode(1_050_003_210, "该产品未开启动态注册功能"); ErrorCode DEVICE_REGISTER_SECRET_INVALID = new ErrorCode(1_050_003_211, "产品密钥验证失败"); ErrorCode DEVICE_REGISTER_ALREADY_EXISTS = new ErrorCode(1_050_003_212, "设备已存在,不允许重复注册"); + // 设备属性存储相关错误码 1-050-003-300 + ErrorCode DEVICE_PROPERTY_HISTORY_TIMES_INVALID = new ErrorCode(1_050_003_300, "设备属性历史的时间范围,必须包含开始、结束两个时间"); + ErrorCode DEVICE_PROPERTY_FIELD_NAME_INVALID = new ErrorCode(1_050_003_301, "属性标识符({}) 不合法,无法作为存储字段"); + ErrorCode DEVICE_PROPERTY_FIELD_NAME_RESERVED = new ErrorCode(1_050_003_302, "属性标识符({}) 与存储保留字段({}) 冲突"); + ErrorCode DEVICE_PROPERTY_FIELD_NAME_DUPLICATE = new ErrorCode(1_050_003_303, "属性标识符({}) 与({}) 的存储字段({}) 重复"); // ========== 产品分类 1-050-004-000 ========== ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_050_004_000, "产品分类不存在"); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/IoTDBUtils.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/IoTDBUtils.java new file mode 100644 index 0000000..4cf2f8a --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/IoTDBUtils.java @@ -0,0 +1,150 @@ +package cn.iocoder.yudao.module.iot.framework.iotdb.core; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import org.apache.iotdb.rpc.StatementExecutionException; + +import java.sql.SQLException; +import java.util.*; + +/** + * IoTDB 工具类 + * + * 1. 异常分类:识别“表不存在” + * 2. 启动前提检查:只读取配置并校验,不修改 IoTDB 的任何配置 + * + * @author 芋道源码 + */ +public class IoTDBUtils { + + /** + * IoTDB 状态码 - 表不存在 + */ + public static final int STATUS_CODE_TABLE_NOT_EXISTS = 550; + + /** + * 要求的时间精度:毫秒 + */ + public static final String TIMESTAMP_PRECISION_MS = "ms"; + /** + * 要求关闭的配置项:部分写入。开启时,一行中类型错误的列会失败,其它列仍然写入 + */ + public static final String CONFIG_ENABLE_PARTIAL_INSERT = "enable_partial_insert"; + /** + * DataNode 的运行状态 + */ + public static final String DATA_NODE_STATUS_RUNNING = "Running"; + + // ========== 异常分类 ========== + + /** + * 判断异常是否为“表不存在” + * + * 只识别明确的 550 状态码,并沿 cause 链查找:外层 SQLException 的 errorCode 可能为 0, + * 真实状态码在内层的 SQLException 或 {@link StatementExecutionException} 中。 + * 列不存在(616)、类型不匹配(507)、权限等其它错误,都返回 false,由调用方原样抛出。 + * + * @param throwable 异常 + * @return 是否表不存在 + */ + @SuppressWarnings("PatternVariableCanBeUsed") // 保持 JDK8 兼容性 + public static boolean isTableNotExists(Throwable throwable) { + Set visited = Collections.newSetFromMap(new IdentityHashMap<>()); + for (Throwable cause = throwable; cause != null && visited.add(cause); cause = cause.getCause()) { + if (cause instanceof StatementExecutionException + && ((StatementExecutionException) cause).getStatusCode() == STATUS_CODE_TABLE_NOT_EXISTS) { + return true; + } + if (cause instanceof SQLException + && ((SQLException) cause).getErrorCode() == STATUS_CODE_TABLE_NOT_EXISTS) { + return true; + } + } + return false; + } + + // ========== 启动前提检查 ========== + + /** + * 校验时间精度为毫秒 + * + * @param variables SHOW VARIABLES 的结果 + */ + public static void validateTimestampPrecision(List> variables) { + Map variable = CollUtil.findOne(variables, + row -> StrUtil.equalsIgnoreCase(getString(row, "Variable"), "TimestampPrecision")); + if (variable == null) { + throw new IllegalStateException("[IoTDB 前提检查] 无法读取 TimestampPrecision,请确认账号有查询权限"); + } + String precision = getString(variable, "Value"); + if (!StrUtil.equals(TIMESTAMP_PRECISION_MS, precision)) { + throw new IllegalStateException(StrUtil.format( + "[IoTDB 前提检查] TimestampPrecision 必须为 ms,当前为 {}", precision)); + } + } + + /** + * 校验所有 DataNode 都处于运行状态,并返回它们的编号 + * + * @param dataNodes SHOW DATANODES 的结果 + * @return DataNode 编号列表 + */ + public static List validateDataNodes(List> dataNodes) { + if (CollUtil.isEmpty(dataNodes)) { + throw new IllegalStateException("[IoTDB 前提检查] 无法读取 DataNode 列表,请确认账号有查询权限"); + } + List nodeIds = new ArrayList<>(dataNodes.size()); + for (Map dataNode : dataNodes) { + Object nodeId = getIgnoreCase(dataNode, "NodeID"); + String status = getString(dataNode, "Status"); + if (!(nodeId instanceof Number)) { + throw new IllegalStateException(StrUtil.format("[IoTDB 前提检查] 无法识别 DataNode 编号:{}", dataNode)); + } + if (!StrUtil.equalsIgnoreCase(DATA_NODE_STATUS_RUNNING, status)) { + throw new IllegalStateException(StrUtil.format( + "[IoTDB 前提检查] DataNode({}) 状态为 {},必须全部为 Running 才能确认部分写入配置", nodeId, status)); + } + nodeIds.add(((Number) nodeId).intValue()); + } + return nodeIds; + } + + /** + * 校验 DataNode 关闭了部分写入(enable_partial_insert=false) + * + * @param nodeId DataNode 编号 + * @param configurations SHOW ALL CONFIGURATION ON nodeId 的结果 + */ + public static void validatePartialInsertDisabled(Integer nodeId, List> configurations) { + Map configuration = CollUtil.findOne(configurations, + row -> StrUtil.equals(getString(row, "name"), CONFIG_ENABLE_PARTIAL_INSERT)); + if (configuration == null) { + throw new IllegalStateException(StrUtil.format( + "[IoTDB 前提检查] DataNode({}) 无法读取 {} 配置,请确认 IoTDB 版本与账号权限", nodeId, CONFIG_ENABLE_PARTIAL_INSERT)); + } + String value = getString(configuration, "value"); + if (!StrUtil.equalsIgnoreCase(Boolean.FALSE.toString(), value)) { + throw new IllegalStateException(StrUtil.format( + "[IoTDB 前提检查] DataNode({}) 的 {} 必须为 false,当前为 {}。请修改所有 DataNode 的配置文件,应用不会自动修改", + nodeId, CONFIG_ENABLE_PARTIAL_INSERT, value)); + } + } + + /** + * 忽略大小写,获得结果行的列值。原因:IoTDB 系统语句的列名为 NodeID、Variable 等,不同版本大小写可能不同 + */ + public static Object getIgnoreCase(Map row, String column) { + for (Map.Entry entry : row.entrySet()) { + if (StrUtil.equalsIgnoreCase(entry.getKey(), column)) { + return entry.getValue(); + } + } + return null; + } + + private static String getString(Map row, String column) { + Object value = getIgnoreCase(row, column); + return value != null ? value.toString() : null; + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/annotation/IoTDBDS.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/annotation/IoTDBDS.java new file mode 100644 index 0000000..5bb355c --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/annotation/IoTDBDS.java @@ -0,0 +1,19 @@ +package cn.iocoder.yudao.module.iot.framework.iotdb.core.annotation; + +import com.baomidou.dynamic.datasource.annotation.DS; + +import java.lang.annotation.*; + +/** + * IoTDB 数据源 + * + * 对应 spring.datasource.dynamic.datasource.iotdb 条目 + * + * @author 芋道源码 + */ +@Target({ElementType.TYPE, ElementType.METHOD}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@DS("iotdb") +public @interface IoTDBDS { +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/package-info.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/package-info.java new file mode 100644 index 0000000..bcbafe2 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/iotdb/package-info.java @@ -0,0 +1,4 @@ +/** + * iot 模块的 IoTDB 拓展封装 + */ +package cn.iocoder.yudao.module.iot.framework.iotdb; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageConfiguration.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageConfiguration.java new file mode 100644 index 0000000..0798dc9 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageConfiguration.java @@ -0,0 +1,17 @@ +package cn.iocoder.yudao.module.iot.framework.storage.config; + +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Configuration; + +// TODO DONE @AI:按照项目的习惯,这个是不是不用写单测?已移除重复的装配单测 IotStorageConfigurationTest,实际装配由实库验收覆盖 +/** + * IoT 时序存储的配置类 + * + * 由 yudao.iot.storage.type 选择存储后端,对应的 DAO 实现通过 @ConditionalOnProperty 装配 + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties(IotStorageProperties.class) +public class IotStorageConfiguration { +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageInitRunner.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageInitRunner.java new file mode 100644 index 0000000..40093a5 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageInitRunner.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.iot.framework.storage.config; + +import cn.iocoder.yudao.module.iot.dal.storage.IotDeviceMessageDAO; +import cn.iocoder.yudao.module.iot.dal.storage.IotDevicePropertyDAO; +import com.baomidou.dynamic.datasource.DynamicRoutingDataSource; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import org.springframework.boot.ApplicationArguments; +import org.springframework.boot.ApplicationRunner; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; + +// TODO DONE @AI:按照项目的习惯,这个是不是不用写单测?已移除独立单测 IotStorageInitRunnerTest,关键的缺数据源防回落 master 断言并入实库验收 +/** + * IoT 时序存储的初始化 Runner:校验数据源、前提条件,并创建消息表 + * + * 只初始化 yudao.iot.storage.type 选中的存储后端。失败时退出系统,避免带着不可用的存储运行 + * + * @author 芋道源码 + */ +@Component +@Slf4j +public class IotStorageInitRunner implements ApplicationRunner { + + @Resource + private IotStorageProperties storageProperties; + @Resource + private DataSource dataSource; + + @Resource + private IotDevicePropertyDAO devicePropertyDAO; + @Resource + private IotDeviceMessageDAO deviceMessageDAO; + + @Override + public void run(ApplicationArguments args) { + try { + initialize(); + } catch (Exception ex) { + // 初始化失败时打印错误消息并退出系统 + log.error("[run][IoT 时序存储({}) 初始化失败,系统无法正常运行,即将退出]", storageProperties.getType(), ex); + System.exit(1); + } + } + + /** + * 初始化选中的存储后端 + */ + public void initialize() { + // 1. 校验数据源已配置:dynamic-datasource 找不到数据源时,会回退到 master,必须提前拦截 + validateDataSourceExists(); + // 2. 初始化 DAO + devicePropertyDAO.initialize(); + deviceMessageDAO.initialize(); + log.info("[initialize][IoT 时序存储({}) 初始化完成]", storageProperties.getType()); + } + + private void validateDataSourceExists() { + String dataSourceName = storageProperties.getType().getDataSourceName(); + if (!(dataSource instanceof DynamicRoutingDataSource)) { + throw new IllegalStateException(String.format("[IoT 时序存储] 需要使用 dynamic-datasource 多数据源,当前为 %s", + dataSource.getClass().getName())); + } + if (!((DynamicRoutingDataSource) dataSource).getDataSources().containsKey(dataSourceName)) { + throw new IllegalStateException(String.format("[IoT 时序存储] 未配置数据源 spring.datasource.dynamic.datasource.%s," + + "请检查 yudao.iot.storage.type=%s 对应的数据源配置", dataSourceName, storageProperties.getType().getType())); + } + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageProperties.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageProperties.java new file mode 100644 index 0000000..6bbda4f --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/config/IotStorageProperties.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.iot.framework.storage.config; + +import cn.iocoder.yudao.module.iot.framework.storage.core.enums.IotStorageTypeEnum; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +/** + * IoT 时序数据存储的配置项 + * + * @author 芋道源码 + */ +@ConfigurationProperties(prefix = IotStorageProperties.PREFIX) +@Validated +@Data +public class IotStorageProperties { + + public static final String PREFIX = "yudao.iot.storage"; + + /** + * 存储类型,同时决定属性历史、消息日志的存储后端 + * + * 写错值时,配置绑定失败,应用启动失败 + */ + @NotNull(message = "IoT 存储类型不能为空") + private IotStorageTypeEnum type = IotStorageTypeEnum.TDENGINE; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/core/enums/IotStorageTypeEnum.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/core/enums/IotStorageTypeEnum.java new file mode 100644 index 0000000..6bc16d5 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/core/enums/IotStorageTypeEnum.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.iot.framework.storage.core.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * IoT 时序数据(属性历史、消息日志)的存储类型枚举 + * + * @author 芋道源码 + */ +@Getter +@AllArgsConstructor +public enum IotStorageTypeEnum { + + TDENGINE("tdengine", "tdengine"), + IOTDB("iotdb", "iotdb"); + + /** + * 类型,对应 yudao.iot.storage.type 配置项 + */ + private final String type; + /** + * 数据源名,对应 spring.datasource.dynamic.datasource 下的条目 + */ + private final String dataSourceName; + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/core/util/IotStorageFieldUtils.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/core/util/IotStorageFieldUtils.java new file mode 100644 index 0000000..ad72612 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/core/util/IotStorageFieldUtils.java @@ -0,0 +1,103 @@ +package cn.iocoder.yudao.module.iot.framework.storage.core.util; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.regex.Pattern; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; + +/** + * IoT 时序存储的字段名工具类 + * + * 属性标识符(identifier)统一归一化为小写下划线的“中立字段名”,各存储后端在此基础上映射物理列名: + * 1. TDengine:直接使用中立字段名 + * 2. IoTDB:使用 p_ + 中立字段名,避免与 time 等内置列冲突 + * + * @author 芋道源码 + */ +public class IotStorageFieldUtils { + + /** + * 系统字段 - 存储时间 + */ + public static final String FIELD_TS = "ts"; + /** + * 系统字段 - 上报时间 + */ + public static final String FIELD_REPORT_TIME = "report_time"; + /** + * 系统字段 - 设备编号 + */ + public static final String FIELD_DEVICE_ID = "device_id"; + + /** + * 保留字段名:属性标识符归一化后,不允许与它们相同 + */ + public static final Set RESERVED_FIELD_NAMES = SetUtils.asSet(FIELD_TS, FIELD_REPORT_TIME, FIELD_DEVICE_ID); + + /** + * 中立字段名的格式:只允许小写字母、数字、下划线,且以字母开头 + * + * 动态拼接到 SQL 结构名(列名)前,必须通过该格式校验 + */ + private static final Pattern FIELD_NAME_PATTERN = Pattern.compile("^[a-z][a-z0-9_]{0,63}$"); + + /** + * 构建中立字段名:转为小写下划线,需要和建表、写入、查询保持一致。 + * 例如:PT -> pt,PfT -> pf_t。 + * + * @param identifier 属性标识符 + * @return 中立字段名 + */ + public static String buildFieldName(String identifier) { + if (StrUtil.isBlank(identifier)) { + return identifier; + } + return StrUtil.toUnderlineCase(identifier).toLowerCase(Locale.ROOT); + } + + /** + * 判断属性标识符,归一化后是否为合法的属性字段名(格式合法,且不是保留字段) + * + * @param identifier 属性标识符 + * @return 是否合法 + */ + public static boolean isPropertyFieldName(String identifier) { + String fieldName = buildFieldName(identifier); + return fieldName != null && FIELD_NAME_PATTERN.matcher(fieldName).matches() + && !RESERVED_FIELD_NAMES.contains(fieldName); + } + + /** + * 校验属性标识符列表,可以作为存储字段。define、insert 拼接 SQL 之前,都需要校验原始标识符: + * 1. 归一化后格式合法 + * 2. 归一化后不是 ts、report_time、device_id 保留字段 + * 3. 归一化后不重复,例如说 fooBar 与 foo_bar + * + * @param identifiers 属性标识符列表 + */ + public static void validatePropertyIdentifiers(Collection identifiers) { + Map fieldNames = new HashMap<>(); + for (String identifier : identifiers) { + String fieldName = buildFieldName(identifier); + if (fieldName == null || !FIELD_NAME_PATTERN.matcher(fieldName).matches()) { + throw exception(DEVICE_PROPERTY_FIELD_NAME_INVALID, identifier); + } + if (RESERVED_FIELD_NAMES.contains(fieldName)) { + throw exception(DEVICE_PROPERTY_FIELD_NAME_RESERVED, identifier, fieldName); + } + String existsIdentifier = fieldNames.putIfAbsent(fieldName, identifier); + if (existsIdentifier != null) { + throw exception(DEVICE_PROPERTY_FIELD_NAME_DUPLICATE, identifier, existsIdentifier, fieldName); + } + } + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/package-info.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/package-info.java new file mode 100644 index 0000000..46e49db --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/storage/package-info.java @@ -0,0 +1,4 @@ +/** + * iot 模块的时序数据存储封装:通过 yudao.iot.storage.type 选择 TDengine 或 IoTDB + */ +package cn.iocoder.yudao.module.iot.framework.storage; diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/config/TDengineTableInitRunner.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/config/TDengineTableInitRunner.java deleted file mode 100644 index 1de2dcd..0000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/config/TDengineTableInitRunner.java +++ /dev/null @@ -1,34 +0,0 @@ -package cn.iocoder.yudao.module.iot.framework.tdengine.config; - -import cn.iocoder.yudao.module.iot.service.device.message.IotDeviceMessageService; -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.boot.ApplicationArguments; -import org.springframework.boot.ApplicationRunner; -import org.springframework.stereotype.Component; - -/** - * TDengine 表初始化的 Configuration - * - * @author alwayssuper - */ -@Component -@RequiredArgsConstructor -@Slf4j -public class TDengineTableInitRunner implements ApplicationRunner { - - private final IotDeviceMessageService deviceMessageService; - - @Override - public void run(ApplicationArguments args) { - try { - // 初始化设备消息表 - deviceMessageService.defineDeviceMessageStable(); - } catch (Exception ex) { - // 初始化失败时打印错误消息并退出系统 - log.error("[run][TDengine初始化设备消息表结构失败,系统无法正常运行,即将退出]", ex); - System.exit(1); - } - } - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/core/TDengineTableField.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/core/TDengineTableField.java index 010e369..d472ec3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/core/TDengineTableField.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/framework/tdengine/core/TDengineTableField.java @@ -1,12 +1,10 @@ package cn.iocoder.yudao.module.iot.framework.tdengine.core; -import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.ThingModelProperty; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import java.util.Locale; - /** * TDEngine 表字段 */ @@ -30,9 +28,9 @@ public class TDengineTableField { public static final String TYPE_TIMESTAMP = "TIMESTAMP"; /** - * 字段长度 - VARCHAR 默认长度 + * 字段长度 - VARCHAR 默认长度,与 STRUCT、ARRAY 等 JSON 属性的长度上限保持一致 */ - public static final int LENGTH_VARCHAR = 1024; + public static final int LENGTH_VARCHAR = ThingModelProperty.LENGTH_JSON; /** * 注释 - TAG 字段 @@ -64,15 +62,4 @@ public class TDengineTableField { this.type = type; } - /** - * 构建字段名:TDengine 默认会将字段名转为小写,需要和建表、写入、查询保持一致。 - * 例如:PT -> pt,PfT -> pf_t。 - */ - public static String buildFieldName(String field) { - if (StrUtil.isBlank(field)) { - return field; - } - return StrUtil.toUnderlineCase(field).toLowerCase(Locale.ROOT); - } - } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageService.java index e28f489..5323cca 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageService.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageService.java @@ -21,13 +21,6 @@ import java.util.List; public interface IotDeviceMessageService { /** - * 初始化设备消息的 TDengine 超级表 - * - * 系统启动时,会自动初始化一次 - */ - void defineDeviceMessageStable(); - - /** * 发送设备消息 * * @param message 消息(“codec(编解码)字段” 部分字段) diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java index dae8855..77f113b 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImpl.java @@ -25,12 +25,10 @@ import cn.iocoder.yudao.module.iot.core.topic.property.IotDevicePropertyPostReqD import cn.iocoder.yudao.module.iot.core.util.IotDeviceMessageUtils; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceMessageMapper; +import cn.iocoder.yudao.module.iot.dal.storage.IotDeviceMessageDAO; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService; import cn.iocoder.yudao.module.iot.service.ota.IotOtaTaskRecordService; -import com.baomidou.mybatisplus.core.metadata.IPage; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.google.common.base.Objects; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; @@ -67,22 +65,11 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { private IotOtaTaskRecordService otaTaskRecordService; @Resource - private IotDeviceMessageMapper deviceMessageMapper; + private IotDeviceMessageDAO deviceMessageDAO; @Resource private IotDeviceMessageProducer deviceMessageProducer; - @Override - public void defineDeviceMessageStable() { - if (StrUtil.isNotEmpty(deviceMessageMapper.showSTable())) { - log.info("[defineDeviceMessageStable][设备消息超级表已存在,创建跳过]"); - return; - } - log.info("[defineDeviceMessageStable][设备消息超级表不存在,创建开始...]"); - deviceMessageMapper.createSTable(); - log.info("[defineDeviceMessageStable][设备消息超级表不存在,创建成功]"); - } - @Async void createDeviceLogAsync(IotDeviceMessage message) { IotDeviceMessageDO messageDO = BeanUtils.toBean(message, IotDeviceMessageDO.class) @@ -102,7 +89,7 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { messageDO.setTs(System.currentTimeMillis()); } try { - deviceMessageMapper.insert(messageDO); + deviceMessageDAO.insert(messageDO); } catch (Exception ex) { // 特殊:@Async 方法的异常默认会被 handler 吞掉,这里显式记录便于排查 log.error("[createDeviceLogAsync][消息日志写入失败 deviceId({}) messageId({}) paramsLen({}) dataLen({})]", @@ -337,16 +324,7 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { @Override public PageResult getDeviceMessagePage(IotDeviceMessagePageReqVO pageReqVO) { - try { - IPage page = deviceMessageMapper.selectPage( - new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize()), pageReqVO); - return new PageResult<>(page.getRecords(), page.getTotal()); - } catch (Exception exception) { - if (exception.getMessage().contains("Table does not exist")) { - return PageResult.empty(); - } - throw exception; - } + return deviceMessageDAO.selectPage(pageReqVO); } @Override @@ -354,12 +332,12 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { if (CollUtil.isEmpty(requestIds)) { return ListUtil.of(); } - return deviceMessageMapper.selectListByRequestIdsAndReply(deviceId, requestIds, reply); + return deviceMessageDAO.selectListByRequestIdsAndReply(deviceId, requestIds, reply); } @Override public Long getDeviceMessageCount(LocalDateTime createTime) { - return deviceMessageMapper.selectCountByCreateTime( + return deviceMessageDAO.selectCountByCreateTime( createTime != null ? LocalDateTimeUtil.toEpochMilli(createTime) : null); } @@ -367,7 +345,7 @@ public class IotDeviceMessageServiceImpl implements IotDeviceMessageService { public List getDeviceMessageSummaryByDate( IotStatisticsDeviceMessageReqVO reqVO) { // 1. 按小时统计,获取分项统计数据 - List> countList = deviceMessageMapper.selectDeviceMessageCountGroupByDate( + List> countList = deviceMessageDAO.selectDeviceMessageCountGroupByDate( LocalDateTimeUtil.toEpochMilli(reqVO.getTimes()[0]), LocalDateTimeUtil.toEpochMilli(reqVO.getTimes()[1])); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java index 77db754..dbd09cb 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImpl.java @@ -2,11 +2,9 @@ package cn.iocoder.yudao.module.iot.service.device.property; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.LocalDateTimeUtil; -import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; @@ -14,14 +12,12 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDevicePropertyDO; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; -import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO; import cn.iocoder.yudao.module.iot.dal.redis.device.DeviceReportTimeRedisDAO; import cn.iocoder.yudao.module.iot.dal.redis.device.DeviceServerIdRedisDAO; -import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper; -import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; +import cn.iocoder.yudao.module.iot.dal.storage.IotDevicePropertyDAO; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; -import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; +import cn.iocoder.yudao.module.iot.framework.storage.core.util.IotStorageFieldUtils; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; @@ -35,8 +31,10 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.*; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.getBigDecimal; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_PROPERTY_HISTORY_TIMES_INVALID; /** * IoT 设备【属性】数据 Service 实现类 @@ -47,23 +45,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.getBigD @Slf4j public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { - /** - * 物模型的数据类型,与 TDengine 数据类型的映射关系 - * - * @see TDEngine 数据类型 - */ - private static final Map TYPE_MAPPING = MapUtil.builder() - .put(IotDataSpecsDataTypeEnum.INT.getDataType(), TDengineTableField.TYPE_INT) - .put(IotDataSpecsDataTypeEnum.FLOAT.getDataType(), TDengineTableField.TYPE_FLOAT) - .put(IotDataSpecsDataTypeEnum.DOUBLE.getDataType(), TDengineTableField.TYPE_DOUBLE) - .put(IotDataSpecsDataTypeEnum.ENUM.getDataType(), TDengineTableField.TYPE_TINYINT) - .put(IotDataSpecsDataTypeEnum.BOOL.getDataType(), TDengineTableField.TYPE_TINYINT) - .put(IotDataSpecsDataTypeEnum.TEXT.getDataType(), TDengineTableField.TYPE_VARCHAR) - .put(IotDataSpecsDataTypeEnum.DATE.getDataType(), TDengineTableField.TYPE_TIMESTAMP) - .put(IotDataSpecsDataTypeEnum.STRUCT.getDataType(), TDengineTableField.TYPE_VARCHAR) - .put(IotDataSpecsDataTypeEnum.ARRAY.getDataType(), TDengineTableField.TYPE_VARCHAR) - .build(); - @Resource private IotThingModelService thingModelService; @Resource @@ -81,54 +62,18 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { private DeviceServerIdRedisDAO deviceServerIdRedisDAO; @Resource - private IotDevicePropertyMapper devicePropertyMapper; + private IotDevicePropertyDAO devicePropertyDAO; // ========== 设备属性相关操作 ========== @Override public void defineDevicePropertyData(Long productId) { - // 1.1 查询产品和物模型 + // 1. 查询产品和物模型 IotProductDO product = productService.validateProductExists(productId); List thingModels = filterList(thingModelService.getThingModelListByProductId(productId), thingModel -> IotThingModelTypeEnum.PROPERTY.getType().equals(thingModel.getType())); - // 1.2 解析 DB 里的字段 - List oldFields = new ArrayList<>(); - try { - oldFields.addAll(devicePropertyMapper.getProductPropertySTableFieldList(product.getId())); - } catch (Exception e) { - if (!e.getMessage().contains("Table does not exist")) { - throw e; - } - } - - // 2.1 情况一:如果是新增的时候,需要创建表 - List newFields = buildTableFieldList(thingModels); - if (CollUtil.isEmpty(oldFields)) { - if (CollUtil.isEmpty(newFields)) { - log.info("[defineDevicePropertyData][productId({}) 没有需要定义的属性]", productId); - return; - } - devicePropertyMapper.createProductPropertySTable(product.getId(), newFields); - return; - } - // 2.2 情况二:如果是修改的时候,需要更新表 - devicePropertyMapper.alterProductPropertySTable(product.getId(), oldFields, newFields); - } - - private List buildTableFieldList(List thingModels) { - return convertList(thingModels, thingModel -> { - TDengineTableField field = new TDengineTableField( - TDengineTableField.buildFieldName(thingModel.getIdentifier()), - TYPE_MAPPING.get(thingModel.getProperty().getDataType())); - String dataType = thingModel.getProperty().getDataType(); - if (Objects.equals(dataType, IotDataSpecsDataTypeEnum.TEXT.getDataType())) { - field.setLength(((ThingModelDateOrTextDataSpecs) thingModel.getProperty().getDataSpecs()).getLength()); - } else if (ObjectUtils.equalsAny(dataType, IotDataSpecsDataTypeEnum.STRUCT.getDataType(), - IotDataSpecsDataTypeEnum.ARRAY.getDataType())) { - field.setLength(TDengineTableField.LENGTH_VARCHAR); - } - return field; - }); + // 2. 定义存储结构:字段映射、差异比较、建表改表,由存储 DAO 实现 + devicePropertyDAO.defineProductPropertyTable(product.getId(), thingModels); } @Override @@ -174,7 +119,7 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { log.error("[saveDeviceProperty][消息({}) 没有合法的属性]", message); } else { // 2.1 保存设备属性【数据】 - devicePropertyMapper.insert(device, properties, + devicePropertyDAO.insert(device, properties, System.currentTimeMillis(), LocalDateTimeUtil.toEpochMilli(message.getReportTime())); @@ -213,14 +158,26 @@ public class IotDevicePropertyServiceImpl implements IotDevicePropertyService { @Override public List getHistoryDevicePropertyList(IotDevicePropertyHistoryListReqVO listReqVO) { - try { - return devicePropertyMapper.selectListByHistory(listReqVO); - } catch (Exception exception) { - if (exception.getMessage().contains("Table does not exist")) { - return Collections.emptyList(); - } - throw exception; + // 1.1 校验时间范围:必须包含开始、结束两个时间;任一为空时,无法确定范围,返回空 + LocalDateTime[] times = listReqVO.getTimes(); + if (times == null || times.length != 2) { + throw exception(DEVICE_PROPERTY_HISTORY_TIMES_INVALID); + } + if (times[0] == null || times[1] == null) { + return Collections.emptyList(); + } + // 1.2 校验属性标识符:无法作为存储字段的标识符,不会有历史数据 + if (!IotStorageFieldUtils.isPropertyFieldName(listReqVO.getIdentifier())) { + return Collections.emptyList(); } + // 1.3 校验设备:按当前租户查询,且过滤已删除的设备;不存在时,不查询历史数据 + IotDeviceDO device = deviceService.getDevice(listReqVO.getDeviceId()); + if (device == null) { + return Collections.emptyList(); + } + + // 2. 查询历史数据 + return devicePropertyDAO.selectHistoryList(device.getProductId(), listReqVO); } // ========== 设备时间相关操作 ========== diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java index 9029960..9b645ba 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImpl.java @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo.IotThingModelS import cn.iocoder.yudao.module.iot.convert.thingmodel.IotThingModelConvert; import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; +import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.ThingModelProperty; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.dataType.ThingModelBoolOrEnumDataSpecs; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.dataType.ThingModelDataSpecs; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.dataType.ThingModelDateOrTextDataSpecs; @@ -25,7 +26,6 @@ import cn.iocoder.yudao.module.iot.dal.mysql.thingmodel.IotThingModelMapper; import cn.iocoder.yudao.module.iot.dal.redis.RedisKeyConstants; import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; -import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; import cn.iocoder.yudao.module.iot.service.device.IotDeviceModbusPointService; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import jakarta.annotation.Resource; @@ -193,8 +193,8 @@ public class IotThingModelServiceImpl implements IotThingModelService { String dataType = thingModel.getProperty().getDataType(); if (ObjectUtils.equalsAny(dataType, IotDataSpecsDataTypeEnum.STRUCT.getDataType(), IotDataSpecsDataTypeEnum.ARRAY.getDataType())) { - // 特殊:STRUCT 和 ARRAY 类型,在 TDengine 里,没有对应数据类型,只能通过 JSON 来存储 - return convertToVarchar(JsonUtils.toJsonString(value), TDengineTableField.LENGTH_VARCHAR); + // 特殊:STRUCT 和 ARRAY 类型,在时序库里,没有对应数据类型,只能通过 JSON 来存储 + return convertToVarchar(JsonUtils.toJsonString(value), ThingModelProperty.LENGTH_JSON); } if (IotDataSpecsDataTypeEnum.INT.getDataType().equals(dataType)) { return convertToInt(value); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDevicePropertyMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDevicePropertyMapper.xml index c47c5a5..2003c55 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDevicePropertyMapper.xml +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/device/IotDevicePropertyMapper.xml @@ -51,7 +51,7 @@ TAGS ('${device.id}') (ts, report_time, - ${@cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField@buildFieldName(key)} + ${@cn.iocoder.yudao.module.iot.framework.storage.core.util.IotStorageFieldUtils@buildFieldName(key)} ) VALUES @@ -68,9 +68,9 @@ - SELECT ${@cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField@buildFieldName(reqVO.identifier)} AS `value`, ts AS update_time + SELECT ${@cn.iocoder.yudao.module.iot.framework.storage.core.util.IotStorageFieldUtils@buildFieldName(reqVO.identifier)} AS `value`, ts AS update_time FROM device_property_${reqVO.deviceId} - WHERE ${@cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField@buildFieldName(reqVO.identifier)} IS NOT NULL + WHERE ${@cn.iocoder.yudao.module.iot.framework.storage.core.util.IotStorageFieldUtils@buildFieldName(reqVO.identifier)} IS NOT NULL AND ts BETWEEN ${@cn.hutool.core.date.LocalDateTimeUtil@toEpochMilli(reqVO.times[0])} AND ${@cn.hutool.core.date.LocalDateTimeUtil@toEpochMilli(reqVO.times[1])} ORDER BY ts DESC diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotdb/IotDeviceMessageIoTDBMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotdb/IotDeviceMessageIoTDBMapper.xml new file mode 100644 index 0000000..c5bb9f0 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotdb/IotDeviceMessageIoTDBMapper.xml @@ -0,0 +1,129 @@ + + + + + + + + DESC device_message + + + + CREATE TABLE IF NOT EXISTS device_message ( + device_id STRING TAG, + id STRING FIELD, + upstream INT32 FIELD, + reply INT32 FIELD, + method STRING FIELD, + identifier STRING FIELD, + request_id STRING FIELD, + server_id STRING FIELD, + params STRING FIELD, + data STRING FIELD, + msg STRING FIELD, + report_time STRING FIELD, + tenant_id STRING FIELD, + code STRING FIELD + ) + + + + INSERT INTO device_message ( + time, device_id, id, upstream, reply, + method, identifier, request_id, server_id, params, + data, msg, report_time, tenant_id, code + ) + VALUES ( + #{ts}, #{deviceId}, #{id}, #{upstream}, #{reply}, + #{method}, #{identifier}, #{requestId}, #{serverId}, #{params}, + #{data}, #{msg}, #{reportTime}, #{tenantId}, #{code} + ) + + + + SELECT time AS ts, device_id, id, upstream, reply, + method, identifier, request_id, server_id, params, + data, msg, report_time, tenant_id, code + FROM device_message + + + + WHERE device_id = #{deviceId} + + AND method = #{method} + + + AND upstream = #{upstream} + + + AND reply = #{reply} + + + AND identifier = #{identifier} + + + + + + + ORDER BY time DESC + + LIMIT #{limit} OFFSET #{offset} + + + + + SELECT count(*) + FROM device_message + + + + + + WHERE device_id = #{deviceId} + AND reply = #{reply} + AND request_id IN + + #{requestId} + + ORDER BY time DESC + + + + SELECT count(*) + FROM device_message + + + AND time >= #{createTime} + + + + + + + SELECT + date_bin(1h, time) AS time, + count_if(upstream = 1) AS upstream_count, + count_if(upstream = 0) AS downstream_count + FROM device_message + + + AND time >= #{startTime} + + + AND time <= #{endTime} + + + GROUP BY date_bin(1h, time) + + + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotdb/IotDevicePropertyIoTDBMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotdb/IotDevicePropertyIoTDBMapper.xml new file mode 100644 index 0000000..7530c27 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/iotdb/IotDevicePropertyIoTDBMapper.xml @@ -0,0 +1,71 @@ + + + + + + + + DESC product_property_${productId} + + + + CREATE TABLE IF NOT EXISTS product_property_${productId} ( + device_id STRING TAG, + report_time TIMESTAMP FIELD + + , "${column.name}" ${column.type} FIELD + + ) + + + + ALTER TABLE product_property_${productId} + ADD COLUMN IF NOT EXISTS "${column.name}" ${column.type} FIELD + + + + ALTER TABLE product_property_${productId} + DROP COLUMN IF EXISTS "${columnName}" + + + + INSERT INTO product_property_${productId} (time, device_id + + , report_time + + + , "${column.name}" + + ) + VALUES (#{ts}, #{deviceId} + + , #{reportTime} + + + , #{column.value} + + ) + + + + SELECT "${columnName}" AS "value", time AS update_time + FROM product_property_${productId} + WHERE device_id = #{deviceId} + AND time >= #{startTime} + AND time <= #{endTime} + AND "${columnName}" IS NOT NULL + ORDER BY time DESC + + + diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/IoTDBUtilsTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/IoTDBUtilsTest.java new file mode 100644 index 0000000..0696fa0 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/iotdb/core/IoTDBUtilsTest.java @@ -0,0 +1,153 @@ +package cn.iocoder.yudao.module.iot.framework.iotdb.core; + +import cn.hutool.core.map.MapUtil; +import org.apache.iotdb.common.rpc.thrift.TSStatus; +import org.apache.iotdb.jdbc.IoTDBSQLException; +import org.apache.iotdb.rpc.StatementExecutionException; +import org.apache.iotdb.rpc.TSStatusCode; +import org.junit.jupiter.api.Test; +import org.springframework.jdbc.UncategorizedSQLException; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link IoTDBUtils} 的单元测试 + * + * @author 芋道源码 + */ +public class IoTDBUtilsTest { + + // ========== isTableNotExists ========== + + @Test + public void testIsTableNotExists_statusCode() { + assertEquals(TSStatusCode.TABLE_NOT_EXISTS.getStatusCode(), IoTDBUtils.STATUS_CODE_TABLE_NOT_EXISTS); + } + + @Test + public void testIsTableNotExists_true() { + // 驱动抛出的异常:errorCode 为 IoTDB 状态码 + IoTDBSQLException sqlException = new IoTDBSQLException("550: Table 'db.product_property_1' does not exist", + new TSStatus(TSStatusCode.TABLE_NOT_EXISTS.getStatusCode())); + assertTrue(IoTDBUtils.isTableNotExists(sqlException)); + // Spring、MyBatis 包装后的异常:沿 cause 链查找 + assertTrue(IoTDBUtils.isTableNotExists(new UncategorizedSQLException("select", "SELECT 1", sqlException))); + assertTrue(IoTDBUtils.isTableNotExists(new RuntimeException(new RuntimeException(sqlException)))); + // Session 风格的异常 + assertTrue(IoTDBUtils.isTableNotExists(new RuntimeException( + new StatementExecutionException(new TSStatus(TSStatusCode.TABLE_NOT_EXISTS.getStatusCode()))))); + } + + @Test + public void testIsTableNotExists_false() { + // 列不存在、类型不匹配:不是表不存在,需要原样抛出 + assertFalse(IoTDBUtils.isTableNotExists(new IoTDBSQLException("616", + new TSStatus(TSStatusCode.COLUMN_NOT_EXISTS.getStatusCode())))); + assertFalse(IoTDBUtils.isTableNotExists(new StatementExecutionException( + new TSStatus(TSStatusCode.DATA_TYPE_MISMATCH.getStatusCode())))); + // 只靠异常文案,不识别为表不存在 + assertFalse(IoTDBUtils.isTableNotExists(new RuntimeException("Table does not exist"))); + assertFalse(IoTDBUtils.isTableNotExists(null)); + } + + @Test + public void testIsTableNotExists_causeLoop() { + // 准备参数:cause 链成环 + RuntimeException a = new RuntimeException("a"); + RuntimeException b = new RuntimeException("b"); + a.initCause(b); + b.initCause(a); + + // 调用,并断言:不会死循环 + assertFalse(IoTDBUtils.isTableNotExists(a)); + } + + // ========== validateTimestampPrecision ========== + + @Test + public void testValidateTimestampPrecision_success() { + List> variables = Arrays.asList( + row("Variable", "ClusterName", "Value", "defaultCluster"), + row("variable", "TimestampPrecision", "value", "ms")); + assertDoesNotThrow(() -> IoTDBUtils.validateTimestampPrecision(variables)); + } + + @Test + public void testValidateTimestampPrecision_failure() { + // 精度不是 ms + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateTimestampPrecision( + Collections.singletonList(row("Variable", "TimestampPrecision", "Value", "ns")))); + // 无法读取 + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateTimestampPrecision( + Collections.singletonList(row("Variable", "ClusterName", "Value", "defaultCluster")))); + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateTimestampPrecision(Collections.emptyList())); + } + + // ========== validateDataNodes ========== + + @Test + public void testValidateDataNodes_success() { + List> dataNodes = Arrays.asList( + row("NodeID", 1, "Status", "Running"), + row("NodeID", 3, "Status", "running")); + assertEquals(Arrays.asList(1, 3), IoTDBUtils.validateDataNodes(dataNodes)); + } + + @Test + public void testValidateDataNodes_failure() { + // 没有 DataNode + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateDataNodes(Collections.emptyList())); + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateDataNodes(null)); + // 有 DataNode 不是 Running:无法确认它的配置 + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateDataNodes(Arrays.asList( + row("NodeID", 1, "Status", "Running"), + row("NodeID", 2, "Status", "Unknown")))); + // 编号无法识别 + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateDataNodes( + Collections.singletonList(row("NodeID", "abc", "Status", "Running")))); + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validateDataNodes( + Collections.singletonList(row("Status", "Running")))); + } + + // ========== validatePartialInsertDisabled ========== + + @Test + public void testValidatePartialInsertDisabled_success() { + List> configurations = Arrays.asList( + row("name", "dn_rpc_port", "value", "6667", "default_value", "6667"), + row("name", "enable_partial_insert", "value", "false", "default_value", "true")); + assertDoesNotThrow(() -> IoTDBUtils.validatePartialInsertDisabled(1, configurations)); + } + + @Test + public void testValidatePartialInsertDisabled_failure() { + // 开启了部分写入 + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validatePartialInsertDisabled(1, + Collections.singletonList(row("name", "enable_partial_insert", "value", "true")))); + // 无法读取配置 + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validatePartialInsertDisabled(1, + Collections.singletonList(row("name", "dn_rpc_port", "value", "6667")))); + assertThrows(IllegalStateException.class, () -> IoTDBUtils.validatePartialInsertDisabled(1, + Collections.singletonList(row("name", "enable_partial_insert")))); + } + + // ========== getIgnoreCase ========== + + @Test + public void testGetIgnoreCase() { + Map row = row("NodeID", 1); + assertEquals(1, IoTDBUtils.getIgnoreCase(row, "nodeid")); + assertNull(IoTDBUtils.getIgnoreCase(row, "Status")); + } + + private static Map row(Object... keyValues) { + Map row = new LinkedHashMap<>(); + for (int i = 0; i < keyValues.length; i += 2) { + row.put((String) keyValues[i], keyValues[i + 1]); + } + return MapUtil.unmodifiable(row); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/storage/core/util/IotStorageFieldUtilsTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/storage/core/util/IotStorageFieldUtilsTest.java new file mode 100644 index 0000000..e773e42 --- /dev/null +++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/storage/core/util/IotStorageFieldUtilsTest.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.iot.framework.storage.core.util; + +import cn.hutool.core.util.StrUtil; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link IotStorageFieldUtils} 的单元测试 + * + * @author 芋道源码 + */ +public class IotStorageFieldUtilsTest { + + @Test + public void testBuildFieldName_success() { + assertEquals("ua", IotStorageFieldUtils.buildFieldName("Ua")); + assertEquals("pf_t", IotStorageFieldUtils.buildFieldName("PfT")); + assertEquals("pt", IotStorageFieldUtils.buildFieldName("PT")); + assertEquals("pa", IotStorageFieldUtils.buildFieldName("PA")); + assertEquals("geo_location", IotStorageFieldUtils.buildFieldName("GeoLocation")); + assertEquals("light_status", IotStorageFieldUtils.buildFieldName("LightStatus")); + assertEquals("foo_bar", IotStorageFieldUtils.buildFieldName("foo_bar")); + } + + @Test + public void testBuildFieldName_blank() { + // 空白原样返回,由 isPropertyFieldName、validatePropertyIdentifiers 判定为不合法 + assertNull(IotStorageFieldUtils.buildFieldName(null)); + assertEquals("", IotStorageFieldUtils.buildFieldName("")); + assertEquals(" ", IotStorageFieldUtils.buildFieldName(" ")); + } + + @Test + public void testIsPropertyFieldName_true() { + assertTrue(IotStorageFieldUtils.isPropertyFieldName("Temperature")); + assertTrue(IotStorageFieldUtils.isPropertyFieldName("PfT")); + assertTrue(IotStorageFieldUtils.isPropertyFieldName("a1_b2")); + assertTrue(IotStorageFieldUtils.isPropertyFieldName(StrUtil.repeat('a', 64))); + } + + @Test + public void testIsPropertyFieldName_false() { + // 保留字段:归一化后与系统字段相同 + assertFalse(IotStorageFieldUtils.isPropertyFieldName("ts")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("TS")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("reportTime")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("report_time")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("deviceId")); + // 格式不合法:不能安全地拼接到 SQL 结构名 + assertFalse(IotStorageFieldUtils.isPropertyFieldName(null)); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName(" ")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("1abc")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("温度")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("a-b")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("a\"b")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName("a` OR 1=1")); + assertFalse(IotStorageFieldUtils.isPropertyFieldName(StrUtil.repeat('a', 65))); + } + + @Test + public void testValidatePropertyIdentifiers_success() { + // 调用,并断言 + assertDoesNotThrow(() -> IotStorageFieldUtils.validatePropertyIdentifiers( + Arrays.asList("Temperature", "PfT", "geo_location"))); + assertDoesNotThrow(() -> IotStorageFieldUtils.validatePropertyIdentifiers(Collections.emptyList())); + } + + @Test + public void testValidatePropertyIdentifiers_invalid() { + assertServiceException(() -> IotStorageFieldUtils.validatePropertyIdentifiers( + Arrays.asList("Temperature", "温度")), DEVICE_PROPERTY_FIELD_NAME_INVALID, "温度"); + assertServiceException(() -> IotStorageFieldUtils.validatePropertyIdentifiers( + Collections.singletonList(null)), DEVICE_PROPERTY_FIELD_NAME_INVALID, (Object) null); + } + + @Test + public void testValidatePropertyIdentifiers_reserved() { + assertServiceException(() -> IotStorageFieldUtils.validatePropertyIdentifiers( + Collections.singletonList("reportTime")), DEVICE_PROPERTY_FIELD_NAME_RESERVED, "reportTime", "report_time"); + assertServiceException(() -> IotStorageFieldUtils.validatePropertyIdentifiers( + Collections.singletonList("deviceId")), DEVICE_PROPERTY_FIELD_NAME_RESERVED, "deviceId", "device_id"); + } + + @Test + public void testValidatePropertyIdentifiers_duplicate() { + assertServiceException(() -> IotStorageFieldUtils.validatePropertyIdentifiers( + Arrays.asList("fooBar", "foo_bar")), DEVICE_PROPERTY_FIELD_NAME_DUPLICATE, "foo_bar", "fooBar", "foo_bar"); + } + +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/tdengine/core/TDengineTableFieldTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/tdengine/core/TDengineTableFieldTest.java deleted file mode 100644 index df2cb42..0000000 --- a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/framework/tdengine/core/TDengineTableFieldTest.java +++ /dev/null @@ -1,27 +0,0 @@ -package cn.iocoder.yudao.module.iot.framework.tdengine.core; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNull; - -public class TDengineTableFieldTest { - - @Test - public void testBuildFieldName() { - assertEquals("ua", TDengineTableField.buildFieldName("Ua")); - assertEquals("pf_t", TDengineTableField.buildFieldName("PfT")); - assertEquals("pt", TDengineTableField.buildFieldName("PT")); - assertEquals("pa", TDengineTableField.buildFieldName("PA")); - assertEquals("geo_location", TDengineTableField.buildFieldName("GeoLocation")); - assertEquals("light_status", TDengineTableField.buildFieldName("LightStatus")); - } - - @Test - public void testBuildFieldName_blank() { - assertNull(TDengineTableField.buildFieldName(null)); - assertEquals("", TDengineTableField.buildFieldName("")); - assertEquals(" ", TDengineTableField.buildFieldName(" ")); - } - -} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImplTest.java index e880621..8bb9b64 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImplTest.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/message/IotDeviceMessageServiceImplTest.java @@ -2,39 +2,43 @@ package cn.iocoder.yudao.module.iot.service.device.message; import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.exception.ServiceException; +import cn.iocoder.yudao.framework.common.enums.DateIntervalEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import cn.iocoder.yudao.module.iot.controller.admin.device.vo.message.IotDeviceMessagePageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.statistics.vo.IotStatisticsDeviceMessageSummaryByDateRespVO; import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.core.mq.producer.IotDeviceMessageProducer; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceMessageDO; -import cn.iocoder.yudao.module.iot.dal.tdengine.IotDeviceMessageMapper; +import cn.iocoder.yudao.module.iot.dal.storage.IotDeviceMessageDAO; import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.device.property.IotDevicePropertyService; import cn.iocoder.yudao.module.iot.service.ota.IotOtaTaskRecordService; -import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; import org.mockito.InjectMocks; import org.mockito.Mock; +import java.sql.Timestamp; import java.time.LocalDateTime; +import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.any; -import static org.mockito.ArgumentMatchers.eq; import static org.mockito.ArgumentMatchers.isNull; +import static org.mockito.ArgumentMatchers.same; import static org.mockito.Mockito.*; /** * {@link IotDeviceMessageServiceImpl} 的单元测试 * - * 注:TDengine 数据源没有 embedded 替代,mapper 与依赖 service 走 mock; + * 注:时序库没有 embedded 替代,存储 DAO 与依赖 service 走 mock; * handleUpstreamDeviceMessage 与 sendDeviceMessage 下行成功路径依赖 SpringUtil.getBean 的自调用 * createDeviceLogAsync,更适合放到集成测试,本类不展开。 * @@ -52,36 +56,10 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { @Mock private IotOtaTaskRecordService otaTaskRecordService; @Mock - private IotDeviceMessageMapper deviceMessageMapper; + private IotDeviceMessageDAO deviceMessageDAO; @Mock private IotDeviceMessageProducer deviceMessageProducer; - // ========== defineDeviceMessageStable ========== - - @Test - public void testDefineDeviceMessageStable_whenTableExists_skipCreate() { - // 准备:showSTable 返回非空 → 表已存在 - when(deviceMessageMapper.showSTable()).thenReturn("device_message"); - - // 调用 - service.defineDeviceMessageStable(); - - // 断言:跳过 createSTable - verify(deviceMessageMapper, never()).createSTable(); - } - - @Test - public void testDefineDeviceMessageStable_whenTableMissing_create() { - // 准备:showSTable 返回空 → 表不存在 - when(deviceMessageMapper.showSTable()).thenReturn(""); - - // 调用 - service.defineDeviceMessageStable(); - - // 断言:触发 createSTable - verify(deviceMessageMapper, times(1)).createSTable(); - } - // ========== createDeviceLogAsync ========== @Test @@ -96,7 +74,7 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { // 断言:mapper.insert 接收到的 messageDO 已被填上 ts,值在 [before, after] 区间 ArgumentCaptor captor = ArgumentCaptor.forClass(IotDeviceMessageDO.class); - verify(deviceMessageMapper).insert(captor.capture()); + verify(deviceMessageDAO).insert(captor.capture()); Long actualTs = captor.getValue().getTs(); assertNotNull(actualTs, "ts 不应为空"); assertTrue(actualTs >= before && actualTs <= after, @@ -114,7 +92,7 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { // 断言:mapper.insert 接收到的 messageDO 已补充 id ArgumentCaptor captor = ArgumentCaptor.forClass(IotDeviceMessageDO.class); - verify(deviceMessageMapper).insert(captor.capture()); + verify(deviceMessageDAO).insert(captor.capture()); assertNotNull(captor.getValue().getId(), "id 不应为空"); } @@ -122,11 +100,11 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { public void testCreateDeviceLogAsync_swallowMapperException() { // 准备:mapper.insert 抛异常,验证 @Async 方法内部 try/catch 兜底,不向上抛 IotDeviceMessage message = buildMessage(IotDeviceMessageMethodEnum.PROPERTY_POST.getMethod()); - doThrow(new RuntimeException("DB unavailable")).when(deviceMessageMapper).insert(any()); + doThrow(new RuntimeException("DB unavailable")).when(deviceMessageDAO).insert(any()); // 调用 & 断言 assertDoesNotThrow(() -> service.createDeviceLogAsync(message)); - verify(deviceMessageMapper).insert(any(IotDeviceMessageDO.class)); + verify(deviceMessageDAO).insert(any(IotDeviceMessageDO.class)); } // ========== sendDeviceMessage ========== @@ -170,49 +148,18 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { reqVO.setPageNo(1); reqVO.setPageSize(10); IotDeviceMessageDO record = new IotDeviceMessageDO().setId("msg-1"); - Page page = new Page<>(1, 10, 1L); - page.setRecords(Collections.singletonList(record)); - when(deviceMessageMapper.selectPage(any(), eq(reqVO))).thenReturn(page); + when(deviceMessageDAO.selectPage(same(reqVO))) + .thenReturn(new PageResult<>(Collections.singletonList(record), 1L)); // 调用 PageResult result = service.getDeviceMessagePage(reqVO); - // 断言 + // 断言:表不存在等存储差异,由 DAO 处理(见各 DAO 的单元测试) assertEquals(1L, result.getTotal()); assertEquals(1, result.getList().size()); assertEquals("msg-1", result.getList().get(0).getId()); } - @Test - public void testGetDeviceMessagePage_whenTableMissing_returnEmpty() { - // 准备:mapper 抛 "Table does not exist" → 视为表未创建,返回空结果 - IotDeviceMessagePageReqVO reqVO = new IotDeviceMessagePageReqVO(); - reqVO.setPageNo(1); - reqVO.setPageSize(10); - when(deviceMessageMapper.selectPage(any(), any())) - .thenThrow(new RuntimeException("Table does not exist")); - - // 调用 - PageResult result = service.getDeviceMessagePage(reqVO); - - // 断言 - assertEquals(0L, result.getTotal()); - assertTrue(result.getList().isEmpty()); - } - - @Test - public void testGetDeviceMessagePage_otherException_rethrow() { - // 准备:mapper 抛非「表不存在」的异常 → 应向上抛 - IotDeviceMessagePageReqVO reqVO = new IotDeviceMessagePageReqVO(); - reqVO.setPageNo(1); - reqVO.setPageSize(10); - when(deviceMessageMapper.selectPage(any(), any())) - .thenThrow(new RuntimeException("Connection refused")); - - // 调用 & 断言 - assertThrows(RuntimeException.class, () -> service.getDeviceMessagePage(reqVO)); - } - // ========== getDeviceMessageListByRequestIdsAndReply ========== @Test @@ -222,7 +169,7 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { 1L, Collections.emptyList(), true); assertTrue(result.isEmpty()); - verify(deviceMessageMapper, never()).selectListByRequestIdsAndReply(any(), any(), any()); + verify(deviceMessageDAO, never()).selectListByRequestIdsAndReply(any(), any(), any()); } @Test @@ -230,7 +177,7 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { // 准备 List requestIds = Collections.singletonList("req-1"); IotDeviceMessageDO record = new IotDeviceMessageDO().setId("msg-1"); - when(deviceMessageMapper.selectListByRequestIdsAndReply(1L, requestIds, true)) + when(deviceMessageDAO.selectListByRequestIdsAndReply(1L, requestIds, true)) .thenReturn(Collections.singletonList(record)); // 调用 @@ -247,14 +194,14 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { @Test public void testGetDeviceMessageCount_whenCreateTimeNull_passNullToMapper() { // 准备 - when(deviceMessageMapper.selectCountByCreateTime(isNull())).thenReturn(123L); + when(deviceMessageDAO.selectCountByCreateTime(isNull())).thenReturn(123L); // 调用 Long count = service.getDeviceMessageCount(null); // 断言 assertEquals(123L, count); - verify(deviceMessageMapper).selectCountByCreateTime(isNull()); + verify(deviceMessageDAO).selectCountByCreateTime(isNull()); } @Test @@ -262,7 +209,7 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { // 准备:service 内部用 LocalDateTimeUtil.toEpochMilli 做转换,断言时也用同函数得到期望值 LocalDateTime createTime = LocalDateTime.of(2026, 1, 1, 0, 0); long expectedMs = LocalDateTimeUtil.toEpochMilli(createTime); - when(deviceMessageMapper.selectCountByCreateTime(expectedMs)).thenReturn(456L); + when(deviceMessageDAO.selectCountByCreateTime(expectedMs)).thenReturn(456L); // 调用 Long count = service.getDeviceMessageCount(createTime); @@ -271,6 +218,33 @@ public class IotDeviceMessageServiceImplTest extends BaseMockitoUnitTest { assertEquals(456L, count); } + // ========== getDeviceMessageSummaryByDate ========== + + @Test + public void testGetDeviceMessageSummaryByDate_success() { + // 准备参数:按天合并 2026-01-01 的小时统计 + IotStatisticsDeviceMessageReqVO reqVO = new IotStatisticsDeviceMessageReqVO(); + reqVO.setInterval(DateIntervalEnum.DAY.getInterval()); + LocalDateTime startTime = LocalDateTime.of(2026, 1, 1, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2026, 1, 1, 23, 59, 59); + reqVO.setTimes(new LocalDateTime[]{startTime, endTime}); + + // mock 方法:DAO 统一返回 Timestamp 时间、Long 数量 + when(deviceMessageDAO.selectDeviceMessageCountGroupByDate( + LocalDateTimeUtil.toEpochMilli(startTime), LocalDateTimeUtil.toEpochMilli(endTime))) + .thenReturn(Arrays.asList( + IotDeviceMessageDAO.buildMessageCount(Timestamp.valueOf(startTime.withHour(1)), 3L, 1L), + IotDeviceMessageDAO.buildMessageCount(Timestamp.valueOf(startTime.withHour(2)), 2L, 0L))); + + // 调用 + List list = service.getDeviceMessageSummaryByDate(reqVO); + + // 断言 + assertEquals(1, list.size()); + assertEquals(5, list.get(0).getUpstreamCount()); + assertEquals(1, list.get(0).getDownstreamCount()); + } + // ========== 辅助方法 ========== /** 构造一条最简消息(指定 method 决定上下行分支) */ diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java index 67be85e..e5f97c3 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/device/property/IotDevicePropertyServiceImplTest.java @@ -1,6 +1,10 @@ package cn.iocoder.yudao.module.iot.service.device.property; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyHistoryListReqVO; +import cn.iocoder.yudao.module.iot.controller.admin.device.vo.property.IotDevicePropertyRespVO; import cn.iocoder.yudao.module.iot.core.enums.IotDeviceMessageMethodEnum; import cn.iocoder.yudao.module.iot.core.mq.message.IotDeviceMessage; import cn.iocoder.yudao.module.iot.dal.dataobject.device.IotDeviceDO; @@ -9,10 +13,10 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.model.ThingModelProperty; import cn.iocoder.yudao.module.iot.dal.redis.device.DevicePropertyRedisDAO; -import cn.iocoder.yudao.module.iot.dal.tdengine.IotDevicePropertyMapper; +import cn.iocoder.yudao.module.iot.dal.storage.IotDevicePropertyDAO; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotDataSpecsDataTypeEnum; import cn.iocoder.yudao.module.iot.enums.thingmodel.IotThingModelTypeEnum; -import cn.iocoder.yudao.module.iot.framework.tdengine.core.TDengineTableField; +import cn.iocoder.yudao.module.iot.service.device.IotDeviceService; import cn.iocoder.yudao.module.iot.service.product.IotProductService; import cn.iocoder.yudao.module.iot.service.thingmodel.IotThingModelService; import org.junit.jupiter.api.Test; @@ -22,12 +26,14 @@ import org.mockito.Mock; import java.time.LocalDateTime; import java.util.Arrays; -import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.DEVICE_PROPERTY_HISTORY_TIMES_INVALID; +import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS; import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.ArgumentMatchers.*; @@ -48,7 +54,9 @@ public class IotDevicePropertyServiceImplTest extends BaseMockitoUnitTest { @Mock private IotProductService productService; @Mock - private IotDevicePropertyMapper devicePropertyMapper; + private IotDeviceService deviceService; + @Mock + private IotDevicePropertyDAO devicePropertyDAO; @Mock private DevicePropertyRedisDAO deviceDataRedisDAO; @@ -97,7 +105,7 @@ public class IotDevicePropertyServiceImplTest extends BaseMockitoUnitTest { service.saveDeviceProperty(device, message); // 断言:没有合法属性,不会写入 TDengine 与 Redis - verify(devicePropertyMapper, never()).insert(any(), any(), anyLong(), anyLong()); + verify(devicePropertyDAO, never()).insert(any(), any(), anyLong(), anyLong()); verify(deviceDataRedisDAO, never()).putAll(anyLong(), any()); } @@ -119,7 +127,7 @@ public class IotDevicePropertyServiceImplTest extends BaseMockitoUnitTest { assertDoesNotThrow(() -> service.saveDeviceProperty(device, message)); // 断言:没有合法属性,不会写入 TDengine 与 Redis - verify(devicePropertyMapper, never()).insert(any(), any(), anyLong(), anyLong()); + verify(devicePropertyDAO, never()).insert(any(), any(), anyLong(), anyLong()); verify(deviceDataRedisDAO, never()).putAll(anyLong(), any()); } @@ -141,7 +149,7 @@ public class IotDevicePropertyServiceImplTest extends BaseMockitoUnitTest { // 断言:跳过空值,不会转换属性值,也不会写入 TDengine 与 Redis verify(thingModelService, never()).convertThingModelPropertyValue(any(), any()); - verify(devicePropertyMapper, never()).insert(any(), any(), anyLong(), anyLong()); + verify(devicePropertyDAO, never()).insert(any(), any(), anyLong(), anyLong()); verify(deviceDataRedisDAO, never()).putAll(anyLong(), any()); } @@ -170,31 +178,149 @@ public class IotDevicePropertyServiceImplTest extends BaseMockitoUnitTest { } @Test - public void testDefineDevicePropertyData_fieldNameToLowerCase() { - // 准备参数:全大写缩写和驼峰缩写都需要转换为 TDengine 实际的小写字段名 + public void testDefineDevicePropertyData_success() { + // 准备参数:只有属性类型的物模型,才需要定义存储结构 Long productId = 2L; IotProductDO product = IotProductDO.builder().id(productId).build(); - List thingModels = Arrays.asList( - buildThingModel("Ua", IotDataSpecsDataTypeEnum.FLOAT.getDataType()), - buildThingModel("PfT", IotDataSpecsDataTypeEnum.FLOAT.getDataType()), - buildThingModel("PT", IotDataSpecsDataTypeEnum.FLOAT.getDataType()), - buildThingModel("PA", IotDataSpecsDataTypeEnum.FLOAT.getDataType())); - thingModels.forEach(thingModel -> thingModel.setType(IotThingModelTypeEnum.PROPERTY.getType())); + IotThingModelDO temperature = buildThingModel("Temperature", IotDataSpecsDataTypeEnum.FLOAT.getDataType()); + temperature.setType(IotThingModelTypeEnum.PROPERTY.getType()); + IotThingModelDO alarm = buildThingModel("Alarm", IotDataSpecsDataTypeEnum.INT.getDataType()); + alarm.setType(IotThingModelTypeEnum.EVENT.getType()); // mock 方法 when(productService.validateProductExists(productId)).thenReturn(product); - when(thingModelService.getThingModelListByProductId(productId)).thenReturn(thingModels); - when(devicePropertyMapper.getProductPropertySTableFieldList(productId)).thenReturn(Collections.emptyList()); + when(thingModelService.getThingModelListByProductId(productId)).thenReturn(Arrays.asList(temperature, alarm)); // 调用 service.defineDevicePropertyData(productId); - // 断言:字段名统一为小写下划线,避免 PT 和数据库中的 pt 被误判为不同字段 - ArgumentCaptor> captor = ArgumentCaptor.forClass(List.class); - verify(devicePropertyMapper).createProductPropertySTable(eq(productId), captor.capture()); - assertEquals(Arrays.asList("ua", "pf_t", "pt", "pa"), captor.getValue().stream() - .map(TDengineTableField::getField) - .collect(Collectors.toList())); + // 断言:只传入属性物模型,由存储 DAO 完成字段映射与差异比较 + verify(devicePropertyDAO).defineProductPropertyTable(eq(productId), eq(singletonList(temperature))); + } + + @Test + public void testDefineDevicePropertyData_productNotExists() { + // 准备参数 + Long productId = 2L; + + // mock 方法:产品不存在 + when(productService.validateProductExists(productId)) + .thenThrow(exception(PRODUCT_NOT_EXISTS)); + + // 调用,并断言 + assertServiceException(() -> service.defineDevicePropertyData(productId), PRODUCT_NOT_EXISTS); + verify(devicePropertyDAO, never()).defineProductPropertyTable(any(), any()); + } + + @Test + public void testSaveDeviceProperty_success() { + // 准备参数 + IotDeviceDO device = buildDevice(); + IotThingModelDO thingModel = buildThingModel("Temperature", IotDataSpecsDataTypeEnum.INT.getDataType()); + Map params = new HashMap<>(); + params.put("Temperature", 36); + IotDeviceMessage message = buildMessage(params); + + // mock 方法 + when(thingModelService.getThingModelListByProductIdFromCache(device.getProductId())) + .thenReturn(singletonList(thingModel)); + when(thingModelService.convertThingModelPropertyValue(thingModel, 36)).thenReturn(36); + + // 调用 + long before = System.currentTimeMillis(); + service.saveDeviceProperty(device, message); + long after = System.currentTimeMillis(); + + // 断言:ts 为存储时间,reportTime 为上报时间 + ArgumentCaptor tsCaptor = ArgumentCaptor.forClass(Long.class); + verify(devicePropertyDAO).insert(eq(device), eq(MapUtil.of("Temperature", 36)), tsCaptor.capture(), + eq(LocalDateTimeUtil.toEpochMilli(message.getReportTime()))); + assertTrue(tsCaptor.getValue() >= before && tsCaptor.getValue() <= after); + } + + // ========== getHistoryDevicePropertyList ========== + + @Test + public void testGetHistoryDevicePropertyList_success() { + // 准备参数 + IotDevicePropertyHistoryListReqVO reqVO = buildHistoryReqVO("Temperature", + LocalDateTime.of(2026, 1, 1, 0, 0), LocalDateTime.of(2026, 1, 2, 0, 0)); + IotDevicePropertyRespVO respVO = new IotDevicePropertyRespVO(); + respVO.setValue(36); + respVO.setUpdateTime(1L); + + // mock 方法 + when(deviceService.getDevice(eq(1L))).thenReturn(buildDevice()); + when(devicePropertyDAO.selectHistoryList(eq(2L), same(reqVO))).thenReturn(singletonList(respVO)); + + // 调用 + List list = service.getHistoryDevicePropertyList(reqVO); + + // 断言:按设备的产品编号查询时序库;使用按租户、逻辑删除过滤的 getDevice,而不是忽略租户的缓存查询 + assertEquals(singletonList(respVO), list); + verify(deviceService, never()).getDeviceFromCache(anyLong()); + } + + @Test + public void testGetHistoryDevicePropertyList_timesNull() { + // 准备参数 + IotDevicePropertyHistoryListReqVO reqVO = buildHistoryReqVO("Temperature"); + reqVO.setTimes(null); + + // 调用,并断言 + assertServiceException(() -> service.getHistoryDevicePropertyList(reqVO), DEVICE_PROPERTY_HISTORY_TIMES_INVALID); + verifyNoInteractions(deviceService, devicePropertyDAO); + } + + @Test + public void testGetHistoryDevicePropertyList_timesLengthInvalid() { + // 准备参数 + IotDevicePropertyHistoryListReqVO reqVO = buildHistoryReqVO("Temperature", LocalDateTime.now()); + + // 调用,并断言 + assertServiceException(() -> service.getHistoryDevicePropertyList(reqVO), DEVICE_PROPERTY_HISTORY_TIMES_INVALID); + verifyNoInteractions(deviceService, devicePropertyDAO); + } + + @Test + public void testGetHistoryDevicePropertyList_timeNull() { + // 准备参数:开始时间为空、结束时间为空 + IotDevicePropertyHistoryListReqVO reqVO1 = buildHistoryReqVO("Temperature", null, LocalDateTime.now()); + IotDevicePropertyHistoryListReqVO reqVO2 = buildHistoryReqVO("Temperature", LocalDateTime.now(), null); + + // 调用,并断言:返回空,不查询设备与时序库 + assertTrue(service.getHistoryDevicePropertyList(reqVO1).isEmpty()); + assertTrue(service.getHistoryDevicePropertyList(reqVO2).isEmpty()); + verifyNoInteractions(deviceService, devicePropertyDAO); + } + + @Test + public void testGetHistoryDevicePropertyList_identifierInvalid() { + // 准备参数:保留字段、非法格式 + LocalDateTime now = LocalDateTime.now(); + IotDevicePropertyHistoryListReqVO reqVO1 = buildHistoryReqVO("reportTime", now, now); + IotDevicePropertyHistoryListReqVO reqVO2 = buildHistoryReqVO("ts", now, now); + IotDevicePropertyHistoryListReqVO reqVO3 = buildHistoryReqVO("a` OR 1=1", now, now); + + // 调用,并断言:返回空,不查询设备与时序库 + assertTrue(service.getHistoryDevicePropertyList(reqVO1).isEmpty()); + assertTrue(service.getHistoryDevicePropertyList(reqVO2).isEmpty()); + assertTrue(service.getHistoryDevicePropertyList(reqVO3).isEmpty()); + verifyNoInteractions(deviceService, devicePropertyDAO); + } + + @Test + public void testGetHistoryDevicePropertyList_deviceNotExists() { + // 准备参数 + LocalDateTime now = LocalDateTime.now(); + IotDevicePropertyHistoryListReqVO reqVO = buildHistoryReqVO("Temperature", now, now); + + // mock 方法:设备不存在、已删除,或者不属于当前租户 + when(deviceService.getDevice(eq(1L))).thenReturn(null); + + // 调用,并断言:返回空,不查询时序库 + assertTrue(service.getHistoryDevicePropertyList(reqVO).isEmpty()); + verifyNoInteractions(devicePropertyDAO); } // ========== 辅助方法 ========== @@ -228,12 +354,23 @@ public class IotDevicePropertyServiceImplTest extends BaseMockitoUnitTest { } /** - * 抓取 mapper.insert 的 properties 入参 + * 构造属性历史查询条件,设备编号固定为 1 + */ + private IotDevicePropertyHistoryListReqVO buildHistoryReqVO(String identifier, LocalDateTime... times) { + IotDevicePropertyHistoryListReqVO reqVO = new IotDevicePropertyHistoryListReqVO(); + reqVO.setDeviceId(1L); + reqVO.setIdentifier(identifier); + reqVO.setTimes(times); + return reqVO; + } + + /** + * 抓取 DAO.insert 的 properties 入参 */ @SuppressWarnings("unchecked") private Map captureMapperInsertProperties() { ArgumentCaptor> captor = ArgumentCaptor.forClass(Map.class); - verify(devicePropertyMapper).insert(any(IotDeviceDO.class), captor.capture(), anyLong(), anyLong()); + verify(devicePropertyDAO).insert(any(IotDeviceDO.class), captor.capture(), anyLong(), anyLong()); return captor.getValue(); } diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImplTest.java index 2668c43..46f1a27 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImplTest.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thingmodel/IotThingModelServiceImplTest.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.iot.service.thingmodel; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.iot.dal.dataobject.thingmodel.IotThingModelDO; @@ -15,11 +16,14 @@ import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; import org.springframework.test.context.bean.override.mockito.MockitoBean; +import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; import java.util.Arrays; import java.util.HashMap; +import java.util.List; import java.util.Map; +import static java.util.Collections.singletonList; import static org.junit.jupiter.api.Assertions.*; /** @@ -162,6 +166,51 @@ public class IotThingModelServiceImplTest extends BaseDbUnitTest { assertEquals(JsonUtils.toJsonString(value), result); } + @Test + public void testConvertThingModelPropertyValue_jsonMaxLength() { + // 准备参数:JSON 恰好 LENGTH_JSON 字节,包含中文、emoji 等多字节字符 + Map structValue = buildJsonValue(ThingModelProperty.LENGTH_JSON); + List arrayValue = singletonList(buildJsonValue(ThingModelProperty.LENGTH_JSON - 2)); + String structJson = JsonUtils.toJsonString(structValue); + String arrayJson = JsonUtils.toJsonString(arrayValue); + assertEquals(ThingModelProperty.LENGTH_JSON, structJson.getBytes(StandardCharsets.UTF_8).length); + assertEquals(ThingModelProperty.LENGTH_JSON, arrayJson.getBytes(StandardCharsets.UTF_8).length); + assertTrue(structJson.length() < ThingModelProperty.LENGTH_JSON); // 按字节而不是字符计算 + + // 调用,并断言:STRUCT、ARRAY 都可以写入 + assertEquals(structJson, thingModelService.convertThingModelPropertyValue( + buildThingModel("Location", IotDataSpecsDataTypeEnum.STRUCT.getDataType()), structValue)); + assertEquals(arrayJson, thingModelService.convertThingModelPropertyValue( + buildThingModel("Points", IotDataSpecsDataTypeEnum.ARRAY.getDataType()), arrayValue)); + } + + @Test + public void testConvertThingModelPropertyValue_jsonOverLength() { + // 准备参数:JSON 超过 LENGTH_JSON 1 个字节,包含中文、emoji 等多字节字符 + Map structValue = buildJsonValue(ThingModelProperty.LENGTH_JSON + 1); + List arrayValue = singletonList(buildJsonValue(ThingModelProperty.LENGTH_JSON - 1)); + assertEquals(ThingModelProperty.LENGTH_JSON + 1, JsonUtils.toJsonString(structValue).getBytes(StandardCharsets.UTF_8).length); + assertEquals(ThingModelProperty.LENGTH_JSON + 1, JsonUtils.toJsonString(arrayValue).getBytes(StandardCharsets.UTF_8).length); + + // 调用,并断言:STRUCT、ARRAY 都返回 null,不写入 + assertNull(thingModelService.convertThingModelPropertyValue( + buildThingModel("Location", IotDataSpecsDataTypeEnum.STRUCT.getDataType()), structValue)); + assertNull(thingModelService.convertThingModelPropertyValue( + buildThingModel("Points", IotDataSpecsDataTypeEnum.ARRAY.getDataType()), arrayValue)); + } + + /** + * 构建 JSON 序列化后恰好 jsonBytes 字节(UTF-8)的结构体,包含中文、emoji 等多字节字符 + */ + private static Map buildJsonValue(int jsonBytes) { + String prefix = "中文😀"; + Map value = new HashMap<>(); + value.put("name", prefix); + int padding = jsonBytes - JsonUtils.toJsonString(value).getBytes(StandardCharsets.UTF_8).length; + value.put("name", prefix + StrUtil.repeat('x', padding)); + return value; + } + private void assertBoolValueConvertedToByte(Object reportedValue, byte expected) { IotThingModelDO thingModel = buildThingModel("PowerSwitch", IotDataSpecsDataTypeEnum.BOOL.getDataType()); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql b/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql index 8cf6c9d..b1cc3bd 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql +++ b/yudao-module-iot/yudao-module-iot-biz/src/test/resources/sql/create_tables.sql @@ -43,20 +43,23 @@ CREATE TABLE IF NOT EXISTS "iot_product" ( CREATE TABLE IF NOT EXISTS "iot_device" ( "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, "device_name" varchar(255) NOT NULL DEFAULT '', - "product_id" bigint NOT NULL, - "device_key" varchar(100) NOT NULL DEFAULT '', - "device_secret" varchar(100) NOT NULL DEFAULT '', "nickname" varchar(255) DEFAULT NULL, - "status" tinyint NOT NULL DEFAULT '0', - "status_last_update_time" timestamp DEFAULT NULL, - "last_online_time" timestamp DEFAULT NULL, - "last_offline_time" timestamp DEFAULT NULL, - "active_time" timestamp DEFAULT NULL, - "ip" varchar(50) DEFAULT NULL, - "firmware_version" varchar(50) DEFAULT NULL, - "device_type" tinyint NOT NULL DEFAULT '0', + "serial_number" varchar(255) DEFAULT NULL, + "pic_url" varchar(255) DEFAULT NULL, + "group_ids" varchar(255) DEFAULT NULL, + "product_id" bigint NOT NULL, + "product_key" varchar(100) DEFAULT NULL, + "device_type" tinyint DEFAULT NULL, "gateway_id" bigint DEFAULT NULL, - "sub_device_count" int NOT NULL DEFAULT '0', + "state" tinyint DEFAULT NULL, + "online_time" timestamp DEFAULT NULL, + "offline_time" timestamp DEFAULT NULL, + "active_time" timestamp DEFAULT NULL, + "firmware_id" bigint DEFAULT NULL, + "device_secret" varchar(100) DEFAULT NULL, + "latitude" decimal(10, 6) DEFAULT NULL, + "longitude" decimal(10, 6) DEFAULT NULL, + "config" varchar(4096) DEFAULT NULL, "creator" varchar(64) DEFAULT '', "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, "updater" varchar(64) DEFAULT '', diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java index 56ebc28..9e11336 100644 --- a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.product.controller.admin.history.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; @Schema(description = "管理后台 - 商品浏览记录 Response VO") @Data diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java index d962fe7..801f1e2 100755 --- a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.product.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java index 14f1ee4..13d0309 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity; import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.product.PointProductRespVO; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java index 638ea61..2de36d5 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.promotion.controller.admin.point.vo.product; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; @Schema(description = "管理后台 - 积分商城商品 Response VO") @Data diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java index 83e00c2..56458af 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.promotion.controller.app.point.vo; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; @Schema(description = "用户 App - 积分商城活动 Response VO") @Data diff --git a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java index 86126ca..55f5944 100644 --- a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java +++ b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.statistics.controller.admin.product.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDate; diff --git a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java index 9e27c6f..4baf48d 100644 --- a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java +++ b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; -import cn.idev.excel.annotation.ExcelProperty; -import cn.idev.excel.annotation.format.DateTimeFormat; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.format.DateTimeFormat; import java.time.LocalDate; diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java index 3cc312a..7585f10 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java index d680868..f6c1298 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/plan/vo/MesCalPlanRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java index 27d4117..1c6d6f5 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/cal/team/vo/MesCalTeamRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java index ff9c79d..88e6c13 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkplan/vo/MesDvCheckPlanRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.checkplan.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java index 2985316..cd70ddc 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/MesDvCheckRecordRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java index 27a90ab..98711e3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/checkrecord/vo/line/MesDvCheckRecordLineRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.checkrecord.vo.line; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java index 82b2364..1530376 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryImportExcelVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; @@ -8,6 +7,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * 设备台账 Excel 导入 VO diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java index 5d46e43..25694f0 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/MesDvMachineryRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java index 80859d8..f47e5ee 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/machinery/vo/type/MesDvMachineryTypeRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.machinery.vo.type; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java index a2448ef..3d7d2ac 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/MesDvMaintenRecordRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java index adea3c9..9c225f1 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/maintenrecord/vo/line/MesDvMaintenRecordLineRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.maintenrecord.vo.line; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java index 2a621ca..3e42fb9 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/MesDvRepairRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java index 3adcda5..5d6757e 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/repair/vo/line/MesDvRepairLineRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.repair.vo.line; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java index 03b04ed..67154a4 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/dv/subject/vo/MesDvSubjectRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.dv.subject.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java index a184bc2..593a314 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/part/MesMdAutoCodePartRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.part; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java index 5c69f74..198fdbf 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/autocode/vo/rule/MesMdAutoCodeRuleRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.autocode.vo.rule; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java index ee99e1c..9fbc811 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientImportExcelVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; @@ -8,6 +7,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * 客户 Excel 导入 VO diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java index 9ed58bb..3628411 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/client/vo/MesMdClientRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.client.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportExcelVO.java index dee51f7..acfd71c 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportExcelVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemImportExcelVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; @@ -8,6 +7,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java index 9ce6d95..60fe1a7 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/MesMdItemRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java index 447cbe7..0328ff5 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/item/vo/type/MesMdItemTypeRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.item.vo.type; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureRespVO.java index 033ddb4..9eb7d89 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/unitmeasure/vo/MesMdUnitMeasureRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.unitmeasure.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java index 237e603..0bc0069 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorImportExcelVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; @@ -8,6 +7,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * 供应商 Excel 导入 VO diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java index 00450cc..734017d 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/vendor/vo/MesMdVendorRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.vendor.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationRespVO.java index ef65dea..0b587a3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/MesMdWorkstationRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopRespVO.java index a04043c..4d5fc27 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/md/workstation/vo/workshop/MesMdWorkshopRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.md.workstation.vo.workshop; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordRespVO.java index ef5afa7..c81c3d8 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/andon/vo/record/MesProAndonRecordRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.pro.andon.vo.record; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java index 4e3fca9..2721aae 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/card/vo/MesProCardRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.pro.card.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java index b86dc24..d5cf755 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/feedback/vo/MesProFeedbackRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.pro.feedback.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteRespVO.java index 749d4a2..57c0205 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/route/vo/MesProRouteRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java index 70e1530..e50b459 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/MesProWorkOrderRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java index 140e49e..ee9218a 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workorder/vo/bom/MesProWorkOrderBomRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.bom; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java index 3177790..037f235 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/pro/workrecord/vo/MesProWorkRecordLogRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.mes.controller.admin.pro.workrecord.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java index 850a9fe..b081971 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/defect/vo/MesQcDefectRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.defect.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java index f3f5995..1255a41 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/indicator/vo/MesQcIndicatorRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.indicator.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java index 469076d..9ee4ae3 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/ipqc/vo/MesQcIpqcRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.ipqc.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java index 0c19e1c..4613eab 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/iqc/vo/MesQcIqcRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.iqc.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java index 79d9bed..719cf9a 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/oqc/vo/MesQcOqcRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.oqc.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java index d6cf184..ce06766 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/rqc/vo/MesQcRqcRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.rqc.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateRespVO.java index ea5932c..ac62efa 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/MesQcTemplateRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java index e32be87..0ab4429 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/indicator/MesQcTemplateIndicatorRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.indicator; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemRespVO.java index 91d4b2f..f20561f 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/qc/template/vo/item/MesQcTemplateItemRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.qc.template.vo.item; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java index dbe4b44..26b06b1 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/MesTmToolRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeRespVO.java index e46c400..1708875 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/tm/tool/vo/type/MesTmToolTypeRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.tm.tool.vo.type; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeRespVO.java index 10d1eab..1b732c2 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/arrivalnotice/vo/MesWmArrivalNoticeRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeRespVO.java index 5123e45..c12909d 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/MesWmBarcodeRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigRespVO.java index b6b97e5..0871d04 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/barcode/vo/config/MesWmBarcodeConfigRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.barcode.vo.config; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptRespVO.java index da430a7..bba7c19 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/itemreceipt/vo/MesWmItemReceiptRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.itemreceipt.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java index 03349b3..d36337e 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/materialstock/vo/MesWmMaterialStockRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.materialstock.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueRespVO.java index ad6a39e..b776429 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourceissue/vo/MesWmOutsourceIssueRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourceissue.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptRespVO.java index 749fc53..bdeafa4 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/outsourcereceipt/vo/MesWmOutsourceReceiptRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.outsourcereceipt.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageRespVO.java index a5aed09..6f54d91 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/packages/vo/MesWmPackageRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.packages.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptRespVO.java index 617bde9..ec35f21 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productreceipt/vo/MesWmProductReceiptRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.productreceipt.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesRespVO.java index 4d67b5e..55bc451 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/productsales/vo/MesWmProductSalesRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.productsales.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java index 473de99..3000e4f 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/salesnotice/vo/MesWmSalesNoticeRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.salesnotice.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java index 05e2b5e..d40b7be 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnGroupRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java index d831b2d..c32e81f 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/sn/vo/MesWmSnRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.sn.vo; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanRespVO.java index 1c68417..c31d743 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/plan/vo/MesWmStockTakingPlanRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.plan.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskRespVO.java index 4e3115b..e397cae 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/MesWmStockTakingTaskRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultRespVO.java index cc5638c..87c338b 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/stocktaking/task/vo/result/MesWmStockTakingTaskResultRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.stocktaking.task.vo.result; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseRespVO.java index 6c85e3b..3095f0d 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/MesWmWarehouseRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaRespVO.java index 0cd11b0..db60617 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/area/MesWmWarehouseAreaRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.area; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java index 9228685..ddc6ac1 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/controller/admin/wm/warehouse/vo/location/MesWmWarehouseLocationRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.mes.controller.admin.wm.warehouse.vo.location; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanMapper.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanMapper.java index 9478a13..3123514 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanMapper.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/dal/mysql/cal/plan/MesCalPlanMapper.java @@ -8,6 +8,9 @@ import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDate; +import java.util.List; + /** * MES 排班计划 Mapper * @@ -32,6 +35,15 @@ public interface MesCalPlanMapper extends BaseMapperX { return selectOne(MesCalPlanDO::getCode, code); } + default List selectListByStatusAndDay(Integer status, LocalDate day) { + return selectList(new LambdaQueryWrapperX() + .eq(MesCalPlanDO::getStatus, status) + // TODO @AI:dayend 获取下?应该有方法,这样可以 le,更统一点; + .lt(MesCalPlanDO::getStartDate, day.plusDays(1).atStartOfDay()) + .ge(MesCalPlanDO::getEndDate, day.atStartOfDay()) + .orderByAsc(MesCalPlanDO::getId)); + } + default void updateWithShiftFieldCleanup(MesCalPlanDO plan, boolean clearShiftMethod, boolean clearShiftCount) { update(plan, Wrappers.lambdaUpdate() .eq(MesCalPlanDO::getId, plan.getId()) diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java index bc19c6d..d9cf299 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/enums/ErrorCodeConstants.java @@ -140,6 +140,9 @@ public interface ErrorCodeConstants { ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH = new ErrorCode(1_040_201_202, "班次数量不满足轮班方式要求"); ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_COUNT_INVALID = new ErrorCode(1_040_201_203, "按天倒班必须填写合法的倒班天数"); ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_METHOD_INVALID = new ErrorCode(1_040_201_204, "不支持的倒班方式:{}"); + ErrorCode CAL_TEAM_SHIFT_GENERATE_SHIFT_TIME_INVALID = new ErrorCode(1_040_201_205, "班次【{}】的开始或结束时间格式不正确,应为 HH:mm,结束时间可为 24:00"); + ErrorCode CAL_TEAM_SHIFT_GENERATE_REST_INVALID = new ErrorCode(1_040_201_206, + "班组【{}】{} {}与 {} {}的上班时间重叠或首尾相接,没有休息间隔,请调整班次时间或倒班方式"); // ========== MES 日历排班-排班计划(1-040-202-000) ========== ErrorCode CAL_PLAN_NOT_EXISTS = new ErrorCode(1_040_202_000, "排班计划不存在"); @@ -152,6 +155,8 @@ public interface ErrorCodeConstants { // ========== MES 日历排班-假期设置(1-040-203-000) ========== ErrorCode CAL_HOLIDAY_NOT_EXISTS = new ErrorCode(1_040_203_000, "假期设置不存在"); + ErrorCode CAL_HOLIDAY_PLAN_CONFIRMED = new ErrorCode(1_040_203_001, + "{} 在已确认的排班计划【{}】范围内,修改是否节假日会与已生成的排班不一致,不允许修改"); // ========== MES 设备管理-设备类型(1-040-300-000) ========== ErrorCode DV_MACHINERY_TYPE_NOT_EXISTS = new ErrorCode(1_040_300_000, "设备类型不存在"); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImpl.java index 0502794..3c7695a 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImpl.java @@ -1,16 +1,27 @@ package cn.iocoder.yudao.module.mes.service.cal.holiday; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidaySaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; import cn.iocoder.yudao.module.mes.dal.mysql.cal.holiday.MesCalHolidayMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalHolidayTypeEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; import java.util.List; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_HOLIDAY_PLAN_CONFIRMED; + /** * MES 假期设置 Service 实现类 * @@ -23,10 +34,17 @@ public class MesCalHolidayServiceImpl implements MesCalHolidayService { @Resource private MesCalHolidayMapper holidayMapper; + @Resource + @Lazy + private MesCalPlanService planService; + @Override public Long saveHoliday(MesCalHolidaySaveReqVO saveReqVO) { - // Upsert 逻辑:如果该日期已有记录,则更新 + // 1. 校验是否节假日的变化,不影响已确认的排班计划 MesCalHolidayDO existing = holidayMapper.selectByDay(saveReqVO.getDay()); + validateHolidayChangeForConfirmedPlan(existing, saveReqVO); + + // 2.1 Upsert 逻辑:如果该日期已有记录,则更新 if (existing != null) { MesCalHolidayDO updateObj = BeanUtils.toBean(saveReqVO, MesCalHolidayDO.class); updateObj.setId(existing.getId()); @@ -34,12 +52,33 @@ public class MesCalHolidayServiceImpl implements MesCalHolidayService { return existing.getId(); } - // 插入新记录 + // 2.2 插入新记录 MesCalHolidayDO holiday = BeanUtils.toBean(saveReqVO, MesCalHolidayDO.class); holidayMapper.insert(holiday); return holiday.getId(); } + /** + * 校验是否节假日的变化,不影响已确认的排班计划 + * + * 排班计划确认时按“节假日停班”生成排班记录(按天倒班时还会顺延后续倒班),确认后不会重新生成。 + * 因此已确认计划范围内的日期,不允许在“节假日”与“非节假日”之间切换,避免与已生成的排班不一致 https://t.zsxq.com/XdcRW + */ + private void validateHolidayChangeForConfirmedPlan(MesCalHolidayDO existing, MesCalHolidaySaveReqVO saveReqVO) { + boolean oldHoliday = existing != null && MesCalHolidayTypeEnum.HOLIDAY.getType().equals(existing.getType()); + boolean newHoliday = MesCalHolidayTypeEnum.HOLIDAY.getType().equals(saveReqVO.getType()); + if (oldHoliday == newHoliday) { + return; + } + List plans = planService.getPlanListByStatusAndDay( + MesCalPlanStatusEnum.CONFIRMED.getStatus(), saveReqVO.getDay().toLocalDate()); + if (CollUtil.isEmpty(plans)) { + return; + } + throw exception(CAL_HOLIDAY_PLAN_CONFIRMED, saveReqVO.getDay().toLocalDate(), + StrUtil.join("、", convertList(plans, MesCalPlanDO::getName))); + } + @Override public List getHolidayList(LocalDateTime startDay, LocalDateTime endDay) { return holidayMapper.selectList(startDay, endDay); diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java index 5e141f6..b66e1bf 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveRe import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; import jakarta.validation.Valid; +import java.time.LocalDate; import java.util.Collection; import java.util.List; import java.util.Map; @@ -90,4 +91,13 @@ public interface MesCalPlanService { */ PageResult getPlanPage(MesCalPlanPageReqVO pageReqVO); + /** + * 获得指定状态、且起止日期包含指定日期的排班计划列表 + * + * @param status 状态 + * @param day 日期 + * @return 排班计划列表 + */ + List getPlanListByStatusAndDay(Integer status, LocalDate day); + } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java index 68631dd..cb59047 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImpl.java @@ -18,6 +18,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.time.LocalDate; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -143,6 +144,11 @@ public class MesCalPlanServiceImpl implements MesCalPlanService { } @Override + public List getPlanListByStatusAndDay(Integer status, LocalDate day) { + return planMapper.selectListByStatusAndDay(status, day); + } + + @Override public MesCalPlanDO validatePlanPrepare(Long planId) { MesCalPlanDO plan = validatePlanExists(planId); if (ObjUtil.notEqual(MesCalPlanStatusEnum.PREPARE.getStatus(), plan.getStatus())) { @@ -171,11 +177,13 @@ public class MesCalPlanServiceImpl implements MesCalPlanService { /** * 确认排班计划时,校验班组数量是否与轮班方式匹配 + * + * 排班只会使用轮班方式所需数量的班组,多出的班组不会参与轮休或替班,因此要求数量一致,避免被静默忽略 https://t.zsxq.com/XdcRW */ private void validateTeamCountForConfirm(Long planId, Integer shiftType) { Long teamCount = planTeamService.getPlanTeamCountByPlanId(planId); MesCalShiftTypeEnum shiftTypeEnum = MesCalShiftTypeEnum.valueOf(shiftType); - if (teamCount < shiftTypeEnum.getRequiredTeamCount()) { + if (teamCount == null || teamCount != shiftTypeEnum.getRequiredTeamCount()) { throw exception(CAL_PLAN_TEAM_COUNT_NOT_MATCH); } } diff --git a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java index 52fa763..b026c03 100644 --- a/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java +++ b/yudao-module-mes/src/main/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImpl.java @@ -1,13 +1,18 @@ package cn.iocoder.yudao.module.mes.service.cal.team; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.module.mes.controller.admin.cal.team.vo.shift.MesCalTeamShiftListReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamShiftMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalHolidayTypeEnum; import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum; import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService; import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService; import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService; @@ -20,14 +25,25 @@ import org.springframework.validation.annotation.Validated; import java.time.LocalDate; import java.time.LocalDateTime; +import java.time.LocalTime; import java.time.temporal.ChronoUnit; import java.util.ArrayList; +import java.util.Comparator; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_REST_INVALID; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_COUNT_INVALID; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_METHOD_INVALID; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_TIME_INVALID; import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_TEAM_NOT_ENOUGH; /** @@ -39,6 +55,11 @@ import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIF @Validated public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService { + /** + * 班次时间格式:H:mm 或 HH:mm + */ + private static final Pattern SHIFT_TIME_PATTERN = Pattern.compile("^(\\d{1,2}):(\\d{2})$"); + @Resource private MesCalTeamShiftMapper teamShiftMapper; @@ -51,6 +72,12 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService { @Resource @Lazy private MesCalPlanTeamService planTeamService; + @Resource + @Lazy + private MesCalHolidayService holidayService; + @Resource + @Lazy + private MesCalTeamService teamService; @Transactional(rollbackFor = Exception.class) @Override @@ -71,25 +98,118 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService { throw exception(CAL_TEAM_SHIFT_GENERATE_SHIFT_NOT_ENOUGH); } - // 2. 计算日期跨度,遍历每天生成排班记录,最后统一写入数据库 + // 2.1 计算日期跨度,查询范围内的节假日 LocalDate startDate = plan.getStartDate().toLocalDate(); LocalDate endDate = plan.getEndDate().toLocalDate(); long days = ChronoUnit.DAYS.between(startDate, endDate) + 1; + Set holidayDates = getHolidayDates(startDate, endDate); + // 2.2 遍历每天生成排班记录,最后统一写入数据库 + // 假期停班:节假日不生成排班,按天倒班只累计有效排班日(假期不消耗倒班天数);按周/月/季度仍按日历周期换班 https://t.zsxq.com/XdcRW + boolean dayMethod = MesCalShiftMethodEnum.DAY.getMethod().equals(plan.getShiftMethod()); List allRecords = new ArrayList<>(); int shiftIndex = 0; + int workDayOffset = 0; for (int i = 0; i < days; i++) { LocalDate currentDate = startDate.plusDays(i); LocalDateTime currentDay = currentDate.atStartOfDay(); - // 2.2.1 根据倒班方式计算 shiftIndex 单白班不倒班,跳过 - if (!MesCalShiftTypeEnum.SINGLE.getType().equals(plan.getShiftType())) { - shiftIndex = calculateShiftIndex(shiftIndex, i, currentDate, startDate, plan); + boolean holiday = holidayDates.contains(currentDate); + // 2.2.1 根据倒班方式计算 shiftIndex 单白班不倒班,跳过;周期起点恰逢假期时,也照常换班 + if (!MesCalShiftTypeEnum.SINGLE.getType().equals(plan.getShiftType()) && !(dayMethod && holiday)) { + shiftIndex = calculateShiftIndex(shiftIndex, dayMethod ? workDayOffset : i, currentDate, startDate, plan); + } + if (holiday) { + continue; } + workDayOffset++; // 2.2.2 根据轮班方式生成排班记录,收集到列表 buildRecordsForDay(allRecords, planId, currentDay, shiftIndex, plan.getShiftType(), teams, shifts); } + // 2.3 校验同一班组相邻两次排班之间留有休息间隔 https://t.zsxq.com/XdcRW + validateTeamShiftRest(allRecords, shifts); // 3. 批量插入排班记录 - teamShiftMapper.insertBatch(allRecords); + if (CollUtil.isNotEmpty(allRecords)) { + teamShiftMapper.insertBatch(allRecords); + } + } + + /** + * 获得日期范围内的节假日(日期类型为节假日的,排班时停班) + */ + private Set getHolidayDates(LocalDate startDate, LocalDate endDate) { + List holidays = holidayService.getHolidayList( + startDate.atStartOfDay(), endDate.atTime(23, 59, 59)); + return convertSet(holidays, holiday -> holiday.getDay().toLocalDate(), + holiday -> MesCalHolidayTypeEnum.HOLIDAY.getType().equals(holiday.getType())); + } + + /** + * 校验同一班组相邻两次排班之间留有休息间隔 + * + * 按全部排班的上班开始时刻排序,前一班的结束时刻不早于同一班组下一班的开始时刻, + * 即上班时间重叠或首尾相接(例如夜班次日 08:00 下班后立即接 08:00 的白班),不允许生成 + */ + private void validateTeamShiftRest(List records, List shifts) { + // 1. 解析班次的开始、结束时间 + Map shiftMap = convertMap(shifts, MesCalPlanShiftDO::getId); + Map shiftTimeMap = convertMap(shifts, MesCalPlanShiftDO::getId, + shift -> new LocalTime[]{parseShiftTime(shift, shift.getStartTime(), false), + parseShiftTime(shift, shift.getEndTime(), true)}); + + // 2. 按上班开始时刻排序,逐条与同一班组的上一次排班比较 + List sortedRecords = new ArrayList<>(records); + sortedRecords.sort(Comparator.comparing(record -> buildShiftTimeRange(record, shiftTimeMap)[0])); + Map lastRecordMap = new HashMap<>(); + for (MesCalTeamShiftDO record : sortedRecords) { + MesCalTeamShiftDO lastRecord = lastRecordMap.put(record.getTeamId(), record); + if (lastRecord == null || buildShiftTimeRange(lastRecord, shiftTimeMap)[1] + .isBefore(buildShiftTimeRange(record, shiftTimeMap)[0])) { + continue; + } + MesCalTeamDO team = teamService.getTeam(record.getTeamId()); + throw exception(CAL_TEAM_SHIFT_GENERATE_REST_INVALID, team != null ? team.getName() : record.getTeamId(), + lastRecord.getDay().toLocalDate(), shiftMap.get(lastRecord.getShiftId()).getName(), + record.getDay().toLocalDate(), shiftMap.get(record.getShiftId()).getName()); + } + } + + /** + * 计算排班记录的实际上班时间段 + * + * 开始时间在排班日期当天;结束时间不晚于开始时间(例如 20:00~08:00、16:00~00:00)时,跨午夜到次日结束 + * + * @return [开始时刻, 结束时刻] + */ + private static LocalDateTime[] buildShiftTimeRange(MesCalTeamShiftDO record, Map shiftTimeMap) { + LocalTime[] shiftTime = shiftTimeMap.get(record.getShiftId()); + LocalDate day = record.getDay().toLocalDate(); + LocalDateTime start = day.atTime(shiftTime[0]); + LocalDateTime end = shiftTime[1].isAfter(shiftTime[0]) ? day.atTime(shiftTime[1]) + : day.plusDays(1).atTime(shiftTime[1]); + return new LocalDateTime[]{start, end}; + } + + /** + * 解析班次时间,兼容 H:mm(例如 8:00) + * + * 结束时间允许 24:00,表示当天 24:00,按 00:00 处理后由“结束时间不晚于开始时间时跨午夜到次日”规则得到次日 00:00 https://t.zsxq.com/XdcRW + * + * @param endTime 是否为结束时间 + */ + private static LocalTime parseShiftTime(MesCalPlanShiftDO shift, String time, boolean endTime) { + Matcher matcher = time != null ? SHIFT_TIME_PATTERN.matcher(time.trim()) : null; + if (matcher == null || !matcher.matches()) { + throw exception(CAL_TEAM_SHIFT_GENERATE_SHIFT_TIME_INVALID, shift.getName()); + } + int hour = Integer.parseInt(matcher.group(1)); + int minute = Integer.parseInt(matcher.group(2)); + if (endTime && hour == 24 && minute == 0) { + return LocalTime.MIDNIGHT; + } + if (hour > 23 || minute > 59) { + throw exception(CAL_TEAM_SHIFT_GENERATE_SHIFT_TIME_INVALID, shift.getName()); + } + return LocalTime.of(hour, minute); } /** @@ -180,7 +300,7 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService { .sort(1).build()); } } else if (MesCalShiftTypeEnum.THREE.getType().equals(shiftType)) { - // 三班倒 + // 三班倒:按 白班 → 夜班 → 中班 轮转。原 白班 → 中班 → 夜班 轮转时,换班当天中班 24:00 下班的班组会立即接 00:00 的夜班 https://t.zsxq.com/XdcRW if (shiftIndex % 3 == 0) { // A 组上白班、B 组上中班、C 组上夜班 allRecords.add(MesCalTeamShiftDO.builder() @@ -199,39 +319,39 @@ public class MesCalTeamShiftServiceImpl implements MesCalTeamShiftService { .shiftId(shifts.get(2).getId()) .sort(3).build()); } else if (shiftIndex % 3 == 1) { - // A 组上中班、B 组上夜班、C 组上白班 + // A 组上夜班、B 组上白班、C 组上中班 allRecords.add(MesCalTeamShiftDO.builder() .planId(planId).day(currentDay) .teamId(teams.get(0).getTeamId()) - .shiftId(shifts.get(1).getId()) - .sort(2).build()); - allRecords.add(MesCalTeamShiftDO.builder() - .planId(planId).day(currentDay) - .teamId(teams.get(1).getTeamId()) .shiftId(shifts.get(2).getId()) .sort(3).build()); allRecords.add(MesCalTeamShiftDO.builder() .planId(planId).day(currentDay) - .teamId(teams.get(2).getTeamId()) + .teamId(teams.get(1).getTeamId()) .shiftId(shifts.get(0).getId()) .sort(1).build()); + allRecords.add(MesCalTeamShiftDO.builder() + .planId(planId).day(currentDay) + .teamId(teams.get(2).getTeamId()) + .shiftId(shifts.get(1).getId()) + .sort(2).build()); } else { - // A 组上夜班、B 组上白班、C 组上中班 + // A 组上中班、B 组上夜班、C 组上白班 allRecords.add(MesCalTeamShiftDO.builder() .planId(planId).day(currentDay) .teamId(teams.get(0).getTeamId()) - .shiftId(shifts.get(2).getId()) - .sort(3).build()); + .shiftId(shifts.get(1).getId()) + .sort(2).build()); allRecords.add(MesCalTeamShiftDO.builder() .planId(planId).day(currentDay) .teamId(teams.get(1).getTeamId()) - .shiftId(shifts.get(0).getId()) - .sort(1).build()); + .shiftId(shifts.get(2).getId()) + .sort(3).build()); allRecords.add(MesCalTeamShiftDO.builder() .planId(planId).day(currentDay) .teamId(teams.get(2).getTeamId()) - .shiftId(shifts.get(1).getId()) - .sort(2).build()); + .shiftId(shifts.get(0).getId()) + .sort(1).build()); } } } diff --git a/yudao-module-mes/src/main/resources/mapper/home/MesHomeStatisticsMapper.xml b/yudao-module-mes/src/main/resources/mapper/home/MesHomeStatisticsMapper.xml index 33d6f00..f0307cf 100644 --- a/yudao-module-mes/src/main/resources/mapper/home/MesHomeStatisticsMapper.xml +++ b/yudao-module-mes/src/main/resources/mapper/home/MesHomeStatisticsMapper.xml @@ -3,7 +3,7 @@ - + SELECT status, COUNT(*) AS count FROM mes_pro_work_order WHERE deleted = 0 @@ -11,7 +11,7 @@ - + SELECT IFNULL(SUM(feedback_quantity), 0) AS feedbackQuantity, IFNULL(SUM(qualified_quantity), 0) AS qualifiedQuantity, IFNULL(SUM(unqualified_quantity), 0) AS unqualifiedQuantity @@ -25,7 +25,7 @@ - + SELECT status, COUNT(*) AS count FROM mes_dv_machinery WHERE deleted = 0 @@ -51,7 +51,7 @@ - + SELECT DATE_FORMAT(feedback_time, '%Y-%m-%d') AS date, IFNULL(SUM(feedback_quantity), 0) AS quantity, IFNULL(SUM(qualified_quantity), 0) AS qualifiedQuantity, diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImplTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImplTest.java new file mode 100644 index 0000000..a0d0033 --- /dev/null +++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/holiday/MesCalHolidayServiceImplTest.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.mes.service.cal.holiday; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.controller.admin.cal.holiday.vo.MesCalHolidaySaveReqVO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; +import cn.iocoder.yudao.module.mes.dal.mysql.cal.holiday.MesCalHolidayMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalHolidayTypeEnum; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalPlanStatusEnum; +import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Test; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_HOLIDAY_PLAN_CONFIRMED; +import static java.util.Collections.emptyList; +import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link MesCalHolidayServiceImpl} 的单元测试 + * + * @author 芋道源码 + */ +@Import(MesCalHolidayServiceImpl.class) +public class MesCalHolidayServiceImplTest extends BaseDbUnitTest { + + @Resource + private MesCalHolidayServiceImpl holidayService; + + @Resource + private MesCalHolidayMapper holidayMapper; + + @MockitoBean + private MesCalPlanService planService; + + @Test + public void testSaveHoliday_addHolidayInConfirmedPlan() { + // 准备参数 + MesCalHolidaySaveReqVO reqVO = randomPojo(MesCalHolidaySaveReqVO.class, o -> { + o.setId(null); // 避免 id 被赋值 + o.setDay(LocalDateTime.of(2026, 10, 20, 0, 0)); + o.setType(MesCalHolidayTypeEnum.HOLIDAY.getType()); + }); + // mock planService 的方法:该日期在已确认的排班计划范围内 + MesCalPlanDO plan = randomPojo(MesCalPlanDO.class, o -> o.setStatus(MesCalPlanStatusEnum.CONFIRMED.getStatus())); + when(planService.getPlanListByStatusAndDay(eq(MesCalPlanStatusEnum.CONFIRMED.getStatus()), + eq(reqVO.getDay().toLocalDate()))).thenReturn(singletonList(plan)); + + // 调用,并断言异常 + assertServiceException(() -> holidayService.saveHoliday(reqVO), CAL_HOLIDAY_PLAN_CONFIRMED, + reqVO.getDay().toLocalDate(), plan.getName()); + // 断言:未写入假期设置 + assertNull(holidayMapper.selectByDay(reqVO.getDay())); + } + + @Test + public void testSaveHoliday_cancelHolidayInConfirmedPlan() { + // mock 数据:已有节假日 + MesCalHolidayDO dbHoliday = randomPojo(MesCalHolidayDO.class, o -> { + o.setId(null); // 避免 id 被赋值 + o.setDay(LocalDateTime.of(2026, 10, 20, 0, 0)); + o.setType(MesCalHolidayTypeEnum.HOLIDAY.getType()); + }); + holidayMapper.insert(dbHoliday); + // 准备参数:改为工作日 + MesCalHolidaySaveReqVO reqVO = randomPojo(MesCalHolidaySaveReqVO.class, o -> { + o.setId(null); // 避免 id 被赋值 + o.setDay(dbHoliday.getDay()); + o.setType(MesCalHolidayTypeEnum.WORKDAY.getType()); + }); + // mock planService 的方法:该日期在已确认的排班计划范围内 + MesCalPlanDO plan = randomPojo(MesCalPlanDO.class, o -> o.setStatus(MesCalPlanStatusEnum.CONFIRMED.getStatus())); + when(planService.getPlanListByStatusAndDay(eq(MesCalPlanStatusEnum.CONFIRMED.getStatus()), + eq(reqVO.getDay().toLocalDate()))).thenReturn(singletonList(plan)); + + // 调用,并断言异常 + assertServiceException(() -> holidayService.saveHoliday(reqVO), CAL_HOLIDAY_PLAN_CONFIRMED, + reqVO.getDay().toLocalDate(), plan.getName()); + // 断言:假期设置未被修改 + assertPojoEquals(dbHoliday, holidayMapper.selectById(dbHoliday.getId())); + } + + @Test + public void testSaveHoliday_updateRemarkInConfirmedPlan() { + // mock 数据:已有节假日 + MesCalHolidayDO dbHoliday = randomPojo(MesCalHolidayDO.class, o -> { + o.setId(null); // 避免 id 被赋值 + o.setDay(LocalDateTime.of(2026, 10, 20, 0, 0)); + o.setType(MesCalHolidayTypeEnum.HOLIDAY.getType()); + }); + holidayMapper.insert(dbHoliday); + // 准备参数:仍为节假日,只修改备注 + MesCalHolidaySaveReqVO reqVO = randomPojo(MesCalHolidaySaveReqVO.class, o -> { + o.setId(null); // 避免 id 被赋值 + o.setDay(dbHoliday.getDay()); + o.setType(MesCalHolidayTypeEnum.HOLIDAY.getType()); + }); + + // 调用 + Long id = holidayService.saveHoliday(reqVO); + // 断言:更新已有记录,且是否节假日未变化,无需校验排班计划 + assertEquals(dbHoliday.getId(), id); + assertPojoEquals(reqVO, holidayMapper.selectById(id), "id"); + verify(planService, never()).getPlanListByStatusAndDay(any(), any()); + } + + @Test + public void testSaveHoliday_createWithoutConfirmedPlan() { + // 准备参数 + MesCalHolidaySaveReqVO reqVO = randomPojo(MesCalHolidaySaveReqVO.class, o -> { + o.setId(null); // 避免 id 被赋值 + o.setDay(LocalDateTime.of(2026, 10, 20, 0, 0)); + o.setType(MesCalHolidayTypeEnum.HOLIDAY.getType()); + }); + // mock planService 的方法:该日期没有已确认的排班计划 + when(planService.getPlanListByStatusAndDay(eq(MesCalPlanStatusEnum.CONFIRMED.getStatus()), + eq(reqVO.getDay().toLocalDate()))).thenReturn(emptyList()); + + // 调用 + Long id = holidayService.saveHoliday(reqVO); + // 断言 + assertPojoEquals(reqVO, holidayMapper.selectById(id), "id"); + } + +} diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java index 9f0016e..83fe34e 100644 --- a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java +++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/plan/MesCalPlanServiceImplTest.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.mes.service.cal.plan; +import cn.iocoder.yudao.framework.common.util.collection.SetUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.mes.controller.admin.cal.plan.vo.MesCalPlanSaveReqVO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; @@ -14,9 +15,17 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import jakarta.annotation.Resource; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.util.List; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_PLAN_NOT_PREPARE; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_PLAN_TEAM_COUNT_NOT_MATCH; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_REST_INVALID; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -88,6 +97,85 @@ public class MesCalPlanServiceImplTest extends BaseDbUnitTest { assertEquals(MesCalPlanStatusEnum.CONFIRMED.getStatus(), updatePlan.getStatus()); // 断言 2:触发生成班组排班记录 verify(teamShiftService).generateTeamShiftRecords(plan.getId()); + // 断言 3:重复确认被拒绝,且不会再次生成班组排班记录 + assertServiceException(() -> planService.confirmPlan(plan.getId()), CAL_PLAN_NOT_PREPARE); + verify(teamShiftService, times(1)).generateTeamShiftRecords(plan.getId()); + } + + @Test + public void testConfirmPlan_generateFailed_rollbackStatus() { + // mock 数据:插入一条草稿状态的两班倒排班计划 + MesCalPlanDO plan = randomPojo(MesCalPlanDO.class, o -> { + o.setCalendarType(1); + o.setStartDate(LocalDateTime.of(2026, 10, 19, 0, 0)); + o.setEndDate(LocalDateTime.of(2026, 10, 21, 0, 0)); + o.setStatus(MesCalPlanStatusEnum.PREPARE.getStatus()); + o.setShiftType(MesCalShiftTypeEnum.TWO.getType()); + o.setShiftMethod(MesCalShiftMethodEnum.DAY.getMethod()); + o.setShiftCount(1); + }); + planMapper.insert(plan); + // mock 方法:班组数量满足要求,但生成排班时校验到没有休息间隔 + when(planTeamService.getPlanTeamCountByPlanId(plan.getId())).thenReturn(2L); + doThrow(exception(CAL_TEAM_SHIFT_GENERATE_REST_INVALID, "乙班", + LocalDate.of(2026, 10, 19), "夜班", LocalDate.of(2026, 10, 20), "白班")) + .when(teamShiftService).generateTeamShiftRecords(plan.getId()); + + // 调用,并断言异常 + assertServiceException(() -> planService.confirmPlan(plan.getId()), CAL_TEAM_SHIFT_GENERATE_REST_INVALID, + "乙班", LocalDate.of(2026, 10, 19), "夜班", LocalDate.of(2026, 10, 20), "白班"); + // 断言:事务回滚,计划仍为草稿 + MesCalPlanDO dbPlan = planMapper.selectById(plan.getId()); + assertEquals(MesCalPlanStatusEnum.PREPARE.getStatus(), dbPlan.getStatus()); + } + + @Test + public void testConfirmPlan_teamCountExceed() { + // mock 数据:插入一条草稿状态的两班倒排班计划 + MesCalPlanDO plan = randomPojo(MesCalPlanDO.class, o -> { + o.setCalendarType(1); + o.setStartDate(LocalDateTime.of(2026, 10, 19, 0, 0)); + o.setEndDate(LocalDateTime.of(2026, 10, 21, 0, 0)); + o.setStatus(MesCalPlanStatusEnum.PREPARE.getStatus()); + o.setShiftType(MesCalShiftTypeEnum.TWO.getType()); + o.setShiftMethod(MesCalShiftMethodEnum.DAY.getMethod()); + o.setShiftCount(1); + }); + planMapper.insert(plan); + // mock 方法:分配了 3 个班组,多出的班组不会参与排班 + when(planTeamService.getPlanTeamCountByPlanId(plan.getId())).thenReturn(3L); + + // 调用,并断言异常 + assertServiceException(() -> planService.confirmPlan(plan.getId()), CAL_PLAN_TEAM_COUNT_NOT_MATCH); + // 断言:计划仍为草稿,且未生成排班记录 + MesCalPlanDO dbPlan = planMapper.selectById(plan.getId()); + assertEquals(MesCalPlanStatusEnum.PREPARE.getStatus(), dbPlan.getStatus()); + verify(teamShiftService, never()).generateTeamShiftRecords(plan.getId()); + } + + @Test + public void testGetPlanListByStatusAndDay() { + // mock 数据:已确认,结束日期为当天 + MesCalPlanDO plan01 = randomPlan(LocalDateTime.of(2026, 10, 1, 0, 0), + LocalDateTime.of(2026, 10, 19, 0, 0), MesCalPlanStatusEnum.CONFIRMED.getStatus()); + planMapper.insert(plan01); + // mock 数据:已确认,开始日期为当天 + MesCalPlanDO plan02 = randomPlan(LocalDateTime.of(2026, 10, 19, 0, 0), + LocalDateTime.of(2026, 10, 31, 0, 0), MesCalPlanStatusEnum.CONFIRMED.getStatus()); + planMapper.insert(plan02); + // mock 数据:已确认,但不包含当天 + planMapper.insert(randomPlan(LocalDateTime.of(2026, 10, 20, 0, 0), + LocalDateTime.of(2026, 10, 31, 0, 0), MesCalPlanStatusEnum.CONFIRMED.getStatus())); + // mock 数据:包含当天,但为草稿 + planMapper.insert(randomPlan(LocalDateTime.of(2026, 10, 1, 0, 0), + LocalDateTime.of(2026, 10, 31, 0, 0), MesCalPlanStatusEnum.PREPARE.getStatus())); + + // 调用 + List list = planService.getPlanListByStatusAndDay( + MesCalPlanStatusEnum.CONFIRMED.getStatus(), LocalDate.of(2026, 10, 19)); + + // 断言:只返回包含当天的已确认计划(起止日期为当天也算) + assertEquals(SetUtils.asSet(plan01.getId(), plan02.getId()), convertSet(list, MesCalPlanDO::getId)); } @Test @@ -116,4 +204,16 @@ public class MesCalPlanServiceImplTest extends BaseDbUnitTest { verify(teamShiftService, never()).deleteByPlanId(plan.getId()); } + private static MesCalPlanDO randomPlan(LocalDateTime startDate, LocalDateTime endDate, Integer status) { + return randomPojo(MesCalPlanDO.class, o -> { + o.setCalendarType(1); + o.setStartDate(startDate); + o.setEndDate(endDate); + o.setStatus(status); + o.setShiftType(MesCalShiftTypeEnum.TWO.getType()); + o.setShiftMethod(MesCalShiftMethodEnum.DAY.getMethod()); + o.setShiftCount(1); + }); + } + } diff --git a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java index cd0d419..0d3749c 100644 --- a/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java +++ b/yudao-module-mes/src/test/java/cn/iocoder/yudao/module/mes/service/cal/team/MesCalTeamShiftServiceImplTest.java @@ -2,13 +2,17 @@ package cn.iocoder.yudao.module.mes.service.cal.team; import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.holiday.MesCalHolidayDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanShiftDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.plan.MesCalPlanTeamDO; +import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamDO; import cn.iocoder.yudao.module.mes.dal.dataobject.cal.team.MesCalTeamShiftDO; import cn.iocoder.yudao.module.mes.dal.mysql.cal.team.MesCalTeamShiftMapper; +import cn.iocoder.yudao.module.mes.enums.cal.MesCalHolidayTypeEnum; import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftMethodEnum; import cn.iocoder.yudao.module.mes.enums.cal.MesCalShiftTypeEnum; +import cn.iocoder.yudao.module.mes.service.cal.holiday.MesCalHolidayService; import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanService; import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanShiftService; import cn.iocoder.yudao.module.mes.service.cal.plan.MesCalPlanTeamService; @@ -18,10 +22,15 @@ import org.springframework.test.context.bean.override.mockito.MockitoBean; import jakarta.annotation.Resource; +import java.time.LocalDate; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_REST_INVALID; +import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.CAL_TEAM_SHIFT_GENERATE_SHIFT_TIME_INVALID; import static org.junit.jupiter.api.Assertions.*; import static org.mockito.Mockito.*; @@ -45,6 +54,10 @@ public class MesCalTeamShiftServiceImplTest extends BaseDbUnitTest { private MesCalPlanShiftService planShiftService; @MockitoBean private MesCalPlanTeamService planTeamService; + @MockitoBean + private MesCalHolidayService holidayService; + @MockitoBean + private MesCalTeamService teamService; @Test public void testGenerateTeamShiftRecords_threeShift_rotateThreeStates() { @@ -79,22 +92,22 @@ public class MesCalTeamShiftServiceImplTest extends BaseDbUnitTest { // 调用 teamShiftService.generateTeamShiftRecords(planId); - // 断言:3 天 × 3 班次 = 9 条排班记录,班组按天轮转 - List records = teamShiftMapper.selectListByPlanId(planId); - records.sort(Comparator.comparing(MesCalTeamShiftDO::getDay).thenComparing(MesCalTeamShiftDO::getSort)); + // 断言:3 天 × 3 班次 = 9 条排班记录,班组按 白班 → 夜班 → 中班 轮转 + // 说明:原先按 白班 → 中班 → 夜班 轮转时,B 组 4/1 中班 24:00 下班后会立即接 4/2 00:00 的夜班,没有休息间隔 + List records = getRecords(planId); assertEquals(9, records.size()); // 断言:第 1 天(shiftIndex=0):A 白班、B 中班、C 夜班 assertRecord(records.get(0), LocalDateTime.of(2026, 4, 1, 0, 0), 1, 101L, 11L); assertRecord(records.get(1), LocalDateTime.of(2026, 4, 1, 0, 0), 2, 102L, 12L); assertRecord(records.get(2), LocalDateTime.of(2026, 4, 1, 0, 0), 3, 103L, 13L); - // 断言:第 2 天(shiftIndex=1):C 白班、A 中班、B 夜班 - assertRecord(records.get(3), LocalDateTime.of(2026, 4, 2, 0, 0), 1, 103L, 11L); - assertRecord(records.get(4), LocalDateTime.of(2026, 4, 2, 0, 0), 2, 101L, 12L); - assertRecord(records.get(5), LocalDateTime.of(2026, 4, 2, 0, 0), 3, 102L, 13L); - // 断言:第 3 天(shiftIndex=2):B 白班、C 中班、A 夜班 - assertRecord(records.get(6), LocalDateTime.of(2026, 4, 3, 0, 0), 1, 102L, 11L); - assertRecord(records.get(7), LocalDateTime.of(2026, 4, 3, 0, 0), 2, 103L, 12L); - assertRecord(records.get(8), LocalDateTime.of(2026, 4, 3, 0, 0), 3, 101L, 13L); + // 断言:第 2 天(shiftIndex=1):B 白班、C 中班、A 夜班(A、B 休息 8 小时,C 休息 32 小时) + assertRecord(records.get(3), LocalDateTime.of(2026, 4, 2, 0, 0), 1, 102L, 11L); + assertRecord(records.get(4), LocalDateTime.of(2026, 4, 2, 0, 0), 2, 103L, 12L); + assertRecord(records.get(5), LocalDateTime.of(2026, 4, 2, 0, 0), 3, 101L, 13L); + // 断言:第 3 天(shiftIndex=2):C 白班、A 中班、B 夜班 + assertRecord(records.get(6), LocalDateTime.of(2026, 4, 3, 0, 0), 1, 103L, 11L); + assertRecord(records.get(7), LocalDateTime.of(2026, 4, 3, 0, 0), 2, 101L, 12L); + assertRecord(records.get(8), LocalDateTime.of(2026, 4, 3, 0, 0), 3, 102L, 13L); } @Test @@ -121,6 +134,392 @@ public class MesCalTeamShiftServiceImplTest extends BaseDbUnitTest { assertRecord(records.get(1), start.plusDays(1), 1, 101L, 11L); } + @Test + public void testGenerateTeamShiftRecords_singleCrossMidnight() { + // 准备参数 + Long planId = 3003L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 21); + // mock 方法:单班次 22:00~06:00,跨午夜到次日结束,每天之间休息 16 小时 + mockPlan(planId, MesCalShiftTypeEnum.SINGLE, null, null, startDate, endDate); + when(planShiftService.getPlanShiftListByPlanId(planId)).thenReturn(ListUtil.of( + MesCalPlanShiftDO.builder().id(11L).planId(planId).sort(1).name("夜班") + .startTime("22:00").endTime("06:00").build())); + mockTeams(planId, 101L); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:每天 1 条排班记录 + List records = getRecords(planId); + assertEquals(3, records.size()); + assertRecord(records.get(0), startDate.atStartOfDay(), 1, 101L, 11L); + assertRecord(records.get(1), startDate.plusDays(1).atStartOfDay(), 1, 101L, 11L); + assertRecord(records.get(2), endDate.atStartOfDay(), 1, 101L, 11L); + } + + @Test + public void testGenerateTeamShiftRecords_twoShiftFullDay_rotateWithoutRest() { + // 准备参数 + Long planId = 3004L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 21); + // mock 方法:两班倒、按天倒班 1 天,默认班次 08:00~20:00 / 20:00~08:00 覆盖全天 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 1, startDate, endDate); + mockTwoShifts(planId, "08:00", "20:00", "20:00", "08:00"); + mockTeams(planId, 101L, 102L); + when(teamService.getTeam(eq(102L))).thenReturn(MesCalTeamDO.builder().id(102L).name("乙班").build()); + + // 调用,并断言异常:B 组 10-19 夜班次日 08:00 下班后,立即接 10-20 08:00 的白班,连续上班 24 小时 + assertServiceException(() -> teamShiftService.generateTeamShiftRecords(planId), + CAL_TEAM_SHIFT_GENERATE_REST_INVALID, "乙班", + LocalDate.of(2026, 10, 19), "夜班", LocalDate.of(2026, 10, 20), "白班"); + // 断言:没有写入任何排班记录 + assertTrue(teamShiftMapper.selectListByPlanId(planId).isEmpty()); + } + + @Test + public void testGenerateTeamShiftRecords_twoShiftFullDay_longerShiftCountOnlyDelay() { + // 准备参数 + Long planId = 3005L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 23); + // mock 方法:两班倒、按天倒班 3 天,默认班次覆盖全天 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 3, startDate, endDate); + mockTwoShifts(planId, "08:00", "20:00", "20:00", "08:00"); + mockTeams(planId, 101L, 102L); + when(teamService.getTeam(eq(102L))).thenReturn(MesCalTeamDO.builder().id(102L).name("乙班").build()); + + // 调用,并断言异常:增加倒班天数只是推迟到 10-22 换班,B 组仍然夜班下班后立即接白班 + assertServiceException(() -> teamShiftService.generateTeamShiftRecords(planId), + CAL_TEAM_SHIFT_GENERATE_REST_INVALID, "乙班", + LocalDate.of(2026, 10, 21), "夜班", LocalDate.of(2026, 10, 22), "白班"); + // 断言:没有写入任何排班记录 + assertTrue(teamShiftMapper.selectListByPlanId(planId).isEmpty()); + } + + @Test + public void testGenerateTeamShiftRecords_twoShiftOverlap() { + // 准备参数 + Long planId = 3006L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 20); + // mock 方法:两班倒、按天倒班 1 天,夜班 20:00~08:30 与次日 08:00 的白班重叠 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 1, startDate, endDate); + mockTwoShifts(planId, "08:00", "20:00", "20:00", "08:30"); + mockTeams(planId, 101L, 102L); + when(teamService.getTeam(eq(102L))).thenReturn(MesCalTeamDO.builder().id(102L).name("乙班").build()); + + // 调用,并断言异常 + assertServiceException(() -> teamShiftService.generateTeamShiftRecords(planId), + CAL_TEAM_SHIFT_GENERATE_REST_INVALID, "乙班", + LocalDate.of(2026, 10, 19), "夜班", LocalDate.of(2026, 10, 20), "白班"); + // 断言:没有写入任何排班记录 + assertTrue(teamShiftMapper.selectListByPlanId(planId).isEmpty()); + } + + @Test + public void testGenerateTeamShiftRecords_twoShiftOneMinuteRest() { + // 准备参数 + Long planId = 3007L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 21); + // mock 方法:两班倒、按天倒班 1 天,夜班 20:00~07:59,与次日 08:00 的白班之间留 1 分钟 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 1, startDate, endDate); + mockTwoShifts(planId, "08:00", "20:00", "20:00", "07:59"); + mockTeams(planId, 101L, 102L); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:3 天 × 2 班次 = 6 条排班记录,每天换班 + List records = getRecords(planId); + assertEquals(6, records.size()); + assertRecord(records.get(0), LocalDateTime.of(2026, 10, 19, 0, 0), 1, 101L, 11L); + assertRecord(records.get(1), LocalDateTime.of(2026, 10, 19, 0, 0), 2, 102L, 12L); + assertRecord(records.get(2), LocalDateTime.of(2026, 10, 20, 0, 0), 1, 102L, 11L); + assertRecord(records.get(3), LocalDateTime.of(2026, 10, 20, 0, 0), 2, 101L, 12L); + assertRecord(records.get(4), LocalDateTime.of(2026, 10, 21, 0, 0), 1, 101L, 11L); + assertRecord(records.get(5), LocalDateTime.of(2026, 10, 21, 0, 0), 2, 102L, 12L); + } + + @Test + public void testGenerateTeamShiftRecords_twoShiftFullDay_singleDay() { + // 准备参数 + Long planId = 3008L; + LocalDate day = LocalDate.of(2026, 10, 19); + // mock 方法:两班倒、默认班次覆盖全天,只排 1 天,不发生换班 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 1, day, day); + mockTwoShifts(planId, "08:00", "20:00", "20:00", "08:00"); + mockTeams(planId, 101L, 102L); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:1 天 × 2 班次 = 2 条排班记录 + List records = getRecords(planId); + assertEquals(2, records.size()); + assertRecord(records.get(0), day.atStartOfDay(), 1, 101L, 11L); + assertRecord(records.get(1), day.atStartOfDay(), 2, 102L, 12L); + } + + @Test + public void testGenerateTeamShiftRecords_shiftTimeInvalid() { + // 准备参数 + Long planId = 3009L; + LocalDate day = LocalDate.of(2026, 10, 19); + // mock 方法:白班结束时间不合法 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 1, day, day); + mockTwoShifts(planId, "08:00", "25:00", "20:00", "08:00"); + mockTeams(planId, 101L, 102L); + + // 调用,并断言异常 + assertServiceException(() -> teamShiftService.generateTeamShiftRecords(planId), + CAL_TEAM_SHIFT_GENERATE_SHIFT_TIME_INVALID, "白班"); + // 断言:没有写入任何排班记录 + assertTrue(teamShiftMapper.selectListByPlanId(planId).isEmpty()); + } + + @Test + public void testGenerateTeamShiftRecords_threeShift_hourWithoutZeroAndEnd24() { + // 准备参数 + Long planId = 3016L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 20); + // mock 方法:三班倒、按天倒班 1 天,时间写作 8:00、0:00,中班结束写作 24:00 + mockPlan(planId, MesCalShiftTypeEnum.THREE, MesCalShiftMethodEnum.DAY, 1, startDate, endDate); + when(planShiftService.getPlanShiftListByPlanId(planId)).thenReturn(ListUtil.of( + MesCalPlanShiftDO.builder().id(11L).planId(planId).sort(1).name("白班").startTime("8:00").endTime("16:00").build(), + MesCalPlanShiftDO.builder().id(12L).planId(planId).sort(2).name("中班").startTime("16:00").endTime("24:00").build(), + MesCalPlanShiftDO.builder().id(13L).planId(planId).sort(3).name("夜班").startTime("0:00").endTime("8:00").build())); + mockTeams(planId, 101L, 102L, 103L); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:与默认班次一致,2 天 × 3 班次 = 6 条排班记录,换班后休息 8 / 8 / 32 小时 + List records = getRecords(planId); + assertEquals(6, records.size()); + assertRecord(records.get(0), startDate.atStartOfDay(), 1, 101L, 11L); + assertRecord(records.get(1), startDate.atStartOfDay(), 2, 102L, 12L); + assertRecord(records.get(2), startDate.atStartOfDay(), 3, 103L, 13L); + assertRecord(records.get(3), endDate.atStartOfDay(), 1, 102L, 11L); + assertRecord(records.get(4), endDate.atStartOfDay(), 2, 103L, 12L); + assertRecord(records.get(5), endDate.atStartOfDay(), 3, 101L, 13L); + } + + @Test + public void testGenerateTeamShiftRecords_singleFullDayEnd24_withoutRest() { + // 准备参数 + Long planId = 3017L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 20); + // mock 方法:单班次 00:00~24:00,结束于次日 00:00,与次日的班次首尾相接 + mockPlan(planId, MesCalShiftTypeEnum.SINGLE, null, null, startDate, endDate); + when(planShiftService.getPlanShiftListByPlanId(planId)).thenReturn(ListUtil.of( + MesCalPlanShiftDO.builder().id(11L).planId(planId).sort(1).name("全天班") + .startTime("00:00").endTime("24:00").build())); + mockTeams(planId, 101L); + when(teamService.getTeam(eq(101L))).thenReturn(MesCalTeamDO.builder().id(101L).name("甲班").build()); + + // 调用,并断言异常:24:00 不放宽连班校验 + assertServiceException(() -> teamShiftService.generateTeamShiftRecords(planId), + CAL_TEAM_SHIFT_GENERATE_REST_INVALID, "甲班", startDate, "全天班", endDate, "全天班"); + // 断言:没有写入任何排班记录 + assertTrue(teamShiftMapper.selectListByPlanId(planId).isEmpty()); + } + + @Test + public void testGenerateTeamShiftRecords_shiftTimeInvalid_boundary() { + // 准备参数:开始时间不允许 24:00;结束时间只允许 24:00 整;分钟、小时越界;非 H:mm 格式 + String[][] cases = { + {"24:00", "08:00"}, {"08:00", "24:30"}, {"08:60", "16:00"}, + {"08:00", "16:5"}, {"8点", "16:00"}, {"08:00:00", "16:00"} + }; + for (int i = 0; i < cases.length; i++) { + Long planId = 3020L + i; + LocalDate day = LocalDate.of(2026, 10, 19); + // mock 方法:单班次 + mockPlan(planId, MesCalShiftTypeEnum.SINGLE, null, null, day, day); + when(planShiftService.getPlanShiftListByPlanId(planId)).thenReturn(ListUtil.of( + MesCalPlanShiftDO.builder().id(11L).planId(planId).sort(1).name("白班") + .startTime(cases[i][0]).endTime(cases[i][1]).build())); + mockTeams(planId, 101L); + + // 调用,并断言异常 + assertServiceException(() -> teamShiftService.generateTeamShiftRecords(planId), + CAL_TEAM_SHIFT_GENERATE_SHIFT_TIME_INVALID, "白班"); + // 断言:没有写入任何排班记录 + assertTrue(teamShiftMapper.selectListByPlanId(planId).isEmpty()); + } + } + + @Test + public void testGenerateTeamShiftRecords_dayMethod_holidayNotConsumeShiftCount() { + // 准备参数 + Long planId = 3010L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 22); + // mock 方法:两班倒、按天倒班 2 天,班次之间留有空档 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 2, startDate, endDate); + mockTwoShifts(planId, "08:00", "17:00", "20:00", "05:00"); + mockTeams(planId, 101L, 102L); + // mock 方法:10-20 为节假日;10-21 为工作日,照常排班 + mockHolidays(startDate, endDate, buildHoliday(LocalDate.of(2026, 10, 20), MesCalHolidayTypeEnum.HOLIDAY), + buildHoliday(LocalDate.of(2026, 10, 21), MesCalHolidayTypeEnum.WORKDAY)); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:节假日停班,3 个有效排班日 × 2 班次 = 6 条排班记录 + List records = getRecords(planId); + assertEquals(6, records.size()); + // 断言:10-19、10-21 为第 1、2 个有效排班日,A 组白班 + assertRecord(records.get(0), LocalDateTime.of(2026, 10, 19, 0, 0), 1, 101L, 11L); + assertRecord(records.get(1), LocalDateTime.of(2026, 10, 19, 0, 0), 2, 102L, 12L); + assertRecord(records.get(2), LocalDateTime.of(2026, 10, 21, 0, 0), 1, 101L, 11L); + assertRecord(records.get(3), LocalDateTime.of(2026, 10, 21, 0, 0), 2, 102L, 12L); + // 断言:10-22 为第 3 个有效排班日,才换班 + assertRecord(records.get(4), LocalDateTime.of(2026, 10, 22, 0, 0), 1, 102L, 11L); + assertRecord(records.get(5), LocalDateTime.of(2026, 10, 22, 0, 0), 2, 101L, 12L); + } + + @Test + public void testGenerateTeamShiftRecords_dayMethod_firstDayHoliday() { + // 准备参数 + Long planId = 3011L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 21); + // mock 方法:两班倒、按天倒班 1 天,首日 10-19 为节假日 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 1, startDate, endDate); + mockTwoShifts(planId, "08:00", "17:00", "20:00", "05:00"); + mockTeams(planId, 101L, 102L); + mockHolidays(startDate, endDate, buildHoliday(startDate, MesCalHolidayTypeEnum.HOLIDAY)); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:从 10-20 开始排班,10-20 为第 1 个有效排班日,不换班 + List records = getRecords(planId); + assertEquals(4, records.size()); + assertRecord(records.get(0), LocalDateTime.of(2026, 10, 20, 0, 0), 1, 101L, 11L); + assertRecord(records.get(1), LocalDateTime.of(2026, 10, 20, 0, 0), 2, 102L, 12L); + assertRecord(records.get(2), LocalDateTime.of(2026, 10, 21, 0, 0), 1, 102L, 11L); + assertRecord(records.get(3), LocalDateTime.of(2026, 10, 21, 0, 0), 2, 101L, 12L); + } + + @Test + public void testGenerateTeamShiftRecords_allHoliday() { + // 准备参数 + Long planId = 3012L; + LocalDate startDate = LocalDate.of(2026, 10, 19); + LocalDate endDate = LocalDate.of(2026, 10, 20); + // mock 方法:两班倒、计划范围内全部为节假日 + mockPlan(planId, MesCalShiftTypeEnum.TWO, MesCalShiftMethodEnum.DAY, 1, startDate, endDate); + mockTwoShifts(planId, "08:00", "20:00", "20:00", "08:00"); + mockTeams(planId, 101L, 102L); + mockHolidays(startDate, endDate, buildHoliday(startDate, MesCalHolidayTypeEnum.HOLIDAY), + buildHoliday(endDate, MesCalHolidayTypeEnum.HOLIDAY)); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:不生成排班记录 + assertTrue(teamShiftMapper.selectListByPlanId(planId).isEmpty()); + } + + @Test + public void testGenerateTeamShiftRecords_weekMethod_holidayOnWeekStart() { + // 10-18 周日、10-19 周一为节假日、10-20 周二 + assertRotateAcrossHoliday(3013L, MesCalShiftMethodEnum.WEEK, + LocalDate.of(2026, 10, 18), LocalDate.of(2026, 10, 19)); + } + + @Test + public void testGenerateTeamShiftRecords_monthMethod_holidayOnMonthStart() { + // 09-30、10-01 月初为节假日、10-02 + assertRotateAcrossHoliday(3014L, MesCalShiftMethodEnum.MONTH, + LocalDate.of(2026, 9, 30), LocalDate.of(2026, 10, 1)); + } + + @Test + public void testGenerateTeamShiftRecords_quarterMethod_holidayOnQuarterStart() { + // 06-30、07-01 季度初为节假日、07-02 + assertRotateAcrossHoliday(3015L, MesCalShiftMethodEnum.QUARTER, + LocalDate.of(2026, 6, 30), LocalDate.of(2026, 7, 1)); + } + + /** + * 断言按周/月/季度倒班时,周期起点恰逢节假日也照常换班 + * + * 默认两班倒班次覆盖全天,换班前一天夜班的班组,隔着节假日停班一天再上白班,留有 24 小时休息 + */ + private void assertRotateAcrossHoliday(Long planId, MesCalShiftMethodEnum shiftMethod, + LocalDate startDate, LocalDate holidayDate) { + // 准备参数 + LocalDate endDate = holidayDate.plusDays(1); + // mock 方法:两班倒、默认班次覆盖全天,周期起点为节假日 + mockPlan(planId, MesCalShiftTypeEnum.TWO, shiftMethod, null, startDate, endDate); + mockTwoShifts(planId, "08:00", "20:00", "20:00", "08:00"); + mockTeams(planId, 101L, 102L); + mockHolidays(startDate, endDate, buildHoliday(holidayDate, MesCalHolidayTypeEnum.HOLIDAY)); + + // 调用 + teamShiftService.generateTeamShiftRecords(planId); + + // 断言:节假日停班,2 天 × 2 班次 = 4 条排班记录 + List records = getRecords(planId); + assertEquals(4, records.size()); + // 断言:周期起点前,A 组白班、B 组夜班 + assertRecord(records.get(0), startDate.atStartOfDay(), 1, 101L, 11L); + assertRecord(records.get(1), startDate.atStartOfDay(), 2, 102L, 12L); + // 断言:周期起点虽为节假日,仍然换班:B 组白班、A 组夜班 + assertRecord(records.get(2), endDate.atStartOfDay(), 1, 102L, 11L); + assertRecord(records.get(3), endDate.atStartOfDay(), 2, 101L, 12L); + } + + private void mockPlan(Long planId, MesCalShiftTypeEnum shiftType, MesCalShiftMethodEnum shiftMethod, + Integer shiftCount, LocalDate startDate, LocalDate endDate) { + when(planService.getPlan(planId)).thenReturn(MesCalPlanDO.builder() + .id(planId).code("PLAN-" + planId).name("排班计划" + planId) + .calendarType(1).startDate(startDate.atStartOfDay()).endDate(endDate.atStartOfDay()) + .shiftType(shiftType.getType()) + .shiftMethod(shiftMethod != null ? shiftMethod.getMethod() : null) + .shiftCount(shiftCount).build()); + } + + private void mockTwoShifts(Long planId, String dayStartTime, String dayEndTime, + String nightStartTime, String nightEndTime) { + when(planShiftService.getPlanShiftListByPlanId(planId)).thenReturn(ListUtil.of( + MesCalPlanShiftDO.builder().id(11L).planId(planId).sort(1).name("白班") + .startTime(dayStartTime).endTime(dayEndTime).build(), + MesCalPlanShiftDO.builder().id(12L).planId(planId).sort(2).name("夜班") + .startTime(nightStartTime).endTime(nightEndTime).build())); + } + + private void mockTeams(Long planId, Long... teamIds) { + List teams = new ArrayList<>(); + for (int i = 0; i < teamIds.length; i++) { + teams.add(MesCalPlanTeamDO.builder().id(21L + i).planId(planId).teamId(teamIds[i]).build()); + } + when(planTeamService.getPlanTeamListByPlanId(planId)).thenReturn(teams); + } + + private void mockHolidays(LocalDate startDate, LocalDate endDate, MesCalHolidayDO... holidays) { + when(holidayService.getHolidayList(startDate.atStartOfDay(), endDate.atTime(23, 59, 59))) + .thenReturn(ListUtil.of(holidays)); + } + + private static MesCalHolidayDO buildHoliday(LocalDate day, MesCalHolidayTypeEnum type) { + return MesCalHolidayDO.builder().day(day.atStartOfDay()).type(type.getType()).build(); + } + + private List getRecords(Long planId) { + List records = teamShiftMapper.selectListByPlanId(planId); + records.sort(Comparator.comparing(MesCalTeamShiftDO::getDay).thenComparing(MesCalTeamShiftDO::getSort)); + return records; + } + private static void assertRecord(MesCalTeamShiftDO actual, LocalDateTime day, Integer sort, Long teamId, Long shiftId) { assertEquals(day, actual.getDay()); diff --git a/yudao-module-mes/src/test/resources/sql/clean.sql b/yudao-module-mes/src/test/resources/sql/clean.sql index 8cb28c3..106ff8d 100644 --- a/yudao-module-mes/src/test/resources/sql/clean.sql +++ b/yudao-module-mes/src/test/resources/sql/clean.sql @@ -2,6 +2,7 @@ DELETE FROM "mes_cal_team_shift"; DELETE FROM "mes_cal_plan_team"; DELETE FROM "mes_cal_plan_shift"; DELETE FROM "mes_cal_plan"; +DELETE FROM "mes_cal_holiday"; DELETE FROM "mes_md_auto_code_rule"; DELETE FROM "mes_md_auto_code_part"; DELETE FROM "mes_md_auto_code_record"; diff --git a/yudao-module-mes/src/test/resources/sql/create_tables.sql b/yudao-module-mes/src/test/resources/sql/create_tables.sql index fd73613..23fe4c2 100644 --- a/yudao-module-mes/src/test/resources/sql/create_tables.sql +++ b/yudao-module-mes/src/test/resources/sql/create_tables.sql @@ -80,6 +80,23 @@ CREATE TABLE IF NOT EXISTS "mes_cal_team_shift" ( ); -- ---------------------------- +-- MES 假期设置 +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "mes_cal_holiday" ( + "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY, + "day" timestamp DEFAULT NULL, + "type" tinyint DEFAULT NULL, + "remark" varchar(500) DEFAULT NULL, + "creator" varchar(64) DEFAULT '', + "create_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updater" varchar(64) DEFAULT '', + "update_time" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted" bit NOT NULL DEFAULT FALSE, + "tenant_id" bigint NOT NULL DEFAULT 0, + PRIMARY KEY ("id") +); + +-- ---------------------------- -- MES 编码规则表 -- ---------------------------- CREATE TABLE IF NOT EXISTS "mes_md_auto_code_rule" ( diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java index 1cb3625..18f29b5 100755 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java index 8794086..0e8ddf6 100755 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java index 5c2ac3f..4bd9a7f 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java @@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.Map; diff --git a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemImportExcelVO.java b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemImportExcelVO.java index faff648..e7b89ee 100644 --- a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemImportExcelVO.java +++ b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemImportExcelVO.java @@ -1,7 +1,5 @@ package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -15,6 +13,8 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemRespVO.java b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemRespVO.java index 92d5628..7677686 100644 --- a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemRespVO.java +++ b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/controller/admin/pm/workitem/vo/workitem/PmsWorkItemRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.workitem; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.module.pms.controller.admin.pm.workitem.vo.label.PmsWorkItemLabelRespVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectService.java b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectService.java index 560dff7..8330577 100644 --- a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectService.java +++ b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectService.java @@ -45,6 +45,16 @@ public interface PmsProjectService { PmsProjectDO getProject(Long id); /** + * 获得项目,并锁定项目行 + * + * 需在事务中调用,锁保持至事务结束 + * + * @param id 项目编号 + * @return 项目 + */ + PmsProjectDO getProjectForUpdate(Long id); + + /** * 获得项目详情并记录访问时间 * * @param id 项目编号 diff --git a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImpl.java b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImpl.java index 8674dc8..bef6c65 100644 --- a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImpl.java +++ b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImpl.java @@ -118,6 +118,11 @@ public class PmsProjectServiceImpl implements PmsProjectService { } @Override + public PmsProjectDO getProjectForUpdate(Long id) { + return projectMapper.selectOneForUpdate(PmsProjectDO::getId, id); + } + + @Override public PmsProjectDO getProjectAndUpdateVisitTime(Long id, Long userId) { // 1. 校验当前用户可以查看项目 PmsProjectDO project = projectMemberService.validateProjectReadable(id, userId); @@ -307,8 +312,11 @@ public class PmsProjectServiceImpl implements PmsProjectService { @Override @Transactional(rollbackFor = Exception.class) public void deleteProject(Long id, Long userId) { - // 1.1 校验项目存在 - PmsProjectDO project = validateProjectExists(id); + // 1.1 锁定项目并校验存在,与个人排序保持一致的加锁顺序(https://t.zsxq.com/V48Hl) + PmsProjectDO project = getProjectForUpdate(id); + if (project == null) { + throw exception(PROJECT_NOT_EXISTS); + } // 1.2 校验项目位于回收站 if (ObjectUtil.notEqual(PmsProjectStatusEnum.RECYCLED.getStatus(), project.getStatus())) { throw exception(PROJECT_STATUS_INVALID); diff --git a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImpl.java b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImpl.java index c40f3db..652b38a 100644 --- a/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImpl.java +++ b/yudao-module-pms/src/main/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImpl.java @@ -1,10 +1,14 @@ package cn.iocoder.yudao.module.pms.service.pm.workitem; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.project.PmsProjectDO; import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemDO; import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemUserSortDO; import cn.iocoder.yudao.module.pms.dal.mysql.pm.workitem.PmsWorkItemUserSortMapper; +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectStatusEnum; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; @@ -13,7 +17,10 @@ import java.util.Comparator; import java.util.List; import java.util.Map; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_NOT_EXISTS; +import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_STATUS_INVALID; /** * PMS 工作项个人排序 Service 实现类 @@ -27,13 +34,27 @@ public class PmsWorkItemUserSortServiceImpl implements PmsWorkItemUserSortServic @Resource private PmsWorkItemUserSortMapper workItemUserSortMapper; + @Lazy // 延迟加载,避免循环依赖 + @Resource + private PmsProjectService projectService; + @Override @Transactional(rollbackFor = Exception.class) public void updateWorkItemUserSort(Long projectId, List workItemIds, Long userId) { - // 1. 删除原有个人排序 + // 1.1 锁定项目,避免并发更新个人排序产生重复记录(https://t.zsxq.com/V48Hl) + PmsProjectDO project = projectService.getProjectForUpdate(projectId); + // 1.2 校验锁定后的项目状态,避免项目并发回收、删除后继续写入个人排序 + if (project == null) { + throw exception(PROJECT_NOT_EXISTS); + } + if (!PmsProjectStatusEnum.ACTIVE.getStatus().equals(project.getStatus())) { + throw exception(PROJECT_STATUS_INVALID); + } + + // 2. 删除原有个人排序 workItemUserSortMapper.deleteByProjectIdAndUserId(projectId, userId); - // 2. 按请求顺序保存个人排序 + // 3. 按请求顺序保存个人排序 for (int index = 0; index < workItemIds.size(); index++) { workItemUserSortMapper.insert(new PmsWorkItemUserSortDO().setProjectId(projectId) .setWorkItemId(workItemIds.get(index)).setUserId(userId).setSort(index + 1)); diff --git a/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImplTest.java b/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImplTest.java index ffecc25..3fc1f8d 100644 --- a/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImplTest.java +++ b/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/project/PmsProjectServiceImplTest.java @@ -33,6 +33,7 @@ import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServic import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_ADMIN_REQUIRED; +import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_NOT_EXISTS; import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_OWNER_REQUIRED; import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_STATUS_INVALID; import static java.util.Arrays.asList; @@ -237,6 +238,35 @@ public class PmsProjectServiceImplTest extends BaseDbUnitTest { } @Test + public void testDeleteProject_success() { + // mock 数据 + Long userId = randomLongId(); + PmsProjectDO project = randomProjectDO(PmsProjectStatusEnum.RECYCLED.getStatus()); + projectMapper.insert(project); + when(projectMemberService.hasProjectOwnerPermission(project.getId(), userId)).thenReturn(true); + + // 调用 + projectService.deleteProject(project.getId(), userId); + + // 断言 + assertNull(projectMapper.selectById(project.getId())); + verify(workItemWorkLogService).deleteWorkItemWorkLogListByProjectId(project.getId()); + verify(workItemService).deleteWorkItemListByProjectId(project.getId()); + verify(iterationService).deleteIterationListByProjectId(project.getId()); + verify(projectMemberService).deleteProjectMemberListByProjectId(project.getId()); + } + + @Test + public void testDeleteProject_projectNotExists() { + // 准备参数 + Long projectId = randomLongId(); + Long userId = randomLongId(); + + // 调用,并断言异常 + assertServiceException(() -> projectService.deleteProject(projectId, userId), PROJECT_NOT_EXISTS); + } + + @Test public void testDeleteProject_statusInvalid() { // mock 数据 Long userId = randomLongId(); diff --git a/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemServiceImplTest.java b/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemServiceImplTest.java index 0dfd682..ccb16ae 100644 --- a/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemServiceImplTest.java +++ b/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemServiceImplTest.java @@ -24,6 +24,7 @@ import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemMemberD import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemStatusDO; import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemUserSortDO; import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemWorkLogDO; +import cn.iocoder.yudao.module.pms.dal.mysql.pm.project.PmsProjectMapper; import cn.iocoder.yudao.module.pms.dal.mysql.pm.workitem.PmsWorkItemBoardMapper; import cn.iocoder.yudao.module.pms.dal.mysql.pm.workitem.PmsWorkItemCommentMapper; import cn.iocoder.yudao.module.pms.dal.mysql.pm.workitem.PmsWorkItemMapper; @@ -39,9 +40,14 @@ import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemPriorityEnum; import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemStatusTypeEnum; import cn.iocoder.yudao.module.pms.enums.pm.workitem.PmsWorkItemTypeEnum; import cn.iocoder.yudao.module.pms.service.pm.iteration.PmsIterationService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectAnnouncementService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectFavoriteService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectGroupService; import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectMemberService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectServiceImpl; import cn.iocoder.yudao.module.system.api.notify.NotifyMessageSendApi; import cn.iocoder.yudao.module.system.api.notify.dto.NotifySendSingleToUserReqDTO; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; @@ -88,7 +94,8 @@ import static org.mockito.Mockito.when; * * @author 芋道源码 */ -@Import({PmsWorkItemServiceImpl.class, PmsWorkItemUserSortServiceImpl.class, PmsWorkItemStatusServiceImpl.class, +@Import({PmsWorkItemServiceImpl.class, PmsWorkItemUserSortServiceImpl.class, PmsProjectServiceImpl.class, + PmsWorkItemStatusServiceImpl.class, PmsWorkItemBoardServiceImpl.class, PmsWorkItemCommentServiceImpl.class, PmsWorkItemWorkLogServiceImpl.class}) public class PmsWorkItemServiceImplTest extends BaseDbUnitTest { @@ -110,10 +117,18 @@ public class PmsWorkItemServiceImplTest extends BaseDbUnitTest { private PmsWorkItemWorkLogMapper workItemWorkLogMapper; @Resource private PmsWorkItemUserSortMapper workItemUserSortMapper; + @Resource + private PmsProjectMapper projectMapper; @MockitoBean private PmsProjectMemberService projectMemberService; @MockitoBean + private PmsProjectGroupService projectGroupService; + @MockitoBean + private PmsProjectFavoriteService projectFavoriteService; + @MockitoBean + private PmsProjectAnnouncementService projectAnnouncementService; + @MockitoBean private PmsIterationService iterationService; @MockitoBean private PmsWorkItemLabelService workItemLabelService; @@ -126,6 +141,8 @@ public class PmsWorkItemServiceImplTest extends BaseDbUnitTest { private NotifyMessageSendApi notifyMessageSendApi; @MockitoBean private AdminUserApi adminUserApi; + @MockitoBean + private PermissionApi permissionApi; @Test public void testCreateWorkItem_success() { @@ -510,6 +527,8 @@ public class PmsWorkItemServiceImplTest extends BaseDbUnitTest { // mock 数据 Long userId = randomLongId(); Long projectId = randomLongId(); + PmsProjectDO project = randomProjectDO(projectId, PmsProjectTypeEnum.AGILE.getType()); + projectMapper.insert(project); PmsWorkItemStatusDO taskStatus = randomStatusDO(projectId, PmsWorkItemTypeEnum.TASK.getType(), PmsWorkItemStatusTypeEnum.PENDING.getType(), true, 1); workItemStatusMapper.insert(taskStatus); @@ -521,7 +540,7 @@ public class PmsWorkItemServiceImplTest extends BaseDbUnitTest { PmsWorkItemDO second = randomWorkItemDO(projectId, PmsWorkItemTypeEnum.DEFECT.getType(), defectStatus, 2); workItemMapper.insert(second); when(projectMemberService.validateProjectWritable(projectId, userId)) - .thenReturn(randomProjectDO(projectId, PmsProjectTypeEnum.AGILE.getType())); + .thenReturn(project); // 准备参数 PmsWorkItemPlanningSortReqVO reqVO = new PmsWorkItemPlanningSortReqVO().setProjectId(projectId) .setWorkItemIds(Arrays.asList(second.getId(), first.getId())); diff --git a/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImplTest.java b/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImplTest.java index ac05d72..cb22fcf 100644 --- a/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImplTest.java +++ b/yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImplTest.java @@ -5,8 +5,18 @@ import cn.iocoder.yudao.framework.tenant.config.TenantProperties; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.framework.tenant.core.db.TenantDatabaseInterceptor; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.pms.dal.dataobject.pm.project.PmsProjectDO; import cn.iocoder.yudao.module.pms.dal.dataobject.pm.workitem.PmsWorkItemUserSortDO; +import cn.iocoder.yudao.module.pms.dal.mysql.pm.project.PmsProjectMapper; import cn.iocoder.yudao.module.pms.dal.mysql.pm.workitem.PmsWorkItemUserSortMapper; +import cn.iocoder.yudao.module.pms.enums.pm.project.PmsProjectStatusEnum; +import cn.iocoder.yudao.module.pms.service.pm.iteration.PmsIterationService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectAnnouncementService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectFavoriteService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectGroupService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectMemberService; +import cn.iocoder.yudao.module.pms.service.pm.project.PmsProjectServiceImpl; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.TenantLineInnerInterceptor; import jakarta.annotation.Resource; @@ -17,15 +27,25 @@ import org.springframework.boot.test.context.TestConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Import; import org.springframework.jdbc.core.JdbcTemplate; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import javax.sql.DataSource; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_NOT_EXISTS; +import static cn.iocoder.yudao.module.pms.enums.ErrorCodeConstants.PROJECT_STATUS_INVALID; import static org.junit.jupiter.api.Assertions.assertEquals; /** @@ -33,18 +53,41 @@ import static org.junit.jupiter.api.Assertions.assertEquals; * * @author 芋道源码 */ -@Import({PmsWorkItemUserSortServiceImpl.class, PmsWorkItemUserSortServiceImplTest.TenantTestConfiguration.class}) +@Import({PmsWorkItemUserSortServiceImpl.class, PmsProjectServiceImpl.class, + PmsWorkItemUserSortServiceImplTest.TenantTestConfiguration.class}) public class PmsWorkItemUserSortServiceImplTest extends BaseDbUnitTest { @Resource private PmsWorkItemUserSortServiceImpl workItemUserSortService; + @Resource private PmsWorkItemUserSortMapper workItemUserSortMapper; @Resource + private PmsProjectMapper projectMapper; + @Resource private JdbcTemplate jdbcTemplate; @Resource private TenantLineInnerInterceptor tenantLineInnerInterceptor; + @MockitoBean + private PmsProjectMemberService projectMemberService; + @MockitoBean + private PmsProjectGroupService projectGroupService; + @MockitoBean + private PmsProjectFavoriteService projectFavoriteService; + @MockitoBean + private PmsProjectAnnouncementService projectAnnouncementService; + @MockitoBean + private PmsIterationService iterationService; + @MockitoBean + private PmsWorkItemService workItemService; + @MockitoBean + private PmsWorkItemStatusService workItemStatusService; + @MockitoBean + private PmsWorkItemWorkLogService workItemWorkLogService; + @MockitoBean + private PermissionApi permissionApi; + @BeforeEach public void before() { TenantContextHolder.setTenantId(0L); @@ -56,9 +99,33 @@ public class PmsWorkItemUserSortServiceImplTest extends BaseDbUnitTest { } @Test + public void testUpdateWorkItemUserSort_success() { + // mock 数据 + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1); + projectMapper.insert(project); + workItemUserSortService.updateWorkItemUserSort(project.getId(), List.of(50L, 51L), 238L); + workItemUserSortService.updateWorkItemUserSort(project.getId(), List.of(50L, 51L), 239L); + + // 调用:连续调整个人排序,并移除不再位于待规划区域的工作项 + workItemUserSortService.updateWorkItemUserSort(project.getId(), List.of(51L, 50L), 238L); + workItemUserSortService.updateWorkItemUserSort(project.getId(), List.of(50L), 238L); + + // 断言:仅保留当前顺序,不影响其他用户的个人排序 + List userSorts = workItemUserSortMapper + .selectListByProjectIdAndUserId(project.getId(), 238L); + assertEquals(List.of(50L), convertList(userSorts, PmsWorkItemUserSortDO::getWorkItemId)); + assertEquals(1, userSorts.get(0).getSort()); + assertEquals(List.of(50L, 51L), convertList(workItemUserSortMapper + .selectListByProjectIdAndUserId(project.getId(), 239L), PmsWorkItemUserSortDO::getWorkItemId)); + } + + @Test public void testUpdateWorkItemUserSort_repeated() { + // mock 数据 + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1); + projectMapper.insert(project); // 准备参数 - Long projectId = randomLongId(); + Long projectId = project.getId(); Long userId = randomLongId(); Long firstId = randomLongId(); Long secondId = randomLongId(); @@ -78,7 +145,9 @@ public class PmsWorkItemUserSortServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateWorkItemUserSort_deletedRecords() { // mock 数据 - Long projectId = randomLongId(); + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1); + projectMapper.insert(project); + Long projectId = project.getId(); Long userId = randomLongId(); Long workItemId = randomLongId(); insertUserSort(projectId, workItemId, userId, false); @@ -99,7 +168,9 @@ public class PmsWorkItemUserSortServiceImplTest extends BaseDbUnitTest { @Test public void testUpdateWorkItemUserSort_empty() { // mock 数据 - Long projectId = randomLongId(); + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1); + projectMapper.insert(project); + Long projectId = project.getId(); Long userId = randomLongId(); Long workItemId = randomLongId(); insertUserSort(projectId, workItemId, userId, false); @@ -113,6 +184,87 @@ public class PmsWorkItemUserSortServiceImplTest extends BaseDbUnitTest { } @Test + public void testUpdateWorkItemUserSort_projectNotExists() { + // 调用,并断言异常 + assertServiceException(() -> workItemUserSortService.updateWorkItemUserSort(999L, + List.of(50L), 238L), PROJECT_NOT_EXISTS); + assertEquals(0L, workItemUserSortMapper.selectCount()); + } + + @Test + public void testUpdateWorkItemUserSort_projectDeleted() { + // mock 数据 + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1); + projectMapper.insert(project); + projectMapper.deleteById(project.getId()); + + // 调用,并断言异常 + assertServiceException(() -> workItemUserSortService.updateWorkItemUserSort(project.getId(), + List.of(50L), 238L), PROJECT_NOT_EXISTS); + assertEquals(0L, workItemUserSortMapper.selectCount()); + } + + @Test + public void testUpdateWorkItemUserSort_projectStatusInvalid() { + // mock 数据 + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1) + .setStatus(PmsProjectStatusEnum.RECYCLED.getStatus()); + projectMapper.insert(project); + workItemUserSortMapper.insert(new PmsWorkItemUserSortDO().setProjectId(project.getId()) + .setWorkItemId(50L).setUserId(238L).setSort(1)); + + // 调用,并断言异常 + assertServiceException(() -> workItemUserSortService.updateWorkItemUserSort(project.getId(), + List.of(51L), 238L), PROJECT_STATUS_INVALID); + // 断言:拒绝更新时保留原有个人排序 + assertEquals(List.of(50L), convertList(workItemUserSortMapper + .selectListByProjectIdAndUserId(project.getId(), 238L), PmsWorkItemUserSortDO::getWorkItemId)); + } + + @Test + public void testUpdateWorkItemUserSort_concurrent() throws Exception { + // mock 数据 + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1); + projectMapper.insert(project); + // 准备参数 + CountDownLatch startLatch = new CountDownLatch(1); + ExecutorService executor = Executors.newFixedThreadPool(4); + List> futures = new ArrayList<>(); + + // 调用:同一项目、同一用户并发保存个人排序 + try { + for (int index = 0; index < 4; index++) { + futures.add(executor.submit(() -> { + // 工作线程使用与测试线程相同的租户,结束后清理,避免租户上下文残留 + TenantContextHolder.setTenantId(0L); + try { + startLatch.await(); + for (int count = 0; count < 5; count++) { + workItemUserSortService.updateWorkItemUserSort(project.getId(), List.of(51L, 50L), 238L); + } + return null; + } finally { + TenantContextHolder.clear(); + } + })); + } + startLatch.countDown(); + for (Future> future : futures) { + future.get(20, TimeUnit.SECONDS); + } + } finally { + executor.shutdownNow(); + executor.awaitTermination(10, TimeUnit.SECONDS); + } + + // 断言:没有重复的有效记录,顺序与最后一次保存一致 + List userSorts = workItemUserSortMapper + .selectListByProjectIdAndUserId(project.getId(), 238L); + assertEquals(List.of(51L, 50L), convertList(userSorts, PmsWorkItemUserSortDO::getWorkItemId)); + assertEquals(List.of(1, 2), convertList(userSorts, PmsWorkItemUserSortDO::getSort)); + } + + @Test public void testDeleteWorkItemUserSortByWorkItemId_success() { // mock 数据 Long projectId = randomLongId(); @@ -151,7 +303,9 @@ public class PmsWorkItemUserSortServiceImplTest extends BaseDbUnitTest { @Test public void testDeleteWorkItemUserSort_tenantIsolation() { // mock 数据:两个租户使用相同的业务编号 - Long projectId = randomLongId(); + PmsProjectDO project = new PmsProjectDO().setName("测试项目").setType(1).setLevel(1); + projectMapper.insert(project); + Long projectId = project.getId(); Long userId = randomLongId(); Long workItemId = randomLongId(); insertUserSort(projectId, workItemId, userId, false); diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java index 18ccb7f..d03c545 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java index d019ad7..9f73a41 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; @Schema(description = "管理后台 - 岗位信息的精简 Response VO") @Data diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java index fce51e9..fa6899c 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java index 2301a75..684a16e 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java index 9abe3aa..40004ff 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java index df4334c..64f79f5 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import org.dromara.core.trans.anno.Trans; import org.dromara.core.trans.constant.TransType; import org.dromara.core.trans.vo.VO; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java index c1c7cfe..00a4c76 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.Set; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java index 66a867f..641a879 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.Map; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java index 9caed5c..6dba709 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index dd91812..b2a7eff 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java index f6400e1..fec2e8f 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; @@ -8,6 +7,7 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * 用户 Excel 导入 VO diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java index ba32224..1da6d30 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.Set; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java index a47d7fe..03a46ba 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImpl.java @@ -63,7 +63,7 @@ public class NotifySendServiceImpl implements NotifySendService { NotifyTemplateDO template = notifyTemplateService.getNotifyTemplateByCodeFromCache(templateCode); // 站内信模板不存在 if (template == null) { - throw exception(NOTICE_NOT_FOUND); + throw exception(NOTIFY_TEMPLATE_NOT_EXISTS); } return template; } diff --git a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java index 9dbdac4..c4d39e7 100644 --- a/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java +++ b/yudao-module-system/src/test/java/cn/iocoder/yudao/module/system/service/notify/NotifySendServiceImplTest.java @@ -17,8 +17,8 @@ import java.util.Map; import static cn.hutool.core.util.RandomUtil.randomEle; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTICE_NOT_FOUND; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_SEND_TEMPLATE_PARAM_MISS; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.NOTIFY_TEMPLATE_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNull; import static org.mockito.ArgumentMatchers.eq; @@ -150,14 +150,32 @@ class NotifySendServiceImplTest extends BaseMockitoUnitTest { } @Test - public void testCheckMailTemplateValid_notExists() { + public void testSendSingleNotifyToAdmin_templateNotExists() { + // 准备参数 + Long userId = randomLongId(); + String templateCode = randomString(); + Map templateParams = MapUtil.builder().put("code", "1234") + .put("op", "login").build(); + // mock NotifyTemplateService 的方法 + when(notifyTemplateService.getNotifyTemplateByCodeFromCache(eq(templateCode))).thenReturn(null); + + // 调用,并断言异常 + assertServiceException(() -> notifySendService.sendSingleNotifyToAdmin(userId, templateCode, templateParams), + NOTIFY_TEMPLATE_NOT_EXISTS); + // 断言 + verify(notifyTemplateService, never()).formatNotifyTemplateContent(anyString(), anyMap()); + verify(notifyMessageService, never()).createNotifyMessage(anyLong(), anyInt(), any(), anyString(), anyMap()); + } + + @Test + public void testValidateNotifyTemplate_notExists() { // 准备参数 String templateCode = randomString(); // mock 方法 // 调用,并断言异常 assertServiceException(() -> notifySendService.validateNotifyTemplate(templateCode), - NOTICE_NOT_FOUND); + NOTIFY_TEMPLATE_NOT_EXISTS); } @Test diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/brand/WmsItemBrandRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/brand/WmsItemBrandRespVO.java index bc68efe..377b125 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/brand/WmsItemBrandRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/brand/WmsItemBrandRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.brand; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/item/WmsItemRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/item/WmsItemRespVO.java index d4e7416..870e398 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/item/WmsItemRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/item/vo/item/WmsItemRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.item; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.module.wms.controller.admin.md.item.vo.sku.WmsItemSkuRespVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/merchant/vo/WmsMerchantRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/merchant/vo/WmsMerchantRespVO.java index c88c876..e9db783 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/merchant/vo/WmsMerchantRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/merchant/vo/WmsMerchantRespVO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.wms.controller.admin.md.merchant.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.wms.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/warehouse/vo/WmsWarehouseRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/warehouse/vo/WmsWarehouseRespVO.java index 67c16bf..4707711 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/warehouse/vo/WmsWarehouseRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/md/warehouse/vo/WmsWarehouseRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.wms.controller.admin.md.warehouse.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/check/vo/order/WmsCheckOrderRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/check/vo/order/WmsCheckOrderRespVO.java index 962de82..fda01b1 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/check/vo/order/WmsCheckOrderRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/check/vo/order/WmsCheckOrderRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.wms.controller.admin.order.check.vo.detail.WmsCheckOrderDetailRespVO; import cn.iocoder.yudao.module.wms.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/movement/vo/order/WmsMovementOrderRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/movement/vo/order/WmsMovementOrderRespVO.java index ecad02e..2ab6328 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/movement/vo/order/WmsMovementOrderRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/movement/vo/order/WmsMovementOrderRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.wms.controller.admin.order.movement.vo.detail.WmsMovementOrderDetailRespVO; import cn.iocoder.yudao.module.wms.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/receipt/vo/order/WmsReceiptOrderRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/receipt/vo/order/WmsReceiptOrderRespVO.java index 24d3b04..cceb943 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/receipt/vo/order/WmsReceiptOrderRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/receipt/vo/order/WmsReceiptOrderRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.wms.controller.admin.order.receipt.vo.detail.WmsReceiptOrderDetailRespVO; import cn.iocoder.yudao.module.wms.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/order/WmsShipmentOrderRespVO.java b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/order/WmsShipmentOrderRespVO.java index b391c1d..a708394 100644 --- a/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/order/WmsShipmentOrderRespVO.java +++ b/yudao-module-wms/src/main/java/cn/iocoder/yudao/module/wms/controller/admin/order/shipment/vo/order/WmsShipmentOrderRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.wms.controller.admin.order.shipment.vo.detail.WmsShipmentOrderDetailRespVO; import cn.iocoder.yudao.module.wms.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-wms/src/main/resources/mapper/home/WmsHomeStatisticsMapper.xml b/yudao-module-wms/src/main/resources/mapper/home/WmsHomeStatisticsMapper.xml index 38c7bdf..59813e9 100644 --- a/yudao-module-wms/src/main/resources/mapper/home/WmsHomeStatisticsMapper.xml +++ b/yudao-module-wms/src/main/resources/mapper/home/WmsHomeStatisticsMapper.xml @@ -3,7 +3,7 @@ - + SELECT orderType, status, SUM(count) AS count FROM ( SELECT ${@cn.iocoder.yudao.module.wms.enums.order.WmsOrderTypeEnum@RECEIPT.type} AS orderType, @@ -51,7 +51,7 @@ - + SELECT date, orderType, SUM(count) AS count FROM ( SELECT DATE_FORMAT(order_time, '%Y-%m-%d') AS date, @@ -117,7 +117,7 @@ - + SELECT item.id AS id, item.name AS name, IFNULL(SUM(inventory.quantity), 0) AS quantity @@ -135,7 +135,7 @@ - + SELECT warehouse.id AS id, warehouse.name AS name, IFNULL(SUM(inventory.quantity), 0) AS quantity diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 98fc077..9cfdf92 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -55,6 +55,24 @@ spring: url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例 username: root password: 123456 +# tdengine: # IoT 数据库(需要 IoT 物联网,且 yudao.iot.storage.type 为 tdengine 再开启噢!) +# lazy: true # 开启懒加载,保证启动速度 +# url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro?varcharAsString=true&enableAutoReconnect=true # 参见:https://t.zsxq.com/qaX9c,开启 TDengine WebSocket 自动重连 +# driver-class-name: com.taosdata.jdbc.ws.WebSocketDriver +# username: root +# password: taosdata +# druid: +# validation-query: SELECT SERVER_STATUS() # TDengine 数据源的有效性检查 SQL +# iotdb: # IoT 数据库(需要 IoT 物联网,且 yudao.iot.storage.type 为 iotdb 再开启噢!) +# lazy: true # 开启懒加载,保证启动速度 +# type: com.zaxxer.hikari.HikariDataSource # IoTDB 不使用 Druid 连接池 +# url: jdbc:iotdb://127.0.0.1:6667/ruoyi_vue_pro?sql_dialect=table # 表模型;数据库需要预先创建,且时间精度为 ms +# driver-class-name: org.apache.iotdb.jdbc.IoTDBDriver +# username: root +# password: root +# hikari: +# maximum-pool-size: 8 +# connection-test-query: SELECT 1 # IoTDB 数据源的有效性检查 SQL # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 7170af9..38245d8 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -71,7 +71,7 @@ spring: url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true username: root password: 123456 -# tdengine: # IoT 数据库(需要 IoT 物联网再开启噢!) +# tdengine: # IoT 数据库(需要 IoT 物联网,且 yudao.iot.storage.type 为 tdengine 再开启噢!) # lazy: true # 开启懒加载,保证启动速度 # url: jdbc:TAOS-WS://127.0.0.1:6041/ruoyi_vue_pro?varcharAsString=true&enableAutoReconnect=true # 参见:https://t.zsxq.com/qaX9c,开启 TDengine WebSocket 自动重连 # driver-class-name: com.taosdata.jdbc.ws.WebSocketDriver @@ -79,6 +79,16 @@ spring: # password: taosdata # druid: # validation-query: SELECT SERVER_STATUS() # TDengine 数据源的有效性检查 SQL +# iotdb: # IoT 数据库(需要 IoT 物联网,且 yudao.iot.storage.type 为 iotdb 再开启噢!) +# lazy: true # 开启懒加载,保证启动速度 +# type: com.zaxxer.hikari.HikariDataSource # IoTDB 不使用 Druid 连接池 +# url: jdbc:iotdb://127.0.0.1:6667/ruoyi_vue_pro?sql_dialect=table # 表模型;数据库需要预先创建,且时间精度为 ms +# driver-class-name: org.apache.iotdb.jdbc.IoTDBDriver +# username: root +# password: root +# hikari: +# maximum-pool-size: 8 +# connection-test-query: SELECT 1 # IoTDB 数据源的有效性检查 SQL # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 data: diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 6a64a10..3f49e16 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -368,5 +368,7 @@ yudao: iot: message-bus: type: redis # 消息总线的类型 + storage: + type: tdengine # 时序存储的类型:tdengine、iotdb,需要配置同名的 spring.datasource.dynamic.datasource 数据源 debug: false
>> P selectJoinMapsPage(P page, @Param(Constants.WRAPPER) MPJBaseJoin wrapper) { + return (P) selectJoinPage((IPage) page, CaseInsensitiveResultMap.class, wrapper); + } + default T selectOne(String field, Object value) { return selectOne(new QueryWrapper().eq(field, value)); } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMap.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMap.java new file mode 100644 index 0000000..2d1243b --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMap.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import org.springframework.util.LinkedCaseInsensitiveMap; + +import java.util.Locale; + +/** + * key 大小写不敏感的 MyBatis 查询结果 Map + * + * 背景:使用 Map 接收查询结果时,key 为 JDBC 返回的列标签。PostgreSQL 等会将未加引号的列名、别名折叠为小写, + * Oracle、达梦等会折叠为大写,导致 map.get("conversationId") 这类按固定 key 取值的代码,在 MySQL 以外的数据库取不到值。 + * + * 实现:基于 {@link LinkedCaseInsensitiveMap},get / containsKey / remove 时忽略 key 的大小写, + * 同时保留原始的列标签作为 key(遍历、序列化时不变)。固定使用 {@link Locale#ROOT},避免服务器默认 Locale(例如土耳其语)影响 key 的匹配。 + * + * 使用方式:由 MyBatis 直接创建结果行,Mapper 的返回类型仍声明为 Map,业务无需感知该类 + * 1. MyBatis Plus 的 selectMaps:由 YudaoSqlInjector 注入,自动使用该类 + * 2. MyBatis Plus Join 的 selectJoinMaps 等:由 BaseMapperX 覆盖,自动使用该类 + * 3. XML SQL:将 resultType 设置为该类 + * 4. 注解 SQL:添加 @ResultMap({@link #RESULT_MAP_ID}) + * + * 注意:仅大小写不同的多个 key,会合并为一个,保留后写入的 key 和值 + * + * @author 芋道源码 + * @see 星球讨论:Map 查询结果的跨数据库兼容问题 + */ +public class CaseInsensitiveResultMap extends LinkedCaseInsensitiveMap { + + /** + * 注解 SQL 使用的 resultMap 编号 + * + * 由 YudaoMybatisAutoConfiguration 注册到 MyBatis 全局配置;包含“.”,所以不会拼接 Mapper 的 namespace + */ + public static final String RESULT_MAP_ID = "cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap"; + + /** + * 创建空的结果 Map + * + * 用途:MyBatis 通过无参构造方法,实例化结果行 + */ + public CaseInsensitiveResultMap() { + super(Locale.ROOT); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMapTest.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMapTest.java new file mode 100644 index 0000000..700a340 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMapTest.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.framework.mybatis.core.util; + +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import org.junit.jupiter.api.Test; +import org.springframework.util.LinkedCaseInsensitiveMap; + +import java.util.*; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link CaseInsensitiveResultMap} 的单元测试 + * + * @author 芋道源码 + */ +public class CaseInsensitiveResultMapTest { + + @Test + public void testGet_ignoreCase() { + // 准备参数 + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + map.put("conversationId", 1024L); + + // 调用,并断言:PostgreSQL 小写、Oracle 大写,都可以取到值 + assertEquals(1024L, map.get("conversationId")); + assertEquals(1024L, map.get("conversationid")); + assertEquals(1024L, map.get("CONVERSATIONID")); + assertTrue(map.containsKey("CONVERSATIONID")); + assertEquals(1024L, MapUtil.getLong(map, "conversationid")); + // 断言:保留原始的 key + assertEquals(Collections.singletonList("conversationId"), new ArrayList<>(map.keySet())); + } + + @Test + public void testPut_nullValue() { + // 准备参数 + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + map.put("sum_count", null); + + // 调用,并断言 + assertTrue(map.containsKey("SUM_COUNT")); + assertNull(map.get("SUM_COUNT")); + assertEquals(0, MapUtil.getInt(map, "SUM_COUNT", 0)); + } + + @Test + public void testPut_sameKeyIgnoreCase() { + // 准备参数 + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + + // 调用:仅大小写不同的 key + map.put("id", 1L); + map.put("ID", 2L); + + // 断言:合并为一个,保留后写入的 key 和值 + assertEquals(1, map.size()); + assertEquals(2L, map.get("id")); + assertEquals(Collections.singletonList("ID"), new ArrayList<>(map.keySet())); + } + + @Test + public void testGet_turkishDefaultLocale() { + Locale defaultLocale = Locale.getDefault(); + try { + // 准备参数:土耳其语下,大写 I 转小写为无点的 ı + Locale.setDefault(Locale.forLanguageTag("tr-TR")); + CaseInsensitiveResultMap map = new CaseInsensitiveResultMap<>(); + map.put("CONVERSATIONID", 1024L); + LinkedCaseInsensitiveMap defaultLocaleMap = new LinkedCaseInsensitiveMap<>(); + defaultLocaleMap.put("CONVERSATIONID", 1024L); + + // 调用,并断言:固定 Locale.ROOT,不受默认 Locale 影响 + assertEquals(1024L, map.get("conversationId")); + // 断言:使用默认 Locale 时,取不到值 + assertNull(defaultLocaleMap.get("conversationId")); + } finally { + Locale.setDefault(defaultLocale); + } + } + + @Test + public void testConvertMap_numberKey() { + // 准备参数:模拟 Oracle 返回的结果行 + List> rows = Arrays.asList(buildRow(1024L, 3), buildRow(2048L, 5)); + + // 调用:业务转换为数字 key 的 Map + Map result = CollectionUtils.convertMap(rows, + row -> MapUtil.getLong(row, "conversationId"), + row -> MapUtil.getInt(row, "count")); + + // 断言:数字 key 的业务 Map 不受影响 + assertInstanceOf(HashMap.class, result); + assertEquals(3, result.get(1024L)); + assertEquals(5, result.get(2048L)); + } + + private static Map buildRow(Long conversationId, Integer count) { + CaseInsensitiveResultMap row = new CaseInsensitiveResultMap<>(); + row.put("CONVERSATIONID", conversationId); + row.put("COUNT", count); + return row; + } + +} diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImplTest.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImplTest.java new file mode 100644 index 0000000..b1d0f02 --- /dev/null +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImplTest.java @@ -0,0 +1,387 @@ +package cn.iocoder.yudao.module.ai.service.chat; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.security.core.LoginUser; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO; +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO; +import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper; +import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService; +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; +import cn.iocoder.yudao.module.ai.service.model.AiModelService; +import cn.iocoder.yudao.module.ai.service.model.AiToolService; +import lombok.Data; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.springframework.ai.chat.model.ToolContext; +import org.springframework.ai.deepseek.DeepSeekChatModel; +import org.springframework.ai.deepseek.api.DeepSeekApi; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletion; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionChunk; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionFinishReason; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.ChatCompletionFunction; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.Role; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.ToolCall; +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionRequest; +import org.springframework.ai.tool.ToolCallback; +import org.springframework.ai.tool.function.FunctionToolCallback; +import org.springframework.ai.tool.resolution.ToolCallbackResolver; +import org.springframework.http.ResponseEntity; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.security.core.context.SecurityContextHolder; +import reactor.core.publisher.Flux; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicLong; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_STREAM_ERROR; +import static cn.iocoder.yudao.module.ai.util.AiUtils.TOOL_CONTEXT_LOGIN_USER; +import static cn.iocoder.yudao.module.ai.util.AiUtils.TOOL_CONTEXT_TENANT_ID; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.*; + +/** + * {@link AiChatMessageServiceImpl} 的单元测试类 + * + * 使用真实的 {@link DeepSeekChatModel} 和工具调用,仅 mock 底层的 {@link DeepSeekApi} + * + * @author 芋道源码 + */ +public class AiChatMessageServiceImplTest extends BaseMockitoUnitTest { + + private static final String MODEL_NAME = "deepseek-test"; + private static final Double TEMPERATURE = 0.5; + private static final Integer MAX_TOKENS = 1024; + + private static final String TOOL_NAME = "query_weather"; + private static final String TOOL_RESULT = "杭州:晴,25℃"; + private static final ChatCompletionMessage TOOL_CALL_MESSAGE = new ChatCompletionMessage("我来查询一下杭州的天气", + Role.ASSISTANT, null, null, singletonList(new ToolCall("call_1", "function", + new ChatCompletionFunction(TOOL_NAME, "{\"city\":\"杭州\"}")))); + + private static final List TOOL_ANSWER_CHUNKS = asList("杭州今天", "晴,25℃"); + private static final String TOOL_ANSWER = String.join("", TOOL_ANSWER_CHUNKS); + private static final List PLAIN_ANSWER_CHUNKS = asList("你好,", "我是 AI 助手"); + private static final String PLAIN_ANSWER = String.join("", PLAIN_ANSWER_CHUNKS); + + /** + * assistant 消息编号:先插入 user 消息(编号 1),再插入 assistant 消息(编号 2) + */ + private static final Long ASSISTANT_MESSAGE_ID = 2L; + + @InjectMocks + private AiChatMessageServiceImpl chatMessageService; + + @Mock + private AiChatMessageMapper chatMessageMapper; + @Mock + private AiChatConversationService chatConversationService; + @Mock + private AiChatRoleService chatRoleService; + @Mock + private AiModelService modalService; + @Mock + private AiKnowledgeDocumentService knowledgeDocumentService; + @Mock + private AiToolService toolService; + @Mock + private ToolCallbackResolver toolCallbackResolver; + @Mock + private DeepSeekApi deepSeekApi; + + @AfterEach + public void after() { + SecurityContextHolder.clearContext(); + TenantContextHolder.clear(); + } + + @Test + public void testSendMessage_toolCall() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + Long tenantId = randomLongId(); + mockLoginUser(userId, tenantId); + // mock deepSeekApi 的方法:先请求工具,再返回回答 + when(deepSeekApi.chatCompletionEntity(any())).thenReturn(buildChatCompletion(TOOL_CALL_MESSAGE), + buildChatCompletion(new ChatCompletionMessage(TOOL_ANSWER, Role.ASSISTANT))); + + // 调用 + AiChatMessageSendRespVO respVO = chatMessageService.sendMessage(reqVO, userId); + // 断言 + assertEquals(TOOL_ANSWER, respVO.getReceive().getContent()); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ChatCompletionRequest.class); + verify(deepSeekApi, times(2)).chatCompletionEntity(requestCaptor.capture()); + assertToolExecuted(requestCaptor.getAllValues(), toolContexts, userId, tenantId); + // 断言模型参数 + ChatCompletionRequest request = requestCaptor.getAllValues().get(0); + assertEquals(MODEL_NAME, request.model()); + assertEquals(TEMPERATURE, request.temperature()); + assertEquals(MAX_TOKENS, request.maxTokens()); + // 断言消息保存 + assertAssistantMessageUpdated(TOOL_ANSWER); + } + + @Test + public void testSendMessage_withoutTool() { + // 准备参数 + Long userId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("你好"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, null); + // mock deepSeekApi 的方法 + when(deepSeekApi.chatCompletionEntity(any())) + .thenReturn(buildChatCompletion(new ChatCompletionMessage(PLAIN_ANSWER, Role.ASSISTANT))); + + // 调用 + AiChatMessageSendRespVO respVO = chatMessageService.sendMessage(reqVO, userId); + // 断言 + assertEquals(PLAIN_ANSWER, respVO.getReceive().getContent()); + verify(deepSeekApi).chatCompletionEntity(any()); + // 断言消息保存 + assertAssistantMessageUpdated(PLAIN_ANSWER); + } + + @Test + public void testSendMessage_toolCallThenModelError() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + mockLoginUser(userId, randomLongId()); + // mock deepSeekApi 的方法:先请求工具,再抛出异常 + RuntimeException modelException = new IllegalStateException("模型服务异常"); + when(deepSeekApi.chatCompletionEntity(any())).thenReturn(buildChatCompletion(TOOL_CALL_MESSAGE)) + .thenThrow(modelException); + + // 调用,并断言异常 + RuntimeException exception = assertThrows(RuntimeException.class, + () -> chatMessageService.sendMessage(reqVO, userId)); + assertSame(modelException, exception); + // 断言工具已执行、消息未保存 + verify(deepSeekApi, times(2)).chatCompletionEntity(any()); + assertEquals(1, toolContexts.size()); + verify(chatMessageMapper, never()).updateById(any(AiChatMessageDO.class)); + } + + @Test + public void testSendChatMessageStream_toolCall() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + Long tenantId = randomLongId(); + mockLoginUser(userId, tenantId); + // mock deepSeekApi 的方法:先请求工具,再流式返回回答 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(Flux.just(buildChatCompletionChunk(TOOL_CALL_MESSAGE)), + buildAnswerChunks(TOOL_ANSWER_CHUNKS)); + + // 调用 + List> results = chatMessageService + .sendChatMessageStream(reqVO, userId).collectList().block(); + // 断言(工具调用轮次不下发) + assertNotNull(results); + assertTrue(results.stream().allMatch(CommonResult::isSuccess)); + assertEquals(TOOL_ANSWER, joinContent(results)); + ArgumentCaptor requestCaptor = ArgumentCaptor.forClass(ChatCompletionRequest.class); + verify(deepSeekApi, times(2)).chatCompletionStream(requestCaptor.capture()); + assertToolExecuted(requestCaptor.getAllValues(), toolContexts, userId, tenantId); + // 断言消息保存 + assertAssistantMessageUpdated(TOOL_ANSWER); + } + + @Test + public void testSendChatMessageStream_withoutTool() { + // 准备参数 + Long userId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("你好"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, null); + // mock deepSeekApi 的方法 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(buildAnswerChunks(PLAIN_ANSWER_CHUNKS)); + + // 调用 + List> results = chatMessageService + .sendChatMessageStream(reqVO, userId).collectList().block(); + // 断言 + assertNotNull(results); + assertTrue(results.stream().allMatch(CommonResult::isSuccess)); + assertEquals(PLAIN_ANSWER, joinContent(results)); + verify(deepSeekApi).chatCompletionStream(any()); + // 断言消息保存 + assertAssistantMessageUpdated(PLAIN_ANSWER); + } + + @Test + public void testSendChatMessageStream_toolCallThenModelError() { + // 准备参数 + Long userId = randomLongId(); + Long roleId = randomLongId(); + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId()) + .setContent("杭州天气怎么样?"); + // mock 对话、模型 + mockConversation(reqVO.getConversationId(), userId, roleId); + // mock 工具 + List toolContexts = new CopyOnWriteArrayList<>(); + mockWeatherTool(roleId, toolContexts); + // mock 登录用户、租户 + mockLoginUser(userId, randomLongId()); + // mock deepSeekApi 的方法:先请求工具,再返回异常 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(Flux.just(buildChatCompletionChunk(TOOL_CALL_MESSAGE)), + Flux.error(new IllegalStateException("模型服务异常"))); + + // 调用 + List> results = chatMessageService + .sendChatMessageStream(reqVO, userId).collectList().block(); + // 断言 + assertNotNull(results); + assertEquals(CHAT_STREAM_ERROR.getCode(), CollUtil.getLast(results).getCode()); + verify(deepSeekApi, times(2)).chatCompletionStream(any()); + assertEquals(1, toolContexts.size()); + // 断言消息删除(无内容) + verify(chatMessageMapper).deleteById(ASSISTANT_MESSAGE_ID); + verify(chatMessageMapper, never()).updateById(any(AiChatMessageDO.class)); + } + + private void mockConversation(Long conversationId, Long userId, Long roleId) { + // mock 对话 + AiChatConversationDO conversation = new AiChatConversationDO().setId(conversationId).setUserId(userId) + .setRoleId(roleId).setModelId(randomLongId()).setTemperature(TEMPERATURE).setMaxTokens(MAX_TOKENS); + when(chatConversationService.validateChatConversationExists(eq(conversationId))).thenReturn(conversation); + // mock 模型:真实的 DeepSeekChatModel + AiModelDO model = new AiModelDO().setId(conversation.getModelId()).setModel(MODEL_NAME) + .setPlatform(AiPlatformEnum.DEEP_SEEK.getPlatform()); + when(modalService.validateModel(eq(model.getId()))).thenReturn(model); + when(modalService.getChatModel(eq(model.getId()))) + .thenReturn(DeepSeekChatModel.builder().deepSeekApi(deepSeekApi).build()); + // mock 消息插入:依次分配编号 + AtomicLong messageId = new AtomicLong(); + doAnswer(invocation -> { + invocation.getArgument(0).setId(messageId.incrementAndGet()); + return 1; + }).when(chatMessageMapper).insert(any(AiChatMessageDO.class)); + } + + private void mockWeatherTool(Long roleId, List toolContexts) { + // mock 工具:真实的 FunctionToolCallback + Long toolId = randomLongId(); + ToolCallback toolCallback = FunctionToolCallback.builder(TOOL_NAME, + (request, toolContext) -> { + toolContexts.add(toolContext); + return request.getCity() + ":晴,25℃"; + }).description("查询城市天气").inputType(WeatherRequest.class).build(); + when(chatRoleService.getChatRole(eq(roleId))).thenReturn(new AiChatRoleDO().setId(roleId) + .setToolIds(singletonList(toolId))); + when(toolService.getToolList(eq(singletonList(toolId)))) + .thenReturn(singletonList(new AiToolDO().setId(toolId).setName(TOOL_NAME))); + when(toolCallbackResolver.resolve(eq(TOOL_NAME))).thenReturn(toolCallback); + } + + private static void mockLoginUser(Long userId, Long tenantId) { + SecurityFrameworkUtils.setLoginUser(new LoginUser().setId(userId), new MockHttpServletRequest()); + TenantContextHolder.setTenantId(tenantId); + } + + private static void assertToolExecuted(List requests, List toolContexts, + Long userId, Long tenantId) { + // 断言首轮请求带上工具 + assertEquals(1, requests.get(0).tools().size()); + // 断言工具执行,并拿到登录用户、租户 + assertEquals(1, toolContexts.size()); + Map context = toolContexts.get(0).getContext(); + assertEquals(userId, ((LoginUser) context.get(TOOL_CONTEXT_LOGIN_USER)).getId()); + assertEquals(tenantId, context.get(TOOL_CONTEXT_TENANT_ID)); + // 断言次轮请求回传工具结果 + ChatCompletionMessage toolMessage = CollUtil.getLast(requests.get(1).messages()); + assertEquals(Role.TOOL, toolMessage.role()); + assertTrue(toolMessage.content().contains(TOOL_RESULT)); + } + + private void assertAssistantMessageUpdated(String content) { + ArgumentCaptor messageCaptor = ArgumentCaptor.forClass(AiChatMessageDO.class); + verify(chatMessageMapper).updateById(messageCaptor.capture()); + assertEquals(ASSISTANT_MESSAGE_ID, messageCaptor.getValue().getId()); + assertEquals(content, messageCaptor.getValue().getContent()); + } + + private static String joinContent(List> results) { + return results.stream().map(result -> result.getData().getReceive().getContent()) + .collect(Collectors.joining()); + } + + private static ResponseEntity buildChatCompletion(ChatCompletionMessage message) { + ChatCompletion.Choice choice = new ChatCompletion.Choice(buildFinishReason(message), 0, message, null); + return ResponseEntity.ok(new ChatCompletion("chatcmpl-1", singletonList(choice), null, MODEL_NAME, + null, null, null)); + } + + private static Flux buildAnswerChunks(List contents) { + return Flux.fromIterable(contents) + .map(content -> buildChatCompletionChunk(new ChatCompletionMessage(content, Role.ASSISTANT))); + } + + private static ChatCompletionChunk buildChatCompletionChunk(ChatCompletionMessage delta) { + ChatCompletionChunk.ChunkChoice choice = new ChatCompletionChunk.ChunkChoice(buildFinishReason(delta), + 0, delta, null); + return new ChatCompletionChunk("chatcmpl-1", singletonList(choice), null, MODEL_NAME, + null, null, null, null); + } + + private static ChatCompletionFinishReason buildFinishReason(ChatCompletionMessage message) { + return CollUtil.isNotEmpty(message.toolCalls()) ? ChatCompletionFinishReason.TOOL_CALLS + : ChatCompletionFinishReason.STOP; + } + + @Data + public static class WeatherRequest { + + private String city; + + } + +} diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java index 7ce45b3..4ea4df3 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.expression; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index 644c95a..e5a76ad 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index 911f48d..8fdfac2 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java index e198531..6205cba 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java index 170b8a1..5dd09ef 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java index 884ba3a..8bad952 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java @@ -5,11 +5,11 @@ import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction; -import cn.idev.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java index 1b33728..73e7373 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java index 075c3b3..eafb5e5 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.followup.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java index a9c2a7a..d85e98d 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java index c8e181e..7c5a2bb 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java index aeca925..e5c4a98 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import org.dromara.core.trans.anno.Trans; import org.dromara.core.trans.constant.TransType; import org.dromara.core.trans.vo.VO; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java index 5feb99c..830b9bc 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java index 75827db..b6a3ee1 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java index 3e03169..5a16048 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java index df89465..e5472c9 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java index 2398e06..5c0e267 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java index 29d4c2f..bb25768 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java index 8dcc9f8..d8f0bca 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java index 3044d5a..a1ec7fe 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java index 03c446e..4562649 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java index e6a6aa4..302ef79 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java index 6762419..bd86fdd 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java index 538a3b1..1d85685 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java index c75a99a..c079635 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java @@ -1,12 +1,13 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; +import org.apache.fesod.sheet.annotation.*; + import java.math.BigDecimal; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @Schema(description = "管理后台 - ERP 客户 Response VO") @Data diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index b1374e8..49c0d09 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index a004ed3..cbbe1a1 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java index 6a1ade0..fae4f6a 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java index 6f9b8da..6a2ea80 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index 1d23f36..9a2aff1 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java index f5f7650..0c4350e 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java index a1d0f51..35bd849 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java index 47e1261..77d82e8 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.erp.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java index 8d84789..b4e7482 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java index 06825b8..00e97e3 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java index 6a15e3c..f2ab852 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem; -import cn.idev.excel.annotation.ExcelProperty; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.Size; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * FMS 辅助核算项目 Excel 导入 VO diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java index f41a550..ffbaf69 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java index df1e229..4ddefd8 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java index 07a8dcf..2950ca4 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject; -import cn.idev.excel.annotation.ExcelProperty; import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelProperty; /** * FMS 科目 Excel 导入 VO diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java index 9a4bf25..d059f3d 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectRespVO.java @@ -4,11 +4,11 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.StringListConvert; import cn.iocoder.yudao.module.fms.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java index c4f53e0..14c979b 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarybalance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java index 5b8aee3..628cde8 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarydetail; import com.fasterxml.jackson.annotation.JsonFormat; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java index 3dd6606..3e1be63 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java index a0f67ec..1efc363 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail; import com.fasterxml.jackson.annotation.JsonFormat; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java index 12afe27..bb47e66 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.general; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java index 3317ccb..78b01ef 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitydetail; import com.fasterxml.jackson.annotation.JsonFormat; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDate; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java index 2f44668..5ae486c 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitygeneral; -import cn.idev.excel.annotation.ExcelIgnore; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnore; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.util.ArrayList; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java index 5249b9d..6f28079 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.subjectbalance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.util.ArrayList; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java index 2820415..f852d0c 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.report.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java index 18fe2ca..a77f1d7 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java index db12e3b..900e163 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.fms.controller.admin.voucher.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; -import cn.idev.excel.annotation.format.DateTimeFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.format.DateTimeFormat; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java index 9bdf07b..7158199 100644 --- a/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java +++ b/yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.fms.controller.admin.voucher.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java index 35c178d..be332f7 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.clock; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java index d21dc36..4a1a0f0 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.leave; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java index 4708af0..208e9d3 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.statistics; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.clock.HrmAttendanceClockRespVO; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java index 5aa1eb7..a3a48a6 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.statistics; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java index 87b37db..60f2538 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java @@ -1,7 +1,5 @@ package cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.employee; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; @@ -14,6 +12,8 @@ import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java index d7e0319..f194938 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.employee; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.experimental.Accessors; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java index c02b1f5..558c55b 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.changerecord; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.option.HrmSalaryOptionValueVO; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java index c1969c0..a0df917 100644 --- a/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java +++ b/yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java @@ -1,13 +1,13 @@ package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.employeeinfo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.option.HrmSalaryOptionValueVO; import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.math.BigDecimal; import java.time.LocalDateTime; diff --git a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java index 26e3d98..c847e1c 100644 --- a/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java +++ b/yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.im.dal.mysql.statistics; +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap; import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.ResultMap; import org.apache.ibatis.annotations.Select; import java.time.LocalDateTime; @@ -59,6 +61,7 @@ public interface ImStatisticsManagerMapper { @Select("SELECT DATE(create_time) AS date, COUNT(*) AS count FROM system_users " + "WHERE deleted = 0 AND create_time >= #{beginTime} AND create_time < #{endTime} " + "GROUP BY DATE(create_time)") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectNewUserDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -74,6 +77,7 @@ public interface ImStatisticsManagerMapper { " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY day") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectActiveUserDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); // ==================== 群 ==================== @@ -111,6 +115,7 @@ public interface ImStatisticsManagerMapper { " GROUP BY g.id" + ") t " + "GROUP BY `range`") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectGroupSizeDistribution(); // ==================== 消息 ==================== @@ -140,6 +145,7 @@ public interface ImStatisticsManagerMapper { "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime} " + "GROUP BY DATE(send_time)") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectPrivateMessageDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -150,6 +156,7 @@ public interface ImStatisticsManagerMapper { "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime} " + "GROUP BY DATE(send_time)") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectGroupMessageDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -167,6 +174,7 @@ public interface ImStatisticsManagerMapper { " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY type") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectMessageTypeDistribution(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime); @@ -184,6 +192,7 @@ public interface ImStatisticsManagerMapper { " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION + " AND send_time >= #{beginTime} AND send_time < #{endTime}" + ") t GROUP BY user_id ORDER BY messageCount DESC LIMIT #{limit}") + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID) List> selectTopSenders(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime, @Param("limit") int limit); diff --git a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java index 7c50033..effc562 100644 --- a/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java +++ b/yudao-module-im/src/test/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapperTest.java @@ -228,6 +228,9 @@ public class ImStatisticsManagerMapperTest extends BaseDbUnitTest { assertEquals(3L, ((Number) tops.get(0).get("messageCount")).longValue()); assertEquals(2L, ((Number) tops.get(1).get("userId")).longValue()); assertEquals(2L, ((Number) tops.get(1).get("messageCount")).longValue()); + // 断言:key 大小写不敏感,兼容 PostgreSQL 小写、Oracle 大写的列标签 + assertEquals(1L, ((Number) tops.get(0).get("userid")).longValue()); + assertEquals(3L, ((Number) tops.get(0).get("MESSAGECOUNT")).longValue()); } // ========== 工具方法 ========== diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java index 622bb04..26c72df 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java index df0ef60..8cc9b8a 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java index bac533b..acc295f 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java index 3094484..b429a3e 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.erp.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java index 3db315b..737fe46 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java index f100c80..f9cd803 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java @@ -2,10 +2,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java index 9a4be2e..4779502 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java index 1d33cdf..d7929ad 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java index 1b3dc0f..a730b42 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java index 7097924..ef4f2fb 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import cn.idev.excel.annotation.ExcelIgnoreUnannotated; -import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated; +import org.apache.fesod.sheet.annotation.ExcelProperty; import java.time.LocalDateTime; diff --git a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm index 51b0751..4164283 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm @@ -1,6 +1,6 @@ package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm index eae083a..77a9927 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm @@ -19,7 +19,7 @@ import java.time.LocalDateTime; #end #end ## 处理 Excel 导出 -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; #foreach ($column in $columns) #if ("$!column.dictType" != "")## 有设置数据字典 import ${DictFormatClassName}; diff --git a/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm b/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm index f15ada4..bb2914d 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm @@ -15,7 +15,7 @@ import ${BaseDOClassName}; ## 处理 Excel 导出 + Schema 注解(仅 DO 模式) #if ($voType == 20) import io.swagger.v3.oas.annotations.media.Schema; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; #foreach ($column in $columns) #if ("$!column.dictType" != "")## 有设置数据字典 import ${DictFormatClassName}; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_general_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_antd_schema_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_general_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vben5_ele_schema_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue2_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_admin_uniapp_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_master_erp/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_master_inner/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_master_normal/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO index c85f412..a46a12b 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentImportExcelVO @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; -import cn.idev.excel.annotation.ExcelProperty; +import org.apache.fesod.sheet.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO index 12166f4..d62fbbd 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_one_importEnable/java/InfraStudentRespVO @@ -5,7 +5,7 @@ import lombok.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO index 4e77b00..09aaf29 100644 --- a/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/vue3_tree/java/InfraCategoryRespVO @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; -import cn.idev.excel.annotation.*; +import org.apache.fesod.sheet.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data diff --git a/yudao-module-iot/yudao-module-iot-biz/pom.xml b/yudao-module-iot/yudao-module-iot-biz/pom.xml index 75cdd32..b671a62 100644 --- a/yudao-module-iot/yudao-module-iot-biz/pom.xml +++ b/yudao-module-iot/yudao-module-iot-biz/pom.xml @@ -50,6 +50,10 @@ com.taosdata.jdbc taos-jdbcdriver