From ce2a7d2c96df8f41ffc1557bea00bd4bbd34d09e Mon Sep 17 00:00:00 2001 From: Ken Date: Thu, 22 May 2025 13:30:27 +0800 Subject: [PATCH 01/81] =?UTF-8?q?feat(dict):=20=E5=AE=9E=E7=8E=B0=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E6=95=B0=E6=8D=AE=E5=AD=97=E5=85=B8=E6=A0=A1=E9=AA=8C?= =?UTF-8?q?=E6=B3=A8=E8=A7=A3=20@InDict=EF=BC=88#785=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新增注解 @InDict,用于在参数校验阶段判断传入值是否存在于指定的数据字典中。 BREAKING CHANGE: 无 Closes #785 --- .../yudao-spring-boot-starter-excel/pom.xml | 6 +++ .../dict/core/DictFrameworkUtils.java | 5 +++ .../framework/dict/validation/InDict.java | 38 ++++++++++++++++++ .../validation/InDictCollectionValidator.java | 40 +++++++++++++++++++ .../dict/validation/InDictValidator.java | 40 +++++++++++++++++++ 5 files changed, 129 insertions(+) create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java diff --git a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml index 0413986a64..0316c62e50 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml @@ -46,6 +46,12 @@ easyexcel + + jakarta.validation + jakarta.validation-api + provided + + com.google.guava guava diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/core/DictFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/core/DictFrameworkUtils.java index 9fc67bfe7f..2a2350f02b 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/core/DictFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/core/DictFrameworkUtils.java @@ -76,4 +76,9 @@ public class DictFrameworkUtils { return dictData!= null ? dictData.getValue(): null; } + @SneakyThrows + public static List getDictDataValueList(String dictType) { + List dictDatas = GET_DICT_DATA_CACHE.get(dictType); + return convertList(dictDatas, DictDataRespDTO::getValue); + } } diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java new file mode 100644 index 0000000000..dab0af782f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java @@ -0,0 +1,38 @@ +package cn.iocoder.yudao.framework.dict.validation; + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ + ElementType.METHOD, + ElementType.FIELD, + ElementType.ANNOTATION_TYPE, + ElementType.CONSTRUCTOR, + ElementType.PARAMETER, + ElementType.TYPE_USE +}) +@Retention(RetentionPolicy.RUNTIME) +@Documented +@Constraint( + validatedBy = {InDictValidator.class, InDictCollectionValidator.class} +) +public @interface InDict { + + /** + * 数据字典type + */ + String type(); + + String message() default "必须在指定范围 {value}"; + + Class[] groups() default {}; + + Class[] payload() default {}; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java new file mode 100644 index 0000000000..ab036171e2 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.framework.dict.validation; + +import cn.iocoder.yudao.framework.common.util.string.StrUtils; +import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +import java.util.Collection; +import java.util.List; + +public class InDictCollectionValidator implements ConstraintValidator> { + + private String dictType; + + @Override + public void initialize(InDict annotation) { + this.dictType = annotation.type(); + } + + @Override + public boolean isValid(Collection list, ConstraintValidatorContext context) { + if (list == null) { + return true; + } + List dbValues = DictFrameworkUtils.getDictDataValueList(dictType); + boolean match = list.stream().allMatch(v -> dbValues.stream() + .anyMatch(dbValue -> dbValue.equalsIgnoreCase(v.toString()))); + if (match) { + return true; + } + // 校验不通过,自定义提示语句 + context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值 + context.buildConstraintViolationWithTemplate( + context.getDefaultConstraintMessageTemplate().replaceAll("\\{value}",dbValues.toString()) + ).addConstraintViolation(); // 重新添加错误提示语句 + return false; + } + +} + diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java new file mode 100644 index 0000000000..05f50cb839 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.framework.dict.validation; + +import cn.iocoder.yudao.framework.common.util.string.StrUtils; +import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; + +import java.util.List; + +public class InDictValidator implements ConstraintValidator { + + private String dictType; + + @Override + public void initialize(InDict annotation) { + this.dictType = annotation.type(); + } + + @Override + public boolean isValid(Object value, ConstraintValidatorContext context) { + // 为空时,默认不校验,即认为通过 + if (value == null) { + return true; + } + // 校验通过 + final List values = DictFrameworkUtils.getDictDataValueList(dictType); + boolean match = values.stream().anyMatch(v -> v.equalsIgnoreCase(value.toString())); + if (match) { + return true; + } + // 校验不通过,自定义提示语句 + context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值 + context.buildConstraintViolationWithTemplate( + context.getDefaultConstraintMessageTemplate().replaceAll("\\{value}", values.toString()) + ).addConstraintViolation(); // 重新添加错误提示语句 + return false; + } + +} + From 3b2a3dd0ea75b4288b615436af0c1c98f32e1118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8A=8B=E9=81=93=E6=BA=90=E7=A0=81?= Date: Mon, 9 Jun 2025 06:36:11 +0000 Subject: [PATCH 02/81] =?UTF-8?q?fix:=20ERP=E7=BB=9F=E8=AE=A1=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=9C=A8=E5=A4=9A=E7=A7=9F=E6=88=B7=E5=85=B3=E9=97=AD?= =?UTF-8?q?=E6=97=B6=E7=9A=84NullPointerException=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复ErpSaleStatisticsMapper.xml中硬编码使用getRequiredTenantId()导致的空指针异常 - 修复ErpPurchaseStatisticsMapper.xml中硬编码使用getRequiredTenantId()导致的空指针异常 - 使用条件判断getTenantId() != null来决定是否添加租户条件 - 添加单元测试验证多租户开启和关闭时的统计查询功能 - 确保向后兼容,多租户开启时正常工作,关闭时不报错 --- .../ErpPurchaseStatisticsMapper.xml | 8 +- .../statistics/ErpSaleStatisticsMapper.xml | 8 +- .../statistics/ErpStatisticsServiceTest.java | 155 ++++++++++++++++++ 3 files changed, 167 insertions(+), 4 deletions(-) create mode 100644 yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java diff --git a/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml b/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml index 699286b5da..a88fb3a88c 100644 --- a/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml +++ b/yudao-module-erp/src/main/resources/mapper/statistics/ErpPurchaseStatisticsMapper.xml @@ -10,7 +10,9 @@ AND in_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) - (SELECT IFNULL(SUM(total_price), 0) FROM erp_purchase_return @@ -18,7 +20,9 @@ AND return_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) diff --git a/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml b/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml index 324cbd432b..3e04ee706e 100644 --- a/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml +++ b/yudao-module-erp/src/main/resources/mapper/statistics/ErpSaleStatisticsMapper.xml @@ -10,7 +10,9 @@ AND out_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) - (SELECT IFNULL(SUM(total_price), 0) FROM erp_sale_return @@ -18,7 +20,9 @@ AND return_time < #{endTime} - AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getRequiredTenantId()} + + AND tenant_id = ${@cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder@getTenantId()} + AND deleted = 0) diff --git a/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java b/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java new file mode 100644 index 0000000000..c96f2d35fa --- /dev/null +++ b/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java @@ -0,0 +1,155 @@ +package cn.iocoder.yudao.module.erp.service.statistics; + +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpPurchaseStatisticsMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpSaleStatisticsMapper; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.test.context.ActiveProfiles; + +import jakarta.annotation.Resource; +import java.math.BigDecimal; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.when; + +/** + * ERP 统计服务测试类 + * 主要测试在多租户关闭情况下,统计查询是否能正常工作 + * + * @author 芋道源码 + */ +@SpringBootTest +@ActiveProfiles("unit-test") +public class ErpStatisticsServiceTest { + + @Resource + private ErpSaleStatisticsService saleStatisticsService; + + @Resource + private ErpPurchaseStatisticsService purchaseStatisticsService; + + @MockBean + private ErpSaleStatisticsMapper saleStatisticsMapper; + + @MockBean + private ErpPurchaseStatisticsMapper purchaseStatisticsMapper; + + @BeforeEach + void setUp() { + // 清理租户上下文 + TenantContextHolder.clear(); + } + + @AfterEach + void tearDown() { + // 清理租户上下文 + TenantContextHolder.clear(); + } + + @Test + void testSaleStatisticsWithoutTenant() { + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("1000.00"); + + // Mock 返回值 + when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在没有租户ID的情况下调用销售统计 + assertDoesNotThrow(() -> { + BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户关闭时,销售统计查询应该能正常工作"); + } + + @Test + void testPurchaseStatisticsWithoutTenant() { + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("800.00"); + + // Mock 返回值 + when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在没有租户ID的情况下调用采购统计 + assertDoesNotThrow(() -> { + BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户关闭时,采购统计查询应该能正常工作"); + } + + @Test + void testSaleStatisticsWithTenant() { + // 设置租户ID + Long tenantId = 1L; + TenantContextHolder.setTenantId(tenantId); + + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("1500.00"); + + // Mock 返回值 + when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在有租户ID的情况下调用销售统计 + assertDoesNotThrow(() -> { + BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户开启时,销售统计查询应该能正常工作"); + + // 验证租户ID是否正确设置 + assertEquals(tenantId, TenantContextHolder.getTenantId()); + } + + @Test + void testPurchaseStatisticsWithTenant() { + // 设置租户ID + Long tenantId = 2L; + TenantContextHolder.setTenantId(tenantId); + + // 准备参数 + LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); + LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); + BigDecimal expectedPrice = new BigDecimal("1200.00"); + + // Mock 返回值 + when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) + .thenReturn(expectedPrice); + + // 测试:在有租户ID的情况下调用采购统计 + assertDoesNotThrow(() -> { + BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); + assertEquals(expectedPrice, result); + }, "在多租户开启时,采购统计查询应该能正常工作"); + + // 验证租户ID是否正确设置 + assertEquals(tenantId, TenantContextHolder.getTenantId()); + } + + @Test + void testTenantContextHolderMethods() { + // 测试 getTenantId() 在没有设置租户时返回 null + assertNull(TenantContextHolder.getTenantId(), "未设置租户时应该返回 null"); + + // 设置租户ID + Long tenantId = 3L; + TenantContextHolder.setTenantId(tenantId); + assertEquals(tenantId, TenantContextHolder.getTenantId(), "设置租户后应该能正确获取"); + + // 清理租户上下文 + TenantContextHolder.clear(); + assertNull(TenantContextHolder.getTenantId(), "清理后应该返回 null"); + } +} From 9dec02d02ec0721481392e3774be8131d2dc26e8 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Tue, 10 Jun 2025 14:51:41 +0800 Subject: [PATCH 03/81] =?UTF-8?q?feat:=20=E4=BD=BF=E7=94=A8=20fastExcel=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=20easyExcel=20(https://github.com/fast-excel?= =?UTF-8?q?/fastexcel)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 21 +++++-------------- .../yudao-spring-boot-starter-excel/pom.xml | 9 ++------ .../excel/core/convert/AreaConvert.java | 10 ++++----- .../excel/core/convert/DictConvert.java | 12 +++++------ .../excel/core/convert/JsonConvert.java | 10 ++++----- .../excel/core/convert/MoneyConvert.java | 10 ++++----- .../core/handler/SelectSheetWriteHandler.java | 10 ++++----- .../framework/excel/core/util/ExcelUtils.java | 6 +++--- .../BpmProcessExpressionRespVO.java | 4 ++-- .../vo/business/CrmBusinessRespVO.java | 4 ++-- .../admin/clue/vo/CrmClueRespVO.java | 4 ++-- .../admin/contact/vo/CrmContactRespVO.java | 4 ++-- .../vo/contract/CrmContractRespVO.java | 4 ++-- .../vo/customer/CrmCustomerImportExcelVO.java | 2 +- .../vo/customer/CrmCustomerRespVO.java | 4 ++-- .../followup/vo/CrmFollowUpRecordRespVO.java | 6 +++--- .../operatelog/vo/CrmOperateLogRespVO.java | 2 +- .../category/CrmProductCategoryListReqVO.java | 2 +- .../product/vo/product/CrmProductRespVO.java | 4 ++-- .../vo/plan/CrmReceivablePlanRespVO.java | 4 ++-- .../vo/receivable/CrmReceivableRespVO.java | 4 ++-- .../finance/vo/account/ErpAccountRespVO.java | 6 +++--- .../vo/payment/ErpFinancePaymentRespVO.java | 6 +++--- .../vo/receipt/ErpFinanceReceiptRespVO.java | 6 +++--- .../vo/category/ErpProductCategoryRespVO.java | 6 +++--- .../product/vo/product/ErpProductRespVO.java | 6 +++--- .../product/vo/unit/ErpProductUnitRespVO.java | 6 +++--- .../purchase/vo/in/ErpPurchaseInRespVO.java | 6 +++--- .../vo/order/ErpPurchaseOrderRespVO.java | 6 +++--- .../vo/returns/ErpPurchaseReturnRespVO.java | 6 +++--- .../vo/supplier/ErpSupplierRespVO.java | 6 +++--- .../sale/vo/customer/ErpCustomerRespVO.java | 7 ++----- .../sale/vo/order/ErpSaleOrderRespVO.java | 6 +++--- .../admin/sale/vo/out/ErpSaleOutRespVO.java | 6 +++--- .../sale/vo/returns/ErpSaleReturnRespVO.java | 6 +++--- .../stock/vo/check/ErpStockCheckRespVO.java | 6 +++--- .../admin/stock/vo/in/ErpStockInRespVO.java | 6 +++--- .../stock/vo/move/ErpStockMoveRespVO.java | 6 +++--- .../admin/stock/vo/out/ErpStockOutRespVO.java | 6 +++--- .../stock/vo/record/ErpStockRecordRespVO.java | 6 +++--- .../admin/stock/vo/stock/ErpStockRespVO.java | 6 +++--- .../vo/warehouse/ErpWarehouseRespVO.java | 6 +++--- .../admin/config/vo/ConfigRespVO.java | 4 ++-- .../demo/demo01/vo/Demo01ContactRespVO.java | 6 +++--- .../demo/demo02/vo/Demo02CategoryRespVO.java | 6 +++--- .../demo03/erp/vo/Demo03StudentErpRespVO.java | 6 +++--- .../inner/vo/Demo03StudentInnerRespVO.java | 6 +++--- .../normal/vo/Demo03StudentNormalRespVO.java | 6 +++--- .../admin/job/vo/job/JobRespVO.java | 4 ++-- .../admin/job/vo/log/JobLogRespVO.java | 4 ++-- .../vo/apiaccesslog/ApiAccessLogRespVO.java | 4 ++-- .../vo/apierrorlog/ApiErrorLogRespVO.java | 4 ++-- .../codegen/java/controller/vo/respVO.vm | 4 ++-- .../src/main/resources/codegen/java/dal/do.vm | 4 ++-- .../vue2_master_erp/java/InfraStudentRespVO | 4 ++-- .../vue2_master_inner/java/InfraStudentRespVO | 4 ++-- .../java/InfraStudentRespVO | 4 ++-- .../vue2_one/java/InfraStudentRespVO | 4 ++-- .../vue2_tree/java/InfraCategoryRespVO | 4 ++-- .../vue3_master_erp/java/InfraStudentRespVO | 4 ++-- .../vue3_master_inner/java/InfraStudentRespVO | 4 ++-- .../java/InfraStudentRespVO | 4 ++-- .../vue3_one/java/InfraStudentRespVO | 4 ++-- .../vue3_tree/java/InfraCategoryRespVO | 4 ++-- .../vo/device/IotDeviceImportExcelVO.java | 4 ++-- .../IotDeviceMqttConnectionParamsRespVO.java | 6 +++--- .../device/vo/device/IotDeviceRespVO.java | 6 +++--- .../product/vo/product/IotProductRespVO.java | 6 +++--- .../thingmodel/vo/IotThingModelRespVO.java | 6 +++--- .../vo/ProductBrowseHistoryRespVO.java | 2 +- .../admin/spu/vo/ProductSpuRespVO.java | 4 ++-- .../kefu/vo/message/KeFuMessageRespVO.java | 3 +-- .../vo/activity/PointActivityRespVO.java | 6 +++--- .../point/vo/product/PointProductRespVO.java | 4 ++-- .../app/point/vo/AppPointActivityRespVO.java | 2 +- .../product/vo/ProductStatisticsRespVO.java | 6 +++--- .../trade/vo/TradeTrendSummaryExcelVO.java | 4 ++-- .../vo/express/DeliveryExpressExcelVO.java | 2 +- .../admin/order/vo/PayOrderExcelVO.java | 2 +- .../admin/refund/vo/PayRefundExcelVO.java | 2 +- .../admin/transfer/vo/PayTransferRespVO.java | 4 ++-- .../admin/dept/vo/post/PostRespVO.java | 4 ++-- .../admin/dept/vo/post/PostSimpleRespVO.java | 2 +- .../admin/dict/vo/data/DictDataRespVO.java | 4 ++-- .../admin/dict/vo/type/DictTypeRespVO.java | 4 ++-- .../logger/vo/loginlog/LoginLogRespVO.java | 4 ++-- .../vo/operatelog/OperateLogRespVO.java | 4 ++-- .../admin/permission/vo/role/RoleRespVO.java | 4 ++-- .../admin/sms/vo/log/SmsLogRespVO.java | 4 ++-- .../sms/vo/template/SmsTemplateRespVO.java | 4 ++-- .../admin/tenant/vo/tenant/TenantRespVO.java | 4 ++-- .../admin/user/vo/user/UserImportExcelVO.java | 2 +- .../admin/user/vo/user/UserRespVO.java | 4 ++-- 93 files changed, 227 insertions(+), 247 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index f7f615b492..63e31b0886 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -54,7 +54,7 @@ 1.6.3 5.8.35 6.0.0-M19 - 4.0.3 + 1.2.0 2.4.1 1.2.83 33.4.8-jre @@ -69,8 +69,6 @@ 0.9.0 4.5.13 - 2.17.0 - 1.27.1 2.30.14 1.16.7 1.4.0 @@ -479,20 +477,11 @@ - com.alibaba - easyexcel - ${easyexcel.version} - - - commons-io - commons-io - ${commons-io.version} - - - org.apache.commons - commons-compress - ${commons-compress.version} + cn.idev.excel + fastexcel + ${fastexcel.version} + org.apache.tika tika-core diff --git a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml index 0413986a64..b4af03d033 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-excel/pom.xml @@ -42,8 +42,8 @@ - com.alibaba - easyexcel + cn.idev.excel + fastexcel @@ -51,11 +51,6 @@ guava - - org.apache.commons - commons-compress - - cn.iocoder.boot yudao-spring-boot-starter-biz-ip diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java index 9778b17aea..b5ca863173 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/AreaConvert.java @@ -3,11 +3,11 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.hutool.core.convert.Convert; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.utils.AreaUtils; -import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.metadata.data.ReadCellData; -import com.alibaba.excel.metadata.property.ExcelContentProperty; +import cn.idev.excel.converters.Converter; +import cn.idev.excel.enums.CellDataTypeEnum; +import cn.idev.excel.metadata.GlobalConfiguration; +import cn.idev.excel.metadata.data.ReadCellData; +import cn.idev.excel.metadata.property.ExcelContentProperty; import lombok.extern.slf4j.Slf4j; /** diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java index e393195ed1..b9e0dcb735 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/DictConvert.java @@ -3,12 +3,12 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.hutool.core.convert.Convert; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.metadata.data.ReadCellData; -import com.alibaba.excel.metadata.data.WriteCellData; -import com.alibaba.excel.metadata.property.ExcelContentProperty; +import cn.idev.excel.converters.Converter; +import cn.idev.excel.enums.CellDataTypeEnum; +import cn.idev.excel.metadata.GlobalConfiguration; +import cn.idev.excel.metadata.data.ReadCellData; +import cn.idev.excel.metadata.data.WriteCellData; +import cn.idev.excel.metadata.property.ExcelContentProperty; import lombok.extern.slf4j.Slf4j; /** diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java index 0d4794e5fa..6958c32e0c 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/JsonConvert.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.framework.excel.core.convert; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.metadata.data.WriteCellData; -import com.alibaba.excel.metadata.property.ExcelContentProperty; +import cn.idev.excel.converters.Converter; +import cn.idev.excel.enums.CellDataTypeEnum; +import cn.idev.excel.metadata.GlobalConfiguration; +import cn.idev.excel.metadata.data.WriteCellData; +import cn.idev.excel.metadata.property.ExcelContentProperty; /** * Excel Json 转换器 diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java index ee66fe7dec..9ed0bd581f 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/convert/MoneyConvert.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.excel.core.convert; -import com.alibaba.excel.converters.Converter; -import com.alibaba.excel.enums.CellDataTypeEnum; -import com.alibaba.excel.metadata.GlobalConfiguration; -import com.alibaba.excel.metadata.data.WriteCellData; -import com.alibaba.excel.metadata.property.ExcelContentProperty; +import cn.idev.excel.converters.Converter; +import cn.idev.excel.enums.CellDataTypeEnum; +import cn.idev.excel.metadata.GlobalConfiguration; +import cn.idev.excel.metadata.data.WriteCellData; +import cn.idev.excel.metadata.property.ExcelContentProperty; import java.math.BigDecimal; import java.math.RoundingMode; diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java index ef1eb65bcd..754fa1f7c0 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java @@ -10,10 +10,10 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction; -import com.alibaba.excel.annotation.ExcelProperty; -import com.alibaba.excel.write.handler.SheetWriteHandler; -import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import cn.idev.excel.annotation.ExcelProperty; +import cn.idev.excel.write.handler.SheetWriteHandler; +import cn.idev.excel.write.metadata.holder.WriteSheetHolder; +import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder; import lombok.extern.slf4j.Slf4j; import org.apache.poi.hssf.usermodel.HSSFDataValidation; import org.apache.poi.ss.usermodel.*; @@ -155,4 +155,4 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { writeSheetHolder.getSheet().addValidationData(validation); } -} \ No newline at end of file +} diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index eb037d9e17..bae20d6c53 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.framework.excel.core.util; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; -import com.alibaba.excel.EasyExcel; -import com.alibaba.excel.converters.longconverter.LongStringConverter; -import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import cn.idev.excel.EasyExcel; +import cn.idev.excel.converters.longconverter.LongStringConverter; +import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java index d877f60a88..7ce45b3350 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/expression/BpmProcessExpressionRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.expression; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -27,4 +27,4 @@ public class BpmProcessExpressionRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java index 49cdcb80be..d94c856210 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index 56e5c25612..911f48d130 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java index b2b1e83848..e198531179 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/vo/CrmContactRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.contact.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.ToString; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java index a01bc110b9..307a7472fb 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/contract/CrmContractRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java index a45e9115fe..07d86a4f03 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerImportExcelVO.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.convert.AreaConvert; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.framework.excel.core.AreaExcelColumnSelectFunction; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java index 236129918c..1b337282ac 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/customer/CrmCustomerRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo.customer; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java index 1ce10b73e3..075c3b360f 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.followup.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -61,4 +61,4 @@ public class CrmFollowUpRecordRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java index 8e458a8a0f..a9c2a7a701 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java index 6144c95c4d..c8e181e341 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/category/CrmProductCategoryListReqVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.product.vo.category; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java index aa955a9f4e..5ef01a37f5 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/vo/product/CrmProductRespVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import com.fhs.core.trans.anno.Trans; import com.fhs.core.trans.constant.TransType; import com.fhs.core.trans.vo.VO; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java index ad1ce3a7b7..2208887db5 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.plan; import cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable.CrmReceivableRespVO; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java index 6d712e3a54..75827db68f 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivableRespVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.contract.CrmContractRespVO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java index a1c2e954db..3e03169689 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -47,4 +47,4 @@ public class ErpAccountRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java index 12b5a7df8e..df89465f00 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -96,4 +96,4 @@ public class ErpFinancePaymentRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java index ec82875957..2398e065ca 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -96,4 +96,4 @@ public class ErpFinanceReceiptRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java index 23d7d9e8ff..29d4c2fd6e 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -44,4 +44,4 @@ public class ErpProductCategoryRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java index 9be9bc2559..8dcc9f89ba 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -73,4 +73,4 @@ public class ErpProductRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java index 06f604920c..3044d5aef1 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -31,4 +31,4 @@ public class ErpProductUnitRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java index beeeab8692..03c446ed1c 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -142,4 +142,4 @@ public class ErpPurchaseInRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java index bc76720eed..e6a6aa4f64 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -149,4 +149,4 @@ public class ErpPurchaseOrderRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java index 223b9327e9..676241949c 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -142,4 +142,4 @@ public class ErpPurchaseReturnRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java index 5ba5892c1b..538a3b1e60 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -81,4 +81,4 @@ public class ErpSupplierRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java index f1a58a03d5..c75a99a086 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java @@ -2,12 +2,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; -import java.util.*; -import java.util.*; import java.math.BigDecimal; -import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -81,4 +78,4 @@ public class ErpCustomerRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index e5958a841f..b1374e8248 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -152,4 +152,4 @@ public class ErpSaleOrderRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index bc15a13398..a004ed3889 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -145,4 +145,4 @@ public class ErpSaleOutRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java index ba52f4f80d..6a1ade0b33 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -145,4 +145,4 @@ public class ErpSaleReturnRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java index af53e3c726..6f9b8da0f8 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -108,4 +108,4 @@ public class ErpStockCheckRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index 077b9dd1b6..1d23f3692c 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -107,4 +107,4 @@ public class ErpStockInRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java index 799ddc3f16..f5f7650aee 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -104,4 +104,4 @@ public class ErpStockMoveRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java index 22a88e7c93..a1d0f51016 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -107,4 +107,4 @@ public class ErpStockOutRespVO { } -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java index ff4b3e12a1..47e1261831 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.erp.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -84,4 +84,4 @@ public class ErpStockRecordRespVO { @ExcelProperty("创建人") private String creatorName; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java index 06366a0dd4..8d84789901 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -46,4 +46,4 @@ public class ErpStockRespVO { @ExcelProperty("仓库名称") private String warehouseName; -} \ No newline at end of file +} diff --git a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java index 188d426997..06825b848b 100644 --- a/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java +++ b/yudao-module-erp/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -61,4 +61,4 @@ public class ErpWarehouseRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java index b4f642f697..622bb04269 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/config/vo/ConfigRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.config.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java index 17ee9fef84..df0ef60401 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo01/vo/Demo01ContactRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo01.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -43,4 +43,4 @@ public class Demo01ContactRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java index 1f2efd46a7..bac533bca6 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo02/vo/Demo02CategoryRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo02.vo; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -28,4 +28,4 @@ public class Demo02CategoryRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java index 84dfe6e037..30944843f5 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/erp/vo/Demo03StudentErpRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.erp.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -39,4 +39,4 @@ public class Demo03StudentErpRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java index 48d5e4889a..3db315b3ea 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/inner/vo/Demo03StudentInnerRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.inner.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -39,4 +39,4 @@ public class Demo03StudentInnerRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java index e36a7965c1..f100c80dce 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/demo/demo03/normal/vo/Demo03StudentNormalRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.demo.demo03.normal.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -39,4 +39,4 @@ public class Demo03StudentNormalRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java index aee0d9bcf1..9a4be2eafe 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/job/JobRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.job.vo.job; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; import lombok.Data; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java index 543339d695..3574e98d59 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/job/vo/log/JobLogRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.job.vo.log; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java index d9e65c403c..45fc4df130 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apiaccesslog/ApiAccessLogRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apiaccesslog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java index a3f6f0e84c..7097924e96 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/logger/vo/apierrorlog/ApiErrorLogRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.infra.controller.admin.logger.vo.apierrorlog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.infra.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm index 24c3519451..eae083a893 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/controller/vo/respVO.vm @@ -19,7 +19,7 @@ import java.time.LocalDateTime; #end #end ## 处理 Excel 导出 -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; #foreach ($column in $columns) #if ("$!column.dictType" != "")## 有设置数据字典 import ${DictFormatClassName}; @@ -50,4 +50,4 @@ public class ${sceneEnum.prefixClass}${table.className}RespVO { #end #end -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm b/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm index baf53f5986..f15ada4309 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/dal/do.vm @@ -15,7 +15,7 @@ import ${BaseDOClassName}; ## 处理 Excel 导出 + Schema 注解(仅 DO 模式) #if ($voType == 20) import io.swagger.v3.oas.annotations.media.Schema; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; #foreach ($column in $columns) #if ("$!column.dictType" != "")## 有设置数据字典 import ${DictFormatClassName}; @@ -100,4 +100,4 @@ public class ${table.className}DO extends BaseDO { #end #end -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_erp/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_erp/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_inner/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_inner/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_normal/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_master_normal/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_one/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_one/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_tree/java/InfraCategoryRespVO index 6325d866c5..335881c4b7 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue2_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue2_tree/java/InfraCategoryRespVO @@ -4,7 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; import java.util.*; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data @@ -23,4 +23,4 @@ public class InfraCategoryRespVO { @ExcelProperty("父编号") private Long parentId; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_erp/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_erp/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_erp/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_erp/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_inner/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_inner/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_inner/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_inner/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_normal/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_normal/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_normal/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_master_normal/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_one/java/InfraStudentRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_one/java/InfraStudentRespVO index c41a5501fe..f86f6791c4 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_one/java/InfraStudentRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_one/java/InfraStudentRespVO @@ -6,7 +6,7 @@ import java.util.*; import java.util.*; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; @@ -57,4 +57,4 @@ public class InfraStudentRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_tree/java/InfraCategoryRespVO b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_tree/java/InfraCategoryRespVO index 6325d866c5..335881c4b7 100644 --- a/yudao-module-infra/src/test/resources/codegen/windows10/vue3_tree/java/InfraCategoryRespVO +++ b/yudao-module-infra/src/test/resources/codegen/windows10/vue3_tree/java/InfraCategoryRespVO @@ -4,7 +4,7 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.util.*; import java.util.*; -import com.alibaba.excel.annotation.*; +import cn.idev.excel.annotation.*; @Schema(description = "管理后台 - 分类 Response VO") @Data @@ -23,4 +23,4 @@ public class InfraCategoryRespVO { @ExcelProperty("父编号") private Long parentId; -} \ No newline at end of file +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java index 710e74263d..74585be565 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceImportExcelVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import lombok.AllArgsConstructor; @@ -34,4 +34,4 @@ public class IotDeviceImportExcelVO { @ExcelProperty("设备分组") private String groupNames; -} \ No newline at end of file +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceMqttConnectionParamsRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceMqttConnectionParamsRespVO.java index 5ce68c0fe1..39d80c527d 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceMqttConnectionParamsRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceMqttConnectionParamsRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -22,4 +22,4 @@ public class IotDeviceMqttConnectionParamsRespVO { @ExcelProperty("MQTT 密码") private String mqttPassword; -} \ No newline at end of file +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java index 8404ca9224..74ef173afc 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/device/vo/device/IotDeviceRespVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.iot.controller.admin.device.vo.device; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -90,4 +90,4 @@ public class IotDeviceRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java index f674651d51..0455334652 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/product/IotProductRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.controller.admin.product.vo.product; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.iot.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -84,4 +84,4 @@ public class IotProductRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java index 15a5b9f959..9de915dc43 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thingmodel/vo/IotThingModelRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.iot.controller.admin.thingmodel.vo; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelEvent; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelProperty; import cn.iocoder.yudao.module.iot.controller.admin.thingmodel.model.ThingModelService; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -51,4 +51,4 @@ public class IotThingModelRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java index df8ae8c5bd..56ebc283fe 100644 --- a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.product.controller.admin.history.vo; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java index fbc75522a7..d962fe7469 100755 --- a/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java +++ b/yudao-module-mall/yudao-module-product/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuRespVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.product.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java index 248160dd9c..059d6af579 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/kefu/vo/message/KeFuMessageRespVO.java @@ -4,7 +4,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.time.LocalDateTime; -import com.alibaba.excel.annotation.*; @Schema(description = "管理后台 - 客服消息 Response VO") @Data @@ -42,4 +41,4 @@ public class KeFuMessageRespVO { @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java index d81b3d6902..14f1ee4ccd 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/activity/PointActivityRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.promotion.controller.admin.point.vo.activity; import cn.iocoder.yudao.module.promotion.controller.admin.point.vo.product.PointProductRespVO; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -69,4 +69,4 @@ public class PointActivityRespVO { @Schema(description = "兑换金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "15860") private Integer price; -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java index 8e8250b387..638ea61fb8 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/vo/product/PointProductRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.admin.point.vo.product; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -36,4 +36,4 @@ public class PointProductRespVO { @Schema(description = "积分商城商品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") private Integer activityStatus; -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java index ddcc23b9cb..83e00c202a 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/vo/AppPointActivityRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.promotion.controller.app.point.vo; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java index 9d93142e31..86126ca705 100644 --- a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java +++ b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/product/vo/ProductStatisticsRespVO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.statistics.controller.admin.product.vo; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import com.fasterxml.jackson.annotation.JsonFormat; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -78,4 +78,4 @@ public class ProductStatisticsRespVO { @Schema(description = "访客支付转化率(百分比)", requiredMode = Schema.RequiredMode.REQUIRED, example = "15") private Integer browseConvertPercent; -} \ No newline at end of file +} diff --git a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java index 5b14fa1d4e..9e27c6f3a1 100644 --- a/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java +++ b/yudao-module-mall/yudao-module-statistics/src/main/java/cn/iocoder/yudao/module/statistics/controller/admin/trade/vo/TradeTrendSummaryExcelVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.statistics.controller.admin.trade.vo; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; -import com.alibaba.excel.annotation.ExcelProperty; -import com.alibaba.excel.annotation.format.DateTimeFormat; +import cn.idev.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.format.DateTimeFormat; import lombok.Data; import java.time.LocalDate; diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java index c84a3a1896..3cc312a913 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/delivery/vo/express/DeliveryExpressExcelVO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.trade.controller.admin.delivery.vo.express; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; import java.time.LocalDateTime; diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java index 5dc17a0f0c..1cb362541e 100755 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/vo/PayOrderExcelVO.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; import java.time.LocalDateTime; diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java index 758b6b6b09..8794086616 100755 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/vo/PayRefundExcelVO.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import lombok.Data; import java.time.LocalDateTime; diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java index 9e98db1170..5c2ac3fa82 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.MoneyConvert; import cn.iocoder.yudao.module.pay.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; import java.time.LocalDateTime; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java index dde6f95097..18ccb7ffad 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java index 72852a18e3..d019ad7235 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dept/vo/post/PostSimpleRespVO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.system.controller.admin.dept.vo.post; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java index 8857a7059c..fce51e99c6 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/data/DictDataRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.data; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java index 6ddd47bcd8..2301a7526a 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/dict/vo/type/DictTypeRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.dict.vo.type; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java index 7b9cd165e2..9abe3aa53b 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/loginlog/LoginLogRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.logger.vo.loginlog; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java index e017ba7cbe..436d209066 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/vo/operatelog/OperateLogRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import com.fhs.core.trans.anno.Trans; import com.fhs.core.trans.constant.TransType; import com.fhs.core.trans.vo.VO; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java index 89f80c6724..c1c7cfea62 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/permission/vo/role/RoleRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.permission.vo.role; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java index 77409ed918..66a867fd0d 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/log/SmsLogRespVO.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.framework.excel.core.convert.JsonConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java index 6b8aecaaad..9caed5c49b 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/vo/template/SmsTemplateRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.sms.vo.template; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java index 5a444b5213..62ccb7c611 100755 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/tenant/vo/tenant/TenantRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java index a360f1af2c..0c7c5a3c33 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserImportExcelVO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelProperty; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java index 2837318f9a..ba322240e2 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserRespVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; +import cn.idev.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; From 1d5c07706247821a3649bd42d265a76c3c92a7f7 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Sun, 15 Jun 2025 18:55:42 +0800 Subject: [PATCH 04/81] =?UTF-8?q?feat:=20=E4=BD=BF=E7=94=A8=20fastExcel=20?= =?UTF-8?q?=E6=9B=BF=E6=8D=A2=20easyExcel=20(https://github.com/fast-excel?= =?UTF-8?q?/fastexcel)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/core/handler/SelectSheetWriteHandler.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java index 0cace13ac8..cd6c87f68f 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.framework.excel.core.handler; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.ReflectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.poi.excel.ExcelUtil; @@ -11,12 +10,8 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import cn.iocoder.yudao.framework.excel.core.annotations.ExcelColumnSelect; import cn.iocoder.yudao.framework.excel.core.function.ExcelColumnSelectFunction; -import com.alibaba.excel.annotation.ExcelIgnore; -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import com.alibaba.excel.annotation.ExcelProperty; -import com.alibaba.excel.write.handler.SheetWriteHandler; -import com.alibaba.excel.write.metadata.holder.WriteSheetHolder; -import com.alibaba.excel.write.metadata.holder.WriteWorkbookHolder; +import cn.idev.excel.annotation.ExcelIgnore; +import cn.idev.excel.annotation.ExcelIgnoreUnannotated; import cn.idev.excel.annotation.ExcelProperty; import cn.idev.excel.write.handler.SheetWriteHandler; import cn.idev.excel.write.metadata.holder.WriteSheetHolder; From a5ad8bb708d708ef5e9d2a2e7bc12deb99ee924e Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 18 Jun 2025 12:45:22 +0800 Subject: [PATCH 05/81] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0MP4=E6=96=87=E4=BB=B6=E4=B9=8B=E5=90=8E=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E4=B8=8B=E8=BD=BD=E8=BF=9E=E6=8E=A5=E4=B8=8B=E8=BD=BD?= =?UTF-8?q?MP4=E6=96=87=E4=BB=B6=E6=BA=90=E6=96=87=E4=BB=B6=E8=83=BD?= =?UTF-8?q?=E9=80=9A=E8=BF=87windows=E8=87=AA=E5=B8=A6=E6=92=AD=E6=94=BE?= =?UTF-8?q?=E5=99=A8=E6=92=AD=E6=94=BE=E4=B8=8B=E8=BD=BD=E4=B8=8B=E6=9D=A5?= =?UTF-8?q?=E7=9A=84=E6=92=AD=E6=94=BE=E4=B8=8D=E4=BA=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../infra/framework/file/core/utils/FileTypeUtils.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java index e2c607842f..9cc4175884 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/framework/file/core/utils/FileTypeUtils.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.infra.framework.file.core.utils; import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.http.HttpUtils; -import com.alibaba.ttl.TransmittableThreadLocal; import jakarta.servlet.http.HttpServletResponse; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; @@ -86,8 +85,8 @@ public class FileTypeUtils { response.setContentType(contentType); // 针对 video 的特殊处理,解决视频地址在移动端播放的兼容性问题 if (StrUtil.containsIgnoreCase(contentType, "video")) { - response.setHeader("Content-Length", String.valueOf(content.length - 1)); - response.setHeader("Content-Range", String.valueOf(content.length - 1)); + response.setHeader("Content-Length", String.valueOf(content.length)); + response.setHeader("Content-Range", "bytes 0-" + (content.length - 1) + "/" + content.length); response.setHeader("Accept-Ranges", "bytes"); } // 输出附件 From 9fc4a4061fc9a5a32ad339338610126a85e1b785 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 18 Jun 2025 15:40:51 +0800 Subject: [PATCH 06/81] =?UTF-8?q?fix:=20=E5=88=9B=E5=BB=BA=E6=8B=BC?= =?UTF-8?q?=E5=9B=A2=E6=B4=BB=E5=8A=A8=E6=97=B6=E6=A0=A1=E9=AA=8C=E5=95=86?= =?UTF-8?q?=E5=93=81=E6=98=AF=E5=90=A6=E5=8F=82=E4=B8=8E=E4=BA=86=E5=85=B6?= =?UTF-8?q?=E5=AE=83=E6=B4=BB=E5=8A=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/combination/CombinationActivityServiceImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java index 8e168f4f9f..f5b38a13cc 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/combination/CombinationActivityServiceImpl.java @@ -86,7 +86,7 @@ public class CombinationActivityServiceImpl implements CombinationActivityServic activityList.removeIf(item -> ObjectUtil.equal(item.getId(), activityId)); } // 查找是否有其它活动,选择了该产品 - List matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getId(), spuId)); + List matchActivityList = filterList(activityList, activity -> ObjectUtil.equal(activity.getSpuId(), spuId)); if (CollUtil.isNotEmpty(matchActivityList)) { throw exception(COMBINATION_ACTIVITY_SPU_CONFLICTS); } From cac82a13a7db455751159901c666a77d74feb171 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Wed, 18 Jun 2025 17:23:59 +0800 Subject: [PATCH 07/81] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E6=8B=BC?= =?UTF-8?q?=E5=9B=A2=E8=BF=98=E6=B2=A1=E6=88=90=E5=9B=A2=EF=BC=8C=E8=99=9A?= =?UTF-8?q?=E6=8B=9F=E6=88=90=E5=9B=A2=E6=98=AF=E5=90=A6=EF=BC=8C=E8=BF=99?= =?UTF-8?q?=E4=B8=AA=E6=97=B6=E5=80=99=E6=A0=B8=E9=94=80=E4=B9=9F=E8=83=BD?= =?UTF-8?q?=E6=A0=B8=E9=94=80=E6=88=90=E5=8A=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/trade/enums/ErrorCodeConstants.java | 3 ++- .../service/order/TradeOrderUpdateServiceImpl.java | 13 +++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java index b2d72e4b01..8ec1159244 100644 --- a/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java +++ b/yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java @@ -39,7 +39,8 @@ public interface ErrorCodeConstants { ErrorCode ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_NOT_FOUND = new ErrorCode(1_011_000_034, "交易订单更新支付订单退款状态失败,原因:退款单不存在"); ErrorCode ORDER_UPDATE_PAID_ORDER_REFUNDED_FAIL_REFUND_STATUS_NOT_SUCCESS = new ErrorCode(1_011_000_035, "交易订单更新支付订单退款状态失败,原因:退款单状态不是【退款成功】"); ErrorCode ORDER_PICK_UP_FAIL_NOT_VERIFY_USER = new ErrorCode(1_011_000_036, "交易订单自提失败,原因:你没有核销该门店订单的权限"); - ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_037, "交易订单创建失败,原因:用户积分不足"); + ErrorCode ORDER_PICK_UP_FAIL_COMBINATION_NOT_SUCCESS = new ErrorCode(1_011_000_037, "交易订单自提失败,原因:商品拼团记录不是【成功】状态"); + ErrorCode ORDER_CREATE_FAIL_INSUFFICIENT_USER_POINTS = new ErrorCode(1_011_000_038, "交易订单创建失败,原因:用户积分不足"); // ========== After Sale 模块 1-011-000-100 ========== ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在"); diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index 8dcc0ad75e..bafe56c5be 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -25,6 +25,9 @@ import cn.iocoder.yudao.module.pay.enums.order.PayOrderStatusEnum; import cn.iocoder.yudao.module.pay.enums.refund.PayRefundStatusEnum; import cn.iocoder.yudao.module.product.api.comment.ProductCommentApi; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; +import cn.iocoder.yudao.module.promotion.api.combination.CombinationRecordApi; +import cn.iocoder.yudao.module.promotion.api.combination.dto.CombinationRecordRespDTO; +import cn.iocoder.yudao.module.promotion.enums.combination.CombinationRecordStatusEnum; import cn.iocoder.yudao.module.system.api.social.SocialClientApi; import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO; import cn.iocoder.yudao.module.trade.controller.admin.order.vo.TradeOrderDeliveryReqVO; @@ -121,6 +124,8 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { public SocialClientApi socialClientApi; @Resource public PayRefundApi payRefundApi; + @Resource + private CombinationRecordApi combinationRecordApi; @Resource private TradeOrderProperties tradeOrderProperties; @@ -775,6 +780,14 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { if (ObjUtil.notEqual(DeliveryTypeEnum.PICK_UP.getType(), order.getDeliveryType())) { throw exception(ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP); } + // 情况一:如果是拼团订单,则校验拼团是否成功 + if (TradeOrderTypeEnum.isCombination(order.getType())) { + CombinationRecordRespDTO combinationRecord = combinationRecordApi.getCombinationRecordByOrderId( + order.getUserId(), order.getId()); + if (!CombinationRecordStatusEnum.isSuccess(combinationRecord.getStatus())) { + throw exception(ORDER_PICK_UP_FAIL_COMBINATION_NOT_SUCCESS); + } + } DeliveryPickUpStoreDO deliveryPickUpStore = pickUpStoreService.getDeliveryPickUpStore(order.getPickUpStoreId()); if (deliveryPickUpStore == null || !CollUtil.contains(deliveryPickUpStore.getVerifyUserIds(), userId)) { From c611f1ad15f8d564142c25a303dce4359ebe38cb Mon Sep 17 00:00:00 2001 From: xubinbin0303 Date: Tue, 1 Jul 2025 19:17:15 +0800 Subject: [PATCH 08/81] =?UTF-8?q?refactor.trade:=20=E4=BC=98=E5=8C=96=20Kd?= =?UTF-8?q?100ExpressQueryRespDTO=20=E4=B8=AD=E6=97=B6=E9=97=B4=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=9A=84=E5=A4=84=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 timeStr 字段用于存储原始时间字符串 - 添加 parseTime 方法将时间字符串解析为 LocalDateTime 对象- 保留原有的 @JsonFormat 注解以确保序列化格式不变 --- .../core/client/dto/kd100/Kd100ExpressQueryRespDTO.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java index 9d33cac21b..0b3034737b 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -58,9 +59,13 @@ public class Kd100ExpressQueryRespDTO { /** * 轨迹发生时间 */ - @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) - private LocalDateTime time; + private String timeStr; + @JsonProperty("time") + public void parseTime(String timeStr) { + this.time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern(FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)); + } + private LocalDateTime time; /** * 轨迹描述 */ From 14a233afceee4c3faa8803ad8d2df352924f3a3d Mon Sep 17 00:00:00 2001 From: ningjingzhiyuan1024 <596928539@qq.com> Date: Sat, 5 Jul 2025 16:18:06 +0800 Subject: [PATCH 09/81] =?UTF-8?q?refactor(trade):=20=E4=BC=98=E5=8C=96=20K?= =?UTF-8?q?d100ExpressQueryRespDTO=20=E4=B8=AD=E6=97=B6=E9=97=B4=E5=AD=97?= =?UTF-8?q?=E6=AE=B5=E7=9A=84=E5=8F=8D=E5=BA=8F=E5=88=97=E5=8C=96=E6=96=B9?= =?UTF-8?q?=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除手动解析时间字符串的方法 - 使用 @JsonFormat 和 @JsonDeserialize 注解实现自动反序列化 - 提高代码简洁性和可维护性 --- .../core/client/dto/kd100/Kd100ExpressQueryRespDTO.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java index 0b3034737b..2c0f8cba44 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java @@ -62,9 +62,8 @@ public class Kd100ExpressQueryRespDTO { private String timeStr; @JsonProperty("time") - public void parseTime(String timeStr) { - this.time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern(FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)); - } + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime time; /** * 轨迹描述 From 92410453652c6bb93f6056921f20f0f74435fa35 Mon Sep 17 00:00:00 2001 From: ningjingzhiyuan1024 <596928539@qq.com> Date: Sat, 5 Jul 2025 16:18:06 +0800 Subject: [PATCH 10/81] =?UTF-8?q?refactor.trade:=20=E7=A7=BB=E9=99=A4=20Kd?= =?UTF-8?q?100ExpressQueryRespDTO=20=E4=B8=AD=E7=9A=84=E5=86=97=E4=BD=99?= =?UTF-8?q?=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 删除了 Kd100ExpressQueryRespDTO 类中的 timeStr 字段 - 保留了已有的 time 字段,用于表示轨迹发生时间 --- .../core/client/dto/kd100/Kd100ExpressQueryRespDTO.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java index 0b3034737b..6a8e83e3b3 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java @@ -59,12 +59,9 @@ public class Kd100ExpressQueryRespDTO { /** * 轨迹发生时间 */ - private String timeStr; - @JsonProperty("time") - public void parseTime(String timeStr) { - this.time = LocalDateTime.parse(timeStr, DateTimeFormatter.ofPattern(FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)); - } + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) + @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime time; /** * 轨迹描述 From a6901845248a56c65b2a01d43110cbde8dc45a7f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 6 Jul 2025 16:19:45 +0800 Subject: [PATCH 11/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90ERP=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E3=80=91=E6=B8=85=E7=90=86=E5=A4=9A=E4=BD=99=E7=9A=84?= =?UTF-8?q?=20ErpStatisticsServiceTest=20=E7=B1=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../statistics/ErpStatisticsServiceTest.java | 155 ------------------ 1 file changed, 155 deletions(-) delete mode 100644 yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java diff --git a/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java b/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java deleted file mode 100644 index c96f2d35fa..0000000000 --- a/yudao-module-erp/src/test/java/cn/iocoder/yudao/module/erp/service/statistics/ErpStatisticsServiceTest.java +++ /dev/null @@ -1,155 +0,0 @@ -package cn.iocoder.yudao.module.erp.service.statistics; - -import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; -import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpPurchaseStatisticsMapper; -import cn.iocoder.yudao.module.erp.dal.mysql.statistics.ErpSaleStatisticsMapper; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.boot.test.mock.mockito.MockBean; -import org.springframework.test.context.ActiveProfiles; - -import jakarta.annotation.Resource; -import java.math.BigDecimal; -import java.time.LocalDateTime; - -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.when; - -/** - * ERP 统计服务测试类 - * 主要测试在多租户关闭情况下,统计查询是否能正常工作 - * - * @author 芋道源码 - */ -@SpringBootTest -@ActiveProfiles("unit-test") -public class ErpStatisticsServiceTest { - - @Resource - private ErpSaleStatisticsService saleStatisticsService; - - @Resource - private ErpPurchaseStatisticsService purchaseStatisticsService; - - @MockBean - private ErpSaleStatisticsMapper saleStatisticsMapper; - - @MockBean - private ErpPurchaseStatisticsMapper purchaseStatisticsMapper; - - @BeforeEach - void setUp() { - // 清理租户上下文 - TenantContextHolder.clear(); - } - - @AfterEach - void tearDown() { - // 清理租户上下文 - TenantContextHolder.clear(); - } - - @Test - void testSaleStatisticsWithoutTenant() { - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("1000.00"); - - // Mock 返回值 - when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在没有租户ID的情况下调用销售统计 - assertDoesNotThrow(() -> { - BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户关闭时,销售统计查询应该能正常工作"); - } - - @Test - void testPurchaseStatisticsWithoutTenant() { - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("800.00"); - - // Mock 返回值 - when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在没有租户ID的情况下调用采购统计 - assertDoesNotThrow(() -> { - BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户关闭时,采购统计查询应该能正常工作"); - } - - @Test - void testSaleStatisticsWithTenant() { - // 设置租户ID - Long tenantId = 1L; - TenantContextHolder.setTenantId(tenantId); - - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("1500.00"); - - // Mock 返回值 - when(saleStatisticsMapper.getSalePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在有租户ID的情况下调用销售统计 - assertDoesNotThrow(() -> { - BigDecimal result = saleStatisticsService.getSalePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户开启时,销售统计查询应该能正常工作"); - - // 验证租户ID是否正确设置 - assertEquals(tenantId, TenantContextHolder.getTenantId()); - } - - @Test - void testPurchaseStatisticsWithTenant() { - // 设置租户ID - Long tenantId = 2L; - TenantContextHolder.setTenantId(tenantId); - - // 准备参数 - LocalDateTime beginTime = LocalDateTime.of(2024, 1, 1, 0, 0, 0); - LocalDateTime endTime = LocalDateTime.of(2024, 1, 31, 23, 59, 59); - BigDecimal expectedPrice = new BigDecimal("1200.00"); - - // Mock 返回值 - when(purchaseStatisticsMapper.getPurchasePrice(any(LocalDateTime.class), any(LocalDateTime.class))) - .thenReturn(expectedPrice); - - // 测试:在有租户ID的情况下调用采购统计 - assertDoesNotThrow(() -> { - BigDecimal result = purchaseStatisticsService.getPurchasePrice(beginTime, endTime); - assertEquals(expectedPrice, result); - }, "在多租户开启时,采购统计查询应该能正常工作"); - - // 验证租户ID是否正确设置 - assertEquals(tenantId, TenantContextHolder.getTenantId()); - } - - @Test - void testTenantContextHolderMethods() { - // 测试 getTenantId() 在没有设置租户时返回 null - assertNull(TenantContextHolder.getTenantId(), "未设置租户时应该返回 null"); - - // 设置租户ID - Long tenantId = 3L; - TenantContextHolder.setTenantId(tenantId); - assertEquals(tenantId, TenantContextHolder.getTenantId(), "设置租户后应该能正确获取"); - - // 清理租户上下文 - TenantContextHolder.clear(); - assertNull(TenantContextHolder.getTenantId(), "清理后应该返回 null"); - } -} From eca9307344e235e506b53eddae12c3fdabeb224c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 6 Jul 2025 16:38:14 +0800 Subject: [PATCH 12/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90MALL=20=E5=95=86?= =?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BF=AE=E5=A4=8D=E9=80=80=E6=AC=BE=E9=80=9A?= =?UTF-8?q?=E7=9F=A5=E4=B8=AD=20merchantRefundId=20=E5=AD=97=E7=AC=A6?= =?UTF-8?q?=E4=B8=B2=E8=BD=AC=E6=8D=A2=20Long=20=E7=B1=BB=E5=9E=8B?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/aftersale/AfterSaleController.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java index d2165cb868..2bc654b290 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java @@ -141,9 +141,8 @@ public class AfterSaleController { public CommonResult updateAfterSaleRefunded(@RequestBody PayRefundNotifyReqDTO notifyReqDTO) { log.info("[updateAfterRefund][notifyReqDTO({})]", notifyReqDTO); if (StrUtil.startWithAny(notifyReqDTO.getMerchantRefundId(), "order-")) { - tradeOrderUpdateService.updatePaidOrderRefunded( - Long.parseLong(notifyReqDTO.getMerchantRefundId()), - notifyReqDTO.getPayRefundId()); + Long orderId = Long.parseLong(StrUtil.subAfter(notifyReqDTO.getMerchantRefundId(), "order-", true)); + tradeOrderUpdateService.updatePaidOrderRefunded(orderId, notifyReqDTO.getPayRefundId()); } else { afterSaleService.updateAfterSaleRefunded( Long.parseLong(notifyReqDTO.getMerchantRefundId()), From d8e1610495fb3dfc66c1d368d4e26af952e8d37f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 8 Jul 2025 09:39:44 +0800 Subject: [PATCH 13/81] feat: enhance MyBatis utility for sorting and update SQL aliases in TradeOrderStatisticsMapper --- .../mybatis/core/mapper/BaseMapperX.java | 1 + .../mybatis/core/util/MyBatisUtils.java | 27 ++++++++++++++----- .../trade/TradeOrderStatisticsMapper.xml | 8 +++--- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java index d7ad5fad8f..52ca947cc5 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/mapper/BaseMapperX.java @@ -42,6 +42,7 @@ public interface BaseMapperX extends MPJBaseMapper { default PageResult selectPage(PageParam pageParam, Collection sortingFields, @Param("ew") Wrapper queryWrapper) { // 特殊:不分页,直接查询全部 if (PageParam.PAGE_SIZE_NONE.equals(pageParam.getPageSize())) { + MyBatisUtils.addOrder(queryWrapper, sortingFields); List list = selectList(queryWrapper); return new PageResult<>(list, (long) list.size()); } diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java index 784f699e44..ac33ba8eff 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/util/MyBatisUtils.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.mybatis.core.util; -import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.func.Func1; import cn.hutool.core.lang.func.LambdaUtil; import cn.hutool.core.util.StrUtil; @@ -8,6 +8,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.SortingField; import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum; import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.conditions.Wrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.metadata.OrderItem; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; @@ -20,7 +22,6 @@ import net.sf.jsqlparser.schema.Table; import java.util.ArrayList; import java.util.Collection; import java.util.List; -import java.util.stream.Collectors; /** * MyBatis 工具类 @@ -37,15 +38,27 @@ public class MyBatisUtils { // 页码 + 数量 Page page = new Page<>(pageParam.getPageNo(), pageParam.getPageSize()); // 排序字段 - if (!CollectionUtil.isEmpty(sortingFields)) { - page.addOrder(sortingFields.stream().map(sortingField -> SortingField.ORDER_ASC.equals(sortingField.getOrder()) - ? OrderItem.asc(StrUtil.toUnderlineCase(sortingField.getField())) - : OrderItem.desc(StrUtil.toUnderlineCase(sortingField.getField()))) - .collect(Collectors.toList())); + if (CollUtil.isNotEmpty(sortingFields)) { + for (SortingField sortingField : sortingFields) { + page.addOrder(new OrderItem().setAsc(SortingField.ORDER_ASC.equals(sortingField.getOrder())) + .setColumn(StrUtil.toUnderlineCase(sortingField.getField()))); + } } return page; } + public static void addOrder(Wrapper wrapper, Collection sortingFields) { + if (CollUtil.isEmpty(sortingFields)) { + return; + } + QueryWrapper query = (QueryWrapper) wrapper; + for (SortingField sortingField : sortingFields) { + query.orderBy(true, + SortingField.ORDER_ASC.equals(sortingField.getOrder()), + StrUtil.toUnderlineCase(sortingField.getField())); + } + } + /** * 将拦截器添加到链中 * 由于 MybatisPlusInterceptor 不支持添加拦截器,所以只能全量设置 diff --git a/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml b/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml index 07d2f0d580..e47c85e9b4 100644 --- a/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml +++ b/yudao-module-mall/yudao-module-statistics/src/main/resources/mapper/trade/TradeOrderStatisticsMapper.xml @@ -76,8 +76,8 @@ - SELECT IFNULL(SUM(pay_price), 0) AS orderPayPrice, - COUNT(1) AS orderPayCount + SELECT IFNULL(SUM(pay_price), 0) AS order_pay_price, + COUNT(1) AS order_pay_count FROM trade_order WHERE pay_status = #{payStatus} AND pay_time BETWEEN #{beginTime} AND #{endTime} From 563985dcfc9e68ddc208f72c811ff0b2ced83cf2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 19:17:50 +0800 Subject: [PATCH 14/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90MP=20=E5=85=AC?= =?UTF-8?q?=E4=BC=97=E5=8F=B7=E3=80=91=E5=85=BC=E5=AE=B9=E6=97=A0=20API=20?= =?UTF-8?q?=E6=9D=83=E9=99=90=E7=9A=84=E4=B8=AA=E4=BA=BA=E5=85=AC=E4=BC=97?= =?UTF-8?q?=E5=8F=B7=E5=9C=BA=E6=99=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mp/service/handler/user/SubscribeHandler.java | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java b/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java index 14540836a7..0f68baf39e 100644 --- a/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java +++ b/yudao-module-mp/src/main/java/cn/iocoder/yudao/module/mp/service/handler/user/SubscribeHandler.java @@ -1,10 +1,13 @@ package cn.iocoder.yudao.module.mp.service.handler.user; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.module.mp.framework.mp.core.context.MpContextHolder; import cn.iocoder.yudao.module.mp.service.message.MpAutoReplyService; import cn.iocoder.yudao.module.mp.service.user.MpUserService; +import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import me.chanjar.weixin.common.error.WxErrorException; +import me.chanjar.weixin.common.error.WxMpErrorMsgEnum; import me.chanjar.weixin.common.session.WxSessionManager; import me.chanjar.weixin.mp.api.WxMpMessageHandler; import me.chanjar.weixin.mp.api.WxMpService; @@ -13,7 +16,6 @@ import me.chanjar.weixin.mp.bean.message.WxMpXmlOutMessage; import me.chanjar.weixin.mp.bean.result.WxMpUser; import org.springframework.stereotype.Component; -import jakarta.annotation.Resource; import java.util.Map; /** @@ -40,6 +42,13 @@ public class SubscribeHandler implements WxMpMessageHandler { wxMpUser = weixinService.getUserService().userInfo(wxMessage.getFromUser()); } catch (WxErrorException e) { log.error("[handle][粉丝({})] 获取粉丝信息失败!", wxMessage.getFromUser(), e); + // 特殊情况(个人账号,无接口权限):https://t.zsxq.com/cLFq5 + if (ObjUtil.equal(e.getError().getErrorCode(), WxMpErrorMsgEnum.CODE_48001)) { + wxMpUser = new WxMpUser(); + wxMpUser.setOpenId(wxMessage.getFromUser()); + wxMpUser.setSubscribe(true); + wxMpUser.setSubscribeTime(System.currentTimeMillis() / 1000L); + } } // 第二步,保存粉丝信息 From 7fc522938d1eadd09ea1a0c43413b47b92a523b7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 19:27:07 +0800 Subject: [PATCH 15/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91=E7=A4=BE=E4=BA=A4=E7=BB=91?= =?UTF-8?q?=E5=AE=9A=EF=BC=8C=E4=BD=BF=E7=94=A8=20code=20=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E7=A0=81=E7=9A=84=E5=8F=82=E6=95=B0=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/controller/admin/socail/SocialUserController.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java index 77a77daa1f..f26ca4d937 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/socail/SocialUserController.java @@ -38,7 +38,8 @@ public class SocialUserController { @PostMapping("/bind") @Operation(summary = "社交绑定,使用 code 授权码") public CommonResult socialBind(@RequestBody @Valid SocialUserBindReqVO reqVO) { - socialUserService.bindSocialUser(BeanUtils.toBean(reqVO, SocialUserBindReqDTO.class) + socialUserService.bindSocialUser(new SocialUserBindReqDTO().setSocialType(reqVO.getType()) + .setCode(reqVO.getCode()).setState(reqVO.getState()) .setUserId(getLoginUserId()).setUserType(UserTypeEnum.ADMIN.getValue())); return CommonResult.success(true); } From bda357508a825557877b43a7d1b7ba864d659b87 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 22:37:48 +0800 Subject: [PATCH 16/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91SecurityFrameworkUtils=20?= =?UTF-8?q?=E7=9A=84=20setLoginUser=20=E6=96=B9=E6=B3=95=EF=BC=8C=E7=A7=BB?= =?UTF-8?q?=E9=99=A4=E5=AF=B9=20request=20=E5=BC=BA=E4=BE=9D=E8=B5=96?= =?UTF-8?q?=EF=BC=8C=E5=8F=AF=E7=94=A8=E4=BA=8E=20Job=20=E8=AE=B0=E5=BD=95?= =?UTF-8?q?=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../security/core/util/SecurityFrameworkUtils.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java index 98dc7afb8d..4f8024474b 100644 --- a/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-security/src/main/java/cn/iocoder/yudao/framework/security/core/util/SecurityFrameworkUtils.java @@ -126,8 +126,10 @@ public class SecurityFrameworkUtils { // 额外设置到 request 中,用于 ApiAccessLogFilter 可以获取到用户编号; // 原因是,Spring Security 的 Filter 在 ApiAccessLogFilter 后面,在它记录访问日志时,线上上下文已经没有用户编号等信息 - WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); - WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); + if (request != null) { + WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); + WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); + } } private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) { From 569ff42e6f9d2a4499ca0cfe113585e705ab59f2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 9 Jul 2025 23:24:17 +0800 Subject: [PATCH 17/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91=E4=BC=98=E5=8C=96=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20SimpleAsyncTaskExecutor=20=E5=BC=82=E6=AD=A5?= =?UTF-8?q?=E7=BA=BF=E7=A8=8B=E6=B1=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/YudaoAsyncAutoConfiguration.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java index 6d517e5e40..4b08210971 100644 --- a/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-job/src/main/java/cn/iocoder/yudao/framework/quartz/config/YudaoAsyncAutoConfiguration.java @@ -7,6 +7,7 @@ import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.core.task.SimpleAsyncTaskExecutor; /** * 异步任务 Configuration @@ -21,13 +22,20 @@ public class YudaoAsyncAutoConfiguration { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { - if (!(bean instanceof ThreadPoolTaskExecutor)) { - return bean; + // 处理 ThreadPoolTaskExecutor + if (bean instanceof ThreadPoolTaskExecutor) { + ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean; + executor.setTaskDecorator(TtlRunnable::get); + return executor; } - // 修改提交的任务,接入 TransmittableThreadLocal - ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) bean; - executor.setTaskDecorator(TtlRunnable::get); - return executor; + // 处理 SimpleAsyncTaskExecutor + // 参考 https://t.zsxq.com/CBoks 增加 + if (bean instanceof SimpleAsyncTaskExecutor) { + SimpleAsyncTaskExecutor executor = (SimpleAsyncTaskExecutor) bean; + executor.setTaskDecorator(TtlRunnable::get); + return executor; + } + return bean; } }; From 7a5e28d08a44197e44c58de78ba85a4e6599b03a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 11 Jul 2025 21:57:09 +0800 Subject: [PATCH 18/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91=E5=A2=9E=E5=8A=A0=20lombok?= =?UTF-8?q?-mapstruct-binding=20=E4=BE=9D=E8=B5=96=EF=BC=8C=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=20IDEA=20=E5=81=B6=E7=84=B6=E5=87=BA=E7=8E=B0=20No=20?= =?UTF-8?q?property=20named=20=E2=80=9Cxxx"=20exists=20=E7=9A=84=E7=BC=96?= =?UTF-8?q?=E8=AF=91=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pom.xml b/pom.xml index f5f0a32e36..b271f1d4b9 100644 --- a/pom.xml +++ b/pom.xml @@ -87,6 +87,13 @@ lombok ${lombok.version} + + + org.projectlombok + lombok-mapstruct-binding + 0.2.0 + org.mapstruct mapstruct-processor From 285da1398924a19b57b1f2951beaa61927e09374 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 11 Jul 2025 22:04:13 +0800 Subject: [PATCH 19/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91=E4=BF=AE=E5=A4=8D=20Defaul?= =?UTF-8?q?tDBFieldHandler=20=E5=9C=A8=20Async=20=E6=83=85=E5=86=B5?= =?UTF-8?q?=E4=B8=8B=EF=BC=8C=E6=97=A0=E6=B3=95=E8=8E=B7=E5=8F=96=E5=88=B0?= =?UTF-8?q?=20getLoginUserId=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml | 4 ++-- .../mybatis/core/handler/DefaultDBFieldHandler.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml index 5a619c5118..3272059d85 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/pom.xml @@ -24,8 +24,8 @@ cn.iocoder.boot - yudao-spring-boot-starter-web - provided + yudao-spring-boot-starter-security + provided diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java index 94dada129b..3c35999109 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/handler/DefaultDBFieldHandler.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.framework.mybatis.core.handler; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; @@ -32,7 +32,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { baseDO.setUpdateTime(current); } - Long userId = WebFrameworkUtils.getLoginUserId(); + Long userId = SecurityFrameworkUtils.getLoginUserId(); // 当前登录用户不为空,创建人为空,则当前登录用户为创建人 if (Objects.nonNull(userId) && Objects.isNull(baseDO.getCreator())) { baseDO.setCreator(userId.toString()); @@ -54,7 +54,7 @@ public class DefaultDBFieldHandler implements MetaObjectHandler { // 当前登录用户不为空,更新人为空,则当前登录用户为更新人 Object modifier = getFieldValByName("updater", metaObject); - Long userId = WebFrameworkUtils.getLoginUserId(); + Long userId = SecurityFrameworkUtils.getLoginUserId(); if (Objects.nonNull(userId) && Objects.isNull(modifier)) { setFieldValByName("updater", userId.toString(), metaObject); } From 520fb79e2a0fef99e524a5659b0a70528b2fcd61 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 11 Jul 2025 23:42:52 +0800 Subject: [PATCH 20/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90REPORT=20=E6=8A=A5?= =?UTF-8?q?=E8=A1=A8=E3=80=91jimureport=20from=201.9.4=20to=202.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 94c3e31aa8..bf6175cdd3 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -74,7 +74,8 @@ 2.30.14 1.16.7 1.4.0 - 1.9.4 + 2.0.0 + 1.9.5 4.7.5.B @@ -603,7 +604,7 @@ org.jeecgframework.jimureport jimubi-spring-boot3-starter - ${jimureport.version} + ${jimubi.version} com.github.jsqlparser From e7c9e3dc231d112639340b292500b29760f09996 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 13 Jul 2025 11:16:14 +0800 Subject: [PATCH 21/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90INFRA=20=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E8=AE=BE=E6=96=BD=E3=80=91=E6=9B=B4=E6=96=B0=20pgsql?= =?UTF-8?q?=20quartz=20sql?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/postgresql/quartz.sql | 415 +++++++++++++++++--------------------- 1 file changed, 185 insertions(+), 230 deletions(-) diff --git a/sql/postgresql/quartz.sql b/sql/postgresql/quartz.sql index 4ec390c527..46bb938431 100644 --- a/sql/postgresql/quartz.sql +++ b/sql/postgresql/quartz.sql @@ -1,253 +1,208 @@ --- ---------------------------- --- qrtz_blob_triggers --- ---------------------------- -CREATE TABLE qrtz_blob_triggers +-- https://github.com/quartz-scheduler/quartz/blob/main/quartz/src/main/resources/org/quartz/impl/jdbcjobstore/tables_postgres.sql +-- Thanks to Patrick Lightbody for submitting this... +-- +-- In your Quartz properties file, you'll need to set +-- org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.PostgreSQLDelegate + +DROP TABLE IF EXISTS QRTZ_FIRED_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_PAUSED_TRIGGER_GRPS; +DROP TABLE IF EXISTS QRTZ_SCHEDULER_STATE; +DROP TABLE IF EXISTS QRTZ_LOCKS; +DROP TABLE IF EXISTS QRTZ_SIMPLE_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_CRON_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_SIMPROP_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_BLOB_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_TRIGGERS; +DROP TABLE IF EXISTS QRTZ_JOB_DETAILS; +DROP TABLE IF EXISTS QRTZ_CALENDARS; + +CREATE TABLE QRTZ_JOB_DETAILS ( - sched_name varchar(120) NOT NULL, - trigger_name varchar(190) NOT NULL, - trigger_group varchar(190) NOT NULL, - blob_data bytea NULL, - PRIMARY KEY (sched_name, trigger_name, trigger_group) + SCHED_NAME VARCHAR(120) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + JOB_CLASS_NAME VARCHAR(250) NOT NULL, + IS_DURABLE BOOL NOT NULL, + IS_NONCONCURRENT BOOL NOT NULL, + IS_UPDATE_DATA BOOL NOT NULL, + REQUESTS_RECOVERY BOOL NOT NULL, + JOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME, JOB_NAME, JOB_GROUP) ); -CREATE INDEX idx_qrtz_blob_triggers_sched_name ON qrtz_blob_triggers (sched_name, trigger_name, trigger_group); - --- ---------------------------- --- qrtz_calendars --- ---------------------------- -CREATE TABLE qrtz_calendars +CREATE TABLE QRTZ_TRIGGERS ( - sched_name varchar(120) NOT NULL, - calendar_name varchar(190) NOT NULL, - calendar bytea NOT NULL, - PRIMARY KEY (sched_name, calendar_name) + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + JOB_NAME VARCHAR(200) NOT NULL, + JOB_GROUP VARCHAR(200) NOT NULL, + DESCRIPTION VARCHAR(250) NULL, + NEXT_FIRE_TIME BIGINT NULL, + PREV_FIRE_TIME BIGINT NULL, + PRIORITY INTEGER NULL, + TRIGGER_STATE VARCHAR(16) NOT NULL, + TRIGGER_TYPE VARCHAR(8) NOT NULL, + START_TIME BIGINT NOT NULL, + END_TIME BIGINT NULL, + CALENDAR_NAME VARCHAR(200) NULL, + MISFIRE_INSTR SMALLINT NULL, + JOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, JOB_NAME, JOB_GROUP) + REFERENCES QRTZ_JOB_DETAILS (SCHED_NAME, JOB_NAME, JOB_GROUP) +); + +CREATE TABLE QRTZ_SIMPLE_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + REPEAT_COUNT BIGINT NOT NULL, + REPEAT_INTERVAL BIGINT NOT NULL, + TIMES_TRIGGERED BIGINT NOT NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE QRTZ_CRON_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + CRON_EXPRESSION VARCHAR(120) NOT NULL, + TIME_ZONE_ID VARCHAR(80), + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE QRTZ_SIMPROP_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + STR_PROP_1 VARCHAR(512) NULL, + STR_PROP_2 VARCHAR(512) NULL, + STR_PROP_3 VARCHAR(512) NULL, + INT_PROP_1 INT NULL, + INT_PROP_2 INT NULL, + LONG_PROP_1 BIGINT NULL, + LONG_PROP_2 BIGINT NULL, + DEC_PROP_1 NUMERIC(13, 4) NULL, + DEC_PROP_2 NUMERIC(13, 4) NULL, + BOOL_PROP_1 BOOL NULL, + BOOL_PROP_2 BOOL NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE QRTZ_BLOB_TRIGGERS +( + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + BLOB_DATA BYTEA NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP), + FOREIGN KEY (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) + REFERENCES QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP) +); + +CREATE TABLE QRTZ_CALENDARS +( + SCHED_NAME VARCHAR(120) NOT NULL, + CALENDAR_NAME VARCHAR(200) NOT NULL, + CALENDAR BYTEA NOT NULL, + PRIMARY KEY (SCHED_NAME, CALENDAR_NAME) ); --- ---------------------------- --- qrtz_cron_triggers --- ---------------------------- -CREATE TABLE qrtz_cron_triggers +CREATE TABLE QRTZ_PAUSED_TRIGGER_GRPS ( - sched_name varchar(120) NOT NULL, - trigger_name varchar(190) NOT NULL, - trigger_group varchar(190) NOT NULL, - cron_expression varchar(120) NOT NULL, - time_zone_id varchar(80) NULL DEFAULT NULL, - PRIMARY KEY (sched_name, trigger_name, trigger_group) + SCHED_NAME VARCHAR(120) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + PRIMARY KEY (SCHED_NAME, TRIGGER_GROUP) ); --- @formatter:off -BEGIN; -COMMIT; --- @formatter:on - --- ---------------------------- --- qrtz_fired_triggers --- ---------------------------- -CREATE TABLE qrtz_fired_triggers +CREATE TABLE QRTZ_FIRED_TRIGGERS ( - sched_name varchar(120) NOT NULL, - entry_id varchar(95) NOT NULL, - trigger_name varchar(190) NOT NULL, - trigger_group varchar(190) NOT NULL, - instance_name varchar(190) NOT NULL, - fired_time int8 NOT NULL, - sched_time int8 NOT NULL, - priority int4 NOT NULL, - state varchar(16) NOT NULL, - job_name varchar(190) NULL DEFAULT NULL, - job_group varchar(190) NULL DEFAULT NULL, - is_nonconcurrent varchar(1) NULL DEFAULT NULL, - requests_recovery varchar(1) NULL DEFAULT NULL, - PRIMARY KEY (sched_name, entry_id) + SCHED_NAME VARCHAR(120) NOT NULL, + ENTRY_ID VARCHAR(95) NOT NULL, + TRIGGER_NAME VARCHAR(200) NOT NULL, + TRIGGER_GROUP VARCHAR(200) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + FIRED_TIME BIGINT NOT NULL, + SCHED_TIME BIGINT NOT NULL, + PRIORITY INTEGER NOT NULL, + STATE VARCHAR(16) NOT NULL, + JOB_NAME VARCHAR(200) NULL, + JOB_GROUP VARCHAR(200) NULL, + IS_NONCONCURRENT BOOL NULL, + REQUESTS_RECOVERY BOOL NULL, + PRIMARY KEY (SCHED_NAME, ENTRY_ID) ); -CREATE INDEX idx_qrtz_ft_trig_inst_name ON qrtz_fired_triggers (sched_name, instance_name); -CREATE INDEX idx_qrtz_ft_inst_job_req_rcvry ON qrtz_fired_triggers (sched_name, instance_name, requests_recovery); -CREATE INDEX idx_qrtz_ft_j_g ON qrtz_fired_triggers (sched_name, job_name, job_group); -CREATE INDEX idx_qrtz_ft_jg ON qrtz_fired_triggers (sched_name, job_group); -CREATE INDEX idx_qrtz_ft_t_g ON qrtz_fired_triggers (sched_name, trigger_name, trigger_group); -CREATE INDEX idx_qrtz_ft_tg ON qrtz_fired_triggers (sched_name, trigger_group); - --- ---------------------------- --- qrtz_job_details --- ---------------------------- -CREATE TABLE qrtz_job_details +CREATE TABLE QRTZ_SCHEDULER_STATE ( - sched_name varchar(120) NOT NULL, - job_name varchar(190) NOT NULL, - job_group varchar(190) NOT NULL, - description varchar(250) NULL DEFAULT NULL, - job_class_name varchar(250) NOT NULL, - is_durable varchar(1) NOT NULL, - is_nonconcurrent varchar(1) NOT NULL, - is_update_data varchar(1) NOT NULL, - requests_recovery varchar(1) NOT NULL, - job_data bytea NULL, - PRIMARY KEY (sched_name, job_name, job_group) + SCHED_NAME VARCHAR(120) NOT NULL, + INSTANCE_NAME VARCHAR(200) NOT NULL, + LAST_CHECKIN_TIME BIGINT NOT NULL, + CHECKIN_INTERVAL BIGINT NOT NULL, + PRIMARY KEY (SCHED_NAME, INSTANCE_NAME) ); -CREATE INDEX idx_qrtz_j_req_recovery ON qrtz_job_details (sched_name, requests_recovery); -CREATE INDEX idx_qrtz_j_grp ON qrtz_job_details (sched_name, job_group); - --- @formatter:off -BEGIN; -COMMIT; --- @formatter:on - --- ---------------------------- --- qrtz_locks --- ---------------------------- -CREATE TABLE qrtz_locks +CREATE TABLE QRTZ_LOCKS ( - sched_name varchar(120) NOT NULL, - lock_name varchar(40) NOT NULL, - PRIMARY KEY (sched_name, lock_name) + SCHED_NAME VARCHAR(120) NOT NULL, + LOCK_NAME VARCHAR(40) NOT NULL, + PRIMARY KEY (SCHED_NAME, LOCK_NAME) ); --- @formatter:off -BEGIN; -COMMIT; --- @formatter:on +CREATE INDEX IDX_QRTZ_J_REQ_RECOVERY + ON QRTZ_JOB_DETAILS (SCHED_NAME, REQUESTS_RECOVERY); +CREATE INDEX IDX_QRTZ_J_GRP + ON QRTZ_JOB_DETAILS (SCHED_NAME, JOB_GROUP); --- ---------------------------- --- qrtz_paused_trigger_grps --- ---------------------------- -CREATE TABLE qrtz_paused_trigger_grps -( - sched_name varchar(120) NOT NULL, - trigger_group varchar(190) NOT NULL, - PRIMARY KEY (sched_name, trigger_group) -); +CREATE INDEX IDX_QRTZ_T_J + ON QRTZ_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP); +CREATE INDEX IDX_QRTZ_T_JG + ON QRTZ_TRIGGERS (SCHED_NAME, JOB_GROUP); +CREATE INDEX IDX_QRTZ_T_C + ON QRTZ_TRIGGERS (SCHED_NAME, CALENDAR_NAME); +CREATE INDEX IDX_QRTZ_T_G + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP); +CREATE INDEX IDX_QRTZ_T_STATE + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_N_STATE + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP, TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_N_G_STATE + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_GROUP, TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_NEXT_FIRE_TIME + ON QRTZ_TRIGGERS (SCHED_NAME, NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_ST + ON QRTZ_TRIGGERS (SCHED_NAME, TRIGGER_STATE, NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_MISFIRE + ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME); +CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE + ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_STATE); +CREATE INDEX IDX_QRTZ_T_NFT_ST_MISFIRE_GRP + ON QRTZ_TRIGGERS (SCHED_NAME, MISFIRE_INSTR, NEXT_FIRE_TIME, TRIGGER_GROUP, TRIGGER_STATE); --- ---------------------------- --- qrtz_scheduler_state --- ---------------------------- -CREATE TABLE qrtz_scheduler_state -( - sched_name varchar(120) NOT NULL, - instance_name varchar(190) NOT NULL, - last_checkin_time int8 NOT NULL, - checkin_interval int8 NOT NULL, - PRIMARY KEY (sched_name, instance_name) -); - --- @formatter:off -BEGIN; -COMMIT; --- @formatter:on - --- ---------------------------- --- qrtz_simple_triggers --- ---------------------------- -CREATE TABLE qrtz_simple_triggers -( - sched_name varchar(120) NOT NULL, - trigger_name varchar(190) NOT NULL, - trigger_group varchar(190) NOT NULL, - repeat_count int8 NOT NULL, - repeat_interval int8 NOT NULL, - times_triggered int8 NOT NULL, - PRIMARY KEY (sched_name, trigger_name, trigger_group) -); - --- ---------------------------- --- qrtz_simprop_triggers --- ---------------------------- -CREATE TABLE qrtz_simprop_triggers -( - sched_name varchar(120) NOT NULL, - trigger_name varchar(190) NOT NULL, - trigger_group varchar(190) NOT NULL, - str_prop_1 varchar(512) NULL DEFAULT NULL, - str_prop_2 varchar(512) NULL DEFAULT NULL, - str_prop_3 varchar(512) NULL DEFAULT NULL, - int_prop_1 int4 NULL DEFAULT NULL, - int_prop_2 int4 NULL DEFAULT NULL, - long_prop_1 int8 NULL DEFAULT NULL, - long_prop_2 int8 NULL DEFAULT NULL, - dec_prop_1 numeric(13, 4) NULL DEFAULT NULL, - dec_prop_2 numeric(13, 4) NULL DEFAULT NULL, - bool_prop_1 varchar(1) NULL DEFAULT NULL, - bool_prop_2 varchar(1) NULL DEFAULT NULL, - PRIMARY KEY (sched_name, trigger_name, trigger_group) -); - --- ---------------------------- --- qrtz_triggers --- ---------------------------- -CREATE TABLE qrtz_triggers -( - sched_name varchar(120) NOT NULL, - trigger_name varchar(190) NOT NULL, - trigger_group varchar(190) NOT NULL, - job_name varchar(190) NOT NULL, - job_group varchar(190) NOT NULL, - description varchar(250) NULL DEFAULT NULL, - next_fire_time int8 NULL DEFAULT NULL, - prev_fire_time int8 NULL DEFAULT NULL, - priority int4 NULL DEFAULT NULL, - trigger_state varchar(16) NOT NULL, - trigger_type varchar(8) NOT NULL, - start_time int8 NOT NULL, - end_time int8 NULL DEFAULT NULL, - calendar_name varchar(190) NULL DEFAULT NULL, - misfire_instr int2 NULL DEFAULT NULL, - job_data bytea NULL, - PRIMARY KEY (sched_name, trigger_name, trigger_group) -); - -CREATE INDEX idx_qrtz_t_j ON qrtz_triggers (sched_name, job_name, job_group); -CREATE INDEX idx_qrtz_t_jg ON qrtz_triggers (sched_name, job_group); -CREATE INDEX idx_qrtz_t_c ON qrtz_triggers (sched_name, calendar_name); -CREATE INDEX idx_qrtz_t_g ON qrtz_triggers (sched_name, trigger_group); -CREATE INDEX idx_qrtz_t_state ON qrtz_triggers (sched_name, trigger_state); -CREATE INDEX idx_qrtz_t_n_state ON qrtz_triggers (sched_name, trigger_name, trigger_group, trigger_state); -CREATE INDEX idx_qrtz_t_n_g_state ON qrtz_triggers (sched_name, trigger_group, trigger_state); -CREATE INDEX idx_qrtz_t_next_fire_time ON qrtz_triggers (sched_name, next_fire_time); -CREATE INDEX idx_qrtz_t_nft_st ON qrtz_triggers (sched_name, trigger_state, next_fire_time); -CREATE INDEX idx_qrtz_t_nft_misfire ON qrtz_triggers (sched_name, misfire_instr, next_fire_time); -CREATE INDEX idx_qrtz_t_nft_st_misfire ON qrtz_triggers (sched_name, misfire_instr, next_fire_time, trigger_state); -CREATE INDEX idx_qrtz_t_nft_st_misfire_grp ON qrtz_triggers (sched_name, misfire_instr, next_fire_time, trigger_group, - trigger_state); - --- @formatter:off -BEGIN; -COMMIT; --- @formatter:on +CREATE INDEX IDX_QRTZ_FT_TRIG_INST_NAME + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME); +CREATE INDEX IDX_QRTZ_FT_INST_JOB_REQ_RCVRY + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, INSTANCE_NAME, REQUESTS_RECOVERY); +CREATE INDEX IDX_QRTZ_FT_J_G + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_NAME, JOB_GROUP); +CREATE INDEX IDX_QRTZ_FT_JG + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, JOB_GROUP); +CREATE INDEX IDX_QRTZ_FT_T_G + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_NAME, TRIGGER_GROUP); +CREATE INDEX IDX_QRTZ_FT_TG + ON QRTZ_FIRED_TRIGGERS (SCHED_NAME, TRIGGER_GROUP); --- ---------------------------- --- FK: qrtz_blob_triggers --- ---------------------------- -ALTER TABLE qrtz_blob_triggers - ADD CONSTRAINT qrtz_blob_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name, - trigger_name, - trigger_group); - --- ---------------------------- --- FK: qrtz_cron_triggers --- ---------------------------- -ALTER TABLE qrtz_cron_triggers - ADD CONSTRAINT qrtz_cron_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name, trigger_name, trigger_group); - --- ---------------------------- --- FK: qrtz_simple_triggers --- ---------------------------- -ALTER TABLE qrtz_simple_triggers - ADD CONSTRAINT qrtz_simple_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name, - trigger_name, - trigger_group); - --- ---------------------------- --- FK: qrtz_simprop_triggers --- ---------------------------- -ALTER TABLE qrtz_simprop_triggers - ADD CONSTRAINT qrtz_simprop_triggers_ibfk_1 FOREIGN KEY (sched_name, trigger_name, trigger_group) REFERENCES qrtz_triggers (sched_name, trigger_name, trigger_group); - --- ---------------------------- --- FK: qrtz_triggers --- ---------------------------- -ALTER TABLE qrtz_triggers - ADD CONSTRAINT qrtz_triggers_ibfk_1 FOREIGN KEY (sched_name, job_name, job_group) REFERENCES qrtz_job_details (sched_name, job_name, job_group); +COMMIT; \ No newline at end of file From 64516b22106294f541c07a443cc6358fda56c1a0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 13 Jul 2025 16:06:41 +0800 Subject: [PATCH 22/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90INFRA=20=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E8=AE=BE=E6=96=BD=E3=80=91=E6=96=87=E4=BB=B6=E4=B8=8A?= =?UTF-8?q?=E4=BC=A0=E6=97=B6=EF=BC=8Cdirectory=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BB=BB=E6=84=8F=E8=B7=AF=E5=BE=84=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/file/vo/file/FileUploadReqVO.java | 9 +++++++++ .../infra/controller/app/file/vo/AppFileUploadReqVO.java | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadReqVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadReqVO.java index 4096f477e3..44e8b65d76 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadReqVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileUploadReqVO.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.NotNull; import lombok.Data; import org.springframework.web.multipart.MultipartFile; @@ -16,4 +19,10 @@ public class FileUploadReqVO { @Schema(description = "文件目录", example = "XXX/YYY") private String directory; + @AssertTrue(message = "文件目录不正确") + @JsonIgnore + public boolean isDirectoryValid() { + return !StrUtil.containsAny(directory, "..", "/", "\\"); + } + } diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java index fde120a067..d10a21cc49 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/controller/app/file/vo/AppFileUploadReqVO.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.infra.controller.app.file.vo; +import cn.hutool.core.util.StrUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.NotNull; import lombok.Data; import org.springframework.web.multipart.MultipartFile; @@ -16,4 +19,10 @@ public class AppFileUploadReqVO { @Schema(description = "文件目录", example = "XXX/YYY") private String directory; + @AssertTrue(message = "文件目录不正确") + @JsonIgnore + public boolean isDirectoryValid() { + return !StrUtil.containsAny(directory, "..", "/", "\\"); + } + } From a54e743a884eb328eadbcb9b6bfd1573bc554691 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 13 Jul 2025 16:15:18 +0800 Subject: [PATCH 23/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90SYSTEM=20=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E7=AE=A1=E7=90=86=E3=80=91=E6=89=8B=E6=9C=BA=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E7=A0=81=E7=99=BB=E5=BD=95=EF=BC=8C=E5=A2=9E=E5=8A=A0?= =?UTF-8?q?=E9=99=90=E6=B5=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/system/controller/admin/auth/AuthController.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java index d9269470d0..e41aee576d 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java @@ -127,6 +127,8 @@ public class AuthController { @PostMapping("/sms-login") @PermitAll @Operation(summary = "使用短信验证码登录") + // 可按需开启限流:https://github.com/YunaiV/ruoyi-vue-pro/issues/851 + // @RateLimiter(time = 60, count = 6, keyResolver = ExpressionRateLimiterKeyResolver.class, keyArg = "#reqVO.mobile") public CommonResult smsLogin(@RequestBody @Valid AuthSmsLoginReqVO reqVO) { return success(authService.smsLogin(reqVO)); } From a9c7b584ccbf2ad377893c0316fd70df5bbbc40d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 13 Jul 2025 17:06:40 +0800 Subject: [PATCH 24/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90MALL=20=E5=95=86?= =?UTF-8?q?=E5=9F=8E=E7=AE=A1=E7=90=86=E3=80=91=E4=BC=98=E6=83=A0=E5=8A=B5?= =?UTF-8?q?=E6=89=A3=E5=87=8F=E6=97=B6=EF=BC=8C=E5=A2=9E=E5=8A=A0=20WHERE?= =?UTF-8?q?=20=E4=B9=90=E8=A7=82=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dal/dataobject/coupon/CouponTemplateDO.java | 8 ++++++-- .../dal/mysql/coupon/CouponTemplateMapper.java | 12 +++++++++--- .../promotion/service/coupon/CouponServiceImpl.java | 3 +-- .../service/coupon/CouponTemplateServiceImpl.java | 10 ++++++---- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java index 91216bf184..59ee95fb12 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java @@ -31,9 +31,13 @@ import java.util.List; public class CouponTemplateDO extends BaseDO { /** - * 不限制领取数量 + * 领取数量 - 不限制 */ - public static final Integer TIME_LIMIT_COUNT_MAX = -1; + public static final Integer TAKE_LIMIT_COUNT_MAX = -1; + /** + * 发放数量 - 不限制 + */ + public static final Integer TOTAL_COUNT_MAX = -1; // ========== 基本信息 BEGIN ========== /** diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java index 3096a49f3c..84e98f3dbd 100755 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/coupon/CouponTemplateMapper.java @@ -40,10 +40,16 @@ public interface CouponTemplateMapper extends BaseMapperX { .orderByDesc(CouponTemplateDO::getId)); } - default void updateTakeCount(Long id, Integer incrCount) { - update(null, new LambdaUpdateWrapper() + default int updateTakeCount(Long id, Integer incrCount) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() .eq(CouponTemplateDO::getId, id) - .setSql("take_count = take_count + " + incrCount)); + .setSql("take_count = take_count + " + incrCount); + // 增加已领取的数量(incrCount 为正数),需要考虑发放数量 totalCount 的限制 + if (incrCount > 0) { + updateWrapper.and(i -> i.apply("take_count < total_count") + .or().eq(CouponTemplateDO::getTotalCount, CouponTemplateDO.TOTAL_COUNT_MAX)); + } + return update(updateWrapper); } default List selectListByTakeType(Integer takeType) { diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java index e6f82a69fc..e175807503 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java @@ -137,7 +137,6 @@ public class CouponServiceImpl implements CouponService { // 4. 增加优惠劵模板的领取数量 couponTemplateService.updateCouponTemplateTakeCount(template.getId(), userIds.size()); - return convertMultiMap(couponList, CouponDO::getUserId, CouponDO::getId); } @@ -281,7 +280,7 @@ public class CouponServiceImpl implements CouponService { } // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) - && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 + && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 非不限制 && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) { throw exception(COUPON_TEMPLATE_NOT_ENOUGH); } diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java index 175e33b197..bdd8b32825 100755 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java @@ -22,8 +22,7 @@ import java.util.List; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_NOT_EXISTS; -import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL; +import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*; /** * 优惠劵模板 Service 实现类 @@ -60,7 +59,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { CouponTemplateDO couponTemplate = validateCouponTemplateExists(updateReqVO.getId()); // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时) if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType()) - && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TIME_LIMIT_COUNT_MAX) // 非不限制 + && ObjUtil.notEqual(couponTemplate.getTakeLimitCount(), CouponTemplateDO.TAKE_LIMIT_COUNT_MAX) // 非不限制 && updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) { throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount()); } @@ -116,7 +115,10 @@ public class CouponTemplateServiceImpl implements CouponTemplateService { @Override public void updateCouponTemplateTakeCount(Long id, int incrCount) { - couponTemplateMapper.updateTakeCount(id, incrCount); + int updateCount = couponTemplateMapper.updateTakeCount(id, incrCount); + if (updateCount == 0) { + throw exception(COUPON_TEMPLATE_NOT_ENOUGH); + } } @Override From af94536a0606e62f3288687b4f4fdee1fce74feb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 13:10:51 +0800 Subject: [PATCH 25/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90CRM=20=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86=E3=80=91=E4=BF=AE=E6=94=B9=E6=95=B0?= =?UTF-8?q?=E6=8D=AE=E6=97=B6=EF=BC=8C=E9=81=BF=E5=85=8D=E6=93=8D=E4=BD=9C?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E5=87=BA=E7=8E=B0=E2=80=9C=E5=88=A0=E9=99=A4?= =?UTF-8?q?=E8=B4=9F=E8=B4=A3=E4=BA=BA=E2=80=9D=E7=9A=84=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/business/CrmBusinessServiceImpl.java | 1 + .../crm/service/clue/CrmClueServiceImpl.java | 13 +++++++------ .../service/contact/CrmContactServiceImpl.java | 1 + .../service/contract/CrmContractServiceImpl.java | 9 +++++---- .../service/customer/CrmCustomerServiceImpl.java | 1 + .../receivable/CrmReceivablePlanServiceImpl.java | 1 + .../receivable/CrmReceivableServiceImpl.java | 15 ++++++++------- 7 files changed, 24 insertions(+), 17 deletions(-) diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 6e75f23daa..71b1884cc2 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -142,6 +142,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { updateBusinessProduct(updateObj.getId(), businessProducts); // 3. 记录操作日志上下文 + updateReqVO.setOwnerUserId(oldBusiness.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldBusiness, CrmBusinessSaveReqVO.class)); LogRecordContext.putVariable("businessName", oldBusiness.getName()); } diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index c8c850ab48..0250fe14f5 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -92,19 +92,20 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CLUE_TYPE, subType = CRM_CLUE_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CRM_CLUE_UPDATE_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) - public void updateClue(CrmClueSaveReqVO updateReq) { - Assert.notNull(updateReq.getId(), "线索编号不能为空"); + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CLUE, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.OWNER) + public void updateClue(CrmClueSaveReqVO updateReqVO) { + Assert.notNull(updateReqVO.getId(), "线索编号不能为空"); // 1.1 校验线索是否存在 - CrmClueDO oldClue = validateClueExists(updateReq.getId()); + CrmClueDO oldClue = validateClueExists(updateReqVO.getId()); // 1.2 校验关联数据 - validateRelationDataExists(updateReq); + validateRelationDataExists(updateReqVO); // 2. 更新线索 - CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class); + CrmClueDO updateObj = BeanUtils.toBean(updateReqVO, CrmClueDO.class); clueMapper.updateById(updateObj); // 3. 记录操作日志上下文 + updateReqVO.setOwnerUserId(oldClue.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmCustomerSaveReqVO.class)); LogRecordContext.putVariable("clueName", oldClue.getName()); } diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 2819c528cd..958fc7520d 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -114,6 +114,7 @@ public class CrmContactServiceImpl implements CrmContactService { contactMapper.updateById(updateObj); // 3. 记录操作日志 + updateReqVO.setOwnerUserId(oldContact.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContact, CrmContactSaveReqVO.class)); LogRecordContext.putVariable("contactName", oldContact.getName()); } diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 12236bf5bc..d25d7c0046 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -140,9 +140,9 @@ public class CrmContractServiceImpl implements CrmContractService { Assert.notNull(updateReqVO.getId(), "合同编号不能为空"); updateReqVO.setOwnerUserId(null); // 不允许更新的字段 // 1.1 校验存在 - CrmContractDO contract = validateContractExists(updateReqVO.getId()); + CrmContractDO oldContract = validateContractExists(updateReqVO.getId()); // 1.2 只有草稿、审批中,可以编辑; - if (!ObjectUtils.equalsAny(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), + if (!ObjectUtils.equalsAny(oldContract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { throw exception(CONTRACT_UPDATE_FAIL_NOT_DRAFT); } @@ -159,8 +159,9 @@ public class CrmContractServiceImpl implements CrmContractService { updateContractProduct(updateReqVO.getId(), contractProducts); // 3. 记录操作日志上下文 - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contract, CrmContractSaveReqVO.class)); - LogRecordContext.putVariable("contractName", contract.getName()); + updateReqVO.setOwnerUserId(oldContract.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class)); + LogRecordContext.putVariable("contractName", oldContract.getName()); } private void updateContractProduct(Long id, List newList) { diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 184369c791..11ac107d98 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -137,6 +137,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { customerMapper.updateById(updateObj); // 3. 记录操作日志上下文 + updateReqVO.setOwnerUserId(oldCustomer.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldCustomer, CrmCustomerSaveReqVO.class)); LogRecordContext.putVariable("customerName", oldCustomer.getName()); } diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index b18c1a0c4f..5005508bbb 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -104,6 +104,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { receivablePlanMapper.updateById(updateObj); // 3. 记录操作日志上下文 + updateReqVO.setOwnerUserId(oldReceivablePlan.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivablePlan, CrmReceivablePlanSaveReqVO.class)); LogRecordContext.putVariable("receivablePlan", oldReceivablePlan); } diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index c1ba3a7c43..642c8e6872 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -162,14 +162,14 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { Assert.notNull(updateReqVO.getId(), "回款编号不能为空"); updateReqVO.setOwnerUserId(null).setCustomerId(null).setContractId(null).setPlanId(null); // 不允许修改的字段 // 1.1 校验存在 - CrmReceivableDO receivable = validateReceivableExists(updateReqVO.getId()); - updateReqVO.setOwnerUserId(receivable.getOwnerUserId()).setCustomerId(receivable.getCustomerId()) - .setContractId(receivable.getContractId()).setPlanId(receivable.getPlanId()); // 设置已存在的值 + CrmReceivableDO oldReceivable = validateReceivableExists(updateReqVO.getId()); + updateReqVO.setOwnerUserId(oldReceivable.getOwnerUserId()).setCustomerId(oldReceivable.getCustomerId()) + .setContractId(oldReceivable.getContractId()).setPlanId(oldReceivable.getPlanId()); // 设置已存在的值 // 1.2 校验可回款金额超过上限 validateReceivablePriceExceedsLimit(updateReqVO); // 1.3 只有草稿、审批中,可以编辑; - if (!ObjectUtils.equalsAny(receivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), + if (!ObjectUtils.equalsAny(oldReceivable.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { throw exception(RECEIVABLE_UPDATE_FAIL_EDITING_PROHIBITED); } @@ -179,9 +179,10 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { receivableMapper.updateById(updateObj); // 3. 记录操作日志上下文 - LogRecordContext.putVariable("receivable", receivable); - LogRecordContext.putVariable("period", getReceivablePeriod(receivable.getPlanId())); - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(receivable, CrmReceivableSaveReqVO.class)); + updateReqVO.setOwnerUserId(oldReceivable.getOwnerUserId()); // 避免操作日志出现“删除负责人”的情况 + LogRecordContext.putVariable("oldReceivable", oldReceivable); + LogRecordContext.putVariable("period", getReceivablePeriod(oldReceivable.getPlanId())); + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldReceivable, CrmReceivableSaveReqVO.class)); } private Integer getReceivablePeriod(Long planId) { From c96f6bb3607481fcac7cb10be17be4e2e3477299 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 13:19:14 +0800 Subject: [PATCH 26/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90CRM=20=E5=AE=A2?= =?UTF-8?q?=E6=88=B7=E7=AE=A1=E7=90=86=E3=80=91CRM=20=E8=B6=85=E7=AE=A1?= =?UTF-8?q?=EF=BC=8C=E6=97=A0=E6=B3=95=E5=BC=BA=E5=88=B6=E8=BD=AC=E7=A7=BB?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/service/permission/CrmPermissionServiceImpl.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index b479443390..6e2c37c89a 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -210,12 +210,12 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { CrmPermissionDO oldPermission = permissionMapper.selectByBizTypeAndBizIdByUserId( transferReqBO.getBizType(), transferReqBO.getBizId(), transferReqBO.getUserId()); String bizTypeName = CrmBizTypeEnum.getNameByType(transferReqBO.getBizType()); - if (oldPermission == null // 不是拥有者,并且不是超管 - || (!isOwner(oldPermission.getLevel()) && !CrmPermissionUtils.isCrmAdmin())) { + if ((oldPermission == null || !isOwner(oldPermission.getLevel())) + && !CrmPermissionUtils.isCrmAdmin()) { // 并且不是超管 throw exception(CRM_PERMISSION_DENIED, bizTypeName); } // 1.1 校验转移对象是否已经是该负责人 - if (ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) { + if (oldPermission != null && ObjUtil.equal(transferReqBO.getNewOwnerUserId(), oldPermission.getUserId())) { throw exception(CRM_PERMISSION_MODEL_TRANSFER_FAIL_OWNER_USER_EXISTS, bizTypeName); } // 1.2 校验新负责人是否存在 From e50250449a1d38128d6577917aa033e1414731a9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 19:50:02 +0800 Subject: [PATCH 27/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90AI=20=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E3=80=91UserProfileQueryToolFunction=20?= =?UTF-8?q?=E6=B2=A1=E6=9C=89=E5=8F=82=E6=95=B0=EF=BC=8C=E4=BC=9A=E6=8A=A5?= =?UTF-8?q?=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../tool/UserProfileQueryToolFunction.java | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/model/tool/UserProfileQueryToolFunction.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/model/tool/UserProfileQueryToolFunction.java index 6e0ba51c9e..5656d39292 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/model/tool/UserProfileQueryToolFunction.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/model/tool/UserProfileQueryToolFunction.java @@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.fasterxml.jackson.annotation.JsonClassDescription; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyDescription; import jakarta.annotation.Resource; import lombok.AllArgsConstructor; import lombok.Data; @@ -17,7 +19,7 @@ import org.springframework.stereotype.Component; import java.util.function.BiFunction; /** - * 工具:当前用户信息查询 + * 工具:用户信息查询 * * 同时,也是展示 ToolContext 上下文的使用 * @@ -31,8 +33,17 @@ public class UserProfileQueryToolFunction private AdminUserApi adminUserApi; @Data - @JsonClassDescription("当前用户信息查询") - public static class Request { } + @JsonClassDescription("用户信息查询") + public static class Request { + + /** + * 用户编号 + */ + @JsonProperty(value = "id") + @JsonPropertyDescription("用户编号,例如说:1。如果查询自己,则 id 为空") + private Long id; + + } @Data @AllArgsConstructor @@ -61,13 +72,19 @@ public class UserProfileQueryToolFunction @Override public Response apply(Request request, ToolContext toolContext) { - LoginUser loginUser = (LoginUser) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_LOGIN_USER); Long tenantId = (Long) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_TENANT_ID); - if (loginUser == null | tenantId == null) { - return null; + if (tenantId == null) { + return new Response(); + } + if (request.getId() == null) { + LoginUser loginUser = (LoginUser) toolContext.getContext().get(AiUtils.TOOL_CONTEXT_LOGIN_USER); + if (loginUser == null) { + return new Response(); + } + request.setId(loginUser.getId()); } return TenantUtils.execute(tenantId, () -> { - AdminUserRespDTO user = adminUserApi.getUser(loginUser.getId()); + AdminUserRespDTO user = adminUserApi.getUser(request.getId()); return BeanUtils.toBean(user, Response.class); }); } From c789418a7bd9aedd1097de1b160141b7dded92eb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 20:34:42 +0800 Subject: [PATCH 28/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90AI=20=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E3=80=91=E4=BE=9D=E8=B5=96=20spring=20ai=20?= =?UTF-8?q?=E5=8D=87=E7=BA=A7=E5=88=B0=201.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/pom.xml | 38 ++++++++++--------- .../ai/config/AiAutoConfiguration.java | 8 ++-- .../siliconflow/SiliconFlowImageModel.java | 2 +- .../ai/service/image/AiImageServiceImpl.java | 16 ++++---- .../iocoder/yudao/module/ai/util/AiUtils.java | 14 +++---- .../core/model/chat/OpenAIChatModelTests.java | 4 +- .../core/model/chat/TongYiChatModelTests.java | 11 ++++-- .../model/image/OpenAiImageModelTests.java | 6 +-- .../src/main/resources/application-dev.yaml | 4 +- .../src/main/resources/application-local.yaml | 4 +- 10 files changed, 56 insertions(+), 51 deletions(-) diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml index 4b02a7e00f..95c836777a 100644 --- a/yudao-module-ai/pom.xml +++ b/yudao-module-ai/pom.xml @@ -19,7 +19,8 @@ 国外:OpenAI、Ollama、Midjourney、StableDiffusion、Suno - 1.0.0-M6 + 1.0.0 + 1.0.0.2 1.0.2 @@ -75,65 +76,66 @@ org.springframework.ai - spring-ai-openai-spring-boot-starter + spring-ai-starter-model-openai ${spring-ai.version} org.springframework.ai - spring-ai-azure-openai-spring-boot-starter + spring-ai-starter-model-azure-openai ${spring-ai.version} org.springframework.ai - spring-ai-ollama-spring-boot-starter + spring-ai-starter-model-ollama ${spring-ai.version} org.springframework.ai - spring-ai-stability-ai-spring-boot-starter + spring-ai-starter-model-stability-ai ${spring-ai.version} com.alibaba.cloud.ai - spring-ai-alibaba-starter - ${spring-ai.version}.1 + spring-ai-alibaba-starter-dashscope + ${alibaba-ai.version} - org.springframework.ai - spring-ai-qianfan-spring-boot-starter - ${spring-ai.version} + org.springaicommunity + qianfan-spring-boot-starter + 1.0.0 org.springframework.ai - spring-ai-zhipuai-spring-boot-starter + spring-ai-starter-model-zhipuai ${spring-ai.version} org.springframework.ai - spring-ai-minimax-spring-boot-starter + spring-ai-starter-model-minimax ${spring-ai.version} - org.springframework.ai - spring-ai-moonshot-spring-boot-starter - ${spring-ai.version} + + org.springaicommunity + moonshot-spring-boot-starter + 1.0.0 org.springframework.ai - spring-ai-qdrant-store + spring-ai-starter-vector-store-qdrant ${spring-ai.version} org.springframework.ai - spring-ai-redis-store + spring-ai-starter-vector-store-redis ${spring-ai.version} @@ -144,7 +146,7 @@ org.springframework.ai - spring-ai-milvus-store + spring-ai-starter-vector-store-milvus ${spring-ai.version} diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java index a28d726b90..ae8a7e75f6 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java @@ -14,10 +14,6 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties; -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties; -import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties; -import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; import org.springframework.ai.embedding.BatchingStrategy; import org.springframework.ai.embedding.TokenCountBatchingStrategy; import org.springframework.ai.model.tool.ToolCallingManager; @@ -26,6 +22,10 @@ import org.springframework.ai.openai.OpenAiChatOptions; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.tokenizer.JTokkitTokenCountEstimator; import org.springframework.ai.tokenizer.TokenCountEstimator; +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties; +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties; +import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties; +import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.context.annotation.Bean; diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/siliconflow/SiliconFlowImageModel.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/siliconflow/SiliconFlowImageModel.java index 43f8ad2168..44a652309e 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/siliconflow/SiliconFlowImageModel.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/siliconflow/SiliconFlowImageModel.java @@ -89,7 +89,7 @@ public class SiliconFlowImageModel implements ImageModel { var observationContext = ImageModelObservationContext.builder() .imagePrompt(imagePrompt) .provider(SiliconFlowApiConstants.PROVIDER_NAME) - .requestOptions(imagePrompt.getOptions()) + .imagePrompt(imagePrompt) .build(); return ImageModelObservationDocumentation.IMAGE_MODEL_OPERATION diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java index 671098a704..79214a0325 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/service/image/AiImageServiceImpl.java @@ -9,9 +9,6 @@ import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; import cn.hutool.http.HttpUtil; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageOptions; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.ai.controller.admin.image.vo.AiImageDrawReqVO; @@ -24,17 +21,20 @@ import cn.iocoder.yudao.module.ai.dal.dataobject.image.AiImageDO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiModelDO; import cn.iocoder.yudao.module.ai.dal.mysql.image.AiImageMapper; import cn.iocoder.yudao.module.ai.enums.image.AiImageStatusEnum; +import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; +import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; +import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageOptions; import cn.iocoder.yudao.module.ai.service.model.AiModelService; import cn.iocoder.yudao.module.infra.api.file.FileApi; import com.alibaba.cloud.ai.dashscope.image.DashScopeImageOptions; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springaicommunity.qianfan.QianFanImageOptions; import org.springframework.ai.image.ImageModel; import org.springframework.ai.image.ImageOptions; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; import org.springframework.ai.openai.OpenAiImageOptions; -import org.springframework.ai.qianfan.QianFanImageOptions; import org.springframework.ai.stabilityai.api.StabilityAiImageOptions; import org.springframework.ai.zhipuai.ZhiPuAiImageOptions; import org.springframework.scheduling.annotation.Async; @@ -140,10 +140,10 @@ public class AiImageServiceImpl implements AiImageService { private static ImageOptions buildImageOptions(AiImageDrawReqVO draw, AiModelDO model) { if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.OPENAI.getPlatform())) { // https://platform.openai.com/docs/api-reference/images/create - return OpenAiImageOptions.builder().withModel(model.getModel()) - .withHeight(draw.getHeight()).withWidth(draw.getWidth()) - .withStyle(MapUtil.getStr(draw.getOptions(), "style")) // 风格 - .withResponseFormat("b64_json") + return OpenAiImageOptions.builder().model(model.getModel()) + .height(draw.getHeight()).width(draw.getWidth()) + .style(MapUtil.getStr(draw.getOptions(), "style")) // 风格 + .responseFormat("b64_json") .build(); } else if (ObjUtil.equal(model.getPlatform(), AiPlatformEnum.SILICON_FLOW.getPlatform())) { // https://docs.siliconflow.cn/cn/api-reference/images/images-generations diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java index ac3ff39a49..0744ff6307 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/util/AiUtils.java @@ -2,18 +2,18 @@ package cn.iocoder.yudao.module.ai.util; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatOptions; +import org.springaicommunity.moonshot.MoonshotChatOptions; +import org.springaicommunity.qianfan.QianFanChatOptions; import org.springframework.ai.azure.openai.AzureOpenAiChatOptions; import org.springframework.ai.chat.messages.*; import org.springframework.ai.chat.prompt.ChatOptions; import org.springframework.ai.minimax.MiniMaxChatOptions; -import org.springframework.ai.moonshot.MoonshotChatOptions; import org.springframework.ai.ollama.api.OllamaOptions; import org.springframework.ai.openai.OpenAiChatOptions; -import org.springframework.ai.qianfan.QianFanChatOptions; import org.springframework.ai.zhipuai.ZhiPuAiChatOptions; import java.util.Collections; @@ -43,18 +43,18 @@ public class AiUtils { switch (platform) { case TONG_YI: return DashScopeChatOptions.builder().withModel(model).withTemperature(temperature).withMaxToken(maxTokens) - .withFunctions(toolNames).withToolContext(toolContext).build(); + .withToolNames(toolNames).withToolContext(toolContext).build(); case YI_YAN: return QianFanChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens).build(); case ZHI_PU: return ZhiPuAiChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) - .functions(toolNames).toolContext(toolContext).build(); + .toolNames(toolNames).toolContext(toolContext).build(); case MINI_MAX: return MiniMaxChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) - .functions(toolNames).toolContext(toolContext).build(); + .toolNames(toolNames).toolContext(toolContext).build(); case MOONSHOT: return MoonshotChatOptions.builder().model(model).temperature(temperature).maxTokens(maxTokens) - .functions(toolNames).toolContext(toolContext).build(); + .toolNames(toolNames).toolContext(toolContext).build(); case OPENAI: case DEEP_SEEK: // 复用 OpenAI 客户端 case DOU_BAO: // 复用 OpenAI 客户端 diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OpenAIChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OpenAIChatModelTests.java index ff866fe40b..c650fd0420 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OpenAIChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OpenAIChatModelTests.java @@ -25,10 +25,10 @@ public class OpenAIChatModelTests { private final OpenAiChatModel chatModel = OpenAiChatModel.builder() .openAiApi(OpenAiApi.builder() .baseUrl("https://api.holdai.top") - .apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17") // apiKey + .apiKey("sk-PytRecQlmjEteoa2RRN6cGnwslo72UUPLQVNEMS6K9yjbmpD") // apiKey .build()) .defaultOptions(OpenAiChatOptions.builder() - .model(OpenAiApi.ChatModel.GPT_4_O) // 模型 + .model(OpenAiApi.ChatModel.GPT_4_1_NANO) // 模型 .temperature(0.7) .build()) .build(); diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java index 4f0efdb20c..4f2e27edd2 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/TongYiChatModelTests.java @@ -22,14 +22,17 @@ import java.util.List; */ public class TongYiChatModelTests { - private final DashScopeChatModel chatModel = new DashScopeChatModel( - new DashScopeApi("sk-7d903764249848cfa912733146da12d1"), - DashScopeChatOptions.builder() + private final DashScopeChatModel chatModel = DashScopeChatModel.builder() + .dashScopeApi(DashScopeApi.builder() + .apiKey("sk-47aa124781be4bfb95244cc62f63f7d0") + .build()) + .defaultOptions( DashScopeChatOptions.builder() .withModel("qwen1.5-72b-chat") // 模型 // .withModel("deepseek-r1") // 模型(deepseek-r1) // .withModel("deepseek-v3") // 模型(deepseek-v3) // .withModel("deepseek-r1-distill-qwen-1.5b") // 模型(deepseek-r1-distill-qwen-1.5b) - .build()); + .build()) + .build(); @Test @Disabled diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/OpenAiImageModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/OpenAiImageModelTests.java index 49015b9b9e..1b124529de 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/OpenAiImageModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/OpenAiImageModelTests.java @@ -18,7 +18,7 @@ public class OpenAiImageModelTests { private final OpenAiImageModel imageModel = new OpenAiImageModel(OpenAiImageApi.builder() .baseUrl("https://api.holdai.top") // apiKey - .apiKey("sk-aN6nWn3fILjrgLFT0fC4Aa60B72e4253826c77B29dC94f17") + .apiKey("sk-PytRecQlmjEteoa2RRN6cGnwslo72UUPLQVNEMS6K9yjbmpD") .build()); @Test @@ -26,8 +26,8 @@ public class OpenAiImageModelTests { public void testCall() { // 准备参数 ImageOptions options = OpenAiImageOptions.builder() - .withModel(OpenAiImageApi.ImageModel.DALL_E_2.getValue()) // 这个模型比较便宜 - .withHeight(256).withWidth(256) + .model(OpenAiImageApi.ImageModel.DALL_E_2.getValue()) // 这个模型比较便宜 + .height(256).width(256) .build(); ImagePrompt prompt = new ImagePrompt("中国长城!", options); diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index db07245c63..344e97ecf8 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -6,8 +6,8 @@ server: spring: autoconfigure: exclude: - - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 - - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 + - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 + - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 # 数据源配置项 datasource: druid: # Druid 【监控】相关的全局配置 diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 2849775e62..5d23b9b70d 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -10,8 +10,8 @@ spring: - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 - - org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 - - org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 + - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 + - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 # 数据源配置项 datasource: druid: # Druid 【监控】相关的全局配置 From 3d0eb77148c5869c42699ba1f2831e4ed89f01ab Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 20:56:00 +0800 Subject: [PATCH 29/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90AI=20=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E3=80=91=E5=BC=95=E5=85=A5=20spring-ai-start?= =?UTF-8?q?er-model-deepseek=20=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-ai/pom.xml | 31 ++++++++----- .../ai/config/AiAutoConfiguration.java | 28 ------------ .../ai/config/YudaoAiProperties.java | 19 -------- .../model/deepseek/DeepSeekChatModel.java | 45 ------------------- .../model/chat/DeepSeekChatModelTests.java | 18 +++----- 5 files changed, 26 insertions(+), 115 deletions(-) delete mode 100644 yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/deepseek/DeepSeekChatModel.java diff --git a/yudao-module-ai/pom.xml b/yudao-module-ai/pom.xml index 95c836777a..4a2323bcfa 100644 --- a/yudao-module-ai/pom.xml +++ b/yudao-module-ai/pom.xml @@ -84,6 +84,11 @@ spring-ai-starter-model-azure-openai ${spring-ai.version} + + org.springframework.ai + spring-ai-starter-model-deepseek + ${spring-ai.version} + org.springframework.ai spring-ai-starter-model-ollama @@ -94,18 +99,6 @@ spring-ai-starter-model-stability-ai ${spring-ai.version} - - - com.alibaba.cloud.ai - spring-ai-alibaba-starter-dashscope - ${alibaba-ai.version} - - - - org.springaicommunity - qianfan-spring-boot-starter - 1.0.0 - org.springframework.ai @@ -117,6 +110,20 @@ spring-ai-starter-model-minimax ${spring-ai.version} + + + + com.alibaba.cloud.ai + spring-ai-alibaba-starter-dashscope + ${alibaba-ai.version} + + + + + org.springaicommunity + qianfan-spring-boot-starter + 1.0.0 + org.springaicommunity diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java index ae8a7e75f6..4ff7c9e4dc 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/AiAutoConfiguration.java @@ -5,7 +5,6 @@ import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactory; import cn.iocoder.yudao.module.ai.framework.ai.core.AiModelFactoryImpl; import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; @@ -52,33 +51,6 @@ public class AiAutoConfiguration { // ========== 各种 AI Client 创建 ========== - @Bean - @ConditionalOnProperty(value = "yudao.ai.deepseek.enable", havingValue = "true") - public DeepSeekChatModel deepSeekChatModel(YudaoAiProperties yudaoAiProperties) { - YudaoAiProperties.DeepSeekProperties properties = yudaoAiProperties.getDeepseek(); - return buildDeepSeekChatModel(properties); - } - - public DeepSeekChatModel buildDeepSeekChatModel(YudaoAiProperties.DeepSeekProperties properties) { - if (StrUtil.isEmpty(properties.getModel())) { - properties.setModel(DeepSeekChatModel.MODEL_DEFAULT); - } - OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(DeepSeekChatModel.BASE_URL) - .apiKey(properties.getApiKey()) - .build()) - .defaultOptions(OpenAiChatOptions.builder() - .model(properties.getModel()) - .temperature(properties.getTemperature()) - .maxTokens(properties.getMaxTokens()) - .topP(properties.getTopP()) - .build()) - .toolCallingManager(getToolCallingManager()) - .build(); - return new DeepSeekChatModel(openAiChatModel); - } - @Bean @ConditionalOnProperty(value = "yudao.ai.doubao.enable", havingValue = "true") public DouBaoChatModel douBaoChatClient(YudaoAiProperties yudaoAiProperties) { diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java index 7f8046768a..7c26aa89ca 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/config/YudaoAiProperties.java @@ -13,12 +13,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; @Data public class YudaoAiProperties { - /** - * DeepSeek - */ - @SuppressWarnings("SpellCheckingInspection") - private DeepSeekProperties deepseek; - /** * 字节豆包 */ @@ -60,19 +54,6 @@ public class YudaoAiProperties { @SuppressWarnings("SpellCheckingInspection") private SunoProperties suno; - @Data - public static class DeepSeekProperties { - - private String enable; - private String apiKey; - - private String model; - private Double temperature; - private Integer maxTokens; - private Double topP; - - } - @Data public static class DouBaoProperties { diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/deepseek/DeepSeekChatModel.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/deepseek/DeepSeekChatModel.java deleted file mode 100644 index d603abf6b0..0000000000 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/deepseek/DeepSeekChatModel.java +++ /dev/null @@ -1,45 +0,0 @@ -package cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.ai.chat.model.ChatModel; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.ChatOptions; -import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatModel; -import reactor.core.publisher.Flux; - -/** - * DeepSeek {@link ChatModel} 实现类 - * - * @author fansili - */ -@Slf4j -@RequiredArgsConstructor -public class DeepSeekChatModel implements ChatModel { - - public static final String BASE_URL = "https://api.deepseek.com"; - - public static final String MODEL_DEFAULT = "deepseek-chat"; - - /** - * 兼容 OpenAI 接口,进行复用 - */ - private final OpenAiChatModel openAiChatModel; - - @Override - public ChatResponse call(Prompt prompt) { - return openAiChatModel.call(prompt); - } - - @Override - public Flux stream(Prompt prompt) { - return openAiChatModel.stream(prompt); - } - - @Override - public ChatOptions getDefaultOptions() { - return openAiChatModel.getDefaultOptions(); - } - -} diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/DeepSeekChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/DeepSeekChatModelTests.java index d20a1761f6..7b51df1662 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/DeepSeekChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/DeepSeekChatModelTests.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.ai.chat.messages.Message; @@ -8,9 +7,9 @@ import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.openai.OpenAiChatModel; -import org.springframework.ai.openai.OpenAiChatOptions; -import org.springframework.ai.openai.api.OpenAiApi; +import org.springframework.ai.deepseek.DeepSeekChatModel; +import org.springframework.ai.deepseek.DeepSeekChatOptions; +import org.springframework.ai.deepseek.api.DeepSeekApi; import reactor.core.publisher.Flux; import java.util.ArrayList; @@ -23,19 +22,16 @@ import java.util.List; */ public class DeepSeekChatModelTests { - private final OpenAiChatModel openAiChatModel = OpenAiChatModel.builder() - .openAiApi(OpenAiApi.builder() - .baseUrl(DeepSeekChatModel.BASE_URL) - .apiKey("sk-e52047409b144d97b791a6a46a2d") // apiKey + private final DeepSeekChatModel chatModel = DeepSeekChatModel.builder() + .deepSeekApi(DeepSeekApi.builder() + .apiKey("sk-eaf4172a057344dd9bc64b1f806b6axx") // apiKey .build()) - .defaultOptions(OpenAiChatOptions.builder() + .defaultOptions(DeepSeekChatOptions.builder() .model("deepseek-chat") // 模型 .temperature(0.7) .build()) .build(); - private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel); - @Test @Disabled public void testCall() { From 750709d706fdad1fdde16e6fab7a75de238ea879 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 21:40:00 +0800 Subject: [PATCH 30/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90AI=20=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E3=80=91deepseek=E3=80=81azure=E3=80=81baich?= =?UTF-8?q?uan=E3=80=81moonshot=20=E9=80=82=E9=85=8D=201.0.0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/core/AiModelFactoryImpl.java | 223 +++++++++++------- .../model/chat/AzureOpenAIChatModelTests.java | 14 +- .../model/chat/BaiChuanChatModelTests.java | 3 +- .../model/chat/MoonshotChatModelTests.java | 20 +- .../image/StabilityAiImageModelTests.java | 4 +- .../src/main/resources/application.yaml | 9 +- 6 files changed, 160 insertions(+), 113 deletions(-) diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java index f258ffaf1b..2aeecab917 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java @@ -8,11 +8,11 @@ import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.RuntimeUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; +import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; import cn.iocoder.yudao.module.ai.framework.ai.config.AiAutoConfiguration; import cn.iocoder.yudao.module.ai.framework.ai.config.YudaoAiProperties; -import cn.iocoder.yudao.module.ai.enums.model.AiPlatformEnum; import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.doubao.DouBaoChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.hunyuan.HunYuanChatModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.midjourney.api.MidjourneyApi; @@ -22,8 +22,9 @@ import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlo import cn.iocoder.yudao.module.ai.framework.ai.core.model.siliconflow.SiliconFlowImageModel; import cn.iocoder.yudao.module.ai.framework.ai.core.model.suno.api.SunoApi; import cn.iocoder.yudao.module.ai.framework.ai.core.model.xinghuo.XingHuoChatModel; -import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; -import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeAutoConfiguration; +import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeChatAutoConfiguration; +import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeEmbeddingAutoConfiguration; +import com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeImageAutoConfiguration; import com.alibaba.cloud.ai.dashscope.api.DashScopeApi; import com.alibaba.cloud.ai.dashscope.api.DashScopeImageApi; import com.alibaba.cloud.ai.dashscope.chat.DashScopeChatModel; @@ -32,47 +33,55 @@ import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingModel; import com.alibaba.cloud.ai.dashscope.embedding.DashScopeEmbeddingOptions; import com.alibaba.cloud.ai.dashscope.image.DashScopeImageModel; import com.azure.ai.openai.OpenAIClientBuilder; +import com.azure.core.credential.KeyCredential; import io.micrometer.observation.ObservationRegistry; import io.milvus.client.MilvusServiceClient; import io.qdrant.client.QdrantClient; import io.qdrant.client.QdrantGrpcClient; import lombok.SneakyThrows; -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiAutoConfiguration; -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties; -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiConnectionProperties; -import org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiEmbeddingProperties; -import org.springframework.ai.autoconfigure.minimax.MiniMaxAutoConfiguration; -import org.springframework.ai.autoconfigure.moonshot.MoonshotAutoConfiguration; -import org.springframework.ai.autoconfigure.ollama.OllamaAutoConfiguration; -import org.springframework.ai.autoconfigure.openai.OpenAiAutoConfiguration; -import org.springframework.ai.autoconfigure.qianfan.QianFanAutoConfiguration; -import org.springframework.ai.autoconfigure.stabilityai.StabilityAiImageAutoConfiguration; -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientConnectionDetails; -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusServiceClientProperties; -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreAutoConfiguration; -import org.springframework.ai.autoconfigure.vectorstore.milvus.MilvusVectorStoreProperties; -import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreAutoConfiguration; -import org.springframework.ai.autoconfigure.vectorstore.qdrant.QdrantVectorStoreProperties; -import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreAutoConfiguration; -import org.springframework.ai.autoconfigure.vectorstore.redis.RedisVectorStoreProperties; -import org.springframework.ai.autoconfigure.zhipuai.ZhiPuAiAutoConfiguration; +import org.springaicommunity.moonshot.MoonshotChatModel; +import org.springaicommunity.moonshot.MoonshotChatOptions; +import org.springaicommunity.moonshot.api.MoonshotApi; +import org.springaicommunity.moonshot.autoconfigure.MoonshotChatAutoConfiguration; +import org.springaicommunity.qianfan.QianFanChatModel; +import org.springaicommunity.qianfan.QianFanEmbeddingModel; +import org.springaicommunity.qianfan.QianFanEmbeddingOptions; +import org.springaicommunity.qianfan.QianFanImageModel; +import org.springaicommunity.qianfan.api.QianFanApi; +import org.springaicommunity.qianfan.api.QianFanImageApi; +import org.springaicommunity.qianfan.autoconfigure.QianFanChatAutoConfiguration; +import org.springaicommunity.qianfan.autoconfigure.QianFanEmbeddingAutoConfiguration; import org.springframework.ai.azure.openai.AzureOpenAiChatModel; import org.springframework.ai.azure.openai.AzureOpenAiEmbeddingModel; import org.springframework.ai.chat.model.ChatModel; +import org.springframework.ai.deepseek.DeepSeekChatModel; +import org.springframework.ai.deepseek.DeepSeekChatOptions; +import org.springframework.ai.deepseek.api.DeepSeekApi; import org.springframework.ai.document.MetadataMode; import org.springframework.ai.embedding.BatchingStrategy; import org.springframework.ai.embedding.EmbeddingModel; +import org.springframework.ai.embedding.observation.EmbeddingModelObservationConvention; import org.springframework.ai.image.ImageModel; import org.springframework.ai.minimax.MiniMaxChatModel; import org.springframework.ai.minimax.MiniMaxChatOptions; import org.springframework.ai.minimax.MiniMaxEmbeddingModel; import org.springframework.ai.minimax.MiniMaxEmbeddingOptions; import org.springframework.ai.minimax.api.MiniMaxApi; -import org.springframework.ai.model.function.FunctionCallbackResolver; +import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatAutoConfiguration; +import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingAutoConfiguration; +import org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiEmbeddingProperties; +import org.springframework.ai.model.deepseek.autoconfigure.DeepSeekChatAutoConfiguration; +import org.springframework.ai.model.minimax.autoconfigure.MiniMaxChatAutoConfiguration; +import org.springframework.ai.model.minimax.autoconfigure.MiniMaxEmbeddingAutoConfiguration; +import org.springframework.ai.model.ollama.autoconfigure.OllamaChatAutoConfiguration; +import org.springframework.ai.model.openai.autoconfigure.OpenAiChatAutoConfiguration; +import org.springframework.ai.model.openai.autoconfigure.OpenAiEmbeddingAutoConfiguration; +import org.springframework.ai.model.openai.autoconfigure.OpenAiImageAutoConfiguration; +import org.springframework.ai.model.stabilityai.autoconfigure.StabilityAiImageAutoConfiguration; import org.springframework.ai.model.tool.ToolCallingManager; -import org.springframework.ai.moonshot.MoonshotChatModel; -import org.springframework.ai.moonshot.MoonshotChatOptions; -import org.springframework.ai.moonshot.api.MoonshotApi; +import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiChatAutoConfiguration; +import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiEmbeddingAutoConfiguration; +import org.springframework.ai.model.zhipuai.autoconfigure.ZhiPuAiImageAutoConfiguration; import org.springframework.ai.ollama.OllamaChatModel; import org.springframework.ai.ollama.OllamaEmbeddingModel; import org.springframework.ai.ollama.api.OllamaApi; @@ -84,21 +93,23 @@ import org.springframework.ai.openai.OpenAiImageModel; import org.springframework.ai.openai.api.OpenAiApi; import org.springframework.ai.openai.api.OpenAiImageApi; import org.springframework.ai.openai.api.common.OpenAiApiConstants; -import org.springframework.ai.qianfan.QianFanChatModel; -import org.springframework.ai.qianfan.QianFanEmbeddingModel; -import org.springframework.ai.qianfan.QianFanEmbeddingOptions; -import org.springframework.ai.qianfan.QianFanImageModel; -import org.springframework.ai.qianfan.api.QianFanApi; -import org.springframework.ai.qianfan.api.QianFanImageApi; import org.springframework.ai.stabilityai.StabilityAiImageModel; import org.springframework.ai.stabilityai.api.StabilityAiApi; import org.springframework.ai.vectorstore.SimpleVectorStore; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.ai.vectorstore.milvus.MilvusVectorStore; +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientConnectionDetails; +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusServiceClientProperties; +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration; +import org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreProperties; import org.springframework.ai.vectorstore.observation.DefaultVectorStoreObservationConvention; import org.springframework.ai.vectorstore.observation.VectorStoreObservationConvention; import org.springframework.ai.vectorstore.qdrant.QdrantVectorStore; +import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration; +import org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreProperties; import org.springframework.ai.vectorstore.redis.RedisVectorStore; +import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreAutoConfiguration; +import org.springframework.ai.vectorstore.redis.autoconfigure.RedisVectorStoreProperties; import org.springframework.ai.zhipuai.*; import org.springframework.ai.zhipuai.api.ZhiPuAiApi; import org.springframework.ai.zhipuai.api.ZhiPuAiImageApi; @@ -190,7 +201,7 @@ public class AiModelFactoryImpl implements AiModelFactory { case XING_HUO: return SpringUtil.getBean(XingHuoChatModel.class); case BAI_CHUAN: - return SpringUtil.getBean(AzureOpenAiChatModel.class); + return SpringUtil.getBean(BaiChuanChatModel.class); case OPENAI: return SpringUtil.getBean(OpenAiChatModel.class); case AZURE_OPENAI: @@ -319,27 +330,34 @@ public class AiModelFactoryImpl implements AiModelFactory { // ========== 各种创建 spring-ai 客户端的方法 ========== /** - * 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeChatModel 方法 + * 可参考 {@link DashScopeChatAutoConfiguration} 的 dashscopeChatModel 方法 */ private static DashScopeChatModel buildTongYiChatModel(String key) { - DashScopeApi dashScopeApi = new DashScopeApi(key); + DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(key).build(); DashScopeChatOptions options = DashScopeChatOptions.builder().withModel(DashScopeApi.DEFAULT_CHAT_MODEL) .withTemperature(0.7).build(); - return new DashScopeChatModel(dashScopeApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); + return DashScopeChatModel.builder() + .dashScopeApi(dashScopeApi) + .defaultOptions(options) + .toolCallingManager(getToolCallingManager()) + .build(); } /** - * 可参考 {@link DashScopeAutoConfiguration} 的 dashScopeImageModel 方法 + * 可参考 {@link DashScopeImageAutoConfiguration} 的 dashScopeImageModel 方法 */ private static DashScopeImageModel buildTongYiImagesModel(String key) { DashScopeImageApi dashScopeImageApi = new DashScopeImageApi(key); - return new DashScopeImageModel(dashScopeImageApi); + return DashScopeImageModel.builder() + .dashScopeApi(dashScopeImageApi) + .build(); } /** - * 可参考 {@link QianFanAutoConfiguration} 的 qianFanChatModel 方法 + * 可参考 {@link QianFanChatAutoConfiguration} 的 qianFanChatModel 方法 */ private static QianFanChatModel buildYiYanChatModel(String key) { + // TODO @芋艿:未测试 List keys = StrUtil.split(key, '|'); Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); String appKey = keys.get(0); @@ -349,9 +367,10 @@ public class AiModelFactoryImpl implements AiModelFactory { } /** - * 可参考 {@link QianFanAutoConfiguration} 的 qianFanImageModel 方法 + * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanImageModel 方法 */ private QianFanImageModel buildQianFanImageModel(String key) { + // TODO @芋艿:未测试 List keys = StrUtil.split(key, '|'); Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); String appKey = keys.get(0); @@ -361,12 +380,17 @@ public class AiModelFactoryImpl implements AiModelFactory { } /** - * 可参考 {@link AiAutoConfiguration#deepSeekChatModel(YudaoAiProperties)} + * 可参考 {@link DeepSeekChatAutoConfiguration} 的 deepSeekChatModel 方法 */ private static DeepSeekChatModel buildDeepSeekChatModel(String apiKey) { - YudaoAiProperties.DeepSeekProperties properties = new YudaoAiProperties.DeepSeekProperties() - .setApiKey(apiKey); - return new AiAutoConfiguration().buildDeepSeekChatModel(properties); + DeepSeekApi deepSeekApi = DeepSeekApi.builder().apiKey(apiKey).build(); + DeepSeekChatOptions options = DeepSeekChatOptions.builder().model(DeepSeekApi.DEFAULT_CHAT_MODEL) + .temperature(0.7).build(); + return DeepSeekChatModel.builder() + .deepSeekApi(deepSeekApi) + .defaultOptions(options) + .toolCallingManager(getToolCallingManager()) + .build(); } /** @@ -397,17 +421,18 @@ public class AiModelFactoryImpl implements AiModelFactory { } /** - * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiChatModel 方法 + * 可参考 {@link ZhiPuAiChatAutoConfiguration} 的 zhiPuAiChatModel 方法 */ private ZhiPuAiChatModel buildZhiPuChatModel(String apiKey, String url) { ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) : new ZhiPuAiApi(url, apiKey); ZhiPuAiChatOptions options = ZhiPuAiChatOptions.builder().model(ZhiPuAiApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); - return new ZhiPuAiChatModel(zhiPuAiApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); + return new ZhiPuAiChatModel(zhiPuAiApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE, + getObservationRegistry().getIfAvailable()); } /** - * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiImageModel 方法 + * 可参考 {@link ZhiPuAiImageAutoConfiguration} 的 zhiPuAiImageModel 方法 */ private ZhiPuAiImageModel buildZhiPuAiImageModel(String apiKey, String url) { ZhiPuAiImageApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiImageApi(apiKey) @@ -416,23 +441,30 @@ public class AiModelFactoryImpl implements AiModelFactory { } /** - * 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxChatModel 方法 + * 可参考 {@link MiniMaxChatAutoConfiguration} 的 miniMaxChatModel 方法 */ private MiniMaxChatModel buildMiniMaxChatModel(String apiKey, String url) { MiniMaxApi miniMaxApi = StrUtil.isEmpty(url) ? new MiniMaxApi(apiKey) : new MiniMaxApi(url, apiKey); MiniMaxChatOptions options = MiniMaxChatOptions.builder().model(MiniMaxApi.DEFAULT_CHAT_MODEL).temperature(0.7).build(); - return new MiniMaxChatModel(miniMaxApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); + return new MiniMaxChatModel(miniMaxApi, options, getToolCallingManager(), DEFAULT_RETRY_TEMPLATE); } /** - * 可参考 {@link MoonshotAutoConfiguration} 的 moonshotChatModel 方法 + * 可参考 {@link MoonshotChatAutoConfiguration} 的 moonshotChatModel 方法 */ private MoonshotChatModel buildMoonshotChatModel(String apiKey, String url) { - MoonshotApi moonshotApi = StrUtil.isEmpty(url)? new MoonshotApi(apiKey) - : new MoonshotApi(url, apiKey); + MoonshotApi.Builder moonshotApiBuilder = MoonshotApi.builder() + .apiKey(apiKey); + if (StrUtil.isNotEmpty(url)) { + moonshotApiBuilder.baseUrl(url); + } MoonshotChatOptions options = MoonshotChatOptions.builder().model(MoonshotApi.DEFAULT_CHAT_MODEL).build(); - return new MoonshotChatModel(moonshotApi, options, getFunctionCallbackResolver(), DEFAULT_RETRY_TEMPLATE); + return MoonshotChatModel.builder() + .moonshotApi(moonshotApiBuilder.build()) + .defaultOptions(options) + .toolCallingManager(getToolCallingManager()) + .build(); } /** @@ -456,33 +488,32 @@ public class AiModelFactoryImpl implements AiModelFactory { } /** - * 可参考 {@link OpenAiAutoConfiguration} 的 openAiChatModel 方法 + * 可参考 {@link OpenAiChatAutoConfiguration} 的 openAiChatModel 方法 */ private static OpenAiChatModel buildOpenAiChatModel(String openAiToken, String url) { url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); OpenAiApi openAiApi = OpenAiApi.builder().baseUrl(url).apiKey(openAiToken).build(); - return OpenAiChatModel.builder().openAiApi(openAiApi).toolCallingManager(getToolCallingManager()).build(); + return OpenAiChatModel.builder() + .openAiApi(openAiApi) + .toolCallingManager(getToolCallingManager()) + .build(); } - // TODO @芋艿:手头暂时没密钥,使用建议再测试下 /** - * 可参考 {@link AzureOpenAiAutoConfiguration} + * 可参考 {@link AzureOpenAiChatAutoConfiguration} */ private static AzureOpenAiChatModel buildAzureOpenAiChatModel(String apiKey, String url) { - AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration(); - // 创建 OpenAIClient 对象 - AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties(); - connectionProperties.setApiKey(apiKey); - connectionProperties.setEndpoint(url); - OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null); - // 获取 AzureOpenAiChatProperties 对象 - AzureOpenAiChatProperties chatProperties = SpringUtil.getBean(AzureOpenAiChatProperties.class); - return azureOpenAiAutoConfiguration.azureOpenAiChatModel(openAIClient, chatProperties, - getToolCallingManager(), null, null); + // TODO @芋艿:使用前,请测试,暂时没密钥!!! + OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() + .endpoint(url).credential(new KeyCredential(apiKey)); + return AzureOpenAiChatModel.builder() + .openAIClientBuilder(openAIClientBuilder) + .toolCallingManager(getToolCallingManager()) + .build(); } /** - * 可参考 {@link OpenAiAutoConfiguration} 的 openAiImageModel 方法 + * 可参考 {@link OpenAiImageAutoConfiguration} 的 openAiImageModel 方法 */ private OpenAiImageModel buildOpenAiImageModel(String openAiToken, String url) { url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); @@ -494,16 +525,18 @@ public class AiModelFactoryImpl implements AiModelFactory { * 创建 SiliconFlowImageModel 对象 */ private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) { + // TODO @芋艿:未测试 url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL); SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken); return new SiliconFlowImageModel(openAiApi); } /** - * 可参考 {@link OllamaAutoConfiguration} 的 ollamaApi 方法 + * 可参考 {@link OllamaChatAutoConfiguration} 的 ollamaChatModel 方法 */ private static OllamaChatModel buildOllamaChatModel(String url) { - OllamaApi ollamaApi = new OllamaApi(url); + // TODO @芋艿:未测试 + OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); return OllamaChatModel.builder().ollamaApi(ollamaApi).toolCallingManager(getToolCallingManager()).build(); } @@ -519,16 +552,16 @@ public class AiModelFactoryImpl implements AiModelFactory { // ========== 各种创建 EmbeddingModel 的方法 ========== /** - * 可参考 {@link DashScopeAutoConfiguration} 的 dashscopeEmbeddingModel 方法 + * 可参考 {@link DashScopeEmbeddingAutoConfiguration} 的 dashscopeEmbeddingModel 方法 */ private DashScopeEmbeddingModel buildTongYiEmbeddingModel(String apiKey, String model) { - DashScopeApi dashScopeApi = new DashScopeApi(apiKey); + DashScopeApi dashScopeApi = DashScopeApi.builder().apiKey(apiKey).build(); DashScopeEmbeddingOptions dashScopeEmbeddingOptions = DashScopeEmbeddingOptions.builder().withModel(model).build(); return new DashScopeEmbeddingModel(dashScopeApi, MetadataMode.EMBED, dashScopeEmbeddingOptions); } /** - * 可参考 {@link ZhiPuAiAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法 + * 可参考 {@link ZhiPuAiEmbeddingAutoConfiguration} 的 zhiPuAiEmbeddingModel 方法 */ private ZhiPuAiEmbeddingModel buildZhiPuEmbeddingModel(String apiKey, String url, String model) { ZhiPuAiApi zhiPuAiApi = StrUtil.isEmpty(url) ? new ZhiPuAiApi(apiKey) @@ -538,7 +571,7 @@ public class AiModelFactoryImpl implements AiModelFactory { } /** - * 可参考 {@link MiniMaxAutoConfiguration} 的 miniMaxEmbeddingModel 方法 + * 可参考 {@link MiniMaxEmbeddingAutoConfiguration} 的 miniMaxEmbeddingModel 方法 */ private EmbeddingModel buildMiniMaxEmbeddingModel(String apiKey, String url, String model) { MiniMaxApi miniMaxApi = StrUtil.isEmpty(url)? new MiniMaxApi(apiKey) @@ -548,7 +581,7 @@ public class AiModelFactoryImpl implements AiModelFactory { } /** - * 可参考 {@link QianFanAutoConfiguration} 的 qianFanEmbeddingModel 方法 + * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanEmbeddingModel 方法 */ private QianFanEmbeddingModel buildYiYanEmbeddingModel(String key, String model) { List keys = StrUtil.split(key, '|'); @@ -561,13 +594,13 @@ public class AiModelFactoryImpl implements AiModelFactory { } private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) { - OllamaApi ollamaApi = new OllamaApi(url); + OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build(); return OllamaEmbeddingModel.builder().ollamaApi(ollamaApi).defaultOptions(ollamaOptions).build(); } /** - * 可参考 {@link OpenAiAutoConfiguration} 的 openAiEmbeddingModel 方法 + * 可参考 {@link OpenAiEmbeddingAutoConfiguration} 的 openAiEmbeddingModel 方法 */ private OpenAiEmbeddingModel buildOpenAiEmbeddingModel(String openAiToken, String url, String model) { url = StrUtil.blankToDefault(url, OpenAiApiConstants.DEFAULT_BASE_URL); @@ -576,21 +609,19 @@ public class AiModelFactoryImpl implements AiModelFactory { return new OpenAiEmbeddingModel(openAiApi, MetadataMode.EMBED, openAiEmbeddingProperties); } - // TODO @芋艿:手头暂时没密钥,使用建议再测试下 /** - * 可参考 {@link AzureOpenAiAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法 + * 可参考 {@link AzureOpenAiEmbeddingAutoConfiguration} 的 azureOpenAiEmbeddingModel 方法 */ private AzureOpenAiEmbeddingModel buildAzureOpenAiEmbeddingModel(String apiKey, String url, String model) { - AzureOpenAiAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiAutoConfiguration(); - // 创建 OpenAIClient 对象 - AzureOpenAiConnectionProperties connectionProperties = new AzureOpenAiConnectionProperties(); - connectionProperties.setApiKey(apiKey); - connectionProperties.setEndpoint(url); - OpenAIClientBuilder openAIClient = azureOpenAiAutoConfiguration.openAIClientBuilder(connectionProperties, null); + // TODO @芋艿:手头暂时没密钥,使用建议再测试下 + AzureOpenAiEmbeddingAutoConfiguration azureOpenAiAutoConfiguration = new AzureOpenAiEmbeddingAutoConfiguration(); + // 创建 OpenAIClientBuilder 对象 + OpenAIClientBuilder openAIClientBuilder = new OpenAIClientBuilder() + .endpoint(url).credential(new KeyCredential(apiKey)); // 获取 AzureOpenAiChatProperties 对象 AzureOpenAiEmbeddingProperties embeddingProperties = SpringUtil.getBean(AzureOpenAiEmbeddingProperties.class); - return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClient, embeddingProperties, - null, null); + return azureOpenAiAutoConfiguration.azureOpenAiEmbeddingModel(openAIClientBuilder, embeddingProperties, + getObservationRegistry(), getEmbeddingModelObservationConvention()); } // ========== 各种创建 VectorStore 的方法 ========== @@ -657,10 +688,11 @@ public class AiModelFactoryImpl implements AiModelFactory { RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort()); // 创建 RedisVectorStoreProperties 对象 + // TODO @芋艿:index-name 可能影响索引名; RedisVectorStoreAutoConfiguration configuration = new RedisVectorStoreAutoConfiguration(); RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class); RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel) - .indexName(properties.getIndex()).prefix(properties.getPrefix()) + .indexName(properties.getIndexName()).prefix(properties.getPrefix()) .initializeSchema(properties.isInitializeSchema()) .metadataFields(convertList(metadataFields.entrySet(), entry -> { String fieldName = entry.getKey(); @@ -730,10 +762,12 @@ public class AiModelFactoryImpl implements AiModelFactory { private static ObjectProvider getCustomObservationConvention() { return new ObjectProvider<>() { + @Override public VectorStoreObservationConvention getObject() throws BeansException { return new DefaultVectorStoreObservationConvention(); } + }; } @@ -745,8 +779,15 @@ public class AiModelFactoryImpl implements AiModelFactory { return SpringUtil.getBean(ToolCallingManager.class); } - private static FunctionCallbackResolver getFunctionCallbackResolver() { - return SpringUtil.getBean(FunctionCallbackResolver.class); + private static ObjectProvider getEmbeddingModelObservationConvention() { + return new ObjectProvider<>() { + + @Override + public EmbeddingModelObservationConvention getObject() throws BeansException { + return SpringUtil.getBean(EmbeddingModelObservationConvention.class); + } + + }; } } diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/AzureOpenAIChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/AzureOpenAIChatModelTests.java index 5c924a5823..69776d8e68 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/AzureOpenAIChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/AzureOpenAIChatModelTests.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; import com.azure.ai.openai.OpenAIClientBuilder; import com.azure.core.credential.AzureKeyCredential; -import com.azure.core.util.ClientOptions; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.ai.azure.openai.AzureOpenAiChatModel; @@ -17,7 +16,7 @@ import reactor.core.publisher.Flux; import java.util.ArrayList; import java.util.List; -import static org.springframework.ai.autoconfigure.azure.openai.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME; +import static org.springframework.ai.model.azure.openai.autoconfigure.AzureOpenAiChatProperties.DEFAULT_DEPLOYMENT_NAME; /** * {@link AzureOpenAiChatModel} 集成测试 @@ -29,10 +28,13 @@ public class AzureOpenAIChatModelTests { // TODO @芋艿:晚点在调整 private final OpenAIClientBuilder openAiApi = new OpenAIClientBuilder() .endpoint("https://eastusprejade.openai.azure.com") - .credential(new AzureKeyCredential("xxx")) - .clientOptions((new ClientOptions()).setApplicationId("spring-ai")); - private final AzureOpenAiChatModel chatModel = new AzureOpenAiChatModel(openAiApi, - AzureOpenAiChatOptions.builder().deploymentName(DEFAULT_DEPLOYMENT_NAME).build()); + .credential(new AzureKeyCredential("xxx")); + private final AzureOpenAiChatModel chatModel = AzureOpenAiChatModel.builder() + .openAIClientBuilder(openAiApi) + .defaultOptions(AzureOpenAiChatOptions.builder() + .deploymentName(DEFAULT_DEPLOYMENT_NAME) + .build()) + .build(); @Test @Disabled diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/BaiChuanChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/BaiChuanChatModelTests.java index d1cc381fb9..06b0b25653 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/BaiChuanChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/BaiChuanChatModelTests.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; import cn.iocoder.yudao.module.ai.framework.ai.core.model.baichuan.BaiChuanChatModel; -import cn.iocoder.yudao.module.ai.framework.ai.core.model.deepseek.DeepSeekChatModel; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.ai.chat.messages.Message; @@ -35,7 +34,7 @@ public class BaiChuanChatModelTests { .build()) .build(); - private final DeepSeekChatModel chatModel = new DeepSeekChatModel(openAiChatModel); + private final BaiChuanChatModel chatModel = new BaiChuanChatModel(openAiChatModel); @Test @Disabled diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/MoonshotChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/MoonshotChatModelTests.java index 7de7fd709c..992334b4d9 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/MoonshotChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/MoonshotChatModelTests.java @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.springaicommunity.moonshot.MoonshotChatModel; +import org.springaicommunity.moonshot.MoonshotChatOptions; +import org.springaicommunity.moonshot.api.MoonshotApi; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.SystemMessage; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.moonshot.MoonshotChatModel; -import org.springframework.ai.moonshot.MoonshotChatOptions; -import org.springframework.ai.moonshot.api.MoonshotApi; import reactor.core.publisher.Flux; import java.util.ArrayList; @@ -22,11 +22,15 @@ import java.util.List; */ public class MoonshotChatModelTests { - private final MoonshotChatModel chatModel = new MoonshotChatModel( - new MoonshotApi("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA"), // 密钥 - MoonshotChatOptions.builder() - .model("moonshot-v1-8k") // 模型 - .build()); + private final MoonshotChatModel chatModel = MoonshotChatModel.builder() + .moonshotApi(MoonshotApi.builder() + .apiKey("sk-aHYYV1SARscItye5QQRRNbXij4fy65Ee7pNZlC9gsSQnUKXA") // 密钥 + .build()) + .defaultOptions(MoonshotChatOptions.builder() + .model("kimi-k2-0711-preview") // 模型 + .build()) + .build(); + @Test @Disabled public void testCall() { diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/StabilityAiImageModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/StabilityAiImageModelTests.java index b58e6df00e..8cf556d9f8 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/StabilityAiImageModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/StabilityAiImageModelTests.java @@ -31,8 +31,8 @@ public class StabilityAiImageModelTests { public void testCall() { // 准备参数 ImageOptions options = OpenAiImageOptions.builder() - .withModel("stable-diffusion-v1-6") - .withHeight(320).withWidth(320) + .model("stable-diffusion-v1-6") + .height(320).width(320) .build(); ImagePrompt prompt = new ImagePrompt("great wall", options); diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 37b783d57d..b9658e9746 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -188,13 +188,14 @@ spring: api-key: xxxx moonshot: # 月之暗灭(KIMI) api-key: sk-abc + deepseek: # DeepSeek + api-key: sk-e94db327cc7d457d99a8de8810fc6b12 + chat: + options: + model: deepseek-chat yudao: ai: - deep-seek: # DeepSeek - enable: true - api-key: sk-e94db327cc7d457d99a8de8810fc6b12 - model: deepseek-chat doubao: # 字节豆包 enable: true api-key: 5c1b5747-26d2-4ebd-a4e0-dd0e8d8b4272 From 39ecf5ebe5aa8489a7ec44fd9bf31226c2f6887d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 22:42:56 +0800 Subject: [PATCH 31/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90AI=20=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E3=80=91=E6=96=87=E5=BF=83=E4=B8=80=E8=A8=80?= =?UTF-8?q?=E5=AD=98=E5=9C=A8=20springai=20=E6=8E=A5=E5=85=A5=E9=97=AE?= =?UTF-8?q?=E9=A2=98=EF=BC=8C=E6=97=A0=E6=B3=95=E4=BD=BF=E7=94=A8=20https:?= =?UTF-8?q?//github.com/spring-ai-community/qianfan/issues/6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/ai/core/AiModelFactoryImpl.java | 16 ++-- .../core/model/chat/LlamaChatModelTests.java | 90 ++++++++----------- .../core/model/chat/OllamaChatModelTests.java | 4 +- .../core/model/chat/YiYanChatModelTests.java | 10 +-- .../core/model/image/QianFanImageTests.java | 6 +- 5 files changed, 59 insertions(+), 67 deletions(-) diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java index 2aeecab917..759c0a038f 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java @@ -357,7 +357,7 @@ public class AiModelFactoryImpl implements AiModelFactory { * 可参考 {@link QianFanChatAutoConfiguration} 的 qianFanChatModel 方法 */ private static QianFanChatModel buildYiYanChatModel(String key) { - // TODO @芋艿:未测试 + // TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6 List keys = StrUtil.split(key, '|'); Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); String appKey = keys.get(0); @@ -370,7 +370,7 @@ public class AiModelFactoryImpl implements AiModelFactory { * 可参考 {@link QianFanEmbeddingAutoConfiguration} 的 qianFanImageModel 方法 */ private QianFanImageModel buildQianFanImageModel(String key) { - // TODO @芋艿:未测试 + // TODO spring ai qianfan 有 bug,无法使用 https://github.com/spring-ai-community/qianfan/issues/6 List keys = StrUtil.split(key, '|'); Assert.equals(keys.size(), 2, "YiYanChatClient 的密钥需要 (appKey|secretKey) 格式"); String appKey = keys.get(0); @@ -525,7 +525,6 @@ public class AiModelFactoryImpl implements AiModelFactory { * 创建 SiliconFlowImageModel 对象 */ private SiliconFlowImageModel buildSiliconFlowImageModel(String apiToken, String url) { - // TODO @芋艿:未测试 url = StrUtil.blankToDefault(url, SiliconFlowApiConstants.DEFAULT_BASE_URL); SiliconFlowImageApi openAiApi = new SiliconFlowImageApi(url, apiToken); return new SiliconFlowImageModel(openAiApi); @@ -535,9 +534,11 @@ public class AiModelFactoryImpl implements AiModelFactory { * 可参考 {@link OllamaChatAutoConfiguration} 的 ollamaChatModel 方法 */ private static OllamaChatModel buildOllamaChatModel(String url) { - // TODO @芋艿:未测试 OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); - return OllamaChatModel.builder().ollamaApi(ollamaApi).toolCallingManager(getToolCallingManager()).build(); + return OllamaChatModel.builder() + .ollamaApi(ollamaApi) + .toolCallingManager(getToolCallingManager()) + .build(); } /** @@ -596,7 +597,10 @@ public class AiModelFactoryImpl implements AiModelFactory { private OllamaEmbeddingModel buildOllamaEmbeddingModel(String url, String model) { OllamaApi ollamaApi = OllamaApi.builder().baseUrl(url).build(); OllamaOptions ollamaOptions = OllamaOptions.builder().model(model).build(); - return OllamaEmbeddingModel.builder().ollamaApi(ollamaApi).defaultOptions(ollamaOptions).build(); + return OllamaEmbeddingModel.builder() + .ollamaApi(ollamaApi) + .defaultOptions(ollamaOptions) + .build(); } /** diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/LlamaChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/LlamaChatModelTests.java index 153342d44c..69e2c1daaa 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/LlamaChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/LlamaChatModelTests.java @@ -1,20 +1,6 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.ai.chat.messages.Message; -import org.springframework.ai.chat.messages.SystemMessage; -import org.springframework.ai.chat.messages.UserMessage; -import org.springframework.ai.chat.model.ChatResponse; -import org.springframework.ai.chat.prompt.Prompt; import org.springframework.ai.ollama.OllamaChatModel; -import org.springframework.ai.ollama.api.OllamaApi; -import org.springframework.ai.ollama.api.OllamaModel; -import org.springframework.ai.ollama.api.OllamaOptions; -import reactor.core.publisher.Flux; - -import java.util.ArrayList; -import java.util.List; /** * {@link OllamaChatModel} 集成测试 @@ -23,43 +9,43 @@ import java.util.List; */ public class LlamaChatModelTests { - private final OllamaChatModel chatModel = OllamaChatModel.builder() - .ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址 - .defaultOptions(OllamaOptions.builder() - .model(OllamaModel.LLAMA3.getName()) // 模型 - .build()) - .build(); - - @Test - @Disabled - public void testCall() { - // 准备参数 - List messages = new ArrayList<>(); - messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); - messages.add(new UserMessage("1 + 1 = ?")); - - // 调用 - ChatResponse response = chatModel.call(new Prompt(messages)); - // 打印结果 - System.out.println(response); - System.out.println(response.getResult().getOutput()); - } - - @Test - @Disabled - public void testStream() { - // 准备参数 - List messages = new ArrayList<>(); - messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); - messages.add(new UserMessage("1 + 1 = ?")); - - // 调用 - Flux flux = chatModel.stream(new Prompt(messages)); - // 打印结果 - flux.doOnNext(response -> { -// System.out.println(response); - System.out.println(response.getResult().getOutput()); - }).then().block(); - } +// private final OllamaChatModel chatModel = OllamaChatModel.builder() +// .ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址 +// .defaultOptions(OllamaOptions.builder() +// .model(OllamaModel.LLAMA3.getName()) // 模型 +// .build()) +// .build(); +// +// @Test +// @Disabled +// public void testCall() { +// // 准备参数 +// List messages = new ArrayList<>(); +// messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); +// messages.add(new UserMessage("1 + 1 = ?")); +// +// // 调用 +// ChatResponse response = chatModel.call(new Prompt(messages)); +// // 打印结果 +// System.out.println(response); +// System.out.println(response.getResult().getOutput()); +// } +// +// @Test +// @Disabled +// public void testStream() { +// // 准备参数 +// List messages = new ArrayList<>(); +// messages.add(new SystemMessage("你是一个优质的文言文作者,用文言文描述着各城市的人文风景。")); +// messages.add(new UserMessage("1 + 1 = ?")); +// +// // 调用 +// Flux flux = chatModel.stream(new Prompt(messages)); +// // 打印结果 +// flux.doOnNext(response -> { +//// System.out.println(response); +// System.out.println(response.getResult().getOutput()); +// }).then().block(); +// } } diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OllamaChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OllamaChatModelTests.java index f86e67a667..d2bf68812b 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OllamaChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/OllamaChatModelTests.java @@ -23,7 +23,9 @@ import java.util.List; public class OllamaChatModelTests { private final OllamaChatModel chatModel = OllamaChatModel.builder() - .ollamaApi(new OllamaApi("http://127.0.0.1:11434")) // Ollama 服务地址 + .ollamaApi(OllamaApi.builder() + .baseUrl("http://127.0.0.1:11434") // Ollama 服务地址 + .build()) .defaultOptions(OllamaOptions.builder() // .model("qwen") // 模型(https://ollama.com/library/qwen) .model("deepseek-r1") // 模型(https://ollama.com/library/deepseek-r1) diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/YiYanChatModelTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/YiYanChatModelTests.java index ab6f642437..cb7be2a296 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/YiYanChatModelTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/chat/YiYanChatModelTests.java @@ -2,13 +2,13 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.chat; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.springaicommunity.qianfan.QianFanChatModel; +import org.springaicommunity.qianfan.QianFanChatOptions; +import org.springaicommunity.qianfan.api.QianFanApi; import org.springframework.ai.chat.messages.Message; import org.springframework.ai.chat.messages.UserMessage; import org.springframework.ai.chat.model.ChatResponse; import org.springframework.ai.chat.prompt.Prompt; -import org.springframework.ai.qianfan.QianFanChatModel; -import org.springframework.ai.qianfan.QianFanChatOptions; -import org.springframework.ai.qianfan.api.QianFanApi; import reactor.core.publisher.Flux; import java.util.ArrayList; @@ -23,9 +23,9 @@ import java.util.List; public class YiYanChatModelTests { private final QianFanChatModel chatModel = new QianFanChatModel( - new QianFanApi("qS8k8dYr2nXunagK4SSU8Xjj", "pHGbx51ql2f0hOyabQvSZezahVC3hh3e"), // 密钥 + new QianFanApi("DGnyzREuaY7av7c38bOM9Ji2", "9aR8myflEOPDrEeLhoXv0FdqANOAyIZW"), // 密钥 QianFanChatOptions.builder() - .model(QianFanApi.ChatModel.ERNIE_4_0_8K_Preview.getValue()) + .model("ERNIE-4.5-8K-Preview") .build() ); diff --git a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/QianFanImageTests.java b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/QianFanImageTests.java index 8f44ab9ad1..156360f255 100644 --- a/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/QianFanImageTests.java +++ b/yudao-module-ai/src/test/java/cn/iocoder/yudao/module/ai/framework/ai/core/model/image/QianFanImageTests.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.ai.framework.ai.core.model.image; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.springaicommunity.qianfan.QianFanImageModel; +import org.springaicommunity.qianfan.QianFanImageOptions; +import org.springaicommunity.qianfan.api.QianFanImageApi; import org.springframework.ai.image.ImagePrompt; import org.springframework.ai.image.ImageResponse; -import org.springframework.ai.qianfan.QianFanImageModel; -import org.springframework.ai.qianfan.QianFanImageOptions; -import org.springframework.ai.qianfan.api.QianFanImageApi; import static cn.iocoder.yudao.module.ai.framework.ai.core.model.image.StabilityAiImageModelTests.viewImage; From ea5b12f21e2c0eb3e9e833b12e1af3bfad0681f1 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 14 Jul 2025 22:44:50 +0800 Subject: [PATCH 32/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90AI=20=E5=A4=A7?= =?UTF-8?q?=E6=A8=A1=E5=9E=8B=E3=80=91RedisVectorStore=20=E6=94=AF?= =?UTF-8?q?=E6=8C=81=20username=E3=80=81password?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/ai/framework/ai/core/AiModelFactoryImpl.java | 5 ++--- yudao-server/src/main/resources/application.yaml | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java index 759c0a038f..f7b42e30ae 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/framework/ai/core/AiModelFactoryImpl.java @@ -690,10 +690,9 @@ public class AiModelFactoryImpl implements AiModelFactory { Map> metadataFields) { // 创建 JedisPooled 对象 RedisProperties redisProperties = SpringUtils.getBean(RedisProperties.class); - JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort()); + JedisPooled jedisPooled = new JedisPooled(redisProperties.getHost(), redisProperties.getPort(), + redisProperties.getUsername(), redisProperties.getPassword()); // 创建 RedisVectorStoreProperties 对象 - // TODO @芋艿:index-name 可能影响索引名; - RedisVectorStoreAutoConfiguration configuration = new RedisVectorStoreAutoConfiguration(); RedisVectorStoreProperties properties = SpringUtil.getBean(RedisVectorStoreProperties.class); RedisVectorStore redisVectorStore = RedisVectorStore.builder(jedisPooled, embeddingModel) .indexName(properties.getIndexName()).prefix(properties.getPrefix()) diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index b9658e9746..12a4abf896 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -150,7 +150,7 @@ spring: vectorstore: # 向量存储 redis: initialize-schema: true - index: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行 + index-name: knowledge_index # Redis 中向量索引的名称:用于存储和检索向量数据的索引标识符,所有相关的向量搜索操作都会基于这个索引进行 prefix: "knowledge_segment:" # Redis 中存储向量数据的键名前缀:这个前缀会添加到每个存储在 Redis 中的向量数据键名前,每个 document 都是一个 hash 结构 qdrant: initialize-schema: true From a10e7aedaa41a0618c6fa67e811abc045e4318be Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 16 Jul 2025 00:02:57 +0800 Subject: [PATCH 33/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90Pay=20=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E3=80=91=E5=8E=BB=E9=99=A4=2054=20=E5=BC=BA=E5=88=B6?= =?UTF-8?q?=20id=20=E8=BD=AC=E8=B4=A6=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/pay/service/transfer/PayTransferServiceImpl.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java index dbd12c7986..8f123f8102 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java @@ -264,9 +264,6 @@ public class PayTransferServiceImpl implements PayTransferService { } int count = 0; for (PayTransferDO transfer : list) { - if (!transfer.getId().equals(54L)) { - continue; - } count += syncTransfer(transfer) ? 1 : 0; } return count; From aef47bcf70e423c486fe00f4f98305d01116d773 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 16 Jul 2025 00:11:27 +0800 Subject: [PATCH 34/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90INFRA=20=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E8=AE=BE=E6=96=BD=E3=80=91=E4=BB=A3=E7=A0=81=E7=94=9F?= =?UTF-8?q?=E6=88=90=E6=A8=A1=E7=89=88=EF=BC=8Cclean=20=E7=BC=BA=E5=B0=91?= =?UTF-8?q?=E4=BA=86=20;=20=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/codegen/java/service/serviceImpl.vm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm b/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm index ee9fc49f97..42afdf90ae 100644 --- a/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm +++ b/yudao-module-infra/src/main/resources/codegen/java/service/serviceImpl.vm @@ -316,7 +316,7 @@ public class ${table.className}ServiceImpl implements ${table.className}Service } // 插入 #end - ${subClassNameVar}.clean() // 清理掉创建、更新时间等相关属性值 + ${subClassNameVar}.clean(); // 清理掉创建、更新时间等相关属性值 ${subClassNameVars.get($index)}Mapper.insert(${subClassNameVar}); return ${subClassNameVar}.getId(); } From 1978603bd96d9cacfa52c2ccf749dc29f090d2b0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 19 Jul 2025 15:31:13 +0800 Subject: [PATCH 35/81] =?UTF-8?q?(=E3=80=83'=E2=96=BD'=E3=80=83)=20v2.6.1?= =?UTF-8?q?=20=E5=8F=91=E5=B8=83=EF=BC=9AVben5=20+=20antd=20=E7=AE=A1?= =?UTF-8?q?=E7=90=86=E5=90=8E=E5=8F=B0=E6=94=AF=E6=8C=81=20BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=81CRM=20=E5=AE=A2=E6=88=B7=E7=AE=A1?= =?UTF-8?q?=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- yudao-dependencies/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index b271f1d4b9..48a6f0589d 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.6.0-SNAPSHOT + 2.6.1-SNAPSHOT 17 ${java.version} diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index bf6175cdd3..27ad06fe5d 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.6.0-SNAPSHOT + 2.6.1-SNAPSHOT 1.6.0 3.4.5 From 4a111d2cb57f7ee626aaac29315b80a9db33f6c1 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Sat, 19 Jul 2025 16:56:23 +0800 Subject: [PATCH 36/81] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3use-vxe-grid?= =?UTF-8?q?=E4=B8=AD=E7=9A=84=E4=BB=A3=E7=90=86=E9=85=8D=E7=BD=AE=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm | 2 +- .../vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm | 2 +- .../resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm | 2 +- .../vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm index fdac956ff7..635e12ac24 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm @@ -180,7 +180,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ #end }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>, diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm index 97404b0211..4001ed3992 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm @@ -131,7 +131,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ enabled: true, }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, #else diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm index 3bb2b6a4a1..f9232d6b50 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm @@ -174,7 +174,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ #end }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>, diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm index 4dd5a6f1b4..5afb9c7a0d 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm @@ -125,7 +125,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ enabled: true, }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, #else From bfcc1987cb1e8675f7e8d540c55a5d5a5be09c64 Mon Sep 17 00:00:00 2001 From: xingyu4j Date: Sat, 19 Jul 2025 16:56:23 +0800 Subject: [PATCH 37/81] =?UTF-8?q?fix:=20=E3=80=90BPM=20=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81=E3=80=91=E9=81=BF=E5=85=8D=E5=9C=A8=20BpmHttpRequestU?= =?UTF-8?q?tils=20=E4=B8=AD=E9=87=8D=E5=A4=8D=E6=B7=BB=E5=8A=A0=20processI?= =?UTF-8?q?nstanceId=20=E5=8F=82=E6=95=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/framework/flowable/core/util/BpmHttpRequestUtils.java | 4 +++- .../codegen/vue3_vben5_antd/schema/views/index.vue.vm | 2 +- .../vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm | 2 +- .../codegen/vue3_vben5_ele/schema/views/index.vue.vm | 2 +- .../vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java index 2503c0fff9..014b5e3f0d 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java @@ -108,7 +108,9 @@ public class BpmHttpRequestUtils { Map processVariables = processInstance.getProcessVariables(); MultiValueMap body = new LinkedMultiValueMap<>(); addHttpRequestParam(body, bodySettings, processVariables); - body.add("processInstanceId", processInstance.getId()); + if (!body.containsKey("processInstanceId")) { // 避免重复添加 + body.add("processInstanceId", processInstance.getId()); + } return body; } diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm index fdac956ff7..635e12ac24 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/index.vue.vm @@ -180,7 +180,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ #end }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>, diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm index 97404b0211..4001ed3992 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_antd/schema/views/modules/list_sub_erp.vue.vm @@ -131,7 +131,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ enabled: true, }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, #else diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm index 3bb2b6a4a1..f9232d6b50 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/index.vue.vm @@ -174,7 +174,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ #end }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, } as VxeTableGridOptions<${simpleClassName}Api.${simpleClassName}>, diff --git a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm index 4dd5a6f1b4..5afb9c7a0d 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3_vben5_ele/schema/views/modules/list_sub_erp.vue.vm @@ -125,7 +125,7 @@ const [Grid, gridApi] = useVbenVxeGrid({ enabled: true, }, toolbarConfig: { - refresh: { code: 'query' }, + refresh: true, search: true, }, #else From dc7763ef0b126dc561b2bdbf2d9f60c2b671f16f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 20 Jul 2025 16:45:16 +0800 Subject: [PATCH 38/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91BpmTaskCandidateExpressionStrategy?= =?UTF-8?q?=20=E5=9C=A8=20PropertyNotFoundException=20=E4=B8=8D=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=E6=97=B6=EF=BC=8C=E9=A2=91=E7=B9=81=E6=89=93=20warn?= =?UTF-8?q?=20=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../expression/BpmTaskAssignLeaderExpression.java | 1 + .../expression/BpmTaskAssignStartUserExpression.java | 1 + .../other/BpmTaskCandidateExpressionStrategy.java | 11 +++++++---- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java index 7c1950f8ce..e9180c8695 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignLeaderExpression.java @@ -24,6 +24,7 @@ import static java.util.Collections.emptySet; * @author 芋道源码 */ @Component +@Deprecated // 仅仅是表达式的示例,建议使用 BpmTaskCandidateStartUserDeptLeaderStrategy 替代 public class BpmTaskAssignLeaderExpression { @Resource diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java index ac243c0f43..f22dc508cb 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/expression/BpmTaskAssignStartUserExpression.java @@ -16,6 +16,7 @@ import java.util.Set; * @author 芋道源码 */ @Component +@Deprecated // 仅仅是表达式的示例,建议使用 BpmTaskCandidateStartUserStrategy 替代 public class BpmTaskAssignStartUserExpression { @Resource diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java index 64ca9e8538..86c137a4b7 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java @@ -8,6 +8,7 @@ import com.google.common.collect.Sets; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.model.BpmnModel; import org.flowable.common.engine.api.FlowableException; +import org.flowable.common.engine.impl.javax.el.PropertyNotFoundException; import org.flowable.engine.delegate.DelegateExecution; import org.springframework.stereotype.Component; @@ -48,10 +49,12 @@ public class BpmTaskCandidateExpressionStrategy implements BpmTaskCandidateStrat Object result = FlowableUtils.getExpressionValue(variables, param); return CollectionUtils.toLinkedHashSet(Long.class, result); } catch (FlowableException ex) { - // 预测未运行的节点时候,表达式如果包含 execution 或者不存在的流程变量会抛异常, - log.warn("[calculateUsersByActivity][表达式({}) 变量({}) 解析报错", param, variables, ex); - // 不能预测候选人,返回空列表, 避免流程无法进行 - return Sets.newHashSet(); + // 预测未运行的节点时候,表达式如果包含 execution 或者不存在的流程变量会抛异常,此时忽略该异常!相当于说,不做流程预测!!! + if (ex.getCause() != null && ex.getCause() instanceof PropertyNotFoundException) { + return Sets.newHashSet(); + } + log.error("[calculateUsersByActivity][表达式({}) 变量({}) 解析报错", param, variables, ex); + throw ex; } } From c645813725420517bcb92c6fee82a09e90e7ebc0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 20 Jul 2025 17:47:50 +0800 Subject: [PATCH 39/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E5=BE=85=E5=8A=9E=E4=BB=BB=E5=8A=A1?= =?UTF-8?q?=E3=80=81=E5=B7=B2=E5=8A=9E=E4=BB=BB=E5=8A=A1=EF=BC=8C=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E6=97=B6=E9=97=B4=E8=8C=83=E5=9B=B4=E6=9F=A5=E8=AF=A2?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E4=BC=9A=E6=8B=BC=E6=8E=A5=20OR=20=E7=9A=84?= =?UTF-8?q?=E6=83=85=E5=86=B5=EF=BC=88=E9=9D=9E=E5=AE=8C=E7=BE=8E=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E6=96=B9=E6=A1=88=EF=BC=89=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/task/BpmTaskServiceImpl.java | 28 +++++++++++++------ 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 1164f4da72..1f7e699032 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -230,10 +230,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { if (StrUtil.isNotBlank(pageVO.getName())) { taskQuery.taskNameLike("%" + pageVO.getName() + "%"); } - if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { - taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); - taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1])); - } +// if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { +// taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); +// taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1])); +// } // 执行查询 long count = taskQuery.count(); if (count == 0) { @@ -244,6 +244,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { // 特殊:强制移除自动完成的“发起人”节点 // 补充说明:由于 taskQuery 无法方面的过滤,所以暂时通过内存过滤 tasks.removeIf(task -> task.getTaskDefinitionKey().equals(START_USER_NODE_ID)); + // TODO @芋艿:https://t.zsxq.com/MNzqp 【flowable bug】:taskCreatedAfter、taskCreatedBefore 拼接的是 OR + if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { + tasks.removeIf(task -> task.getCreateTime() == null + || task.getCreateTime().before(DateUtils.of(pageVO.getCreateTime()[0])) + || task.getCreateTime().after(DateUtils.of(pageVO.getCreateTime()[1]))); + } return new PageResult<>(tasks, count); } @@ -259,16 +265,22 @@ public class BpmTaskServiceImpl implements BpmTaskService { if (StrUtil.isNotEmpty(pageVO.getCategory())) { taskQuery.taskCategory(pageVO.getCategory()); } - if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { - taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); - taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1])); - } +// if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { +// taskQuery.taskCreatedAfter(DateUtils.of(pageVO.getCreateTime()[0])); +// taskQuery.taskCreatedBefore(DateUtils.of(pageVO.getCreateTime()[1])); +// } // 执行查询 long count = taskQuery.count(); if (count == 0) { return PageResult.empty(); } List tasks = taskQuery.listPage(PageUtils.getStart(pageVO), pageVO.getPageSize()); + // TODO @芋艿:https://t.zsxq.com/MNzqp 【flowable bug】:taskCreatedAfter、taskCreatedBefore 拼接的是 OR + if (ArrayUtil.isNotEmpty(pageVO.getCreateTime())) { + tasks.removeIf(task -> task.getCreateTime() == null + || task.getCreateTime().before(DateUtils.of(pageVO.getCreateTime()[0])) + || task.getCreateTime().after(DateUtils.of(pageVO.getCreateTime()[1]))); + } return new PageResult<>(tasks, count); } From 14d8c2bb404caa337565a80b242c736822f3278a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 20 Jul 2025 20:02:48 +0800 Subject: [PATCH 40/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91buildConditionExpression=20=E5=9C=A8?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E9=A2=84=E6=B5=8B=E6=97=B6=EF=BC=8C=E5=9B=A0?= =?UTF-8?q?=E4=B8=BA=E5=8F=98=E9=87=8F=E4=B8=8D=E5=AD=98=E5=9C=A8=EF=BC=8C?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=20Unknow=20property=20=E5=BC=82=E5=B8=B8?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/util/SimpleModelUtils.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index bd427e32f2..c9f3ff6fcb 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -4,7 +4,6 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.*; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO.ConditionGroups; @@ -17,13 +16,14 @@ import cn.iocoder.yudao.module.bpm.service.task.listener.BpmCallActivityListener import cn.iocoder.yudao.module.bpm.service.task.listener.BpmUserTaskListener; import org.flowable.bpmn.BpmnAutoLayout; import org.flowable.bpmn.constants.BpmnXMLConstants; -import org.flowable.bpmn.model.Process; import org.flowable.bpmn.model.*; +import org.flowable.bpmn.model.Process; import org.flowable.engine.delegate.ExecutionListener; import org.flowable.engine.delegate.TaskListener; import java.util.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils.*; import static java.util.Arrays.asList; @@ -684,15 +684,18 @@ public class SimpleModelUtils { if (conditionGroups == null || CollUtil.isEmpty(conditionGroups.getConditions())) { return null; } - List strConditionGroups = CollectionUtils.convertList(conditionGroups.getConditions(), item -> { + List strConditionGroups = convertList(conditionGroups.getConditions(), item -> { if (CollUtil.isEmpty(item.getRules())) { return ""; } // 构造规则表达式 - List list = CollectionUtils.convertList(item.getRules(), (rule) -> { + List list = convertList(item.getRules(), (rule) -> { String rightSide = NumberUtil.isNumber(rule.getRightSide()) ? rule.getRightSide() : "\"" + rule.getRightSide() + "\""; // 如果非数值类型加引号 - return String.format(" %s %s var:convertByType(%s,%s)", rule.getLeftSide(), rule.getOpCode(), rule.getLeftSide(), rightSide); + return String.format(" vars:getOrDefault(%s, null) %s var:convertByType(%s,%s) ", + rule.getLeftSide(), // 左侧:读取变量 + rule.getOpCode(), // 中间:操作符,比较 + rule.getLeftSide(), rightSide); // 右侧:转换变量,VariableConvertByTypeExpressionFunction }); // 构造条件组的表达式 Boolean and = item.getAnd(); From 51859afa9ac1ffb3b7b28af37c6b904ac54b3a62 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 20 Jul 2025 20:26:23 +0800 Subject: [PATCH 41/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91SIMPLE=20=E5=BB=B6=E8=BF=9F=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E6=97=B6=EF=BC=8C=E7=A7=9F=E6=88=B7=E4=B8=8A=E4=B8=8B?= =?UTF-8?q?=E6=96=87=E4=B8=A2=E5=A4=B1=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/listener/BpmTaskEventListener.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java index e50df0bcf0..9aa3889e59 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventTypeEnum; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.BpmnModelUtils; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import com.google.common.collect.ImmutableSet; @@ -58,17 +59,20 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { @Override protected void taskCreated(FlowableEngineEntityEvent event) { - taskService.processTaskCreated((Task) event.getEntity()); + Task entity = (Task) event.getEntity(); + FlowableUtils.execute(entity.getTenantId(), () -> taskService.processTaskCreated(entity)); } @Override protected void taskAssigned(FlowableEngineEntityEvent event) { - taskService.processTaskAssigned((Task) event.getEntity()); + Task entity = (Task) event.getEntity(); + FlowableUtils.execute(entity.getTenantId(), () -> taskService.processTaskAssigned(entity)); } @Override protected void taskCompleted(FlowableEngineEntityEvent event) { - taskService.processTaskCompleted((Task) event.getEntity()); + Task entity = (Task) event.getEntity(); + FlowableUtils.execute(entity.getTenantId(), () -> taskService.processTaskCompleted(entity)); } @Override From d36c0dce7cf24514dd7484f7b9e1a05afd5e2ff8 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 20 Jul 2025 23:43:46 +0800 Subject: [PATCH 42/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91BPMN=20=E5=9C=BA=E6=99=AF=E4=B8=8B?= =?UTF-8?q?=EF=BC=8C=E5=A4=9A=E6=AC=A1=E6=8F=90=E9=86=92=E5=8F=AF=E8=83=BD?= =?UTF-8?q?=E4=B8=A2=E5=A4=B1=20elementId=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/listener/BpmTaskEventListener.java | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java index 9aa3889e59..6e2e48cbec 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmTaskEventListener.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONObject; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.module.bpm.enums.definition.BpmBoundaryEventTypeEnum; import cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants; @@ -98,6 +99,23 @@ public class BpmTaskEventListener extends AbstractFlowableEngineEventListener { String processDefinitionId = event.getProcessDefinitionId(); BpmnModel bpmnModel = modelService.getBpmnModelByDefinitionId(processDefinitionId); Job entity = (Job) event.getEntity(); + // 特殊 from https://t.zsxq.com/h6oWr :当 elementId 为空时,尝试从 JobHandlerConfiguration 中解析 JSON 获取 + String elementId = entity.getElementId(); + if (elementId == null && entity.getJobHandlerConfiguration() != null) { + try { + String handlerConfig = entity.getJobHandlerConfiguration(); + if (handlerConfig.startsWith("{") && handlerConfig.contains("activityId")) { + elementId = new JSONObject(handlerConfig).getStr("activityId"); + } + } catch (Exception e) { + log.error("[timerFired][解析 entity({}) 失败]", entity, e); + return; + } + } + if (elementId == null) { + log.error("[timerFired][解析 entity({}) elementId 为空,跳过处理]", entity); + return; + } FlowElement element = BpmnModelUtils.getFlowElementById(bpmnModel, entity.getElementId()); if (!(element instanceof BoundaryEvent)) { return; From 3aac40a51e6dcdd449e4ea5d0418ca837de5a2da Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 21 Jul 2025 16:17:17 +0800 Subject: [PATCH 43/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E6=B5=81=E7=A8=8B=E6=A8=A1=E5=9E=8B?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E5=88=A0=E9=99=A4=E6=97=B6=EF=BC=8C=E9=A2=9D?= =?UTF-8?q?=E5=A4=96=E6=A0=A1=E9=AA=8C=E6=98=AF=E5=90=A6=E8=A2=AB=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E6=A8=A1=E5=9E=8B=E6=89=80=E4=BD=BF=E7=94=A8=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/bpm/enums/ErrorCodeConstants.java | 1 + .../definition/BpmCategoryServiceImpl.java | 16 +++++++++++++--- .../bpm/service/definition/BpmModelService.java | 8 ++++++++ .../service/definition/BpmModelServiceImpl.java | 8 ++++++++ 4 files changed, 30 insertions(+), 3 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index d5d6fa77c4..4f7d7bf7ce 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -74,6 +74,7 @@ public interface ErrorCodeConstants { ErrorCode CATEGORY_NOT_EXISTS = new ErrorCode(1_009_012_000, "流程分类不存在"); ErrorCode CATEGORY_NAME_DUPLICATE = new ErrorCode(1_009_012_001, "流程分类名字【{}】重复"); ErrorCode CATEGORY_CODE_DUPLICATE = new ErrorCode(1_009_012_002, "流程分类编码【{}】重复"); + ErrorCode CATEGORY_DELETE_FAIL_MODEL_USED = new ErrorCode(1_009_012_003, "删除失败,流程分类【{}】已被流程模型使用,请先删除对应的流程模型"); // ========== BPM 流程监听器 1-009-013-000 ========== ErrorCode PROCESS_LISTENER_NOT_EXISTS = new ErrorCode(1_009_013_000, "流程监听器不存在"); diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryServiceImpl.java index 8a48da15a4..42d399acd5 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmCategoryServiceImpl.java @@ -34,6 +34,9 @@ public class BpmCategoryServiceImpl implements BpmCategoryService { @Resource private BpmCategoryMapper bpmCategoryMapper; + @Resource + private BpmModelService modelService; + @Override public Long createCategory(BpmCategorySaveReqVO createReqVO) { // 校验唯一 @@ -77,15 +80,22 @@ public class BpmCategoryServiceImpl implements BpmCategoryService { @Override public void deleteCategory(Long id) { // 校验存在 - validateCategoryExists(id); + BpmCategoryDO category = validateCategoryExists(id); + // 校验是否被流程模型使用 + Long count = modelService.getModelCountByCategory(category.getCode()); + if (count > 0) { + throw exception(CATEGORY_DELETE_FAIL_MODEL_USED, category.getName()); + } // 删除 bpmCategoryMapper.deleteById(id); } - private void validateCategoryExists(Long id) { - if (bpmCategoryMapper.selectById(id) == null) { + private BpmCategoryDO validateCategoryExists(Long id) { + BpmCategoryDO category = bpmCategoryMapper.selectById(id); + if (category == null) { throw exception(CATEGORY_NOT_EXISTS); } + return category; } @Override diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java index 5601bcda31..3273d24cbe 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java @@ -24,6 +24,14 @@ public interface BpmModelService { */ List getModelList(String name); + /** + * 根据分类编码获得流程模型数量 + * + * @param category 分类编码 + * @return 流程模型数量 + */ + Long getModelCountByCategory(String category); + /** * 创建流程模型 * diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index e8e90006f8..c23ea9ce8f 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -88,6 +88,14 @@ public class BpmModelServiceImpl implements BpmModelService { return modelQuery.list(); } + @Override + public Long getModelCountByCategory(String category) { + return repositoryService.createModelQuery() + .modelCategory(category) + .modelTenantId(FlowableUtils.getTenantId()) + .count(); + } + @Override @Transactional(rollbackFor = Exception.class) public String createModel(@Valid BpmModelSaveReqVO createReqVO) { From fb6771aad0425df1cd23245a6001929de046e23d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 21 Jul 2025 19:45:30 +0800 Subject: [PATCH 44/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90MALL=20=E5=95=86?= =?UTF-8?q?=E5=9F=8E=E3=80=91=E7=A7=92=E6=9D=80=E6=97=B6=E9=97=B4=E6=AE=B5?= =?UTF-8?q?=E7=9A=84=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/service/seckill/SeckillActivityServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java index dcc5596f25..3c84a172ab 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java @@ -303,7 +303,9 @@ public class SeckillActivityServiceImpl implements SeckillActivityService { throw exception(SECKILL_JOIN_ACTIVITY_TIME_ERROR); } SeckillConfigDO config = seckillConfigService.getCurrentSeckillConfig(); - if (config == null || !CollectionUtil.contains(activity.getConfigIds(), config.getId())) { + if (config == null + || !CollectionUtil.contains(activity.getConfigIds(), config.getId()) + || !LocalDateTimeUtils.isBetween(config.getStartTime(), config.getEndTime())) { throw exception(SECKILL_JOIN_ACTIVITY_TIME_ERROR); } // 1.3 超过单次购买限制 From 57add7b6e7939642ad3bd4240cbaf0c9af324ec6 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Mon, 21 Jul 2025 16:05:50 +0000 Subject: [PATCH 45/81] =?UTF-8?q?feat:=20=20sql/tools=20=E9=94=99=E8=AF=AF?= =?UTF-8?q?=E4=BF=A1=E6=81=AF=E8=BE=93=E5=87=BA=E5=88=B0=20stderr?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: dhb52 --- sql/tools/convertor.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sql/tools/convertor.py b/sql/tools/convertor.py index 7ab8ad1ef3..d286d3b238 100644 --- a/sql/tools/convertor.py +++ b/sql/tools/convertor.py @@ -17,6 +17,7 @@ uv run --with simple-ddl-parser convertor.py dm8 > ../dm/ruoyi-vue-pro-dm8.sql import argparse import pathlib import re +import sys import time from abc import ABC, abstractmethod from typing import Dict, Generator, Optional, Tuple, Union @@ -293,8 +294,10 @@ class Convertor(ABC): # 将parse失败的脚本打印出来 if error_scripts: + print("!!! 以下内容无法正常解析", file=sys.stderr) for script in error_scripts: - print(script) + # print to stderr + print(script, file=sys.stderr) class PostgreSQLConvertor(Convertor): From 7ba084bc4dfafeb0475ef04a4e1b9e7deef3abf6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 22 Jul 2025 12:26:08 +0800 Subject: [PATCH 46/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E5=AD=90=E6=B5=81=E7=A8=8B=E8=BF=94?= =?UTF-8?q?=E5=9B=9E=E7=9A=84=20processInstanceId=20=E4=B8=8D=E6=AD=A3?= =?UTF-8?q?=E7=A1=AE=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/task/vo/instance/BpmApprovalDetailRespVO.java | 2 +- .../bpm/service/task/BpmProcessInstanceServiceImpl.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java index 38c2bc1013..0a785b10f4 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmApprovalDetailRespVO.java @@ -73,7 +73,7 @@ public class BpmApprovalDetailRespVO { private List candidateUsers; // 只包含未生成 ApprovalTaskInfo 的用户列表 @Schema(description = "流程编号", example = "8761d8e0-0922-11f0-bd37-00ff1db677bf") - private String processInstanceId; // 当且仅当,该节点是子流程节点时,才会有值(CallActivity 的 processInstanceId 字段) + private String processInstanceId; // 当且仅当,该节点是子流程节点时,才会有值(CallActivity 的 calledProcessInstanceId 字段) } diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index a42a3ecd4b..d056e4dbd8 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -244,7 +244,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService if (historicProcessInstance == null) { throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); } - // 1.3 校验BpmnModel + // 1.3 校验 BpmnModel BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId()); if (bpmnModel == null) { return null; @@ -449,7 +449,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus) .setStartTime(DateUtils.of(activity.getStartTime())) .setEndTime(DateUtils.of(activity.getEndTime())) - .setProcessInstanceId(activity.getProcessInstanceId()); + .setProcessInstanceId(activity.getCalledProcessInstanceId()); approvalNodes.add(callActivity); } }); @@ -521,7 +521,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); } if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) { - activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId()); + activityNode.setProcessInstanceId(firstActivity.getCalledProcessInstanceId()); } return activityNode; }); From b766f8d820a13ec12a25f02485570b7e50a10df2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 22 Jul 2025 20:15:52 +0800 Subject: [PATCH 47/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E5=AD=90=E6=B5=81=E7=A8=8B=E6=94=AF?= =?UTF-8?q?=E6=8C=81=E6=B5=81=E7=A8=8B=20title=20=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E6=A0=87=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmProcessInstanceEventListener.java | 17 +- .../task/BpmProcessInstanceServiceImpl.java | 161 ++++++++++-------- 2 files changed, 104 insertions(+), 74 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java index ba2aaa6bcb..3deb545fa8 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.listener; +import cn.iocoder.yudao.module.bpm.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import com.google.common.collect.ImmutableSet; import jakarta.annotation.Resource; @@ -37,18 +38,26 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent @Override protected void processCreated(FlowableEngineEntityEvent event) { - processInstanceService.processProcessInstanceCreated((ProcessInstance)event.getEntity()); + ProcessInstance processInstance = (ProcessInstance) event.getEntity(); + FlowableUtils.execute(processInstance.getTenantId(), + () -> processInstanceService.processProcessInstanceCreated(processInstance)); } @Override protected void processCompleted(FlowableEngineEntityEvent event) { - processInstanceService.processProcessInstanceCompleted((ProcessInstance)event.getEntity()); + ProcessInstance processInstance = (ProcessInstance) event.getEntity(); + FlowableUtils.execute(processInstance.getTenantId(), + () -> processInstanceService.processProcessInstanceCompleted(processInstance)); } - @Override // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法 + @Override protected void processCancelled(FlowableCancelledEvent event) { + // 特殊情况:当跳转到 EndEvent 流程实例未结束, 会执行 deleteProcessInstance 方法 ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getProcessInstanceId()); - processInstanceService.processProcessInstanceCompleted(processInstance); + if (processInstance != null) { + FlowableUtils.execute(processInstance.getTenantId(), + () -> processInstanceService.processProcessInstanceCompleted(processInstance)); + } } } diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index d056e4dbd8..66fbaf79a3 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -4,10 +4,7 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ArrayUtil; -import cn.hutool.core.util.ObjUtil; -import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; +import cn.hutool.core.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -61,6 +58,8 @@ import org.flowable.task.api.history.HistoricTaskInstance; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import org.springframework.transaction.support.TransactionSynchronization; +import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.validation.annotation.Validated; import java.util.*; @@ -244,7 +243,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService if (historicProcessInstance == null) { throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); } - // 1.3 校验 BpmnModel + // 1.3 校验BpmnModel BpmnModel bpmnModel = processDefinitionService.getProcessDefinitionBpmnModel(task.getProcessDefinitionId()); if (bpmnModel == null) { return null; @@ -449,7 +448,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus) .setStartTime(DateUtils.of(activity.getStartTime())) .setEndTime(DateUtils.of(activity.getEndTime())) - .setProcessInstanceId(activity.getCalledProcessInstanceId()); + .setProcessInstanceId(activity.getProcessInstanceId()); approvalNodes.add(callActivity); } }); @@ -521,7 +520,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); } if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) { - activityNode.setProcessInstanceId(firstActivity.getCalledProcessInstanceId()); + activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId()); } return activityNode; }); @@ -771,17 +770,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService processInstanceBuilder.predefineProcessInstanceId(processIdRedisDAO.generate(processIdRule)); } // 3.2 流程名称 - BpmModelMetaInfoVO.TitleSetting titleSetting = processDefinitionInfo.getTitleSetting(); - if (titleSetting != null && Boolean.TRUE.equals(titleSetting.getEnable())) { - AdminUserRespDTO user = adminUserApi.getUser(userId); - Map cloneVariables = new HashMap<>(variables); - cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname()); - cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now()); - cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim()); - processInstanceBuilder.name(StrUtil.format(titleSetting.getTitle(), cloneVariables)); - } else { - processInstanceBuilder.name(definition.getName().trim()); - } + processInstanceBuilder.name(generateProcessInstanceName(userId, definition, processDefinitionInfo, variables)); // 3.3 发起流程实例 ProcessInstance instance = processInstanceBuilder.start(); return instance.getId(); @@ -817,6 +806,25 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService }); } + private String generateProcessInstanceName(Long userId, + ProcessDefinition definition, + BpmProcessDefinitionInfoDO definitionInfo, + Map variables) { + if (definition == null || definitionInfo == null) { + return null; + } + BpmModelMetaInfoVO.TitleSetting titleSetting = definitionInfo.getTitleSetting(); + if (titleSetting == null || !BooleanUtil.isTrue(titleSetting.getEnable())) { + return definition.getName(); + } + AdminUserRespDTO user = adminUserApi.getUser(userId); + Map cloneVariables = new HashMap<>(variables); + cloneVariables.put(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_START_USER_ID, user.getNickname()); + cloneVariables.put(BpmnVariableConstants.PROCESS_START_TIME, DateUtil.now()); + cloneVariables.put(BpmnVariableConstants.PROCESS_DEFINITION_NAME, definition.getName().trim()); + return StrUtil.format(definitionInfo.getTitleSetting().getTitle(), cloneVariables); + } + @Override public void cancelProcessInstanceByStartUser(Long userId, @Valid BpmProcessInstanceCancelReqVO cancelReqVO) { // 1.1 校验流程实例存在 @@ -833,7 +841,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService .getProcessDefinitionInfo(instance.getProcessDefinitionId()); Assert.notNull(processDefinitionInfo, "流程定义({})不存在", processDefinitionInfo); if (processDefinitionInfo.getAllowCancelRunningProcess() != null // 防止未配置 AllowCancelRunningProcess , 默认为可取消 - && Boolean.FALSE.equals(processDefinitionInfo.getAllowCancelRunningProcess())) { + && BooleanUtil.isFalse(processDefinitionInfo.getAllowCancelRunningProcess())) { throw exception(PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW); } // 1.4 子流程不允许取消 @@ -900,64 +908,77 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService @Override public void processProcessInstanceCompleted(ProcessInstance instance) { - // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 - FlowableUtils.execute(instance.getTenantId(), () -> { - // 1.1 获取当前状态 - Integer status = (Integer) instance.getProcessVariables() - .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); - String reason = (String) instance.getProcessVariables() - .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON); - // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态 - // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了 - if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) { - status = BpmProcessInstanceStatusEnum.APPROVE.getStatus(); - runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, - status); + // 1.1 获取当前状态 + Integer status = (Integer) instance.getProcessVariables() + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS); + String reason = (String) instance.getProcessVariables() + .get(BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_REASON); + // 1.2 当流程状态还是审批状态中,说明审批通过了,则变更下它的状态 + // 为什么这么处理?因为流程完成,并且完成了,说明审批通过了 + if (Objects.equals(status, BpmProcessInstanceStatusEnum.RUNNING.getStatus())) { + status = BpmProcessInstanceStatusEnum.APPROVE.getStatus(); + runtimeService.setVariable(instance.getId(), BpmnVariableConstants.PROCESS_INSTANCE_VARIABLE_STATUS, + status); + } + + // 2. 发送对应的消息通知 + if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { + messageService.sendMessageWhenProcessInstanceApprove( + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance)); + } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) { + messageService.sendMessageWhenProcessInstanceReject( + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason)); + } + + // 3. 发送流程实例的状态事件 + processInstanceEventPublisher.sendProcessInstanceResultEvent( + BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status)); + + // 4. 流程后置通知 + if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. + getProcessDefinitionInfo(instance.getProcessDefinitionId()); + if (ObjUtil.isNotNull(processDefinitionInfo) && + ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) { + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting(); + + BpmHttpRequestUtils.executeBpmHttpRequest(instance, + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); } - - // 2. 发送对应的消息通知 - if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { - messageService.sendMessageWhenProcessInstanceApprove( - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceApproveMessage(instance)); - } else if (Objects.equals(status, BpmProcessInstanceStatusEnum.REJECT.getStatus())) { - messageService.sendMessageWhenProcessInstanceReject( - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceRejectMessage(instance, reason)); - } - - // 3. 发送流程实例的状态事件 - processInstanceEventPublisher.sendProcessInstanceResultEvent( - BpmProcessInstanceConvert.INSTANCE.buildProcessInstanceStatusEvent(this, instance, status)); - - // 4. 流程后置通知 - if (Objects.equals(status, BpmProcessInstanceStatusEnum.APPROVE.getStatus())) { - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. - getProcessDefinitionInfo(instance.getProcessDefinitionId()); - if (ObjUtil.isNotNull(processDefinitionInfo) && - ObjUtil.isNotNull(processDefinitionInfo.getProcessAfterTriggerSetting())) { - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessAfterTriggerSetting(); - - BpmHttpRequestUtils.executeBpmHttpRequest(instance, - setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); - } - } - }); + } } @Override public void processProcessInstanceCreated(ProcessInstance instance) { - // 注意:需要基于 instance 设置租户编号,避免 Flowable 内部异步时,丢失租户编号 - FlowableUtils.execute(instance.getTenantId(), () -> { - // 流程前置通知 - BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. - getProcessDefinitionInfo(instance.getProcessDefinitionId()); - if (ObjUtil.isNull(processDefinitionInfo) || - ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) { - return; + BpmProcessDefinitionInfoDO processDefinitionInfo = processDefinitionService. + getProcessDefinitionInfo(instance.getProcessDefinitionId()); + ProcessDefinition processDefinition = processDefinitionService.getProcessDefinition(instance.getProcessDefinitionId()); + if (processDefinition == null || processDefinitionInfo == null) { + return; + } + + // 自定义标题。目的:主要处理子流程的标题无法处理 + // 注意:必须使用 TransactionSynchronizationManager 事务提交后,否则不生效!!! + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronization() { + + @Override + public void afterCommit() { + String name = generateProcessInstanceName(Long.valueOf(instance.getStartUserId()), + processDefinition, processDefinitionInfo, instance.getProcessVariables()); + if (ObjUtil.notEqual(instance.getName(), name)) { + runtimeService.setProcessInstanceName(instance.getProcessInstanceId(), name); + } } - BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting(); - BpmHttpRequestUtils.executeBpmHttpRequest(instance, - setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); + }); + + // 流程前置通知 + if (ObjUtil.isNull(processDefinitionInfo.getProcessBeforeTriggerSetting())) { + return; + } + BpmModelMetaInfoVO.HttpRequestSetting setting = processDefinitionInfo.getProcessBeforeTriggerSetting(); + BpmHttpRequestUtils.executeBpmHttpRequest(instance, + setting.getUrl(), setting.getHeader(), setting.getBody(), true, setting.getResponse()); } } From 989c4e4b88bc32e0eddab2d5c4fc969f51133b51 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 22 Jul 2025 21:57:01 +0800 Subject: [PATCH 48/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91bpmn=20subProcess=20=E5=AD=98?= =?UTF-8?q?=E5=9C=A8=20userTask=20NPE=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/candidate/BpmTaskCandidateInvoker.java | 7 ++----- .../bpm/framework/flowable/core/util/BpmnModelUtils.java | 6 +++++- .../yudao/module/bpm/service/task/BpmTaskServiceImpl.java | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java index 7f66b29d3b..df8b0d5fd5 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/BpmTaskCandidateInvoker.java @@ -18,10 +18,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.google.common.annotations.VisibleForTesting; import lombok.extern.slf4j.Slf4j; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.CallActivity; -import org.flowable.bpmn.model.FlowElement; -import org.flowable.bpmn.model.UserTask; +import org.flowable.bpmn.model.*; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.runtime.ProcessInstance; @@ -132,7 +129,7 @@ public class BpmTaskCandidateInvoker { Long startUserId, String processDefinitionId, Map processVariables) { // 如果是 CallActivity 子流程,不进行计算候选人 FlowElement flowElement = BpmnModelUtils.getFlowElementById(bpmnModel, activityId); - if (flowElement instanceof CallActivity) { + if (flowElement instanceof CallActivity || flowElement instanceof SubProcess) { return new HashSet<>(); } // 审批类型非人工审核时,不进行计算候选人。原因是:后续会自动通过、不通过 diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index 1cccf18f04..460af124f6 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -478,7 +478,11 @@ public class BpmnModelUtils { */ public static FlowElement getFlowElementById(BpmnModel model, String flowElementId) { Process process = model.getMainProcess(); - return process.getFlowElement(flowElementId); + FlowElement flowElement = process.getFlowElement(flowElementId); + if (flowElement != null) { + return flowElement; + } + return model.getFlowElement(flowElementId); } /** diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 1f7e699032..942a50669a 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -1379,7 +1379,7 @@ public class BpmTaskServiceImpl implements BpmTaskService { PROCESS_INSTANCE_VARIABLE_SKIP_START_USER_NODE, String.class)); if (userTaskElement.getId().equals(START_USER_NODE_ID) && (skipStartUserNodeFlag == null // 目的:一般是“主流程”,发起人节点,自动通过审核 - || Boolean.TRUE.equals(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 + || BooleanUtil.isTrue(skipStartUserNodeFlag)) // 目的:一般是“子流程”,发起人节点,按配置自动通过审核 && ObjUtil.notEqual(returnTaskFlag, Boolean.TRUE)) { getSelf().approveTask(Long.valueOf(task.getAssignee()), new BpmTaskApproveReqVO().setId(task.getId()) .setReason(BpmReasonEnum.ASSIGN_START_USER_APPROVE_WHEN_SKIP_START_USER_NODE.getReason())); From 376114a8741ad134ea13396c777ee176d07fddf6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 22 Jul 2025 23:59:20 +0800 Subject: [PATCH 49/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E4=BF=AE=E5=A4=8D=E5=AD=90=E6=B5=81?= =?UTF-8?q?=E7=A8=8B=E5=8F=91=E8=B5=B7=E4=BA=BA=E4=B8=BA=E5=88=97=E8=A1=A8?= =?UTF-8?q?=E6=97=B6=E5=AE=9E=E9=99=85=E5=8F=91=E8=B5=B7=E4=BA=BA=E4=BC=9A?= =?UTF-8?q?=E5=8F=98=E6=88=90=E4=B8=BB=E6=B5=81=E7=A8=8B=E5=8F=91=E8=B5=B7?= =?UTF-8?q?=E4=BA=BA=20https://gitee.com/zhijiantianya/yudao-cloud/issues/?= =?UTF-8?q?ICNHA8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/task/BpmProcessInstanceServiceImpl.java | 4 ++-- .../task/listener/BpmCallActivityListener.java | 13 +++++++++---- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 66fbaf79a3..9ce877b67c 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -448,7 +448,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService .setNodeType(BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType()).setStatus(processInstanceStatus) .setStartTime(DateUtils.of(activity.getStartTime())) .setEndTime(DateUtils.of(activity.getEndTime())) - .setProcessInstanceId(activity.getProcessInstanceId()); + .setProcessInstanceId(activity.getCalledProcessInstanceId()); approvalNodes.add(callActivity); } }); @@ -520,7 +520,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService activityNode.setCandidateUserIds(CollUtil.sub(candidateUserIds, index + 1, candidateUserIds.size())); } if (BpmSimpleModelNodeTypeEnum.CHILD_PROCESS.getType().equals(activityNode.getNodeType())) { - activityNode.setProcessInstanceId(firstActivity.getProcessInstanceId()); + activityNode.setProcessInstanceId(firstActivity.getCalledProcessInstanceId()); } return activityNode; }); diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java index 40313a9663..da148a8562 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/listener/BpmCallActivityListener.java @@ -85,10 +85,15 @@ public class BpmCallActivityListener implements ExecutionListener { // 2.2 使用表单值,并兜底字符串转 Long 失败时使用主流程发起人 try { FlowableUtils.setAuthenticatedUserId(Long.parseLong(formFieldValue)); - } catch (Exception e) { - log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", - DELEGATE_EXPRESSION, formFieldValue); - FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); + } catch (NumberFormatException ex) { + try { + List formFieldValues = JsonUtils.parseArray(formFieldValue, Long.class); + FlowableUtils.setAuthenticatedUserId(formFieldValues.get(0)); + } catch (Exception e) { + log.error("[notify][监听器:{},子流程监听器设置流程的发起人字符串转 Long 失败,字符串:{}]", + DELEGATE_EXPRESSION, formFieldValue); + FlowableUtils.setAuthenticatedUserId(Long.parseLong(processInstance.getStartUserId())); + } } } } From a4244ab9996f2e8f9951ed4a495dc7e027f862be Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 23 Jul 2025 12:46:00 +0800 Subject: [PATCH 50/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E5=AD=98=E5=9C=A8=E5=8A=A0=E7=AD=BE?= =?UTF-8?q?=E6=97=B6=EF=BC=8C=E9=80=80=E5=9B=9E=E6=8A=A5=20Execution=20cou?= =?UTF-8?q?ld=20not=20be=20found=20with=20id=20null?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/bpm/service/task/BpmTaskServiceImpl.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 942a50669a..1dbd0b17c0 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -898,7 +898,9 @@ public class BpmTaskServiceImpl implements BpmTaskService { if (!returnTaskKeyList.contains(task.getTaskDefinitionKey())) { return; } - runExecutionIds.add(task.getExecutionId()); + if (task.getExecutionId() != null) { + runExecutionIds.add(task.getExecutionId()); + } // 判断是否分配给自己任务,因为会签任务,一个节点会有多个任务 if (isAssignUserTask(userId, task)) { // 情况一:自己的任务,进行 RETURN 标记 From 0cd7bca209bd2206afd428e27eef144ce3505169 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 23 Jul 2025 20:59:26 +0800 Subject: [PATCH 51/81] =?UTF-8?q?chore=EF=BC=9Amybatis=20from=203.5.10.1?= =?UTF-8?q?=20to=203.5.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 4 +-- .../mybatis/core/query/MPJLambdaWrapperX.java | 36 ------------------- 2 files changed, 2 insertions(+), 38 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 27ad06fe5d..d13f89b127 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -24,9 +24,9 @@ 1.2.24 3.5.19 - 3.5.10.1 + 3.5.12 + 1.5.4 4.3.1 - 1.4.13 3.0.6 3.41.0 8.1.3.140 diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java index 48e901d624..ded0384000 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java @@ -207,12 +207,6 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } - @Override - public MPJLambdaWrapperX selectCount(SFunction column, String alias) { - super.selectCount(column, alias); - return this; - } - @Override public MPJLambdaWrapperX selectCount(SFunction column, SFunction alias) { super.selectCount(column, alias); @@ -225,12 +219,6 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } - @Override - public MPJLambdaWrapperX selectSum(SFunction column, String alias) { - super.selectSum(column, alias); - return this; - } - @Override public MPJLambdaWrapperX selectSum(SFunction column, SFunction alias) { super.selectSum(column, alias); @@ -243,12 +231,6 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } - @Override - public MPJLambdaWrapperX selectMax(SFunction column, String alias) { - super.selectMax(column, alias); - return this; - } - @Override public MPJLambdaWrapperX selectMax(SFunction column, SFunction alias) { super.selectMax(column, alias); @@ -261,12 +243,6 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } - @Override - public MPJLambdaWrapperX selectMin(SFunction column, String alias) { - super.selectMin(column, alias); - return this; - } - @Override public MPJLambdaWrapperX selectMin(SFunction column, SFunction alias) { super.selectMin(column, alias); @@ -279,12 +255,6 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } - @Override - public MPJLambdaWrapperX selectAvg(SFunction column, String alias) { - super.selectAvg(column, alias); - return this; - } - @Override public MPJLambdaWrapperX selectAvg(SFunction column, SFunction alias) { super.selectAvg(column, alias); @@ -297,12 +267,6 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } - @Override - public MPJLambdaWrapperX selectLen(SFunction column, String alias) { - super.selectLen(column, alias); - return this; - } - @Override public MPJLambdaWrapperX selectLen(SFunction column, SFunction alias) { super.selectLen(column, alias); From d650a0b1239dd3454214309d04a2c9e9096d25ca Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 23 Jul 2025 21:40:55 +0800 Subject: [PATCH 52/81] =?UTF-8?q?chore=EF=BC=9Amybatis=20from=203.5.10.1?= =?UTF-8?q?=20to=203.5.12?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mybatis/core/query/MPJLambdaWrapperX.java | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java index ded0384000..8b5a0fcfc8 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/MPJLambdaWrapperX.java @@ -118,7 +118,6 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { @Override public MPJLambdaWrapperX orderByDesc(SFunction column) { - //noinspection unchecked super.orderByDesc(true, column); return this; } @@ -207,6 +206,12 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } + @Override + public MPJLambdaWrapperX selectCount(SFunction column, String alias) { + super.selectCount(column, alias); + return this; + } + @Override public MPJLambdaWrapperX selectCount(SFunction column, SFunction alias) { super.selectCount(column, alias); @@ -219,6 +224,12 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } + @Override + public MPJLambdaWrapperX selectSum(SFunction column, String alias) { + super.selectSum(column, alias); + return this; + } + @Override public MPJLambdaWrapperX selectSum(SFunction column, SFunction alias) { super.selectSum(column, alias); @@ -231,6 +242,12 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } + @Override + public MPJLambdaWrapperX selectMax(SFunction column, String alias) { + super.selectMax(column, alias); + return this; + } + @Override public MPJLambdaWrapperX selectMax(SFunction column, SFunction alias) { super.selectMax(column, alias); @@ -243,6 +260,12 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } + @Override + public MPJLambdaWrapperX selectMin(SFunction column, String alias) { + super.selectMin(column, alias); + return this; + } + @Override public MPJLambdaWrapperX selectMin(SFunction column, SFunction alias) { super.selectMin(column, alias); @@ -255,6 +278,12 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } + @Override + public MPJLambdaWrapperX selectAvg(SFunction column, String alias) { + super.selectAvg(column, alias); + return this; + } + @Override public MPJLambdaWrapperX selectAvg(SFunction column, SFunction alias) { super.selectAvg(column, alias); @@ -267,6 +296,12 @@ public class MPJLambdaWrapperX extends MPJLambdaWrapper { return this; } + @Override + public MPJLambdaWrapperX selectLen(SFunction column, String alias) { + super.selectLen(column, alias); + return this; + } + @Override public MPJLambdaWrapperX selectLen(SFunction column, SFunction alias) { super.selectLen(column, alias); From d128d787188fdae094528d477ae1672c430db0ae Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 23 Jul 2025 22:17:54 +0800 Subject: [PATCH 53/81] =?UTF-8?q?reactor=EF=BC=9Aeasy-trans=20=E9=BB=98?= =?UTF-8?q?=E8=AE=A4=E7=A6=81=E7=94=A8=EF=BC=8C=E9=81=BF=E5=85=8D=E5=BD=B1?= =?UTF-8?q?=E5=93=8D=E6=8E=A5=E5=8F=A3=E6=80=A7=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/admin/chat/AiChatConversationController.java | 4 ++++ .../ai/controller/admin/model/AiChatRoleController.java | 4 ++++ .../crm/controller/admin/product/CrmProductController.java | 3 +++ .../iot/controller/admin/ota/IotOtaFirmwareController.java | 2 ++ .../controller/admin/ota/IotOtaUpgradeRecordController.java | 3 +++ .../system/controller/admin/logger/OperateLogController.java | 2 ++ yudao-server/src/main/resources/application.yaml | 2 +- 7 files changed, 19 insertions(+), 1 deletion(-) diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java index 5142cde443..ddd426d283 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/chat/AiChatConversationController.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.chat.vo.conversation.AiChatCo import cn.iocoder.yudao.module.ai.dal.dataobject.chat.AiChatConversationDO; import cn.iocoder.yudao.module.ai.service.chat.AiChatConversationService; import cn.iocoder.yudao.module.ai.service.chat.AiChatMessageService; +import com.fhs.core.trans.anno.TransMethodResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -54,6 +55,7 @@ public class AiChatConversationController { @GetMapping("/my-list") @Operation(summary = "获得【我的】聊天对话列表") + @TransMethodResult public CommonResult> getChatConversationMyList() { List list = chatConversationService.getChatConversationListByUserId(getLoginUserId()); return success(BeanUtils.toBean(list, AiChatConversationRespVO.class)); @@ -62,6 +64,7 @@ public class AiChatConversationController { @GetMapping("/get-my") @Operation(summary = "获得【我的】聊天对话") @Parameter(name = "id", required = true, description = "对话编号", example = "1024") + @TransMethodResult public CommonResult getChatConversationMy(@RequestParam("id") Long id) { AiChatConversationDO conversation = chatConversationService.getChatConversation(id); if (conversation != null && ObjUtil.notEqual(conversation.getUserId(), getLoginUserId())) { @@ -90,6 +93,7 @@ public class AiChatConversationController { @GetMapping("/page") @Operation(summary = "获得对话分页", description = "用于【对话管理】菜单") @PreAuthorize("@ss.hasPermission('ai:chat-conversation:query')") + @TransMethodResult public CommonResult> getChatConversationPage(AiChatConversationPageReqVO pageReqVO) { PageResult pageResult = chatConversationService.getChatConversationPage(pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { diff --git a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java index 5714c5fedd..804e211527 100644 --- a/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java +++ b/yudao-module-ai/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/model/AiChatRoleController.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleS import cn.iocoder.yudao.module.ai.controller.admin.model.vo.chatRole.AiChatRoleSaveReqVO; import cn.iocoder.yudao.module.ai.dal.dataobject.model.AiChatRoleDO; import cn.iocoder.yudao.module.ai.service.model.AiChatRoleService; +import com.fhs.core.trans.anno.TransMethodResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -35,6 +36,7 @@ public class AiChatRoleController { @GetMapping("/my-page") @Operation(summary = "获得【我的】聊天角色分页") + @TransMethodResult public CommonResult> getChatRoleMyPage(@Valid AiChatRolePageReqVO pageReqVO) { PageResult pageResult = chatRoleService.getChatRoleMyPage(pageReqVO, getLoginUserId()); return success(BeanUtils.toBean(pageResult, AiChatRoleRespVO.class)); @@ -43,6 +45,7 @@ public class AiChatRoleController { @GetMapping("/get-my") @Operation(summary = "获得【我的】聊天角色") @Parameter(name = "id", description = "编号", required = true, example = "1024") + @TransMethodResult public CommonResult getChatRoleMy(@RequestParam("id") Long id) { AiChatRoleDO chatRole = chatRoleService.getChatRole(id); if (ObjUtil.notEqual(chatRole.getUserId(), getLoginUserId())) { @@ -108,6 +111,7 @@ public class AiChatRoleController { @Operation(summary = "获得聊天角色") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('ai:chat-role:query')") + @TransMethodResult public CommonResult getChatRole(@RequestParam("id") Long id) { AiChatRoleDO chatRole = chatRoleService.getChatRole(id); return success(BeanUtils.toBean(chatRole, AiChatRoleRespVO.class)); diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java index bf98a80606..adefc77556 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java @@ -14,6 +14,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.enums.product.CrmProductStatusEnum; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import com.fhs.core.trans.anno.TransMethodResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -70,6 +71,7 @@ public class CrmProductController { @Operation(summary = "获得产品") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:product:query')") + @TransMethodResult public CommonResult getProduct(@RequestParam("id") Long id) { CrmProductDO product = productService.getProduct(id); return success(BeanUtils.toBean(product, CrmProductRespVO.class)); @@ -86,6 +88,7 @@ public class CrmProductController { @GetMapping("/page") @Operation(summary = "获得产品分页") @PreAuthorize("@ss.hasPermission('crm:product:query')") + @TransMethodResult public CommonResult> getProductPage(@Valid CrmProductPageReqVO pageVO) { PageResult pageResult = productService.getProductPage(pageVO); return success(BeanUtils.toBean(pageResult, CrmProductRespVO.class)); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaFirmwareController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaFirmwareController.java index 6cc3918e8f..38407333ea 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaFirmwareController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaFirmwareController.java @@ -9,6 +9,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwa import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.firmware.IotOtaFirmwareUpdateReqVO; import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaFirmwareDO; import cn.iocoder.yudao.module.iot.service.ota.IotOtaFirmwareService; +import com.fhs.core.trans.anno.TransMethodResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -46,6 +47,7 @@ public class IotOtaFirmwareController { @GetMapping("/get") @Operation(summary = "获得 OTA 固件") @PreAuthorize("@ss.hasPermission('iot:ota-firmware:query')") + @TransMethodResult public CommonResult getOtaFirmware(@RequestParam("id") Long id) { IotOtaFirmwareDO otaFirmware = otaFirmwareService.getOtaFirmware(id); return success(BeanUtils.toBean(otaFirmware, IotOtaFirmwareRespVO.class)); diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaUpgradeRecordController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaUpgradeRecordController.java index f6bc526ac2..b18caecfb8 100644 --- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaUpgradeRecordController.java +++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/IotOtaUpgradeRecordController.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.record.IotOta import cn.iocoder.yudao.module.iot.controller.admin.ota.vo.upgrade.record.IotOtaUpgradeRecordRespVO; import cn.iocoder.yudao.module.iot.dal.dataobject.ota.IotOtaUpgradeRecordDO; import cn.iocoder.yudao.module.iot.service.ota.IotOtaUpgradeRecordService; +import com.fhs.core.trans.anno.TransMethodResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -48,6 +49,7 @@ public class IotOtaUpgradeRecordController { @GetMapping("/page") @Operation(summary = "获得升级记录分页") @PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')") + @TransMethodResult public CommonResult> getUpgradeRecordPage( @Valid IotOtaUpgradeRecordPageReqVO pageReqVO) { PageResult pageResult = upgradeRecordService.getUpgradeRecordPage(pageReqVO); @@ -58,6 +60,7 @@ public class IotOtaUpgradeRecordController { @Operation(summary = "获得升级记录") @PreAuthorize("@ss.hasPermission('iot:ota-upgrade-record:query')") @Parameter(name = "id", description = "升级记录编号", required = true, example = "1024") + @TransMethodResult public CommonResult getUpgradeRecord(@RequestParam("id") Long id) { IotOtaUpgradeRecordDO upgradeRecord = upgradeRecordService.getUpgradeRecord(id); return success(BeanUtils.toBean(upgradeRecord, IotOtaUpgradeRecordRespVO.class)); diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java index 71b45d346e..257477071a 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/logger/OperateLogController.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.Oper import cn.iocoder.yudao.module.system.controller.admin.logger.vo.operatelog.OperateLogRespVO; import cn.iocoder.yudao.module.system.dal.dataobject.logger.OperateLogDO; import cn.iocoder.yudao.module.system.service.logger.OperateLogService; +import com.fhs.core.trans.anno.TransMethodResult; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -40,6 +41,7 @@ public class OperateLogController { @GetMapping("/page") @Operation(summary = "查看操作日志分页列表") @PreAuthorize("@ss.hasPermission('system:operate-log:query')") + @TransMethodResult public CommonResult> pageOperateLog(@Valid OperateLogPageReqVO pageReqVO) { PageResult pageResult = operateLogService.getOperateLogPage(pageReqVO); return success(BeanUtils.toBean(pageResult, OperateLogRespVO.class)); diff --git a/yudao-server/src/main/resources/application.yaml b/yudao-server/src/main/resources/application.yaml index 12a4abf896..6519cbf0e5 100644 --- a/yudao-server/src/main/resources/application.yaml +++ b/yudao-server/src/main/resources/application.yaml @@ -96,7 +96,7 @@ spring: # VO 转换(数据翻译)相关 easy-trans: - is-enable-global: true # 启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 + is-enable-global: false # 【默认禁用,对性能确认压力大】启用全局翻译(拦截所有 SpringMVC ResponseBody 进行自动翻译 )。如果对于性能要求很高可关闭此配置,或通过 @IgnoreTrans 忽略某个接口 --- #################### 验证码相关配置 #################### From d09e4849ba6d79d9906df1a4b7e17ffa314c52a1 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 24 Jul 2025 09:02:45 +0800 Subject: [PATCH 54/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90Infra=20=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E8=AE=BE=E7=BD=AE=E3=80=91=E6=94=AF=E6=8C=81=20yudao.?= =?UTF-8?q?websocket.enable=20=E6=89=8B=E5=8A=A8=E5=85=B3=E9=97=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/infra/api/websocket/WebSocketSenderApiImpl.java | 6 +++--- .../infra/websocket/DemoWebSocketMessageListener.java | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java index cc060aafa1..52950537c3 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/api/websocket/WebSocketSenderApiImpl.java @@ -1,10 +1,9 @@ package cn.iocoder.yudao.module.infra.api.websocket; import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import jakarta.annotation.Resource; - /** * WebSocket 发送器的 API 实现类 * @@ -13,7 +12,8 @@ import jakarta.annotation.Resource; @Component public class WebSocketSenderApiImpl implements WebSocketSenderApi { - @Resource + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") + @Autowired(required = false) // 由于 yudao.websocket.enable 配置项,可以关闭 WebSocket 的功能,所以这里只能不强制注入 private WebSocketMessageSender webSocketMessageSender; @Override diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java index a3b71505bc..f0bdc69325 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/websocket/DemoWebSocketMessageListener.java @@ -6,11 +6,10 @@ import cn.iocoder.yudao.framework.websocket.core.sender.WebSocketMessageSender; import cn.iocoder.yudao.framework.websocket.core.util.WebSocketFrameworkUtils; import cn.iocoder.yudao.module.infra.websocket.message.DemoReceiveMessage; import cn.iocoder.yudao.module.infra.websocket.message.DemoSendMessage; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.socket.WebSocketSession; -import jakarta.annotation.Resource; - /** * WebSocket 示例:单发消息 * @@ -19,7 +18,8 @@ import jakarta.annotation.Resource; @Component public class DemoWebSocketMessageListener implements WebSocketMessageListener { - @Resource + @SuppressWarnings("SpringJavaAutowiredFieldsWarningInspection") + @Autowired(required = false) // 由于 yudao.websocket.enable 配置项,可以关闭 WebSocket 的功能,所以这里只能不强制注入 private WebSocketMessageSender webSocketMessageSender; @Override From 97cec2897b85c9afddc6f52c93118c23817c379e Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Thu, 24 Jul 2025 22:23:15 +0800 Subject: [PATCH 55/81] =?UTF-8?q?feat:=20[BPM=20=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81]=20=E5=B9=B6=E8=A1=8C=E5=88=86=E6=94=AF=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=E5=8C=85=E5=AE=B9=E7=BD=91=E5=85=B3=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmSimpleModelNodeTypeEnum.java | 2 +- .../flowable/core/util/SimpleModelUtils.java | 32 ++++++++++++------- 2 files changed, 22 insertions(+), 12 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java index e5ffa12025..d97c145c3f 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/definition/BpmSimpleModelNodeTypeEnum.java @@ -35,7 +35,7 @@ public enum BpmSimpleModelNodeTypeEnum implements ArrayValuable { // 50 ~ 条件分支 CONDITION_NODE(50, "条件", "sequenceFlow"), // 用于构建流转条件的表达式 CONDITION_BRANCH_NODE(51, "条件分支", "exclusiveGateway"), - PARALLEL_BRANCH_NODE(52, "并行分支", "parallelGateway"), + PARALLEL_BRANCH_NODE(52, "并行分支", "inclusiveGateway"), // 并行分支使用包容网关实现,条件表达式结果设置为 true INCLUSIVE_BRANCH_NODE(53, "包容分支", "inclusiveGateway"), ROUTER_BRANCH_NODE(54, "路由分支", "exclusiveGateway") ; diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index c9f3ff6fcb..5e9313840b 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -239,13 +239,13 @@ public class SimpleModelUtils { // 3.1 分支有后续节点。即分支 1: A->B->C->D 的情况 if (isValidNode(conditionChildNode)) { // 3.1.1 建立与后续的节点的连线。例如说,建立 A->B 的连线 - SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), item); + SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), conditionChildNode.getId(), nodeType, item); process.addFlowElement(sequenceFlow); // 3.1.2 递归调用后续节点连线。例如说,建立 B->C->D 的连线 traverseNodeToBuildSequenceFlow(process, conditionChildNode, branchEndNodeId); } else { // 3.2 分支没有后续节点。例如说,建立 A->D 的连线 - SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, item); + SequenceFlow sequenceFlow = ConditionNodeConvert.buildSequenceFlow(node.getId(), branchEndNodeId, nodeType, item); process.addFlowElement(sequenceFlow); } } @@ -591,17 +591,22 @@ public class SimpleModelUtils { private static class ParallelBranchNodeConvert implements NodeConvert { + /** + * 并行分支使用包容网关。需要设置所有出口条件表达式的值为 true. + * 参见: {@link ConditionNodeConvert#buildSequenceFlow} + */ @Override - public List convertList(BpmSimpleModelNodeVO node) { - ParallelGateway parallelGateway = new ParallelGateway(); - parallelGateway.setId(node.getId()); + public List convertList(BpmSimpleModelNodeVO node) { + + InclusiveGateway inclusiveGateway = new InclusiveGateway(); + inclusiveGateway.setId(node.getId()); // TODO @jason:setName - // 并行聚合网关由程序创建,前端不需要传入 - ParallelGateway joinParallelGateway = new ParallelGateway(); + // 合并网关 由程序创建,前端不需要传入 + InclusiveGateway joinParallelGateway = new InclusiveGateway(); joinParallelGateway.setId(buildGatewayJoinId(node.getId())); // TODO @jason:setName - return CollUtil.newArrayList(parallelGateway, joinParallelGateway); + return CollUtil.newArrayList(inclusiveGateway, joinParallelGateway); } @Override @@ -652,8 +657,14 @@ public class SimpleModelUtils { } public static SequenceFlow buildSequenceFlow(String sourceId, String targetId, - BpmSimpleModelNodeVO node) { - String conditionExpression = buildConditionExpression(node.getConditionSetting()); + BpmSimpleModelNodeTypeEnum nodeType, BpmSimpleModelNodeVO node) { + String conditionExpression; + // 并行分支,使用包容网关实现,强制设置条件表达式为 true + if (BpmSimpleModelNodeTypeEnum.PARALLEL_BRANCH_NODE == nodeType) { + conditionExpression ="${true}"; + } else { + conditionExpression = buildConditionExpression(node.getConditionSetting()); + } return buildBpmnSequenceFlow(sourceId, targetId, node.getId(), node.getName(), conditionExpression); } } @@ -662,7 +673,6 @@ public class SimpleModelUtils { * 构造条件表达式 */ public static String buildConditionExpression(BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { - // 并行网关不需要设置条件 if (conditionSetting == null) { return null; } From 76d8906748839807cc50261bcb79b09a73aadca8 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Thu, 24 Jul 2025 23:07:15 +0800 Subject: [PATCH 56/81] =?UTF-8?q?fix:=20[BPM=20=E5=B7=A5=E4=BD=9C=E6=B5=81?= =?UTF-8?q?]=20=E8=8E=B7=E5=8F=96=E4=B8=8B=E4=B8=AA=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E4=BB=BB=E5=8A=A1=E8=8A=82=E7=82=B9=E9=97=AE=E9=A2=98=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/task/BpmProcessInstanceServiceImpl.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 9ce877b67c..85d15a6327 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.*; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.DateUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; @@ -66,6 +67,7 @@ import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmApprovalDetailRespVO.ActivityNode; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.bpm.framework.flowable.core.enums.BpmnModelConstants.START_USER_NODE_ID; @@ -263,7 +265,9 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 3. 获取下一个将要执行的节点集合 FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); List nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); - List nextActivityNodes = convertList(nextFlowNodes, node -> new ActivityNode().setId(node.getId()) + // 仅仅获取 UserTask 节点 TODO:如果网关节点和网关节点相连,获取下个 UserTask. 貌似有点不准。 + List nextUserTaskList = CollectionUtils.filterList(nextFlowNodes, node -> node instanceof UserTask); + List nextActivityNodes = convertList(nextUserTaskList, node -> new ActivityNode().setId(node.getId()) .setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) .setStatus(BpmTaskStatusEnum.RUNNING.getStatus()) .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(node)) From 4347f1336299664693f77f1a7aa3129f59a3d53b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 25 Jul 2025 20:18:33 +0800 Subject: [PATCH 57/81] =?UTF-8?q?review=EF=BC=9A=E3=80=90BPM=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E5=B9=B6=E8=A1=8C=E5=88=86=E6=94=AF?= =?UTF-8?q?=E4=BD=BF=E7=94=A8=E5=8C=85=E5=AE=B9=E7=BD=91=E5=85=B3=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20=3D=E3=80=8B=E8=A1=A5=E5=85=85=E4=B8=80=E4=BA=9B?= =?UTF-8?q?=E6=B3=A8=E9=87=8A=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/framework/flowable/core/util/SimpleModelUtils.java | 5 +++-- .../bpm/service/task/BpmProcessInstanceServiceImpl.java | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 5e9313840b..f3c00258e5 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -592,8 +592,9 @@ public class SimpleModelUtils { private static class ParallelBranchNodeConvert implements NodeConvert { /** - * 并行分支使用包容网关。需要设置所有出口条件表达式的值为 true. - * 参见: {@link ConditionNodeConvert#buildSequenceFlow} + * 并行分支使用包容网关。需要设置所有出口条件表达式的值为 true 。原因是,解决 https://t.zsxq.com/m6GXh 反馈问题 + * + * @see {@link ConditionNodeConvert#buildSequenceFlow} */ @Override public List convertList(BpmSimpleModelNodeVO node) { diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 85d15a6327..47265f5c72 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -265,7 +265,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService // 3. 获取下一个将要执行的节点集合 FlowElement flowElement = bpmnModel.getFlowElement(task.getTaskDefinitionKey()); List nextFlowNodes = BpmnModelUtils.getNextFlowNodes(flowElement, bpmnModel, processVariables); - // 仅仅获取 UserTask 节点 TODO:如果网关节点和网关节点相连,获取下个 UserTask. 貌似有点不准。 + // 仅仅获取 UserTask 节点 TODO add from jason:如果网关节点和网关节点相连,获取下个 UserTask. 貌似有点不准。 List nextUserTaskList = CollectionUtils.filterList(nextFlowNodes, node -> node instanceof UserTask); List nextActivityNodes = convertList(nextUserTaskList, node -> new ActivityNode().setId(node.getId()) .setName(node.getName()).setNodeType(BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType()) From 28965b9bbf5d5606f2b4762d09d1f3dd2f3af74f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 25 Jul 2025 23:17:35 +0800 Subject: [PATCH 58/81] =?UTF-8?q?reactor=EF=BC=9A=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E8=BF=9E=E6=8E=A5=E6=B1=A0=E7=9A=84=E9=85=8D?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-server/src/main/resources/application-dev.yaml | 12 +++++++----- .../src/main/resources/application-local.yaml | 10 ++++++---- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 344e97ecf8..44c1cecfa3 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -33,14 +33,16 @@ spring: initial-size: 5 # 初始连接数 min-idle: 10 # 最小连接池数量 max-active: 20 # 最大连接池数量 - max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 - time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 - min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 - max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 - validation-query: SELECT 1 # 配置检测连接是否有效 + max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒(1 分钟) + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒(1 分钟) + min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒(10 分钟) + max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒(30 分钟) + validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 test-while-idle: true test-on-borrow: false test-on-return: false + pool-prepared-statements: true # 是否开启 PreparedStatement 缓存 + max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量 primary: master datasource: master: diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 5d23b9b70d..e868eca456 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -37,14 +37,16 @@ spring: initial-size: 1 # 初始连接数 min-idle: 1 # 最小连接池数量 max-active: 20 # 最大连接池数量 - max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒 - time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒 - min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒 - max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒 + max-wait: 60000 # 配置获取连接等待超时的时间,单位:毫秒(1 分钟) + time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒(1 分钟) + min-evictable-idle-time-millis: 600000 # 配置一个连接在池中最小生存的时间,单位:毫秒(10 分钟) + max-evictable-idle-time-millis: 1800000 # 配置一个连接在池中最大生存的时间,单位:毫秒(30 分钟) validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效 test-while-idle: true test-on-borrow: false test-on-return: false + pool-prepared-statements: true # 是否开启 PreparedStatement 缓存 + max-pool-prepared-statement-per-connection-size: 20 # 每个连接缓存的 PreparedStatement 数量 primary: master datasource: master: From 529c570bbd7b700785f1297d8b47e56ff07c8088 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 12:45:41 +0800 Subject: [PATCH 59/81] =?UTF-8?q?reactor=EF=BC=9A=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=97=A5=E5=BF=97=E6=A0=BC=E5=BC=8F=EF=BC=8C=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=20FILE=20=E9=87=8C=E5=AD=98=E5=9C=A8=20highlight=E3=80=81cyan?= =?UTF-8?q?=E9=AB=98=E4=BA=AE=20reactor=EF=BC=9A=E5=BC=B1=E5=8C=96?= =?UTF-8?q?=E5=AF=B9=20skywalking=20=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=8F=AF?= =?UTF-8?q?=E6=8C=89=E9=9C=80=E5=BC=95=E5=85=A5=EF=BC=8C=E6=9B=B4=E7=81=B5?= =?UTF-8?q?=E6=B4=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao-spring-boot-starter-monitor/pom.xml | 4 + .../config/YudaoTracerAutoConfiguration.java | 45 ++++++----- .../dto/kd100/Kd100ExpressQueryRespDTO.java | 1 - .../src/main/resources/logback-spring.xml | 74 +++++++------------ 4 files changed, 56 insertions(+), 68 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml index ebd1210c03..c9a65e8c18 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml @@ -44,18 +44,22 @@ io.opentracing opentracing-util + true org.apache.skywalking apm-toolkit-trace + true org.apache.skywalking apm-toolkit-logback-1.x + true org.apache.skywalking apm-toolkit-opentracing + true diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java index c7d9e2c0db..7876742620 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-monitor/src/main/java/cn/iocoder/yudao/framework/tracer/config/YudaoTracerAutoConfiguration.java @@ -3,6 +3,9 @@ package cn.iocoder.yudao.framework.tracer.config; import cn.iocoder.yudao.framework.common.enums.WebFilterOrderEnum; import cn.iocoder.yudao.framework.tracer.core.aop.BizTraceAspect; import cn.iocoder.yudao.framework.tracer.core.filter.TraceFilter; +import io.opentracing.Tracer; +import io.opentracing.util.GlobalTracer; +import org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; @@ -16,30 +19,32 @@ import org.springframework.context.annotation.Bean; * @author mashu */ @AutoConfiguration -@ConditionalOnClass({BizTraceAspect.class}) +@ConditionalOnClass(name = { + "org.apache.skywalking.apm.toolkit.opentracing.SkywalkingTracer", + "io.opentracing.Tracer" +}) @EnableConfigurationProperties(TracerProperties.class) @ConditionalOnProperty(prefix = "yudao.tracer", value = "enable", matchIfMissing = true) public class YudaoTracerAutoConfiguration { - // TODO @芋艿:重要。目前 opentracing 版本存在冲突,要么保证 skywalking,要么保证阿里云短信 sdk -// @Bean -// public TracerProperties bizTracerProperties() { -// return new TracerProperties(); -// } -// -// @Bean -// public BizTraceAspect bizTracingAop() { -// return new BizTraceAspect(tracer()); -// } -// -// @Bean -// public Tracer tracer() { -// // 创建 SkywalkingTracer 对象 -// SkywalkingTracer tracer = new SkywalkingTracer(); -// // 设置为 GlobalTracer 的追踪器 -// GlobalTracer.register(tracer); -// return tracer; -// } + @Bean + public TracerProperties bizTracerProperties() { + return new TracerProperties(); + } + + @Bean + public BizTraceAspect bizTracingAop() { + return new BizTraceAspect(tracer()); + } + + @Bean + public Tracer tracer() { + // 创建 SkywalkingTracer 对象 + SkywalkingTracer tracer = new SkywalkingTracer(); + // 设置为 GlobalTracer 的追踪器 + GlobalTracer.registerIfAbsent(tracer); + return tracer; + } /** * 创建 TraceFilter 过滤器,响应 header 设置 traceId diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java index 6a8e83e3b3..0cf5c96caa 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java @@ -59,7 +59,6 @@ public class Kd100ExpressQueryRespDTO { /** * 轨迹发生时间 */ - @JsonProperty("time") @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND, timezone = TIME_ZONE_DEFAULT) @JsonDeserialize(using = LocalDateTimeDeserializer.class) private LocalDateTime time; diff --git a/yudao-server/src/main/resources/logback-spring.xml b/yudao-server/src/main/resources/logback-spring.xml index b1b9f3fafb..15b28cfdff 100644 --- a/yudao-server/src/main/resources/logback-spring.xml +++ b/yudao-server/src/main/resources/logback-spring.xml @@ -1,76 +1,56 @@ - - - - - - + + + + +       - - - ${PATTERN_DEFAULT} - + + ${CONSOLE_LOG_PATTERN} - - - ${PATTERN_DEFAULT} - + + ${FILE_LOG_PATTERN} ${LOG_FILE} + - - ${LOGBACK_ROLLINGPOLICY_FILE_NAME_PATTERN:-${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz} - - ${LOGBACK_ROLLINGPOLICY_CLEAN_HISTORY_ON_START:-false} - - ${LOGBACK_ROLLINGPOLICY_MAX_FILE_SIZE:-10MB} - - ${LOGBACK_ROLLINGPOLICY_TOTAL_SIZE_CAP:-0} - - ${LOGBACK_ROLLINGPOLICY_MAX_HISTORY:-30} + ${LOG_FILE}.%d{yyyy-MM-dd}.%i.log + 30 + 10MB - - 0 - - 256 + 0 + 512 - - + + - - - - - - - - - - - - - - - - + + + + + + + From 8e1729d7b2595223f963947f7ff409c1f80ee04f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 13:50:06 +0800 Subject: [PATCH 60/81] =?UTF-8?q?reactor=EF=BC=9A=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=8D=E5=BC=95=E5=85=A5=20micrometer-registry-prometheus=20?= =?UTF-8?q?=E4=BE=9D=E8=B5=96=EF=BC=8C=E5=87=8F=E5=B0=91=E5=8C=85=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-framework/yudao-spring-boot-starter-monitor/pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml index c9a65e8c18..50cfc31e09 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml @@ -66,6 +66,7 @@ io.micrometer micrometer-registry-prometheus + true From 5cbba7633859b0f40d9a13620c8ee4a1918f4f4a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 14:37:24 +0800 Subject: [PATCH 61/81] =?UTF-8?q?reactor=EF=BC=9A=E9=BB=98=E8=AE=A4?= =?UTF-8?q?=E4=B8=8D=E5=BC=95=E5=85=A5=20spring-boot-admin=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E7=81=B5=E6=B4=BB=EF=BC=8C=E5=90=8C=E6=97=B6=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E9=80=9F=E5=BA=A6=E6=9B=B4=E5=BF=AB=EF=BC=88=E6=8F=90?= =?UTF-8?q?=E5=8D=87=E5=BC=80=E5=8F=91=E6=95=88=E7=8E=87=EF=BC=89=EF=BC=81?= =?UTF-8?q?=EF=BC=81=EF=BC=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-framework/yudao-spring-boot-starter-monitor/pom.xml | 3 ++- yudao-module-infra/pom.xml | 1 + yudao-server/src/main/resources/application-dev.yaml | 1 + yudao-server/src/main/resources/application-local.yaml | 3 --- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml index 50cfc31e09..6b6970fbef 100644 --- a/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-monitor/pom.xml @@ -71,7 +71,8 @@ de.codecentric - spring-boot-admin-starter-client + spring-boot-admin-starter-client + true diff --git a/yudao-module-infra/pom.xml b/yudao-module-infra/pom.xml index 8b983cfe4b..be053b5cae 100644 --- a/yudao-module-infra/pom.xml +++ b/yudao-module-infra/pom.xml @@ -92,6 +92,7 @@ de.codecentric spring-boot-admin-starter-server + true diff --git a/yudao-server/src/main/resources/application-dev.yaml b/yudao-server/src/main/resources/application-dev.yaml index 44c1cecfa3..6d228c7474 100644 --- a/yudao-server/src/main/resources/application-dev.yaml +++ b/yudao-server/src/main/resources/application-dev.yaml @@ -5,6 +5,7 @@ server: spring: autoconfigure: + # noinspection SpringBootApplicationYaml exclude: - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index e868eca456..7b79eca5b6 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -7,9 +7,6 @@ spring: # noinspection SpringBootApplicationYaml exclude: - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置 - - de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置 - - de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置 - - de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置 - org.springframework.ai.vectorstore.qdrant.autoconfigure.QdrantVectorStoreAutoConfiguration # 禁用 AI 模块的 Qdrant,手动创建 - org.springframework.ai.vectorstore.milvus.autoconfigure.MilvusVectorStoreAutoConfiguration # 禁用 AI 模块的 Milvus,手动创建 # 数据源配置项 From ca65267f6d224de3ca381615705a4dfd1839cdee Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 16:06:27 +0800 Subject: [PATCH 62/81] =?UTF-8?q?fix=EF=BC=9ACacheRequestBodyFilter=20?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=20Spring=20Boot=20Admin=20=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A5=E5=BF=97=E7=BA=A7=E5=88=AB=EF=BC=8C?= =?UTF-8?q?https://github.com/YunaiV/ruoyi-vue-pro/issues/795?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/core/filter/CacheRequestBodyFilter.java | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java index 9071998f91..ae7bfeca70 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.framework.web.core.filter; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import org.springframework.web.filter.OncePerRequestFilter; @@ -16,6 +17,14 @@ import java.io.IOException; */ public class CacheRequestBodyFilter extends OncePerRequestFilter { + /** + * 需要排除的 URI + * + * 1. 排除 Spring Boot Admin 相关请求,避免客户端连接中断导致的异常。 + * 例如说:795 ISSUE + */ + private static final String[] IGNORE_URIS = {"/admin", "/actuator"}; + @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws IOException, ServletException { @@ -24,7 +33,13 @@ public class CacheRequestBodyFilter extends OncePerRequestFilter { @Override protected boolean shouldNotFilter(HttpServletRequest request) { - // 只处理 json 请求内容 + // 1. 校验是否为排除的 URL + String requestURI = request.getRequestURI(); + if (StrUtil.containsAny(requestURI, IGNORE_URIS)) { + return true; + } + + // 2. 只处理 json 请求内容 return !ServletUtils.isJsonRequest(request); } From 13802ceb3afcbc434641f561b3cc64eecdc9c5dc Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 16:37:49 +0800 Subject: [PATCH 63/81] =?UTF-8?q?fix=EF=BC=9ADateUtils=E3=80=81LocalDateTi?= =?UTF-8?q?meUtils=20=E5=8D=95=E8=AF=8D=E6=8B=BC=E5=86=99=E9=94=99?= =?UTF-8?q?=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/common/util/date/DateUtils.java | 12 ++++++------ .../common/util/date/LocalDateTimeUtils.java | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java index b51a838c69..d6051e85fe 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/DateUtils.java @@ -74,30 +74,30 @@ public class DateUtils { * 创建指定时间 * * @param year 年 - * @param mouth 月 + * @param month 月 * @param day 日 * @return 指定时间 */ - public static Date buildTime(int year, int mouth, int day) { - return buildTime(year, mouth, day, 0, 0, 0); + public static Date buildTime(int year, int month, int day) { + return buildTime(year, month, day, 0, 0, 0); } /** * 创建指定时间 * * @param year 年 - * @param mouth 月 + * @param month 月 * @param day 日 * @param hour 小时 * @param minute 分钟 * @param second 秒 * @return 指定时间 */ - public static Date buildTime(int year, int mouth, int day, + public static Date buildTime(int year, int month, int day, int hour, int minute, int second) { Calendar calendar = Calendar.getInstance(); calendar.set(Calendar.YEAR, year); - calendar.set(Calendar.MONTH, mouth - 1); + calendar.set(Calendar.MONTH, month - 1); calendar.set(Calendar.DAY_OF_MONTH, day); calendar.set(Calendar.HOUR_OF_DAY, hour); calendar.set(Calendar.MINUTE, minute); diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java index 8d18479c81..26b3961685 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/date/LocalDateTimeUtils.java @@ -69,17 +69,17 @@ public class LocalDateTimeUtils { * 创建指定时间 * * @param year 年 - * @param mouth 月 + * @param month 月 * @param day 日 * @return 指定时间 */ - public static LocalDateTime buildTime(int year, int mouth, int day) { - return LocalDateTime.of(year, mouth, day, 0, 0, 0); + public static LocalDateTime buildTime(int year, int month, int day) { + return LocalDateTime.of(year, month, day, 0, 0, 0); } - public static LocalDateTime[] buildBetweenTime(int year1, int mouth1, int day1, - int year2, int mouth2, int day2) { - return new LocalDateTime[]{buildTime(year1, mouth1, day1), buildTime(year2, mouth2, day2)}; + public static LocalDateTime[] buildBetweenTime(int year1, int month1, int day1, + int year2, int month2, int day2) { + return new LocalDateTime[]{buildTime(year1, month1, day1), buildTime(year2, month2, day2)}; } /** From f05a66f8e4dcab5dbfbd70cf3ebbdb68013f3a1d Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 16:55:55 +0800 Subject: [PATCH 64/81] =?UTF-8?q?fix=EF=BC=9ACacheRequestBodyFilter=20?= =?UTF-8?q?=E5=AF=BC=E8=87=B4=20Spring=20Boot=20Admin=20=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=A5=E5=BF=97=E7=BA=A7=E5=88=AB=EF=BC=8C?= =?UTF-8?q?https://github.com/YunaiV/ruoyi-vue-pro/issues/795?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/web/core/filter/CacheRequestBodyFilter.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java index ae7bfeca70..49958fc096 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/filter/CacheRequestBodyFilter.java @@ -23,7 +23,7 @@ public class CacheRequestBodyFilter extends OncePerRequestFilter { * 1. 排除 Spring Boot Admin 相关请求,避免客户端连接中断导致的异常。 * 例如说:795 ISSUE */ - private static final String[] IGNORE_URIS = {"/admin", "/actuator"}; + private static final String[] IGNORE_URIS = {"/admin/", "/actuator/"}; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) @@ -35,7 +35,7 @@ public class CacheRequestBodyFilter extends OncePerRequestFilter { protected boolean shouldNotFilter(HttpServletRequest request) { // 1. 校验是否为排除的 URL String requestURI = request.getRequestURI(); - if (StrUtil.containsAny(requestURI, IGNORE_URIS)) { + if (StrUtil.startWithAny(requestURI, IGNORE_URIS)) { return true; } From c25d1b37193f6985af7583723cb3c0c9e240e869 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 17:15:57 +0800 Subject: [PATCH 65/81] =?UTF-8?q?review=EF=BC=9A@InDict=20=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=EF=BC=8C=E4=BB=A5=E5=8F=8A=E7=9B=B8=E5=85=B3?= =?UTF-8?q?=E7=9A=84=E4=BD=BF=E7=94=A8=E6=A1=88=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iocoder/yudao/framework/dict/validation/InDict.java | 2 +- .../dict/validation/InDictCollectionValidator.java | 9 ++++++--- .../yudao/framework/dict/validation/InDictValidator.java | 5 +++-- .../admin/user/vo/user/UserUpdateStatusReqVO.java | 6 ++++-- 4 files changed, 14 insertions(+), 8 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java index dab0af782f..de7498775c 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDict.java @@ -25,7 +25,7 @@ import java.lang.annotation.Target; public @interface InDict { /** - * 数据字典type + * 数据字典 type */ String type(); diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java index ab036171e2..a7184b066a 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictCollectionValidator.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.dict.validation; -import cn.iocoder.yudao.framework.common.util.string.StrUtils; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; @@ -19,19 +19,22 @@ public class InDictCollectionValidator implements ConstraintValidator list, ConstraintValidatorContext context) { - if (list == null) { + // 为空时,默认不校验,即认为通过 + if (CollUtil.isEmpty(list)) { return true; } + // 校验全部通过 List dbValues = DictFrameworkUtils.getDictDataValueList(dictType); boolean match = list.stream().allMatch(v -> dbValues.stream() .anyMatch(dbValue -> dbValue.equalsIgnoreCase(v.toString()))); if (match) { return true; } + // 校验不通过,自定义提示语句 context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值 context.buildConstraintViolationWithTemplate( - context.getDefaultConstraintMessageTemplate().replaceAll("\\{value}",dbValues.toString()) + context.getDefaultConstraintMessageTemplate().replaceAll("\\{value}", dbValues.toString()) ).addConstraintViolation(); // 重新添加错误提示语句 return false; } diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java index 05f50cb839..b67f017750 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/dict/validation/InDictValidator.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.dict.validation; -import cn.iocoder.yudao.framework.common.util.string.StrUtils; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.dict.core.DictFrameworkUtils; import jakarta.validation.ConstraintValidator; import jakarta.validation.ConstraintValidatorContext; @@ -24,10 +24,11 @@ public class InDictValidator implements ConstraintValidator { } // 校验通过 final List values = DictFrameworkUtils.getDictDataValueList(dictType); - boolean match = values.stream().anyMatch(v -> v.equalsIgnoreCase(value.toString())); + boolean match = values.stream().anyMatch(v -> StrUtil.equalsIgnoreCase(v, value.toString())); if (match) { return true; } + // 校验不通过,自定义提示语句 context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值 context.buildConstraintViolationWithTemplate( diff --git a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java index ae03d18625..8e3e5db179 100644 --- a/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java +++ b/yudao-module-system/src/main/java/cn/iocoder/yudao/module/system/controller/admin/user/vo/user/UserUpdateStatusReqVO.java @@ -2,10 +2,11 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.user; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.dict.validation.InDict; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - import jakarta.validation.constraints.NotNull; +import lombok.Data; @Schema(description = "管理后台 - 用户更新状态 Request VO") @Data @@ -18,6 +19,7 @@ public class UserUpdateStatusReqVO { @Schema(description = "状态,见 CommonStatusEnum 枚举", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "状态不能为空") @InEnum(value = CommonStatusEnum.class, message = "修改状态必须是 {value}") + @InDict(type = DictTypeConstants.COMMON_STATUS) private Integer status; } From 8b2247f7f94ba0a60e92aafebb998e3409db7a6c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 17:16:07 +0800 Subject: [PATCH 66/81] =?UTF-8?q?=E5=90=8C=E6=AD=A5=20https://gitee.com/zh?= =?UTF-8?q?ijiantianya/ruoyi-vue-pro/pulls/1382/=20=E8=B4=A1=E7=8C=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/codegen/vue3/views/components/list_sub_erp.vue.vm | 1 + .../src/main/resources/codegen/vue3/views/index.vue.vm | 1 + 2 files changed, 2 insertions(+) diff --git a/yudao-module-infra/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm index c0dddc0767..f9fbb9787b 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3/views/components/list_sub_erp.vue.vm @@ -138,6 +138,7 @@ watch( () => props.${subJoinColumn.javaField}, (val: number) => { if (!val) { + list.value = [] // 清空列表 return } queryParams.${subJoinColumn.javaField} = val diff --git a/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm index f6ce0e50c7..851bc2b5e4 100644 --- a/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm +++ b/yudao-module-infra/src/main/resources/codegen/vue3/views/index.vue.vm @@ -353,6 +353,7 @@ const handleDelete = async (id: number) => { // 发起删除 await ${simpleClassName}Api.delete${simpleClassName}(id) message.success(t('common.delSuccess')) + currentRow.value = {} // 刷新列表 await getList() } catch {} From 1b412546eb9914d28fc394c8cc46f5c38d249a2e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 19:49:50 +0800 Subject: [PATCH 67/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90Mall=20=E5=95=86?= =?UTF-8?q?=E5=9F=8E=E3=80=91=E4=BF=AE=E5=A4=8D=E7=A7=AF=E5=88=86=E5=95=86?= =?UTF-8?q?=E5=93=81=E6=96=B0=E5=A2=9E=E6=97=B6=E6=A0=A1=E9=AA=8C=E5=95=86?= =?UTF-8?q?=E5=93=81=E6=98=AF=E5=90=A6=E5=8F=82=E4=B8=8E=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E6=B4=BB=E5=8A=A8=E6=A0=A1=E9=AA=8C=E5=A4=B1=E8=B4=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../promotion/service/point/PointActivityServiceImpl.java | 1 + .../core/client/dto/kd100/Kd100ExpressQueryRespDTO.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/point/PointActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/point/PointActivityServiceImpl.java index 582cadb0d4..0b945794ad 100644 --- a/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/point/PointActivityServiceImpl.java +++ b/yudao-module-mall/yudao-module-promotion/src/main/java/cn/iocoder/yudao/module/promotion/service/point/PointActivityServiceImpl.java @@ -222,6 +222,7 @@ public class PointActivityServiceImpl implements PointActivityService { if (spu == null) { throw exception(SPU_NOT_EXISTS); } + products.forEach(product -> product.setSpuId(spuId)); // 2. 校验商品 sku 都存在 List skus = productSkuApi.getSkuListBySpuId(singletonList(spuId)); diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java index 0cf5c96caa..d5442cbeeb 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/client/dto/kd100/Kd100ExpressQueryRespDTO.java @@ -2,10 +2,11 @@ package cn.iocoder.yudao.module.trade.framework.delivery.core.client.dto.kd100; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; import lombok.Data; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; From 77193102a2038fafb71e03ac31e680257c40af75 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 20:08:04 +0800 Subject: [PATCH 68/81] =?UTF-8?q?feat=EF=BC=9A=E6=B7=BB=E5=8A=A0=E8=87=AA?= =?UTF-8?q?=E9=80=82=E5=BA=94=E5=88=97=E5=AE=BD=E5=A4=84=E7=90=86=E5=99=A8?= =?UTF-8?q?=E5=B9=B6=E6=9B=BF=E6=8D=A2=E9=BB=98=E8=AE=A4=E5=88=97=E5=AE=BD?= =?UTF-8?q?=E7=AD=96=E7=95=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ColumnWidthMatchStyleStrategy.java | 78 +++++++++++++++++++ .../core/handler/SelectSheetWriteHandler.java | 2 +- .../framework/excel/core/util/ExcelUtils.java | 14 ++-- .../yudao/framework/excel/package-info.java | 2 +- 4 files changed, 87 insertions(+), 9 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java new file mode 100644 index 0000000000..49a5b31572 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/ColumnWidthMatchStyleStrategy.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.framework.excel.core.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.idev.excel.enums.CellDataTypeEnum; +import cn.idev.excel.metadata.Head; +import cn.idev.excel.metadata.data.WriteCellData; +import cn.idev.excel.util.MapUtils; +import cn.idev.excel.write.metadata.holder.WriteSheetHolder; +import cn.idev.excel.write.style.column.AbstractColumnWidthStyleStrategy; +import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import org.apache.poi.ss.usermodel.Cell; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Excel 自适应列宽处理器 + * + * 相比 {@link LongestMatchColumnWidthStyleStrategy} 来说,额外处理了 DATE 类型! + * + * @see 添加自适应列宽处理器,并替换默认列宽策略 + * @author hmb + */ +public class ColumnWidthMatchStyleStrategy extends AbstractColumnWidthStyleStrategy { + + private static final int MAX_COLUMN_WIDTH = 255; + + private final Map> cache = MapUtils.newHashMapWithExpectedSize(8); + + @Override + protected void setColumnWidth(WriteSheetHolder writeSheetHolder, List> cellDataList, Cell cell, + Head head, Integer relativeRowIndex, Boolean isHead) { + boolean needSetWidth = isHead || CollUtil.isNotEmpty(cellDataList); + if (!needSetWidth) { + return; + } + Map maxColumnWidthMap = cache.computeIfAbsent(writeSheetHolder.getSheetNo(), + key -> new HashMap<>(16)); + Integer columnWidth = dataLength(cellDataList, cell, isHead); + if (columnWidth < 0) { + return; + } + if (columnWidth > MAX_COLUMN_WIDTH) { + columnWidth = MAX_COLUMN_WIDTH; + } + Integer maxColumnWidth = maxColumnWidthMap.get(cell.getColumnIndex()); + if (maxColumnWidth == null || columnWidth > maxColumnWidth) { + maxColumnWidthMap.put(cell.getColumnIndex(), columnWidth); + writeSheetHolder.getSheet().setColumnWidth(cell.getColumnIndex(), columnWidth * 256); + } + } + + @SuppressWarnings("EnhancedSwitchMigration") + private Integer dataLength(List> cellDataList, Cell cell, Boolean isHead) { + if (isHead) { + return cell.getStringCellValue().getBytes().length; + } + WriteCellData cellData = cellDataList.get(0); + CellDataTypeEnum type = cellData.getType(); + if (type == null) { + return -1; + } + switch (type) { + case STRING: + return cellData.getStringValue().getBytes().length; + case BOOLEAN: + return cellData.getBooleanValue().toString().getBytes().length; + case NUMBER: + return cellData.getNumberValue().toString().getBytes().length; + case DATE: + return cellData.getDateValue().toString().getBytes().length; + default: + return -1; + } + } + +} \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java index cd6c87f68f..c55e1210a2 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/handler/SelectSheetWriteHandler.java @@ -86,7 +86,7 @@ public class SelectSheetWriteHandler implements SheetWriteHandler { /** * 判断字段是否是静态的、最终的、 transient 的 - * 原因:EasyExcel 默认是忽略 static final 或 transient 的字段,所以需要判断 + * 原因:FastExcel 默认是忽略 static final 或 transient 的字段,所以需要判断 * * @param field 字段 * @return 是否是静态的、最终的、transient 的 diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java index bae20d6c53..f05d3e51e5 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/core/util/ExcelUtils.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.framework.excel.core.util; -import cn.iocoder.yudao.framework.common.util.http.HttpUtils; -import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; -import cn.idev.excel.EasyExcel; +import cn.idev.excel.FastExcelFactory; import cn.idev.excel.converters.longconverter.LongStringConverter; -import cn.idev.excel.write.style.column.LongestMatchColumnWidthStyleStrategy; +import cn.iocoder.yudao.framework.common.util.http.HttpUtils; +import cn.iocoder.yudao.framework.excel.core.handler.ColumnWidthMatchStyleStrategy; +import cn.iocoder.yudao.framework.excel.core.handler.SelectSheetWriteHandler; import jakarta.servlet.http.HttpServletResponse; import org.springframework.web.multipart.MultipartFile; @@ -32,9 +32,9 @@ public class ExcelUtils { public static void write(HttpServletResponse response, String filename, String sheetName, Class head, List data) throws IOException { // 输出 Excel - EasyExcel.write(response.getOutputStream(), head) + FastExcelFactory.write(response.getOutputStream(), head) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 - .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 + .registerWriteHandler(new ColumnWidthMatchStyleStrategy()) // 基于 column 长度,自动适配。最大 255 宽度 .registerWriteHandler(new SelectSheetWriteHandler(head)) // 基于固定 sheet 实现下拉框 .registerConverter(new LongStringConverter()) // 避免 Long 类型丢失精度 .sheet(sheetName).doWrite(data); @@ -44,7 +44,7 @@ public class ExcelUtils { } public static List read(MultipartFile file, Class head) throws IOException { - return EasyExcel.read(file.getInputStream(), head, null) + return FastExcelFactory.read(file.getInputStream(), head, null) .autoCloseStream(false) // 不要自动关闭,交给 Servlet 自己处理 .doReadAllSync(); } diff --git a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java index 53bc5c01bf..72c3ac42e1 100644 --- a/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java +++ b/yudao-framework/yudao-spring-boot-starter-excel/src/main/java/cn/iocoder/yudao/framework/excel/package-info.java @@ -1,4 +1,4 @@ /** - * 基于 EasyExcel 实现 Excel 相关的操作 + * 基于 FastExcel 实现 Excel 相关的操作 */ package cn.iocoder.yudao.framework.excel; From 99442ec05c29b8839dbf796628bad7f72b2b99da Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 21:21:02 +0800 Subject: [PATCH 69/81] =?UTF-8?q?fix=EF=BC=9AApiErrorLogServiceImpl=20?= =?UTF-8?q?=E5=9C=A8=E5=BE=AE=E6=9C=8D=E5=8A=A1=E5=9C=BA=E6=99=AF=E4=B8=8B?= =?UTF-8?q?=EF=BC=8C=E8=AE=B0=E5=BD=95=E6=97=A5=E5=BF=97=E5=AD=98=E5=9C=A8?= =?UTF-8?q?=E7=9A=84=E5=BE=AA=E7=8E=AF=E8=B0=83=E7=94=A8=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/logger/ApiErrorLogServiceImpl.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java index e91c098941..536b265f93 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/logger/ApiErrorLogServiceImpl.java @@ -40,11 +40,16 @@ public class ApiErrorLogServiceImpl implements ApiErrorLogService { ApiErrorLogDO apiErrorLog = BeanUtils.toBean(createDTO, ApiErrorLogDO.class) .setProcessStatus(ApiErrorLogProcessStatusEnum.INIT.getStatus()); apiErrorLog.setRequestParams(StrUtils.maxLength(apiErrorLog.getRequestParams(), REQUEST_PARAMS_MAX_LENGTH)); - if (TenantContextHolder.getTenantId() != null) { - apiErrorLogMapper.insert(apiErrorLog); - } else { - // 极端情况下,上下文中没有租户时,此时忽略租户上下文,避免插入失败! - TenantUtils.executeIgnore(() -> apiErrorLogMapper.insert(apiErrorLog)); + try { + if (TenantContextHolder.getTenantId() != null) { + apiErrorLogMapper.insert(apiErrorLog); + } else { + // 极端情况下,上下文中没有租户时,此时忽略租户上下文,避免插入失败! + TenantUtils.executeIgnore(() -> apiErrorLogMapper.insert(apiErrorLog)); + } + } catch (Exception ex) { + // 兜底处理,目前只有 yudao-cloud 会发生:https://gitee.com/yudaocode/yudao-cloud-mini/issues/IC1O0A + log.error("[createApiErrorLog][记录时({}) 发生异常]", createDTO, ex); } } From bf5ac4ede2ef8e0ba9736cff74c571d05baad981 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 21:30:16 +0800 Subject: [PATCH 70/81] =?UTF-8?q?feat=EF=BC=9ACacheUtils=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20CACHE=5FMAX=5FSIZE=20=E9=BB=98=E8=AE=A4=E5=A4=A7?= =?UTF-8?q?=E5=B0=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/common/util/cache/CacheUtils.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java index 12a6e17246..4d9168ebdb 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/cache/CacheUtils.java @@ -14,6 +14,13 @@ import java.util.concurrent.Executors; */ public class CacheUtils { + /** + * 异步刷新的 LoadingCache 最大缓存数量 + * + * @see 本地缓存 CacheUtils 工具类建议 + */ + private static final Integer CACHE_MAX_SIZE = 10000; + /** * 构建异步刷新的 LoadingCache 对象 * @@ -29,6 +36,7 @@ public class CacheUtils { */ public static LoadingCache buildAsyncReloadingCache(Duration duration, CacheLoader loader) { return CacheBuilder.newBuilder() + .maximumSize(CACHE_MAX_SIZE) // 只阻塞当前数据加载线程,其他线程返回旧值 .refreshAfterWrite(duration) // 通过 asyncReloading 实现全异步加载,包括 refreshAfterWrite 被阻塞的加载线程 @@ -43,7 +51,11 @@ public class CacheUtils { * @return LoadingCache 对象 */ public static LoadingCache buildCache(Duration duration, CacheLoader loader) { - return CacheBuilder.newBuilder().refreshAfterWrite(duration).build(loader); + return CacheBuilder.newBuilder() + .maximumSize(CACHE_MAX_SIZE) + // 只阻塞当前数据加载线程,其他线程返回旧值 + .refreshAfterWrite(duration) + .build(loader); } } From 4a8c485b920d024112ba623f578828d8206e577a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 26 Jul 2025 23:06:21 +0800 Subject: [PATCH 71/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E6=9D=83=E9=99=90=E3=80=91=E5=BC=BA=E5=88=B6=E9=9C=80=E8=A6=81?= =?UTF-8?q?=20PermissionCommonApi?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/YudaoDeptDataPermissionAutoConfiguration.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java index ab5b3bc7ec..46b6ca7c59 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-biz-data-permission/src/main/java/cn/iocoder/yudao/framework/datapermission/config/YudaoDeptDataPermissionAutoConfiguration.java @@ -18,7 +18,7 @@ import java.util.List; */ @AutoConfiguration @ConditionalOnClass(LoginUser.class) -@ConditionalOnBean(value = {PermissionCommonApi.class, DeptDataPermissionRuleCustomizer.class}) +@ConditionalOnBean(value = {DeptDataPermissionRuleCustomizer.class}) public class YudaoDeptDataPermissionAutoConfiguration { @Bean From 47ff2bf9225ae31b89c44e6f5de3415d9fb07820 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 27 Jul 2025 10:11:39 +0800 Subject: [PATCH 72/81] =?UTF-8?q?fix=EF=BC=9AXss=20=E5=BC=80=E5=90=AF?= =?UTF-8?q?=E4=B8=8D=E7=94=9F=E6=95=88=E7=9A=84=E9=97=AE=E9=A2=98=20https:?= =?UTF-8?q?//t.zsxq.com/qq02q?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/xss/config/YudaoXssAutoConfiguration.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java index 99b6a448f3..16f87dae1f 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/xss/config/YudaoXssAutoConfiguration.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.xss.core.clean.JsoupXssCleaner; import cn.iocoder.yudao.framework.xss.core.clean.XssCleaner; import cn.iocoder.yudao.framework.xss.core.filter.XssFilter; import cn.iocoder.yudao.framework.xss.core.json.XssStringJsonDeserializer; -import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.boot.autoconfigure.AutoConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; @@ -42,13 +41,13 @@ public class YudaoXssAutoConfiguration implements WebMvcConfigurer { */ @Bean @ConditionalOnMissingBean(name = "xssJacksonCustomizer") - @ConditionalOnBean(ObjectMapper.class) @ConditionalOnProperty(value = "yudao.xss.enable", havingValue = "true") public Jackson2ObjectMapperBuilderCustomizer xssJacksonCustomizer(XssProperties properties, PathMatcher pathMatcher, XssCleaner xssCleaner) { // 在反序列化时进行 xss 过滤,可以替换使用 XssStringJsonSerializer,在序列化时进行处理 - return builder -> builder.deserializerByType(String.class, new XssStringJsonDeserializer(properties, pathMatcher, xssCleaner)); + return builder -> + builder.deserializerByType(String.class, new XssStringJsonDeserializer(properties, pathMatcher, xssCleaner)); } /** From ae9e35f184614da50f15399c7fe52c5f9413e61b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 27 Jul 2025 11:04:19 +0800 Subject: [PATCH 73/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90infra=20=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E8=AE=BE=E6=96=BD=E3=80=91=E4=BC=98=E5=8C=96=20vben3?= =?UTF-8?q?=20=E6=A8=A1=E7=89=88=E8=B7=AF=E5=BE=84=EF=BC=8C=E4=B8=8D?= =?UTF-8?q?=E5=9C=A8=E4=BD=BF=E7=94=A8=20vue3=20=E9=81=BF=E5=85=8D?= =?UTF-8?q?=E8=AF=AF=E8=A7=A3=20https://github.com/yudaocode/yudao-ui-admi?= =?UTF-8?q?n-vben/issues/60?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/codegen/inner/CodegenEngine.java | 81 ++++++++++--------- 1 file changed, 43 insertions(+), 38 deletions(-) diff --git a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java index b69f0c6254..a0ce062cdc 100644 --- a/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java +++ b/yudao-module-infra/src/main/java/cn/iocoder/yudao/module/infra/service/codegen/inner/CodegenEngine.java @@ -139,85 +139,85 @@ public class CodegenEngine { vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // VUE3_VBEN2_ANTD_SCHEMA .put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/${classNameVar}.data.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/${simpleClassName}Modal.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN2_ANTD_SCHEMA.getType(), vue3VbenTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) + vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) // VUE3_VBEN5_ANTD_SCHEMA .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/data.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) + vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_SCHEMA.getType(), vue3Vben5AntdSchemaTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) // VUE3_VBEN5_ANTD .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) + vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_ANTD_GENERAL.getType(), vue3Vben5AntdGeneralTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) // VUE3_VBEN5_EP_SCHEMA .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/data.ts"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/data.ts")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/data.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) + vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_SCHEMA.getType(), vue3Vben5EpSchemaTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) // VUE3_VBEN5_EP .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/index.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/index.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/index.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/form.vue"), - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("api/api.ts"), - vue3FilePath("api/${table.moduleName}/${table.businessName}/index.ts")) + vue3VbenFilePath("api/${table.moduleName}/${table.businessName}/index.ts")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/modules/form_sub_normal.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/modules/form_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/modules/form_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-form.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/modules/list_sub_inner.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) .put(CodegenFrontTypeEnum.VUE3_VBEN5_EP_GENERAL.getType(), vue3Vben5EpGeneralTemplatePath("views/modules/list_sub_erp.vue"), // 特殊:主子表专属逻辑 - vue3FilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) + vue3VbenFilePath("views/${table.moduleName}/${table.businessName}/modules/${subSimpleClassName_strikeCase}-list.vue")) .build(); @Resource @@ -614,6 +614,11 @@ public class CodegenEngine { "src/" + path; } + private static String vue3VbenFilePath(String path) { + return "yudao-ui-${sceneEnum.basePackage}-vben/" + // 顶级目录 + "src/" + path; + } + private static String vue3VbenTemplatePath(String path) { return "codegen/vue3_vben/" + path + ".vm"; } From 8ffe9272e80ec9b07fce6b29d8f041bc5ac7a01b Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 27 Jul 2025 19:18:04 +0800 Subject: [PATCH 74/81] =?UTF-8?q?feat=EF=BC=9A=E3=80=90pay=20=E6=94=AF?= =?UTF-8?q?=E4=BB=98=E3=80=91=E5=A2=9E=E5=8A=A0=20userid=E3=80=81usertype?= =?UTF-8?q?=EF=BC=8C=E5=B9=B6=E9=A2=9D=E5=A4=96=E6=94=AF=E6=8C=81=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=A0=A1=E9=AA=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../convert/aftersale/AfterSaleConvert.java | 2 +- .../convert/order/TradeOrderConvert.java | 4 ++- .../aftersale/AfterSaleServiceImpl.java | 2 ++ .../BrokerageWithdrawServiceImpl.java | 1 + .../order/TradeOrderUpdateServiceImpl.java | 1 + .../api/order/dto/PayOrderCreateReqDTO.java | 13 +++++++ .../api/refund/dto/PayRefundCreateReqDTO.java | 13 +++++++ .../transfer/dto/PayTransferCreateReqDTO.java | 35 +++++++++++++------ .../admin/demo/PayDemoWithdrawController.java | 3 +- .../app/order/AppPayOrderController.java | 13 +++++-- .../pay/convert/order/PayOrderConvert.java | 5 +-- .../pay/dal/dataobject/order/PayOrderDO.java | 9 +++++ .../dal/dataobject/refund/PayRefundDO.java | 9 +++++ .../dataobject/transfer/PayTransferDO.java | 12 +++++-- .../service/demo/PayDemoOrderServiceImpl.java | 3 ++ .../service/demo/PayDemoWithdrawService.java | 3 +- .../demo/PayDemoWithdrawServiceImpl.java | 4 ++- .../wallet/PayWalletRechargeServiceImpl.java | 4 +-- .../src/test/resources/sql/clean.sql | 1 + .../src/test/resources/sql/create_tables.sql | 33 +++++++++++++++++ 20 files changed, 143 insertions(+), 27 deletions(-) diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java index 54480f696b..0e508a4643 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java @@ -43,7 +43,7 @@ public interface AfterSaleConvert { @Mapping(source = "afterSale.id", target = "merchantRefundId"), @Mapping(source = "afterSale.applyReason", target = "reason"), @Mapping(source = "afterSale.refundPrice", target = "price"), - @Mapping(source = "orderProperties.payAppKey", target = "appKey") + @Mapping(source = "orderProperties.payAppKey", target = "appKey"), }) PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale, TradeOrderProperties orderProperties); diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java index fa0b9c8163..beacddab87 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/convert/order/TradeOrderConvert.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.trade.convert.order; import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.string.StrUtils; @@ -101,7 +102,8 @@ public interface TradeOrderConvert { default PayOrderCreateReqDTO convert(TradeOrderDO order, List orderItems, TradeOrderProperties orderProperties) { PayOrderCreateReqDTO createReqDTO = new PayOrderCreateReqDTO() - .setAppKey(orderProperties.getPayAppKey()).setUserIp(order.getUserIp()); + .setAppKey(orderProperties.getPayAppKey()).setUserIp(order.getUserIp()) + .setUserId(order.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue()); // 商户相关字段 createReqDTO.setMerchantOrderId(String.valueOf(order.getId())); String subject = orderItems.get(0).getSpuName(); diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java index f0c63a032d..7be62fc78d 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.aftersale; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.pay.api.refund.PayRefundApi; @@ -362,6 +363,7 @@ public class AfterSaleServiceImpl implements AfterSaleService { private void createPayRefund(String userIp, AfterSaleDO afterSale) { // 创建退款单 PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties) + .setUserId(afterSale.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue()) .setReason(StrUtil.format("退款【{}】", afterSale.getSpuName())); Long payRefundId = payRefundApi.createRefund(createReqDTO); diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java index a873927f6c..fcadac827a 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java @@ -151,6 +151,7 @@ public class BrokerageWithdrawServiceImpl implements BrokerageWithdrawService { .setAppKey(tradeOrderProperties.getPayAppKey()).setChannelCode(channelCode) .setMerchantTransferId(withdraw.getId().toString()).setSubject("佣金提现").setPrice(withdraw.getPrice()) .setUserAccount(userAccount).setUserName(userName).setUserIp(getClientIP()) + .setUserId(withdraw.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue()) // 用户信息 .setChannelExtras(channelExtras); // 1.3 发起请求 PayTransferCreateRespDTO transferRespDTO = payTransferApi.createTransfer(transferReqDTO); diff --git a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java index bafe56c5be..690f3de52c 100644 --- a/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java @@ -952,6 +952,7 @@ public class TradeOrderUpdateServiceImpl implements TradeOrderUpdateService { payRefundApi.createRefund(new PayRefundCreateReqDTO() .setAppKey(tradeOrderProperties.getPayAppKey()) // 支付应用 .setUserIp(NetUtil.getLocalhostStr()) // 使用本机 IP,因为是服务器发起退款的 + .setUserId(order.getUserId()).setUserType(UserTypeEnum.MEMBER.getValue()) // 用户信息 .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号 // 特殊:因为订单支持 AfterSale 单个售后退款,也支持整单退款,所以需要通过 order- 进行下区分 // 具体可见 AfterSaleController 的 updateAfterSaleRefunded 方法 diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java index 3a7b181be3..a2f035cddd 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderCreateReqDTO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.pay.api.order.dto; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import jakarta.validation.constraints.DecimalMin; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -22,12 +24,23 @@ public class PayOrderCreateReqDTO implements Serializable { */ @NotNull(message = "应用标识不能为空") private String appKey; + /** * 用户 IP */ @NotEmpty(message = "用户 IP 不能为空") private String userIp; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + @InEnum(UserTypeEnum.class) + private Integer userType; + // ========== 商户相关字段 ========== /** diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java index 6910fc2fe5..cc1743be64 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundCreateReqDTO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.pay.api.refund.dto; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -19,12 +21,23 @@ public class PayRefundCreateReqDTO { */ @NotNull(message = "应用标识不能为空") private String appKey; + /** * 用户 IP */ @NotEmpty(message = "用户 IP 不能为空") private String userIp; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + @InEnum(UserTypeEnum.class) + private Integer userType; + // ========== 商户相关字段 ========== /** * 商户订单编号 diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java index 1ac5c04af6..86dd70cce5 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.pay.api.transfer.dto; import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.common.validation.InEnum; import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -26,23 +28,23 @@ public class PayTransferCreateReqDTO { @NotNull(message = "应用标识不能为空") private String appKey; - /** - * 转账渠道 - */ - @NotEmpty(message = "转账渠道不能为空") - private String channelCode; - - /** - * 转账渠道的额外参数 - */ - private Map channelExtras; - /** * 用户 IP */ @NotEmpty(message = "用户 IP 不能为空") private String userIp; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + @InEnum(UserTypeEnum.class) + private Integer userType; + + // ========== 商户相关字段 ========== /** * 商户转账单编号 */ @@ -75,6 +77,17 @@ public class PayTransferCreateReqDTO { */ private String userName; + /** + * 转账渠道 + */ + @NotEmpty(message = "转账渠道不能为空") + private String channelCode; + + /** + * 转账渠道的额外参数 + */ + private Map channelExtras; + /** * 【微信】现金营销场景 * diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.java index 033bc95d79..ef5e4a8a9c 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoWithdrawController.java @@ -19,6 +19,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 示例提现订单") // 目的:演示转账功能 @RestController @@ -40,7 +41,7 @@ public class PayDemoWithdrawController { @Operation(summary = "提现单转账") @Parameter(name = "id", required = true, description = "提现单编号", example = "1024") public CommonResult transferDemoWithdraw(@RequestParam("id") Long id) { - Long payTransferId = demoWithdrawService.transferDemoWithdraw(id); + Long payTransferId = demoWithdrawService.transferDemoWithdraw(id, getLoginUserId()); return success(payTransferId); } diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java index 88eeb0960a..4f57163841 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.pay.controller.app.order; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderRespVO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.PayOrderSubmitRespVO; import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitReqVO; import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; -import cn.iocoder.yudao.module.pay.convert.order.PayOrderConvert; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.wallet.PayWalletDO; import cn.iocoder.yudao.module.pay.enums.PayChannelEnum; @@ -52,6 +52,15 @@ public class AppPayOrderController { public CommonResult getOrder(@RequestParam("id") Long id, @RequestParam(value = "sync", required = false) Boolean sync) { PayOrderDO order = payOrderService.getOrder(id); + if (order== null) { + return success(null); + } + // 重要:校验订单是否是当前用户,避免越权 + if (order.getUserId() != null // 特殊:早期订单未存储 userId,所以忽略 + && ObjUtil.notEqual(order.getUserId(), getLoginUserId())) { + return success(null); + } + // sync 仅在等待支付 if (Boolean.TRUE.equals(sync) && PayOrderStatusEnum.isWaiting(order.getStatus())) { payOrderService.syncOrderQuietly(order.getId()); @@ -75,7 +84,7 @@ public class AppPayOrderController { // 2. 提交支付 PayOrderSubmitRespVO respVO = payOrderService.submitOrder(reqVO, getClientIP()); - return success(PayOrderConvert.INSTANCE.convert3(respVO)); + return success(BeanUtils.toBean(respVO, AppPayOrderSubmitRespVO.class)); } } diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java index 8321de32ce..1813e2c2d7 100755 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/convert/order/PayOrderConvert.java @@ -3,14 +3,13 @@ package cn.iocoder.yudao.module.pay.convert.order; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderCreateReqDTO; import cn.iocoder.yudao.module.pay.api.order.dto.PayOrderRespDTO; import cn.iocoder.yudao.module.pay.controller.admin.order.vo.*; -import cn.iocoder.yudao.module.pay.controller.app.order.vo.AppPayOrderSubmitRespVO; import cn.iocoder.yudao.module.pay.dal.dataobject.app.PayAppDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderDO; import cn.iocoder.yudao.module.pay.dal.dataobject.order.PayOrderExtensionDO; +import cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderUnifiedReqDTO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; @@ -69,6 +68,4 @@ public interface PayOrderConvert { @Mapping(source = "order.status", target = "status") PayOrderSubmitRespVO convert(PayOrderDO order, cn.iocoder.yudao.module.pay.framework.pay.core.client.dto.order.PayOrderRespDTO respDTO); - AppPayOrderSubmitRespVO convert3(PayOrderSubmitRespVO bean); - } diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java index ac0ef34f2e..4eea1cc4ef 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/order/PayOrderDO.java @@ -49,6 +49,15 @@ public class PayOrderDO extends BaseDO { */ private String channelCode; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + private Integer userType; + // ========== 商户相关字段 ========== /** diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java index 607483f91a..0804926820 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/refund/PayRefundDO.java @@ -77,6 +77,15 @@ public class PayRefundDO extends BaseDO { */ private String orderNo; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + private Integer userType; + // ========== 商户相关字段 ========== /** * 商户订单编号 diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java index 94f8521dbd..d0f3a80211 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java @@ -30,7 +30,6 @@ public class PayTransferDO extends BaseDO { */ @TableId private Long id; - /** * 转账单号 */ @@ -42,14 +41,12 @@ public class PayTransferDO extends BaseDO { * 关联 {@link PayAppDO#getId()} */ private Long appId; - /** * 转账渠道编号 * * 关联 {@link PayChannelDO#getId()} */ private Long channelId; - /** * 转账渠道编码 * @@ -57,6 +54,15 @@ public class PayTransferDO extends BaseDO { */ private String channelCode; + /** + * 用户编号 + */ + private Long userId; + /** + * 用户类型 + */ + private Integer userType; + // ========== 商户相关字段 ========== /** * 商户转账单编号 diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java index 76571f355c..ac756f5763 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.pay.service.demo; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; @@ -90,6 +91,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { // 2.1 创建支付单 Long payOrderId = payOrderApi.createOrder(new PayOrderCreateReqDTO() .setAppKey(PAY_APP_KEY).setUserIp(getClientIP()) // 支付应用 + .setUserId(userId).setUserType(UserTypeEnum.ADMIN.getValue()) // 用户信息 .setMerchantOrderId(demoOrder.getId().toString()) // 业务的订单编号 .setSubject(spuName).setBody("").setPrice(price) // 价格信息 .setExpireTime(addTime(Duration.ofHours(2L)))); // 支付的过期时间 @@ -189,6 +191,7 @@ public class PayDemoOrderServiceImpl implements PayDemoOrderService { // 2.2 创建退款单 Long payRefundId = payRefundApi.createRefund(new PayRefundCreateReqDTO() .setAppKey(PAY_APP_KEY).setUserIp(getClientIP()) // 支付应用 + .setUserId(order.getUserId()).setUserType(UserTypeEnum.ADMIN.getValue()) // 用户信息 .setMerchantOrderId(String.valueOf(order.getId())) // 支付单号 .setMerchantRefundId(refundId) .setReason("想退钱").setPrice(order.getPrice()));// 价格信息 diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawService.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawService.java index e8a5980ad8..6b55810257 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawService.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawService.java @@ -26,9 +26,10 @@ public interface PayDemoWithdrawService { * 提现单转账 * * @param id 提现单编号 + * @param userId 用户编号 * @return 转账编号 */ - Long transferDemoWithdraw(Long id); + Long transferDemoWithdraw(Long id, Long userId); /** * 获得示例提现单分页 diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawServiceImpl.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawServiceImpl.java index b1a3b91516..dddbceea0f 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawServiceImpl.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoWithdrawServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.pay.service.demo; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; @@ -60,7 +61,7 @@ public class PayDemoWithdrawServiceImpl implements PayDemoWithdrawService { } @Override - public Long transferDemoWithdraw(Long id) { + public Long transferDemoWithdraw(Long id, Long userId) { // 1.1 校验提现单 PayDemoWithdrawDO withdraw = validateDemoWithdrawCanTransfer(id); // 1.2 特殊:如果是转账失败的情况,需要充值下 @@ -76,6 +77,7 @@ public class PayDemoWithdrawServiceImpl implements PayDemoWithdrawService { // 2.1 创建支付单 PayTransferCreateReqDTO transferReqDTO = new PayTransferCreateReqDTO() .setAppKey(PAY_APP_KEY).setChannelCode(withdraw.getTransferChannelCode()).setUserIp(getClientIP()) // 支付应用 + .setUserId(userId).setUserType(UserTypeEnum.ADMIN.getValue()) // 用户信息 .setMerchantTransferId(String.valueOf(withdraw.getId())) // 业务的订单编号 .setSubject(withdraw.getSubject()).setPrice(withdraw.getPrice()) // 价格信息 .setUserAccount(withdraw.getUserAccount()).setUserName(withdraw.getUserName()); // 收款信息 diff --git a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java index f1253f4765..95539b28d5 100644 --- a/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java +++ b/yudao-module-pay/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java @@ -64,8 +64,6 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { private PayWalletService payWalletService; @Resource private PayOrderService payOrderService; -// @Resource -// private PayRefundService payRefundService; @Resource private PayWalletRechargePackageService payWalletRechargePackageService; @@ -99,6 +97,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { // 2.1 创建支付单 Long payOrderId = payOrderService.createOrder(new PayOrderCreateReqDTO() .setAppKey(payProperties.getWalletPayAppKey()).setUserIp(userIp) + .setUserId(userId).setUserType(userType) // 用户信息 .setMerchantOrderId(recharge.getId().toString()) // 业务的订单编号 .setSubject(WALLET_RECHARGE_ORDER_SUBJECT).setBody("") .setPrice(recharge.getPayPrice()) @@ -209,6 +208,7 @@ public class PayWalletRechargeServiceImpl implements PayWalletRechargeService { String refundId = walletRechargeId + "-refund"; Long payRefundId = payRefundApi.createRefund(new PayRefundCreateReqDTO() .setAppKey(payProperties.getWalletPayAppKey()).setUserIp(userIp) + .setUserId(wallet.getUserId()).setUserType(wallet.getUserType()) // 用户信息 .setMerchantOrderId(walletRechargeId) .setMerchantRefundId(refundId) .setReason("想退钱").setPrice(walletRecharge.getPayPrice())); diff --git a/yudao-module-pay/src/test/resources/sql/clean.sql b/yudao-module-pay/src/test/resources/sql/clean.sql index 91fff0caee..e7bf56bfa4 100644 --- a/yudao-module-pay/src/test/resources/sql/clean.sql +++ b/yudao-module-pay/src/test/resources/sql/clean.sql @@ -3,5 +3,6 @@ DELETE FROM pay_channel; DELETE FROM pay_order; DELETE FROM pay_order_extension; DELETE FROM pay_refund; +DELETE FROM pay_transfer; DELETE FROM pay_notify_task; DELETE FROM pay_notify_log; diff --git a/yudao-module-pay/src/test/resources/sql/create_tables.sql b/yudao-module-pay/src/test/resources/sql/create_tables.sql index 3f9f764179..6af612f018 100644 --- a/yudao-module-pay/src/test/resources/sql/create_tables.sql +++ b/yudao-module-pay/src/test/resources/sql/create_tables.sql @@ -45,6 +45,8 @@ CREATE TABLE IF NOT EXISTS `pay_order` ( `channel_fee_price` bigint(20) DEFAULT 0, `status` tinyint(4) NOT NULL, `user_ip` varchar(50) NOT NULL, + `user_id` bigint(20) DEFAULT NULL, + `user_type` tinyint(4) DEFAULT NULL, `expire_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `success_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, `notify_time` datetime(0) DEFAULT CURRENT_TIMESTAMP, @@ -97,6 +99,8 @@ CREATE TABLE IF NOT EXISTS `pay_refund` ( `refund_price` bigint(20) NOT NULL, `reason` varchar(256) NOT NULL, `user_ip` varchar(50) NULL DEFAULT NULL, + `user_id` bigint(20) NULL DEFAULT NULL, + `user_type` tinyint(4) NULL DEFAULT NULL, `channel_order_no` varchar(64) NOT NULL, `channel_refund_no` varchar(64) NULL DEFAULT NULL, `success_time` datetime(0) NULL DEFAULT NULL, @@ -145,3 +149,32 @@ CREATE TABLE IF NOT EXISTS `pay_notify_log` ( `deleted` bit(1) NOT NULL DEFAULT FALSE, PRIMARY KEY ("id") ) COMMENT = '支付通知日志'; + +CREATE TABLE IF NOT EXISTS `pay_transfer` ( + "id" number NOT NULL GENERATED BY DEFAULT AS IDENTITY, + `no` varchar(64) NOT NULL, + `app_id` bigint(20) NOT NULL, + `channel_id` bigint(20) NOT NULL, + `channel_code` varchar(32) NOT NULL, + `user_id` bigint(20) NULL DEFAULT NULL, + `user_type` tinyint(4) NULL DEFAULT NULL, + `merchant_transfer_id` varchar(64) NOT NULL, + `price` bigint(20) NOT NULL, + `subject` varchar(256) NOT NULL, + `user_account` varchar(256) NOT NULL, + `user_name` varchar(64) NULL DEFAULT NULL, + `status` tinyint(4) NOT NULL, + `notify_url` varchar(1024) NULL DEFAULT NULL, + `channel_transfer_no` varchar(64) NULL DEFAULT NULL, + `success_time` datetime(0) NULL DEFAULT NULL, + `channel_error_code` varchar(128) NULL DEFAULT NULL, + `channel_error_msg` varchar(256) NULL DEFAULT NULL, + `channel_notify_data` varchar(1024) NULL DEFAULT NULL, + `channel_extras` varchar(1024) NULL DEFAULT NULL, + `creator` varchar(64) NULL DEFAULT '', + `create_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updater` varchar(64) NULL DEFAULT '', + `update_time` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `deleted` bit(1) NOT NULL DEFAULT FALSE, + PRIMARY KEY ("id") +) COMMENT = '转账单'; From 1684706e9aa70df8675b4b6bba212b7f5541d078 Mon Sep 17 00:00:00 2001 From: jason <2667446@qq.com> Date: Tue, 29 Jul 2025 09:36:53 +0800 Subject: [PATCH 75/81] =?UTF-8?q?feat:=20[BPM=20=E5=B7=A5=E4=BD=9C?= =?UTF-8?q?=E6=B5=81]=20=E5=A2=9E=E5=8A=A0=E8=B7=B3=E8=BF=87=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E5=88=A4=E6=96=AD=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/model/simple/BpmSimpleModelNodeVO.java | 3 ++ .../bpm/enums/task/BpmTaskStatusEnum.java | 2 +- .../flowable/core/util/BpmnModelUtils.java | 30 +++++++++++++++++-- .../flowable/core/util/SimpleModelUtils.java | 18 ++++++++++- .../task/BpmProcessInstanceServiceImpl.java | 26 +++++++++++++--- 5 files changed, 71 insertions(+), 8 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java index 1cbebe06e4..4d34df8308 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/vo/model/simple/BpmSimpleModelNodeVO.java @@ -71,6 +71,9 @@ public class BpmSimpleModelNodeVO { @Schema(description = "是否填写审批意见", example = "false") private Boolean reasonRequire; + @Schema(description = "跳过表达式", example = "{true}") + private String skipExpression; // 用于审批节点 + /** * 审批节点拒绝处理 */ diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java index a19f122bd8..9153b3e780 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java @@ -13,7 +13,7 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum BpmTaskStatusEnum { - + SKIP(-2, "跳过"), NOT_START(-1, "未开始"), RUNNING(1, "审批中"), APPROVE(2, "审批通过"), diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java index 460af124f6..1bafa578db 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmnModelUtils.java @@ -800,9 +800,10 @@ public class BpmnModelUtils { || currentElement instanceof EndEvent || currentElement instanceof UserTask || currentElement instanceof ServiceTask) { - // 添加元素 + // 添加节点 FlowNode flowNode = (FlowNode) currentElement; resultElements.add(flowNode); + // 遍历子节点 flowNode.getOutgoingFlows().forEach( nextElement -> simulateNextFlowElements(nextElement.getTargetFlowElement(), variables, resultElements, visitElements)); @@ -835,6 +836,31 @@ public class BpmnModelUtils { } } + /** + * 判断是否跳过此节点 + * + * @param flowNode 节点 + * @param variables 流程变量 + */ + public static boolean isSkipNode(FlowElement flowNode, Map variables) { + // 1. 检查节点是否有跳过表达式(支持多种任务节点类型) + String skipExpression = null; + if (flowNode instanceof UserTask) { + skipExpression = ((UserTask) flowNode).getSkipExpression(); + } else if (flowNode instanceof ServiceTask) { + skipExpression = ((ServiceTask) flowNode).getSkipExpression(); + } else if (flowNode instanceof ScriptTask) { + skipExpression = ((ScriptTask) flowNode).getSkipExpression(); + } + + if (StrUtil.isEmpty(skipExpression)) { + return false; + } + + // 2. 计算跳过表达式的值 + return evalConditionExpress(variables, skipExpression); + } + /** * 根据当前节点,获取下一个节点 * @@ -997,7 +1023,7 @@ public class BpmnModelUtils { * @return 是否满足条件 */ public static boolean evalConditionExpress(Map variables, String expression) { - if (expression == null) { + if (StrUtil.isEmpty(expression)) { return Boolean.FALSE; } // 如果 variables 为空,则创建一个的原因?可能 expression 的计算,不依赖于 variables diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 5e9313840b..b016666a8a 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -464,9 +464,15 @@ public class SimpleModelUtils { addReasonRequire(node.getReasonRequire(), userTask); // 节点类型 addNodeType(node.getType(), userTask); + // 添加跳过表达式 + if (StrUtil.isNotEmpty(node.getSkipExpression())) { + userTask.setSkipExpression(node.getSkipExpression()); + } return userTask; } + + private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) { List flowableListeners = new ArrayList<>(3); if (node.getTaskCreateListener() != null @@ -967,7 +973,7 @@ public class SimpleModelUtils { || nodeType == BpmSimpleModelNodeTypeEnum.COPY_NODE || nodeType == BpmSimpleModelNodeTypeEnum.CHILD_PROCESS || nodeType == BpmSimpleModelNodeTypeEnum.END_NODE) { - // 添加元素 + // 添加此节点 resultNodes.add(currentNode); } @@ -1013,6 +1019,16 @@ public class SimpleModelUtils { simulateNextNode(currentNode.getChildNode(), variables, resultNodes); } + /** + * 根据跳过表达式,判断是否跳过此节点。 + */ + public static boolean isSkipNode(BpmSimpleModelNodeVO currentNode, Map variables) { + if (StrUtil.isEmpty(currentNode.getSkipExpression())) { + return false; + } + return BpmnModelUtils.evalConditionExpress(variables, currentNode.getSkipExpression()); + } + public static boolean evalConditionExpress(Map variables, BpmSimpleModelNodeVO.ConditionSetting conditionSetting) { return BpmnModelUtils.evalConditionExpress(variables, buildConditionExpression(conditionSetting)); } diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 85d15a6327..524dce20c1 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -398,7 +398,7 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService ? BpmSimpleModelNodeTypeEnum.START_USER_NODE.getType() : ObjUtil.defaultIfNull(parseNodeType(flowNode), // 目的:解决“办理节点”的识别 BpmSimpleModelNodeTypeEnum.APPROVE_NODE.getType())) - .setStatus(FlowableUtils.getTaskStatus(task)) + .setStatus(getEndActivityNodeStatus(task)) .setCandidateStrategy(BpmnModelUtils.parseCandidateStrategy(flowNode)) .setStartTime(DateUtils.of(task.getCreateTime())).setEndTime(DateUtils.of(task.getEndTime())) .setTasks(singletonList(BpmProcessInstanceConvert.INSTANCE.buildApprovalTaskInfo(task))); @@ -462,6 +462,15 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService return approvalNodes; } + + /** + * 获取结束节点的状态 + */ + private Integer getEndActivityNodeStatus(HistoricTaskInstance task) { + Integer status = FlowableUtils.getTaskStatus(task); + return status == null ? BpmTaskStatusEnum.SKIP.getStatus() : status; // 结束节点未获取到状态,为跳过状态 + } + /** * 获得【进行中】的活动节点们 */ @@ -565,10 +574,14 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService if (runActivityIds.contains(node.getId())) { return null; } - + Integer status = BpmTaskStatusEnum.NOT_START.getStatus(); + // 如果节点被跳过。设置状态为跳过 + if (SimpleModelUtils.isSkipNode(node, processVariables)) { + status = BpmTaskStatusEnum.SKIP.getStatus(); + } ActivityNode activityNode = new ActivityNode().setId(node.getId()).setName(node.getName()) .setNodeType(node.getType()).setCandidateStrategy(node.getCandidateStrategy()) - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); + .setStatus(status); // 1. 开始节点/审批节点 if (ObjectUtils.equalsAny(node.getType(), @@ -608,8 +621,13 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService if (runActivityIds.contains(node.getId())) { return null; } + Integer status = BpmTaskStatusEnum.NOT_START.getStatus(); + // 如果节点被跳过,状态设置为跳过 + if(BpmnModelUtils.isSkipNode(node, processVariables)){ + status = BpmTaskStatusEnum.SKIP.getStatus(); + } ActivityNode activityNode = new ActivityNode().setId(node.getId()) - .setStatus(BpmTaskStatusEnum.NOT_START.getStatus()); + .setStatus(status); // 1. 开始节点 if (node instanceof StartEvent) { From e07fb6c8fe31e9cde0fd8a1cf46a5db3e1b01f55 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 29 Jul 2025 13:13:47 +0800 Subject: [PATCH 76/81] =?UTF-8?q?review=EF=BC=9A=E3=80=90bpm=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91usertask=20=E7=9A=84=E8=B7=B3?= =?UTF-8?q?=E8=BF=87=E8=A1=A8=E8=BE=BE=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/web/core/handler/GlobalExceptionHandler.java | 6 +++--- .../yudao/module/bpm/enums/task/BpmTaskStatusEnum.java | 1 + .../bpm/framework/flowable/core/util/SimpleModelUtils.java | 4 +--- .../bpm/service/task/BpmProcessInstanceServiceImpl.java | 7 +++++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index e27d04ec68..2f103732cc 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -171,15 +171,15 @@ public class GlobalExceptionHandler { /** * 处理 SpringMVC 请求参数类型错误 * - * 例如说,接口上设置了 @RequestBody实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String + * 例如说,接口上设置了 @RequestBody 实体中 xx 属性类型为 Integer,结果传递 xx 参数类型为 String */ @ExceptionHandler(HttpMessageNotReadableException.class) public CommonResult methodArgumentTypeInvalidFormatExceptionHandler(HttpMessageNotReadableException ex) { log.warn("[methodArgumentTypeInvalidFormatExceptionHandler]", ex); - if(ex.getCause() instanceof InvalidFormatException) { + if (ex.getCause() instanceof InvalidFormatException) { InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause(); return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue())); - }else { + } else { return defaultExceptionHandler(ServletUtils.getRequest(), ex); } } diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java index 9153b3e780..9ba3b5cb3a 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/task/BpmTaskStatusEnum.java @@ -13,6 +13,7 @@ import lombok.Getter; @Getter @AllArgsConstructor public enum BpmTaskStatusEnum { + SKIP(-2, "跳过"), NOT_START(-1, "未开始"), RUNNING(1, "审批中"), diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java index 373f56339b..2582399a81 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/SimpleModelUtils.java @@ -471,8 +471,6 @@ public class SimpleModelUtils { return userTask; } - - private void addUserTaskListener(BpmSimpleModelNodeVO node, UserTask userTask) { List flowableListeners = new ArrayList<>(3); if (node.getTaskCreateListener() != null @@ -1021,7 +1019,7 @@ public class SimpleModelUtils { } /** - * 根据跳过表达式,判断是否跳过此节点。 + * 根据跳过表达式,判断是否跳过此节点 */ public static boolean isSkipNode(BpmSimpleModelNodeVO currentNode, Map variables) { if (StrUtil.isEmpty(currentNode.getSkipExpression())) { diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java index 91815f8dd4..30adda6341 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceServiceImpl.java @@ -462,13 +462,16 @@ public class BpmProcessInstanceServiceImpl implements BpmProcessInstanceService return approvalNodes; } - /** * 获取结束节点的状态 */ private Integer getEndActivityNodeStatus(HistoricTaskInstance task) { Integer status = FlowableUtils.getTaskStatus(task); - return status == null ? BpmTaskStatusEnum.SKIP.getStatus() : status; // 结束节点未获取到状态,为跳过状态 + if (status != null) { + return status; + } + // 结束节点未获取到状态,为跳过状态。可见 bpmn 或者 simple 的 skipExpression + return BpmTaskStatusEnum.SKIP.getStatus(); } /** From ab7d9fdf72f96135efcdc21205d8eee1ba1a9149 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 29 Jul 2025 20:08:27 +0800 Subject: [PATCH 77/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90bpm=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91=E5=A7=94=E6=B4=BE=E3=80=81=E8=BD=AC?= =?UTF-8?q?=E5=8A=9E=E6=97=B6=EF=BC=8Cowner=20=E4=B8=8D=E9=87=8D=E5=A4=8D?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/bpm/service/task/BpmTaskServiceImpl.java | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 1dbd0b17c0..8ea607a773 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -947,7 +947,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { BpmCommentTypeEnum.DELEGATE_START.formatComment(currentUser.getNickname(), delegateUser.getNickname(), reqVO.getReason())); // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) - taskService.setOwner(taskId, task.getAssignee()); + // 特殊:如果已经被委派(owner 非空),则不需要更新 owner:https://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153 + if (StrUtil.isEmpty(task.getOwner())) { + taskService.setOwner(taskId, task.getAssignee()); + } // 3.2 执行委派,将任务委派给 delegateUser taskService.delegateTask(taskId, reqVO.getDelegateUserId().toString()); // 补充说明:委托不单独设置状态。如果需要,可通过 Task 的 DelegationState 字段,判断是否为 DelegationState.PENDING 委托中 @@ -973,7 +976,10 @@ public class BpmTaskServiceImpl implements BpmTaskService { BpmCommentTypeEnum.TRANSFER.formatComment(currentUser.getNickname(), assigneeUser.getNickname(), reqVO.getReason())); // 3.1 设置任务所有人 (owner) 为原任务的处理人 (assignee) - taskService.setOwner(taskId, task.getAssignee()); + // 特殊:如果已经被转派(owner 非空),则不需要更新 owner:https://gitee.com/zhijiantianya/yudao-cloud/issues/ICJ153 + if (StrUtil.isEmpty(task.getOwner())) { + taskService.setOwner(taskId, task.getAssignee()); + } // 3.2 执行转派(审批人),将任务转派给 assigneeUser // 委托( delegate)和转派(transfer)的差别,就在这块的调用!!!! taskService.setAssignee(taskId, reqVO.getAssigneeUserId().toString()); From 176e87141eec2ff13ff089eb10bec9f15102a817 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 29 Jul 2025 22:24:20 +0800 Subject: [PATCH 78/81] =?UTF-8?q?feat=EF=BC=9AGlobalExceptionHandler=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E6=9B=B4=E5=A4=9A=E8=AF=B7=E6=B1=82=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E4=B8=8D=E5=AF=B9=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../core/handler/GlobalExceptionHandler.java | 25 ++++++++++++++++--- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index 2f103732cc..627a5ea784 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -6,6 +6,8 @@ import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.JakartaServletUtil; +import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; +import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO; import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; @@ -14,8 +16,6 @@ import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils; -import cn.iocoder.yudao.framework.common.biz.infra.logger.ApiErrorLogCommonApi; -import cn.iocoder.yudao.framework.common.biz.infra.logger.dto.ApiErrorLogCreateReqDTO; import com.fasterxml.jackson.databind.exc.InvalidFormatException; import jakarta.servlet.http.HttpServletRequest; import jakarta.validation.ConstraintViolation; @@ -29,6 +29,7 @@ import org.springframework.util.Assert; import org.springframework.validation.BindException; import org.springframework.validation.FieldError; import org.springframework.validation.ObjectError; +import org.springframework.web.HttpMediaTypeNotSupportedException; import org.springframework.web.HttpRequestMethodNotSupportedException; import org.springframework.web.bind.MethodArgumentNotValidException; import org.springframework.web.bind.MissingServletRequestParameterException; @@ -101,6 +102,9 @@ public class GlobalExceptionHandler { if (ex instanceof HttpRequestMethodNotSupportedException) { return httpRequestMethodNotSupportedExceptionHandler((HttpRequestMethodNotSupportedException) ex); } + if (ex instanceof HttpMediaTypeNotSupportedException) { + return httpMediaTypeNotSupportedExceptionHandler((HttpMediaTypeNotSupportedException) ex); + } if (ex instanceof ServiceException) { return serviceExceptionHandler((ServiceException) ex); } @@ -179,9 +183,11 @@ public class GlobalExceptionHandler { if (ex.getCause() instanceof InvalidFormatException) { InvalidFormatException invalidFormatException = (InvalidFormatException) ex.getCause(); return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求参数类型错误:%s", invalidFormatException.getValue())); - } else { - return defaultExceptionHandler(ServletUtils.getRequest(), ex); } + if (StrUtil.startWith(ex.getMessage(), "Required request body is missing")) { + return CommonResult.error(BAD_REQUEST.getCode(), "请求参数类型错误: request body 缺失"); + } + return defaultExceptionHandler(ServletUtils.getRequest(), ex); } /** @@ -237,6 +243,17 @@ public class GlobalExceptionHandler { return CommonResult.error(METHOD_NOT_ALLOWED.getCode(), String.format("请求方法不正确:%s", ex.getMessage())); } + /** + * 处理 SpringMVC 请求的 Content-Type 不正确 + * + * 例如说,A 接口的 Content-Type 为 application/json,结果请求的 Content-Type 为 application/octet-stream,导致不匹配 + */ + @ExceptionHandler(HttpMediaTypeNotSupportedException.class) + public CommonResult httpMediaTypeNotSupportedExceptionHandler(HttpMediaTypeNotSupportedException ex) { + log.warn("[httpMediaTypeNotSupportedExceptionHandler]", ex); + return CommonResult.error(BAD_REQUEST.getCode(), String.format("请求类型不正确:%s", ex.getMessage())); + } + /** * 处理 Spring Security 权限不足的异常 * From f71ec384568d6291fef8216d0a6897c4395a9f70 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 30 Jul 2025 19:06:44 +0800 Subject: [PATCH 79/81] =?UTF-8?q?=E3=80=90=E5=90=8C=E6=AD=A5=E3=80=91BOOT?= =?UTF-8?q?=20=E5=92=8C=20CLOUD=20=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/bpm/enums/ErrorCodeConstants.java | 3 +- .../core/util/BpmHttpRequestUtils.java | 50 +++++++++++++++---- .../module/crm/util/CrmPermissionUtils.java | 2 +- 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java index 4f7d7bf7ce..0e3b1b9208 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/enums/ErrorCodeConstants.java @@ -40,7 +40,7 @@ public interface ErrorCodeConstants { ErrorCode PROCESS_INSTANCE_START_USER_SELECT_ASSIGNEES_NOT_EXISTS = new ErrorCode(1_009_004_004, "任务({})的候选人({})不存在"); ErrorCode PROCESS_INSTANCE_START_USER_CAN_START = new ErrorCode(1_009_004_005, "发起流程失败,你没有权限发起该流程"); ErrorCode PROCESS_INSTANCE_CANCEL_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_005, "流程取消失败,该流程不允许取消"); - ErrorCode PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 触发器请求调用失败"); + ErrorCode PROCESS_INSTANCE_HTTP_CALL_ERROR = new ErrorCode(1_009_004_006, "流程 Http 请求调用失败"); ErrorCode PROCESS_INSTANCE_APPROVE_USER_SELECT_ASSIGNEES_NOT_CONFIG = new ErrorCode(1_009_004_007, "下一个任务({})的审批人未配置"); ErrorCode PROCESS_INSTANCE_CANCEL_CHILD_FAIL_NOT_ALLOW = new ErrorCode(1_009_004_008, "子流程取消失败,子流程不允许取消"); @@ -58,7 +58,6 @@ public interface ErrorCodeConstants { ErrorCode TASK_SIGN_DELETE_NO_PARENT = new ErrorCode(1_009_005_012, "任务减签失败,被减签的任务必须是通过加签生成的任务"); ErrorCode TASK_TRANSFER_FAIL_USER_REPEAT = new ErrorCode(1_009_005_013, "任务转办失败,转办人和当前审批人为同一人"); ErrorCode TASK_TRANSFER_FAIL_USER_NOT_EXISTS = new ErrorCode(1_009_005_014, "任务转办失败,转办人不存在"); - ErrorCode TASK_CREATE_FAIL_NO_CANDIDATE_USER = new ErrorCode(1_009_006_003, "操作失败,原因:找不到任务的审批人!"); ErrorCode TASK_SIGNATURE_NOT_EXISTS = new ErrorCode(1_009_005_015, "签名不能为空!"); ErrorCode TASK_REASON_REQUIRE = new ErrorCode(1_009_005_016, "审批意见不能为空!"); diff --git a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java index 014b5e3f0d..358ee9f4dc 100644 --- a/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java +++ b/yudao-module-bpm/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/util/BpmHttpRequestUtils.java @@ -6,15 +6,15 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; import cn.iocoder.yudao.framework.common.util.spring.SpringUtils; +import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; +import cn.iocoder.yudao.module.bpm.api.event.BpmProcessInstanceStatusEvent; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.simple.BpmSimpleModelNodeVO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmHttpRequestParamTypeEnum; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import com.fasterxml.jackson.core.type.TypeReference; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.runtime.ProcessInstance; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.web.client.RestClientException; @@ -26,7 +26,7 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.HEADER_TENANT_ID; -import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR; +import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_INSTANCE_HTTP_CALL_ERROR; /** * 工作流发起 HTTP 请求工具类 @@ -42,7 +42,6 @@ public class BpmHttpRequestUtils { List bodyParams, Boolean handleResponse, List> response) { - RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class); // 1.1 设置请求头 @@ -51,6 +50,7 @@ public class BpmHttpRequestUtils { MultiValueMap body = buildHttpBody(processInstance, bodyParams); // 2. 发起请求 + RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); ResponseEntity responseEntity = sendHttpRequest(url, headers, body, restTemplate); // 3. 处理返回 @@ -78,27 +78,55 @@ public class BpmHttpRequestUtils { } } + public static void executeBpmHttpRequest(BpmProcessInstanceStatusEvent event, + String url) { + // 1.1 设置请求头 + HttpHeaders headers = new HttpHeaders(); + headers.setContentType(MediaType.APPLICATION_JSON); + if (TenantContextHolder.getTenantId() != null) { + headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId())); + } else { + BpmProcessInstanceService processInstanceService = SpringUtils.getBean(BpmProcessInstanceService.class); + ProcessInstance processInstance = processInstanceService.getProcessInstance(event.getId()); + if (processInstance != null) { + headers.add(HEADER_TENANT_ID, String.valueOf(TenantContextHolder.getTenantId())); + } + } + // 1.2 设置请求体 +// MultiValueMap body = new LinkedMultiValueMap<>(); +// body.add("id", event.getId()); +// body.add("processDefinitionKey", event.getProcessDefinitionKey()); +// body.add("status", event.getStatus().toString()); +// if (StrUtil.isNotEmpty(event.getBusinessKey())) { +// body.add("businessKey", event.getBusinessKey()); +// } + + // 2. 发起请求 + RestTemplate restTemplate = SpringUtils.getBean(RestTemplate.class); + sendHttpRequest(url, headers, event, restTemplate); + } + public static ResponseEntity sendHttpRequest(String url, MultiValueMap headers, - MultiValueMap body, + Object body, RestTemplate restTemplate) { - HttpEntity> requestEntity = new HttpEntity<>(body, headers); + HttpEntity requestEntity = new HttpEntity<>(body, headers); ResponseEntity responseEntity; try { responseEntity = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class); - log.info("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); + log.info("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},响应结果:{}]", headers, body, responseEntity); } catch (RestClientException e) { - log.error("[sendHttpRequest][HTTP 触发器,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); - throw exception(PROCESS_INSTANCE_HTTP_TRIGGER_CALL_ERROR); + log.error("[sendHttpRequest][HTTP 请求,请求头:{},请求体:{},请求出错:{}]", headers, body, e.getMessage()); + throw exception(PROCESS_INSTANCE_HTTP_CALL_ERROR); } return responseEntity; } public static MultiValueMap buildHttpHeaders(ProcessInstance processInstance, List headerSettings) { - Map processVariables = processInstance.getProcessVariables(); MultiValueMap headers = new LinkedMultiValueMap<>(); headers.add(HEADER_TENANT_ID, processInstance.getTenantId()); + Map processVariables = processInstance.getProcessVariables(); addHttpRequestParam(headers, headerSettings, processVariables); return headers; } diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java index d2818cd072..f3a0b5792b 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java @@ -32,7 +32,7 @@ public class CrmPermissionUtils { * @return 是/否 */ public static boolean isCrmAdmin() { - PermissionApi permissionApi = SpringUtil.getBean(PermissionApi.class); + PermissionCommonApi permissionApi = SpringUtil.getBean(PermissionCommonApi.class); return permissionApi.hasAnyRoles(getLoginUserId(), RoleCodeEnum.CRM_ADMIN.getCode()); } From aefaff2cad9fe78fb344ff94d2b7f888624c02cb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 31 Jul 2025 09:56:34 +0800 Subject: [PATCH 80/81] =?UTF-8?q?fix=EF=BC=9A=E3=80=90bpm=20=E5=B7=A5?= =?UTF-8?q?=E4=BD=9C=E6=B5=81=E3=80=91BpmCategoryServiceImplTest=20?= =?UTF-8?q?=E5=8D=95=E6=B5=8B=E4=B8=8D=E6=AD=A3=E7=A1=AE=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bpm/service/category/BpmCategoryServiceImplTest.java | 5 +++++ .../cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/category/BpmCategoryServiceImplTest.java b/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/category/BpmCategoryServiceImplTest.java index f71b8aae50..19199e5616 100644 --- a/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/category/BpmCategoryServiceImplTest.java +++ b/yudao-module-bpm/src/test/java/cn/iocoder/yudao/module/bpm/service/category/BpmCategoryServiceImplTest.java @@ -8,9 +8,11 @@ import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.category.BpmCa import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmCategoryDO; import cn.iocoder.yudao.module.bpm.dal.mysql.category.BpmCategoryMapper; import cn.iocoder.yudao.module.bpm.service.definition.BpmCategoryServiceImpl; +import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; +import org.springframework.test.context.bean.override.mockito.MockitoBean; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildTime; @@ -32,6 +34,9 @@ public class BpmCategoryServiceImplTest extends BaseDbUnitTest { @Resource private BpmCategoryServiceImpl categoryService; + @MockitoBean + private BpmModelService modelService; + @Resource private BpmCategoryMapper categoryMapper; diff --git a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java index f3a0b5792b..0563af0ad3 100644 --- a/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java +++ b/yudao-module-crm/src/main/java/cn/iocoder/yudao/module/crm/util/CrmPermissionUtils.java @@ -2,11 +2,11 @@ package cn.iocoder.yudao.module.crm.util; import cn.hutool.core.collection.CollUtil; import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.biz.system.permission.PermissionCommonApi; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import cn.iocoder.yudao.module.system.enums.permission.RoleCodeEnum; From 3a07bcc3c663f843ef130cff616df5a9ccb96902 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 31 Jul 2025 12:57:33 +0800 Subject: [PATCH 81/81] =?UTF-8?q?(=E3=80=83'=E2=96=BD'=E3=80=83)=20v2025.0?= =?UTF-8?q?8=20=E5=8F=91=E5=B8=83=EF=BC=9A=E5=AE=8C=E5=96=84=20vben5(antd)?= =?UTF-8?q?=20=E5=B7=A5=E4=BD=9C=E6=B5=81=E3=80=81=E8=BF=81=E7=A7=BB=20vbe?= =?UTF-8?q?n5(ep)=20=E5=95=86=E5=9F=8E=E3=80=81=E6=94=AF=E6=8C=81=20IoT=20?= =?UTF-8?q?TCP=20=E5=8D=8F=E8=AE=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- yudao-dependencies/pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 48a6f0589d..e4770100e7 100644 --- a/pom.xml +++ b/pom.xml @@ -32,7 +32,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.6.1-SNAPSHOT + 2025.08-SNAPSHOT 17 ${java.version} diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index d3b23f62ca..668249863a 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.6.1-SNAPSHOT + 2025.08-SNAPSHOT 1.6.0 3.4.5