Commit 09aa9ad97f2463a034fe596b2d587194179aa38a

Authored by YunaiV
2 parents ea5fd5d9 173264e2

Merge remote-tracking branch 'origin/master-jdk17' into master-jdk17

# Conflicts:
#	yudao-module-pms/src/test/java/cn/iocoder/yudao/module/pms/service/pm/workitem/PmsWorkItemUserSortServiceImplTest.java
Showing 310 changed files with 4866 additions and 809 deletions

Too many changes.

To preserve performance only 100 of 310 files are displayed.

yudao-dependencies/pom.xml
... ... @@ -34,6 +34,7 @@
34 34 <kingbase.jdbc.version>9.0.1.jre7</kingbase.jdbc.version>
35 35 <opengauss.jdbc.version>7.0.0-RC3-og</opengauss.jdbc.version>
36 36 <taos.version>3.9.2</taos.version>
  37 + <iotdb.version>2.0.8</iotdb.version> <!-- TODO 特殊:暂不升级 2.0.10/2.0.11,其 TablePreparedStatement.execute 不设置 ResultSet,导致 Mapper 的 SELECT 为空、COUNT 为 null -->
37 38 <!-- 消息队列 -->
38 39 <rocketmq-spring.version>2.3.6</rocketmq-spring.version>
39 40 <!-- 服务保障相关 -->
... ... @@ -58,7 +59,7 @@
58 59 <mapstruct.version>1.7.0.Beta2</mapstruct.version>
59 60 <hutool-5.version>5.8.47</hutool-5.version>
60 61 <hutool-6.version>6.0.0-M22</hutool-6.version>
61   - <fastexcel.version>1.3.0</fastexcel.version>
  62 + <fesod.version>2.1.0-incubating</fesod.version>
62 63 <aviator.version>5.4.4</aviator.version>
63 64 <velocity.version>2.4.1</velocity.version>
64 65 <fastjson2.version>2.0.65</fastjson2.version>
... ... @@ -312,6 +313,12 @@
312 313 <version>${taos.version}</version>
313 314 </dependency>
314 315  
  316 + <dependency>
  317 + <groupId>org.apache.iotdb</groupId>
  318 + <artifactId>iotdb-jdbc</artifactId>
  319 + <version>${iotdb.version}</version>
  320 + </dependency>
  321 +
315 322 <!-- Job 定时任务相关 -->
316 323 <dependency>
317 324 <groupId>cn.iocoder.boot</groupId>
... ... @@ -509,9 +516,9 @@
509 516 </dependency>
510 517  
511 518 <dependency>
512   - <groupId>cn.idev.excel</groupId>
513   - <artifactId>fastexcel</artifactId>
514   - <version>${fastexcel.version}</version>
  519 + <groupId>org.apache.fesod</groupId>
  520 + <artifactId>fesod-sheet</artifactId>
  521 + <version>${fesod.version}</version>
515 522 </dependency>
516 523  
517 524 <dependency>
... ...
yudao-framework/yudao-spring-boot-starter-excel/pom.xml
... ... @@ -42,8 +42,8 @@
42 42  
43 43 <!-- 工具类相关 -->
44 44 <dependency>
45   - <groupId>cn.idev.excel</groupId>
46   - <artifactId>fastexcel</artifactId>
  45 + <groupId>org.apache.fesod</groupId>
  46 + <artifactId>fesod-sheet</artifactId>
47 47 </dependency>
48 48  
49 49 <dependency>
... ...
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;
3 3 import cn.hutool.core.convert.Convert;
4 4 import cn.iocoder.yudao.framework.ip.core.Area;
5 5 import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils;
6   -import cn.idev.excel.converters.Converter;
7   -import cn.idev.excel.enums.CellDataTypeEnum;
8   -import cn.idev.excel.metadata.GlobalConfiguration;
9   -import cn.idev.excel.metadata.data.ReadCellData;
10   -import cn.idev.excel.metadata.data.WriteCellData;
11   -import cn.idev.excel.metadata.property.ExcelContentProperty;
12 6 import lombok.extern.slf4j.Slf4j;
  7 +import org.apache.fesod.sheet.converters.Converter;
  8 +import org.apache.fesod.sheet.enums.CellDataTypeEnum;
  9 +import org.apache.fesod.sheet.metadata.GlobalConfiguration;
  10 +import org.apache.fesod.sheet.metadata.data.ReadCellData;
  11 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  12 +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
13 13  
14 14 /**
15 15 * Excel 数据地区转换器
... ...
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;
3 3 import cn.hutool.core.convert.Convert;
4 4 import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
5 5 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6   -import cn.idev.excel.converters.Converter;
7   -import cn.idev.excel.enums.CellDataTypeEnum;
8   -import cn.idev.excel.metadata.GlobalConfiguration;
9   -import cn.idev.excel.metadata.data.ReadCellData;
10   -import cn.idev.excel.metadata.data.WriteCellData;
11   -import cn.idev.excel.metadata.property.ExcelContentProperty;
12 6 import lombok.extern.slf4j.Slf4j;
  7 +import org.apache.fesod.sheet.converters.Converter;
  8 +import org.apache.fesod.sheet.enums.CellDataTypeEnum;
  9 +import org.apache.fesod.sheet.metadata.GlobalConfiguration;
  10 +import org.apache.fesod.sheet.metadata.data.ReadCellData;
  11 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  12 +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
13 13  
14 14 /**
15 15 * Excel 数据字典转换器
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java
1 1 package cn.iocoder.yudao.framework.excel.core.convert;
2 2  
3 3 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
4   -import cn.idev.excel.converters.Converter;
5   -import cn.idev.excel.enums.CellDataTypeEnum;
6   -import cn.idev.excel.metadata.GlobalConfiguration;
7   -import cn.idev.excel.metadata.data.WriteCellData;
8   -import cn.idev.excel.metadata.property.ExcelContentProperty;
  4 +import org.apache.fesod.sheet.converters.Converter;
  5 +import org.apache.fesod.sheet.enums.CellDataTypeEnum;
  6 +import org.apache.fesod.sheet.metadata.GlobalConfiguration;
  7 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  8 +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
9 9  
10 10 /**
11 11 * Excel Json 转换器
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java
1 1 package cn.iocoder.yudao.framework.excel.core.convert;
2 2  
3   -import cn.idev.excel.converters.Converter;
4   -import cn.idev.excel.enums.CellDataTypeEnum;
5   -import cn.idev.excel.metadata.GlobalConfiguration;
6   -import cn.idev.excel.metadata.data.WriteCellData;
7   -import cn.idev.excel.metadata.property.ExcelContentProperty;
  3 +import org.apache.fesod.sheet.converters.Converter;
  4 +import org.apache.fesod.sheet.enums.CellDataTypeEnum;
  5 +import org.apache.fesod.sheet.metadata.GlobalConfiguration;
  6 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  7 +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.math.RoundingMode;
... ...
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;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
6 6 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
7   -import cn.idev.excel.converters.Converter;
8   -import cn.idev.excel.enums.CellDataTypeEnum;
9   -import cn.idev.excel.metadata.GlobalConfiguration;
10   -import cn.idev.excel.metadata.data.ReadCellData;
11   -import cn.idev.excel.metadata.data.WriteCellData;
12   -import cn.idev.excel.metadata.property.ExcelContentProperty;
13 7 import lombok.extern.slf4j.Slf4j;
  8 +import org.apache.fesod.sheet.converters.Converter;
  9 +import org.apache.fesod.sheet.enums.CellDataTypeEnum;
  10 +import org.apache.fesod.sheet.metadata.GlobalConfiguration;
  11 +import org.apache.fesod.sheet.metadata.data.ReadCellData;
  12 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  13 +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
14 14  
15 15 import java.lang.reflect.Array;
16 16 import java.lang.reflect.Field;
... ...
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;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4 4 import cn.hutool.core.util.StrUtil;
5   -import cn.idev.excel.converters.Converter;
6   -import cn.idev.excel.metadata.GlobalConfiguration;
7   -import cn.idev.excel.metadata.data.ReadCellData;
8   -import cn.idev.excel.metadata.data.WriteCellData;
9   -import cn.idev.excel.metadata.property.ExcelContentProperty;
  5 +import org.apache.fesod.sheet.converters.Converter;
  6 +import org.apache.fesod.sheet.metadata.GlobalConfiguration;
  7 +import org.apache.fesod.sheet.metadata.data.ReadCellData;
  8 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  9 +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
10 10  
11 11 import java.util.Collections;
12 12 import java.util.List;
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java
1 1 package cn.iocoder.yudao.framework.excel.core.handler;
2 2  
3 3 import cn.hutool.core.collection.CollUtil;
4   -import cn.idev.excel.enums.CellDataTypeEnum;
5   -import cn.idev.excel.metadata.Head;
6   -import cn.idev.excel.metadata.data.WriteCellData;
7   -import cn.idev.excel.util.MapUtils;
8   -import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
9   -import cn.idev.excel.write.style.column.AbstractColumnWidthStyleStrategy;
10   -import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
  4 +import org.apache.fesod.common.util.MapUtils;
  5 +import org.apache.fesod.sheet.enums.CellDataTypeEnum;
  6 +import org.apache.fesod.sheet.metadata.Head;
  7 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  8 +import org.apache.fesod.sheet.write.metadata.holder.WriteSheetHolder;
  9 +import org.apache.fesod.sheet.write.style.column.AbstractColumnWidthStyleStrategy;
  10 +import org.apache.fesod.sheet.write.style.column.LongestMatchColumnWidthStyleStrategy;
11 11 import org.apache.poi.ss.usermodel.Cell;
12 12  
13 13 import java.nio.charset.StandardCharsets;
... ...
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;
10 10 import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
11 11 import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
12 12 import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction;
13   -import cn.idev.excel.annotation.ExcelIgnore;
14   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
15   -import cn.idev.excel.annotation.ExcelProperty;
16   -import cn.idev.excel.write.handler.SheetWriteHandler;
17   -import cn.idev.excel.write.metadata.holder.WriteSheetHolder;
18   -import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder;
19 13 import lombok.extern.slf4j.Slf4j;
  14 +import org.apache.fesod.sheet.annotation.ExcelIgnore;
  15 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  16 +import org.apache.fesod.sheet.annotation.ExcelProperty;
  17 +import org.apache.fesod.sheet.write.handler.SheetWriteHandler;
  18 +import org.apache.fesod.sheet.write.metadata.holder.WriteSheetHolder;
  19 +import org.apache.fesod.sheet.write.metadata.holder.WriteWorkbookHolder;
20 20 import org.apache.poi.hssf.usermodel.HSSFDataValidation;
21 21 import org.apache.poi.ss.usermodel.*;
22 22 import org.apache.poi.ss.util.CellRangeAddressList;
... ... @@ -86,7 +86,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler {
86 86  
87 87 /**
88 88 * 判断字段是否是静态的、最终的、 transient 的
89   - * 原因:FastExcel 默认是忽略 static final 或 transient 的字段,所以需要判断
  89 + * 原因:Fesod 默认是忽略 static final 或 transient 的字段,所以需要判断
90 90 *
91 91 * @param field 字段
92 92 * @return 是否是静态的、最终的、transient 的
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java
1 1 package cn.iocoder.yudao.framework.excel.core.util;
2 2  
3   -import cn.idev.excel.FastExcelFactory;
4   -import cn.idev.excel.context.AnalysisContext;
5   -import cn.idev.excel.converters.longconverter.LongStringConverter;
6   -import cn.idev.excel.read.listener.ReadListener;
7 3 import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
8 4 import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy;
9 5 import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler;
10 6 import jakarta.servlet.http.HttpServletResponse;
  7 +import org.apache.fesod.sheet.FesodSheet;
  8 +import org.apache.fesod.sheet.context.AnalysisContext;
  9 +import org.apache.fesod.sheet.converters.Converter;
  10 +import org.apache.fesod.sheet.converters.longconverter.LongStringConverter;
  11 +import org.apache.fesod.sheet.enums.CellDataTypeEnum;
  12 +import org.apache.fesod.sheet.read.listener.ReadListener;
11 13 import org.springframework.web.multipart.MultipartFile;
12 14  
13 15 import java.io.IOException;
... ... @@ -25,6 +27,21 @@ import java.util.Map;
25 27 public class ExcelUtils {
26 28  
27 29 /**
  30 + * Long 转 String 的转换器,避免 Long 类型丢失精度
  31 + *
  32 + * 参考 https://t.zsxq.com/a0w1V 帖子:Fesod 写入 xlsx 时,按 supportExcelTypeKey 为 null 查找全局转换器,
  33 + * 所以需要返回 null,否则 registerConverter 的 LongStringConverter 不生效。关联 https://github.com/apache/fesod/issues/648
  34 + */
  35 + private static final Converter<Long> LONG_STRING_CONVERTER = new LongStringConverter() {
  36 +
  37 + @Override
  38 + public CellDataTypeEnum supportExcelTypeKey() {
  39 + return null;
  40 + }
  41 +
  42 + };
  43 +
  44 + /**
28 45 * 将列表以 Excel 响应给前端
29 46 *
30 47 * @param response 响应
... ... @@ -38,11 +55,11 @@ public class ExcelUtils {
38 55 public static <T> void write(HttpServletResponse response, String filename, String sheetName,
39 56 Class<T> head, List<T> data) throws IOException {
40 57 // 输出 Excel
41   - FastExcelFactory.write(response.getOutputStream(), head)
  58 + FesodSheet.write(response.getOutputStream(), head)
42 59 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
43 60 .registerWriteHandler(new ColumnWidthMatchStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
44 61 .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框
45   - .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
  62 + .registerConverter(LONG_STRING_CONVERTER) // 避免 Long 类型丢失精度
46 63 .sheet(sheetName).doWrite(data);
47 64 // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
48 65 response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename));
... ... @@ -62,10 +79,10 @@ public class ExcelUtils {
62 79 public static void write(HttpServletResponse response, String filename, String sheetName,
63 80 List<List<String>> head, List<List<Object>> data) throws IOException {
64 81 // 输出 Excel
65   - FastExcelFactory.write(response.getOutputStream())
  82 + FesodSheet.write(response.getOutputStream())
66 83 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
67 84 .registerWriteHandler(new ColumnWidthMatchStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度
68   - .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度
  85 + .registerConverter(LONG_STRING_CONVERTER) // 避免 Long 类型丢失精度
69 86 .head(head).sheet(sheetName).doWrite(data);
70 87 // 设置 header 和 contentType。写在最后的原因是,避免报错时,响应 contentType 已经被修改了
71 88 response.addHeader("Content-Disposition", "attachment;filename=" + HttpUtils.encodeUtf8(filename));
... ... @@ -78,7 +95,7 @@ public class ExcelUtils {
78 95 }
79 96 // 参考 https://t.zsxq.com/zM77F 帖子,增加 try 处理,兼容 windows 场景
80 97 try (InputStream inputStream = file.getInputStream()) {
81   - return FastExcelFactory.read(inputStream, head, null)
  98 + return FesodSheet.read(inputStream, head, null)
82 99 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
83 100 .doReadAllSync();
84 101 }
... ... @@ -101,7 +118,7 @@ public class ExcelUtils {
101 118 }
102 119 List<T> rows = new ArrayList<>(Math.min(maxRowCount, 1024));
103 120 try (InputStream inputStream = file.getInputStream()) {
104   - FastExcelFactory.read(inputStream, head, new ReadListener<T>() {
  121 + FesodSheet.read(inputStream, head, new ReadListener<T>() {
105 122  
106 123 @Override
107 124 public void invoke(T data, AnalysisContext context) {
... ... @@ -136,7 +153,7 @@ public class ExcelUtils {
136 153 }
137 154 // 参考 https://t.zsxq.com/zM77F 帖子,增加 try 处理,兼容 windows 场景
138 155 try (InputStream inputStream = file.getInputStream()) {
139   - return FastExcelFactory.read(inputStream)
  156 + return FesodSheet.read(inputStream)
140 157 .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理
141 158 .headRowNumber(1)
142 159 .sheet()
... ...
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;
27 27 /**
28 28 * 原生 POI 的 Excel 工具类
29 29 *
30   - * 全局 {@link ExcelUtils}(FastExcel)无法表达单元格锁定、公式、动态列等复杂模板时,各模块基于本类实现自定义 Excel 读写
  30 + * 全局 {@link ExcelUtils}(Fesod)无法表达单元格锁定、公式、动态列等复杂模板时,各模块基于本类实现自定义 Excel 读写
31 31 *
32 32 * @author 芋道源码
33 33 */
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java
1 1 /**
2   - * 基于 FastExcel 实现 Excel 相关的操作
  2 + * 基于 Fesod 实现 Excel 相关的操作
3 3 */
4 4 package cn.iocoder.yudao.framework.excel;
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/convert/MultiDictConvertTest.java
1 1 package cn.iocoder.yudao.framework.excel.core.convert;
2 2  
3 3 import cn.hutool.core.collection.ListUtil;
4   -import cn.idev.excel.metadata.data.ReadCellData;
5   -import cn.idev.excel.metadata.data.WriteCellData;
6   -import cn.idev.excel.metadata.property.ExcelContentProperty;
7 4 import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi;
8 5 import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO;
9 6 import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
10 7 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
11 8 import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  9 +import org.apache.fesod.sheet.metadata.data.ReadCellData;
  10 +import org.apache.fesod.sheet.metadata.data.WriteCellData;
  11 +import org.apache.fesod.sheet.metadata.property.ExcelContentProperty;
12 12 import org.junit.jupiter.api.BeforeEach;
13 13 import org.junit.jupiter.api.Test;
14 14 import org.mockito.Mock;
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategyTest.java
1 1 package cn.iocoder.yudao.framework.excel.core.handler;
2 2  
3   -import cn.idev.excel.FastExcelFactory;
4   -import cn.idev.excel.annotation.ExcelProperty;
  3 +import org.apache.fesod.sheet.FesodSheet;
  4 +import org.apache.fesod.sheet.annotation.ExcelProperty;
5 5 import org.apache.poi.xssf.usermodel.XSSFWorkbook;
6 6 import org.junit.jupiter.api.Test;
7 7  
... ... @@ -59,7 +59,7 @@ public class ColumnWidthMatchStyleStrategyTest {
59 59  
60 60 private XSSFWorkbook write(List<TestRow> rows) throws Exception {
61 61 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
62   - FastExcelFactory.write(outputStream, TestRow.class)
  62 + FesodSheet.write(outputStream, TestRow.class)
63 63 .registerWriteHandler(new ColumnWidthMatchStyleStrategy()).sheet().doWrite(rows);
64 64 return new XSSFWorkbook(new ByteArrayInputStream(outputStream.toByteArray()));
65 65 }
... ...
yudao-framework/yudao-spring-boot-starter-excel/src/test/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtilsTest.java
1 1 package cn.iocoder.yudao.framework.excel.core.util;
2 2  
3   -import cn.idev.excel.FastExcelFactory;
4   -import cn.idev.excel.annotation.ExcelProperty;
  3 +import cn.hutool.core.collection.ListUtil;
  4 +import cn.iocoder.yudao.framework.common.biz.system.dict.DictDataCommonApi;
  5 +import cn.iocoder.yudao.framework.common.biz.system.dict.dto.DictDataRespDTO;
  6 +import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils;
  7 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  8 +import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
  9 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
  10 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  11 +import lombok.Data;
  12 +import lombok.experimental.Accessors;
  13 +import org.apache.fesod.sheet.FesodSheet;
  14 +import org.apache.fesod.sheet.annotation.ExcelProperty;
  15 +import org.apache.poi.ss.usermodel.Cell;
  16 +import org.apache.poi.ss.usermodel.CellType;
  17 +import org.apache.poi.ss.usermodel.Sheet;
  18 +import org.apache.poi.ss.usermodel.Workbook;
  19 +import org.apache.poi.ss.usermodel.WorkbookFactory;
  20 +import org.junit.jupiter.api.BeforeEach;
5 21 import org.junit.jupiter.api.Test;
  22 +import org.mockito.Mock;
  23 +import org.springframework.mock.web.MockHttpServletResponse;
6 24 import org.springframework.mock.web.MockMultipartFile;
7 25  
  26 +import java.io.ByteArrayInputStream;
8 27 import java.io.ByteArrayOutputStream;
9 28 import java.util.Arrays;
  29 +import java.util.Collections;
10 30 import java.util.List;
11 31  
  32 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
12 33 import static org.junit.jupiter.api.Assertions.assertEquals;
  34 +import static org.junit.jupiter.api.Assertions.assertNotNull;
  35 +import static org.mockito.ArgumentMatchers.eq;
  36 +import static org.mockito.Mockito.when;
13 37  
14 38 /**
15 39 * {@link ExcelUtils} 的单元测试
16 40 *
17 41 * @author 芋道源码
18 42 */
19   -public class ExcelUtilsTest {
  43 +public class ExcelUtilsTest extends BaseMockitoUnitTest {
  44 +
  45 + private static final String DICT_TYPE = "test_status";
  46 +
  47 + @Mock
  48 + private DictDataCommonApi dictDataApi;
  49 +
  50 + @BeforeEach
  51 + public void setUp() {
  52 + DictFrameworkUtils.init(dictDataApi);
  53 + DictFrameworkUtils.clearCache();
  54 + }
  55 +
  56 + /**
  57 + * 字段未配置 converter 的 Long 编号,需要导出为文本,避免丢失精度
  58 + */
  59 + @Test
  60 + public void testWrite_class() throws Exception {
  61 + // mock 数据
  62 + mockDictDatas();
  63 + // 准备参数
  64 + MockHttpServletResponse response = new MockHttpServletResponse();
  65 + List<TestUser> list = Arrays.asList(
  66 + new TestUser().setId(1981234567890123456L).setAge(18).setStatus(0),
  67 + new TestUser().setId(Long.MAX_VALUE).setAge(20).setStatus(1));
  68 +
  69 + // 调用
  70 + ExcelUtils.write(response, "用户.xls", "数据", TestUser.class, list);
  71 + // 断言
  72 + try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
  73 + Sheet sheet = workbook.getSheet("数据");
  74 + // 断言 Long 编号
  75 + assertStringCell("1981234567890123456", sheet.getRow(1).getCell(0));
  76 + assertStringCell("9223372036854775807", sheet.getRow(2).getCell(0));
  77 + // 断言普通数值
  78 + assertNumericCell(18, sheet.getRow(1).getCell(1));
  79 + assertNumericCell(20, sheet.getRow(2).getCell(1));
  80 + // 断言字典转换
  81 + assertStringCell("开启", sheet.getRow(1).getCell(2));
  82 + assertStringCell("关闭", sheet.getRow(2).getCell(2));
  83 + // 断言下拉框
  84 + assertNotNull(workbook.getSheet("字典sheet"));
  85 + assertEquals(1, sheet.getDataValidations().size());
  86 + // 断言列宽:19 位 Long 字符串,加上 2 个字符的留白
  87 + assertEquals((19 + 2) * 256, sheet.getColumnWidth(0));
  88 + }
  89 + }
  90 +
  91 + @Test
  92 + public void testWrite_dynamicHead() throws Exception {
  93 + // 准备参数
  94 + MockHttpServletResponse response = new MockHttpServletResponse();
  95 + List<List<String>> head = Arrays.asList(Collections.singletonList("编号"), Collections.singletonList("年龄"));
  96 + List<List<Object>> list = Arrays.asList(
  97 + Arrays.asList(1981234567890123456L, 18),
  98 + Arrays.asList(Long.MAX_VALUE, 20));
  99 +
  100 + // 调用
  101 + ExcelUtils.write(response, "用户.xls", "数据", head, list);
  102 + // 断言
  103 + try (Workbook workbook = WorkbookFactory.create(new ByteArrayInputStream(response.getContentAsByteArray()))) {
  104 + Sheet sheet = workbook.getSheet("数据");
  105 + assertStringCell("编号", sheet.getRow(0).getCell(0));
  106 + // 断言 Long 编号
  107 + assertStringCell("1981234567890123456", sheet.getRow(1).getCell(0));
  108 + assertStringCell("9223372036854775807", sheet.getRow(2).getCell(0));
  109 + // 断言普通数值
  110 + assertNumericCell(18, sheet.getRow(1).getCell(1));
  111 + assertNumericCell(20, sheet.getRow(2).getCell(1));
  112 + }
  113 + }
20 114  
21 115 @Test
22 116 public void testRead_maxRowCount() throws Exception {
23 117 // mock 数据
24 118 ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
25   - FastExcelFactory.write(outputStream, TestRow.class).sheet().doWrite(Arrays.asList(
  119 + FesodSheet.write(outputStream, TestRow.class).sheet().doWrite(Arrays.asList(
26 120 new TestRow("员工一"), new TestRow("员工二"), new TestRow("员工三")));
27 121 MockMultipartFile file = new MockMultipartFile(
28 122 "file", "employees.xlsx", null, outputStream.toByteArray());
... ... @@ -36,6 +130,41 @@ public class ExcelUtilsTest {
36 130 assertEquals("员工二", rows.get(1).getName());
37 131 }
38 132  
  133 + private void mockDictDatas() {
  134 + List<DictDataRespDTO> dictDatas = ListUtil.of(
  135 + randomPojo(DictDataRespDTO.class, o -> o.setDictType(DICT_TYPE).setValue("0").setLabel("开启")),
  136 + randomPojo(DictDataRespDTO.class, o -> o.setDictType(DICT_TYPE).setValue("1").setLabel("关闭"))
  137 + );
  138 + when(dictDataApi.getDictDataList(eq(DICT_TYPE))).thenReturn(dictDatas);
  139 + }
  140 +
  141 + private static void assertStringCell(String expected, Cell cell) {
  142 + assertEquals(CellType.STRING, cell.getCellType());
  143 + assertEquals(expected, cell.getStringCellValue());
  144 + }
  145 +
  146 + private static void assertNumericCell(double expected, Cell cell) {
  147 + assertEquals(CellType.NUMERIC, cell.getCellType());
  148 + assertEquals(expected, cell.getNumericCellValue());
  149 + }
  150 +
  151 + @Data
  152 + @Accessors(chain = true)
  153 + public static class TestUser {
  154 +
  155 + @ExcelProperty("编号")
  156 + private Long id;
  157 +
  158 + @ExcelProperty("年龄")
  159 + private Integer age;
  160 +
  161 + @ExcelProperty(value = "状态", converter = DictConvert.class)
  162 + @DictFormat(DICT_TYPE)
  163 + @ExcelColumnSelect(dictType = DICT_TYPE)
  164 + private Integer status;
  165 +
  166 + }
  167 +
39 168 public static class TestRow {
40 169  
41 170 @ExcelProperty("姓名")
... ...
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;
4 4 import cn.hutool.core.util.StrUtil;
5 5 import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
6 6 import cn.iocoder.yudao.framework.mybatis.core.handler.DefaultDBFieldHandler;
  7 +import cn.iocoder.yudao.framework.mybatis.core.injector.YudaoSqlInjector;
  8 +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap;
7 9 import com.baomidou.mybatisplus.annotation.DbType;
  10 +import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
8 11 import com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration;
9 12 import com.baomidou.mybatisplus.core.handlers.IJsonTypeHandler;
10 13 import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
11 14 import com.baomidou.mybatisplus.core.incrementer.IKeyGenerator;
  15 +import com.baomidou.mybatisplus.core.injector.ISqlInjector;
12 16 import com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler;
13 17 import com.baomidou.mybatisplus.extension.incrementer.*;
14 18 import com.baomidou.mybatisplus.extension.parser.JsqlParserGlobal;
... ... @@ -17,12 +21,15 @@ import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
17 21 import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
18 22 import com.fasterxml.jackson.databind.ObjectMapper;
19 23 import org.apache.ibatis.annotations.Mapper;
  24 +import org.apache.ibatis.mapping.ResultMap;
20 25 import org.mybatis.spring.annotation.MapperScan;
21 26 import org.springframework.boot.autoconfigure.AutoConfiguration;
22 27 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
23 28 import org.springframework.context.annotation.Bean;
  29 +import org.springframework.context.annotation.Primary;
24 30 import org.springframework.core.env.ConfigurableEnvironment;
25 31  
  32 +import java.util.ArrayList;
26 33 import java.util.List;
27 34 import java.util.concurrent.TimeUnit;
28 35  
... ... @@ -59,6 +66,19 @@ public class YudaoMybatisAutoConfiguration {
59 66 }
60 67  
61 68 @Bean
  69 + @Primary // 特殊:使用 @Primary 的原因,避免 MyBatis Plus Join 再创建 MPJSqlInjector 包装它
  70 + public ISqlInjector yudaoSqlInjector() {
  71 + return new YudaoSqlInjector(); // selectMaps 的结果行,使用 CaseInsensitiveResultMap
  72 + }
  73 +
  74 + @Bean
  75 + public ConfigurationCustomizer caseInsensitiveResultMapConfigurationCustomizer() {
  76 + // 注册 CaseInsensitiveResultMap 的 resultMap,用于注解 SQL 的 @ResultMap
  77 + return configuration -> configuration.addResultMap(new ResultMap.Builder(configuration,
  78 + CaseInsensitiveResultMap.RESULT_MAP_ID, CaseInsensitiveResultMap.class, new ArrayList<>()).build());
  79 + }
  80 +
  81 + @Bean
62 82 @ConditionalOnProperty(prefix = "mybatis-plus.global-config.db-config", name = "id-type", havingValue = "INPUT")
63 83 public IKeyGenerator keyGenerator(ConfigurableEnvironment environment) {
64 84 DbType dbType = IdTypeEnvironmentPostProcessor.getDbType(environment);
... ...
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/injector/YudaoSqlInjector.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.mybatis.core.injector;
  2 +
  3 +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap;
  4 +import com.baomidou.mybatisplus.core.injector.AbstractMethod;
  5 +import com.baomidou.mybatisplus.core.metadata.TableInfo;
  6 +import com.github.yulichang.injector.MPJSqlInjector;
  7 +import com.github.yulichang.method.mp.SelectMaps;
  8 +import org.apache.ibatis.mapping.MappedStatement;
  9 +import org.apache.ibatis.mapping.SqlSource;
  10 +import org.apache.ibatis.session.Configuration;
  11 +
  12 +import java.util.List;
  13 +
  14 +/**
  15 + * 自定义 SQL 注入器
  16 + *
  17 + * 在 MyBatis Plus Join 的 {@link MPJSqlInjector} 基础上,将 selectMaps 的结果行替换为 {@link CaseInsensitiveResultMap},
  18 + * 解决 PostgreSQL、Oracle 等数据库列标签大小写折叠,导致按固定 key 取不到值的问题
  19 + *
  20 + * @author 芋道源码
  21 + */
  22 +public class YudaoSqlInjector extends MPJSqlInjector {
  23 +
  24 + @Override
  25 + public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
  26 + List<AbstractMethod> methods = super.getMethodList(configuration, mapperClass, tableInfo);
  27 + methods.replaceAll(method -> method instanceof SelectMaps ? new CaseInsensitiveSelectMaps() : method);
  28 + return methods;
  29 + }
  30 +
  31 + /**
  32 + * 结果行为 {@link CaseInsensitiveResultMap} 的 selectMaps
  33 + *
  34 + * 仅修改结果类型,SQL 仍由 MyBatis Plus Join 的 {@link SelectMaps} 生成,兼容 MPJ 的 Wrapper
  35 + */
  36 + private static class CaseInsensitiveSelectMaps extends SelectMaps {
  37 +
  38 + @Override
  39 + protected MappedStatement addSelectMappedStatementForOther(Class<?> mapperClass, String id, SqlSource sqlSource,
  40 + Class<?> resultType) {
  41 + return super.addSelectMappedStatementForOther(mapperClass, id, sqlSource, CaseInsensitiveResultMap.class);
  42 + }
  43 +
  44 + }
  45 +
  46 +}
... ...
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;
6 6 import cn.iocoder.yudao.framework.common.pojo.SortablePageParam;
7 7 import cn.iocoder.yudao.framework.common.pojo.SortingField;
8 8 import cn.iocoder.yudao.framework.common.util.object.PageUtils;
  9 +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap;
9 10 import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
10 11 import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
11 12 import com.baomidou.mybatisplus.annotation.DbType;
... ... @@ -14,6 +15,7 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
14 15 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
15 16 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
16 17 import com.baomidou.mybatisplus.core.metadata.IPage;
  18 +import com.baomidou.mybatisplus.core.toolkit.Constants;
17 19 import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
18 20 import com.baomidou.mybatisplus.extension.toolkit.Db;
19 21 import com.github.yulichang.base.MPJBaseMapper;
... ... @@ -23,6 +25,7 @@ import org.apache.ibatis.annotations.Param;
23 25  
24 26 import java.util.Collection;
25 27 import java.util.List;
  28 +import java.util.Map;
26 29  
27 30 /**
28 31 * 在 MyBatis Plus 的 BaseMapper 的基础上拓展,提供更多的能力
... ... @@ -99,6 +102,24 @@ public interface BaseMapperX&lt;T&gt; extends MPJBaseMapper&lt;T&gt; {
99 102 return new PageResult<>(mpPage.getRecords(), mpPage.getTotal());
100 103 }
101 104  
  105 + @Override
  106 + @SuppressWarnings("unchecked")
  107 + default Map<String, Object> selectJoinMap(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
  108 + return selectJoinOne(CaseInsensitiveResultMap.class, wrapper);
  109 + }
  110 +
  111 + @Override
  112 + @SuppressWarnings("unchecked")
  113 + default List<Map<String, Object>> selectJoinMaps(@Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
  114 + return (List<Map<String, Object>>) ((Object) selectJoinList(CaseInsensitiveResultMap.class, wrapper));
  115 + }
  116 +
  117 + @Override
  118 + @SuppressWarnings({"unchecked", "rawtypes"})
  119 + default <P extends IPage<Map<String, Object>>> P selectJoinMapsPage(P page, @Param(Constants.WRAPPER) MPJBaseJoin<T> wrapper) {
  120 + return (P) selectJoinPage((IPage) page, CaseInsensitiveResultMap.class, wrapper);
  121 + }
  122 +
102 123 default T selectOne(String field, Object value) {
103 124 return selectOne(new QueryWrapper<T>().eq(field, value));
104 125 }
... ...
yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMap.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.mybatis.core.util;
  2 +
  3 +import org.springframework.util.LinkedCaseInsensitiveMap;
  4 +
  5 +import java.util.Locale;
  6 +
  7 +/**
  8 + * key 大小写不敏感的 MyBatis 查询结果 Map
  9 + *
  10 + * 背景:使用 Map 接收查询结果时,key 为 JDBC 返回的列标签。PostgreSQL 等会将未加引号的列名、别名折叠为小写,
  11 + * Oracle、达梦等会折叠为大写,导致 map.get("conversationId") 这类按固定 key 取值的代码,在 MySQL 以外的数据库取不到值。
  12 + *
  13 + * 实现:基于 {@link LinkedCaseInsensitiveMap},get / containsKey / remove 时忽略 key 的大小写,
  14 + * 同时保留原始的列标签作为 key(遍历、序列化时不变)。固定使用 {@link Locale#ROOT},避免服务器默认 Locale(例如土耳其语)影响 key 的匹配。
  15 + *
  16 + * 使用方式:由 MyBatis 直接创建结果行,Mapper 的返回类型仍声明为 Map,业务无需感知该类
  17 + * 1. MyBatis Plus 的 selectMaps:由 YudaoSqlInjector 注入,自动使用该类
  18 + * 2. MyBatis Plus Join 的 selectJoinMaps 等:由 BaseMapperX 覆盖,自动使用该类
  19 + * 3. XML SQL:将 resultType 设置为该类
  20 + * 4. 注解 SQL:添加 @ResultMap({@link #RESULT_MAP_ID})
  21 + *
  22 + * 注意:仅大小写不同的多个 key,会合并为一个,保留后写入的 key 和值
  23 + *
  24 + * @author 芋道源码
  25 + * @see <a href="https://t.zsxq.com/kPvqm">星球讨论:Map 查询结果的跨数据库兼容问题</a>
  26 + */
  27 +public class CaseInsensitiveResultMap<V> extends LinkedCaseInsensitiveMap<V> {
  28 +
  29 + /**
  30 + * 注解 SQL 使用的 resultMap 编号
  31 + *
  32 + * 由 YudaoMybatisAutoConfiguration 注册到 MyBatis 全局配置;包含“.”,所以不会拼接 Mapper 的 namespace
  33 + */
  34 + public static final String RESULT_MAP_ID = "cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap";
  35 +
  36 + /**
  37 + * 创建空的结果 Map
  38 + *
  39 + * 用途:MyBatis 通过无参构造方法,实例化结果行
  40 + */
  41 + public CaseInsensitiveResultMap() {
  42 + super(Locale.ROOT);
  43 + }
  44 +
  45 +}
... ...
yudao-framework/yudao-spring-boot-starter-mybatis/src/test/java/cn/iocoder/yudao/framework/mybatis/core/util/CaseInsensitiveResultMapTest.java 0 → 100644
  1 +package cn.iocoder.yudao.framework.mybatis.core.util;
  2 +
  3 +import cn.hutool.core.map.MapUtil;
  4 +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
  5 +import org.junit.jupiter.api.Test;
  6 +import org.springframework.util.LinkedCaseInsensitiveMap;
  7 +
  8 +import java.util.*;
  9 +
  10 +import static org.junit.jupiter.api.Assertions.*;
  11 +
  12 +/**
  13 + * {@link CaseInsensitiveResultMap} 的单元测试
  14 + *
  15 + * @author 芋道源码
  16 + */
  17 +public class CaseInsensitiveResultMapTest {
  18 +
  19 + @Test
  20 + public void testGet_ignoreCase() {
  21 + // 准备参数
  22 + CaseInsensitiveResultMap<Object> map = new CaseInsensitiveResultMap<>();
  23 + map.put("conversationId", 1024L);
  24 +
  25 + // 调用,并断言:PostgreSQL 小写、Oracle 大写,都可以取到值
  26 + assertEquals(1024L, map.get("conversationId"));
  27 + assertEquals(1024L, map.get("conversationid"));
  28 + assertEquals(1024L, map.get("CONVERSATIONID"));
  29 + assertTrue(map.containsKey("CONVERSATIONID"));
  30 + assertEquals(1024L, MapUtil.getLong(map, "conversationid"));
  31 + // 断言:保留原始的 key
  32 + assertEquals(Collections.singletonList("conversationId"), new ArrayList<>(map.keySet()));
  33 + }
  34 +
  35 + @Test
  36 + public void testPut_nullValue() {
  37 + // 准备参数
  38 + CaseInsensitiveResultMap<Object> map = new CaseInsensitiveResultMap<>();
  39 + map.put("sum_count", null);
  40 +
  41 + // 调用,并断言
  42 + assertTrue(map.containsKey("SUM_COUNT"));
  43 + assertNull(map.get("SUM_COUNT"));
  44 + assertEquals(0, MapUtil.getInt(map, "SUM_COUNT", 0));
  45 + }
  46 +
  47 + @Test
  48 + public void testPut_sameKeyIgnoreCase() {
  49 + // 准备参数
  50 + CaseInsensitiveResultMap<Object> map = new CaseInsensitiveResultMap<>();
  51 +
  52 + // 调用:仅大小写不同的 key
  53 + map.put("id", 1L);
  54 + map.put("ID", 2L);
  55 +
  56 + // 断言:合并为一个,保留后写入的 key 和值
  57 + assertEquals(1, map.size());
  58 + assertEquals(2L, map.get("id"));
  59 + assertEquals(Collections.singletonList("ID"), new ArrayList<>(map.keySet()));
  60 + }
  61 +
  62 + @Test
  63 + public void testGet_turkishDefaultLocale() {
  64 + Locale defaultLocale = Locale.getDefault();
  65 + try {
  66 + // 准备参数:土耳其语下,大写 I 转小写为无点的 ı
  67 + Locale.setDefault(Locale.forLanguageTag("tr-TR"));
  68 + CaseInsensitiveResultMap<Object> map = new CaseInsensitiveResultMap<>();
  69 + map.put("CONVERSATIONID", 1024L);
  70 + LinkedCaseInsensitiveMap<Object> defaultLocaleMap = new LinkedCaseInsensitiveMap<>();
  71 + defaultLocaleMap.put("CONVERSATIONID", 1024L);
  72 +
  73 + // 调用,并断言:固定 Locale.ROOT,不受默认 Locale 影响
  74 + assertEquals(1024L, map.get("conversationId"));
  75 + // 断言:使用默认 Locale 时,取不到值
  76 + assertNull(defaultLocaleMap.get("conversationId"));
  77 + } finally {
  78 + Locale.setDefault(defaultLocale);
  79 + }
  80 + }
  81 +
  82 + @Test
  83 + public void testConvertMap_numberKey() {
  84 + // 准备参数:模拟 Oracle 返回的结果行
  85 + List<Map<String, Object>> rows = Arrays.asList(buildRow(1024L, 3), buildRow(2048L, 5));
  86 +
  87 + // 调用:业务转换为数字 key 的 Map
  88 + Map<Long, Integer> result = CollectionUtils.convertMap(rows,
  89 + row -> MapUtil.getLong(row, "conversationId"),
  90 + row -> MapUtil.getInt(row, "count"));
  91 +
  92 + // 断言:数字 key 的业务 Map 不受影响
  93 + assertInstanceOf(HashMap.class, result);
  94 + assertEquals(3, result.get(1024L));
  95 + assertEquals(5, result.get(2048L));
  96 + }
  97 +
  98 + private static Map<String, Object> buildRow(Long conversationId, Integer count) {
  99 + CaseInsensitiveResultMap<Object> row = new CaseInsensitiveResultMap<>();
  100 + row.put("CONVERSATIONID", conversationId);
  101 + row.put("COUNT", count);
  102 + return row;
  103 + }
  104 +
  105 +}
... ...
yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImplTest.java 0 → 100644
  1 +package cn.iocoder.yudao.module.ai.service.chat;
  2 +
  3 +import cn.hutool.core.collection.CollUtil;
  4 +import cn.iocoder.yudao.framework.common.pojo.CommonResult;
  5 +import cn.iocoder.yudao.framework.security.core.LoginUser;
  6 +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
  7 +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
  8 +import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
  9 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendReqVO;
  10 +import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.message.AiChatMessageSendRespVO;
  11 +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO;
  12 +import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatMessageDO;
  13 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO;
  14 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO;
  15 +import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiToolDO;
  16 +import cn.iocoder.yudao.module.ai.dal.mysql.chat.AiChatMessageMapper;
  17 +import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum;
  18 +import cn.iocoder.yudao.module.ai.service.knowledge.AiKnowledgeDocumentService;
  19 +import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService;
  20 +import cn.iocoder.yudao.module.ai.service.model.AiModelService;
  21 +import cn.iocoder.yudao.module.ai.service.model.AiToolService;
  22 +import lombok.Data;
  23 +import org.junit.jupiter.api.AfterEach;
  24 +import org.junit.jupiter.api.Test;
  25 +import org.mockito.ArgumentCaptor;
  26 +import org.mockito.InjectMocks;
  27 +import org.mockito.Mock;
  28 +import org.springframework.ai.chat.model.ToolContext;
  29 +import org.springframework.ai.deepseek.DeepSeekChatModel;
  30 +import org.springframework.ai.deepseek.api.DeepSeekApi;
  31 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletion;
  32 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionChunk;
  33 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionFinishReason;
  34 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage;
  35 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.ChatCompletionFunction;
  36 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.Role;
  37 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionMessage.ToolCall;
  38 +import org.springframework.ai.deepseek.api.DeepSeekApi.ChatCompletionRequest;
  39 +import org.springframework.ai.tool.ToolCallback;
  40 +import org.springframework.ai.tool.function.FunctionToolCallback;
  41 +import org.springframework.ai.tool.resolution.ToolCallbackResolver;
  42 +import org.springframework.http.ResponseEntity;
  43 +import org.springframework.mock.web.MockHttpServletRequest;
  44 +import org.springframework.security.core.context.SecurityContextHolder;
  45 +import reactor.core.publisher.Flux;
  46 +
  47 +import java.util.List;
  48 +import java.util.Map;
  49 +import java.util.concurrent.CopyOnWriteArrayList;
  50 +import java.util.concurrent.atomic.AtomicLong;
  51 +import java.util.stream.Collectors;
  52 +
  53 +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId;
  54 +import static cn.iocoder.yudao.module.ai.enums.ErrorCodeConstants.CHAT_STREAM_ERROR;
  55 +import static cn.iocoder.yudao.module.ai.util.AiUtils.TOOL_CONTEXT_LOGIN_USER;
  56 +import static cn.iocoder.yudao.module.ai.util.AiUtils.TOOL_CONTEXT_TENANT_ID;
  57 +import static java.util.Arrays.asList;
  58 +import static java.util.Collections.singletonList;
  59 +import static org.junit.jupiter.api.Assertions.*;
  60 +import static org.mockito.ArgumentMatchers.any;
  61 +import static org.mockito.ArgumentMatchers.eq;
  62 +import static org.mockito.Mockito.*;
  63 +
  64 +/**
  65 + * {@link AiChatMessageServiceImpl} 的单元测试类
  66 + *
  67 + * 使用真实的 {@link DeepSeekChatModel} 和工具调用,仅 mock 底层的 {@link DeepSeekApi}
  68 + *
  69 + * @author 芋道源码
  70 + */
  71 +public class AiChatMessageServiceImplTest extends BaseMockitoUnitTest {
  72 +
  73 + private static final String MODEL_NAME = "deepseek-test";
  74 + private static final Double TEMPERATURE = 0.5;
  75 + private static final Integer MAX_TOKENS = 1024;
  76 +
  77 + private static final String TOOL_NAME = "query_weather";
  78 + private static final String TOOL_RESULT = "杭州:晴,25℃";
  79 + private static final ChatCompletionMessage TOOL_CALL_MESSAGE = new ChatCompletionMessage("我来查询一下杭州的天气",
  80 + Role.ASSISTANT, null, null, singletonList(new ToolCall("call_1", "function",
  81 + new ChatCompletionFunction(TOOL_NAME, "{\"city\":\"杭州\"}"))));
  82 +
  83 + private static final List<String> TOOL_ANSWER_CHUNKS = asList("杭州今天", "晴,25℃");
  84 + private static final String TOOL_ANSWER = String.join("", TOOL_ANSWER_CHUNKS);
  85 + private static final List<String> PLAIN_ANSWER_CHUNKS = asList("你好,", "我是 AI 助手");
  86 + private static final String PLAIN_ANSWER = String.join("", PLAIN_ANSWER_CHUNKS);
  87 +
  88 + /**
  89 + * assistant 消息编号:先插入 user 消息(编号 1),再插入 assistant 消息(编号 2)
  90 + */
  91 + private static final Long ASSISTANT_MESSAGE_ID = 2L;
  92 +
  93 + @InjectMocks
  94 + private AiChatMessageServiceImpl chatMessageService;
  95 +
  96 + @Mock
  97 + private AiChatMessageMapper chatMessageMapper;
  98 + @Mock
  99 + private AiChatConversationService chatConversationService;
  100 + @Mock
  101 + private AiChatRoleService chatRoleService;
  102 + @Mock
  103 + private AiModelService modalService;
  104 + @Mock
  105 + private AiKnowledgeDocumentService knowledgeDocumentService;
  106 + @Mock
  107 + private AiToolService toolService;
  108 + @Mock
  109 + private ToolCallbackResolver toolCallbackResolver;
  110 + @Mock
  111 + private DeepSeekApi deepSeekApi;
  112 +
  113 + @AfterEach
  114 + public void after() {
  115 + SecurityContextHolder.clearContext();
  116 + TenantContextHolder.clear();
  117 + }
  118 +
  119 + @Test
  120 + public void testSendMessage_toolCall() {
  121 + // 准备参数
  122 + Long userId = randomLongId();
  123 + Long roleId = randomLongId();
  124 + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId())
  125 + .setContent("杭州天气怎么样?");
  126 + // mock 对话、模型
  127 + mockConversation(reqVO.getConversationId(), userId, roleId);
  128 + // mock 工具
  129 + List<ToolContext> toolContexts = new CopyOnWriteArrayList<>();
  130 + mockWeatherTool(roleId, toolContexts);
  131 + // mock 登录用户、租户
  132 + Long tenantId = randomLongId();
  133 + mockLoginUser(userId, tenantId);
  134 + // mock deepSeekApi 的方法:先请求工具,再返回回答
  135 + when(deepSeekApi.chatCompletionEntity(any())).thenReturn(buildChatCompletion(TOOL_CALL_MESSAGE),
  136 + buildChatCompletion(new ChatCompletionMessage(TOOL_ANSWER, Role.ASSISTANT)));
  137 +
  138 + // 调用
  139 + AiChatMessageSendRespVO respVO = chatMessageService.sendMessage(reqVO, userId);
  140 + // 断言
  141 + assertEquals(TOOL_ANSWER, respVO.getReceive().getContent());
  142 + ArgumentCaptor<ChatCompletionRequest> requestCaptor = ArgumentCaptor.forClass(ChatCompletionRequest.class);
  143 + verify(deepSeekApi, times(2)).chatCompletionEntity(requestCaptor.capture());
  144 + assertToolExecuted(requestCaptor.getAllValues(), toolContexts, userId, tenantId);
  145 + // 断言模型参数
  146 + ChatCompletionRequest request = requestCaptor.getAllValues().get(0);
  147 + assertEquals(MODEL_NAME, request.model());
  148 + assertEquals(TEMPERATURE, request.temperature());
  149 + assertEquals(MAX_TOKENS, request.maxTokens());
  150 + // 断言消息保存
  151 + assertAssistantMessageUpdated(TOOL_ANSWER);
  152 + }
  153 +
  154 + @Test
  155 + public void testSendMessage_withoutTool() {
  156 + // 准备参数
  157 + Long userId = randomLongId();
  158 + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId())
  159 + .setContent("你好");
  160 + // mock 对话、模型
  161 + mockConversation(reqVO.getConversationId(), userId, null);
  162 + // mock deepSeekApi 的方法
  163 + when(deepSeekApi.chatCompletionEntity(any()))
  164 + .thenReturn(buildChatCompletion(new ChatCompletionMessage(PLAIN_ANSWER, Role.ASSISTANT)));
  165 +
  166 + // 调用
  167 + AiChatMessageSendRespVO respVO = chatMessageService.sendMessage(reqVO, userId);
  168 + // 断言
  169 + assertEquals(PLAIN_ANSWER, respVO.getReceive().getContent());
  170 + verify(deepSeekApi).chatCompletionEntity(any());
  171 + // 断言消息保存
  172 + assertAssistantMessageUpdated(PLAIN_ANSWER);
  173 + }
  174 +
  175 + @Test
  176 + public void testSendMessage_toolCallThenModelError() {
  177 + // 准备参数
  178 + Long userId = randomLongId();
  179 + Long roleId = randomLongId();
  180 + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId())
  181 + .setContent("杭州天气怎么样?");
  182 + // mock 对话、模型
  183 + mockConversation(reqVO.getConversationId(), userId, roleId);
  184 + // mock 工具
  185 + List<ToolContext> toolContexts = new CopyOnWriteArrayList<>();
  186 + mockWeatherTool(roleId, toolContexts);
  187 + // mock 登录用户、租户
  188 + mockLoginUser(userId, randomLongId());
  189 + // mock deepSeekApi 的方法:先请求工具,再抛出异常
  190 + RuntimeException modelException = new IllegalStateException("模型服务异常");
  191 + when(deepSeekApi.chatCompletionEntity(any())).thenReturn(buildChatCompletion(TOOL_CALL_MESSAGE))
  192 + .thenThrow(modelException);
  193 +
  194 + // 调用,并断言异常
  195 + RuntimeException exception = assertThrows(RuntimeException.class,
  196 + () -> chatMessageService.sendMessage(reqVO, userId));
  197 + assertSame(modelException, exception);
  198 + // 断言工具已执行、消息未保存
  199 + verify(deepSeekApi, times(2)).chatCompletionEntity(any());
  200 + assertEquals(1, toolContexts.size());
  201 + verify(chatMessageMapper, never()).updateById(any(AiChatMessageDO.class));
  202 + }
  203 +
  204 + @Test
  205 + public void testSendChatMessageStream_toolCall() {
  206 + // 准备参数
  207 + Long userId = randomLongId();
  208 + Long roleId = randomLongId();
  209 + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId())
  210 + .setContent("杭州天气怎么样?");
  211 + // mock 对话、模型
  212 + mockConversation(reqVO.getConversationId(), userId, roleId);
  213 + // mock 工具
  214 + List<ToolContext> toolContexts = new CopyOnWriteArrayList<>();
  215 + mockWeatherTool(roleId, toolContexts);
  216 + // mock 登录用户、租户
  217 + Long tenantId = randomLongId();
  218 + mockLoginUser(userId, tenantId);
  219 + // mock deepSeekApi 的方法:先请求工具,再流式返回回答
  220 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(Flux.just(buildChatCompletionChunk(TOOL_CALL_MESSAGE)),
  221 + buildAnswerChunks(TOOL_ANSWER_CHUNKS));
  222 +
  223 + // 调用
  224 + List<CommonResult<AiChatMessageSendRespVO>> results = chatMessageService
  225 + .sendChatMessageStream(reqVO, userId).collectList().block();
  226 + // 断言(工具调用轮次不下发)
  227 + assertNotNull(results);
  228 + assertTrue(results.stream().allMatch(CommonResult::isSuccess));
  229 + assertEquals(TOOL_ANSWER, joinContent(results));
  230 + ArgumentCaptor<ChatCompletionRequest> requestCaptor = ArgumentCaptor.forClass(ChatCompletionRequest.class);
  231 + verify(deepSeekApi, times(2)).chatCompletionStream(requestCaptor.capture());
  232 + assertToolExecuted(requestCaptor.getAllValues(), toolContexts, userId, tenantId);
  233 + // 断言消息保存
  234 + assertAssistantMessageUpdated(TOOL_ANSWER);
  235 + }
  236 +
  237 + @Test
  238 + public void testSendChatMessageStream_withoutTool() {
  239 + // 准备参数
  240 + Long userId = randomLongId();
  241 + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId())
  242 + .setContent("你好");
  243 + // mock 对话、模型
  244 + mockConversation(reqVO.getConversationId(), userId, null);
  245 + // mock deepSeekApi 的方法
  246 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(buildAnswerChunks(PLAIN_ANSWER_CHUNKS));
  247 +
  248 + // 调用
  249 + List<CommonResult<AiChatMessageSendRespVO>> results = chatMessageService
  250 + .sendChatMessageStream(reqVO, userId).collectList().block();
  251 + // 断言
  252 + assertNotNull(results);
  253 + assertTrue(results.stream().allMatch(CommonResult::isSuccess));
  254 + assertEquals(PLAIN_ANSWER, joinContent(results));
  255 + verify(deepSeekApi).chatCompletionStream(any());
  256 + // 断言消息保存
  257 + assertAssistantMessageUpdated(PLAIN_ANSWER);
  258 + }
  259 +
  260 + @Test
  261 + public void testSendChatMessageStream_toolCallThenModelError() {
  262 + // 准备参数
  263 + Long userId = randomLongId();
  264 + Long roleId = randomLongId();
  265 + AiChatMessageSendReqVO reqVO = new AiChatMessageSendReqVO().setConversationId(randomLongId())
  266 + .setContent("杭州天气怎么样?");
  267 + // mock 对话、模型
  268 + mockConversation(reqVO.getConversationId(), userId, roleId);
  269 + // mock 工具
  270 + List<ToolContext> toolContexts = new CopyOnWriteArrayList<>();
  271 + mockWeatherTool(roleId, toolContexts);
  272 + // mock 登录用户、租户
  273 + mockLoginUser(userId, randomLongId());
  274 + // mock deepSeekApi 的方法:先请求工具,再返回异常
  275 + when(deepSeekApi.chatCompletionStream(any())).thenReturn(Flux.just(buildChatCompletionChunk(TOOL_CALL_MESSAGE)),
  276 + Flux.error(new IllegalStateException("模型服务异常")));
  277 +
  278 + // 调用
  279 + List<CommonResult<AiChatMessageSendRespVO>> results = chatMessageService
  280 + .sendChatMessageStream(reqVO, userId).collectList().block();
  281 + // 断言
  282 + assertNotNull(results);
  283 + assertEquals(CHAT_STREAM_ERROR.getCode(), CollUtil.getLast(results).getCode());
  284 + verify(deepSeekApi, times(2)).chatCompletionStream(any());
  285 + assertEquals(1, toolContexts.size());
  286 + // 断言消息删除(无内容)
  287 + verify(chatMessageMapper).deleteById(ASSISTANT_MESSAGE_ID);
  288 + verify(chatMessageMapper, never()).updateById(any(AiChatMessageDO.class));
  289 + }
  290 +
  291 + private void mockConversation(Long conversationId, Long userId, Long roleId) {
  292 + // mock 对话
  293 + AiChatConversationDO conversation = new AiChatConversationDO().setId(conversationId).setUserId(userId)
  294 + .setRoleId(roleId).setModelId(randomLongId()).setTemperature(TEMPERATURE).setMaxTokens(MAX_TOKENS);
  295 + when(chatConversationService.validateChatConversationExists(eq(conversationId))).thenReturn(conversation);
  296 + // mock 模型:真实的 DeepSeekChatModel
  297 + AiModelDO model = new AiModelDO().setId(conversation.getModelId()).setModel(MODEL_NAME)
  298 + .setPlatform(AiPlatformEnum.DEEP_SEEK.getPlatform());
  299 + when(modalService.validateModel(eq(model.getId()))).thenReturn(model);
  300 + when(modalService.getChatModel(eq(model.getId())))
  301 + .thenReturn(DeepSeekChatModel.builder().deepSeekApi(deepSeekApi).build());
  302 + // mock 消息插入:依次分配编号
  303 + AtomicLong messageId = new AtomicLong();
  304 + doAnswer(invocation -> {
  305 + invocation.<AiChatMessageDO>getArgument(0).setId(messageId.incrementAndGet());
  306 + return 1;
  307 + }).when(chatMessageMapper).insert(any(AiChatMessageDO.class));
  308 + }
  309 +
  310 + private void mockWeatherTool(Long roleId, List<ToolContext> toolContexts) {
  311 + // mock 工具:真实的 FunctionToolCallback
  312 + Long toolId = randomLongId();
  313 + ToolCallback toolCallback = FunctionToolCallback.<WeatherRequest, String>builder(TOOL_NAME,
  314 + (request, toolContext) -> {
  315 + toolContexts.add(toolContext);
  316 + return request.getCity() + ":晴,25℃";
  317 + }).description("查询城市天气").inputType(WeatherRequest.class).build();
  318 + when(chatRoleService.getChatRole(eq(roleId))).thenReturn(new AiChatRoleDO().setId(roleId)
  319 + .setToolIds(singletonList(toolId)));
  320 + when(toolService.getToolList(eq(singletonList(toolId))))
  321 + .thenReturn(singletonList(new AiToolDO().setId(toolId).setName(TOOL_NAME)));
  322 + when(toolCallbackResolver.resolve(eq(TOOL_NAME))).thenReturn(toolCallback);
  323 + }
  324 +
  325 + private static void mockLoginUser(Long userId, Long tenantId) {
  326 + SecurityFrameworkUtils.setLoginUser(new LoginUser().setId(userId), new MockHttpServletRequest());
  327 + TenantContextHolder.setTenantId(tenantId);
  328 + }
  329 +
  330 + private static void assertToolExecuted(List<ChatCompletionRequest> requests, List<ToolContext> toolContexts,
  331 + Long userId, Long tenantId) {
  332 + // 断言首轮请求带上工具
  333 + assertEquals(1, requests.get(0).tools().size());
  334 + // 断言工具执行,并拿到登录用户、租户
  335 + assertEquals(1, toolContexts.size());
  336 + Map<String, Object> context = toolContexts.get(0).getContext();
  337 + assertEquals(userId, ((LoginUser) context.get(TOOL_CONTEXT_LOGIN_USER)).getId());
  338 + assertEquals(tenantId, context.get(TOOL_CONTEXT_TENANT_ID));
  339 + // 断言次轮请求回传工具结果
  340 + ChatCompletionMessage toolMessage = CollUtil.getLast(requests.get(1).messages());
  341 + assertEquals(Role.TOOL, toolMessage.role());
  342 + assertTrue(toolMessage.content().contains(TOOL_RESULT));
  343 + }
  344 +
  345 + private void assertAssistantMessageUpdated(String content) {
  346 + ArgumentCaptor<AiChatMessageDO> messageCaptor = ArgumentCaptor.forClass(AiChatMessageDO.class);
  347 + verify(chatMessageMapper).updateById(messageCaptor.capture());
  348 + assertEquals(ASSISTANT_MESSAGE_ID, messageCaptor.getValue().getId());
  349 + assertEquals(content, messageCaptor.getValue().getContent());
  350 + }
  351 +
  352 + private static String joinContent(List<CommonResult<AiChatMessageSendRespVO>> results) {
  353 + return results.stream().map(result -> result.getData().getReceive().getContent())
  354 + .collect(Collectors.joining());
  355 + }
  356 +
  357 + private static ResponseEntity<ChatCompletion> buildChatCompletion(ChatCompletionMessage message) {
  358 + ChatCompletion.Choice choice = new ChatCompletion.Choice(buildFinishReason(message), 0, message, null);
  359 + return ResponseEntity.ok(new ChatCompletion("chatcmpl-1", singletonList(choice), null, MODEL_NAME,
  360 + null, null, null));
  361 + }
  362 +
  363 + private static Flux<ChatCompletionChunk> buildAnswerChunks(List<String> contents) {
  364 + return Flux.fromIterable(contents)
  365 + .map(content -> buildChatCompletionChunk(new ChatCompletionMessage(content, Role.ASSISTANT)));
  366 + }
  367 +
  368 + private static ChatCompletionChunk buildChatCompletionChunk(ChatCompletionMessage delta) {
  369 + ChatCompletionChunk.ChunkChoice choice = new ChatCompletionChunk.ChunkChoice(buildFinishReason(delta),
  370 + 0, delta, null);
  371 + return new ChatCompletionChunk("chatcmpl-1", singletonList(choice), null, MODEL_NAME,
  372 + null, null, null, null);
  373 + }
  374 +
  375 + private static ChatCompletionFinishReason buildFinishReason(ChatCompletionMessage message) {
  376 + return CollUtil.isNotEmpty(message.toolCalls()) ? ChatCompletionFinishReason.TOOL_CALLS
  377 + : ChatCompletionFinishReason.STOP;
  378 + }
  379 +
  380 + @Data
  381 + public static class WeatherRequest {
  382 +
  383 + private String city;
  384 +
  385 + }
  386 +
  387 +}
... ...
yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java
1 1 package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.expression;
2 2  
3   -import cn.idev.excel.annotation.ExcelProperty;
4 3 import io.swagger.v3.oas.annotations.media.Schema;
5 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelProperty;
6 6  
7 7 import java.time.LocalDateTime;
8 8  
... ...
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.AllArgsConstructor;
7 5 import lombok.Data;
8 6 import lombok.NoArgsConstructor;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.math.BigDecimal;
11 11 import java.time.LocalDateTime;
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
10 8 import lombok.ToString;
  9 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  10 +import org.apache.fesod.sheet.annotation.ExcelProperty;
11 11  
12 12 import java.time.LocalDateTime;
13 13  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
10 8 import lombok.ToString;
  9 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  10 +import org.apache.fesod.sheet.annotation.ExcelProperty;
11 11  
12 12 import java.time.LocalDateTime;
13 13  
... ...
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.AllArgsConstructor;
7 5 import lombok.Data;
8 6 import lombok.NoArgsConstructor;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.math.BigDecimal;
11 11 import java.time.LocalDateTime;
... ...
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;
5 5 import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert;
6 6 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 7 import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction;
8   -import cn.idev.excel.annotation.ExcelProperty;
9 8 import lombok.AllArgsConstructor;
10 9 import lombok.Builder;
11 10 import lombok.Data;
12 11 import lombok.NoArgsConstructor;
  12 +import org.apache.fesod.sheet.annotation.ExcelProperty;
13 13  
14 14 import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*;
15 15  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.time.LocalDateTime;
12 12  
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.time.LocalDateTime;
11 11 import java.util.List;
... ...
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4 3 import io.swagger.v3.oas.annotations.media.Schema;
5 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
6 6  
7 7 import java.time.LocalDateTime;
8 8  
... ...
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category;
2 2  
3   -import cn.idev.excel.annotation.ExcelProperty;
4 3 import io.swagger.v3.oas.annotations.media.Schema;
5 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelProperty;
6 6  
7 7 import java.time.LocalDateTime;
8 8  
... ...
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;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO;
6 6 import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
7   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
8   -import cn.idev.excel.annotation.ExcelProperty;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9 import org.dromara.core.trans.anno.Trans;
10 10 import org.dromara.core.trans.constant.TransType;
11 11 import org.dromara.core.trans.vo.VO;
... ...
yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java
1 1 package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan;
2 2  
3 3 import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO;
4   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
5   -import cn.idev.excel.annotation.ExcelProperty;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
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;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO;
6 6 import cn.iocoder.yudao.module.crm.enums.DictTypeConstants;
7   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
8   -import cn.idev.excel.annotation.ExcelProperty;
9 7 import io.swagger.v3.oas.annotations.media.Schema;
10 8 import lombok.Data;
  9 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  10 +import org.apache.fesod.sheet.annotation.ExcelProperty;
11 11  
12 12 import java.math.BigDecimal;
13 13 import java.time.LocalDateTime;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.time.LocalDateTime;
11 11  
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.time.LocalDateTime;
12 12  
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.math.BigDecimal;
9 9 import java.time.LocalDateTime;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.time.LocalDateTime;
11 11  
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.math.BigDecimal;
12 12 import java.time.LocalDateTime;
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer;
2 2  
  3 +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
  4 +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
3 5 import io.swagger.v3.oas.annotations.media.Schema;
4 6 import lombok.*;
  7 +import org.apache.fesod.sheet.annotation.*;
  8 +
5 9 import java.math.BigDecimal;
6 10 import java.time.LocalDateTime;
7   -import cn.idev.excel.annotation.*;
8   -import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
9   -import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
10 11  
11 12 @Schema(description = "管理后台 - ERP 客户 Response VO")
12 13 @Data
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import jakarta.validation.constraints.NotNull;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import jakarta.validation.constraints.NotNull;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.math.BigDecimal;
12 12 import java.time.LocalDateTime;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.math.BigDecimal;
11 11 import java.time.LocalDateTime;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.math.BigDecimal;
11 11 import java.time.LocalDateTime;
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.math.BigDecimal;
11 11 import java.time.LocalDateTime;
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.erp.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.math.BigDecimal;
12 12 import java.time.LocalDateTime;
... ...
yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java
1 1 package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.math.BigDecimal;
9 9  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.system.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.math.BigDecimal;
12 12 import java.time.LocalDateTime;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemImportExcelVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
2 2  
3   -import cn.idev.excel.annotation.ExcelProperty;
4 3 import jakarta.validation.constraints.NotBlank;
5 4 import jakarta.validation.constraints.Size;
6 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 /**
9 9 * FMS 辅助核算项目 Excel 导入 VO
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/auxiliaryitem/FmsAuxiliaryItemRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.config.vo.auxiliaryitem;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.time.LocalDateTime;
9 9  
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/initialbalance/FmsInitialBalanceExcelVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.config.vo.initialbalance;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import lombok.Data;
  4 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  5 +import org.apache.fesod.sheet.annotation.ExcelProperty;
6 6  
7 7 import java.math.BigDecimal;
8 8  
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/config/vo/subject/FmsSubjectImportExcelVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.config.vo.subject;
2 2  
3   -import cn.idev.excel.annotation.ExcelProperty;
4 3 import jakarta.validation.constraints.NotBlank;
5 4 import lombok.AllArgsConstructor;
6 5 import lombok.Builder;
7 6 import lombok.Data;
8 7 import lombok.NoArgsConstructor;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 /**
11 11 * FMS 科目 Excel 导入 VO
... ...
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;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.framework.excel.core.convert.StringListConvert;
6 6 import cn.iocoder.yudao.module.fms.enums.DictTypeConstants;
7   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
8   -import cn.idev.excel.annotation.ExcelProperty;
9 7 import com.fasterxml.jackson.annotation.JsonIgnore;
10 8 import io.swagger.v3.oas.annotations.media.Schema;
11 9 import lombok.Data;
  10 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  11 +import org.apache.fesod.sheet.annotation.ExcelProperty;
12 12  
13 13 import java.time.LocalDateTime;
14 14 import java.util.List;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarybalance/FmsLedgerAuxiliaryBalanceRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarybalance;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
7 5 import lombok.experimental.Accessors;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10  
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/auxiliarydetail/FmsLedgerAuxiliaryDetailRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.auxiliarydetail;
2 2  
3 3 import com.fasterxml.jackson.annotation.JsonFormat;
4   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
5   -import cn.idev.excel.annotation.ExcelProperty;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDate;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailExportRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import lombok.Data;
  4 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  5 +import org.apache.fesod.sheet.annotation.ExcelProperty;
6 6  
7 7 import java.math.BigDecimal;
8 8 import java.time.LocalDate;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/detail/FmsLedgerDetailRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.detail;
2 2  
3 3 import com.fasterxml.jackson.annotation.JsonFormat;
4   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
5   -import cn.idev.excel.annotation.ExcelProperty;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDate;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/general/FmsLedgerGeneralRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.general;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.math.BigDecimal;
9 9  
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitydetail/FmsLedgerQuantityDetailRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitydetail;
2 2  
3 3 import com.fasterxml.jackson.annotation.JsonFormat;
4   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
5   -import cn.idev.excel.annotation.ExcelProperty;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDate;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/quantitygeneral/FmsLedgerQuantityGeneralRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.quantitygeneral;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnore;
4   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
5   -import cn.idev.excel.annotation.ExcelProperty;
6 3 import io.swagger.v3.oas.annotations.media.Schema;
7 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnore;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.util.ArrayList;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/ledger/vo/subjectbalance/FmsLedgerSubjectBalanceRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.ledger.vo.subjectbalance;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
7 5 import lombok.experimental.Accessors;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.util.ArrayList;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/FmsReportItemRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.report.vo;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.math.BigDecimal;
9 9  
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/report/vo/balance/FmsBalanceSheetRowRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.report.vo.balance;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.math.BigDecimal;
9 9  
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherExportRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.voucher.vo;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5   -import cn.idev.excel.annotation.format.DateTimeFormat;
6 3 import io.swagger.v3.oas.annotations.media.Schema;
7 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
  7 +import org.apache.fesod.sheet.annotation.format.DateTimeFormat;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
yudao-module-fms/src/main/java/cn/iocoder/yudao/module/fms/controller/admin/voucher/vo/FmsVoucherStatisticsRespVO.java
1 1 package cn.iocoder.yudao.module.fms.controller.admin.voucher.vo;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.math.BigDecimal;
9 9  
... ...
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/clock/HrmAttendanceClockRespVO.java
1 1 package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.clock;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 5 import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.math.BigDecimal;
12 12 import java.time.LocalDateTime;
... ...
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/leave/HrmAttendanceLeaveRespVO.java
1 1 package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.leave;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 5 import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.math.BigDecimal;
12 12 import java.time.LocalDateTime;
... ...
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceDailyDetailRespVO.java
1 1 package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.statistics;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.clock.HrmAttendanceClockRespVO;
6 4 import io.swagger.v3.oas.annotations.media.Schema;
7 5 import lombok.Data;
  6 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  7 +import org.apache.fesod.sheet.annotation.ExcelProperty;
8 8  
9 9 import java.math.BigDecimal;
10 10 import java.time.LocalDateTime;
... ...
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/attendance/vo/statistics/HrmAttendanceMonthRecordRespVO.java
1 1 package cn.iocoder.yudao.module.hrm.controller.admin.attendance.vo.statistics;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.math.BigDecimal;
9 9 import java.time.LocalDateTime;
... ...
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/employee/vo/employee/HrmEmployeeImportExcelVO.java
1 1 package cn.iocoder.yudao.module.hrm.controller.admin.employee.vo.employee;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect;
6 4 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
7 5 import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert;
... ... @@ -14,6 +12,8 @@ import lombok.AllArgsConstructor;
14 12 import lombok.Builder;
15 13 import lombok.Data;
16 14 import lombok.NoArgsConstructor;
  15 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  16 +import org.apache.fesod.sheet.annotation.ExcelProperty;
17 17  
18 18 import java.time.LocalDateTime;
19 19  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
10 8 import lombok.experimental.Accessors;
  9 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  10 +import org.apache.fesod.sheet.annotation.ExcelProperty;
11 11  
12 12 import java.time.LocalDateTime;
13 13  
... ...
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/changerecord/HrmSalaryChangeRecordRespVO.java
1 1 package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.changerecord;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 5 import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.option.HrmSalaryOptionValueVO;
8 6 import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants;
9 7 import io.swagger.v3.oas.annotations.media.Schema;
10 8 import lombok.Data;
  9 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  10 +import org.apache.fesod.sheet.annotation.ExcelProperty;
11 11  
12 12 import java.math.BigDecimal;
13 13 import java.time.LocalDateTime;
... ...
yudao-module-hrm/src/main/java/cn/iocoder/yudao/module/hrm/controller/admin/salary/vo/employeeinfo/HrmSalaryEmployeeInfoRespVO.java
1 1 package cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.employeeinfo;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
6 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
7 5 import cn.iocoder.yudao.module.hrm.controller.admin.salary.vo.option.HrmSalaryOptionValueVO;
8 6 import cn.iocoder.yudao.module.hrm.enums.DictTypeConstants;
9 7 import io.swagger.v3.oas.annotations.media.Schema;
10 8 import lombok.Data;
  9 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  10 +import org.apache.fesod.sheet.annotation.ExcelProperty;
11 11  
12 12 import java.math.BigDecimal;
13 13 import java.time.LocalDateTime;
... ...
yudao-module-im/src/main/java/cn/iocoder/yudao/module/im/dal/mysql/statistics/ImStatisticsManagerMapper.java
1 1 package cn.iocoder.yudao.module.im.dal.mysql.statistics;
2 2  
  3 +import cn.iocoder.yudao.framework.mybatis.core.util.CaseInsensitiveResultMap;
3 4 import org.apache.ibatis.annotations.Mapper;
4 5 import org.apache.ibatis.annotations.Param;
  6 +import org.apache.ibatis.annotations.ResultMap;
5 7 import org.apache.ibatis.annotations.Select;
6 8  
7 9 import java.time.LocalDateTime;
... ... @@ -59,6 +61,7 @@ public interface ImStatisticsManagerMapper {
59 61 @Select("SELECT DATE(create_time) AS date, COUNT(*) AS count FROM system_users " +
60 62 "WHERE deleted = 0 AND create_time >= #{beginTime} AND create_time < #{endTime} " +
61 63 "GROUP BY DATE(create_time)")
  64 + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID)
62 65 List<Map<String, Object>> selectNewUserDailyCount(@Param("beginTime") LocalDateTime beginTime,
63 66 @Param("endTime") LocalDateTime endTime);
64 67  
... ... @@ -74,6 +77,7 @@ public interface ImStatisticsManagerMapper {
74 77 " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION +
75 78 " AND send_time >= #{beginTime} AND send_time < #{endTime}" +
76 79 ") t GROUP BY day")
  80 + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID)
77 81 List<Map<String, Object>> selectActiveUserDailyCount(@Param("beginTime") LocalDateTime beginTime, @Param("endTime") LocalDateTime endTime);
78 82  
79 83 // ==================== 群 ====================
... ... @@ -111,6 +115,7 @@ public interface ImStatisticsManagerMapper {
111 115 " GROUP BY g.id" +
112 116 ") t " +
113 117 "GROUP BY `range`")
  118 + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID)
114 119 List<Map<String, Object>> selectGroupSizeDistribution();
115 120  
116 121 // ==================== 消息 ====================
... ... @@ -140,6 +145,7 @@ public interface ImStatisticsManagerMapper {
140 145 "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION +
141 146 " AND send_time >= #{beginTime} AND send_time < #{endTime} " +
142 147 "GROUP BY DATE(send_time)")
  148 + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID)
143 149 List<Map<String, Object>> selectPrivateMessageDailyCount(@Param("beginTime") LocalDateTime beginTime,
144 150 @Param("endTime") LocalDateTime endTime);
145 151  
... ... @@ -150,6 +156,7 @@ public interface ImStatisticsManagerMapper {
150 156 "WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION +
151 157 " AND send_time >= #{beginTime} AND send_time < #{endTime} " +
152 158 "GROUP BY DATE(send_time)")
  159 + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID)
153 160 List<Map<String, Object>> selectGroupMessageDailyCount(@Param("beginTime") LocalDateTime beginTime,
154 161 @Param("endTime") LocalDateTime endTime);
155 162  
... ... @@ -167,6 +174,7 @@ public interface ImStatisticsManagerMapper {
167 174 " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION +
168 175 " AND send_time >= #{beginTime} AND send_time < #{endTime}" +
169 176 ") t GROUP BY type")
  177 + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID)
170 178 List<Map<String, Object>> selectMessageTypeDistribution(@Param("beginTime") LocalDateTime beginTime,
171 179 @Param("endTime") LocalDateTime endTime);
172 180  
... ... @@ -184,6 +192,7 @@ public interface ImStatisticsManagerMapper {
184 192 " WHERE deleted = 0 AND " + NORMAL_MESSAGE_CONDITION +
185 193 " AND send_time >= #{beginTime} AND send_time < #{endTime}" +
186 194 ") t GROUP BY user_id ORDER BY messageCount DESC LIMIT #{limit}")
  195 + @ResultMap(CaseInsensitiveResultMap.RESULT_MAP_ID)
187 196 List<Map<String, Object>> selectTopSenders(@Param("beginTime") LocalDateTime beginTime,
188 197 @Param("endTime") LocalDateTime endTime,
189 198 @Param("limit") int limit);
... ...
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 {
228 228 assertEquals(3L, ((Number) tops.get(0).get("messageCount")).longValue());
229 229 assertEquals(2L, ((Number) tops.get(1).get("userId")).longValue());
230 230 assertEquals(2L, ((Number) tops.get(1).get("messageCount")).longValue());
  231 + // 断言:key 大小写不敏感,兼容 PostgreSQL 小写、Oracle 大写的列标签
  232 + assertEquals(1L, ((Number) tops.get(0).get("userid")).longValue());
  233 + assertEquals(3L, ((Number) tops.get(0).get("MESSAGECOUNT")).longValue());
231 234 }
232 235  
233 236 // ========== 工具方法 ==========
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.time.LocalDateTime;
12 12  
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.time.LocalDateTime;
11 11  
... ...
yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java
1 1 package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo;
2 2  
3   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
4   -import cn.idev.excel.annotation.ExcelProperty;
5 3 import io.swagger.v3.oas.annotations.media.Schema;
6 4 import lombok.Data;
  5 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  6 +import org.apache.fesod.sheet.annotation.ExcelProperty;
7 7  
8 8 import java.time.LocalDateTime;
9 9  
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.time.LocalDateTime;
11 11  
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.time.LocalDateTime;
11 11  
... ...
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;
2 2  
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
6   -import cn.idev.excel.annotation.ExcelProperty;
7 5 import io.swagger.v3.oas.annotations.media.Schema;
8 6 import lombok.Data;
  7 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  8 +import org.apache.fesod.sheet.annotation.ExcelProperty;
9 9  
10 10 import java.time.LocalDateTime;
11 11  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import jakarta.validation.constraints.NotNull;
10 8 import lombok.Data;
  9 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  10 +import org.apache.fesod.sheet.annotation.ExcelProperty;
11 11  
12 12 import java.time.LocalDateTime;
13 13  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.time.LocalDateTime;
12 12  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.time.LocalDateTime;
12 12  
... ...
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;
3 3 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
4 4 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
5 5 import cn.iocoder.yudao.module.infra.enums.DictTypeConstants;
6   -import cn.idev.excel.annotation.ExcelIgnoreUnannotated;
7   -import cn.idev.excel.annotation.ExcelProperty;
8 6 import io.swagger.v3.oas.annotations.media.Schema;
9 7 import lombok.Data;
  8 +import org.apache.fesod.sheet.annotation.ExcelIgnoreUnannotated;
  9 +import org.apache.fesod.sheet.annotation.ExcelProperty;
10 10  
11 11 import java.time.LocalDateTime;
12 12  
... ...
yudao-module-infra/src/main/resources/codegen/java/controller/vo/importExcelVO.vm
1 1 package ${basePackage}.module.${table.moduleName}.controller.${sceneEnum.basePackage}.${table.businessName}.vo;
2 2  
3   -import cn.idev.excel.annotation.ExcelProperty;
  3 +import org.apache.fesod.sheet.annotation.ExcelProperty;
4 4 import lombok.AllArgsConstructor;
5 5 import lombok.Builder;
6 6 import lombok.Data;
... ...
yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm
... ... @@ -19,7 +19,7 @@ import java.time.LocalDateTime;
19 19 #end
20 20 #end
21 21 ## 处理 Excel 导出
22   -import cn.idev.excel.annotation.*;
  22 +import org.apache.fesod.sheet.annotation.*;
23 23 #foreach ($column in $columns)
24 24 #if ("$!column.dictType" != "")## 有设置数据字典
25 25 import ${DictFormatClassName};
... ...
yudao-module-infra/src/main/resources/codegen/java/dal/do.vm
... ... @@ -15,7 +15,7 @@ import ${BaseDOClassName};
15 15 ## 处理 Excel 导出 + Schema 注解(仅 DO 模式)
16 16 #if ($voType == 20)
17 17 import io.swagger.v3.oas.annotations.media.Schema;
18   -import cn.idev.excel.annotation.*;
  18 +import org.apache.fesod.sheet.annotation.*;
19 19 #foreach ($column in $columns)
20 20 #if ("$!column.dictType" != "")## 有设置数据字典
21 21 import ${DictFormatClassName};
... ...
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_erp/java/InfraStudentRespVO
... ... @@ -5,7 +5,7 @@ import lombok.*;
5 5 import java.util.*;
6 6 import org.springframework.format.annotation.DateTimeFormat;
7 7 import java.time.LocalDateTime;
8   -import cn.idev.excel.annotation.*;
  8 +import org.apache.fesod.sheet.annotation.*;
9 9 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
10 10 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
11 11  
... ...
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_inner/java/InfraStudentRespVO
... ... @@ -5,7 +5,7 @@ import lombok.*;
5 5 import java.util.*;
6 6 import org.springframework.format.annotation.DateTimeFormat;
7 7 import java.time.LocalDateTime;
8   -import cn.idev.excel.annotation.*;
  8 +import org.apache.fesod.sheet.annotation.*;
9 9 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
10 10 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
11 11  
... ...
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_master_normal/java/InfraStudentRespVO
... ... @@ -5,7 +5,7 @@ import lombok.*;
5 5 import java.util.*;
6 6 import org.springframework.format.annotation.DateTimeFormat;
7 7 import java.time.LocalDateTime;
8   -import cn.idev.excel.annotation.*;
  8 +import org.apache.fesod.sheet.annotation.*;
9 9 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
10 10 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
11 11  
... ...
yudao-module-infra/src/test/resources/codegen/vben5_antd_general_one/java/InfraStudentRespVO
... ... @@ -5,7 +5,7 @@ import lombok.*;
5 5 import java.util.*;
6 6 import org.springframework.format.annotation.DateTimeFormat;
7 7 import java.time.LocalDateTime;
8   -import cn.idev.excel.annotation.*;
  8 +import org.apache.fesod.sheet.annotation.*;
9 9 import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat;
10 10 import cn.iocoder.yudao.framework.excel.core.convert.DictConvert;
11 11  
... ...