# Conflicts:
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/knowledge/AiKnowledgeController.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/controller/admin/workflow/vo/AiWorkflowTestReqVO.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeDocumentMapper.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/dal/mysql/knowledge/AiKnowledgeSegmentMapper.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/chat/AiChatMessageServiceImpl.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentService.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeDocumentServiceImpl.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeService.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/knowledge/AiKnowledgeServiceImpl.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiModelService.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/model/AiModelServiceImpl.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/workflow/AiWorkflowServiceImpl.java
#	yudao-module-ai/yudao-module-ai-biz/src/main/java/cn/iocoder/yudao/module/ai/service/write/AiWriteServiceImpl.java
#	yudao-module-ai/yudao-spring-boot-starter-ai/pom.xml
#	yudao-module-ai/yudao-spring-boot-starter-ai/src/main/java/cn/iocoder/yudao/framework/ai/core/util/AiUtils.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/task/BpmTaskConvert.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/behavior/BpmSequentialMultiInstanceBehavior.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/form/BpmTaskCandidateFormUserStrategy.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/candidate/strategy/other/BpmTaskCandidateExpressionStrategy.java
#	yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java
#	yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java
#	yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/framework/file/core/ftp/FtpFileClientTest.java
#	yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/framework/file/core/sftp/SftpFileClientTest.java
#	yudao-module-infra/yudao-module-infra-biz/src/test/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImplTest.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/firmware/IotOtaFirmwareCreateReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/firmware/IotOtaFirmwareRespVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/firmware/IotOtaFirmwareUpdateReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/record/IotOtaUpgradeRecordPageReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/record/IotOtaUpgradeRecordRespVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/task/IotOtaUpgradeTaskPageReqVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/task/IotOtaUpgradeTaskRespVO.java
#	yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/ota/vo/upgrade/task/IotOtaUpgradeTaskSaveReqVO.java
#	yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/sku/ProductSkuApi.java
#	yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/ProductSpuApi.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/history/vo/ProductBrowseHistoryRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteBatchReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/favorite/vo/AppFavoriteRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryDeleteReqVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/history/vo/AppProductBrowseHistoryRespVO.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImpl.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuService.java
#	yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/admin/point/PointActivityController.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/vo/template/AppCouponTemplateRespVO.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/point/AppPointActivityController.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/kefu/KeFuMessageServiceImpl.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/point/PointActivityServiceImpl.java
#	yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/seckill/SeckillActivityServiceImpl.java
#	yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/DictTypeConstants.java
#	yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/ErrorCodeConstants.java
#	yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/aftersale/AfterSaleOperateTypeEnum.java
#	yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawStatusEnum.java
#	yudao-module-mall/yudao-module-trade-api/src/main/java/cn/iocoder/yudao/module/trade/enums/brokerage/BrokerageWithdrawTypeEnum.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/aftersale/AfterSaleController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/BrokerageWithdrawController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawPageReqVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/admin/brokerage/vo/withdraw/BrokerageWithdrawRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/aftersale/AppAfterSaleController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/base/spu/AppProductSpuBaseRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageRecordController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/AppBrokerageWithdrawController.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordPageReqVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/record/AppBrokerageRecordRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawCreateReqVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawPageReqVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/brokerage/vo/withdraw/AppBrokerageWithdrawRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/delivery/vo/pickup/AppDeliveryPickUpStoreRespVO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageRecordConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/brokerage/BrokerageWithdrawConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/cart/TradeCartConvert.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/dataobject/brokerage/BrokerageWithdrawDO.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/aftersale/AfterSaleMapper.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/dal/mysql/brokerage/BrokerageWithdrawMapper.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/aop/AfterSaleLogAspect.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/aftersale/core/utils/AfterSaleLogUtils.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/delivery/core/enums/ExpressClientEnum.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/config/TradeOrderProperties.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleService.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImpl.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateService.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderUpdateServiceImpl.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeBrokerageOrderHandler.java
#	yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/handler/TradeOrderHandler.java
#	yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/brokerage/BrokerageWithdrawServiceImplTest.java
#	yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
#	yudao-module-member/yudao-module-member-biz/src/test/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImplTest.java
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/controller/admin/open/MpOpenController.java
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/dal/mysql/user/MpUserMapper.java
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/menu/MenuHandler.java
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/handler/message/MessageReceiveHandler.java
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/material/MpMaterialServiceImpl.java
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageService.java
#	yudao-module-mp/yudao-module-mp-biz/src/main/java/cn/iocoder/yudao/module/mp/service/message/MpMessageServiceImpl.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayRefundNotifyReqDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/notify/dto/PayTransferNotifyReqDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/order/dto/PayOrderRespDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/refund/dto/PayRefundRespDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApi.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferCreateReqDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/dto/PayTransferRespDTO.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/PayWalletApi.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/DictTypeConstants.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/ErrorCodeConstants.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/transfer/PayTransferStatusEnum.java
#	yudao-module-pay/yudao-module-pay-api/src/main/java/cn/iocoder/yudao/module/pay/enums/wallet/PayWalletBizTypeEnum.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/refund/PayRefundApiImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/transfer/PayTransferApiImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/api/wallet/PayWalletApiImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/demo/PayDemoOrderController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/PayNotifyController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskDetailRespVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskPageReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/notify/vo/PayNotifyTaskRespVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/order/PayOrderController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/refund/PayRefundController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/PayTransferController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferPageReqVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/transfer/vo/PayTransferRespVO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/admin/wallet/PayWalletRechargeController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/controller/app/order/AppPayOrderController.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/convert/refund/PayRefundConvert.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/notify/PayNotifyTaskDO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/dataobject/transfer/PayTransferDO.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/notify/PayNotifyTaskMapper.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/dal/mysql/transfer/PayTransferMapper.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/framework/pay/core/WalletPayClient.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/app/PayAppServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/demo/PayDemoOrderServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/notify/PayNotifyServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/transfer/PayTransferServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletRechargeServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletService.java
#	yudao-module-pay/yudao-module-pay-biz/src/main/java/cn/iocoder/yudao/module/pay/service/wallet/PayWalletServiceImpl.java
#	yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/channel/PayChannelServiceTest.java
#	yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/order/PayOrderServiceTest.java
#	yudao-module-pay/yudao-module-pay-biz/src/test/java/cn/iocoder/yudao/module/pay/service/refund/PayRefundServiceTest.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClient.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/PayClientConfig.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferRespDTO.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/dto/transfer/PayTransferUnifiedReqDTO.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/AbstractPayClient.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/alipay/AbstractAlipayPayClient.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/mock/MockPayClient.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/AbstractWxPayClient.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPayClientConfig.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/client/impl/weixin/WxPubPayClient.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/main/java/cn/iocoder/yudao/framework/pay/core/enums/transfer/PayTransferStatusRespEnum.java
#	yudao-module-pay/yudao-spring-boot-starter-biz-pay/src/test/java/cn/iocoder/yudao/framework/pay/core/client/impl/PayClientFactoryImplIntegrationTest.java
#	yudao-module-report/yudao-module-report-biz/pom.xml
#	yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/jmreport/config/JmReportConfiguration.java
#	yudao-module-report/yudao-module-report-biz/src/main/java/cn/iocoder/yudao/module/report/framework/security/config/SecurityConfiguration.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImplTest.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImplTest.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImplTest.java
#	yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImplTest.java
This commit is contained in:
YunaiV
2025-05-13 20:56:41 +08:00
150 changed files with 6210 additions and 1011 deletions

View File

@@ -66,4 +66,20 @@ public interface SocialClientApi {
*/
void sendWxaSubscribeMessage(SocialWxaSubscribeMessageSendReqDTO reqDTO);
/**
* 上传订单发货到微信小程序
*
* @param userType 用户类型
* @param reqDTO 请求
*/
void uploadWxaOrderShippingInfo(Integer userType, SocialWxaOrderUploadShippingInfoReqDTO reqDTO);
/**
* 通知订单收货到微信小程序
*
* @param userType 用户类型
* @param reqDTO 请求
*/
void notifyWxaOrderConfirmReceive(Integer userType, SocialWxaOrderNotifyConfirmReceiveReqDTO reqDTO);
}

View File

@@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.system.api.social.dto;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import java.time.LocalDateTime;
/**
* 小程序订单上传购物详情
*
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/shopping-order/normal-shopping-detail/uploadShoppingInfo.html">上传购物详情</a>
* @author 芋道源码
*/
@Data
public class SocialWxaOrderNotifyConfirmReceiveReqDTO {
/**
* 原支付交易对应的微信订单号
*/
@NotEmpty(message = "原支付交易对应的微信订单号不能为空")
private String transactionId;
/**
* 快递签收时间
*/
@NotNull(message = "快递签收时间不能为空")
private LocalDateTime receivedTime;
}

View File

@@ -0,0 +1,68 @@
package cn.iocoder.yudao.module.system.api.social.dto;
import lombok.Data;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
/**
* 小程序订单上传购物详情
*
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/OpenApiDoc/shopping-order/normal-shopping-detail/uploadShoppingInfo.html">上传购物详情</a>
* @author 芋道源码
*/
@Data
public class SocialWxaOrderUploadShippingInfoReqDTO {
/**
* 物流模式 - 实体物流配送采用快递公司进行实体物流配送形式
*/
public static final Integer LOGISTICS_TYPE_EXPRESS = 1;
/**
* 物流模式 - 虚拟商品,虚拟商品,例如话费充值,点卡等,无实体配送形式
*/
public static final Integer LOGISTICS_TYPE_VIRTUAL = 3;
/**
* 物流模式 - 用户自提
*/
public static final Integer LOGISTICS_TYPE_PICK_UP = 4;
/**
* 支付者,支付者信息(openid)
*/
@NotEmpty(message = "支付者,支付者信息(openid)不能为空")
private String openid;
/**
* 原支付交易对应的微信订单号
*/
@NotEmpty(message = "原支付交易对应的微信订单号不能为空")
private String transactionId;
/**
* 物流模式
*/
@NotNull(message = "物流模式不能为空")
private Integer logisticsType;
/**
* 物流发货单号
*/
private String logisticsNo;
/**
* 物流公司编号
*
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/express/business/express_search.html#%E8%8E%B7%E5%8F%96%E8%BF%90%E5%8A%9Bid%E5%88%97%E8%A1%A8get-delivery-list">物流查询插件简介</a>
*/
private String expressCompany;
/**
* 商品信息
*/
@NotEmpty(message = "商品信息不能为空")
private String itemDesc;
/**
* 收件人手机号
*/
@NotEmpty(message = "收件人手机号")
private String receiverContact;
}

View File

@@ -45,6 +45,7 @@ public interface ErrorCodeConstants {
ErrorCode USER_COUNT_MAX = new ErrorCode(1_002_003_008, "创建用户失败,原因:超过租户最大租户配额({})");
ErrorCode USER_IMPORT_INIT_PASSWORD = new ErrorCode(1_002_003_009, "初始密码不能为空");
ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1_002_003_010, "该手机号尚未注册");
ErrorCode USER_REGISTER_DISABLED = new ErrorCode(1_002_003_011, "注册功能已关闭");
// ========== 部门模块 1-002-004-000 ==========
ErrorCode DEPT_NAME_DUPLICATE = new ErrorCode(1_002_004_000, "已经存在该名字的部门");
@@ -123,10 +124,11 @@ public interface ErrorCodeConstants {
ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_QRCODE_ERROR = new ErrorCode(1_002_018_201, "获得小程序码失败");
ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_SUBSCRIBE_TEMPLATE_ERROR = new ErrorCode(1_002_018_202, "获得小程序订阅消息模版失败");
ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_SUBSCRIBE_MESSAGE_ERROR = new ErrorCode(1_002_018_203, "发送小程序订阅消息失败");
ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_UPLOAD_SHIPPING_INFO_ERROR = new ErrorCode(1_002_018_204, "上传微信小程序发货信息失败");
ErrorCode SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_NOTIFY_CONFIRM_RECEIVE_ERROR = new ErrorCode(1_002_018_205, "上传微信小程序订单收货信息失败");
ErrorCode SOCIAL_CLIENT_NOT_EXISTS = new ErrorCode(1_002_018_210, "社交客户端不存在");
ErrorCode SOCIAL_CLIENT_UNIQUE = new ErrorCode(1_002_018_211, "社交客户端已存在配置");
// ========== OAuth2 客户端 1-002-020-000 =========
ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在");
ErrorCode OAUTH2_CLIENT_EXISTS = new ErrorCode(1_002_020_001, "OAuth2 客户端编号已存在");

View File

@@ -52,7 +52,7 @@ public enum SocialTypeEnum implements ArrayValuable<Integer> {
*
* @see <a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html">接入文档</a>
*/
WECHAT_MINI_APP(34, "WECHAT_MINI_APP"),
WECHAT_MINI_PROGRAM(34, "WECHAT_MINI_PROGRAM"),
;
public static final Integer[] ARRAYS = Arrays.stream(values()).map(SocialTypeEnum::getType).toArray(Integer[]::new);

View File

@@ -90,8 +90,12 @@
<!-- 三方云服务相关 -->
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-justauth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
<groupId>me.zhyd.oauth</groupId>
<artifactId>JustAuth</artifactId> <!-- 社交登陆(例如说,个人微信、企业微信等等) -->
</dependency>
<dependency>
<groupId>com.xkcoding.justauth</groupId>
<artifactId>justauth-spring-boot-starter</artifactId>
</dependency>
<dependency>
@@ -104,8 +108,8 @@
</dependency>
<dependency>
<groupId>com.xingyuv</groupId>
<artifactId>spring-boot-starter-captcha-plus</artifactId> <!-- 验证码,一般用于登录使用 -->
<groupId>com.anji-plus</groupId>
<artifactId>captcha-spring-boot-starter</artifactId> <!-- 验证码,一般用于登录使用 -->
</dependency>
</dependencies>

View File

@@ -84,7 +84,7 @@ public class SocialClientApiImpl implements SocialClientApi {
// 2. 获得社交用户
SocialUserRespDTO socialUser = socialUserService.getSocialUserByUserId(reqDTO.getUserType(), reqDTO.getUserId(),
SocialTypeEnum.WECHAT_MINI_APP.getType());
SocialTypeEnum.WECHAT_MINI_PROGRAM.getType());
if (StrUtil.isBlankIfStr(socialUser.getOpenid())) {
log.warn("[sendWxaSubscribeMessage][reqDTO({}) 发送订阅消息失败,原因:会员 openid 缺失]", reqDTO);
return;
@@ -94,4 +94,14 @@ public class SocialClientApiImpl implements SocialClientApi {
socialClientService.sendSubscribeMessage(reqDTO, template.getPriTmplId(), socialUser.getOpenid());
}
@Override
public void uploadWxaOrderShippingInfo(Integer userType, SocialWxaOrderUploadShippingInfoReqDTO reqDTO) {
socialClientService.uploadWxaOrderShippingInfo(userType, reqDTO);
}
@Override
public void notifyWxaOrderConfirmReceive(Integer userType, SocialWxaOrderNotifyConfirmReceiveReqDTO reqDTO) {
socialClientService.notifyWxaOrderConfirmReceive(userType, reqDTO);
}
}

View File

@@ -47,6 +47,12 @@ public class AuthPermissionInfoRespVO {
@Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048")
private Long deptId;
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
private String username;
@Schema(description = "用户邮箱", example = "yudao@iocoder.cn")
private String email;
}
@Schema(description = "管理后台 - 登录用户的菜单信息 Response VO")

View File

@@ -2,9 +2,10 @@ package cn.iocoder.yudao.module.system.controller.admin.captcha;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import com.xingyuv.captcha.model.common.ResponseModel;
import com.xingyuv.captcha.model.vo.CaptchaVO;
import com.xingyuv.captcha.service.CaptchaService;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.web.bind.annotation.PostMapping;
@@ -27,6 +28,7 @@ public class CaptchaController {
@PostMapping({"/get"})
@Operation(summary = "获得验证码")
@PermitAll
@TenantIgnore
public ResponseModel get(@RequestBody CaptchaVO data, HttpServletRequest request) {
assert request.getRemoteHost() != null;
data.setBrowserInfo(getRemoteId(request));
@@ -36,6 +38,7 @@ public class CaptchaController {
@PostMapping("/check")
@Operation(summary = "校验验证码")
@PermitAll
@TenantIgnore
public ResponseModel check(@RequestBody CaptchaVO data, HttpServletRequest request) {
data.setBrowserInfo(getRemoteId(request));
return captchaService.check(data);

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.controller.admin.sms;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum;
import cn.iocoder.yudao.module.system.service.sms.SmsSendService;
import io.swagger.v3.oas.annotations.Operation;
@@ -24,6 +25,7 @@ public class SmsCallbackController {
@PostMapping("/aliyun")
@PermitAll
@TenantIgnore
@Operation(summary = "阿里云短信的回调", description = "参见 https://help.aliyun.com/document_detail/120998.html 文档")
public CommonResult<Boolean> receiveAliyunSmsStatus(HttpServletRequest request) throws Throwable {
String text = ServletUtils.getBody(request);
@@ -33,6 +35,7 @@ public class SmsCallbackController {
@PostMapping("/tencent")
@PermitAll
@TenantIgnore
@Operation(summary = "腾讯云短信的回调", description = "参见 https://cloud.tencent.com/document/product/382/52077 文档")
public CommonResult<Boolean> receiveTencentSmsStatus(HttpServletRequest request) throws Throwable {
String text = ServletUtils.getBody(request);
@@ -43,6 +46,7 @@ public class SmsCallbackController {
@PostMapping("/huawei")
@PermitAll
@TenantIgnore
@Operation(summary = "华为云短信的回调", description = "参见 https://support.huaweicloud.com/api-msgsms/sms_05_0003.html 文档")
public CommonResult<Boolean> receiveHuaweiSmsStatus(@RequestBody String requestBody) throws Throwable {
smsSendService.receiveSmsStatus(SmsChannelEnum.HUAWEI.getCode(), requestBody);
@@ -51,6 +55,7 @@ public class SmsCallbackController {
@PostMapping("/qiniu")
@PermitAll
@TenantIgnore
@Operation(summary = "七牛云短信的回调", description = "参见 https://developer.qiniu.com/sms/5910/message-push 文档")
public CommonResult<Boolean> receiveQiniuSmsStatus(@RequestBody String requestBody) throws Throwable {
smsSendService.receiveSmsStatus(SmsChannelEnum.QINIU.getCode(), requestBody);

View File

@@ -5,9 +5,9 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserBindReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserUnbindReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserRespVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserUnbindReqVO;
import cn.iocoder.yudao.module.system.convert.social.SocialUserConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
@@ -20,8 +20,10 @@ import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
@Tag(name = "管理后台 - 社交用户")
@@ -48,6 +50,15 @@ public class SocialUserController {
return CommonResult.success(true);
}
@GetMapping("/get-bind-list")
@Operation(summary = "获得绑定社交用户列表")
public CommonResult<List<SocialUserRespVO>> getBindSocialUserList() {
List<SocialUserDO> list = socialUserService.getSocialUserList(getLoginUserId(), UserTypeEnum.ADMIN.getValue());
return success(convertList(list, socialUser -> new SocialUserRespVO() // 返回精简信息
.setId(socialUser.getId()).setType(socialUser.getType()).setOpenid(socialUser.getOpenid())
.setNickname(socialUser.getNickname()).setAvatar(socialUser.getNickname())));
}
// ==================== 社交用户 CRUD ====================
@GetMapping("/get")

View File

@@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantRespVO;
import cn.iocoder.yudao.module.system.controller.admin.tenant.vo.tenant.TenantSaveReqVO;
@@ -39,6 +40,7 @@ public class TenantController {
@GetMapping("/get-id-by-name")
@PermitAll
@TenantIgnore
@Operation(summary = "使用租户名,获得租户编号", description = "登录界面,根据用户的租户名,获得租户编号")
@Parameter(name = "name", description = "租户名", required = true, example = "1024")
public CommonResult<Long> getTenantIdByName(@RequestParam("name") String name) {
@@ -48,6 +50,7 @@ public class TenantController {
@GetMapping({ "simple-list" })
@PermitAll
@TenantIgnore
@Operation(summary = "获取租户精简信息列表", description = "只包含被开启的租户,用于【首页】功能的选择租户选项")
public CommonResult<List<TenantRespVO>> getTenantSimpleList() {
List<TenantDO> list = tenantService.getTenantListByStatus(CommonStatusEnum.ENABLE.getStatus());
@@ -57,6 +60,7 @@ public class TenantController {
@GetMapping("/get-by-website")
@PermitAll
@TenantIgnore
@Operation(summary = "使用域名,获得租户信息", description = "登录界面,根据用户的域名,获得租户信息")
@Parameter(name = "website", description = "域名", required = true, example = "www.iocoder.cn")
public CommonResult<TenantRespVO> getTenantByWebsite(@RequestParam("website") String website) {

View File

@@ -3,3 +3,9 @@ GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10
Authorization: Bearer {{token}}
#Authorization: Bearer test100
tenant-id: {{adminTenantId}}
### 请求 /system/user/page 接口(测试访问别的租户)
GET {{baseUrl}}/system/user/page?pageNo=1&pageSize=10
Authorization: Bearer {{token}}
tenant-id: {{adminTenantId}}
visit-tenant-id: 122

View File

@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.system.controller.admin.user;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileRespVO;
@@ -11,29 +10,24 @@ import cn.iocoder.yudao.module.system.convert.user.UserConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import cn.iocoder.yudao.module.system.service.dept.DeptService;
import cn.iocoder.yudao.module.system.service.dept.PostService;
import cn.iocoder.yudao.module.system.service.permission.PermissionService;
import cn.iocoder.yudao.module.system.service.permission.RoleService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import io.swagger.v3.oas.annotations.tags.Tag;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_IS_EMPTY;
@Tag(name = "管理后台 - 用户个人中心")
@RestController
@@ -52,8 +46,6 @@ public class UserProfileController {
private PermissionService permissionService;
@Resource
private RoleService roleService;
@Resource
private SocialUserService socialService;
@GetMapping("/get")
@Operation(summary = "获得登录用户信息")
@@ -67,9 +59,7 @@ public class UserProfileController {
DeptDO dept = user.getDeptId() != null ? deptService.getDept(user.getDeptId()) : null;
// 获得岗位信息
List<PostDO> posts = CollUtil.isNotEmpty(user.getPostIds()) ? postService.getPostList(user.getPostIds()) : null;
// 获得社交用户信息
List<SocialUserDO> socialUsers = socialService.getSocialUserList(user.getId(), UserTypeEnum.ADMIN.getValue());
return success(UserConvert.INSTANCE.convert(user, userRoles, dept, posts, socialUsers));
return success(UserConvert.INSTANCE.convert(user, userRoles, dept, posts));
}
@PutMapping("/update")
@@ -86,15 +76,4 @@ public class UserProfileController {
return success(true);
}
@RequestMapping(value = "/update-avatar",
method = {RequestMethod.POST, RequestMethod.PUT}) // 解决 uni-app 不支持 Put 上传文件的问题
@Operation(summary = "上传用户个人头像")
public CommonResult<String> updateUserAvatar(@RequestParam("avatarFile") MultipartFile file) throws Exception {
if (file.isEmpty()) {
throw exception(FILE_IS_EMPTY);
}
String avatar = userService.updateUserAvatar(getLoginUserId(), file.getInputStream());
return success(avatar);
}
}

View File

@@ -55,21 +55,5 @@ public class UserProfileRespVO {
* 所属岗位数组
*/
private List<PostSimpleRespVO> posts;
/**
* 社交用户数组
*/
private List<SocialUser> socialUsers;
@Schema(description = "社交用户")
@Data
public static class SocialUser {
@Schema(description = "社交平台的类型,参见 SocialTypeEnum 枚举类", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer type;
@Schema(description = "社交用户的 openid", requiredMode = Schema.RequiredMode.REQUIRED, example = "IPRmJ0wvBptiPIlGEZiPewGwiEiE")
private String openid;
}
}

View File

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.user.vo.profile;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.URL;
import javax.validation.constraints.Email;
import javax.validation.constraints.Size;
@@ -12,7 +13,7 @@ import javax.validation.constraints.Size;
@Data
public class UserProfileUpdateReqVO {
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
@Schema(description = "用户昵称", example = "芋艿")
@Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
private String nickname;
@@ -28,4 +29,8 @@ public class UserProfileUpdateReqVO {
@Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
private Integer sex;
@Schema(description = "角色头像", example = "https://www.iocoder.cn/1.png")
@URL(message = "头像地址格式不正确")
private String avatar;
}

View File

@@ -12,7 +12,6 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSimpleRe
import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO;
import cn.iocoder.yudao.module.system.dal.dataobject.dept.PostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.permission.RoleDO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import org.mapstruct.Mapper;
import org.mapstruct.factory.Mappers;
@@ -46,12 +45,11 @@ public interface UserConvert {
}
default UserProfileRespVO convert(AdminUserDO user, List<RoleDO> userRoles,
DeptDO dept, List<PostDO> posts, List<SocialUserDO> socialUsers) {
DeptDO dept, List<PostDO> posts) {
UserProfileRespVO userVO = BeanUtils.toBean(user, UserProfileRespVO.class);
userVO.setRoles(BeanUtils.toBean(userRoles, RoleSimpleRespVO.class));
userVO.setDept(BeanUtils.toBean(dept, DeptSimpleRespVO.class));
userVO.setPosts(BeanUtils.toBean(posts, PostSimpleRespVO.class));
userVO.setSocialUsers(BeanUtils.toBean(socialUsers, UserProfileRespVO.SocialUser.class));
return userVO;
}

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.dict;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.*;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -15,6 +16,7 @@ import lombok.EqualsAndHashCode;
@KeySequence("system_dict_data_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@TenantIgnore
public class DictDataDO extends BaseDO {
/**

View File

@@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.system.dal.dataobject.dict;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@@ -23,6 +23,7 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TenantIgnore
public class DictTypeDO extends BaseDO {
/**

View File

@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.dal.dataobject.mail;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -19,6 +20,7 @@ import lombok.EqualsAndHashCode;
@KeySequence("system_mail_account_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@TenantIgnore
public class MailAccountDO extends BaseDO {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.mail;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.enums.mail.MailSendStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
@@ -28,6 +29,7 @@ import java.util.Map;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TenantIgnore
public class MailLogDO extends BaseDO implements Serializable {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.mail;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -21,6 +22,7 @@ import java.util.List;
@KeySequence("system_mail_template_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@TenantIgnore
public class MailTemplateDO extends BaseDO {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.notify;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -24,6 +25,7 @@ import java.util.List;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TenantIgnore
public class NotifyTemplateDO extends BaseDO {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.oauth2;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2GrantTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
@@ -22,6 +23,7 @@ import java.util.List;
@KeySequence("system_oauth2_client_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@TenantIgnore
public class OAuth2ClientDO extends BaseDO {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.permission;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.enums.permission.MenuTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
@@ -18,6 +19,7 @@ import lombok.EqualsAndHashCode;
@KeySequence("system_menu_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
@EqualsAndHashCode(callSuper = true)
@TenantIgnore
public class MenuDO extends BaseDO {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sms;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -20,6 +21,7 @@ import lombok.ToString;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@TenantIgnore
public class SmsChannelDO extends BaseDO {
/**

View File

@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.system.dal.dataobject.sms;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
@@ -21,6 +22,7 @@ import java.time.LocalDateTime;
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TenantIgnore
public class SmsCodeDO extends BaseDO {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sms;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.enums.sms.SmsReceiveStatusEnum;
import cn.iocoder.yudao.module.system.enums.sms.SmsSendStatusEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
@@ -27,6 +28,7 @@ import java.util.Map;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TenantIgnore
public class SmsLogDO extends BaseDO {
/**

View File

@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.system.dal.dataobject.sms;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.enums.sms.SmsTemplateTypeEnum;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
@@ -24,6 +25,7 @@ import java.util.List;
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@TenantIgnore
public class SmsTemplateDO extends BaseDO {
/**

View File

@@ -7,8 +7,8 @@ import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.xingyuv.jushauth.config.AuthConfig;
import lombok.*;
import me.zhyd.oauth.config.AuthConfig;
/**
* 社交客户端 DO

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.tenant;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -22,6 +23,7 @@ import java.time.LocalDateTime;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TenantIgnore
public class TenantDO extends BaseDO {
/**

View File

@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.tenant;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import cn.iocoder.yudao.framework.tenant.core.aop.TenantIgnore;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
@@ -23,6 +24,7 @@ import java.util.Set;
@Builder
@AllArgsConstructor
@NoArgsConstructor
@TenantIgnore
public class TenantPackageDO extends BaseDO {
/**

View File

@@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.system.dal.mysql.mail;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.account.MailAccountPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailAccountDO;
import org.apache.ibatis.annotations.Mapper;
@@ -14,7 +13,8 @@ public interface MailAccountMapper extends BaseMapperX<MailAccountDO> {
default PageResult<MailAccountDO> selectPage(MailAccountPageReqVO pageReqVO) {
return selectPage(pageReqVO, new LambdaQueryWrapperX<MailAccountDO>()
.likeIfPresent(MailAccountDO::getMail, pageReqVO.getMail())
.likeIfPresent(MailAccountDO::getUsername , pageReqVO.getUsername()));
.likeIfPresent(MailAccountDO::getUsername , pageReqVO.getUsername())
.orderByDesc(MailAccountDO::getId));
}
}

View File

@@ -3,14 +3,9 @@ package cn.iocoder.yudao.module.system.dal.mysql.mail;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.QueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.mail.vo.template.MailTemplatePageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.mail.MailTemplateDO;
import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.Date;
@Mapper
public interface MailTemplateMapper extends BaseMapperX<MailTemplateDO> {
@@ -21,7 +16,8 @@ public interface MailTemplateMapper extends BaseMapperX<MailTemplateDO> {
.likeIfPresent(MailTemplateDO::getCode, pageReqVO.getCode())
.likeIfPresent(MailTemplateDO::getName, pageReqVO.getName())
.eqIfPresent(MailTemplateDO::getAccountId, pageReqVO.getAccountId())
.betweenIfPresent(MailTemplateDO::getCreateTime, pageReqVO.getCreateTime()));
.betweenIfPresent(MailTemplateDO::getCreateTime, pageReqVO.getCreateTime())
.orderByDesc(MailTemplateDO::getId));
}
default Long selectCountByAccountId(Long accountId) {

View File

@@ -1,11 +1,14 @@
package cn.iocoder.yudao.module.system.framework.captcha.config;
import cn.iocoder.yudao.module.system.framework.captcha.core.RedisCaptchaServiceImpl;
import com.xingyuv.captcha.properties.AjCaptchaProperties;
import com.xingyuv.captcha.service.CaptchaCacheService;
import com.xingyuv.captcha.service.impl.CaptchaServiceFactory;
import com.anji.captcha.config.AjCaptchaAutoConfiguration;
import com.anji.captcha.properties.AjCaptchaProperties;
import com.anji.captcha.service.CaptchaCacheService;
import com.anji.captcha.service.impl.CaptchaServiceFactory;
import org.springframework.boot.autoconfigure.ImportAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.core.StringRedisTemplate;
/**
@@ -14,9 +17,11 @@ import org.springframework.data.redis.core.StringRedisTemplate;
* @author 芋道源码
*/
@Configuration(proxyBeanMethods = false)
@ImportAutoConfiguration(AjCaptchaAutoConfiguration.class) // 目的:解决 aj-captcha 针对 SpringBoot 3.X 自动配置不生效的问题
public class YudaoCaptchaConfiguration {
@Bean
@Bean(name = "AjCaptchaCacheService")
@Primary
public CaptchaCacheService captchaCacheService(AjCaptchaProperties config,
StringRedisTemplate stringRedisTemplate) {
CaptchaCacheService captchaCacheService = CaptchaServiceFactory.getCache(config.getCacheType().name());

View File

@@ -1,6 +1,6 @@
package cn.iocoder.yudao.module.system.framework.captcha.core;
import com.xingyuv.captcha.service.CaptchaCacheService;
import com.anji.captcha.service.CaptchaCacheService;
import lombok.Setter;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -28,7 +28,7 @@ public class RedisCaptchaServiceImpl implements CaptchaCacheService {
@Override
public boolean exists(String key) {
return Boolean.TRUE.equals(stringRedisTemplate.hasKey(key));
return stringRedisTemplate.hasKey(key);
}
@Override

View File

@@ -0,0 +1,37 @@
package cn.iocoder.yudao.module.system.framework.justauth.config;
import cn.iocoder.yudao.module.system.framework.justauth.core.AuthRequestFactory;
import com.xkcoding.justauth.autoconfigure.JustAuthProperties;
import com.xkcoding.justauth.support.cache.RedisStateCache;
import me.zhyd.oauth.cache.AuthStateCache;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
/**
* JustAuth 配置类 TODO 芋艿:等 justauth 1.4.1 版本发布!!!
*
* @author 芋道源码
*/
@Configuration(proxyBeanMethods = false)
public class YudaoJustAuthConfiguration {
@Bean(name = "authRequestFactory2") // TODO @芋艿:等 justauth1.4.1 发布,可以去掉
@ConditionalOnProperty(
prefix = "justauth",
value = {"enabled"},
havingValue = "true",
matchIfMissing = true
)
public AuthRequestFactory authRequestFactory(JustAuthProperties properties, AuthStateCache authStateCache) {
return new AuthRequestFactory(properties, authStateCache);
}
@Bean
public AuthStateCache authStateCache(RedisTemplate<String, String> justAuthRedisCacheTemplate,
JustAuthProperties justAuthProperties) {
return new RedisStateCache(justAuthRedisCacheTemplate, justAuthProperties.getCache());
}
}

View File

@@ -0,0 +1,321 @@
/*
* Copyright (c) 2019-2029, xkcoding & Yangkai.Shen & 沈扬凯 (237497819@qq.com & xkcoding.com).
* <p>
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* <p>
* http://www.gnu.org/licenses/lgpl.html
* <p>
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package cn.iocoder.yudao.module.system.framework.justauth.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.EnumUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.xkcoding.http.config.HttpConfig;
import com.xkcoding.justauth.autoconfigure.ExtendProperties;
import com.xkcoding.justauth.autoconfigure.JustAuthProperties;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.cache.AuthStateCache;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.config.AuthDefaultSource;
import me.zhyd.oauth.config.AuthSource;
import me.zhyd.oauth.enums.AuthResponseStatus;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.request.*;
import org.springframework.util.CollectionUtils;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
// TODO @芋艿:等官方发布 1.4.1
/**
* <p>
* AuthRequest工厂类
* </p>
*
* @author yangkai.shen
* @date Created in 2019-07-22 14:21
*/
@Slf4j
@RequiredArgsConstructor
public class AuthRequestFactory {
private final JustAuthProperties properties;
private final AuthStateCache authStateCache;
/**
* 返回当前Oauth列表
*
* @return Oauth列表
*/
@SuppressWarnings({"unchecked", "rawtypes"})
public List<String> oauthList() {
// 默认列表
List<String> defaultList = new ArrayList<>(properties.getType().keySet());
// 扩展列表
List<String> extendList = new ArrayList<>();
ExtendProperties extend = properties.getExtend();
if (null != extend) {
Class enumClass = extend.getEnumClass();
List<String> names = EnumUtil.getNames(enumClass);
// 扩展列表
extendList = extend.getConfig()
.keySet()
.stream()
.filter(x -> names.contains(x.toUpperCase()))
.map(String::toUpperCase)
.collect(Collectors.toList());
}
// 合并
return (List<String>) CollUtil.addAll(defaultList, extendList);
}
/**
* 返回AuthRequest对象
*
* @param source {@link AuthSource}
* @return {@link AuthRequest}
*/
public AuthRequest get(String source) {
if (StrUtil.isBlank(source)) {
throw new AuthException(AuthResponseStatus.NO_AUTH_SOURCE);
}
// 获取 JustAuth 中已存在的
AuthRequest authRequest = getDefaultRequest(source);
// 如果获取不到则尝试取自定义的
if (authRequest == null) {
authRequest = getExtendRequest(properties.getExtend().getEnumClass(), source);
}
if (authRequest == null) {
throw new AuthException(AuthResponseStatus.UNSUPPORTED);
}
return authRequest;
}
/**
* 获取自定义的 request
*
* @param clazz 枚举类 {@link AuthSource}
* @param source {@link AuthSource}
* @return {@link AuthRequest}
*/
@SuppressWarnings({"unchecked", "rawtypes"})
private AuthRequest getExtendRequest(Class clazz, String source) {
String upperSource = source.toUpperCase();
try {
EnumUtil.fromString(clazz, upperSource);
} catch (IllegalArgumentException e) {
// 无自定义匹配
return null;
}
Map<String, ExtendProperties.ExtendRequestConfig> extendConfig = properties.getExtend().getConfig();
// key 转大写
Map<String, ExtendProperties.ExtendRequestConfig> upperConfig = new HashMap<>(6);
extendConfig.forEach((k, v) -> upperConfig.put(k.toUpperCase(), v));
ExtendProperties.ExtendRequestConfig extendRequestConfig = upperConfig.get(upperSource);
if (extendRequestConfig != null) {
// 配置 http config
configureHttpConfig(upperSource, extendRequestConfig, properties.getHttpConfig());
Class<? extends AuthRequest> requestClass = extendRequestConfig.getRequestClass();
if (requestClass != null) {
// 反射获取 Request 对象,所以必须实现 2 个参数的构造方法
return ReflectUtil.newInstance(requestClass, (AuthConfig) extendRequestConfig, authStateCache);
}
}
return null;
}
/**
* 获取默认的 Request
*
* @param source {@link AuthSource}
* @return {@link AuthRequest}
*/
private AuthRequest getDefaultRequest(String source) {
AuthDefaultSource authDefaultSource;
try {
authDefaultSource = EnumUtil.fromString(AuthDefaultSource.class, source.toUpperCase());
} catch (IllegalArgumentException e) {
// 无自定义匹配
return null;
}
AuthConfig config = properties.getType().get(authDefaultSource.name());
// 找不到对应关系,直接返回空
if (config == null) {
return null;
}
// 配置 http config
configureHttpConfig(authDefaultSource.name(), config, properties.getHttpConfig());
switch (authDefaultSource) {
case GITHUB:
return new AuthGithubRequest(config, authStateCache);
case WEIBO:
return new AuthWeiboRequest(config, authStateCache);
case GITEE:
return new AuthGiteeRequest(config, authStateCache);
case DINGTALK:
return new AuthDingTalkRequest(config, authStateCache);
case DINGTALK_V2:
return new AuthDingTalkV2Request(config, authStateCache);
case DINGTALK_ACCOUNT:
return new AuthDingTalkAccountRequest(config, authStateCache);
case BAIDU:
return new AuthBaiduRequest(config, authStateCache);
case CSDN:
return new AuthCsdnRequest(config, authStateCache);
case CODING:
return new AuthCodingRequest(config, authStateCache);
case OSCHINA:
return new AuthOschinaRequest(config, authStateCache);
case ALIPAY:
return new AuthAlipayRequest(config, authStateCache);
case QQ:
return new AuthQqRequest(config, authStateCache);
case WECHAT_OPEN:
return new AuthWeChatOpenRequest(config, authStateCache);
case WECHAT_MP:
return new AuthWeChatMpRequest(config, authStateCache);
case TAOBAO:
return new AuthTaobaoRequest(config, authStateCache);
case GOOGLE:
return new AuthGoogleRequest(config, authStateCache);
case FACEBOOK:
return new AuthFacebookRequest(config, authStateCache);
case DOUYIN:
return new AuthDouyinRequest(config, authStateCache);
case LINKEDIN:
return new AuthLinkedinRequest(config, authStateCache);
case MICROSOFT:
return new AuthMicrosoftRequest(config, authStateCache);
case MICROSOFT_CN:
return new AuthMicrosoftCnRequest(config, authStateCache);
case MI:
return new AuthMiRequest(config, authStateCache);
case TOUTIAO:
return new AuthToutiaoRequest(config, authStateCache);
case TEAMBITION:
return new AuthTeambitionRequest(config, authStateCache);
case RENREN:
return new AuthRenrenRequest(config, authStateCache);
case PINTEREST:
return new AuthPinterestRequest(config, authStateCache);
case STACK_OVERFLOW:
return new AuthStackOverflowRequest(config, authStateCache);
case HUAWEI:
return new AuthHuaweiRequest(config, authStateCache);
case HUAWEI_V3:
return new AuthHuaweiV3Request(config, authStateCache);
case WECHAT_ENTERPRISE:
return new AuthWeChatEnterpriseQrcodeRequest(config, authStateCache);
case WECHAT_ENTERPRISE_V2:
return new AuthWeChatEnterpriseQrcodeV2Request(config, authStateCache);
case WECHAT_ENTERPRISE_QRCODE_THIRD:
return new AuthWeChatEnterpriseThirdQrcodeRequest(config, authStateCache);
case WECHAT_ENTERPRISE_WEB:
return new AuthWeChatEnterpriseWebRequest(config, authStateCache);
case KUJIALE:
return new AuthKujialeRequest(config, authStateCache);
case GITLAB:
return new AuthGitlabRequest(config, authStateCache);
case MEITUAN:
return new AuthMeituanRequest(config, authStateCache);
case ELEME:
return new AuthElemeRequest(config, authStateCache);
case TWITTER:
return new AuthTwitterRequest(config, authStateCache);
case FEISHU:
return new AuthFeishuRequest(config, authStateCache);
case JD:
return new AuthJdRequest(config, authStateCache);
case ALIYUN:
return new AuthAliyunRequest(config, authStateCache);
case XMLY:
return new AuthXmlyRequest(config, authStateCache);
case AMAZON:
return new AuthAmazonRequest(config, authStateCache);
case SLACK:
return new AuthSlackRequest(config, authStateCache);
case LINE:
return new AuthLineRequest(config, authStateCache);
case OKTA:
return new AuthOktaRequest(config, authStateCache);
case PROGINN:
return new AuthProginnRequest(config,authStateCache);
case AFDIAN:
return new AuthAfDianRequest(config,authStateCache);
case APPLE:
return new AuthAppleRequest(config,authStateCache);
case FIGMA:
return new AuthFigmaRequest(config,authStateCache);
case WECHAT_MINI_PROGRAM:
config.setIgnoreCheckRedirectUri(true);
config.setIgnoreCheckState(true);
return new AuthWechatMiniProgramRequest(config, authStateCache);
case QQ_MINI_PROGRAM:
config.setIgnoreCheckRedirectUri(true);
config.setIgnoreCheckState(true);
return new AuthQQMiniProgramRequest(config, authStateCache);
default:
return null;
}
}
/**
* 配置 http 相关的配置
*
* @param authSource {@link AuthSource}
* @param authConfig {@link AuthConfig}
*/
private void configureHttpConfig(String authSource, AuthConfig authConfig, JustAuthProperties.JustAuthHttpConfig httpConfig) {
if (null == httpConfig) {
return;
}
Map<String, JustAuthProperties.JustAuthProxyConfig> proxyConfigMap = httpConfig.getProxy();
if (CollectionUtils.isEmpty(proxyConfigMap)) {
return;
}
JustAuthProperties.JustAuthProxyConfig proxyConfig = proxyConfigMap.get(authSource);
if (null == proxyConfig) {
return;
}
authConfig.setHttpConfig(HttpConfig.builder()
.timeout(httpConfig.getTimeout())
.proxy(new Proxy(Proxy.Type.valueOf(proxyConfig.getType()), new InetSocketAddress(proxyConfig.getHostname(), proxyConfig.getPort())))
.build());
}
}

View File

@@ -0,0 +1,6 @@
/**
* justauth 三方登录的拓展
*
* @author 芋道源码
*/
package cn.iocoder.yudao.module.system.framework.justauth;

View File

@@ -24,10 +24,10 @@ import cn.iocoder.yudao.module.system.service.member.MemberService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.anji.captcha.model.common.ResponseModel;
import com.anji.captcha.model.vo.CaptchaVO;
import com.anji.captcha.service.CaptchaService;
import com.google.common.annotations.VisibleForTesting;
import com.xingyuv.captcha.model.common.ResponseModel;
import com.xingyuv.captcha.model.vo.CaptchaVO;
import com.xingyuv.captcha.service.CaptchaService;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;

View File

@@ -3,18 +3,19 @@ package cn.iocoder.yudao.module.system.service.social;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaOrderNotifyConfirmReceiveReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaOrderUploadShippingInfoReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import com.xingyuv.jushauth.model.AuthUser;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
import me.chanjar.weixin.common.bean.subscribemsg.TemplateInfo;
import java.util.List;
import me.zhyd.oauth.model.AuthUser;
import javax.validation.Valid;
import java.util.List;
/**
* 社交应用 Service 接口
@@ -93,6 +94,22 @@ public interface SocialClientService {
*/
void sendSubscribeMessage(SocialWxaSubscribeMessageSendReqDTO reqDTO, String templateId, String openId);
/**
* 上传订单发货到微信小程序
*
* @param userType 用户类型
* @param reqDTO 请求
*/
void uploadWxaOrderShippingInfo(Integer userType, SocialWxaOrderUploadShippingInfoReqDTO reqDTO);
/**
* 通知订单收货到微信小程序
*
* @param userType 用户类型
* @param reqDTO 请求
*/
void notifyWxaOrderConfirmReceive(Integer userType, SocialWxaOrderNotifyConfirmReceiveReqDTO reqDTO);
// =================== 客户端管理 ===================
/**

View File

@@ -5,11 +5,15 @@ import cn.binarywang.wx.miniapp.api.WxMaSubscribeService;
import cn.binarywang.wx.miniapp.api.impl.WxMaServiceImpl;
import cn.binarywang.wx.miniapp.bean.WxMaPhoneNumberInfo;
import cn.binarywang.wx.miniapp.bean.WxMaSubscribeMessage;
import cn.binarywang.wx.miniapp.bean.shop.request.shipping.*;
import cn.binarywang.wx.miniapp.bean.shop.response.WxMaOrderShippingInfoBaseResponse;
import cn.binarywang.wx.miniapp.config.impl.WxMaRedisBetterConfigImpl;
import cn.binarywang.wx.miniapp.constant.WxMaConstants;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.DesensitizedUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
@@ -19,6 +23,8 @@ import cn.iocoder.yudao.framework.common.util.cache.CacheUtils;
import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaOrderNotifyConfirmReceiveReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaOrderUploadShippingInfoReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxaSubscribeMessageSendReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.client.SocialClientSaveReqVO;
@@ -26,18 +32,12 @@ import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
import cn.iocoder.yudao.module.system.dal.mysql.social.SocialClientMapper;
import cn.iocoder.yudao.module.system.dal.redis.RedisKeyConstants;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import cn.iocoder.yudao.module.system.framework.justauth.core.AuthRequestFactory;
import com.binarywang.spring.starter.wxjava.miniapp.properties.WxMaProperties;
import com.binarywang.spring.starter.wxjava.mp.properties.WxMpProperties;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.xingyuv.jushauth.config.AuthConfig;
import com.xingyuv.jushauth.model.AuthCallback;
import com.xingyuv.jushauth.model.AuthResponse;
import com.xingyuv.jushauth.model.AuthUser;
import com.xingyuv.jushauth.request.AuthRequest;
import com.xingyuv.jushauth.utils.AuthStateUtils;
import com.xingyuv.justauth.AuthRequestFactory;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxJsapiSignature;
@@ -47,6 +47,13 @@ import me.chanjar.weixin.common.redis.RedisTemplateWxRedisOps;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.api.impl.WxMpServiceImpl;
import me.chanjar.weixin.mp.config.impl.WxMpRedisConfigImpl;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthCallback;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.request.AuthRequest;
import me.zhyd.oauth.utils.AuthStateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.StringRedisTemplate;
@@ -54,14 +61,17 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.time.Duration;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.UTC_MS_WITH_XXX_OFFSET_FORMATTER;
import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
import static java.util.Collections.singletonList;
/**
* 社交应用 Service 实现类
@@ -91,7 +101,8 @@ public class SocialClientServiceImpl implements SocialClientService {
@Value("${yudao.wxa-subscribe-message.miniprogram-state:formal}")
public String miniprogramState;
@Resource
// @Resource
@Autowired // TODO @芋艿:等 justauth1.4.1 发布,可以去掉
private AuthRequestFactory authRequestFactory;
@Resource
@@ -327,6 +338,64 @@ public class SocialClientServiceImpl implements SocialClientService {
return subscribeMessage;
}
@Override
public void uploadWxaOrderShippingInfo(Integer userType, SocialWxaOrderUploadShippingInfoReqDTO reqDTO) {
WxMaService service = getWxMaService(userType);
List<ShippingListBean> shippingList;
if (Objects.equals(reqDTO.getLogisticsType(), SocialWxaOrderUploadShippingInfoReqDTO.LOGISTICS_TYPE_EXPRESS)) {
shippingList = singletonList(ShippingListBean.builder()
.trackingNo(reqDTO.getLogisticsNo())
.expressCompany(reqDTO.getExpressCompany())
.itemDesc(reqDTO.getItemDesc())
.contact(ContactBean.builder().receiverContact(DesensitizedUtil.mobilePhone(reqDTO.getReceiverContact())).build())
.build());
} else {
shippingList = singletonList(ShippingListBean.builder().itemDesc(reqDTO.getItemDesc()).build());
}
WxMaOrderShippingInfoUploadRequest request = WxMaOrderShippingInfoUploadRequest.builder()
.orderKey(OrderKeyBean.builder()
.orderNumberType(2) // 使用原支付交易对应的微信订单号,即渠道单号
.transactionId(reqDTO.getTransactionId())
.build())
.logisticsType(reqDTO.getLogisticsType()) // 配送方式
.deliveryMode(1) // 统一发货
.shippingList(shippingList)
.payer(PayerBean.builder().openid(reqDTO.getOpenid()).build())
.uploadTime(ZonedDateTime.now().format(UTC_MS_WITH_XXX_OFFSET_FORMATTER))
.build();
try {
WxMaOrderShippingInfoBaseResponse response = service.getWxMaOrderShippingService().upload(request);
if (response.getErrCode() != 0) {
log.error("[uploadWxaOrderShippingInfo][上传微信小程序发货信息失败request({}) response({})]", request, response);
throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_UPLOAD_SHIPPING_INFO_ERROR, response.getErrMsg());
}
log.info("[uploadWxaOrderShippingInfo][上传微信小程序发货信息成功request({}) response({})]", request, response);
} catch (WxErrorException ex) {
log.error("[uploadWxaOrderShippingInfo][上传微信小程序发货信息失败request({})]", request, ex);
throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_UPLOAD_SHIPPING_INFO_ERROR, ex.getError().getErrorMsg());
}
}
@Override
public void notifyWxaOrderConfirmReceive(Integer userType, SocialWxaOrderNotifyConfirmReceiveReqDTO reqDTO) {
WxMaService service = getWxMaService(userType);
WxMaOrderShippingInfoNotifyConfirmRequest request = WxMaOrderShippingInfoNotifyConfirmRequest.builder()
.transactionId(reqDTO.getTransactionId())
.receivedTime(LocalDateTimeUtil.toEpochMilli(reqDTO.getReceivedTime()))
.build();
try {
WxMaOrderShippingInfoBaseResponse response = service.getWxMaOrderShippingService().notifyConfirmReceive(request);
if (response.getErrCode() != 0) {
log.error("[notifyWxaOrderConfirmReceive][确认收货提醒到微信小程序失败request({}) response({})]", request, response);
throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_NOTIFY_CONFIRM_RECEIVE_ERROR, response.getErrMsg());
}
log.info("[notifyWxaOrderConfirmReceive][确认收货提醒到微信小程序成功request({}) response({})]", request, response);
} catch (WxErrorException ex) {
log.error("[notifyWxaOrderConfirmReceive][确认收货提醒到微信小程序失败request({})]", request, ex);
throw exception(SOCIAL_CLIENT_WEIXIN_MINI_APP_ORDER_NOTIFY_CONFIRM_RECEIVE_ERROR, ex.getError().getErrorMsg());
}
}
/**
* 获得 clientId + clientSecret 对应的 WxMpService 对象
*
@@ -337,7 +406,7 @@ public class SocialClientServiceImpl implements SocialClientService {
WxMaService getWxMaService(Integer userType) {
// 第一步,查询 DB 的配置项,获得对应的 WxMaService 对象
SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(
SocialTypeEnum.WECHAT_MINI_APP.getType(), userType);
SocialTypeEnum.WECHAT_MINI_PROGRAM.getType(), userType);
if (client != null && Objects.equals(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
return wxMaServiceCache.getUnchecked(client.getClientId() + ":" + client.getClientSecret());
}

View File

@@ -6,15 +6,14 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialWxQrcodeReqDTO;
import cn.iocoder.yudao.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper;
import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper;
import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
import com.xingyuv.jushauth.model.AuthUser;
import lombok.extern.slf4j.Slf4j;
import me.zhyd.oauth.model.AuthUser;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

View File

@@ -9,6 +9,7 @@ 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.object.BeanUtils;
import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission;
import cn.iocoder.yudao.framework.tenant.config.TenantProperties;
import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.framework.tenant.core.util.TenantUtils;
@@ -96,6 +97,7 @@ public class TenantServiceImpl implements TenantService {
@Override
@DSTransactional // 多数据源,使用 @DSTransactional 保证本地事务,以及数据源的切换
@DataPermission(enable = false) // 参见 https://gitee.com/zhijiantianya/ruoyi-vue-pro/pulls/1154 说明
public Long createTenant(TenantSaveReqVO createReqVO) {
// 校验租户名称是否重复
validTenantNameDuplicate(createReqVO.getName(), null);

View File

@@ -11,9 +11,8 @@ import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRe
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
import javax.validation.Valid;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
@@ -73,14 +72,6 @@ public interface AdminUserService {
*/
void updateUserPassword(Long id, @Valid UserProfileUpdatePasswordReqVO reqVO);
/**
* 更新用户头像
*
* @param id 用户 id
* @param avatarFile 头像文件
*/
String updateUserAvatar(Long id, InputStream avatarFile) throws Exception;
/**
* 修改密码
*

View File

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.service.user;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
@@ -61,6 +62,8 @@ public class AdminUserServiceImpl implements AdminUserService {
static final String USER_INIT_PASSWORD_KEY = "system.user.init-password";
static final String USER_REGISTER_ENABLED_KEY = "system.user.register-enabled";
@Resource
private AdminUserMapper userMapper;
@@ -79,8 +82,6 @@ public class AdminUserServiceImpl implements AdminUserService {
@Resource
private UserPostMapper userPostMapper;
@Resource
private FileApi fileApi;
@Resource
private ConfigApi configApi;
@@ -117,14 +118,18 @@ public class AdminUserServiceImpl implements AdminUserService {
@Override
public Long registerUser(AuthRegisterReqVO registerReqVO) {
// 1.1 校验账户配合
// 1.1 校验是否开启注册
if (ObjUtil.notEqual(configApi.getConfigValueByKey(USER_REGISTER_ENABLED_KEY), "true")) {
throw exception(USER_REGISTER_DISABLED);
}
// 1.2 校验账户配合
tenantService.handleTenantInfo(tenant -> {
long count = userMapper.selectCount();
if (count >= tenant.getAccountCount()) {
throw exception(USER_COUNT_MAX, tenant.getAccountCount());
}
});
// 1.2 校验正确性
// 1.3 校验正确性
validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, null, null);
// 2. 插入用户
@@ -198,19 +203,6 @@ public class AdminUserServiceImpl implements AdminUserService {
userMapper.updateById(updateObj);
}
@Override
public String updateUserAvatar(Long id, InputStream avatarFile) {
validateUserExists(id);
// 存储文件
String avatar = fileApi.createFile(IoUtil.readBytes(avatarFile));
// 更新路径
AdminUserDO sysUserDO = new AdminUserDO();
sysUserDO.setId(id);
sysUserDO.setAvatar(avatar);
userMapper.updateById(sysUserDO);
return avatar;
}
@Override
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_PASSWORD_SUB_TYPE, bizNo = "{{#id}}",
success = SYSTEM_USER_UPDATE_PASSWORD_SUCCESS)

View File

@@ -1 +1 @@
cn.iocoder.yudao.module.system.framework.captcha.core.RedisCaptchaServiceImpl
cn.iocoder.yudao.module.system.framework.captcha.core.RedisCaptchaServiceImpl