From e7a77fffb72595958d245598c4abe87c6b4b84b6 Mon Sep 17 00:00:00 2001
From: zouyu <2723363702@qq.com>
Date: 星期六, 01 三月 2025 16:59:06 +0800
Subject: [PATCH] 初始化
---
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java | 16
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodListServiceImpl.java | 150
basic-server/src/main/resources/mapper/StandardProductListMapper.xml | 144
ruoyi-admin/src/main/java/com/ruoyi/CodeGenerator.java | 104
basic-server/src/main/resources/mapper/StructureTestObjectPartMapper.xml | 8
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java | 76
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java | 16
basic-server/src/main/java/com/ruoyi/basic/pojo/Laboratory.java | 62
performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryCorrectionHoursServiceImpl.java | 104
ruoyi-system/src/main/resources/mapper/system/CustomMapper.xml | 14
basic-server/src/main/java/com/ruoyi/basic/mapper/CertificationMapper.java | 14
ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java | 570
performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOutputWorkingHoursDto.java | 19
performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOriginalHoursService.java | 30
performance-server/src/main/java/com/ruoyi/performance/controller/ShiftTimeController.java | 55
basic-server/src/main/java/com/ruoyi/basic/dto/SampleDto.java | 23
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java | 73
basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodListMapper.java | 40
ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java | 484
basic-server/src/main/resources/mapper/ProductPartMapper.xml | 10
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java | 75
ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm | 590
basic-server/src/main/java/com/ruoyi/basic/service/StructureItemParameterService.java | 8
ruoyi-generator/pom.xml | 40
performance-server/src/main/java/com/ruoyi/performance/service/PerformanceShiftService.java | 32
basic-server/src/main/java/com/ruoyi/basic/controller/ProductSupplierDensityController.java | 59
ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm | 76
performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursMapper.xml | 38
basic-server/src/main/java/com/ruoyi/basic/controller/StructureTestObjectPartController.java | 59
ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java | 59
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java | 76
basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java | 24
basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureItemParameterServiceImpl.java | 24
ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java | 130
basic-server/src/main/java/com/ruoyi/basic/mapper/ProductSupplierDensityMapper.java | 22
ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml | 117
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java | 92
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java | 163
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java | 18
pom.xml | 385
ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java | 85
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java | 99
basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeMapper.java | 92
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java | 89
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java | 61
basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectData.java | 25
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java | 76
ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java | 43
performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOriginalHoursMapper.java | 13
ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml | 89
ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java | 30
basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java | 52
ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java | 49
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java | 191
ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberTableInfo.java | 16
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java | 18
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java | 142
basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java | 276
ruoyi-common/src/main/java/com/ruoyi/common/numgen/SerializedLambda.java | 143
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java | 115
performance-server/src/main/resources/mapper/AuxiliaryOutputWorkingHoursMapper.xml | 186
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java | 144
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java | 28
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java | 202
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java | 144
basic-server/src/main/java/com/ruoyi/basic/pojo/Certification.java | 72
ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java | 94
ruoyi-system/src/main/java/com/ruoyi/system/service/CustomService.java | 28
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java | 535
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java | 89
ruoyi-generator/src/main/resources/vm/sql/sql.vm | 22
performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursController.java | 59
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java | 121
basic-server/src/main/java/com/ruoyi/basic/dto/CopyStandardProductListDto.java | 23
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Custom.java | 65
ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java | 268
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java | 68
basic-server/src/main/java/com/ruoyi/basic/controller/StandardTemplateController.java | 68
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java | 87
ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java | 20
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethodList.java | 83
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java | 97
performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursDayService.java | 44
basic-server/src/main/java/com/ruoyi/basic/service/LaboratoryService.java | 27
bin/run.bat | 14
performance-server/src/main/resources/mapper/PerformanceShiftMapper.xml | 135
bin/package.bat | 12
basic-server/src/main/java/com/ruoyi/basic/pojo/Seal.java | 43
LICENSE | 20
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java | 80
performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursLookDto.java | 26
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java | 34
performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOutputWorkingHoursController.java | 74
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java | 44
ruoyi-generator/src/main/resources/vm/java/service.java.vm | 61
ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java | 171
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java | 141
ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java | 20
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java | 46
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java | 19
basic-server/src/main/java/com/ruoyi/basic/mapper/LaboratoryMapper.java | 20
basic-server/src/main/java/com/ruoyi/basic/pojo/InsSample1.java | 123
basic-server/src/main/resources/mapper/StandardTemplateMapper.xml | 40
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java | 61
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java | 46
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java | 216
basic-server/src/main/java/com/ruoyi/basic/service/ProductSupplierDensityService.java | 22
ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java | 117
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java | 130
ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java | 18
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java | 106
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java | 184
performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryCorrectionHoursMapper.java | 27
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductList.java | 221
ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java | 31
ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java | 408
ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java | 57
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java | 178
ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml | 143
ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java | 183
ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java | 110
ruoyi-generator/src/main/resources/vm/java/domain.java.vm | 105
basic-server/src/main/java/com/ruoyi/basic/service/StandardTemplateService.java | 34
basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodListService.java | 28
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java | 46
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java | 44
performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryCorrectionHoursController.java | 59
basic-server/src/main/java/com/ruoyi/basic/service/ProductPartService.java | 14
ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml | 94
ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml | 87
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java | 77
ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java | 53
basic-server/src/main/resources/mapper/StandardMethodListMapper.xml | 99
basic-server/src/main/java/com/ruoyi/basic/controller/SealController.java | 50
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java | 82
ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java | 99
ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java | 146
ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java | 148
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java | 101
basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObject.java | 63
ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java | 83
ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java | 27
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java | 56
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java | 48
basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObjectPart.java | 56
performance-server/src/main/java/com/ruoyi/performance/utils/CustomerDoubleSerialize.java | 26
ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml | 127
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java | 261
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java | 96
ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm | 140
basic-server/src/main/java/com/ruoyi/basic/dto/TestItemDto.java | 16
performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursDayController.java | 101
ruoyi-system/src/main/java/com/ruoyi/system/service/UserService.java | 15
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java | 127
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java | 241
ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml | 152
basic-server/src/main/resources/mapper/StandardTreeMapper.xml | 384
ry.sh | 86
basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodMapper.java | 26
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java | 24
basic-server/src/main/java/com/ruoyi/basic/pojo/ProductSupplierDensity.java | 57
ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java | 120
ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml | 57
basic-server/src/main/java/com/ruoyi/basic/pojo/IfsInventoryQuantity.java | 210
basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectPartService.java | 22
performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOutputWorkingHoursService.java | 44
ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MySqlInjector.java | 24
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomServiceImpl.java | 62
performance-server/src/main/resources/mapper/AuxiliaryCorrectionHoursMapper.xml | 75
ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java | 111
ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java | 27
basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java | 22
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java | 231
performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryCorrectionHours.java | 181
basic-server/src/main/java/com/ruoyi/basic/mapper/SealMapper.java | 17
ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java | 58
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml | 233
basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListSupplierAskService.java | 23
ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java | 86
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java | 11
basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductSupplierDensityServiceImpl.java | 64
performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOutputWorkingHoursServiceImpl.java | 260
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java | 373
ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java | 74
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java | 130
ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGeneratorModelHelper.java | 107
ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java | 173
ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java | 126
basic-server/src/main/java/com/ruoyi/basic/dto/SampleTypeDto.java | 29
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java | 63
basic-server/src/main/java/com/ruoyi/basic/dto/ModelDto.java | 15
ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java | 39
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java | 124
ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java | 382
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java | 95
ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java | 28
ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml | 34
basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService2.java | 13
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java | 59
ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm | 505
basic-server/src/main/java/com/ruoyi/basic/service/impl/LaboratoryServiceImpl.java | 53
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java | 79
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java | 129
basic-server/src/main/resources/mapper/StandardProductListSupplierAskMapper.xml | 5
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java | 98
ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml | 210
ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java | 15
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java | 232
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java | 182
performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursService.java | 26
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java | 118
basic-server/src/main/java/com/ruoyi/basic/controller/LaboratoryController.java | 62
ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java | 385
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java | 67
ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java | 70
performance-server/src/main/java/com/ruoyi/performance/excel/AuxiliaryCorrectionHoursListener.java | 41
ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java | 101
basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java | 393
ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java | 87
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java | 42
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java | 232
ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm | 474
performance-server/src/main/java/com/ruoyi/performance/pojo/PerformanceShift.java | 54
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java | 40
ruoyi-generator/src/main/resources/generator.yml | 12
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/UserController.java | 25
ruoyi-generator/src/main/resources/vm/js/api.js.vm | 44
README.md | 95
ruoyi-admin/src/main/resources/banner.txt | 24
performance-server/src/main/java/com/ruoyi/performance/service/ShiftTimeService.java | 22
ruoyi-common/src/main/java/com/ruoyi/common/utils/QueryWrappers.java | 68
ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java | 92
ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java | 114
basic-server/pom.xml | 33
ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java | 45
performance-server/src/main/java/com/ruoyi/performance/pojo/ShiftTime.java | 54
basic-server/src/main/java/com/ruoyi/basic/service/CapacityScopeService.java | 46
basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java | 188
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java | 107
basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectListener.java | 38
ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java | 50
basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java | 121
ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java | 44
basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectPartServiceImpl.java | 75
ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java | 1010 +
ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGenerator.java | 146
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java | 181
performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryAllDto.java | 35
performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryWorkingHoursDayDto.java | 16
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java | 76
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java | 543
basic-server/src/main/resources/mapper/SealMapper.xml | 19
basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectPartMapper.java | 21
basic-server/src/main/resources/mapper/CertificationMapper.xml | 19
basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListMapper.java | 69
basic-server/src/main/java/com/ruoyi/basic/service/impl/CertificationServiceImpl.java | 45
ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java | 684
basic-server/src/main/java/com/ruoyi/basic/mapper/StructureItemParameterMapper.java | 30
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java | 30
ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml | 122
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java | 262
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java | 131
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListService2Impl.java | 12
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListSupplierAskServiceImpl.java | 79
ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java | 68
ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java | 69
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java | 16
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java | 69
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java | 427
ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java | 59
performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOriginalHoursServiceImpl.java | 635
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/MinioResult.java | 16
ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java | 263
ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java | 218
performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHours.java | 60
ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java | 18
ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java | 110
ruoyi-quartz/pom.xml | 40
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java | 203
ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java | 167
ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java | 33
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java | 111
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java | 83
ruoyi-generator/src/main/resources/vm/java/controller.java.vm | 115
inspect-server/pom.xml | 34
basic-server/src/main/resources/mapper/StandardMethodMapper.xml | 67
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java | 19
ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java | 56
ruoyi-common/src/main/java/com/ruoyi/common/numgen/LambdaUtils.java | 127
ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java | 26
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MinioUtils.java | 294
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java | 24
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java | 274
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java | 84
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java | 113
performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursMapper.java | 19
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java | 16
basic-server/src/main/java/com/ruoyi/basic/pojo/ProductPart.java | 49
basic-server/src/main/java/com/ruoyi/basic/controller/CertificationController.java | 41
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java | 338
performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftAddDto.java | 27
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java | 102
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java | 269
ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java | 531
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java | 121
ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java | 86
bin/clean.bat | 12
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java | 1900 ++
basic-server/src/main/resources/mapper/ProductSupplierDensityMapper.xml | 8
performance-server/src/main/java/com/ruoyi/performance/dto/HoursDay.java | 15
ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java | 94
ruoyi-framework/pom.xml | 64
basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectServiceImpl.java | 19
basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService.java | 67
ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java | 52
performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java | 563
performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursServiceImpl.java | 55
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java | 173
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java | 550
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java | 19
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java | 132
basic-server/src/main/java/com/ruoyi/basic/mapper/ProductPartMapper.java | 13
basic-server/src/main/resources/mapper/StructureItemParameterMapper.xml | 121
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java | 16
ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java | 122
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java | 72
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java | 363
ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java | 16
performance-server/src/main/java/com/ruoyi/performance/controller/PerformanceShiftController.java | 152
ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java | 257
basic-server/src/main/resources/mapper/ProductMapper.xml | 44
basic-server/src/main/java/com/ruoyi/basic/dto/PageTestObjectDto.java | 25
performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursDayServiceImpl.java | 232
ry.bat | 67
ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java | 58
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java | 115
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java | 63
ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml | 44
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java | 66
basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTemplateMapper.java | 32
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java | 99
performance-server/src/main/java/com/ruoyi/performance/mapper/ShiftTimeMapper.java | 16
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java | 139
ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java | 81
basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodService.java | 30
.gitignore | 51
ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java | 89
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java | 48
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java | 52
ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java | 178
ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml | 159
basic-server/src/main/java/com/ruoyi/basic/controller/ProductPartController.java | 50
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java | 176
ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBaseMapper.java | 15
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java | 206
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java | 256
ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java | 56
basic-server/src/main/resources/mapper/IfsInventoryQuantityMapper.xml | 74
ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java | 34
basic-server/src/main/java/com/ruoyi/basic/dto/ResetTreeDragDTO.java | 26
ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java | 158
ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java | 155
ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml | 20
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java | 44
basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityCheckDto.java | 182
basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java | 185
ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java | 36
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java | 159
basic-server/src/main/java/com/ruoyi/basic/mapper/IfsInventoryQuantityMapper.java | 42
basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListSupplierAskMapper.java | 18
performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryCorrectionHoursService.java | 29
ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java | 26
basic-server/src/main/java/com/ruoyi/basic/dto/ProductDTO1.java | 16
ruoyi-admin/src/main/resources/application-druid.yml | 71
ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java | 49
ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java | 254
performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursDayMapper.java | 43
basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantitySupplierDto.java | 124
performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOriginalHoursController.java | 44
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java | 91
basic-server/src/main/java/com/ruoyi/basic/controller/StandardMethodController.java | 59
basic-server/src/main/java/com/ruoyi/basic/service/CertificationService.java | 17
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java | 118
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java | 96
basic-server/src/main/java/com/ruoyi/basic/service/ProductService.java | 28
ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm | 169
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java | 111
ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java | 55
ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java | 24
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java | 102
ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java | 34
ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java | 39
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java | 238
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListServiceImpl.java | 701
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java | 107
ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java | 21
ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java | 67
ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java | 291
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java | 86
ruoyi-generator/src/main/resources/vm/vue/index.vue.vm | 602
basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityDto.java | 82
performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryOutputWorkingHours.java | 123
ruoyi-admin/src/main/resources/application.yml | 132
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethod.java | 85
performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOutputWorkingHoursMapper.java | 55
ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java | 56
ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java | 410
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java | 114
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java | 60
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java | 92
basic-server/src/main/java/com/ruoyi/basic/dto/LaboratoryDto.java | 18
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java | 274
ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java | 240
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java | 291
basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectService.java | 15
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java | 65
basic-server/src/main/java/com/ruoyi/basic/dto/InsSampleReceiveDto.java | 35
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java | 16
basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java | 260
ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java | 40
ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml | 111
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java | 29
ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java | 35
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java | 60
performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHoursDay.java | 113
ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java | 55
performance-server/src/main/java/com/ruoyi/performance/utils/StyleYearUtils.java | 89
ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java | 19
ruoyi-system/pom.xml | 28
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java | 93
performance-server/src/main/resources/mapper/ShiftTimeMapper.xml | 17
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java | 62
performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryCorrectionHoursDto.java | 22
basic-server/src/main/java/com/ruoyi/basic/dto/FactoryDto.java | 18
performance-server/pom.xml | 34
ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml | 34
ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java | 97
ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties | 1
ruoyi-generator/src/main/resources/vm/java/mapper.java.vm | 91
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java | 24
ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java | 28
performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursDayMapper.xml | 116
performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftMapDto.java | 27
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java | 46
basic-server/src/main/java/com/ruoyi/basic/dto/ProductDto.java | 11
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java | 266
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java | 69
ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml | 124
basic-server/src/main/resources/mapper/StructureTestMapper.xml | 36
basic-server/src/main/java/com/ruoyi/basic/service/impl/SealServiceImpl.java | 39
performance-server/src/main/resources/mapper/AuxiliaryOriginalHoursMapper.xml | 59
ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java | 239
performance-server/src/main/java/com/ruoyi/performance/service/impl/ShiftTimeServiceImpl.java | 41
ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java | 44
performance-server/src/main/java/com/ruoyi/performance/mapper/PerformanceShiftMapper.java | 41
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java | 88
basic-server/src/main/java/com/ruoyi/basic/pojo/Product.java | 57
ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java | 32
ruoyi-common/src/main/java/com/ruoyi/common/utils/JackSonUtil.java | 133
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTree.java | 96
inspect-server/src/main/java/com/ruoyi/basic/pojo/InsSample.java | 123
ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java | 16
performance-server/src/main/java/com/ruoyi/performance/utils/StyleMonthUtils.java | 86
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java | 133
ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java | 64
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java | 81
basic-server/src/main/resources/mapper/LaboratoryMapper.xml | 42
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserServiceImpl.java | 19
ruoyi-admin/src/main/resources/i18n/messages.properties | 38
ruoyi-admin/src/main/resources/logback.xml | 93
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java | 140
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java | 60
ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml | 206
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java | 125
ruoyi-common/src/main/java/com/ruoyi/common/handler/MybatisHandler.java | 38
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java | 197
ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java | 67
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/User.java | 100
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java | 91
performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursDto.java | 251
ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java | 51
ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java | 106
basic-server/src/main/java/com/ruoyi/basic/service/SealService.java | 24
ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml | 34
basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductListSupplierAsk.java | 58
ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java | 20
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/CustomController.java | 62
ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java | 27
basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductPartServiceImpl.java | 68
ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java | 60
ruoyi-admin/pom.xml | 122
ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java | 185
ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java | 44
ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java | 27
ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java | 39
ruoyi-common/pom.xml | 150
ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java | 102
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomMapper.java | 18
ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBatisPlusConfig.java | 27
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java | 38
ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java | 26
ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java | 76
ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserMapper.java | 15
ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java | 88
ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java | 24
ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java | 48
ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java | 124
507 files changed, 54,027 insertions(+), 2 deletions(-)
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..6bb8c15
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,51 @@
+######################################################################
+# Build Tools
+
+.gradle
+/build/
+!gradle/wrapper/gradle-wrapper.jar
+
+target/
+!.mvn/wrapper/maven-wrapper.jar
+
+######################################################################
+# IDE
+
+### STS ###
+.apt_generated
+.classpath
+.factorypath
+.project
+.settings
+.springBeans
+
+### IntelliJ IDEA ###
+.idea
+*.iws
+*.iml
+*.ipr
+
+### JRebel ###
+rebel.xml
+
+### NetBeans ###
+nbproject/private/
+build/*
+nbbuild/
+dist/
+nbdist/
+.nb-gradle/
+
+######################################################################
+# Others
+*.log
+*.xml.versionsBackup
+*.swp
+
+!*/build/*.java
+!*/build/*.html
+!*/build/*.xml
+#/ruoyi-admin/src/main/resources/application.yml
+#/ruoyi-admin/src/main/resources/application-druid.yml
+#/ruoyi-admin/src/main/resources/logback.xml
+#/ruoyi-generator/src/main/resources/generator.yml
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..8564f29
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2018 RuoYi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
diff --git a/README.md b/README.md
index b5d45e5..058fd43 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,95 @@
-## center-lims-after-ruoyi
+<p align="center">
+ <img alt="logo" src="https://oscimg.oschina.net/oscnet/up-d3d0a9303e11d522a06cd263f3079027715.png">
+</p>
+<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">RuoYi v3.8.9</h1>
+<h4 align="center">鍩轰簬SpringBoot+Vue鍓嶅悗绔垎绂荤殑Java蹇�熷紑鍙戞鏋�</h4>
+<p align="center">
+ <a href="https://gitee.com/y_project/RuoYi-Vue/stargazers"><img src="https://gitee.com/y_project/RuoYi-Vue/badge/star.svg?theme=dark"></a>
+ <a href="https://gitee.com/y_project/RuoYi-Vue"><img src="https://img.shields.io/badge/RuoYi-v3.8.9-brightgreen.svg"></a>
+ <a href="https://gitee.com/y_project/RuoYi-Vue/blob/master/LICENSE"><img src="https://img.shields.io/github/license/mashape/apistatus.svg"></a>
+</p>
-妫�娴嬩腑蹇僉IMS鏂板悗绔�
+## 骞冲彴绠�浠�
+鑻ヤ緷鏄竴濂楀叏閮ㄥ紑婧愮殑蹇�熷紑鍙戝钩鍙帮紝姣棤淇濈暀缁欎釜浜哄強浼佷笟鍏嶈垂浣跨敤銆�
+
+* 鍓嶇閲囩敤Vue銆丒lement UI銆�
+* 鍚庣閲囩敤Spring Boot銆丼pring Security銆丷edis & Jwt銆�
+* 鏉冮檺璁よ瘉浣跨敤Jwt锛屾敮鎸佸缁堢璁よ瘉绯荤粺銆�
+* 鏀寔鍔犺浇鍔ㄦ�佹潈闄愯彍鍗曪紝澶氭柟寮忚交鏉炬潈闄愭帶鍒躲��
+* 楂樻晥鐜囧紑鍙戯紝浣跨敤浠g爜鐢熸垚鍣ㄥ彲浠ヤ竴閿敓鎴愬墠鍚庣浠g爜銆�
+* 鎻愪緵浜嗘妧鏈爤锛圼Vue3](https://v3.cn.vuejs.org) [Element Plus](https://element-plus.org/zh-CN) [Vite](https://cn.vitejs.dev)锛夌増鏈琜RuoYi-Vue3](https://gitcode.com/yangzongzhuan/RuoYi-Vue3)锛屼繚鎸佸悓姝ユ洿鏂般��
+* 鎻愪緵浜嗗崟搴旂敤鐗堟湰[RuoYi-Vue-fast](https://gitcode.com/yangzongzhuan/RuoYi-Vue-fast)锛孫racle鐗堟湰[RuoYi-Vue-Oracle](https://gitcode.com/yangzongzhuan/RuoYi-Vue-Oracle)锛屼繚鎸佸悓姝ユ洿鏂般��
+* 涓嶅垎绂荤増鏈紝璇风Щ姝RuoYi](https://gitee.com/y_project/RuoYi)锛屽井鏈嶅姟鐗堟湰锛岃绉绘[RuoYi-Cloud](https://gitee.com/y_project/RuoYi-Cloud)
+* 闃块噷浜戞姌鎵e満锛歔鐐规垜杩涘叆](http://aly.ruoyi.vip)锛岃吘璁簯绉掓潃鍦猴細[鐐规垜杩涘叆](http://txy.ruoyi.vip)
+
+## 鍐呯疆鍔熻兘
+
+1. 鐢ㄦ埛绠$悊锛氱敤鎴锋槸绯荤粺鎿嶄綔鑰咃紝璇ュ姛鑳戒富瑕佸畬鎴愮郴缁熺敤鎴烽厤缃��
+2. 閮ㄩ棬绠$悊锛氶厤缃郴缁熺粍缁囨満鏋勶紙鍏徃銆侀儴闂ㄣ�佸皬缁勶級锛屾爲缁撴瀯灞曠幇鏀寔鏁版嵁鏉冮檺銆�
+3. 宀椾綅绠$悊锛氶厤缃郴缁熺敤鎴锋墍灞炴媴浠昏亴鍔°��
+4. 鑿滃崟绠$悊锛氶厤缃郴缁熻彍鍗曪紝鎿嶄綔鏉冮檺锛屾寜閽潈闄愭爣璇嗙瓑銆�
+5. 瑙掕壊绠$悊锛氳鑹茶彍鍗曟潈闄愬垎閰嶃�佽缃鑹叉寜鏈烘瀯杩涜鏁版嵁鑼冨洿鏉冮檺鍒掑垎銆�
+6. 瀛楀吀绠$悊锛氬绯荤粺涓粡甯镐娇鐢ㄧ殑涓�浜涜緝涓哄浐瀹氱殑鏁版嵁杩涜缁存姢銆�
+7. 鍙傛暟绠$悊锛氬绯荤粺鍔ㄦ�侀厤缃父鐢ㄥ弬鏁般��
+8. 閫氱煡鍏憡锛氱郴缁熼�氱煡鍏憡淇℃伅鍙戝竷缁存姢銆�
+9. 鎿嶄綔鏃ュ織锛氱郴缁熸甯告搷浣滄棩蹇楄褰曞拰鏌ヨ锛涚郴缁熷紓甯镐俊鎭棩蹇楄褰曞拰鏌ヨ銆�
+10. 鐧诲綍鏃ュ織锛氱郴缁熺櫥褰曟棩蹇楄褰曟煡璇㈠寘鍚櫥褰曞紓甯搞��
+11. 鍦ㄧ嚎鐢ㄦ埛锛氬綋鍓嶇郴缁熶腑娲昏穬鐢ㄦ埛鐘舵�佺洃鎺с��
+12. 瀹氭椂浠诲姟锛氬湪绾匡紙娣诲姞銆佷慨鏀广�佸垹闄�)浠诲姟璋冨害鍖呭惈鎵ц缁撴灉鏃ュ織銆�
+13. 浠g爜鐢熸垚锛氬墠鍚庣浠g爜鐨勭敓鎴愶紙java銆乭tml銆亁ml銆乻ql锛夋敮鎸丆RUD涓嬭浇 銆�
+14. 绯荤粺鎺ュ彛锛氭牴鎹笟鍔′唬鐮佽嚜鍔ㄧ敓鎴愮浉鍏崇殑api鎺ュ彛鏂囨。銆�
+15. 鏈嶅姟鐩戞帶锛氱洃瑙嗗綋鍓嶇郴缁烠PU銆佸唴瀛樸�佺鐩樸�佸爢鏍堢瓑鐩稿叧淇℃伅銆�
+16. 缂撳瓨鐩戞帶锛氬绯荤粺鐨勭紦瀛樹俊鎭煡璇紝鍛戒护缁熻绛夈��
+17. 鍦ㄧ嚎鏋勫缓鍣細鎷栧姩琛ㄥ崟鍏冪礌鐢熸垚鐩稿簲鐨凥TML浠g爜銆�
+18. 杩炴帴姹犵洃瑙嗭細鐩戣褰撳墠绯荤粺鏁版嵁搴撹繛鎺ユ睜鐘舵�侊紝鍙繘琛屽垎鏋怱QL鎵惧嚭绯荤粺鎬ц兘鐡堕銆�
+
+## 鍦ㄧ嚎浣撻獙
+
+- admin/admin123
+- 闄嗛檰缁画鏀跺埌涓�浜涙墦璧忥紝涓轰簡鏇村ソ鐨勪綋楠屽凡鐢ㄤ簬婕旂ず鏈嶅姟鍣ㄥ崌绾с�傝阿璋㈠悇浣嶅皬浼欎即銆�
+
+婕旂ず鍦板潃锛歨ttp://vue.ruoyi.vip
+鏂囨。鍦板潃锛歨ttp://doc.ruoyi.vip
+
+## 婕旂ず鍥�
+
+<table>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/cd1f90be5f2684f4560c9519c0f2a232ee8.jpg"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/1cbcf0e6f257c7d3a063c0e3f2ff989e4b3.jpg"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-8074972883b5ba0622e13246738ebba237a.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-9f88719cdfca9af2e58b352a20e23d43b12.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-39bf2584ec3a529b0d5a3b70d15c9b37646.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-936ec82d1f4872e1bc980927654b6007307.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-b2d62ceb95d2dd9b3fbe157bb70d26001e9.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-d67451d308b7a79ad6819723396f7c3d77a.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/5e8c387724954459291aafd5eb52b456f53.jpg"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/644e78da53c2e92a95dfda4f76e6d117c4b.jpg"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-8370a0d02977eebf6dbf854c8450293c937.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-49003ed83f60f633e7153609a53a2b644f7.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-d4fe726319ece268d4746602c39cffc0621.png"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-c195234bbcd30be6927f037a6755e6ab69c.png"/></td>
+ </tr>
+ <tr>
+ <td><img src="https://oscimg.oschina.net/oscnet/b6115bc8c31de52951982e509930b20684a.jpg"/></td>
+ <td><img src="https://oscimg.oschina.net/oscnet/up-5e4daac0bb59612c5038448acbcef235e3a.png"/></td>
+ </tr>
+</table>
+
+
+## 鑻ヤ緷鍓嶅悗绔垎绂讳氦娴佺兢
+
+QQ缇わ細 [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ 鐐瑰嚮鎸夐挳鍏ョ兢銆�
\ No newline at end of file
diff --git a/basic-server/pom.xml b/basic-server/pom.xml
new file mode 100644
index 0000000..e0f5431
--- /dev/null
+++ b/basic-server/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>basic-server</artifactId>
+ <dependencies>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-framework</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-system</artifactId>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ </properties>
+
+</project>
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java
new file mode 100644
index 0000000..810c430
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/CapacityScopeController.java
@@ -0,0 +1,393 @@
+package com.ruoyi.basic.controller;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.poi.excel.ExcelUtil;
+import com.alibaba.excel.EasyExcel;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.system.service.ISysDictTypeService;
+import com.ruoyi.basic.dto.PageTestObjectDto;
+import com.ruoyi.basic.dto.ProductDTO1;
+import com.ruoyi.basic.excel.StructureTestObjectData;
+import com.ruoyi.basic.excel.StructureTestObjectListener;
+import com.ruoyi.basic.pojo.Product;
+import com.ruoyi.basic.pojo.StandardTemplate;
+import com.ruoyi.basic.pojo.StructureItemParameter;
+import com.ruoyi.basic.pojo.StructureTestObject;
+import com.ruoyi.basic.service.CapacityScopeService;
+import com.ruoyi.basic.service.ProductService;
+import com.ruoyi.basic.service.StandardTemplateService;
+import com.ruoyi.basic.service.StructureItemParameterService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.Collectors;
+
+/**
+ * 妫�楠岄」鐩弬鏁�(StructureItemParameter)琛ㄦ帶鍒跺眰
+ *
+ * @author makejava
+ * @since 2024-02-26 16:21:17
+ */
+@Api(tags = "鑳藉姏鑼冨洿")
+@AllArgsConstructor
+@RestController
+@RequestMapping("/capacityScope")
+public class CapacityScopeController {
+
+ private CapacityScopeService capacityScopeService;
+
+ private ProductService productService;
+
+ private StructureItemParameterService structureItemParameterService;
+
+ private ISysDictTypeService dictTypeService;
+
+ private StandardTemplateService standardTemplateService;
+
+ @ApiOperation(value = "鑾峰彇椤圭洰妫�楠屽弬鏁板垪琛�")
+ @PostMapping("/selectItemParameterList")
+ public Result selectItemParameterList(Page page,StructureItemParameter itemParameter) throws Exception {
+ return Result.success(capacityScopeService.selectItemParameterList(page, itemParameter));
+ }
+
+ @ApiOperation(value = "娣诲姞椤圭洰妫�楠屽弬鏁�")
+ @PostMapping("/addItemParameter")
+ public Result addItemParameter(@RequestBody StructureItemParameter itemParameter) {
+ return Result.success(capacityScopeService.addItemParameter(itemParameter));
+ }
+
+ @ApiOperation(value = "鍒犻櫎椤圭洰妫�楠屽弬鏁�")
+ @PostMapping("/delItemParameter")
+ public Result<?> delItemParameter(Integer id) {
+ return Result.success(capacityScopeService.delItemParameter(id));
+ }
+
+ @ApiOperation(value = "淇敼椤圭洰妫�楠屽弬鏁�")
+ @PostMapping("/upItemParameter")
+ public Result<?> upItemParameter(@RequestBody StructureItemParameter itemParameter) {
+ return Result.success(capacityScopeService.upItemParameter(itemParameter));
+ }
+
+ @ApiOperation(value = "鑾峰彇妫�楠屽璞�")
+ @PostMapping("/selectTestObjectList")
+ public Result selectTestObjectList(Page page,PageTestObjectDto pageTestObjectDto) throws Exception {
+ return Result.success(capacityScopeService.selectTestObjectList(page, pageTestObjectDto));
+ }
+
+ @ApiOperation(value = "娣诲姞妫�楠屽璞�")
+ @PostMapping("/addTestObject")
+ public Result addTestObject(@RequestBody StructureTestObject testObject) {
+ return Result.success(capacityScopeService.addTestObject(testObject));
+ }
+
+ @ApiOperation(value = "鍒犻櫎妫�楠屽璞�")
+ @PostMapping("/delTestObject")
+ public Result<?> delTestObject(Integer id) {
+ return Result.success(capacityScopeService.delTestObject(id));
+ }
+
+ @ApiOperation(value = "淇敼妫�楠屽璞�")
+ @PostMapping("/upTestObject")
+ public Result upTestObject(@RequestBody StructureTestObject testObject) {
+ return Result.success(capacityScopeService.upTestObject(testObject));
+ }
+
+ @ApiOperation(value = "鑾峰彇妫�楠屽璞℃灇涓�")
+ @GetMapping("/selectTestObjectByName")
+ public Result selectTestObjectByName() {
+ return Result.success(capacityScopeService.selectTestObjectByName());
+ }
+
+ @ApiOperation(value = "璁惧閲岄潰閫夋嫨妫�楠岄」鐩�(鏍戝舰缁撴瀯)")
+ @PostMapping("/getInsProduction")
+ public Result getInsProduction() {
+ return Result.success(capacityScopeService.getInsProduction());
+ }
+
+ @ApiOperation(value = "缁存姢妫�楠屽璞$殑浜у搧")
+ @PostMapping("/selectProductListByObjectId")
+ public Result selectProductListByObjectId(Page page,ProductDTO1 productDTO) throws Exception {
+ return Result.success(productService.selectProductListByObjectId(page, productDTO));
+ }
+
+ @ApiOperation(value = "娣诲姞浜у搧")
+ @PostMapping("/addProduct")
+ public Result addProduct(@RequestBody Product product) {
+ return Result.success(productService.addProduct(product));
+ }
+
+ @ApiOperation(value = "淇敼浜у搧")
+ @PostMapping("/upProduct")
+ public Result upProduct(@RequestBody Product product) {
+ return Result.success(productService.upProduct(product));
+ }
+
+ @ApiOperation(value = "鍒犻櫎浜у搧")
+ @PostMapping("/delProduct")
+ public Result delProduct(Integer id) {
+ return Result.success(productService.delProduct(id));
+ }
+
+ @ApiOperation(value = "鑾峰彇妫�楠屽璞℃爲")
+ @GetMapping("/getItemTree")
+ public Result getItemTree() {
+ return Result.success(capacityScopeService.getItemTree());
+ }
+
+
+ @ApiOperation(value = "瑁呭瀵煎叆妫�楠岄」鐩�")
+ @PostMapping("/importEquipData")
+ @Transactional
+ public Result importEquipData(@RequestParam("file") MultipartFile file) throws Exception {
+ InputStream inputStream = file.getInputStream();
+ List<StructureItemParameter> lists = new ArrayList<>();
+ AtomicReference<String> sample = new AtomicReference<>();
+ ExcelUtil.readBySax(inputStream, -1, (i, l, list1) -> {
+ if (l == 1) {
+ sample.set(list1.get(1) + "");
+ }
+ if (l >= 1) {
+ StructureItemParameter str = new StructureItemParameter();
+ // 娴嬭瘯瀵硅薄
+ if (list1.get(1) == null) {
+ str.setSample(null);
+ } else {
+ String brand = (String) list1.get(1);
+ StringBuilder builder = new StringBuilder();
+ builder.append("[");
+ // 浜у搧
+ if (ObjectUtil.isNotEmpty(list1.get(2))) {
+ String production = (String) list1.get(2);
+ if (!production.contains("锛�")) {
+ builder.append(String.format("[\"%s\",\"%s\"]", brand, production));
+ } else {
+ Arrays.stream(production.split("锛�")).forEach(item -> {
+ builder.append(String.format("[\"%s\",\"%s\"],", brand, item));
+ });
+ builder.deleteCharAt(builder.length() - 1);
+ }
+ } else {
+ builder.append("[");
+ builder.append(String.format("\"%s\"", brand));
+ builder.append("]");
+ }
+ builder.append("]");
+ str.setSample(builder.toString());
+ }
+ // 妫�楠岄」
+ str.setInspectionItem(list1.get(4).toString().trim());
+ // 妫�楠岄」鑻辨枃
+ if (list1.get(5) != null) {
+ str.setInspectionItemEn(list1.get(5).toString());
+ }
+ // 妫�楠屽瓙椤�
+ if (list1.get(6) == null) {
+ str.setInspectionItemSubclass(null);
+ } else {
+ str.setInspectionItemSubclass(list1.get(6).toString().trim());
+ }
+ // 妫�楠屽瓙椤硅嫳鏂�
+ if (list1.get(7) == null) {
+ str.setInspectionItemSubclassEn(null);
+ } else {
+ str.setInspectionItemSubclassEn(String.valueOf(list1.get(7).toString()));
+ }
+ // 妫�楠岄」鍒嗙被
+ if (list1.get(22) != null && list1.get(22) != "") {
+ str.setInspectionItemClass(list1.get(22).toString().trim());
+ } else {
+ str.setInspectionItemClass(null);
+ }
+ // 妫�楠岄」鍒嗙被鑻辨枃
+ if (list1.get(23) != null && list1.get(23) != "") {
+ str.setInspectionItemClassEn(list1.get(23) + "");
+ } else {
+ str.setInspectionItemClassEn(null);
+ }
+
+ LambdaQueryWrapper<StructureItemParameter> wrapper = Wrappers.lambdaQuery(StructureItemParameter.class)
+ .eq(StructureItemParameter::getInspectionItem, str.getInspectionItem())
+ .eq(StructureItemParameter::getSample, str.getSample())
+
+ .last("limit 1");
+ // 鍒ゆ柇鏄惁鏈夋楠岄」绫诲瀷
+ if (ObjectUtils.isNotEmpty(str.getInspectionItemClass())) {
+ wrapper.eq(StructureItemParameter::getInspectionItemClass, str.getInspectionItemClass());
+ }
+
+ // 鍒ゆ柇鏄惁鏈夋楠屽瓙椤�
+ if (ObjectUtils.isNotEmpty(str.getInspectionItemSubclass())) {
+ wrapper.eq(StructureItemParameter::getInspectionItemSubclass, str.getInspectionItemSubclass());
+ }
+ StructureItemParameter db_str = structureItemParameterService.getOne(wrapper);
+ if (ObjectUtils.isNotEmpty(db_str)) {
+ str.setId(db_str.getId());
+ }
+ // 鏂规硶鍚嶇О
+ if (list1.get(8) == null) {
+ str.setMethod(null);
+ } else {
+ StringBuffer buffer = new StringBuffer();
+ String input = list1.get(8).toString();
+ buffer.append("[");
+ String[] values = input.split("锛�");
+ for (String value : values) {
+ buffer.append("\"").append(value.trim()).append("\",");
+ }
+ buffer.deleteCharAt(buffer.length() - 1);
+ buffer.append("]");
+ str.setMethod(buffer.toString());
+ }
+ // 璇曢獙瀹�
+ if (list1.get(9) == null) {
+ str.setSonLaboratory(null);
+ } else {
+ str.setSonLaboratory(list1.get(9).toString());
+ }
+ // 璁¢噺鍗曚綅
+ if (list1.get(10) == null) {
+ str.setUnit(null);
+ } else {
+ str.setUnit(list1.get(10).toString());
+ }
+ // 瑕佹眰鍊�
+ if (list1.get(11) == null) {
+ str.setAskTell(null);
+ } else {
+ str.setAskTell(list1.get(11).toString());
+ }
+ // 瑕佹眰鎻忚堪
+ if (list1.get(12) == null) {
+ str.setAsk(null);
+ } else {
+ str.setAsk(list1.get(12).toString());
+ }
+ // 鍗曚环
+ if (list1.get(13) == null) {
+ str.setPrice(null);
+ } else {
+ str.setPrice(list1.get(13) + "");
+ }
+ // 宸ユ椂绯绘暟
+ if (list1.get(14) == null) {
+ str.setManHour(null);
+ } else {
+ str.setManHour(Double.valueOf(list1.get(14).toString()));
+ }
+ // 宸ユ椂鍒嗙粍
+ if (list1.get(15) == null) {
+ str.setManHourGroup(null);
+ } else {
+ str.setManHourGroup(list1.get(15).toString());
+ }
+ // 棰勮瀹屾垚鏃堕棿
+ if (list1.get(16) == null) {
+ str.setManDay(null);
+ } else {
+ str.setManDay(Integer.valueOf(list1.get(16).toString()));
+ }
+ // 鏁版嵁绫诲瀷
+ String jy;
+ if (list1.get(17).toString().equals("闈為噰闆嗙被鍨�")) {
+ jy = "0";
+ } else {
+ jy = "1";
+ }
+ str.setInspectionItemType(jy);
+ // 妫�楠岄」绫诲瀷
+ String validateValueType = list1.get(18).toString();
+ if (ObjectUtils.isNotEmpty(validateValueType)) {
+ List<SysDictData> enums = dictTypeService.selectDictDataByName("妫�楠屽�肩被鍨�")
+ .stream().filter(sysDictData -> sysDictData.getDictLabel().equals(validateValueType)).collect(Collectors.toList());
+ str.setInspectionValueType(enums.get(0).getDictValue());
+ }
+ int bsm;
+ //鐗规畩鏍囪瘑
+ if (list1.get(19).toString().equals("鍚�")) {
+ bsm = 0;
+ } else {
+ bsm = 1;
+ }
+ str.setBsm(bsm + "");
+ // 鏁板瓧瀛楀吀
+ if (list1.get(20) != null) {
+ str.setDic(list1.get(20) + "");
+ } else {
+ str.setDic(null);
+ }
+ // 鍘熷璁板綍妯℃澘
+ StandardTemplate standTempIdByName = standardTemplateService.getStandTempIdByName(String.valueOf(list1.get(21)));
+ if (standTempIdByName != null) {
+ str.setTemplateId(standTempIdByName.getId());
+ } else {
+ str.setTemplateId(null);
+ }
+ try {
+ if (list1.get(24) != null) {
+ str.setLaboratory(list1.get(24) + "");
+ }
+ } catch (Exception e) {
+ }
+
+ // 鏉′欢
+ if (list1.get(25) == null) {
+ str.setRadiusList(null);
+ } else {
+ StringBuffer buffer = new StringBuffer();
+ String input = list1.get(25).toString();
+ buffer.append("[");
+ String[] values = input.split("锛�");
+ for (String value : values) {
+ buffer.append("\"").append(value.trim()).append("\",");
+ }
+ buffer.deleteCharAt(buffer.length() - 1);
+ buffer.append("]");
+ str.setRadiusList(buffer.toString());
+ }
+ // 鏀惰垂鏍囧噯
+ if (list1.get(26) == null) {
+ str.setRates(null);
+ } else {
+ str.setRates(list1.get(26) + "");
+ }
+
+ lists.add(str);
+ }
+ });
+// structureItemParameterService.removeNoSample(sample.get());
+ // 濡傛灉鏁版嵁搴撻噷闈㈢殑鏁版嵁瀛樺湪閭d箞灏辨墽琛屾洿鏂版嫹璐濇搷浣�
+ try {
+ structureItemParameterService.saveOrUpdateBatch(lists);
+ } catch (Exception e) {
+ e.printStackTrace();
+ throw new RuntimeException("鏈嶅姟绔姤閿�");
+ }
+ return Result.success();
+ }
+
+ @ApiOperation(value = "瀵煎叆妫�楠屽璞�")
+ @PostMapping("/importExcel")
+ public Result importExcel(@RequestParam("file") MultipartFile file) {
+ try {
+ EasyExcel.read(file.getInputStream(), StructureTestObjectData.class, new StructureTestObjectListener(productService)).sheet().doRead();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return Result.success();
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/CertificationController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/CertificationController.java
new file mode 100644
index 0000000..51ed763
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/CertificationController.java
@@ -0,0 +1,41 @@
+package com.ruoyi.basic.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.pojo.Certification;
+import com.ruoyi.basic.service.CertificationService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Api(tags = "璧勮川璇存槑")
+@AllArgsConstructor
+@RestController
+@RequestMapping("/certification")
+
+public class CertificationController {
+
+ private CertificationService certificationService;
+
+
+ @ApiOperation(value = "鏌ヨ璧勮川鏄庣粏鍒楄〃")
+ @PostMapping("/getCertificationDetail")
+ public Result getCertificationDetail(Page page,Certification certification) {
+ return Result.success(certificationService.getCertificationDetail(page, certification));
+ }
+
+ @ApiOperation(value = "娣诲姞璧勮川鏄庣粏鍒楄〃")
+ @PostMapping("/addCertificationDetail")
+ public Result addCertificationDetail(@RequestBody Certification certification) {
+ return Result.success(certificationService.addCertificationDetail(certification));
+ }
+ @ApiOperation(value = "鍒犻櫎璧勮川鏄庣粏鍒楄〃")
+ @PostMapping("/delCertificationDetail")
+ public Result<?> delCertificationDetail( String ids) {
+ return Result.success(certificationService.delCertificationDetail(ids));
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/LaboratoryController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/LaboratoryController.java
new file mode 100644
index 0000000..c21f7be
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/LaboratoryController.java
@@ -0,0 +1,62 @@
+package com.ruoyi.basic.controller;
+
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.pojo.Laboratory;
+import com.ruoyi.basic.service.LaboratoryService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+
+/**
+ * 瀹為獙瀹ょ鐞�(LaboratoryController)琛ㄦ帶鍒跺眰
+ */
+@Api(tags = "鍦烘墍鎴栬鏂�")
+
+@RestController
+@RequestMapping("/laboratoryScope")
+public class LaboratoryController {
+
+ @Resource
+ private LaboratoryService laboratoryService;
+
+ @ApiOperation(value = "鏌ヨ瀹為獙瀹ょ鐞嗗垪琛�")
+ @PostMapping("/selectItemParameter")
+ public Result selectItemParameter(Page page ,Laboratory itemParameter) {
+ return Result.success(laboratoryService.selectItemParameter(page, itemParameter));
+ }
+
+ @ApiOperation(value = "娣诲姞瀹為獙瀹ゅ弬鏁�")
+ @PostMapping("/addParameter")
+ public Result addParameter(@RequestBody Laboratory itemParameter) {
+ return Result.success(laboratoryService.addParameter(itemParameter));
+ }
+
+ @ApiOperation(value = "鍒犻櫎瀹為獙瀹ゅ弬鏁�")
+ @PostMapping("/delParameter")
+ public Result<?> delParameter(Integer id) {
+ return Result.success(laboratoryService.delParameter(id));
+ }
+
+ @ApiOperation(value = "淇敼瀹為獙瀹ゅ弬鏁�")
+ @PostMapping("/upParameter")
+ public Result<?> upParameter(@RequestBody Laboratory itemParameter) {
+ return Result.success(laboratoryService.upParameter(itemParameter));
+ }
+
+ @ApiOperation(value = "鑾峰彇瀹為獙瀹ゅ悕绉�")
+ @GetMapping("/obtainItemParameterList")
+ public Result obtainItemParameterList() {
+ return Result.success(laboratoryService.obtainItemParameterList());
+ }
+}
+
+
+
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/ProductPartController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/ProductPartController.java
new file mode 100644
index 0000000..ca3a5b9
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/ProductPartController.java
@@ -0,0 +1,50 @@
+package com.ruoyi.basic.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.pojo.ProductPart;
+import com.ruoyi.basic.service.ProductPartService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@RestController
+@AllArgsConstructor
+@RequestMapping("/productPart")
+@Api(tags = "浜у搧闆朵欢缁戝畾")
+public class ProductPartController {
+
+ private ProductPartService productPartService;
+
+ @ApiOperation(value = "鏍规嵁浜у搧id鏌ヨ闆朵欢")
+ @PostMapping("/selectByProductId")
+ public Result selectByProductId(Page page,ProductPart productPart){
+ return Result.success(productPartService.selectByProductId(page,productPart));
+ }
+
+ @ApiOperation(value = "鏂板浜у搧闆朵欢")
+ @PostMapping("/addProductPart")
+ public Result addProductPart(@RequestBody ProductPart productPart) {
+ productPartService.addProductPart(productPart);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鏇存柊浜у搧闆朵欢")
+ @PostMapping("/updateProductPart")
+ public Result updateProductPart(@RequestBody ProductPart productPart) {
+ productPartService.updateProductPartById(productPart);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鍒犻櫎浜у搧闆朵欢")
+ @PostMapping("/deleteProductPart")
+ public Result deleteProductPart(Integer id) {
+ productPartService.removeById(id);
+ return Result.success();
+ }
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/ProductSupplierDensityController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/ProductSupplierDensityController.java
new file mode 100644
index 0000000..1d86970
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/ProductSupplierDensityController.java
@@ -0,0 +1,59 @@
+package com.ruoyi.basic.controller;
+
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.pojo.ProductSupplierDensity;
+import com.ruoyi.basic.service.ProductSupplierDensityService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * 浜у搧鍘傚瀵嗗害缁戝畾琛�
+ *
+ * @author zhuo
+ * @since 2024-09-19
+ */
+@RestController
+@RequestMapping("/productSupplierDensity")
+@AllArgsConstructor
+@Api(tags = "浜у搧鍘傚瀵嗗害缁戝畾")
+public class ProductSupplierDensityController {
+
+ private ProductSupplierDensityService productSupplierDensityService;
+
+ @ApiOperation(value = "鏍规嵁浜у搧id鏌ヨ鍘傚瀵嗗害缁戝畾")
+ @PostMapping("/selectSupplierDensityByProductId")
+ public Result selectSupplierDensityByProductId(Page page,ProductSupplierDensity supplierDensity) {
+ return Result.success(productSupplierDensityService.selectByProductId(page, supplierDensity));
+ }
+
+ @ApiOperation(value = "鏂板鍘傚瀵嗗害缁戝畾")
+ @PostMapping("/addProductSupplierDensity")
+ public Result addProductSupplierDensity(@RequestBody ProductSupplierDensity supplierDensity) {
+ productSupplierDensityService.addProductSupplierDensity(supplierDensity);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鏇存柊鍘傚瀵嗗害缁戝畾")
+ @PostMapping("/updateProductSupplierDensity")
+ public Result updateProductSupplierDensity(@RequestBody ProductSupplierDensity supplierDensity) {
+ productSupplierDensityService.updateProductSupplierDensity(supplierDensity);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鍒犻櫎鍘傚瀵嗗害缁戝畾")
+ @PostMapping("/deleteProductSupplierDensity")
+ public Result deleteProductSupplierDensity(Integer id) {
+ productSupplierDensityService.removeById(id);
+ return Result.success();
+ }
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/SealController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/SealController.java
new file mode 100644
index 0000000..02ab6bb
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/SealController.java
@@ -0,0 +1,50 @@
+package com.ruoyi.basic.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.Laboratory;
+import com.ruoyi.basic.pojo.Seal;
+import com.ruoyi.basic.service.SealService;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.utils.JackSonUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 鍗扮珷绠$悊(SealController)琛ㄦ帶鍒跺眰
+ */
+@Api(tags = "鍗扮珷绠$悊")
+
+@RestController
+@RequestMapping("/sealScope")
+public class SealController {
+
+ @Resource
+ private SealService sealService;
+
+ @ApiOperation(value = "娣诲姞鍗扮珷鍙傛暟")
+ @PostMapping("/addSeal")
+ public Result addSeal(@RequestBody Seal seal) {
+ int i = sealService.addSeal(seal);
+ if(i>0){
+ Integer labId = seal.getLabId();
+ List<Laboratory> laboratory = sealService.Laboratory(labId);
+ return Result.success(laboratory);
+ }else{
+ return Result.fail();
+ }
+
+ }
+ @ApiOperation(value="鏌ヨ鍗扮珷鍒楄〃")
+ @PostMapping("/selectSeal")
+ public Result selectSeal(Page page,Seal seal) {
+ return Result.success(sealService.selectSeal(page,seal));
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/StandardMethodController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardMethodController.java
new file mode 100644
index 0000000..f74f38b
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardMethodController.java
@@ -0,0 +1,59 @@
+package com.ruoyi.basic.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.pojo.StandardMethod;
+import com.ruoyi.basic.service.StandardMethodService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
+@Api(tags = "鏍囧噯鏂规硶")
+@RestController
+@RequestMapping("/standardMethod")
+@AllArgsConstructor
+public class StandardMethodController {
+
+ private StandardMethodService standardMethodService;
+
+ @ApiOperation(value = "鑾峰彇鏍囧噯鏂规硶鍒楄〃")
+ @PostMapping("/selectStandardMethodList")
+ public Result selectStandardMethodList(Page page,StandardMethod standardMethod) throws Exception {
+ return Result.success(standardMethodService.selectStandardMethodList(page, standardMethod));
+ }
+
+ @ApiOperation(value = "鑾峰彇鏍囧噯鏂规硶鏋氫妇")
+ @GetMapping("/selectStandardMethods")
+ public Result selectStandardMethods(){
+ return Result.success(standardMethodService.selectStandardMethods());
+ }
+
+ @ApiOperation(value = "娣诲姞鏍囧噯鏂规硶")
+ @PostMapping("/addStandardMethod")
+ public Result addStandardMethod(@RequestBody StandardMethod standardMethod) {
+ return Result.success(standardMethodService.addStandardMethod(standardMethod));
+ }
+
+ @ApiOperation(value = "鍒犻櫎鏍囧噯鏂规硶")
+ @PostMapping("/delStandardMethod")
+ public Result<?> delStandardMethod(Integer id) {
+ return Result.success(standardMethodService.delStandardMethod(id));
+ }
+
+ @ApiOperation(value = "淇敼鏍囧噯鏂规硶")
+ @PostMapping("/upStandardMethod")
+ public Result<?> upStandardMethod(@RequestBody StandardMethod standardMethod) {
+ return Result.success(standardMethodService.upStandardMethod(standardMethod));
+ }
+
+ @ApiOperation(value = "瀵煎叆鏍囧噯鏄庣粏")
+ @PostMapping("/importStandardDetails")
+ public Result<?> importStandardDetails(@RequestPart("file") MultipartFile file) throws IOException {
+ standardMethodService.inputExcel(file);
+ return Result.success();
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTemplateController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTemplateController.java
new file mode 100644
index 0000000..c14f1a3
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTemplateController.java
@@ -0,0 +1,68 @@
+package com.ruoyi.basic.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.pojo.StandardTemplate;
+import com.ruoyi.basic.service.StandardTemplateService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+@RequestMapping("/StandardTemplate")
+@RestController
+@AllArgsConstructor
+@Api(tags = "鍘熷璁板綍妯℃澘")
+public class StandardTemplateController {
+
+ private StandardTemplateService standardTemplateService;
+
+ @ApiOperation(value = "鑾峰彇鍘熷璁板綍妯℃澘鍒楄〃")
+ @PostMapping("/selectStandardTemplatePageList")
+ public Result selectStandardTemplatePageList(Page page,StandardTemplate standardTemplate) throws Exception {
+ return Result.success(standardTemplateService.selectStandardTemplatePageList(page, standardTemplate));
+ }
+
+ @ApiOperation(value = "娣诲姞鍘熷璁板綍妯℃澘")
+ @PostMapping("/addStandardTemplate")
+ public Result addStandardTemplate(@RequestBody StandardTemplate standardTemplate) {
+ return Result.success(standardTemplateService.addStandardTemplate(standardTemplate));
+ }
+
+ @ApiOperation(value = "淇敼鍘熷璁板綍妯℃澘")
+ @PostMapping("/upStandardTemplate")
+ public Result<?> upStandardTemplate(@RequestBody StandardTemplate standardTemplate) {
+ return Result.success(standardTemplateService.upStandardTemplate(standardTemplate));
+ }
+
+ @ApiOperation(value = "鍒犻櫎鍘熷璁板綍妯℃澘")
+ @PostMapping("/delStandardTemplate")
+ public Result<?> delStandardTemplate(Integer id) {
+ return Result.success(standardTemplateService.delStandardTemplate(id));
+ }
+
+ @ApiOperation(value = "鏌ヨ鍘熷璁板綍妯℃澘鏋氫妇")
+ @GetMapping("/getStandardTemplate")
+ public Result<?> getStandardTemplate() {
+ return Result.success(standardTemplateService.getStandardTemplate());
+ }
+
+ @ApiOperation(value = "閫氳繃妯℃澘id鑾峰彇妫�楠岄」妯℃澘鍐呭")
+ @PostMapping("/getStandTempThingById")
+ public Result<?> getStandTempThingById(Integer id) {
+ return Result.success(standardTemplateService.getStandTempThingById(id));
+ }
+
+ @ApiOperation(value = "缂栬緫妯℃澘缂栧埗")
+ @GetMapping("/getEditTemplatePreparation")
+ public Result<?> getEditTemplatePreparation(@RequestParam("id") Integer id) {
+ StandardTemplate byId = standardTemplateService.getById(id);
+ return Result.success("OK", byId.getThing());
+ }
+
+ @ApiOperation(value = "澶嶅埗鍘熷璁板綍妯℃澘")
+ @PostMapping("/copyStandardTemplate")
+ public Result copyStandardTemplate(@RequestBody StandardTemplate newTemplate) {
+ return Result.success(standardTemplateService.copyStandardTemplate(newTemplate));
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java
new file mode 100644
index 0000000..d24ae09
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/StandardTreeController.java
@@ -0,0 +1,276 @@
+package com.ruoyi.basic.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.dto.CopyStandardProductListDto;
+import com.ruoyi.basic.dto.FactoryDto;
+import com.ruoyi.basic.dto.InsSampleReceiveDto;
+import com.ruoyi.basic.dto.ResetTreeDragDTO;
+import com.ruoyi.basic.pojo.StandardProductList;
+import com.ruoyi.basic.pojo.StandardProductListSupplierAsk;
+import com.ruoyi.basic.pojo.StandardTree;
+import com.ruoyi.basic.service.StandardMethodListService;
+import com.ruoyi.basic.service.StandardProductListService;
+import com.ruoyi.basic.service.StandardProductListSupplierAskService;
+import com.ruoyi.basic.service.StandardTreeService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+import java.util.Map;
+
+@RestController
+@AllArgsConstructor
+@RequestMapping("/standardTree")
+@Api(tags = "鏍囧噯搴�")
+public class StandardTreeController {
+
+ private StandardTreeService standardTreeService;
+
+ private StandardMethodListService standardMethodListService;
+
+ private StandardProductListService standardProductListService;
+
+ private StandardProductListSupplierAskService standardProductListSupplierAskService;
+
+ @ApiOperation(value = "鑾峰彇鏍囧噯鏍�")
+ @GetMapping("/selectStandardTreeList")
+ public Result selectStandardTreeList() {
+ return Result.success(standardTreeService.selectStandardTreeList());
+ }
+
+ @ApiOperation(value = "鑾峰彇鏍囧噯鏍�(妫�楠屼笅鍗�)")
+ @GetMapping("/selectStandardTreeList2")
+ public Result selectStandardTreeList2() {
+ return Result.success(standardTreeService.selectStandardTreeList());
+ }
+
+ @ApiOperation(value = "娣诲姞鏍囧噯鏍�")
+ @PostMapping("/addStandardTree")
+ public Result addStandardTree(@RequestBody StandardTree standardTree) {
+ return Result.success(standardTreeService.addStandardTree(standardTree));
+ }
+
+ @ApiOperation(value = "缁欐爣鍑嗘爲娣诲姞妫�楠屾爣鍑�")
+ @PostMapping("/addStandardMethodList")
+ public Result addStandardMethodList(String tree, Integer standardId) {
+ return Result.success(standardMethodListService.addStandardMethodList(standardId, tree));
+ }
+
+ @ApiOperation(value = "鏍规嵁鏍囧噯鏍戣繘琛屾爣鍑嗘煡璇�")
+ @PostMapping("/selectsStandardMethodByFLSSM")
+ public Result selectsStandardMethodByFLSSM(String tree) {
+ return Result.success(standardMethodListService.selectsStandardMethodByFLSSM(tree));
+ }
+
+ @ApiOperation(value = "淇敼鏍囧噯搴撲腑鐨勫唴瀹�")
+ @PostMapping("/upStandardProductList")
+ public Result upStandardProductList(String str) {
+ StandardProductList list = JSON.parseObject(str, StandardProductList.class);
+ return Result.success(standardProductListService.upStandardProductList(list));
+ }
+
+ @ApiOperation(value = "淇敼鏍囧噯搴撳尯闂�")
+ @PostMapping("/updateSection")
+ public Result updateSection(String str) {
+ StandardProductList list = JSON.parseObject(str, StandardProductList.class);
+ return Result.success(standardProductListService.updateSection(list));
+ }
+
+ @ApiOperation(value = "鍒犻櫎鏍囧噯鏍戜笅鐨勬楠屾爣鍑�")
+ @PostMapping("/delStandardMethodByFLSSM")
+ public Result delStandardMethodByFLSSM(Integer id) {
+ return Result.success(standardMethodListService.delStandardMethodByFLSSM(id));
+ }
+
+ @ApiOperation(value = "鍒犻櫎鏍囧噯鏍戜笅鐨勬楠岄」鐩�")
+ @PostMapping("/delStandardProductByIds")
+ public Result delStandardProductByIds(String ids) {
+ JSONArray lists = JSON.parseArray(ids);
+ return Result.success(standardProductListService.delStandardProduct(lists));
+ }
+
+ @ApiOperation(value = "鏂板鏍囧噯鏍戜笅鐨勬楠岄」鐩�")
+ @PostMapping("/addStandardProduct")
+ public Result addStandardProduct(String ids, String tree) {
+ return Result.success(standardTreeService.addStandardProduct(ids, tree));
+ }
+
+ @ApiOperation(value = "鍒犻櫎鏍囧噯鏍戠殑灞傜骇")
+ @PostMapping("/delStandardTree")
+ public Result delStandardTree(String tree) {
+ return Result.success(standardTreeService.delStandardTree(tree));
+ }
+
+ @ApiOperation(value = "閫氳繃鏍囧噯鏍戞煡璇㈠搴旂殑妫�楠岄」鐩�")
+ @PostMapping("/selectStandardProductList")
+ public Result selectStandardProductList(@RequestBody InsSampleReceiveDto insSample) {
+ return Result.success(standardProductListService.selectStandardProductList(insSample));
+ }
+
+ @ApiOperation(value = "閫氳繃妫�楠屾爣鍑嗘煡璇㈡楠岄」鐩�")
+ @PostMapping("/selectStandardProductListByMethodId")
+ public Result selectStandardProductListByMethodId(Integer id, String tree, Integer page) {
+ return Result.success(standardProductListService.selectStandardProductListByMethodId(id, tree, page));
+ }
+
+ @ApiOperation(value = "鎵归噺缂栬緫鏌ヨ妫�楠岄」鐩�")
+ @PostMapping("/selectStandardProductByMethodId")
+ public Result selectStandardProductByMethodId(Integer id, String tree, Integer page, String laboratory, String item, String items) {
+ return Result.success(standardProductListService.selectStandardProductByMethodId(id, tree, page, laboratory, item, items));
+ }
+
+ @ApiOperation(value = "鎵归噺缂栬緫鏌ヨ鎵�鏈夋楠岄」鐩拰妫�楠屽瓙椤规灇涓�")
+ @PostMapping("/selectStandardProductEnumByMethodId")
+ public Result selectStandardProductEnumByMethodId(Integer id, String tree, String item) {
+ return Result.success(standardProductListService.selectStandardProductEnumByMethodId(id, tree, item));
+ }
+
+ @ApiOperation(value = "鑾峰彇鏍囧噯鏍戜笅鏍囧噯鏂规硶鏋氫妇")
+ @GetMapping("/selectStandardMethodEnum")
+ public Result selectStandardMethodEnum() {
+ return Result.success(standardMethodListService.selectStandardMethodEnum());
+ }
+
+ @ApiOperation(value = "鑾峰彇浜у搧鏋舵瀯")
+ @GetMapping("/getStandardTree2")
+ public Result getStandardTree2() {
+ return Result.success(standardTreeService.getStandardTree2());
+ }
+
+ @ApiOperation(value = "鎵归噺淇敼椤圭洰鍐呭")
+ @PostMapping("/upStandardProducts")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "standardProductList", dataTypeClass = StandardProductList.class),
+ @ApiImplicitParam(name = "ids", dataTypeClass = Integer.class)
+ })
+ public Result upStandardProducts(@RequestBody Map<String, Object> product) {
+ return Result.success(standardTreeService.upStandardProducts(product));
+ }
+
+ @PostMapping("/getStandTreeBySampleType")
+ @ApiOperation("浠呰幏鍙栧厜绾ょ殑鍨嬪彿")
+ public Result<?> getStandTreeBySampleType(String laboratory, String sampleType) {
+ return Result.success(standardTreeService.getStandTreeBySampleType(laboratory, sampleType));
+ }
+
+ @ApiOperation("瀵煎叆鏍囧噯搴�")
+ @PostMapping("/inExcelOfTree/{isEquipment}")
+ public Result inExcelOfTree(@RequestParam("file") MultipartFile file, @PathVariable("isEquipment") Boolean isEquipment) {
+ if (!isEquipment) {
+ standardTreeService.inExcelOfTree(file);
+ } else {
+ standardTreeService.importWorkstationExcel(file);
+ }
+ return Result.success();
+ }
+
+ @ApiOperation("閲嶇疆鏍囧噯搴撳崟浠�")
+ @PostMapping("/resetTreeOfPrice")
+ public Result resetTreeOfPrice(String tree, Integer standardId) {
+ standardTreeService.resetTreeOfPrice(tree, standardId);
+ return Result.success();
+ }
+
+ @ApiOperation("閲嶇疆鏍囧噯搴撳伐鏃剁郴鏁�")
+ @PostMapping("/resetTreeOfHour")
+ public Result resetTreeOfHour(String tree, Integer standardId) {
+ standardTreeService.resetTreeOfHour(tree, standardId);
+ return Result.success();
+ }
+
+ @ApiOperation("閲嶇疆鏍囧噯搴撹姹傛弿杩板拰瑕佹眰鍊�")
+ @PostMapping("/resetTreeOfAsk")
+ public Result resetTreeOfAsk(String tree, Integer standardId) {
+ standardTreeService.resetTreeOfAsk(tree, standardId);
+ return Result.success();
+ }
+
+ @ApiOperation("鏍囧噯搴撴嫋鎷�")
+ @PostMapping("/resetTreeDrag")
+ public Result resetTreeDrag(@RequestBody ResetTreeDragDTO resetTreeDragDTO) {
+ standardProductListService.resetTreeDrag(resetTreeDragDTO);
+ return Result.success();
+ }
+
+ @ApiOperation("鏍囧噯搴撴嫋鎷藉叏閮�")
+ @PostMapping("/resetTreeDragBatch")
+ public Result resetTreeDragBatch(@RequestBody Map<String, Object> params) {
+ List<StandardProductList> standardProductLists = (List<StandardProductList>) params.get("params");
+ standardProductListService.resetTreeDragBatch(standardProductLists);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鏍囧噯鏍戞帓搴�")
+ @PostMapping("/updateTreeSort")
+ public Result updateTreeSort(@RequestBody List<FactoryDto> list) {
+ return Result.success(standardTreeService.updateTreeSort(list));
+ }
+
+ /*************************************************** 鍘傚鐗规畩瑕佹眰鍊煎鐞� ************************************************************/
+
+ @ApiOperation(value = "鏍规嵁浜у搧id鏌ヨ鍘傚瑕佹眰鍊肩粦瀹�")
+ @PostMapping("/selectSupplierAsk")
+ public Result selectSupplierAsk(StandardProductListSupplierAsk supplierAsk) throws Exception {
+ return Result.success(standardProductListSupplierAskService.selectByProductId(supplierAsk));
+ }
+
+ @ApiOperation(value = "鏂板鍘傚瑕佹眰鍊肩粦瀹�")
+ @PostMapping("/addProductSupplierAsk")
+ public Result addProductSupplierAsk(String str) {
+ StandardProductListSupplierAsk supplierAsk = JSON.parseObject(str, StandardProductListSupplierAsk.class);
+ return Result.success(standardProductListSupplierAskService.addProductSupplierAsk(supplierAsk));
+ }
+
+ @ApiOperation(value = "鏇存柊鍘傚瑕佹眰鍊肩粦瀹�")
+ @PostMapping("/updateProductSupplierAsk")
+ public Result updateProductSupplierAsk(String str) {
+ StandardProductListSupplierAsk supplierAsk = JSON.parseObject(str, StandardProductListSupplierAsk.class);
+ standardProductListSupplierAskService.updateProductSupplierAsk(supplierAsk);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鍒犻櫎鍘傚瑕佹眰鍊肩粦瀹�")
+ @PostMapping("/deleteProductSupplierAsk")
+ public Result deleteProductSupplierAsk(Integer supplierAskId) {
+ standardProductListSupplierAskService.removeById(supplierAskId);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "淇敼鏍囧噯鏍�")
+ @PostMapping("/updateStandardTree")
+ public Result updateStandardTree(@RequestBody StandardTree standardTree) {
+ return Result.success(standardTreeService.updateStandardTree(standardTree));
+ }
+
+ @ApiOperation(value = "妫�楠岄」瑕佹眰鍊煎鍒跺姣�")
+ @PostMapping("/copyStandardProductList")
+ public Result copyStandardProductList(@RequestBody CopyStandardProductListDto copyStandardProductListDto) {
+ return Result.success(standardProductListService.copyStandardProductList(copyStandardProductListDto));
+ }
+
+ @ApiOperation(value = "妫�楠岄」瑕佹眰鍊煎崟鐙姣�")
+ @PostMapping("/copyStandardProductOne")
+ public Result copyStandardProductOne(@RequestBody CopyStandardProductListDto copyStandardProductListDto) {
+ return Result.success(standardProductListService.copyStandardProductOne(copyStandardProductListDto));
+ }
+
+ @ApiOperation(value = "妫�楠岄」鎵归噺淇敼瑕佹眰鍊艰姹傛弿杩�")
+ @PostMapping("/updateStandardProductListBatch")
+ public Result updateStandardProductListBatch(@RequestBody Map<String, Object> param) {
+ List<StandardProductList> standardProductList = (List<StandardProductList>) param.get("standardProductList");
+ return Result.success(standardProductListService.updateBatchById(standardProductList));
+ }
+
+ @ApiOperation(value = "妫�楠岄」澶嶅埗鎺掑簭")
+ @PostMapping("/copyStandardProductSort")
+ public Result copyStandardProductSort(@RequestBody CopyStandardProductListDto copyStandardProductListDto) {
+ return Result.success(standardProductListService.copyStandardProductSort(copyStandardProductListDto));
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/controller/StructureTestObjectPartController.java b/basic-server/src/main/java/com/ruoyi/basic/controller/StructureTestObjectPartController.java
new file mode 100644
index 0000000..5a073e8
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/controller/StructureTestObjectPartController.java
@@ -0,0 +1,59 @@
+package com.ruoyi.basic.controller;
+
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.basic.pojo.StructureTestObjectPart;
+import com.ruoyi.basic.service.StructureTestObjectPartService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+
+/**
+ * 妫�楠屽璞¢浂浠惰〃
+ *
+ * @author zhuo
+ * @since 2024-08-07
+ */
+@RestController
+@RequestMapping("/structureTestObjectPart")
+@AllArgsConstructor
+@Api(tags = "妫�楠屽璞¢浂浠惰〃")
+public class StructureTestObjectPartController {
+
+ private StructureTestObjectPartService structureTestObjectPartService;
+
+ @ApiOperation(value = "鏍规嵁妫�楠屽璞d鏌ヨ闆朵欢")
+ @PostMapping("/selectByTestObjectId")
+ public Result selectByTestObjectId(Page page,StructureTestObjectPart structureTestObjectPart){
+ return Result.success(structureTestObjectPartService.selectByTestObjectId(page,structureTestObjectPart));
+ }
+
+ @ApiOperation(value = "鏂板妫�楠屽璞¢浂浠�")
+ @PostMapping("/addTestObjectPart")
+ public Result addTestObjectPart(@RequestBody StructureTestObjectPart structureTestObjectPart) {
+ structureTestObjectPartService.addTestObjectPart(structureTestObjectPart);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鏇存柊妫�楠屽璞¢浂浠�")
+ @PostMapping("/updateTestObjectPart")
+ public Result updateTestObjectPart(@RequestBody StructureTestObjectPart structureTestObjectPart) {
+ structureTestObjectPartService.updateTestObjectPart(structureTestObjectPart);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鍒犻櫎妫�楠屽璞¢浂浠�")
+ @PostMapping("/deleteTestObjectPart")
+ public Result deleteTestObjectPart(Integer id) {
+ structureTestObjectPartService.removeById(id);
+ return Result.success();
+ }
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/CopyStandardProductListDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/CopyStandardProductListDto.java
new file mode 100644
index 0000000..7287adb
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/CopyStandardProductListDto.java
@@ -0,0 +1,23 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.StandardProductList;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 鏍囧噯妫�楠岄」澶嶅埗
+ *
+ * @Author zhuo
+ * @Date 2024/10/31
+ */
+@Data
+public class CopyStandardProductListDto {
+
+ @ApiModelProperty("鍘熸湰妫�楠岄」淇℃伅")
+ private List<StandardProductList> oldStandardProductList;
+
+ @ApiModelProperty("闇�瑕佸姣旂殑妫�楠岄」淇℃伅")
+ private List<StandardProductList> newStandardProductList;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/FactoryDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/FactoryDto.java
new file mode 100644
index 0000000..612bcf8
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/FactoryDto.java
@@ -0,0 +1,18 @@
+package com.ruoyi.basic.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class FactoryDto {
+
+ private String code = "[1]";
+
+ private String label;
+
+ private String value;
+
+ private List<LaboratoryDto> children;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityCheckDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityCheckDto.java
new file mode 100644
index 0000000..db5c582
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityCheckDto.java
@@ -0,0 +1,182 @@
+package com.ruoyi.basic.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * 鍘熸潗鏂欐煡璇�, 鎺掗櫎浜嗕緵搴斿晢
+ * @Author zhuo
+ * @Date 2024/8/28
+ */
+@Data
+public class IfsInventoryQuantityCheckDto implements Serializable {
+
+ private Integer id;
+
+ @ApiModelProperty("鍩�")
+ private String contract;
+
+ @ApiModelProperty("璁㈠崟鍙�")
+ private String orderNo;
+
+
+ @ApiModelProperty("琛屽彿")
+ private String lineNo;
+
+ @ApiModelProperty("涓嬭揪鍙�")
+ private String releaseNo;
+
+ @ApiModelProperty("鎺ユ敹鍙�")
+ private Integer receiptNo;
+
+ @ApiModelProperty("闆朵欢鍙�")
+ private String partNo;
+
+ @ApiModelProperty("闆朵欢鎻忚堪")
+ private String partDesc;
+
+ @ApiModelProperty("鐘舵�佹弿杩�")
+ private String status;
+
+ @ApiModelProperty("鐘舵��")
+ private String statusDb;
+
+ @ApiModelProperty("鎶佃揪鐨勯噰璐暟閲�")
+ private BigDecimal qtyArrived;
+
+ @ApiModelProperty("宸叉楠岀殑璐拱鏁伴噺")
+ private BigDecimal qtyInspected;
+
+ @ApiModelProperty("瑕佹楠岀殑閲囪喘鏁伴噺")
+ private BigDecimal qtyToInspect;
+
+ @ApiModelProperty("鎶佃揪鐨勫簱瀛樻暟閲�")
+ private BigDecimal invQtyInStore;
+
+ @ApiModelProperty("鎶佃揪鐨勯噰璐暟閲�")
+ private BigDecimal purQtyInStore;
+
+ @ApiModelProperty("閰嶇疆鏍囪瘑")
+ private String configurationId;
+
+ @ApiModelProperty("鎵瑰彿")
+ private String lotBatchNo;
+
+ @ApiModelProperty("wdr鍙�")
+ private String waivDevRejNo;
+
+ @ApiModelProperty("娲诲姩搴忓垪")
+ private Integer activitySeq;
+
+
+ @ApiModelProperty("搴忓垪鍙�")
+ private String serialNo;
+
+ @ApiModelProperty("搴撲綅鍙�")
+ private String locationNo;
+
+ @ApiModelProperty("鐗堟湰鍙�")
+ private String engChgLevel;
+
+ @ApiModelProperty("鎺ユ敹浜�")
+ private String receiver;
+
+ @ApiModelProperty("鎺ユ敹浜哄鍚�")
+ private String receiverName;
+
+ @ApiModelProperty("閲囪喘鍛�")
+ private String buyerCode;
+
+ @ApiModelProperty("閲囪喘鍛樺鍚�")
+ private String buyerName;
+
+ @ApiModelProperty("瀹為檯鍒拌揣鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime arriveDate;
+
+ @ApiModelProperty("瀹為檯浜よ揣鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime deliveryDate;
+
+ @ApiModelProperty("鐢熶骇鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime productDate;
+
+ @ApiModelProperty("澶辨晥鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime invalidDate;
+
+
+ @ApiModelProperty("瀹℃壒鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime approvedDate;
+
+ @ApiModelProperty("閲囪喘鐢宠鍒涘缓浜�")
+ private String reqCeater;
+
+ @ApiModelProperty("閲囪喘鐢宠鍒涘缓浜哄鍚�")
+ private String reqCeaterName;
+
+ @ApiModelProperty("閲囪喘璁㈠崟琛屽娉�")
+ private String lineRemarks;
+
+ @ApiModelProperty("鍗曚綅")
+ private String buyUnitMeas;
+
+
+ private Integer isSource;
+
+ private Integer number;
+
+
+ private Integer state;
+
+ @ApiModelProperty("鎺ユ敹鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime receiverDate;
+
+ @ApiModelProperty("鏄惁涓洪娆″嚭鐜� 0 鍚� 1 鏄�")
+ private Integer isFirst;
+
+ @ApiModelProperty("鐩爣搴撲綅鍙�")
+ private String toLocation;
+
+ @ApiModelProperty("鏄惁鏄姤妫� 0 鍚� 1 鏄�")
+ private Integer isInspect;
+
+ @ApiModelProperty("鎶ユ浜�")
+ private String declareUser;
+
+
+ @ApiModelProperty("鎶ユ浜篿d")
+ private Integer declareUserId;
+
+ @ApiModelProperty("鍗曚綅")
+ private String partUnit;
+
+ @ApiModelProperty("浜т笟閾炬娴嬫暟鎹�")
+ private String industryChain;
+
+ @ApiModelProperty("鎶ユ鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime declareDate;
+
+ @ApiModelProperty("鏄惁鍗″彲浠ュ搴︽楠� 0 鍚� 1 鏄�")
+ private Integer isQuarter;
+
+ // 淇敼鍚庣殑
+ @ApiModelProperty("鎵瑰彿")
+ private String updateBatchNo;
+
+ @ApiModelProperty("鏄惁鏄摐鍗曚笣, 0鍚�, 1鏄�")
+ private Integer isCopper;
+
+ @ApiModelProperty("鐗╂枡绫诲瀷")
+ private Integer isExpire;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityDto.java
new file mode 100644
index 0000000..237224e
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantityDto.java
@@ -0,0 +1,82 @@
+package com.ruoyi.basic.dto;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Data
+public class IfsInventoryQuantityDto extends IfsInventoryQuantityCheckDto {
+
+ /**
+ * 濮旀墭缂栧彿
+ */
+ @ApiModelProperty("濮旀墭缂栧彿")
+ private String entrustCode;
+
+ @ApiModelProperty("妫�楠屽璞�")
+ private String sampleType;
+
+ @ApiModelProperty("鏍峰搧鍚嶇О")
+ private String sampleName;
+
+ @ApiModelProperty("鏍峰搧鍨嬪彿")
+ private String sampleModel;
+
+ @ApiModelProperty("鏍峰搧缂栧彿")
+ private String sampleCode;
+
+ // 杩涘巶
+ @ApiModelProperty("璁㈠崟id")
+ private Integer enterOrderId;
+
+ @ApiModelProperty("鎶ュ憡id")
+ private String enterReportId;
+
+ @ApiModelProperty("绯荤粺鐢熸垚鎶ュ憡鍦板潃")
+ private String enterUrl;
+
+ @ApiModelProperty("鎵嬪姩涓婁紶鎶ュ憡鍦板潃")
+ private String enterUrlS;
+
+ // 瀛e害
+ @ApiModelProperty("璁㈠崟id")
+ private Integer quarterOrderId;
+
+ @ApiModelProperty("鎶ュ憡id")
+ private String quarterReportId;
+
+ @ApiModelProperty("绯荤粺鐢熸垚鎶ュ憡鍦板潃")
+ private String quarterUrl;
+
+ @ApiModelProperty("鎵嬪姩涓婁紶鎶ュ憡鍦板潃")
+ private String quarterUrlS;
+
+ private Integer orderState;
+
+ @ApiModelProperty("涓嬪彂鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime sendTime;
+
+ @ApiModelProperty("鏉愭枡鍘傚")
+ private String supplierName;
+
+ @ApiModelProperty("濮旀墭浜�")
+ private String prepareUser;
+
+ @ApiModelProperty("棰滆壊")
+ private String color;
+
+ @ApiModelProperty("鏍囩鐘舵��")
+ private String labelStatus;
+
+ @ApiModelProperty("鏍囩鏉″舰鐮�")
+ private String labelBarCode;
+
+ @ApiModelProperty("鍒涘缓浜�")
+ private Integer createUser;
+
+ @ApiModelProperty("妫�楠屼汉")
+ private String userName;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantitySupplierDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantitySupplierDto.java
new file mode 100644
index 0000000..71bfddb
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/IfsInventoryQuantitySupplierDto.java
@@ -0,0 +1,124 @@
+package com.ruoyi.basic.dto;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.basic.pojo.IfsInventoryQuantity;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 鑳芥煡璇㈠埌渚涘簲鍟�
+ */
+@Data
+@ExcelIgnoreUnannotated
+public class IfsInventoryQuantitySupplierDto extends IfsInventoryQuantity {
+
+ /**
+ * 濮旀墭缂栧彿
+ */
+ @ExcelProperty(index = 2, value = "濮旀墭缂栧彿")
+ @ApiModelProperty("濮旀墭缂栧彿")
+ private String entrustCode;
+
+ @ApiModelProperty("鏍峰搧id")
+ private Integer sampleId;
+
+ @ApiModelProperty("妫�楠屽璞�")
+ private String sampleType;
+
+ @ExcelProperty(index = 7, value = "鏍峰搧鍚嶇О")
+ @ApiModelProperty("鏍峰搧鍚嶇О")
+ private String sampleName;
+
+ @ExcelProperty(index = 8, value = "鏍峰搧鍨嬪彿")
+ @ApiModelProperty("鏍峰搧鍨嬪彿")
+ private String sampleModel;
+
+ @ApiModelProperty("鏍峰搧缂栧彿")
+ private String sampleCode;
+
+ // 杩涘巶
+ @ApiModelProperty("杩涘巶璁㈠崟id")
+ private Integer enterOrderId;
+
+ @ApiModelProperty("鎶ュ憡id")
+ private String enterReportId;
+
+ @ApiModelProperty("绯荤粺鐢熸垚鎶ュ憡鍦板潃")
+ private String enterUrl;
+
+ @ApiModelProperty("鎵嬪姩涓婁紶鎶ュ憡鍦板潃")
+ private String enterUrlS;
+
+ // 瀛e害
+ @ApiModelProperty("瀛e害璁㈠崟id")
+ private Integer quarterOrderId;
+
+ @ApiModelProperty("鎶ュ憡id")
+ private String quarterReportId;
+
+ @ApiModelProperty("绯荤粺鐢熸垚鎶ュ憡鍦板潃")
+ private String quarterUrl;
+
+ @ApiModelProperty("鎵嬪姩涓婁紶鎶ュ憡鍦板潃")
+ private String quarterUrlS;
+
+ private Integer orderState;
+
+ @ApiModelProperty("涓嬪彂鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime sendTime;
+
+ @ApiModelProperty("濮旀墭浜�")
+ private String prepareUser;
+
+ @ApiModelProperty("棰滆壊")
+ private String color;
+
+ @ApiModelProperty("鏍囩鐘舵��")
+ private String labelStatus;
+
+ @ApiModelProperty("鏍囩鏉″舰鐮�")
+ private String labelBarCode;
+
+ @ApiModelProperty("鍒涘缓浜�")
+ private Integer createUser;
+
+ @ExcelProperty(index = 9, value = "妫�楠屼汉")
+ @ApiModelProperty("妫�楠屼汉")
+ private String userName;
+
+ @ExcelProperty(index = 10, value = "涓嬪彂鏃堕棿")
+ private String sendTimeString;
+
+ @ExcelProperty(index = 14, value = "鎺ユ敹鏃堕棿")
+ private String receiverDateString;
+
+ @ExcelProperty(index = 15, value = "鎶ユ鏃堕棿")
+ private String declareDateString;
+
+ // 鍚堟牸鐘舵��,: 0 妫�楠屼腑, 1鍚堟牸, 2涓嶅悎鏍�, 3鏈笅鍗�,4璁╂鏀捐
+ @ExcelProperty(index = 6, value = "妫�楠岀姸鎬�")
+ private String inspectStatusString;
+
+ @ApiModelProperty("鎶ユ寮�濮嬫椂闂�")
+ private String beginDeclareDate;
+
+ @ApiModelProperty("鎶ユ缁撴潫鏃堕棿")
+ private String endDeclareDate;
+
+ @ApiModelProperty("涓嶅悎鏍兼弿杩�")
+ @ExcelProperty(index = 16, value = "涓嶅悎鏍兼弿杩�")
+ private String unqualifiedDesc;
+
+
+ @ApiModelProperty("涓嶅悎鏍奸」")
+ @ExcelProperty(index = 17, value = "涓嶅悎鏍奸」")
+ private String unqualifiedItem;
+
+ @ApiModelProperty("鍏嶆")
+ private Integer isExemption;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/InsSampleReceiveDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/InsSampleReceiveDto.java
new file mode 100644
index 0000000..fbc2683
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/InsSampleReceiveDto.java
@@ -0,0 +1,35 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.InsSample1;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Author zhuo
+ * @Date 2024/10/29
+ */
+@Data
+public class InsSampleReceiveDto extends InsSample1 {
+
+ @ApiModelProperty("闆朵欢鍙�")
+ private String partNo;
+
+ @ApiModelProperty("鍘熸潗鏂檌d")
+ private Integer ifsInventoryId;
+
+ @ApiModelProperty("鑺暟")
+ private String cores;
+
+ @ApiModelProperty("鍨嬪彿鍙傛暟")
+ private String modelNum;
+
+ @ApiModelProperty("瀵间綋鏉愯川")
+ private String conductorMaterial;
+
+ @ApiModelProperty("瀵间綋绫诲瀷")
+ private String conductorType;
+
+ @ApiModelProperty("鏄惁鏄數缂嗛厤缃�")
+ private String isCableTag;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/LaboratoryDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/LaboratoryDto.java
new file mode 100644
index 0000000..e3f000c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/LaboratoryDto.java
@@ -0,0 +1,18 @@
+package com.ruoyi.basic.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class LaboratoryDto {
+
+ private String code = "[2]";
+
+ private String label;
+
+ private String value;
+
+ private List<SampleTypeDto> children;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/ModelDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/ModelDto.java
new file mode 100644
index 0000000..5f8321e
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/ModelDto.java
@@ -0,0 +1,15 @@
+package com.ruoyi.basic.dto;
+
+import lombok.Data;
+
+@Data
+public class ModelDto {
+
+ private String code = "[5]";
+
+ private String label;
+
+ private String value;
+
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/PageTestObjectDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/PageTestObjectDto.java
new file mode 100644
index 0000000..684cf46
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/PageTestObjectDto.java
@@ -0,0 +1,25 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.StructureTestObject;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Author 鎴村崜
+ * @Date 2024/2/26
+ */
+@Data
+public class PageTestObjectDto extends StructureTestObject {
+
+ @ApiModelProperty(value = "浜у搧")
+ private String product;
+
+ @ApiModelProperty(value = "鍒涘缓浜�")
+ private String createUserName;
+
+ @ApiModelProperty(value = "鏇存柊浜�")
+ private String updateUserName;
+
+ @ApiModelProperty(value = "闆朵欢鍙�")
+ private String partNo;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/ProductDTO1.java b/basic-server/src/main/java/com/ruoyi/basic/dto/ProductDTO1.java
new file mode 100644
index 0000000..8ed7631
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/ProductDTO1.java
@@ -0,0 +1,16 @@
+package com.ruoyi.basic.dto;
+
+import com.ruoyi.basic.pojo.Product;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Author zhuo
+ * @Date 2024/8/5
+ */
+@Data
+public class ProductDTO1 extends Product {
+
+ @ApiModelProperty(value = "闆朵欢鍙�")
+ private String partNo;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/ProductDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/ProductDto.java
new file mode 100644
index 0000000..efd5d2e
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/ProductDto.java
@@ -0,0 +1,11 @@
+package com.ruoyi.basic.dto;
+
+import lombok.Data;
+
+@Data
+public class ProductDto {
+
+ private Integer id;
+
+ private String name;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/ResetTreeDragDTO.java b/basic-server/src/main/java/com/ruoyi/basic/dto/ResetTreeDragDTO.java
new file mode 100644
index 0000000..d875a91
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/ResetTreeDragDTO.java
@@ -0,0 +1,26 @@
+package com.ruoyi.basic.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * @Author zhuo
+ * @Date 2024/8/22
+ */
+@Data
+public class ResetTreeDragDTO {
+ @ApiModelProperty(value = "寮�濮嬬储寮�")
+ private String beginIndex;
+
+ @ApiModelProperty(value = "缁撴潫绱㈠紩")
+ private String endIndex;
+
+ @ApiModelProperty(value = "鏍囧噯缂栧彿id")
+ private String methodId;
+
+ @ApiModelProperty(value = "鏁�")
+ private String tree;
+
+ @ApiModelProperty(value = "妫�楠岄」琛宨d")
+ private String productionId;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/SampleDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/SampleDto.java
new file mode 100644
index 0000000..18fc086
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/SampleDto.java
@@ -0,0 +1,23 @@
+package com.ruoyi.basic.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SampleDto {
+
+ private String code = "[4]";
+
+ private String label;
+
+ private String value;
+
+ private String partNo;
+
+ // 鏍峰搧鑻辨枃
+ private String sampleEn;
+
+ private List<ModelDto> children;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/SampleTypeDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/SampleTypeDto.java
new file mode 100644
index 0000000..0ae8087
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/SampleTypeDto.java
@@ -0,0 +1,29 @@
+package com.ruoyi.basic.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class SampleTypeDto {
+
+ private String code = "[3]";
+
+ // 妫�娴嬪璞d
+ private Integer sampleTypeId;
+
+ // 妫�娴嬪璞℃帓搴�
+ private Integer sort;
+
+ private String label;
+
+ private String value;
+
+ private String partNo;
+
+ // 瀵硅薄鑻辨枃
+ private String sampleTypeEn;
+
+ private List<SampleDto> children;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/dto/TestItemDto.java b/basic-server/src/main/java/com/ruoyi/basic/dto/TestItemDto.java
new file mode 100644
index 0000000..4363a1a
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/dto/TestItemDto.java
@@ -0,0 +1,16 @@
+package com.ruoyi.basic.dto;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class TestItemDto {
+
+ private Integer id;
+
+ private String name;
+
+ private List<ProductDto> children;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectData.java b/basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectData.java
new file mode 100644
index 0000000..4fc2fd2
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectData.java
@@ -0,0 +1,25 @@
+package com.ruoyi.basic.excel;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import lombok.Data;
+
+@Data
+public class StructureTestObjectData {
+ @ExcelProperty(value = "鍦烘墍")
+ private String laboratory;
+
+ @ExcelProperty(value = "妫�娴嬪璞�")
+ private String specimenName;
+
+ @ExcelProperty(value = "妫�娴嬪璞�(EN)")
+ private String specimenNameEn;
+
+ @ExcelProperty(value = "瀵硅薄浠e彿")
+ private String code;
+
+ @ExcelProperty(value = "浜у搧鍚嶇О")
+ private String name;
+
+ @ExcelProperty(value = "浜у搧鍚嶇О(EN)")
+ private String nameEn;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectListener.java b/basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectListener.java
new file mode 100644
index 0000000..04d3c2c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/excel/StructureTestObjectListener.java
@@ -0,0 +1,38 @@
+package com.ruoyi.basic.excel;
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.ruoyi.basic.service.ProductService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class StructureTestObjectListener extends AnalysisEventListener<StructureTestObjectData> {
+ private static final int BATCH_COUNT = 1000;
+ List<StructureTestObjectData> list = new ArrayList<>();
+
+ private ProductService productService;
+
+ public StructureTestObjectListener(ProductService productService) {
+ this.productService = productService;
+ }
+
+ @Override
+ public void invoke(StructureTestObjectData data, AnalysisContext analysisContext) {
+ list.add(data);
+ if (list.size() >= BATCH_COUNT) {
+ save();
+ list.clear();
+ }
+ }
+
+ @Override
+ public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+ save();
+ }
+
+
+ private void save() {
+ productService.importPartExcel(list);
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/CertificationMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/CertificationMapper.java
new file mode 100644
index 0000000..2d50f3d
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/CertificationMapper.java
@@ -0,0 +1,14 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.Certification;
+import org.apache.ibatis.annotations.Param;
+
+public interface CertificationMapper extends BaseMapper<Certification> {
+
+ //鏌ヨ璧勮川鏄庣粏鍒楄〃
+ IPage<Certification> getCertificationDetail(Page page, @Param("ew") QueryWrapper<Certification> ew);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/IfsInventoryQuantityMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/IfsInventoryQuantityMapper.java
new file mode 100644
index 0000000..1963bb9
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/IfsInventoryQuantityMapper.java
@@ -0,0 +1,42 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.basic.dto.IfsInventoryQuantityDto;
+import com.ruoyi.basic.pojo.IfsInventoryQuantity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Mapper
+public interface IfsInventoryQuantityMapper extends BaseMapper<IfsInventoryQuantity> {
+
+ /**
+ * 鎵撳嵃鏍囩鏌ヨ
+ * @param ids
+ * @return
+ */
+ List<IfsInventoryQuantityDto> printLabel(@Param("ids") List<Integer> ids);
+
+ /**
+ *
+ * @param ifsInventoryId
+ * @return
+ */
+ int selectReportCountById(@Param("ifsInventoryId") Integer ifsInventoryId);
+
+
+ /**
+ * 鏌ヨ褰撳墠瀛e害鏄惁鍑虹幇杩囪鏉愭枡
+ * @param partDetail 鍨嬪彿
+ * @param supplierName 渚涘簲鍟嗗悕绉�
+ * @param startOfNextQuarter 瀛e害寮�濮嬫椂闂�
+ * @param endOfQuarter 瀛e害缁撴潫鏃堕棿
+ * @return
+ */
+ Integer selectIsFirst(@Param("partDetail") String partDetail,
+ @Param("supplierName") String supplierName,
+ @Param("startOfNextQuarter") LocalDateTime startOfNextQuarter,
+ @Param("endOfQuarter") LocalDateTime endOfQuarter);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/LaboratoryMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/LaboratoryMapper.java
new file mode 100644
index 0000000..df6aab9
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/LaboratoryMapper.java
@@ -0,0 +1,20 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.Laboratory;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 瀹為獙瀹ょ鐞�(Laboratory)琛ㄦ暟鎹簱璁块棶灞�
+ */
+public interface LaboratoryMapper extends BaseMapper<Laboratory> {
+
+ IPage<Laboratory> selectItemParameter(Page page, @Param("ew") QueryWrapper<Laboratory> ew);
+
+ Object obtainItemParameterList(@Param("page") Page page, @Param("ew") QueryWrapper<Laboratory> ew);
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java
new file mode 100644
index 0000000..8fdbc4a
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductMapper.java
@@ -0,0 +1,24 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.ProductDTO1;
+import com.ruoyi.basic.pojo.Product;
+import org.apache.ibatis.annotations.Param;
+
+/**
+* @author z1292
+* @description 閽堝琛ㄣ�恜roduct(浜у搧琛�)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2024-04-26 01:11:02
+* @Entity com.ruoyi.basic.pojo.Product
+*/
+public interface ProductMapper extends BaseMapper<Product> {
+
+ IPage<Product> selectProductListByObjectId(Page page, @Param("ew") QueryWrapper<ProductDTO1> ew, @Param("partNo") String partNo);
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductPartMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductPartMapper.java
new file mode 100644
index 0000000..9d2943f
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductPartMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.ruoyi.basic.pojo.ProductPart;
+import org.apache.ibatis.annotations.Param;
+
+public interface ProductPartMapper extends BaseMapper<ProductPart> {
+ IPage<ProductPart> selectListByProductId(IPage<ProductPart> page,
+ @Param("ew") QueryWrapper<ProductPart> ew,
+ @Param("productId") Integer productId);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductSupplierDensityMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductSupplierDensityMapper.java
new file mode 100644
index 0000000..80b387c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/ProductSupplierDensityMapper.java
@@ -0,0 +1,22 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.ProductSupplierDensity;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 浜у搧鍘傚瀵嗗害缁戝畾琛�
+ *
+ * @author zhuo
+ * @since 2024-09-19
+ */
+@Mapper
+public interface ProductSupplierDensityMapper extends BaseMapper<ProductSupplierDensity> {
+
+ IPage<ProductSupplierDensity> selectListByProductId(@Param("page") Page page, @Param("ew") QueryWrapper<ProductSupplierDensity> ew, @Param("productId") Integer productId);
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/SealMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/SealMapper.java
new file mode 100644
index 0000000..9b96fc9
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/SealMapper.java
@@ -0,0 +1,17 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.Laboratory;
+import com.ruoyi.basic.pojo.Seal;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+public interface SealMapper extends BaseMapper<Seal> {
+ IPage<Seal>selectSeal(Page page, @Param("ew") QueryWrapper<Seal> ew);
+ List<Laboratory> selectLaboratory (Integer labId);
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodListMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodListMapper.java
new file mode 100644
index 0000000..a5e337b
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodListMapper.java
@@ -0,0 +1,40 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.basic.pojo.StandardMethodList;
+import com.ruoyi.basic.pojo.StandardProductList;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_method_list(鏍囧噯鏍戜笅鐨勬爣鍑嗗垪琛�)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2024-03-04 13:44:04
+* @Entity com.ruoyi.basic.pojo.StandardMethodList
+*/
+public interface StandardMethodListMapper extends BaseMapper<StandardMethodList> {
+
+ Map<String, String> selectStandardMethodById(Integer id);
+
+ String selectUserById(Integer id);
+
+ List<StandardMethodList> selectStandardMethodLists(String tree);
+
+ List<StandardMethodList> selectStandardMethodListsByNull(String tree);
+
+ List<StandardMethodList> selectStandardMethodLists3(String tree);
+
+ List<StandardMethodList> selectStandardMethodLists2(@Param("data1") String data1, @Param("data2") String data2, @Param("data3") String data3, @Param("data4") String data4, @Param("data5") String data5);
+
+ List<StandardProductList> selectParameterList(String code);
+
+ List<StandardMethodList> selectListEnum();
+
+ Integer getStandardMethodId(String code);
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodMapper.java
new file mode 100644
index 0000000..fb88032
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardMethodMapper.java
@@ -0,0 +1,26 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.mybatis_config.MyBaseMapper;
+import com.ruoyi.basic.pojo.StandardMethod;
+import org.apache.ibatis.annotations.Param;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_method(鏍囧噯鏂规硶)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2024-03-03 19:21:41
+* @Entity com.ruoyi.basic.pojo.StandardMethod
+*/
+public interface StandardMethodMapper extends MyBaseMapper<StandardMethod> {
+
+ IPage<StandardMethod> selectStandardMethodList(Page page, @Param("ew") QueryWrapper<StandardMethod> ew);
+
+ StandardMethod selectStandMethodById(Integer id);
+
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListMapper.java
new file mode 100644
index 0000000..f25f673
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListMapper.java
@@ -0,0 +1,69 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.ruoyi.basic.pojo.StandardProductList;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_product_list(鏍囧噯鏍戜笅鐨勬楠岄」鐩�)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2024-03-05 10:33:29
+* @Entity com.ruoyi.basic.pojo.StandardProductList
+*/
+public interface StandardProductListMapper extends BaseMapper<StandardProductList> {
+
+ IPage<StandardProductList> standardProductListIPage(@Param("id") Integer id, @Param("tree") String tree, IPage<StandardProductList> page, @Param("laboratory") String laboratory, @Param("insItem") String insItem, @Param("insItems") String insItems);
+
+ StandardProductList getOne(@Param("standardMethodListId") Integer standardMethodListId, @Param("inspectionItem") String inspectionItem, @Param("sample") String sample, @Param("inspectionItemSubclass") String inspectionItemSubclass, @Param("model") String model, @Param("inspectionItemClass") String inspectionItemClass);
+
+ List<StandardProductList> selectDetail(@Param("standardMethodListId") Integer standardMethodListId, @Param("state") int state, @Param("model") String model, @Param("isCableTag") String isCableTag);
+
+ List<StandardProductList> selectDetail2(@Param("standardMethodListId") Integer standardMethodListId, @Param("state") int state, @Param("tree") String tree, @Param("isCableTag") String isCableTag);
+
+ /**
+ * 鏌ヨ闆朵欢棰滆壊
+ * @param partNo
+ * @return
+ */
+ Map<String, String> selectPartColor(@Param("partNo") String partNo);
+
+ /**
+ * 鍖洪棿淇敼
+ * @param productList
+ * @return
+ */
+ void updateSection(@Param("productList") StandardProductList productList);
+
+
+ /**
+ * 浠庝笂寰�涓嬩慨鏀归『搴�
+ * @param beginIndex 寮�濮嬩綅缃�
+ * @param endIndex 缁撴潫浣嶇疆
+ * @param methodId 鏍囧噯id
+ * @param tree 鏍�
+ */
+ void updateSortUp(@Param("beginIndex") Integer beginIndex,
+ @Param("endIndex") Integer endIndex,
+ @Param("methodId") Integer methodId,
+ @Param("tree") String tree);
+
+ /**
+ * 浠庝笅缃戜笂淇敼椤哄簭
+ * @param beginIndex
+ * @param endIndex
+ * @param methodId
+ * @param tree
+ */
+ void updateSortDown(@Param("beginIndex") Integer beginIndex,
+ @Param("endIndex") Integer endIndex,
+ @Param("methodId") Integer methodId,
+ @Param("tree") String tree);
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListSupplierAskMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListSupplierAskMapper.java
new file mode 100644
index 0000000..ff3cdfb
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardProductListSupplierAskMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.basic.pojo.StandardProductListSupplierAsk;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 妫�楠岄」鐩巶瀹跺瘑搴︾粦瀹氳〃
+ *
+ * @author zhuo
+ * @since 2024-09-23
+ */
+@Mapper
+public interface StandardProductListSupplierAskMapper extends BaseMapper<StandardProductListSupplierAsk> {
+
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTemplateMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTemplateMapper.java
new file mode 100644
index 0000000..feb76f2
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTemplateMapper.java
@@ -0,0 +1,32 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.StandardTemplate;
+import org.apache.ibatis.annotations.Param;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_template(鏍囧噯妯℃澘)銆戠殑鏁版嵁搴撴搷浣淢apper
+* @createDate 2024-03-11 13:47:52
+* @Entity com.ruoyi.basic.pojo.StandardTemplate
+*/
+public interface StandardTemplateMapper extends BaseMapper<StandardTemplate> {
+
+ IPage<StandardTemplate> selectStandardTemplatePageList(Page page, @Param("ew") QueryWrapper<StandardTemplate> ew);
+
+ StandardTemplate getStandTempIdByName(String name);
+
+ /**
+ * 鏌ヨ鍘嬬缉鍚庣殑鏁版嵁
+ * @param templateId
+ * @return
+ */
+ String selectCompressThing(Integer templateId);
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeMapper.java
new file mode 100644
index 0000000..4deb5df
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StandardTreeMapper.java
@@ -0,0 +1,92 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.*;
+import com.ruoyi.basic.pojo.IfsInventoryQuantity;
+import com.ruoyi.basic.pojo.StandardMethodList;
+import com.ruoyi.basic.pojo.StandardProductList;
+import com.ruoyi.basic.pojo.StandardTree;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * @author Administrator
+ * @description 閽堝琛ㄣ�恠tandard_tree(鏍囧噯鏍�)銆戠殑鏁版嵁搴撴搷浣淢apper
+ * @createDate 2024-03-01 15:06:44
+ * @Entity com.ruoyi.basic.pojo.StandardTree
+ */
+public interface StandardTreeMapper extends BaseMapper<StandardTree> {
+
+ List<FactoryDto> selectStandardTreeList();
+
+ List<StandardTree> selectStandardTreeList2(String sampleType);
+
+ StandardProductList selectStandardProductById(Integer id);
+
+ List<StandardProductList> getStandardProductListBySample(String sampleType);
+
+ List<StandardMethodList> getStandardMethodListBySample(String sampleType);
+
+ List<StandardProductList> selectStandardProductListByTree(String tree, String sample, String model, String trees, String laboratory);
+
+ List<StandardProductList> selectStandardProductListByTree2(String tree, String sample, String model, String trees, String laboratory);
+
+
+ List<SampleTypeDto> getStandardTree2();
+
+ List<SampleDto> getStandardTree3(String sampleType);
+
+
+ String getLaboratory(String str);
+
+ Integer getStructureItemParameterId(String sampleType, String item, String itemChild, String inspectionItemClass);
+
+ List<ProductDto> selectPList(String name);
+
+ String selSample(String sample);
+
+ List<FactoryDto> selectStandardTreeListByPartNo(@Param("partNo") String partNo);
+
+ IPage<IfsInventoryQuantity> selectIfsPage(IPage<IfsInventoryQuantity> page,
+ @Param("ew") QueryWrapper<IfsInventoryQuantity> ew);
+
+ IPage<IfsInventoryQuantityDto> getIfsByStateOne(IPage<IfsInventoryQuantityDto> page,
+ @Param("ew") QueryWrapper<IfsInventoryQuantityDto> ew);
+
+
+ IPage<IfsInventoryQuantityCheckDto> selectIfsInventoryQuantity(Page<IfsInventoryQuantityCheckDto> page, @Param("ew")QueryWrapper<IfsInventoryQuantityCheckDto> ew);
+
+ /**
+ * 鍘熸潗鎶ユ鏌ヨ鍏ㄩ儴(鍒嗛〉)
+ * @param page
+ * @param ew
+ * @return
+ */
+ IPage<IfsInventoryQuantitySupplierDto> getIfsByOver(Page<IfsInventoryQuantitySupplierDto> page, @Param("ew") QueryWrapper<IfsInventoryQuantitySupplierDto> ew, @Param("beginDeclareDate") String beginDeclareDate, @Param("endDeclareDate")String endDeclareDate);
+
+ /**
+ * 鍘熸潗鎶ユ鏌ヨ鍏ㄩ儴(鏃犲垎椤�)
+ * @param ew
+ * @return
+ */
+ List<IfsInventoryQuantitySupplierDto> getIfsByOverList(@Param("ew") QueryWrapper<IfsInventoryQuantitySupplierDto> ew, @Param("beginDeclareDate") String beginDeclareDate, @Param("endDeclareDate")String endDeclareDate);
+
+ /**
+ * 鍘熸潗鏂欐煡璇㈠搴︽楠�
+ * @param page
+ * @param
+ * @param beginDeclareDate
+ * @param endDeclareDate
+ * @return
+ */
+ IPage<IfsInventoryQuantitySupplierDto> getIfsByQuarter(Page<IfsInventoryQuantitySupplierDto> page, @Param("ew") QueryWrapper<IfsInventoryQuantitySupplierDto> ew, @Param("beginDeclareDate") String beginDeclareDate, @Param("endDeclareDate")String endDeclareDate);
+
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureItemParameterMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureItemParameterMapper.java
new file mode 100644
index 0000000..654741a
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureItemParameterMapper.java
@@ -0,0 +1,30 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.TestItemDto;
+import com.ruoyi.basic.pojo.StructureItemParameter;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 妫�楠岄」鐩弬鏁�(StructureItemParameter)琛ㄦ暟鎹簱璁块棶灞�
+ *
+ * @author makejava
+ * @since 2024-02-26 16:21:17
+ */
+public interface StructureItemParameterMapper extends BaseMapper<StructureItemParameter> {
+
+ IPage<StructureItemParameter> selectItemParameterList(Page page, @Param("ew") QueryWrapper<StructureItemParameter> ew);
+
+ List<Map<String, Object>> getInsProduction();
+
+ List<TestItemDto> getItemTree();
+
+ int removeNoSample(@Param("sample") String sample);
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java
new file mode 100644
index 0000000..1ada57c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectMapper.java
@@ -0,0 +1,22 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.dto.PageTestObjectDto;
+import com.ruoyi.basic.pojo.StructureTestObject;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 妫�娴嬪璞�(StructureTestObject)琛ㄦ暟鎹簱璁块棶灞�
+ *
+ * @author makejava
+ * @since 2024-02-26 17:36:41
+ */
+public interface StructureTestObjectMapper extends BaseMapper<StructureTestObject> {
+
+ IPage<PageTestObjectDto> selectTestObjectList(Page page, @Param("ew") QueryWrapper<PageTestObjectDto> ew, @Param("partNo") String partNo);
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectPartMapper.java b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectPartMapper.java
new file mode 100644
index 0000000..33e54f7
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/mapper/StructureTestObjectPartMapper.java
@@ -0,0 +1,21 @@
+package com.ruoyi.basic.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.basic.pojo.StructureTestObjectPart;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+
+/**
+ * 妫�楠屽璞¢浂浠惰〃
+ *
+ * @author zhuo
+ * @since 2024-08-07
+ */
+@Mapper
+public interface StructureTestObjectPartMapper extends BaseMapper<StructureTestObjectPart> {
+ IPage<StructureTestObjectPart> selectListByTestObjectId(Page page, @Param("ew") QueryWrapper<StructureTestObjectPart> structureTestObjectPartQueryWrapper, @Param("testObjectId") Integer testObjectId);
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/Certification.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/Certification.java
new file mode 100644
index 0000000..7eb1649
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/Certification.java
@@ -0,0 +1,72 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@TableName(value = "certification")
+@Data
+public class Certification implements Serializable {
+
+ @ApiModelProperty(value = "涓婚敭")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty(value = "璧勮川鍚嶇О")
+ private String name;
+
+ @ApiModelProperty(value = "璧勮川缂栫爜")
+ private String code;
+
+ @ApiModelProperty(value = "棰佸彂鏈烘瀯")
+ private String organization;
+
+ @ApiModelProperty(value = "璧勮川璇存槑")
+ private String explanation;
+
+ @ApiModelProperty(value = "棣栨棰佸彂鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime firstIssuanceDate;
+
+ @ApiModelProperty(value = "鏈�杩戦鍙戞椂闂�")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime latestIssuanceDate;
+
+
+
+ @ApiModelProperty(value = "鍒版湡棰佸彂鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime expireTime;
+
+
+ @ApiModelProperty(value = "棰佸竷鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime dateOfIssuance;
+
+ @ApiModelProperty(value = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+
+ @ApiModelProperty(value = "鏇存柊浜�")
+ private String createUserName;
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty(value = "璧勮川鍥剧墖鍦板潃")
+ private String imageUrl;
+
+ @ApiModelProperty(value = "璧勮川闄勪欢鍦板潃")
+ private String fileUrl;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/IfsInventoryQuantity.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/IfsInventoryQuantity.java
new file mode 100644
index 0000000..3984802
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/IfsInventoryQuantity.java
@@ -0,0 +1,210 @@
+package com.ruoyi.basic.pojo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("ifs_inventory_quantity")
+@ExcelIgnoreUnannotated
+public class IfsInventoryQuantity implements Serializable {
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+
+ @ApiModelProperty("鍩�")
+ private String contract;
+
+ @ExcelProperty(index = 13, value = "璁㈠崟鍙�")
+ @ApiModelProperty("璁㈠崟鍙�")
+ private String orderNo;
+
+ @ApiModelProperty("琛屽彿")
+ private String lineNo;
+
+ @ApiModelProperty("涓嬭揪鍙�")
+ private String releaseNo;
+
+ @ApiModelProperty("鎺ユ敹鍙�")
+ private Integer receiptNo;
+
+ @ExcelProperty(index = 3, value = "闆朵欢鍙�")
+ @ApiModelProperty("闆朵欢鍙�")
+ private String partNo;
+
+ @ExcelProperty(index = 4, value = "闆朵欢鎻忚堪")
+ @ApiModelProperty("闆朵欢鎻忚堪")
+ private String partDesc;
+
+ @ApiModelProperty("鐘舵�佹弿杩�(IFS鍘熸湰鎷夊彇鐨勭姸鎬�)")
+ private String status;
+
+ @ApiModelProperty("鐘舵��(IFS鍘熸湰鎷夊彇鐨勭姸鎬�)")
+ private String statusDb;
+
+ @ExcelProperty(index = 11, value = "鎶佃揪鐨勯噰璐暟閲�")
+ @ApiModelProperty("鎶佃揪鐨勯噰璐暟閲�")
+ private BigDecimal qtyArrived;
+
+ @ApiModelProperty("宸叉楠岀殑璐拱鏁伴噺")
+ private BigDecimal qtyInspected;
+
+ @ApiModelProperty("瑕佹楠岀殑閲囪喘鏁伴噺")
+ private BigDecimal qtyToInspect;
+
+ @ApiModelProperty("渚涘簲鍟嗙紪鍙�")
+ private String supplierId;
+
+ @ExcelProperty(index = 5, value = "渚涘簲鍟嗗悕绉�")
+ @ApiModelProperty("渚涘簲鍟嗗悕绉�")
+ private String supplierName;
+
+ @ApiModelProperty("鎶佃揪鐨勫簱瀛樻暟閲�")
+ private BigDecimal invQtyInStore;
+
+ @ApiModelProperty("鎶佃揪鐨勯噰璐暟閲�")
+ private BigDecimal purQtyInStore;
+
+ @ApiModelProperty("閰嶇疆鏍囪瘑")
+ private String configurationId;
+
+ @ApiModelProperty("鎵瑰彿")
+ private String lotBatchNo;
+
+ @ApiModelProperty("wdr鍙�")
+ private String waivDevRejNo;
+
+ @ApiModelProperty("娲诲姩搴忓垪")
+ private Integer activitySeq;
+
+ @ApiModelProperty("搴忓垪鍙�")
+ private String serialNo;
+
+ @ApiModelProperty("搴撲綅鍙�")
+ private String locationNo;
+
+ @ApiModelProperty("鐗堟湰鍙�")
+ private String engChgLevel;
+
+ @ApiModelProperty("鎺ユ敹浜�")
+ private String receiver;
+
+ @ApiModelProperty("鎺ユ敹浜哄鍚�")
+ private String receiverName;
+
+ @ApiModelProperty("閲囪喘鍛�")
+ private String buyerCode;
+
+ @ApiModelProperty("閲囪喘鍛樺鍚�")
+ private String buyerName;
+
+ @ApiModelProperty("瀹為檯鍒拌揣鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime arriveDate;
+
+ @ApiModelProperty("瀹為檯浜よ揣鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime deliveryDate;
+
+ @ApiModelProperty("鐢熶骇鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime productDate;
+
+ @ApiModelProperty("澶辨晥鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime invalidDate;
+
+
+ @ApiModelProperty("瀹℃壒鏃ユ湡")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime approvedDate;
+
+ @ApiModelProperty("閲囪喘鐢宠鍒涘缓浜�")
+ private String reqCeater;
+
+ @ApiModelProperty("閲囪喘鐢宠鍒涘缓浜哄鍚�")
+ private String reqCeaterName;
+
+ @ApiModelProperty("閲囪喘璁㈠崟琛屽娉�")
+ private String lineRemarks;
+
+ @ExcelProperty(index = 12, value = "鍗曚綅")
+ @ApiModelProperty("鍗曚綅")
+ private String buyUnitMeas;
+
+ @ApiModelProperty("鏄惁涓篿fs鎷夊彇,0 鍚�, 1鏄�")
+ private Integer isSource;
+
+ private Integer number;
+
+
+ @ApiModelProperty("鐘舵��: 0:寰呮姤妫�, 1:寰呮楠�, :宸插鏍�")
+ private Integer state;
+
+ @ApiModelProperty("鎺ユ敹鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime receiverDate;
+
+ @ApiModelProperty("鏄惁涓洪娆″嚭鐜� 0 鍚� 1 鏄�")
+ private Integer isFirst;
+
+ @ApiModelProperty("鐩爣搴撲綅鍙�")
+ private String toLocation;
+
+ @ApiModelProperty("鏄惁鏄姤妫� 0 鍚� 1 鏄�")
+ private Integer isInspect;
+
+ @ApiModelProperty("鎶ユ浜�")
+ private String declareUser;
+
+
+ @ApiModelProperty("鎶ユ浜篿d")
+ private Integer declareUserId;
+
+ @ApiModelProperty("鍗曚綅")
+ private String partUnit;
+
+ @ApiModelProperty("浜т笟閾炬娴嬫暟鎹�")
+ private String industryChain;
+
+ @ApiModelProperty("鎶ユ鏃堕棿")
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
+ private LocalDateTime declareDate;
+
+ @ApiModelProperty("鏄惁鍗″彲浠ュ搴︽楠� 0 鍚� 1 鏄�")
+ private Integer isQuarter;
+
+ // 淇敼鍚庣殑
+ @ExcelProperty(index = 1, value = "鎵瑰彿")
+ @ApiModelProperty("鎵瑰彿")
+ private String updateBatchNo;
+
+ @ApiModelProperty("鏄惁缁撴潫, 0鍚�, 1鏄�")
+ private Integer isFinish;
+
+ @ApiModelProperty("鏄惁鏄摐鍗曚笣, 0鍚�, 1鏄�")
+ private Integer isCopper;
+
+ // 鍚堟牸鐘舵��,: 0 妫�楠屼腑, 1鍚堟牸, 2涓嶅悎鏍�, 3鏈笅鍗�,4璁╂鏀捐
+ @ApiModelProperty("妫�楠岀姸鎬�")
+ private Integer inspectStatus;
+
+ @ApiModelProperty("鏄惁閲囪喘璁㈠崟鐧昏: 0鍚�, 1:鏄�")
+ private Integer isRegister;
+
+ @ApiModelProperty("鏄惁淇敼杩囨壒鍙�: 0鍚�, 1:鏄�")
+ private Integer isUpdateBatch;
+
+ // 鏄惁鏄繃鏈熸潗鏂�: 0鍚�, 1:鏄�"
+ @ApiModelProperty("鐗╂枡绫诲瀷")
+ private Integer isExpire;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/InsSample1.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/InsSample1.java
new file mode 100644
index 0000000..19d5cb9
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/InsSample1.java
@@ -0,0 +1,123 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 妫�楠屾牱鍝�
+ * @TableName ins_sample
+ */
+@TableName(value ="ins_sample")
+@Data
+public class InsSample1 implements Serializable {
+ /**
+ *
+ */
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 1锛氬悎鏍� 0锛氫笉鍚堟牸
+ */
+ private Integer insResult;
+
+ /**
+ * 澶栭敭锛歩ns_order琛╥d
+ */
+ private Integer insOrderId;
+
+ /**
+ * 閰嶅鏍峰搧鍨嬪彿
+ */
+ private String joinModel;
+
+ /**
+ * 閰嶅鏍峰搧鍚嶇О
+ */
+ private String joinName;
+
+ /**
+ * 閰嶅鏍峰搧鏁伴噺
+ */
+ private Integer joinNum;
+
+ /**
+ * 鏍峰搧缂栫爜
+ */
+ private String sampleCode;
+
+ /**
+ * 妫�楠屽伐鍘�
+ */
+ private String factory;
+
+ /**
+ * 瀹為獙瀹ゅ悕绉�
+ */
+ private String laboratory;
+
+ /**
+ * 鏍峰搧绫诲瀷
+ */
+ private String sampleType;
+
+ /**
+ * 鏍峰搧鍚嶇О
+ */
+ private String sample;
+
+ /**
+ * 瑙勬牸鍨嬪彿
+ */
+ private String model;
+
+ /**
+ * 妫�楠岀姸鎬�(0锛氬緟妫�楠�1:妫�楠屼腑 2:宸叉楠�3锛氬緟澶嶆牳4锛氬鏍告湭閫氳繃5锛氬鏍搁�氳繃)
+ */
+ private Integer insState;
+
+ /**
+ * 澶囨敞
+ */
+ private String remark;
+
+ private Integer standardMethodListId;
+
+ @ApiModelProperty("鏍峰搧鍗曚綅")
+ private String unit;
+
+ private Integer cellId;
+
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ private Integer parentId;
+
+ @ApiModelProperty("鏁伴噺")
+ private Integer quantity;
+
+ @ApiModelProperty("鐗规畩鏍囧噯鏂规硶")
+ private String specialStandardMethod;
+
+ @TableField(select = false,exist = false)
+ private Integer num=1;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/Laboratory.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/Laboratory.java
new file mode 100644
index 0000000..a9343a1
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/Laboratory.java
@@ -0,0 +1,62 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 瀹為獙瀹ょ鐞�(Laboratory)琛ㄥ璞�
+ */
+@TableName(value = "laboratory")
+@Data
+@NoArgsConstructor
+public class Laboratory implements Serializable {
+ @ApiModelProperty(value = "涓婚敭")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty(value = "瀹為獙瀹ゅ悕绉�")
+ private String laboratoryName;
+
+ @ApiModelProperty(value = "鍦烘墍缂栫爜")
+ private String laboratoryNumber;
+
+ @ApiModelProperty(value = "瀹為獙瀹や唬鍙�")
+ private String laboratoryCode;
+
+ @ApiModelProperty(value = "璐熻矗浜虹數璇�")
+ private String phoneNumber;
+
+ @ApiModelProperty(value = "璐熻矗浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private String head;
+
+ @ApiModelProperty(value = "鍦板潃")
+ private String address;
+
+ @ApiModelProperty(value = "鍒涘缓浜�")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "鍒涘缓浜�")
+ private String createUserName;
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/Product.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/Product.java
new file mode 100644
index 0000000..0847231
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/Product.java
@@ -0,0 +1,57 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 浜у搧琛�
+ * @TableName product
+ */
+@TableName(value ="product")
+@Data
+public class Product implements Serializable {
+ /**
+ *
+ */
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 浜у搧鍚嶇О
+ */
+ private String name;
+
+ /**
+ * 浜у搧鍚嶇ОEN
+ */
+ private String nameEn;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ /**
+ * 澶栭敭锛歴tructure_test_object琛╥d
+ */
+ private Integer objectId;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/ProductPart.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/ProductPart.java
new file mode 100644
index 0000000..0a29975
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/ProductPart.java
@@ -0,0 +1,49 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@TableName("product_part")
+public class ProductPart implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("浜у搧id")
+ private Integer productId;
+
+ @ApiModelProperty("闆朵欢鍙�")
+ private String partNo;
+
+ @ApiModelProperty("棰滆壊")
+ private String color;
+
+ @ApiModelProperty("鑹叉爣")
+ private String colorCode;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/ProductSupplierDensity.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/ProductSupplierDensity.java
new file mode 100644
index 0000000..b953919
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/ProductSupplierDensity.java
@@ -0,0 +1,57 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 浜у搧鍘傚瀵嗗害缁戝畾琛�
+ *
+ * @author zhuo
+ * @since 2024-09-19
+ */
+@Data
+@TableName("product_supplier_density")
+public class ProductSupplierDensity implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("浜у搧id")
+ private Integer productId;
+
+ @ApiModelProperty("鍨嬪彿")
+ private String model;
+
+ @ApiModelProperty("鍘傚鍚嶇О")
+ private String supplierName;
+
+ @ApiModelProperty("瀵嗗害鍊�")
+ private String densityValue;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/Seal.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/Seal.java
new file mode 100644
index 0000000..783703c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/Seal.java
@@ -0,0 +1,43 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鍗扮珷绠$悊(Laboratory)琛ㄥ璞�
+ */
+
+@TableName(value = "seal")
+@Data
+public class Seal implements Serializable {
+ @ApiModelProperty(value = "涓婚敭")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty(value = "瀹為獙瀹d")
+ private Integer labId;
+
+ @TableField(exist=false)
+ @ApiModelProperty(value = "瀹為獙瀹ゅ悕绉�")
+ private String laboratoryName;
+
+ @ApiModelProperty(value = "鍗扮珷鍥剧墖")
+ private String address;
+
+ @ApiModelProperty(value = "鍗扮珷绫诲瀷")
+ private String type;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethod.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethod.java
new file mode 100644
index 0000000..6d5ec08
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethod.java
@@ -0,0 +1,85 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鏍囧噯鏂规硶
+ * @TableName standard_method
+ */
+@TableName(value ="standard_method")
+@Data
+public class StandardMethod implements Serializable {
+ /**
+ *
+ */
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ private String field;
+
+ @ApiModelProperty("妫�楠屽璞�")
+ private String structureTestObjectId;
+
+ /**
+ * 鏍囧噯缂栧彿
+ */
+ @ApiModelProperty(value = "鏍囧噯缂栧彿")
+ private String code;
+
+ /**
+ * 鏍囧噯鏂规硶
+ */
+ @ApiModelProperty(value = "鏍囧噯鎻忚堪")
+ private String name;
+
+ @ApiModelProperty(value = "鏍囧噯鎻忚堪EN")
+ private String nameEn;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty(value = "澶囨敞")
+ private String remark;
+
+ @ApiModelProperty(value = "璧勮川")
+ private String qualificationId;
+
+ @ApiModelProperty(value = "鏄惁浜у搧鏍囧噯")
+ private Integer isProduct;
+
+ @ApiModelProperty(value = "鏄惁鍚敤")
+ private Integer isUse;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓浜�")
+ @TableField(exist = false,select = false)
+ private String createUserName;
+
+ @ApiModelProperty(value = "鏇存柊浜�")
+ @TableField(exist = false,select = false)
+ private String updateUserName;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethodList.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethodList.java
new file mode 100644
index 0000000..8161270
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardMethodList.java
@@ -0,0 +1,83 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鏍囧噯鏍戜笅鐨勬爣鍑嗗垪琛�
+ * @TableName standard_method_list
+ */
+@TableName(value ="standard_method_list")
+@Data
+public class StandardMethodList implements Serializable {
+ /**
+ *
+ */
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 鏍囧噯缂栧彿
+ */
+ @ApiModelProperty("鏍囧噯缂栧彿")
+ private String code;
+
+ /**
+ * 鏍囧噯鍚嶇О
+ */
+ @ApiModelProperty("鏍囧噯绉板彿")
+ private String name;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ private String remark;
+
+ @ApiModelProperty("宸ュ巶")
+ private String factory;
+
+ @ApiModelProperty("瀹為獙瀹�")
+ private String laboratory;
+
+ @ApiModelProperty("鏍峰搧鍒嗙被")
+ private String sampleType;
+
+ @ApiModelProperty("鏍峰搧")
+ private String sample;
+
+ @ApiModelProperty("鍨嬪彿")
+ private String model;
+
+ @ApiModelProperty("")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @TableField(exist = false)
+ private String createUserName;
+ /**
+ *
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+ /**
+ *
+ */
+ @ApiModelProperty("")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+ /**
+ *
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductList.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductList.java
new file mode 100644
index 0000000..1c1b79f
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductList.java
@@ -0,0 +1,221 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鏍囧噯鏍戜笅鐨勬楠岄」鐩�
+ * @TableName standard_product_list
+ */
+@TableName(value ="standard_product_list")
+@Data
+public class StandardProductList implements Serializable {
+ /**
+ * 涓婚敭id
+ */
+ @TableId(value = "id",type = IdType.ASSIGN_ID)
+ @JsonSerialize(using = ToStringSerializer.class)
+ private Long id;
+
+ /**
+ * 妫�楠岄」
+ */
+ @ApiModelProperty("妫�楠岄」")
+ private String inspectionItem;
+
+ @ApiModelProperty("妫�楠岄」EN")
+ private String inspectionItemEn;
+
+ /**
+ * 妫�楠岄」灏忕被
+ */
+ @ApiModelProperty("妫�楠岄」灏忕被")
+ private String inspectionItemSubclass;
+
+ @ApiModelProperty("妫�楠岄」灏忕被EN")
+ private String inspectionItemSubclassEn;
+
+ /**
+ * 瀹為獙瀹�
+ */
+ @ApiModelProperty("瀹為獙瀹�")
+ private String laboratory;
+
+ @ApiModelProperty("瀛愬疄楠屽")
+ private String sonLaboratory;
+
+ /**
+ * 璁¢噺鍗曚綅
+ */
+ @ApiModelProperty("璁¢噺鍗曚綅")
+ private String unit;
+
+ /**
+ * 鍗曚环(鍏�)
+ */
+ @ApiModelProperty("鍗曚环")
+ private String price;
+
+ /**
+ * 宸ユ椂(H)
+ */
+ @ApiModelProperty("宸ユ椂")
+ private String manHour;
+
+ /**
+ * 宸ユ椂鍒嗙粍
+ */
+ @ApiModelProperty("宸ユ椂鍒嗙粍")
+ private String manHourGroup;
+
+ /**
+ * 妫�楠岄」绫诲瀷
+ */
+ @ApiModelProperty("妫�楠岄」绫诲瀷")
+ private String inspectionItemType;
+
+ /**
+ * 妫�楠屽�肩被鍨�
+ */
+ @ApiModelProperty("妫�楠屽�肩被鍨�")
+ private String inspectionValueType;
+
+ /**
+ * 妫�楠屾鏁�
+ */
+ @ApiModelProperty("妫�楠屾鏁�")
+ private Integer checkoutNumber;
+
+ /**
+ * 鍖洪棿
+ */
+ @ApiModelProperty("鍖洪棿")
+ private String section;
+
+ /**
+ * 鍖洪棿
+ */
+ @ApiModelProperty("鑺暟鍖洪棿")
+ private String cores;
+
+ /**
+ * 鏂规硶
+ */
+ @ApiModelProperty("鏂规硶鍒楄〃")
+ private String method;
+
+ @ApiModelProperty("鏂规硶")
+ private String methodS;
+
+ /**
+ * 棰勮鏃堕棿(澶�)
+ */
+ @ApiModelProperty("棰勮鏃堕棿")
+ private Integer manDay;
+
+ /**
+ * 鐗规畩鏍囪瘑
+ */
+ @ApiModelProperty("鐗规畩鏍囪瘑")
+ private String bsm;
+
+ /**
+ * 瑕佹眰鍊�
+ */
+ @ApiModelProperty("瑕佹眰鍊�")
+ private String ask;
+
+ @ApiModelProperty("瑕佹眰鎻忚堪")
+ private String tell;
+
+ /**
+ * 澶栭敭锛氭爣鍑嗘柟娉昳d
+ */
+ @ApiModelProperty("鏍囧噯鏂规硶id")
+ private Integer standardMethodListId;
+
+ @ApiModelProperty("宸ュ巶")
+ private String factory;
+
+ @ApiModelProperty("鏍峰搧鍒嗙被")
+ private String sampleType;
+
+ @ApiModelProperty("鏍峰搧")
+ private String sample;
+
+ @ApiModelProperty("鍨嬪彿")
+ private String model;
+
+ @ApiModelProperty("鍨嬪彿")
+ private Integer templateId;
+
+ @ApiModelProperty("")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+ /**
+ *
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+ /**
+ *
+ */
+ @ApiModelProperty("")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+ /**
+ *
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty("1锛氭湁鏁� 0锛氭棤鏁�")
+ private Integer state;
+
+ private String dic;
+
+ private String tree;
+
+ private Integer structureItemParameterId;
+
+ @ApiModelProperty(value = "妫�楠岄」鍒嗙被")
+ private String inspectionItemClass;
+
+ @ApiModelProperty(value = "妫�楠岄」鍒嗙被EN")
+ private String inspectionItemClassEn;
+
+ @ApiModelProperty(value = "鏉′欢")
+ private String radius;
+
+ @ApiModelProperty(value = "鏉′欢鍒楄〃")
+ private String radiusList;
+
+ @ApiModelProperty(value = "鏀惰垂鏍囧噯(鍏�/娆�)")
+ private String rates;
+
+ @ApiModelProperty(value = "绱㈠紩椤哄簭")
+ private Integer sort;
+
+ /**
+ * 瀵间綋鏉愯川
+ */
+ @ApiModelProperty("瀵间綋鏉愯川")
+ private String conductorMaterial;
+
+ /**
+ * 瀵间綋绫诲瀷
+ */
+ @ApiModelProperty("瀵间綋绫诲瀷")
+ private String conductorType;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductListSupplierAsk.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductListSupplierAsk.java
new file mode 100644
index 0000000..c857a6c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardProductListSupplierAsk.java
@@ -0,0 +1,58 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+/**
+ * 妫�楠岄」鐩巶瀹跺瘑搴︾粦瀹氳〃
+ *
+ * @author zhuo
+ * @since 2024-09-23
+ */
+@TableName(value ="standard_product_list_supplier_ask")
+@Data
+public class StandardProductListSupplierAsk {
+
+ @TableId(type = IdType.AUTO)
+ private Integer supplierAskId;
+
+ @JsonSerialize(using = ToStringSerializer.class)
+ @ApiModelProperty("妫�楠岄」鐩甶d")
+ private Long productListId;
+
+ @ApiModelProperty("鍘傚鍚嶇О")
+ private String supplierName;
+
+ @ApiModelProperty("瑕佹眰鍊�")
+ private String ask;
+
+ @ApiModelProperty("瑕佹眰鎻忚堪")
+ private String tell;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java
new file mode 100644
index 0000000..e26971f
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTemplate.java
@@ -0,0 +1,76 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 鏍囧噯妯℃澘
+ * @TableName standard_template
+ */
+@TableName(value ="standard_template")
+@Data
+public class StandardTemplate implements Serializable {
+ /**
+ *
+ */
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 妯℃澘鍚嶇О
+ */
+ @ApiModelProperty("妯℃澘鍚嶇О")
+ private String name;
+
+ /**
+ * 澶囨敞
+ */
+ @ApiModelProperty("澶囨敞")
+ private String remark;
+
+ /**
+ * 妯℃澘缁撴瀯
+ */
+ private String thing;
+
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+ /**
+ *
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+ /**
+ *
+ */
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+ /**
+ *
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty("鍒涘缓鐢ㄦ埛")
+ @TableField(exist = false)
+ private String createUserName;
+
+ @ApiModelProperty("鏇存柊鐢ㄦ埛")
+ @TableField(exist = false)
+ private String updateUserName;
+
+ /**
+ * 妯℃澘缂栧彿
+ */
+ @ApiModelProperty("妯℃澘缂栧彿")
+ private String number;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTree.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTree.java
new file mode 100644
index 0000000..8c2b6cf
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StandardTree.java
@@ -0,0 +1,96 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+* 鏍囧噯鏍�
+* @TableName standard_tree
+*/
+@TableName(value ="standard_tree")
+@Data
+public class StandardTree implements Serializable {
+
+ /**
+ *
+ */
+ @NotNull(message="[]涓嶈兘涓虹┖")
+ @ApiModelProperty("")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+ /**
+ * 宸ュ巶
+ */
+ @Size(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ @ApiModelProperty("宸ュ巶")
+ @Length(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ private String factory;
+ /**
+ * 瀹為獙瀹�
+ */
+ @Size(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ @ApiModelProperty("瀹為獙瀹�")
+ @Length(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ private String laboratory;
+ /**
+ * 鏍峰搧澶х被
+ */
+ @Size(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ @ApiModelProperty("鏍峰搧澶х被")
+ @Length(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ private String sampleType;
+ /**
+ * 鏍峰搧
+ */
+ @Size(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ @ApiModelProperty("鏍峰搧")
+ @Length(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ private String sample;
+ /**
+ * 鍨嬪彿
+ */
+ @Size(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ @ApiModelProperty("鍨嬪彿")
+ @Length(max= 255,message="缂栫爜闀垮害涓嶈兘瓒呰繃255")
+ private String model;
+ /**
+ *
+ */
+ @ApiModelProperty("")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+ /**
+ *
+ */
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+ /**
+ *
+ */
+ @ApiModelProperty("")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+ /**
+ *
+ */
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ /**
+ * 淇敼鍓嶅悕绉�
+ */
+ @TableField(exist = false,select = false)
+ private String oldModel;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java
new file mode 100644
index 0000000..7faa8be
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureItemParameter.java
@@ -0,0 +1,121 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 妫�楠岄」鐩弬鏁�(StructureItemParameter)琛ㄥ璞�
+ *
+ * @author makejava
+ * @since 2024-02-26 16:21:17
+ */
+@TableName(value ="structure_item_parameter")
+@Data
+public class StructureItemParameter implements Serializable {
+ @ApiModelProperty(value = "涓婚敭")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty(value = "妫�楠岄」")
+ private String inspectionItem;
+
+ @ApiModelProperty(value = "妫�楠岄」EN")
+ private String inspectionItemEn;
+
+ @ApiModelProperty(value = "妫�楠屽瓙椤�")
+ private String inspectionItemSubclass;
+
+ @ApiModelProperty(value = "妫�楠屽瓙椤笶N")
+ private String inspectionItemSubclassEn;
+
+ @ApiModelProperty(value = "妫�楠屽璞�")
+ private String sample;
+
+ @ApiModelProperty(value = "鍗曚环(鍏�)")
+ private String price;
+
+ @ApiModelProperty(value = "鍦烘墍")
+ private String laboratory;
+
+ @ApiModelProperty(value = "璇曢獙瀹�")
+ private String sonLaboratory;
+
+ @ApiModelProperty(value = "瑕佹眰鎻忚堪")
+ private String askTell;
+
+ @ApiModelProperty(value = "瑕佹眰鍊�")
+ private String ask;
+
+ @ApiModelProperty(value = "璁¢噺鍗曚綅")
+ private String unit;
+
+ @ApiModelProperty(value = "璇曢獙鏂规硶")
+ private String method;
+
+ @ApiModelProperty(value = "宸ユ椂(H)")
+ private Double manHour;
+
+ @ApiModelProperty(value = "棰勮鏃堕棿(H)")
+ private Integer manDay;
+
+ @ApiModelProperty(value = "宸ユ椂鍒嗙粍")
+ private String manHourGroup;
+
+ @ApiModelProperty(value = "妫�楠岄」绫诲瀷")
+ private String inspectionItemType;
+
+ @ApiModelProperty(value = "妫�楠屽�肩被鍨�")
+ private String inspectionValueType;
+
+ @ApiModelProperty(value = "妫�楠屾鏁�")
+ private Integer checkoutNumber;
+
+ @ApiModelProperty(value = "鍖洪棿")
+ private String section;
+
+ @ApiModelProperty(value = "鐗规畩鏍囪瘑")
+ private String bsm;
+
+ @ApiModelProperty(value = "鍘熷璁板綍妯℃澘")
+ private Integer templateId;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty(value = "瀛楀吀绫诲瀷")
+ private String dic;
+
+ @ApiModelProperty(value = "妫�楠岄」鍒嗙被")
+ private String inspectionItemClass;
+
+ @ApiModelProperty(value = "妫�楠岄」鍒嗙被EN")
+ private String inspectionItemClassEn;
+
+ @ApiModelProperty(value = "鏉′欢")
+ private String radiusList;
+
+ @ApiModelProperty(value = "鏀惰垂鏍囧噯(鍏�/娆�)")
+ private String rates;
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObject.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObject.java
new file mode 100644
index 0000000..d5af3f2
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObject.java
@@ -0,0 +1,63 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 妫�娴嬪璞�(StructureTestObject)琛ㄥ璞�
+ *
+ * @author makejava
+ * @since 2024-02-26 17:36:41
+ */
+@TableName(value ="structure_test_object")
+@Data
+public class StructureTestObject implements Serializable {
+ @ApiModelProperty(value = "涓婚敭")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty(value = "鍦烘墍")
+ private Integer laboratoryId;
+
+ @ApiModelProperty(value = "妫�楠屽璞�")
+ private String specimenName;
+
+ @ApiModelProperty(value = "妫�楠屽璞N")
+ private String specimenNameEn;
+
+ @ApiModelProperty(value = "瀵硅薄浠e彿")
+ private String code;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty(value = "鎺掑簭")
+ private Integer sort;
+
+ //"瀵硅薄绫诲瀷, 1:鍘熸潗鏂�, 2:鎴愬搧, 3:杈呮潗"
+ @ApiModelProperty(value = "瀵硅薄绫诲瀷")
+ private String objectType;
+
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObjectPart.java b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObjectPart.java
new file mode 100644
index 0000000..a1e500c
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/pojo/StructureTestObjectPart.java
@@ -0,0 +1,56 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 妫�楠屽璞¢浂浠惰〃(StructureTestObjectPart)$desc
+ *
+ * @author makejava
+ * @since 2024-08-07 10:10:30
+ */
+@TableName(value ="structure_test_object_part")
+@Data
+public class StructureTestObjectPart implements Serializable {
+
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("妫�楠屽璞d")
+ private Integer testObjectId;
+
+ @ApiModelProperty("闆朵欢鍙�")
+ private String partNo;
+
+ @ApiModelProperty("棰滆壊")
+ private String color;
+
+ @ApiModelProperty("鑹叉爣")
+ private String colorCode;
+
+ @ApiModelProperty(value = "鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+
+ @ApiModelProperty(value = "淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/CapacityScopeService.java b/basic-server/src/main/java/com/ruoyi/basic/service/CapacityScopeService.java
new file mode 100644
index 0000000..6139cd1
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/CapacityScopeService.java
@@ -0,0 +1,46 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.dto.PageTestObjectDto;
+import com.ruoyi.basic.dto.TestItemDto;
+
+import com.ruoyi.basic.pojo.StructureItemParameter;
+import com.ruoyi.basic.pojo.StructureTestObject;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 妫�楠岄」鐩弬鏁�(StructureItemParameter)琛ㄦ湇鍔℃帴鍙�
+ *
+ * @author makejava
+ * @since 2024-02-26 16:21:17
+ */
+public interface CapacityScopeService extends IService<StructureItemParameter> {
+
+ IPage<StructureItemParameter> selectItemParameterList(Page page, StructureItemParameter itemParameter);
+
+ int addItemParameter(StructureItemParameter itemParameter);
+
+ int delItemParameter(Integer id);
+
+ int upItemParameter(StructureItemParameter itemParameter);
+
+ IPage<PageTestObjectDto> selectTestObjectList(Page page, PageTestObjectDto pageTestObjectDto);
+
+ int addTestObject(StructureTestObject testObject);
+
+ int delTestObject(Integer id);
+
+ int upTestObject(StructureTestObject testObject);
+
+ List<StructureTestObject> selectTestObjectByName();
+
+ //璁惧閲岄潰閫夋嫨妫�楠岄」鐩�(鏍戝舰缁撴瀯)
+ List<Map<String, Object>> getInsProduction();
+
+ List<TestItemDto> getItemTree();
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/CertificationService.java b/basic-server/src/main/java/com/ruoyi/basic/service/CertificationService.java
new file mode 100644
index 0000000..7ecac80
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/CertificationService.java
@@ -0,0 +1,17 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.Certification;
+
+public interface CertificationService extends IService<Certification> {
+ //鏌ヨ璧勮川鏄庣粏鍒楄〃
+ IPage<Certification> getCertificationDetail(Page page, Certification certification);
+
+ //娣诲姞璧勮川鏄庣粏鍒楄〃
+ int addCertificationDetail(Certification certification);
+
+ //鍒犻櫎璧勮川鏄庣粏鍒楄〃
+ int delCertificationDetail(String ids);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/LaboratoryService.java b/basic-server/src/main/java/com/ruoyi/basic/service/LaboratoryService.java
new file mode 100644
index 0000000..4dc05a5
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/LaboratoryService.java
@@ -0,0 +1,27 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.Laboratory;
+
+import java.util.List;
+
+/**
+ * 瀹為獙瀹ょ鐞�(Laboratory)琛ㄦ湇鍔℃帴鍙�
+ */
+public interface LaboratoryService extends IService<Laboratory> {
+
+ IPage<Laboratory> selectItemParameter(Page page, Laboratory itemParameter);
+
+ int addParameter(Laboratory itemParameter);
+
+ int delParameter(Integer id);
+
+ int upParameter(Laboratory itemParameter);
+
+ List<Laboratory> obtainItemParameterList();
+
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/ProductPartService.java b/basic-server/src/main/java/com/ruoyi/basic/service/ProductPartService.java
new file mode 100644
index 0000000..3525752
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/ProductPartService.java
@@ -0,0 +1,14 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.ProductPart;
+
+public interface ProductPartService extends IService<ProductPart> {
+
+ IPage<ProductPart> selectByProductId(IPage<ProductPart> page,ProductPart productPart);
+
+ void addProductPart(ProductPart productPart);
+
+ void updateProductPartById(ProductPart productPart);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/ProductService.java b/basic-server/src/main/java/com/ruoyi/basic/service/ProductService.java
new file mode 100644
index 0000000..6fdc7c2
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/ProductService.java
@@ -0,0 +1,28 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.dto.ProductDTO1;
+import com.ruoyi.basic.excel.StructureTestObjectData;
+import com.ruoyi.basic.pojo.Product;
+
+import java.util.List;
+
+/**
+* @author z1292
+* @description 閽堝琛ㄣ�恜roduct(浜у搧琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice
+* @createDate 2024-04-26 01:11:02
+*/
+public interface ProductService extends IService<Product> {
+
+ IPage<Product> selectProductListByObjectId(Page page, ProductDTO1 productDto);
+
+ int addProduct(Product product);
+
+ int upProduct(Product product);
+
+ int delProduct(Integer id);
+
+ void importPartExcel(List<StructureTestObjectData> list);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/ProductSupplierDensityService.java b/basic-server/src/main/java/com/ruoyi/basic/service/ProductSupplierDensityService.java
new file mode 100644
index 0000000..13be167
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/ProductSupplierDensityService.java
@@ -0,0 +1,22 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.ProductSupplierDensity;
+
+/**
+ * 浜у搧鍘傚瀵嗗害缁戝畾琛�
+ *
+ * @author zhuo
+ * @since 2024-09-19
+ */
+public interface ProductSupplierDensityService extends IService<ProductSupplierDensity> {
+
+ IPage<ProductSupplierDensity> selectByProductId(Page page, ProductSupplierDensity supplierDensity);
+
+ void addProductSupplierDensity(ProductSupplierDensity supplierDensity);
+
+ void updateProductSupplierDensity(ProductSupplierDensity supplierDensity);
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/SealService.java b/basic-server/src/main/java/com/ruoyi/basic/service/SealService.java
new file mode 100644
index 0000000..a31c595
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/SealService.java
@@ -0,0 +1,24 @@
+package com.ruoyi.basic.service;
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.Laboratory;
+import com.ruoyi.basic.pojo.Seal;
+
+import java.util.List;
+import java.util.Map;
+
+public interface SealService extends IService<Seal> {
+
+ //鏂板
+ int addSeal(Seal seal);
+
+ //鏌ヨ
+ IPage<Seal> selectSeal(Page page, Seal seal);
+
+ List<Laboratory> Laboratory(Integer id);
+
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodListService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodListService.java
new file mode 100644
index 0000000..14ee117
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodListService.java
@@ -0,0 +1,28 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StandardMethodList;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_method_list(鏍囧噯鏍戜笅鐨勬爣鍑嗗垪琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice
+* @createDate 2024-03-04 13:44:04
+*/
+public interface StandardMethodListService extends IService<StandardMethodList> {
+
+ int addStandardMethodList(Integer standardId, String tree);
+
+ Map<String, List<?>> selectsStandardMethodByFLSSM(String tree);
+
+ Map<String, List<?>> selectsStandardMethodByFLSSM2(String tree);
+
+ int delStandardMethodByFLSSM(Integer id);
+
+ List<StandardMethodList> selectStandardMethodEnum();
+
+ Integer getStandardMethodId(String code);
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodService.java
new file mode 100644
index 0000000..d9b3432
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardMethodService.java
@@ -0,0 +1,30 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StandardMethod;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_method(鏍囧噯鏂规硶)銆戠殑鏁版嵁搴撴搷浣淪ervice
+* @createDate 2024-03-03 19:21:41
+*/
+public interface StandardMethodService extends IService<StandardMethod> {
+
+ IPage<StandardMethod> selectStandardMethodList(Page page, StandardMethod standardMethod);
+
+ List<StandardMethod> selectStandardMethods();
+
+ int addStandardMethod(StandardMethod standardMethod);
+
+ int delStandardMethod(Integer id);
+
+ int upStandardMethod(StandardMethod standardMethod);
+
+ void inputExcel(MultipartFile file) throws IOException;
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService.java
new file mode 100644
index 0000000..39e0754
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService.java
@@ -0,0 +1,67 @@
+package com.ruoyi.basic.service;
+
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.dto.CopyStandardProductListDto;
+import com.ruoyi.basic.dto.InsSampleReceiveDto;
+import com.ruoyi.basic.dto.ResetTreeDragDTO;
+import com.ruoyi.basic.pojo.StandardProductList;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author Administrator
+ * @description 閽堝琛ㄣ�恠tandard_product_list(鏍囧噯鏍戜笅鐨勬楠岄」鐩�)銆戠殑鏁版嵁搴撴搷浣淪ervice
+ * @createDate 2024-03-05 10:33:29
+ */
+public interface StandardProductListService extends IService<StandardProductList> {
+
+ int upStandardProductList(StandardProductList list);
+
+ int delStandardProduct(JSONArray list);
+
+ List<StandardProductList> selectStandardProductList(InsSampleReceiveDto insSample);
+
+ Map<String, Object> selectStandardProductListByMethodId(Integer id, String tree, Integer page);
+
+ IPage<StandardProductList> selectStandardProductByMethodId(Integer id, String tree, Integer page, String laboratory, String item, String items);
+
+ Map<String, List<?>> selectStandardProductEnumByMethodId(Integer id, String tree, String item);
+
+ boolean updateSection(StandardProductList list);
+
+ /**
+ * 鏍囧噯搴撴嫋鎷�
+ * @param resetTreeDragDTO
+ */
+ void resetTreeDrag(ResetTreeDragDTO resetTreeDragDTO);
+
+ /**
+ * 鏍囧噯搴撴嫋鎷�
+ * @param standardProductLists
+ */
+ void resetTreeDragBatch(List<StandardProductList> standardProductLists);
+
+ /**
+ * 妫�楠岄」瑕佹眰鍊煎姣�
+ * @param copyStandardProductListDto
+ * @return
+ */
+ List<StandardProductList> copyStandardProductList(CopyStandardProductListDto copyStandardProductListDto);
+
+ /**
+ * 妫�楠岄」瑕佹眰鍊煎姣斾竴涓�
+ * @param copyStandardProductListDto
+ * @return
+ */
+ List<StandardProductList> copyStandardProductOne(CopyStandardProductListDto copyStandardProductListDto);
+
+ /**
+ * 妫�楠岄」澶嶅埗鎺掑簭
+ * @param copyStandardProductListDto
+ * @return
+ */
+ boolean copyStandardProductSort(CopyStandardProductListDto copyStandardProductListDto);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService2.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService2.java
new file mode 100644
index 0000000..4f54fe6
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListService2.java
@@ -0,0 +1,13 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StandardProductList;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_product_list(鏍囧噯鏍戜笅鐨勬楠岄」鐩�)銆戠殑鏁版嵁搴撴搷浣淪ervice
+* @createDate 2024-03-05 10:33:29
+*/
+public interface StandardProductListService2 extends IService<StandardProductList> {
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListSupplierAskService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListSupplierAskService.java
new file mode 100644
index 0000000..c32d0e4
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardProductListSupplierAskService.java
@@ -0,0 +1,23 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StandardProductListSupplierAsk;
+
+import java.util.List;
+
+/**
+ * 妫�楠岄」鐩巶瀹跺瘑搴︾粦瀹氳〃
+ *
+ * @author makejava
+ * @since 2024-09-23
+ */
+public interface StandardProductListSupplierAskService extends IService<StandardProductListSupplierAsk> {
+
+ List<StandardProductListSupplierAsk> selectByProductId(StandardProductListSupplierAsk supplierAsk);
+
+ Integer addProductSupplierAsk(StandardProductListSupplierAsk supplierAsk);
+
+ Integer updateProductSupplierAsk(StandardProductListSupplierAsk supplierAsk);
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardTemplateService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardTemplateService.java
new file mode 100644
index 0000000..050cce8
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardTemplateService.java
@@ -0,0 +1,34 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StandardTemplate;
+
+import java.util.List;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_template(鏍囧噯妯℃澘)銆戠殑鏁版嵁搴撴搷浣淪ervice
+* @createDate 2024-03-11 13:47:52
+*/
+public interface StandardTemplateService extends IService<StandardTemplate> {
+
+ IPage<StandardTemplate> selectStandardTemplatePageList(Page page, StandardTemplate standardTemplate);
+
+ int addStandardTemplate(StandardTemplate standardTemplate);
+
+ int upStandardTemplate(StandardTemplate standardTemplate);
+
+ int delStandardTemplate(Integer id);
+
+ List<StandardTemplate> getStandardTemplate();
+
+ String getStandTempThingById(Integer templateId);
+
+ String getStandTempNameById(Integer templateId);
+
+ StandardTemplate getStandTempIdByName(String name);
+
+ int copyStandardTemplate(StandardTemplate newTemplate);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java
new file mode 100644
index 0000000..39d08e7
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StandardTreeService.java
@@ -0,0 +1,52 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.dto.FactoryDto;
+import com.ruoyi.basic.dto.SampleTypeDto;
+import com.ruoyi.basic.pojo.StandardTree;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_tree(鏍囧噯鏍�)銆戠殑鏁版嵁搴撴搷浣淪ervice
+* @createDate 2024-03-01 15:06:44
+*/
+public interface StandardTreeService extends IService<StandardTree> {
+
+ List<FactoryDto> selectStandardTreeList();
+
+
+ int addStandardTree(StandardTree standardTree);
+
+ int delStandardTree(String tree);
+
+ int addStandardProduct(String ids, String tree);
+
+ List<SampleTypeDto> getStandardTree2();
+
+ int upStandardProducts(Map<String, Object> product);
+
+ List<StandardTree> getStandTreeBySampleType(String laboratory, String sampleType);
+
+ void inExcelOfTree(MultipartFile file);
+
+ void resetTreeOfPrice(String tree, Integer standardId);
+
+ void resetTreeOfHour(String tree, Integer standardId);
+
+ void resetTreeOfAsk(String tree, Integer standardId);
+
+ void importWorkstationExcel(MultipartFile file);
+
+ /**
+ * 鏍囧噯鏁版帓搴�
+ * @param list
+ * @return
+ */
+ boolean updateTreeSort(List<FactoryDto> list);
+
+ int updateStandardTree(StandardTree standardTree);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StructureItemParameterService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StructureItemParameterService.java
new file mode 100644
index 0000000..a697619
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StructureItemParameterService.java
@@ -0,0 +1,8 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StructureItemParameter;
+
+public interface StructureItemParameterService extends IService<StructureItemParameter> {
+ void removeNoSample(String sample);
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectPartService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectPartService.java
new file mode 100644
index 0000000..de84817
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectPartService.java
@@ -0,0 +1,22 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StructureTestObjectPart;
+
+/**
+ * 妫�楠屽璞¢浂浠惰〃
+ *
+ * @author zhuo
+ * @since 2024-08-07
+ */
+public interface StructureTestObjectPartService extends IService<StructureTestObjectPart> {
+
+ IPage<StructureTestObjectPart> selectByTestObjectId(Page page, StructureTestObjectPart structureTestObjectPart);
+
+ void addTestObjectPart(StructureTestObjectPart structureTestObjectPart);
+
+ void updateTestObjectPart(StructureTestObjectPart structureTestObjectPart);
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectService.java b/basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectService.java
new file mode 100644
index 0000000..200a51a
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/StructureTestObjectService.java
@@ -0,0 +1,15 @@
+package com.ruoyi.basic.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.basic.pojo.StructureTestObject;
+
+/**
+ * 妫�娴嬪璞�(StructureTestObject)$desc
+ *
+ * @author makejava
+ * @since 2024-09-13 09:45:55
+ */
+public interface StructureTestObjectService extends IService<StructureTestObject> {
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java
new file mode 100644
index 0000000..f63a161
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/CapacityScopeServiceImpl.java
@@ -0,0 +1,185 @@
+package com.ruoyi.basic.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.dto.PageTestObjectDto;
+import com.ruoyi.basic.dto.TestItemDto;
+import com.ruoyi.basic.mapper.*;
+import com.ruoyi.basic.pojo.*;
+import com.ruoyi.basic.service.CapacityScopeService;
+import com.ruoyi.basic.service.StandardProductListService;
+import com.ruoyi.basic.service.StructureItemParameterService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * 妫�楠岄」鐩弬鏁�(StructureItemParameter)琛ㄦ湇鍔″疄鐜扮被
+ *
+ * @author makejava
+ * @since 2024-02-26 16:21:17
+ */
+@Service
+@AllArgsConstructor
+public class CapacityScopeServiceImpl extends ServiceImpl<StructureItemParameterMapper, StructureItemParameter> implements CapacityScopeService {
+
+ private LaboratoryMapper laboratoryMapper;
+
+ private StructureItemParameterMapper structureItemParameterMapper;
+
+ private StructureTestObjectMapper structureTestObjectMapper;
+
+ private ProductMapper productMapper;
+
+ private StructureTestObjectPartMapper structureTestObjectPartMapper;
+
+ private ProductPartMapper productPartMapper;
+
+ private StandardProductListService standardProductListService;
+
+ private StandardTreeMapper standardTreeMapper;
+
+ private StructureItemParameterService structureItemParameterService;
+
+ @Override
+ public IPage<StructureItemParameter> selectItemParameterList(Page page, StructureItemParameter itemParameter) {
+ return structureItemParameterMapper.selectItemParameterList(page, QueryWrappers.queryWrappers(itemParameter));
+ }
+
+ @Override
+ public int addItemParameter(StructureItemParameter itemParameter) {
+ if (itemParameter.getBsm().equals("")||itemParameter.getBsm()==null){
+ itemParameter.setBsm("0");
+ }
+ int insert = structureItemParameterMapper.insert(itemParameter);
+ return insert;
+ }
+
+ @Override
+ public int delItemParameter(Integer id) {
+ return structureItemParameterMapper.deleteById(id);
+ }
+
+ @Override
+ public int upItemParameter(StructureItemParameter itemParameter) {
+ return structureItemParameterMapper.updateById(itemParameter);
+ }
+
+ @Override
+ public IPage<PageTestObjectDto> selectTestObjectList(Page page, PageTestObjectDto pageTestObjectDto) {
+ String partNo = pageTestObjectDto.getPartNo();
+ pageTestObjectDto.setPartNo(null);
+ return structureTestObjectMapper.selectTestObjectList(page, QueryWrappers.queryWrappers(pageTestObjectDto),partNo);
+ }
+
+ @Override
+ public int addTestObject(StructureTestObject testObject) {
+ Long count = structureTestObjectMapper.selectCount(Wrappers.<StructureTestObject>lambdaQuery().eq(StructureTestObject::getSpecimenName, testObject.getSpecimenName()));
+ if(count.compareTo(0L) > 0){
+ throw new BaseException("妫�楠屽璞′笉鑳介噸澶�");
+ }
+
+ return structureTestObjectMapper.insert(testObject);
+ }
+
+ @Override
+ public int delTestObject(Integer id) {
+ // 浜у嚭妫�楠屽璞′骇鍝佺淮鎶�
+ structureTestObjectPartMapper.delete(Wrappers.<StructureTestObjectPart>lambdaQuery()
+ .eq(StructureTestObjectPart::getTestObjectId, id));
+
+ // 鍒犻櫎浜у搧缁存姢鐨勯浂浠剁粦瀹�
+ List<Product> products = productMapper.selectList(Wrappers.<Product>lambdaQuery()
+ .eq(Product::getObjectId, id));
+ List<Integer> productIds = products.stream().map(Product::getId).collect(Collectors.toList());
+ productPartMapper.delete(Wrappers.<ProductPart>lambdaQuery()
+ .in(ProductPart::getProductId, productIds));
+
+ // 鍒犻櫎浜у搧缁存姢
+ productMapper.delete(Wrappers.<Product>lambdaQuery()
+ .in(Product::getId, productIds));
+
+ return structureTestObjectMapper.deleteById(id);
+ }
+
+ @Override
+ public int upTestObject(StructureTestObject testObject) {
+ // 鏌ヨ鏃х殑妫�楠屽璞�
+ StructureTestObject oldTestObject = structureTestObjectMapper.selectById(testObject.getId());
+
+ if (!oldTestObject.getSpecimenName().equals(testObject.getSpecimenName())) {
+ // 鏌ヨ鎵�鏈夊璞′竴鏍风殑妫�楠岄」鐩�
+ List<StandardProductList> standardProductLists = standardProductListService.list(Wrappers.<StandardProductList>lambdaUpdate()
+ .eq(StandardProductList::getSampleType, oldTestObject.getSpecimenName()));
+ if (CollectionUtils.isNotEmpty(standardProductLists)){
+ for (StandardProductList standardProductList : standardProductLists) {
+ // 淇敼鎵�鏈夌殑瀵硅薄鍚嶇О鍜屾暟鍨嬬粨鏋�
+ standardProductList.setSampleType(testObject.getSpecimenName());
+ // 闇�瑕佹埅鍙栫涓夌骇, 閬垮厤涓夊洓绾у悕绉颁竴鏍蜂慨鏀归敊璇�
+ String[] trees = standardProductList.getTree().split(" - ");
+ trees[2] = testObject.getSpecimenName();
+ List<String> list = CollUtil.newArrayList(trees);
+ String newName = CollUtil.join(list, " - ");
+ standardProductList.setTree(newName);
+ }
+ standardProductListService.updateBatchById(standardProductLists);
+ }
+ // 淇敼妫�楠岄」鐩弬鏁扮殑妫�楠屽璞�
+ // 鎷兼帴 ["object", 鏌ヨ妫�楠岄」鐩弬鏁颁慨鏀圭粦瀹氱殑妫�楠屽璞�
+ String format = "[\"{}\",";
+ String sampleOld = StrUtil.format(format, oldTestObject.getSpecimenName());
+ List<StructureItemParameter> itemParameterList = structureItemParameterService.list(Wrappers.<StructureItemParameter>lambdaQuery()
+ .like(StructureItemParameter::getSample, sampleOld));
+ if (CollectionUtils.isNotEmpty(itemParameterList)) {
+ for (StructureItemParameter structureItemParameter : itemParameterList) {
+ // 淇敼缁戝畾鐨勬牱鍝佸悕绉�
+ String sampleNew = StrUtil.format(format, testObject.getSpecimenName());
+ String sampleUp = structureItemParameter.getSample().replace(sampleOld, sampleNew);
+ structureItemParameter.setSample(sampleUp);
+ }
+ structureItemParameterService.updateBatchById(itemParameterList);
+ }
+
+ // 淇敼鏍戠殑鍨嬪彿
+ standardTreeMapper.update(null, Wrappers.<StandardTree>lambdaUpdate()
+ .eq(StandardTree::getSampleType, oldTestObject.getSpecimenName())
+ .set(StandardTree::getSampleType, testObject.getSpecimenName()));
+ }
+
+ Long count = structureTestObjectMapper.selectCount(Wrappers.<StructureTestObject>lambdaQuery()
+ .eq(StructureTestObject::getSpecimenName, testObject.getSpecimenName())
+ .ne(StructureTestObject::getId, testObject.getId()));
+ if(count.compareTo(0L) > 0){
+ throw new BaseException("妫�楠屽璞′笉鑳介噸澶�");
+ }
+
+ return structureTestObjectMapper.updateById(testObject);
+ }
+
+ @Override
+ public List<StructureTestObject> selectTestObjectByName() {
+ return structureTestObjectMapper.selectList(Wrappers.<StructureTestObject>lambdaQuery().select(StructureTestObject::getSpecimenName,StructureTestObject::getId));
+ }
+
+ //璁惧閲岄潰閫夋嫨妫�楠岄」鐩�(鏍戝舰缁撴瀯)
+ @Override
+ public List<Map<String, Object>> getInsProduction() {
+ return structureItemParameterMapper.getInsProduction();
+ }
+
+ @Override
+ public List<TestItemDto> getItemTree() {
+ return structureItemParameterMapper.getItemTree();
+ }
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/CertificationServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/CertificationServiceImpl.java
new file mode 100644
index 0000000..11a6e61
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/CertificationServiceImpl.java
@@ -0,0 +1,45 @@
+package com.ruoyi.basic.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.mapper.CertificationMapper;
+import com.ruoyi.basic.pojo.Certification;
+import com.ruoyi.basic.service.CertificationService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+@Service
+@AllArgsConstructor
+@Transactional(rollbackFor = Exception.class)
+public class CertificationServiceImpl extends ServiceImpl<CertificationMapper, Certification> implements CertificationService {
+
+
+ private CertificationMapper certificationMapper;
+
+
+ //鏌ヨ璧勮川鏄庣粏鍒楄〃
+ @Override
+ public IPage<Certification> getCertificationDetail(Page page, Certification certification) {
+ return certificationMapper.getCertificationDetail(page, QueryWrappers.queryWrappers(certification));
+ }
+
+ //娣诲姞璧勮川鏄庣粏鍒楄〃
+ @Override
+ public int addCertificationDetail(Certification certification) {
+ return certificationMapper.insert(certification);
+ }
+
+ //鍒犻櫎璧勮川鏄庣粏鍒楄〃
+ @Override
+ public int delCertificationDetail(String ids) {
+ List<Integer> list = JSON.parseArray(ids,Integer.class);
+ return certificationMapper.deleteBatchIds(list);
+ }
+
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/LaboratoryServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/LaboratoryServiceImpl.java
new file mode 100644
index 0000000..a91a3c5
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/LaboratoryServiceImpl.java
@@ -0,0 +1,53 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.mapper.LaboratoryMapper;
+import com.ruoyi.basic.pojo.Laboratory;
+import com.ruoyi.basic.service.LaboratoryService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 瀹為獙瀹ょ鐞�(Laboratory)琛ㄦ湇鍔″疄鐜扮被
+ */
+@Service
+@AllArgsConstructor
+public class LaboratoryServiceImpl extends ServiceImpl<LaboratoryMapper, Laboratory> implements LaboratoryService {
+
+
+ private LaboratoryMapper laboratoryMapper;
+
+ @Override
+ public IPage<Laboratory> selectItemParameter(Page page, Laboratory itemParameter) {
+ return laboratoryMapper.selectItemParameter(page, QueryWrappers.queryWrappers(itemParameter));
+ }
+
+ @Override
+ public int addParameter(Laboratory itemParameter) {
+ return laboratoryMapper.insert(itemParameter);
+ }
+
+ @Override
+ public int delParameter(Integer id) {
+ return laboratoryMapper.deleteById(id);
+ }
+
+ @Override
+ public int upParameter(Laboratory itemParameter) {
+ return laboratoryMapper.updateById(itemParameter);
+ }
+
+ @Override
+ public List<Laboratory> obtainItemParameterList() {
+ return laboratoryMapper.selectList(Wrappers.<Laboratory>lambdaQuery().select(Laboratory::getLaboratoryName, Laboratory::getId));
+ }
+
+
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductPartServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductPartServiceImpl.java
new file mode 100644
index 0000000..5ecfb88
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductPartServiceImpl.java
@@ -0,0 +1,68 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.mapper.ProductPartMapper;
+import com.ruoyi.basic.mapper.StructureTestObjectPartMapper;
+import com.ruoyi.basic.pojo.ProductPart;
+import com.ruoyi.basic.pojo.StructureTestObjectPart;
+import com.ruoyi.basic.service.ProductPartService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+@Transactional
+@Service
+@AllArgsConstructor
+public class ProductPartServiceImpl extends ServiceImpl<ProductPartMapper, ProductPart> implements ProductPartService {
+
+ private ProductPartMapper productPartMapper;
+ private StructureTestObjectPartMapper structureTestObjectPartMapper;
+
+
+ @Override
+ public IPage<ProductPart> selectByProductId(IPage<ProductPart> page,ProductPart productPart) {
+ return productPartMapper.selectListByProductId(page, QueryWrappers.queryWrappers(productPart),productPart.getProductId());
+ }
+
+ @Override
+ public void addProductPart(ProductPart productPart) {
+ if (productPart.getProductId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ this.isPartNoExist(productPart.getPartNo(), productPart.getProductId(), null);
+ productPartMapper.insert(productPart);
+ }
+
+ @Override
+ public void updateProductPartById(ProductPart productPart) {
+ this.isPartNoExist(productPart.getPartNo(), productPart.getProductId(), productPart.getId());
+ if (productPart.getProductId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ productPartMapper.updateById(productPart);
+ }
+
+ // 鍒ゆ柇闆朵欢鍙锋槸鍚﹀瓨鍦�
+ public void isPartNoExist(String partNo,Integer productId, Integer id) {
+ // 闆朵欢鍙峰敮涓� 浣嗕笉蹇呭~
+ if (StringUtils.isNotBlank(partNo)) {
+ Long count = productPartMapper.selectCount(new LambdaQueryWrapper<ProductPart>()
+// .eq(ProductPart::getProductId, productId)
+ .eq(ProductPart::getPartNo, partNo)
+ .ne(id != null, ProductPart::getId, id));
+ Long selectCount = structureTestObjectPartMapper.selectCount(Wrappers.<StructureTestObjectPart>lambdaQuery()
+ .eq(StructureTestObjectPart::getPartNo, partNo));
+ if (count > 0 || selectCount > 0) {
+ throw new BaseException("璇ラ浂浠跺彿宸茬粦瀹氳繃妫�楠屽璞�");
+ }
+ } else {
+ throw new BaseException("璇疯緭鍏ラ浂浠跺彿");
+ }
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
new file mode 100644
index 0000000..d1786cb
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductServiceImpl.java
@@ -0,0 +1,188 @@
+package com.ruoyi.basic.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.dto.ProductDTO1;
+import com.ruoyi.basic.excel.StructureTestObjectData;
+import com.ruoyi.basic.mapper.ProductMapper;
+import com.ruoyi.basic.mapper.ProductPartMapper;
+import com.ruoyi.basic.mapper.StandardTreeMapper;
+import com.ruoyi.basic.mapper.StructureTestObjectMapper;
+import com.ruoyi.basic.pojo.*;
+import com.ruoyi.basic.service.LaboratoryService;
+import com.ruoyi.basic.service.ProductService;
+import com.ruoyi.basic.service.StandardProductListService;
+import com.ruoyi.basic.service.StructureItemParameterService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+* @author z1292
+* @description 閽堝琛ㄣ�恜roduct(浜у搧琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+* @createDate 2024-04-26 01:11:02
+*/
+@Service
+@AllArgsConstructor
+public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product>
+ implements ProductService{
+
+ private ProductMapper productMapper;
+
+ private LaboratoryService laboratoryService;
+
+ private StructureTestObjectMapper structureTestObjectMapper;
+
+ private ProductPartMapper productPartMapper;
+
+ private StandardProductListService standardProductListService;
+
+ private StandardTreeMapper standardTreeMapper;
+
+ private StructureItemParameterService structureItemParameterService;
+
+ @Override
+ public IPage<Product> selectProductListByObjectId(Page page, ProductDTO1 product) {
+ String partNo = product.getPartNo();
+ product.setPartNo(null);
+ return productMapper.selectProductListByObjectId(page, QueryWrappers.queryWrappers(product), partNo);
+ }
+
+ @Override
+ public int addProduct(Product product) {
+
+ return productMapper.insert(product);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int upProduct(Product product) {
+ // 鏌ヨ鍘熸湰鐨勫悕绉�
+ Product oldProduct = productMapper.selectById(product.getId());
+
+ if (!oldProduct.getName().equals(product.getName())) {
+ // 淇敼鍚嶇О鍖归厤鐨勬爣鍑嗘爲涓嬬殑妫�楠岄」鐩�
+ // 鏌ヨ鎵�鏈夊璞�+鍚嶇О鐨勬爲
+ StructureTestObject testObject = structureTestObjectMapper.selectById(oldProduct.getObjectId());
+
+ List<StandardProductList> standardProductLists = standardProductListService.list(Wrappers.<StandardProductList>lambdaUpdate()
+ .eq(StandardProductList::getSample, oldProduct.getName())
+ .eq(StandardProductList::getSampleType, testObject.getSpecimenName()));
+ if (CollectionUtils.isNotEmpty(standardProductLists)) {
+ for (StandardProductList standardProductList : standardProductLists) {
+ // 淇敼鏍峰搧鍚嶇О
+ standardProductList.setSample(product.getName());
+ // 淇敼鏍戝悕绉�
+ // 闇�瑕佹埅鍙栫鍥涚骇, 閬垮厤涓夊洓绾у悕绉颁竴鏍蜂慨鏀归敊璇�
+ String[] trees = standardProductList.getTree().split(" - ");
+ trees[3] = product.getName();
+ List<String> list = CollUtil.newArrayList(trees);
+ String newName = CollUtil.join(list, " - ");
+ standardProductList.setTree(newName);
+ }
+ standardProductListService.updateBatchById(standardProductLists);
+ }
+
+ // 淇敼妫�楠岄」鐩弬鏁扮殑妫�楠屽璞�
+ // 鎷兼帴["object","product"]鏌ヨ妫�楠岄」鐩弬鏁颁慨鏀圭粦瀹氱殑妫�楠屽璞�
+ String format = "[\"{}\",\"{}\"]";
+ String sampleOld = StrUtil.format(format, testObject.getSpecimenName(), oldProduct.getName());
+ List<StructureItemParameter> itemParameterList = structureItemParameterService.list(Wrappers.<StructureItemParameter>lambdaQuery()
+ .like(StructureItemParameter::getSample, sampleOld));
+ if (CollectionUtils.isNotEmpty(itemParameterList)) {
+ for (StructureItemParameter structureItemParameter : itemParameterList) {
+ // 淇敼缁戝畾鐨勬牱鍝佸悕绉�
+ String sampleNew = StrUtil.format(format, testObject.getSpecimenName(), product.getName());
+ String sampleUp = structureItemParameter.getSample().replace(sampleOld, sampleNew);
+ structureItemParameter.setSample(sampleUp);
+ }
+ structureItemParameterService.updateBatchById(itemParameterList);
+ }
+
+ // 淇敼鏍戠殑鍨嬪彿
+ standardTreeMapper.update(null, Wrappers.<StandardTree>lambdaUpdate()
+ .eq(StandardTree::getSampleType, testObject.getSpecimenName())
+ .eq(StandardTree::getSample, oldProduct.getName())
+ .set(StandardTree::getSample, product.getName()));
+ }
+
+ return productMapper.updateById(product);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int delProduct(Integer id) {
+ // 鍒犻櫎闆朵欢缁戝畾
+ productPartMapper.delete(Wrappers.<ProductPart>lambdaQuery()
+ .eq(ProductPart::getProductId, id));
+
+ return productMapper.deleteById(id);
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void importPartExcel(List<StructureTestObjectData> list) {
+ list.forEach(i -> {
+ // 妫�楠屽璞�
+ StructureTestObject structureTestObject1 = structureTestObjectMapper.selectOne(Wrappers.<StructureTestObject>lambdaQuery()
+ .eq(StructureTestObject::getSpecimenName, i.getSpecimenName())
+ .eq(StructureTestObject::getSpecimenNameEn, i.getSpecimenNameEn()));
+ Laboratory laboratory = laboratoryService.getOne(Wrappers.<Laboratory>lambdaQuery()
+ .eq(Laboratory::getLaboratoryName, i.getLaboratory()));
+ if (ObjectUtils.isEmpty(laboratory)) {
+ throw new BaseException("鏈壘鍒拌鍦烘墍锛�" + i.getLaboratory() + "锛岃妫�鏌ユ槸鍚﹀瓨鍦ㄨ鍦烘墍锛�");
+ }
+ // 濡傛灉涓虹┖杩涜鏂板
+ if(ObjectUtils.isEmpty(structureTestObject1)) {
+ StructureTestObject structureTestObject = new StructureTestObject();
+ structureTestObject.setLaboratoryId(laboratory.getId());
+ structureTestObject.setSpecimenName(i.getSpecimenName());
+ structureTestObject.setSpecimenNameEn(i.getSpecimenNameEn());
+ structureTestObject.setCode(i.getCode());
+ structureTestObjectMapper.insert(structureTestObject);
+
+ // 浜у搧
+ Product product = productMapper.selectOne(Wrappers.<Product>lambdaQuery()
+ .eq(Product::getName, i.getName())
+ .eq(Product::getNameEn, i.getNameEn()));
+ if (ObjectUtils.isEmpty(product)){
+ Product product1 = new Product();
+ product1.setName(i.getName());
+ product1.setNameEn(i.getNameEn());
+ product1.setObjectId(structureTestObject.getId());
+ baseMapper.insert(product1);
+ }
+ } else {
+ structureTestObject1.setCode(i.getCode());
+ structureTestObject1.setLaboratoryId(laboratory.getId());
+ structureTestObjectMapper.updateById(structureTestObject1);
+ // 浜у搧
+ Product product = productMapper.selectOne(Wrappers.<Product>lambdaQuery()
+ .eq(Product::getName, i.getName())
+ .eq(Product::getNameEn, i.getNameEn()));
+ if (ObjectUtils.isEmpty(product)){
+ Product product1 = new Product();
+ product1.setName(i.getName());
+ product1.setNameEn(i.getNameEn());
+ product1.setObjectId(structureTestObject1.getId());
+ baseMapper.insert(product1);
+ } else {
+ product.setName(i.getName());
+ product.setNameEn(i.getNameEn());
+ product.setObjectId(structureTestObject1.getId());
+ baseMapper.updateById(product);
+ }
+ }
+ });
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductSupplierDensityServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductSupplierDensityServiceImpl.java
new file mode 100644
index 0000000..54a92ab
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/ProductSupplierDensityServiceImpl.java
@@ -0,0 +1,64 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.mapper.ProductSupplierDensityMapper;
+import com.ruoyi.basic.pojo.ProductSupplierDensity;
+import com.ruoyi.basic.service.ProductSupplierDensityService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 浜у搧鍘傚瀵嗗害缁戝畾琛�
+ *
+ * @author zhuo
+ * @since 2024-09-19
+ */
+@Service
+public class ProductSupplierDensityServiceImpl extends ServiceImpl<ProductSupplierDensityMapper, ProductSupplierDensity> implements ProductSupplierDensityService {
+
+ @Override
+ public IPage<ProductSupplierDensity> selectByProductId(Page page, ProductSupplierDensity supplierDensity) {
+ if (supplierDensity.getProductId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ return baseMapper.selectListByProductId(page, QueryWrappers.queryWrappers(supplierDensity), supplierDensity.getProductId());
+ }
+
+ @Override
+ public void addProductSupplierDensity(ProductSupplierDensity supplierDensity) {
+ if (supplierDensity.getProductId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ // 鏌ヨ鏀瑰巶瀹舵槸鍚︾粦瀹氳繃
+// Long count = baseMapper.selectCount(Wrappers.<ProductSupplierDensity>lambdaQuery()
+// .eq(ProductSupplierDensity::getProductId, supplierDensity.getProductId())
+// .eq(ProductSupplierDensity::getModel, supplierDensity)
+// .eq(ProductSupplierDensity::getSupplierName, supplierDensity.getSupplierName()));
+// if (count > 0){
+// throw new BaseException("璇ヤ骇鍝佸凡缁戝畾杩囪鍘傚");
+// }
+
+ baseMapper.insert(supplierDensity);
+ }
+
+ @Override
+ public void updateProductSupplierDensity(ProductSupplierDensity supplierDensity) {
+ if (supplierDensity.getProductId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ // 鏌ヨ鏀瑰巶瀹舵槸鍚︾粦瀹氳繃
+// Long count = baseMapper.selectCount(Wrappers.<ProductSupplierDensity>lambdaQuery()
+// .ne(ProductSupplierDensity::getId, supplierDensity.getId())
+// .eq(ProductSupplierDensity::getProductId, supplierDensity.getProductId())
+// .eq(ProductSupplierDensity::getModel, supplierDensity)
+// .eq(ProductSupplierDensity::getSupplierName, supplierDensity.getSupplierName()));
+// if (count > 0){
+// throw new BaseException("璇ヤ骇鍝佸凡缁戝畾杩囪鍘傚");
+// }
+ baseMapper.updateById(supplierDensity);
+ }
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/SealServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/SealServiceImpl.java
new file mode 100644
index 0000000..8e86931
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/SealServiceImpl.java
@@ -0,0 +1,39 @@
+package com.ruoyi.basic.service.impl;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.mapper.SealMapper;
+import com.ruoyi.basic.pojo.Laboratory;
+import com.ruoyi.basic.pojo.Seal;
+import com.ruoyi.basic.service.SealService;
+import com.ruoyi.common.utils.QueryWrappers;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Service
+@AllArgsConstructor
+public class SealServiceImpl extends ServiceImpl<SealMapper, Seal> implements SealService {
+ private SealMapper sealMapper;
+
+
+ @Override
+ public int addSeal(Seal seal) {
+ return sealMapper.insert(seal);
+ }
+
+
+
+
+ @Override
+ public IPage<Seal> selectSeal(Page page, Seal seal) {
+ return sealMapper.selectSeal(page, QueryWrappers.queryWrappers(seal));
+ }
+ @Override
+ public List<Laboratory> Laboratory(Integer labId) {
+ return sealMapper.selectLaboratory(labId);
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodListServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodListServiceImpl.java
new file mode 100644
index 0000000..5ab1ed5
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodListServiceImpl.java
@@ -0,0 +1,150 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.mapper.StandardMethodListMapper;
+import com.ruoyi.basic.mapper.StandardProductListMapper;
+import com.ruoyi.basic.pojo.StandardMethodList;
+import com.ruoyi.basic.pojo.StandardProductList;
+import com.ruoyi.basic.service.StandardMethodListService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_method_list(鏍囧噯鏍戜笅鐨勬爣鍑嗗垪琛�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+* @createDate 2024-03-04 13:44:04
+*/
+@Service
+@AllArgsConstructor
+public class StandardMethodListServiceImpl extends ServiceImpl<StandardMethodListMapper, StandardMethodList>
+ implements StandardMethodListService{
+
+ private StandardMethodListMapper standardMethodListMapper;
+
+ private StandardProductListMapper standardProductListMapper;
+
+ @Override
+ public int addStandardMethodList(Integer standardId, String tree) {
+ String[] trees = tree.split(" - ");
+ Map<String, String> map = standardMethodListMapper.selectStandardMethodById(standardId);
+ StandardMethodList list = new StandardMethodList();
+ list.setCode(map.get("code"));
+ list.setName(map.get("name"));
+ list.setRemark(map.get("remark"));
+ list.setFactory(trees[0]);
+ try {
+ list.setLaboratory(trees[1]);
+ }catch (Exception e){}
+ try {
+ list.setSampleType(trees[2]);
+ }catch (Exception e){}
+ try {
+ list.setSample(trees[3]);
+ }catch (Exception e){}
+ try {
+ list.setModel(trees[4]);
+ }catch (Exception e){}
+ standardMethodListMapper.insert(list);
+ List<StandardProductList> standardProductLists = standardMethodListMapper.selectParameterList(list.getCode());
+ for (StandardProductList standardProductList : standardProductLists) {
+ standardProductList.setStandardMethodListId(list.getId());
+ standardProductList.setFactory(trees[0]);
+ try {
+ standardProductList.setLaboratory(trees[1]);
+ }catch (Exception e){}
+ try {
+ standardProductList.setSampleType(trees[2]);
+ }catch (Exception e){}
+ try {
+ standardProductList.setSample(trees[3]);
+ }catch (Exception e){}
+ try {
+ standardProductList.setModel(trees[4]);
+ }catch (Exception e){}
+ standardProductListMapper.insert(standardProductList);
+ }
+ return 1;
+ }
+
+ @Override
+ public Map<String, List<?>> selectsStandardMethodByFLSSM(String tree) {
+ String[] trees = tree.split(" - ");
+ Map<String, List<?>> map = new HashMap<>();
+ String str = "";
+ List<StandardMethodList> standardMethodLists = new ArrayList<>();
+ switch (trees.length){
+ case 5:
+ str += "\"" + trees[2] + "\",\"" + trees[3] + "\",\"" + trees[4] + "\"";
+ standardMethodLists.addAll(standardMethodListMapper.selectStandardMethodLists(str));
+ standardMethodLists.addAll(standardMethodListMapper.selectStandardMethodLists("\"" + trees[2] + "\",\"" + trees[3] + "\""));
+ standardMethodLists.addAll(standardMethodListMapper.selectStandardMethodLists("\"" + trees[2] + "\""));
+ break;
+ case 4:
+ str += "\"" + trees[2] + "\",\"" + trees[3] + "\"";
+ standardMethodLists.addAll(standardMethodListMapper.selectStandardMethodLists(str));
+ standardMethodLists.addAll(standardMethodListMapper.selectStandardMethodLists("\"" + trees[2] + "\""));
+ break;
+ case 3:
+ str += "\"" + trees[2] + "\"";
+ standardMethodLists.addAll(standardMethodListMapper.selectStandardMethodLists3(str));
+ break;
+ default:
+ map.put("standardMethodList", null);
+ return map;
+ }
+ standardMethodLists.addAll(standardMethodListMapper.selectStandardMethodListsByNull(str));
+ map.put("standardMethodList", standardMethodLists);
+ return map;
+ }
+
+ @Override
+ public Map<String, List<?>> selectsStandardMethodByFLSSM2(String tree) {
+ String[] trees = tree.split(" - ");
+ List<StandardMethodList> standardMethodLists = null;
+ switch (trees.length){
+ case 5:
+ standardMethodLists = standardMethodListMapper.selectStandardMethodLists2(trees[0],trees[1],trees[2],trees[3],trees[4]);
+ break;
+ case 4:
+ standardMethodLists = standardMethodListMapper.selectStandardMethodLists2(trees[0],trees[1],trees[2],trees[3],null);
+ break;
+ case 3:
+ standardMethodLists = standardMethodListMapper.selectStandardMethodLists2(trees[0],trees[1],trees[2],null,null);
+ break;
+ case 2:
+ standardMethodLists = standardMethodListMapper.selectStandardMethodLists2(trees[0],trees[1],null,null,null);
+ break;
+ case 1:
+ standardMethodLists = standardMethodListMapper.selectStandardMethodLists2(trees[0],null,null,null,null);
+ break;
+ }
+ Map<String, List<?>> map = new HashMap<>();
+ map.put("standardMethodList", standardMethodLists);
+ return map;
+ }
+
+ @Override
+ public int delStandardMethodByFLSSM(Integer id) {
+ standardProductListMapper.delete(Wrappers.<StandardProductList>lambdaUpdate().eq(StandardProductList::getStandardMethodListId, id));
+ return standardMethodListMapper.deleteById(id);
+ }
+ @Override
+ public List<StandardMethodList> selectStandardMethodEnum() {
+ return standardMethodListMapper.selectListEnum();
+ }
+
+ @Override
+ public Integer getStandardMethodId(String code) {
+ return baseMapper.getStandardMethodId(code);
+ }
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java
new file mode 100644
index 0000000..44566bd
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardMethodServiceImpl.java
@@ -0,0 +1,260 @@
+package com.ruoyi.basic.service.impl;
+
+import cn.hutool.json.JSONUtil;
+import cn.hutool.poi.excel.ExcelUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.mapper.StandardMethodMapper;
+import com.ruoyi.basic.mapper.StandardProductListMapper;
+import com.ruoyi.basic.mapper.StructureItemParameterMapper;
+import com.ruoyi.basic.pojo.StandardMethod;
+import com.ruoyi.basic.pojo.StandardProductList;
+import com.ruoyi.basic.pojo.StructureItemParameter;
+import com.ruoyi.basic.service.StandardMethodService;
+import com.ruoyi.basic.service.StandardProductListService;
+import com.ruoyi.basic.service.StructureItemParameterService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.CompletableFuture;
+
+/**
+ * @author Administrator
+ * @description 閽堝琛ㄣ�恠tandard_method(鏍囧噯鏂规硶)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+ * @createDate 2024-03-03 19:21:41
+ */
+@Service
+@AllArgsConstructor
+public class StandardMethodServiceImpl extends ServiceImpl<StandardMethodMapper, StandardMethod>
+ implements StandardMethodService {
+
+
+ private StandardMethodMapper standardMethodMapper;
+
+ StandardProductListMapper standardProductListMapper;
+ StandardProductListService standardProductListService;
+
+ StructureItemParameterMapper structureItemParameterMapper;
+ StructureItemParameterService structureItemParameterService;
+
+ @Override
+ public IPage<StandardMethod> selectStandardMethodList(Page page, StandardMethod standardMethod) {
+ return standardMethodMapper.selectStandardMethodList(page, QueryWrappers.queryWrappers(standardMethod));
+ }
+
+ @Override
+ public List<StandardMethod> selectStandardMethods() {
+ return standardMethodMapper.selectList(Wrappers.<StandardMethod>lambdaQuery().select(StandardMethod::getId, StandardMethod::getCode, StandardMethod::getName).ne(StandardMethod::getId, 0));
+ }
+
+ @Override
+ public int addStandardMethod(StandardMethod standardMethod) {
+ int insert = standardMethodMapper.insert(standardMethod);
+ return insert;
+ }
+
+ @Override
+ public int delStandardMethod(Integer id) {
+ int i = standardMethodMapper.deleteById(id);
+ return i;
+ }
+
+ @Override
+ public int upStandardMethod(StandardMethod standardMethod) {
+ StandardMethod oldStandardMethod = standardMethodMapper.selectById(standardMethod.getId());
+ if (!oldStandardMethod.getCode().equals(standardMethod.getCode())) {
+ CompletableFuture.supplyAsync(() -> replaceMethod(oldStandardMethod.getCode(), standardMethod.getCode()));
+ }
+ int i = standardMethodMapper.updateById(standardMethod);
+ return i;
+ }
+
+ //缂栬緫method鍚庡叏閮ㄦ浛鎹�
+ public String replaceMethod(String oldCode, String code) {
+ //鏌ヨStandardProductList涓墍鏈塎ethod濡傛灉鍖呭惈涔嬪墠鐨勫垯鏇挎崲
+ List<StandardProductList> standardProductLists = standardProductListMapper.selectList(null);
+ for (StandardProductList standardProductList : standardProductLists) {
+ if (standardProductList.getMethod().contains(oldCode)) {
+ String[] split = standardProductList.getMethod().split(",");
+ String a = null;
+ for (int i = 0; i < split.length; i++) {
+ String methodName = split[i].substring(1, split[i].length() - 1);
+ if (i == 0) {
+ methodName = split[i].substring(2, split[i].length() - 1);
+ } else if (i == split.length - 1) {
+ methodName = split[i].substring(1, split[i].length() - 2);
+ }
+ if (methodName.equals(oldCode)) {
+ methodName = code;
+ }
+ a += "\"" + methodName + "\",";
+ }
+ String method = "[\"" + a.substring(0, a.length() - 1) + "\"]";
+ standardProductList.setMethod(method);
+ }
+ }
+ standardProductListService.updateBatchById(standardProductLists);
+ //鏌ヨStructureItemParameter涓墍鏈塎ethod濡傛灉鍖呭惈涔嬪墠鐨勫垯鏇挎崲
+ List<StructureItemParameter> structureItemParameters = structureItemParameterMapper.selectList(null);
+ for (StructureItemParameter structureItemParameter : structureItemParameters) {
+ if (structureItemParameter.getMethod().contains(oldCode)) {
+ String[] split = structureItemParameter.getMethod().split(",");
+ String a = null;
+ for (int i = 0; i < split.length; i++) {
+ String methodName = split[i].substring(1, split[i].length() - 1);
+ if (i == 0) {
+ methodName = split[i].substring(2, split[i].length() - 1);
+ } else if (i == split.length - 1) {
+ methodName = split[i].substring(1, split[i].length() - 2);
+ }
+ if (methodName.equals(oldCode)) {
+ methodName = code;
+ }
+ a += "\"" + methodName + "\",";
+ }
+ String method = "[\"" + a.substring(0, a.length() - 1) + "\"]";
+ structureItemParameter.setMethod(method);
+ }
+ }
+ structureItemParameterService.updateBatchById(structureItemParameters);
+ return "鏇挎崲瀹屾瘯!";
+ }
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void inputExcel(MultipartFile file) throws IOException {
+ // 瀛樺偍妫�娴嬪璞ist
+ List<Object> structureTestObjectIdList = new ArrayList<>();
+ List<StandardMethod> result = new ArrayList<>();
+ ExcelUtil.readBySax(file.getInputStream(), 0, (i, l, list) -> {
+ // 鍘婚櫎绗竴琛岃〃澶�
+ if (l == 0) {
+ return;
+ }
+ // 瀛樺偍鍞竴妫�娴嬪璞�
+ if (!structureTestObjectIdList.contains(list.get(2))) {
+ structureTestObjectIdList.add(list.get(2));
+ }
+ StandardMethod standardMethod = formatData(list);
+ result.add(standardMethod);
+ });
+ addStructureTest(structureTestObjectIdList, result);
+ }
+
+ // 鏍煎紡鍖栨暟鎹�
+ public StandardMethod formatData(List<Object> list) {
+ StandardMethod standardMethod = new StandardMethod();
+ standardMethod.setField(list.get(1).toString());
+ // 閫犳牸寮�
+ List<List<Object>> structureTestObjectId = new ArrayList<>();
+ if (ObjectUtils.isEmpty(list.get(3))) {
+ structureTestObjectId.add(Arrays.asList(list.get(2)));
+ } else {
+ structureTestObjectId.add(Arrays.asList(list.get(2), list.get(3)));
+ }
+ standardMethod.setStructureTestObjectId(JSONUtil.toJsonStr(structureTestObjectId));
+ standardMethod.setCode(list.get(4).toString());
+ standardMethod.setName(list.get(5).toString());
+ standardMethod.setNameEn(list.get(6).toString());
+ if (!Objects.equals(list.get(7), null)) {
+ standardMethod.setRemark(list.get(7).toString());
+ }
+ standardMethod.setQualificationId(list.get(8).toString());
+ if (ObjectUtils.isNotEmpty(list.get(9))) {
+ if (list.get(9).equals("鏄�")) {
+ standardMethod.setIsProduct(1);
+ } else if (list.get(9).equals("鍚�")) {
+ standardMethod.setIsProduct(0);
+ }
+ }
+ if (ObjectUtils.isNotEmpty(list.get(10))) {
+ if (list.get(10).equals("鏄�")) {
+ standardMethod.setIsUse(1);
+ } else if (list.get(9).equals("鍚�")) {
+ standardMethod.setIsUse(0);
+ }
+ }
+ return standardMethod;
+ }
+
+ // 鏂板鏁版嵁
+ public void addStructureTest(List<Object> structureTestObjectIdList, List<StandardMethod> standardMethodList) {
+ List<StandardMethod> updateList = new ArrayList<>();
+ List<Integer> deleteListId = new ArrayList<>();
+ List<StandardMethod> addList = new ArrayList<>();
+ if (!structureTestObjectIdList.isEmpty()) {
+ // 寰幆excel閲岄潰鐨勫垎缁�
+ structureTestObjectIdList.forEach(j -> {
+ // 浠xcel涓殑缁勫悕鏌ヨ鏁版嵁搴撲腑鐨勫垎缁�
+ List<StandardMethod> standardMethods = baseMapper.selectList(Wrappers.<StandardMethod>lambdaQuery()
+ .like(StandardMethod::getStructureTestObjectId, "\"" + j + "\""));
+ // 灏嗙粨鏋滃惊鐜尮閰�
+ for (int i = 0; i < standardMethods.size(); i++) {
+ boolean isExistence = false;
+ for (int i1 = 0; i1 < standardMethodList.size(); i1++) {
+ // 鏇存柊
+ if (standardMethods.get(i).getStructureTestObjectId().equals(standardMethodList.get(i1).getStructureTestObjectId())
+ && standardMethods.get(i).getCode().equals(standardMethodList.get(i1).getCode())
+ && standardMethods.get(i).getField().equals(standardMethodList.get(i1).getField())) {
+ // 缁檈xcel鏁版嵁璧嬪�糹d鍋氭洿鏂�
+ standardMethodList.get(i1).setId(standardMethods.get(i).getId());
+ // 鏇存柊
+ updateList.add(standardMethodList.get(i1));
+ isExistence = true;
+ break;
+ }
+ }
+ // 鍒犻櫎
+ if (!isExistence) {
+ deleteListId.add(standardMethods.get(i).getId());
+ }
+ }
+ for (int i = 0; i < standardMethodList.size(); i++) {
+ if (standardMethodList.get(i).getStructureTestObjectId().contains("\"" + j + "\"")) {
+ boolean isExistence = false;
+ for (int i1 = 0; i1 < standardMethods.size(); i1++) {
+ if (standardMethods.get(i1).getStructureTestObjectId().equals(standardMethodList.get(i).getStructureTestObjectId())
+ && standardMethods.get(i1).getCode().equals(standardMethodList.get(i).getCode())
+ && standardMethods.get(i1).getField().equals(standardMethodList.get(i).getField())) {
+ isExistence = true;
+ break;
+ }
+ }
+ // 鏂板
+ if (!isExistence) {
+ addList.add(standardMethodList.get(i));
+ }
+ }
+ }
+ });
+ }
+ if (!addList.isEmpty()) {
+ // 鏂板
+ baseMapper.insertBatchSomeColumn(addList);
+ }
+
+ if (!deleteListId.isEmpty()) {
+ // 鍒犻櫎
+ baseMapper.deleteBatchIds(deleteListId);
+ }
+
+ if (!updateList.isEmpty()) {
+ // 鏇存柊
+ updateList.forEach(i -> {
+ baseMapper.updateById(i);
+ });
+ }
+ }
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListService2Impl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListService2Impl.java
new file mode 100644
index 0000000..eae1bc2
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListService2Impl.java
@@ -0,0 +1,12 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.mapper.StandardProductListMapper;
+import com.ruoyi.basic.pojo.StandardProductList;
+import com.ruoyi.basic.service.StandardProductListService2;
+import org.springframework.stereotype.Service;
+
+@Service
+public class StandardProductListService2Impl extends ServiceImpl<StandardProductListMapper, StandardProductList>
+ implements StandardProductListService2 {
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListServiceImpl.java
new file mode 100644
index 0000000..c5695ec
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListServiceImpl.java
@@ -0,0 +1,701 @@
+package com.ruoyi.basic.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.*;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.basic.dto.CopyStandardProductListDto;
+import com.ruoyi.basic.dto.InsSampleReceiveDto;
+import com.ruoyi.basic.dto.ProductDto;
+import com.ruoyi.basic.dto.ResetTreeDragDTO;
+import com.ruoyi.basic.mapper.IfsInventoryQuantityMapper;
+import com.ruoyi.basic.mapper.StandardProductListMapper;
+import com.ruoyi.basic.mapper.StandardProductListSupplierAskMapper;
+import com.ruoyi.basic.mapper.StandardTreeMapper;
+import com.ruoyi.basic.pojo.StandardProductList;
+import com.ruoyi.basic.pojo.StandardProductListSupplierAsk;
+import com.ruoyi.basic.pojo.StandardTree;
+import com.ruoyi.basic.service.StandardProductListService;
+import com.ruoyi.basic.service.StandardProductListService2;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * @author Administrator
+ * @description 閽堝琛ㄣ�恠tandard_product_list(鏍囧噯鏍戜笅鐨勬楠岄」鐩�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+ * @createDate 2024-03-05 10:33:29
+ */
+@Service
+@AllArgsConstructor
+public class StandardProductListServiceImpl extends ServiceImpl<StandardProductListMapper, StandardProductList>
+ implements StandardProductListService {
+
+ private StandardProductListMapper standardProductListMapper;
+
+ private StandardTreeMapper standardTreeMapper;
+
+ private StandardProductListService2 standardProductListService2;
+
+ private IfsInventoryQuantityMapper ifsInventoryQuantityMapper;
+
+ private StandardProductListSupplierAskMapper standardProductListSupplierAskMapper;
+
+
+ @Override
+ public int upStandardProductList(StandardProductList list) {
+ return standardProductListMapper.updateById(list);
+ }
+
+ @Override
+ public int delStandardProduct(JSONArray list) {
+ return standardProductListMapper.deleteBatchIds(list);
+ }
+
+ @Override
+ public List<StandardProductList> selectStandardProductList(InsSampleReceiveDto insSample) {
+ // 鏄惁娌℃湁浜у搧
+ boolean isNoSample = false;
+// String[] models = insSample.getModel().split("-(?=[^-]*$)");//鎷嗗垎鏈�鍚庝竴涓��-銆�
+ String model = insSample.getModel();
+ String modelNum = insSample.getModelNum();
+ List<StandardProductList> list = standardProductListMapper.selectDetail(insSample.getStandardMethodListId(), 1, model, insSample.getIsCableTag());
+ if (list.size() == 0) {
+ if (Objects.equals(insSample.getFactory(), "") || insSample.getFactory() == null) {
+ return null;
+ }
+ String[] split = insSample.getFactory().split(" - ");
+ split[3] = split[3].replace("- ", "");
+ String tree = split[0] + " - " + split[1] + " - " + split[2] + " - " + split[3] + " - null";
+ list = standardProductListMapper.selectDetail2(insSample.getStandardMethodListId(), 1, tree, insSample.getIsCableTag());
+ if (list.size() == 0) {
+ String tree1 = split[0] + " - " + split[1] + " - " + split[2] + " - null - " + split[3];
+ list = standardProductListMapper.selectDetail2(insSample.getStandardMethodListId(), 1, tree1, insSample.getIsCableTag());
+
+ // 鍙湁瀵硅薄鐨勪竴灞�
+ if (list.size() == 0) {
+ String tree2 = split[0] + " - " + split[1] + " - " + split[2] + " - null - null";
+ list = standardProductListMapper.selectDetail2(insSample.getStandardMethodListId(), 1, tree2, insSample.getIsCableTag());
+ // 鏍峰搧鐩存帴璧嬪�兼牱鍝佸垎绫�
+ list.forEach(standardProductList -> standardProductList.setSample(standardProductList.getSampleType()));
+ isNoSample = true;
+ }
+ }
+ }
+ String[] split1 = insSample.getFactory().split(" - ");
+ if (!isNoSample) {
+ //鍒ゆ柇闀垮害
+ if (split1.length > 4) {
+ if (ObjectUtils.isNotEmpty(split1[3])) {
+ list = list.stream().filter(list1 -> Objects.nonNull(list1.getSample()) && Objects.equals(list1.getSample(), split1[3])).collect(Collectors.toList());
+ } else if (split1[3].equals("")) {
+ list = list.stream().filter(list1 -> Objects.nonNull(list1.getSampleType()) && Objects.equals(list1.getSampleType(), split1[2])).collect(Collectors.toList());
+ }
+ }
+ }
+ list = list.stream().filter(a -> {
+ try {
+ if (a.getSection() != null && !Objects.equals(a.getSection(), "")) {
+ List<String> sections = JSON.parseArray(a.getSection(), String.class);// 鍖洪棿
+ List<String> cores = JSON.parseArray(a.getCores(), String.class); // 鑺暟
+ List<String> conductorMaterials = JSON.parseArray(a.getConductorMaterial(), String.class); // 瀵间綋鏉愯川
+ List<String> conductorTypes = JSON.parseArray(a.getConductorType(), String.class); // 瀵间綋绫诲瀷
+ List<String> asks = JSON.parseArray(a.getAsk(), String.class);
+ List<String> tells = JSON.parseArray(a.getTell(), String.class);
+ boolean isIf;
+ for (int i = 0; i < sections.size(); i++) {
+ if (Objects.equals(a.getBsm(), "1")) {
+ return true;
+ } else {
+ if (sections.get(i).contains("&")) {
+ String[] split = sections.get(i).split("&");
+ isIf = getIsIf(split[0], modelNum, cores.get(i), conductorMaterials.get(i), conductorTypes.get(i), insSample)
+ && getIsIf(split[1], modelNum, cores.get(i), conductorMaterials.get(i), conductorTypes.get(i), insSample);
+ } else {
+ isIf = getIsIf(sections.get(i), modelNum, cores.get(i), conductorMaterials.get(i), conductorTypes.get(i), insSample);
+ }
+ if (isIf) {
+ a.setSection(sections.get(i));
+ a.setAsk(asks.get(i));
+ a.setTell(tells.get(i));
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+ } catch (Exception ignored) {
+ return false;
+ }
+ return true;
+ }).peek(standardProductList -> {
+ // todo: 鍒ゆ柇鏄惁鏄師鏉愪笅鍗�, 闇�瑕佸晩鎶婇鑹茬粦瀹氬埌璇曟牱棰滆壊鐨勮姹傚�间笂
+ if (StringUtils.isNotBlank(insSample.getPartNo())) {
+ // 鍒ゆ柇鏄惁鏈夎繖涓瓧娈典笖鏄枃鏈被鍨�
+ if (StringUtils.isNotBlank(standardProductList.getInspectionItem())
+ && standardProductList.getInspectionItem().contains("璇曟牱棰滆壊")) {
+ Map<String, String> partColor = baseMapper.selectPartColor(insSample.getPartNo());
+ if (CollectionUtils.isNotEmpty(partColor)) {
+ if (StringUtils.isNotBlank(partColor.get("color"))) {
+ // 鍒ゆ柇妫�楠屽�兼槸鍚︿负绌哄拰涓嶇瓑浜� - 鍜� /
+ if (StringUtils.isBlank(standardProductList.getAsk()) || partColor.get("color").contains("鏈�")) { // 娌℃湁ask鐩存帴澶嶅埗
+ // 鏌ヨ瀵硅薄缁戝畾琛ㄥ拰浜у搧缁戝畾琛�
+ standardProductList.setAsk("=" + partColor.get("color")
+ + (StringUtils.isBlank(partColor.get("color_code")) ? "" : "(" + partColor.get("color_code") + ")"));
+ standardProductList.setTell(partColor.get("color")
+ + (StringUtils.isBlank(partColor.get("color_code")) ? "" : "(" + partColor.get("color_code") + ")"));
+ standardProductList.setInspectionValueType("2");
+ } else { // 鎷兼帴鍒拌姹傛弿杩板墠闈�
+ standardProductList.setTell(partColor.get("color")
+ + (StringUtils.isBlank(partColor.get("color_code")) ? "" : "(" + partColor.get("color_code") + ")") + "@" + standardProductList.getTell());
+ }
+ }
+ }
+ }
+ }
+ })
+ .collect(Collectors.toList());
+
+ // 鏌ヨ鍘傚鏄惁鏈夌壒娈婅姹傚��
+ if (insSample.getIfsInventoryId() != null) {
+ // 鏌ヨ鍘熸潗鏂欏巶瀹跺悕绉�
+ String supplierName = ifsInventoryQuantityMapper.selectById(insSample.getIfsInventoryId())
+ .getSupplierName();
+ List<Long> collect = list.stream().map(StandardProductList::getId).collect(Collectors.toList());
+ if (CollectionUtils.isNotEmpty(collect)) {
+ List<StandardProductListSupplierAsk> supplierAsks = standardProductListSupplierAskMapper.selectList(Wrappers.<StandardProductListSupplierAsk>lambdaQuery()
+ .in(StandardProductListSupplierAsk::getProductListId, collect)
+ .eq(StandardProductListSupplierAsk::getSupplierName, supplierName));
+
+ // 鍒ゆ柇鏈夋病鏈夌壒娈婂�肩粦瀹�
+ if (CollectionUtils.isNotEmpty(supplierAsks)) {
+ for (StandardProductList standardProductList : list) {
+ for (StandardProductListSupplierAsk supplierAsk : supplierAsks) {
+ if (standardProductList.getId().equals(supplierAsk.getProductListId())) {
+ // 閲嶆柊璧嬪�艰姹傚�煎拰瑕佹眰鎻忚堪
+ standardProductList.setAsk(supplierAsk.getAsk());
+ standardProductList.setTell(supplierAsk.getTell());
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ *
+ * @param str 鍒ゅ畾鍏紡
+ * @param model 鍨嬪彿
+ * @param standardCores 鑺暟
+ * @param conductorMaterial 瀵间綋鏉愯川
+ * @param conductorType 瀵间綋绫诲瀷
+ * @param insSample
+ * @return
+ */
+ private boolean getIsIf(String str, String model, String standardCores, String conductorMaterial, String conductorType,InsSampleReceiveDto insSample) {
+ Matcher matcher = Pattern.compile("\\d+(\\.\\d+)?").matcher(model);
+ String model2 = "";
+ while (matcher.find()) {
+ model2 += matcher.group();
+ break;
+ }
+ boolean flag = false;
+ if (str.contains("鈮�") || str.contains(">=")) {
+ String param = str.replace("鈮�", "").replace(">=", "");
+ flag = new BigDecimal(model2).compareTo(new BigDecimal(param)) > -1;
+ } else if (str.contains("鈮�") || str.contains("<=")) {
+ String param = str.replace("鈮�", "").replace("<=", "");
+ flag = new BigDecimal(model2).compareTo(new BigDecimal(param)) < 1;
+ } else if (str.contains(">") || str.contains("锛�")) {
+ String param = str.replace(">", "").replace("锛�", "");
+ flag = new BigDecimal(model2).compareTo(new BigDecimal(param)) > 0;
+ } else if (str.contains("<") || str.contains("锛�")) {
+ String param = str.replace("<", "").replace("锛�", "");
+ flag = new BigDecimal(model2).compareTo(new BigDecimal(param)) < 0;
+ } else if (str.contains("=")) {
+ String param = str.replace("=", "");
+ flag = new BigDecimal(model2).compareTo(new BigDecimal(param)) == 0;
+ }
+ if (flag) {
+ boolean coresMatch = true;
+ boolean conductorMaterialMatch = true;
+ boolean conductorTypeMatch = true;
+
+ // 鍒ゆ柇鏄惁鏈夌嚎鑺暟閲�
+ if (StringUtils.isNotBlank(standardCores)) {
+ if (StringUtils.isBlank(insSample.getCores()) || !standardCores.equals(insSample.getCores())) {
+ coresMatch = false;
+ }
+ }
+
+ // 鍒ゆ柇鏄惁鏈夊浣撴潗璐�
+ if (StringUtils.isNotBlank(conductorMaterial)) {
+ if (StringUtils.isBlank(insSample.getConductorMaterial()) || !conductorMaterial.equals(insSample.getConductorMaterial())) {
+ conductorMaterialMatch = false;
+ }
+ }
+
+ // 鍒ゆ柇鏄惁鏈夊浣撶被鍨�
+ if (StringUtils.isNotBlank(conductorType)) {
+ if (StringUtils.isBlank(insSample.getConductorType()) || !conductorType.equals(insSample.getConductorType())) {
+ conductorTypeMatch = false;
+ }
+ }
+ // 鏈�缁堝垽鏂�
+ flag = coresMatch && conductorMaterialMatch && conductorTypeMatch;
+ }
+
+ return flag;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public Map<String, Object> selectStandardProductListByMethodId(Integer id, String tree, Integer page) {
+ String[] trees = tree.split(" - ");
+ try {
+ String tree1 = trees[2];
+ } catch (Exception e) {
+ throw new BaseException("鎿嶄綔澶揩,绯荤粺浼犲弬閿欒!!!!");
+ }
+ boolean isDrag = false;
+ List<StandardProductList> list = new ArrayList<>();
+ if (trees.length == 3) {
+ List<StandardTree> treeList = new ArrayList<>();
+ StandardTree standardTree = new StandardTree();
+ standardTree.setFactory(trees[0]);
+ standardTree.setLaboratory(trees[1]);
+ standardTree.setSampleType(trees[2]);
+ List<ProductDto> pList = standardTreeMapper.selectPList(trees[2]);
+ if (pList.size() == 0 || pList.get(0) == null) {
+ List<StandardTree> treeList1 = standardTreeMapper.selectList(Wrappers.<StandardTree>lambdaQuery().eq(StandardTree::getLaboratory, trees[1]).eq(StandardTree::getSampleType, trees[2]));
+ if (treeList1.size() == 0) {
+ treeList.add(standardTree);
+ } else {
+ treeList.addAll(treeList1);
+ }
+ } else {
+ for (ProductDto p : pList) {
+ standardTree.setSample(p.getName());
+ List<StandardTree> treeList1 = standardTreeMapper.selectList(Wrappers.<StandardTree>lambdaQuery().eq(StandardTree::getLaboratory, trees[1]).eq(StandardTree::getSampleType, trees[2]).eq(StandardTree::getSample, p.getName()));
+ if (treeList1.size() == 0) {
+ treeList.add(JSON.parseObject(JSON.toJSONString(standardTree), StandardTree.class));
+ } else {
+ treeList.addAll(treeList1);
+ }
+ }
+ }
+ for (StandardTree standardTree2 : treeList) {
+ String tree2 = trees[0] + " - " + trees[1] + " - " + trees[2] + " - " + standardTree2.getSample() + " - " + standardTree2.getModel();
+ list.addAll(standardTreeMapper.selectStandardProductListByTree("\"" + trees[2] + "\"", standardTree2.getSample(), standardTree2.getModel(), tree2, trees[1]));
+ list.addAll(standardTreeMapper.selectStandardProductListByTree2("\"" + trees[2] + "\",\"" + standardTree2.getSample() + "\"", standardTree2.getSample(), standardTree2.getModel(), tree2, trees[1]));
+ }
+ } else if (trees.length == 4) {
+ // 鍒ゆ柇绗洓灞傛槸鍚︽湁鍨嬪彿
+ Long count = standardProductListMapper.selectCount(Wrappers.<StandardProductList>lambdaQuery()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .isNull(StandardProductList::getModel)
+ .like(StandardProductList::getTree, tree));
+ if (count == 0) {
+ isDrag = true;
+ }
+
+ isDrag = true;
+ List<StandardTree> treeList = standardTreeMapper.selectList(Wrappers.<StandardTree>lambdaQuery().eq(StandardTree::getLaboratory, trees[1]).eq(StandardTree::getSampleType, trees[2]).eq(StandardTree::getSample, trees[3]));
+ if (treeList.size() == 0) {
+ StandardTree standardTree = new StandardTree();
+ standardTree.setFactory(trees[0]);
+ standardTree.setLaboratory(trees[1]);
+ standardTree.setSampleType(trees[2]);
+ standardTree.setSample(trees[3]);
+ treeList.add(standardTree);
+ }
+ for (StandardTree standardTree : treeList) {
+ String str = tree + " - " + standardTree.getModel();
+ list.addAll(standardTreeMapper.selectStandardProductListByTree("\"" + trees[2] + "\"", standardTree.getSample(), standardTree.getModel(), str, trees[1]));
+ list.addAll(standardTreeMapper.selectStandardProductListByTree2("\"" + trees[2] + "\",\"" + trees[3] + "\"", standardTree.getSample(), standardTree.getModel(), str, trees[1]));
+ }
+ } else {
+ isDrag = true;
+ list.addAll(standardTreeMapper.selectStandardProductListByTree("\"" + trees[2] + "\"", trees[3].equals("null") ? null : trees[3], trees[4], tree, trees[1]));
+ list.addAll(standardTreeMapper.selectStandardProductListByTree2("\"" + trees[2] + "\",\"" + trees[3] + "\"", trees[3].equals("null") ? null : trees[3], trees[4], tree, trees[1]));
+ }
+ for (StandardProductList productList : list) {
+ productList.setId(IdWorker.getId());
+ }
+ List<StandardProductList> standardProductLists;
+
+ if (isDrag) {
+ standardProductLists = standardProductListMapper.selectList(Wrappers.<StandardProductList>lambdaQuery()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .like(StandardProductList::getTree, tree)
+ .orderByAsc(StandardProductList::getSort));
+ // 鍒ゆ柇鏄惁鏈夋病鏈夊簭鍙风殑, 娌℃湁搴忓彿閲嶇疆
+ boolean b = standardProductLists.stream().anyMatch(standardProductList -> standardProductList.getSort() == null);
+ } else {
+ standardProductLists = standardProductListMapper.selectList(Wrappers.<StandardProductList>lambdaQuery()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .like(StandardProductList::getTree, tree));
+ }
+
+ for (StandardProductList sp : standardProductLists) {
+ for (StandardProductList pl : list) {
+ // 鍒ゆ柇鏉′欢鏄惁鍙湁涓�涓�, 鏈変竴涓殑璇濋粯璁ょ涓�涓�
+ String radiusList = pl.getRadiusList();
+ if (StringUtils.isNotBlank(radiusList) && !radiusList.equals("null") && !radiusList.equals("\"\"")) {
+ JSONArray jsonArray = JSON.parseArray(radiusList);
+ List<String> radius = jsonArray.toJavaList(String.class);
+ if (CollectionUtils.isNotEmpty(radius) && radius.size() == 1) {
+ pl.setRadius(radius.get(0));
+ }
+ }
+ if (Objects.equals(sp.getInspectionItem(), pl.getInspectionItem())
+ && Objects.equals((sp.getInspectionItemSubclass() == null) ? "" : sp.getInspectionItemSubclass(), pl.getInspectionItemSubclass() == null ? "" : pl.getInspectionItemSubclass())
+// && Objects.equals(sp.getSample(), pl.getSample())
+ && Objects.equals(sp.getModel(), pl.getModel())
+ && sp.getTree().indexOf(pl.getSample() == null ? "null" : pl.getSample()) > -1
+ && Objects.equals(sp.getStructureItemParameterId(), pl.getStructureItemParameterId())) {
+ pl.setId(sp.getId());
+ // 娣诲姞鎺掑簭瀛楁
+ pl.setSort(sp.getSort());
+ if (sp.getState() != null && !sp.getState().equals("")) {
+ pl.setState(sp.getState());
+ } else {
+ pl.setState(id == 0 ? 1 : 0);
+ }
+ if (sp.getMethodS() != null && !sp.getMethodS().equals("")) {
+ pl.setMethod(sp.getMethodS());
+ }
+ if (sp.getRadius() != null && !sp.getRadius().equals("")) {
+ pl.setRadius(sp.getRadius());
+ }
+ if (sp.getRates() != null && !sp.getRates().equals("")) {
+ pl.setRates(sp.getRates());
+ }
+ if (sp.getAsk() != null && !sp.getAsk().equals("")) {
+ pl.setAsk(sp.getAsk());
+ }
+ if (sp.getTell() != null && !sp.getTell().equals("")) {
+ pl.setTell(sp.getTell());
+ }
+ if (sp.getPrice() != null && !sp.getPrice().equals("")) {
+ pl.setPrice(sp.getPrice());
+ }
+ if (sp.getManHour() != null && !sp.getManHour().equals("")) {
+ pl.setManHour(sp.getManHour());
+ }
+ if (sp.getSection() != null && !sp.getSection().equals("")) {
+ pl.setSection(sp.getSection());
+ }
+ if (sp.getCores() != null && !sp.getCores().equals("")) {
+ pl.setCores(sp.getCores());
+ }
+ if (sp.getConductorMaterial() != null && !sp.getConductorMaterial().equals("")) {
+ pl.setConductorMaterial(sp.getConductorMaterial());
+ }
+ if (sp.getConductorType() != null && !sp.getConductorType().equals("")) {
+ pl.setConductorType(sp.getConductorType());
+ }
+ if (sp.getTemplateId() != null && !sp.getTemplateId().equals("")) {
+ pl.setTemplateId(sp.getTemplateId());
+ }
+ //鍥犱负杩樻湁涓骇鍝佸彨鑰愬紶绾垮す 鎺ョ画閲戝叿 ,杩欎袱涓」鐩殑鏁版嵁瀹屽叏涓�鏍�,鐗规畩澶勭悊
+ if (sp.getTree() != null && !sp.getTree().equals("") && !pl.getTree().equals("涓ぉ绉戞妧妫�娴嬩腑蹇� - 鐢靛姏浜у搧瀹為獙瀹� - 閲戝叿 - 鑰愬紶绾垮す - null")) {
+ pl.setTree(sp.getTree());
+ }
+ break;
+ }
+ }
+ }
+ if (page == 1) {
+ Integer userId = SecurityUtils.getUserId().intValue();
+// CompletableFuture.supplyAsync(() -> {
+ if (trees.length == 5) {
+ standardProductListMapper.delete(Wrappers.<StandardProductList>lambdaUpdate()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .eq(StandardProductList::getTree, tree));
+ } else {
+ standardProductListMapper.delete(Wrappers.<StandardProductList>lambdaUpdate()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .like(StandardProductList::getTree, tree));
+ }
+
+ boolean success = false;
+ int retryCount = 0;
+ while (!success && retryCount < 100) {
+ try {
+ standardProductListService2.saveBatch(list.stream().map(a -> {
+ a.setFactory(trees[0]);
+ a.setLaboratory(trees[1]);
+ a.setSampleType(trees[2]);
+ a.setCreateUser(userId);
+ a.setUpdateUser(userId);
+ a.setStandardMethodListId(id);
+ return a;
+ }).collect(Collectors.toList()));
+ ;
+ success = true;
+ } catch (Exception e) {
+ // 澶勭悊閲嶅 ID 鐨勮褰曪紝閲嶆柊鐢熸垚 ID 骞剁户缁皾璇曟彃鍏�
+ for (StandardProductList productList : list) {
+ productList.setId(IdWorker.getId());
+ }
+ }
+ }
+ if (!success) {
+ throw new RuntimeException("鎻掑叆澶辫触");
+ }
+
+ }
+ Map<String, Object> map = new HashMap<>();
+ Collections.sort(list, (o1, o2) -> {
+ String field1 = o1.getManHourGroup();
+ String field2 = o2.getManHourGroup();
+
+ boolean isEmpty1 = field1 == null || field1.isEmpty();
+ boolean isEmpty2 = field2 == null || field2.isEmpty();
+
+ if (isEmpty1 && isEmpty2) {
+ return 0;
+ } else if (isEmpty1) {
+ return 1;
+ } else if (isEmpty2) {
+ return -1;
+ } else {
+ int num1 = extractNumber(field1);
+ int num2 = extractNumber(field2);
+ return Integer.compare(num1, num2);
+ }
+ });
+ // 鎸夌収绱㈠紩鎺掑簭
+ if (isDrag) {
+ list.sort((o1, o2) -> (o1.getSort() == null ? 0 : o1.getSort())
+ - (o2.getSort() == null ? 0 : o2.getSort()));
+ }
+ try {
+ map.put("productList", list.subList((page - 1) * 300, page * 300));
+ } catch (IndexOutOfBoundsException e) {
+ map.put("productList", list.subList((page - 1) * 300, list.size()));
+ }
+ map.put("total", list.size());
+ return map;
+ }
+
+ private int extractNumber(String s) {
+ // 浠庡瓧绗︿覆涓彁鍙栨暟瀛楃殑閫昏緫锛岃繖閲屽亣璁惧瓧娈电殑鏍煎紡鏄� "text<number>"
+ String number = s;
+ if (!s.matches("\\d+")) {
+ number = s.replaceAll("\\D", "");
+ }
+ return Integer.parseInt(number);
+ }
+
+ @Override
+ public IPage<StandardProductList> selectStandardProductByMethodId(Integer id, String tree, Integer page, String laboratory, String item, String items) {
+ IPage<StandardProductList> iPage = new Page<>();
+ iPage.setSize(100);
+ iPage.setCurrent(page);
+ return standardProductListMapper.standardProductListIPage(id, tree, iPage, laboratory, item, items);
+ }
+
+ @Override
+ public Map<String, List<?>> selectStandardProductEnumByMethodId(Integer id, String tree, String item) {
+ HashMap<String, List<?>> map = new HashMap<>();
+ map.put("item", standardProductListMapper.selectList(Wrappers.<StandardProductList>lambdaQuery()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .like(StandardProductList::getTree, tree)
+ .select(StandardProductList::getInspectionItem)
+ .groupBy(StandardProductList::getInspectionItem)));
+ if (ObjectUtils.isNotEmpty(item)) {
+ map.put("items", standardProductListMapper.selectList(Wrappers.<StandardProductList>lambdaQuery()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .eq(StandardProductList::getInspectionItem, item)
+ .like(StandardProductList::getTree, tree)
+ .select(StandardProductList::getInspectionItemSubclass)
+ .groupBy(StandardProductList::getInspectionItemSubclass)));
+ } else {
+ map.put("items", standardProductListMapper.selectList(Wrappers.<StandardProductList>lambdaQuery()
+ .eq(StandardProductList::getStandardMethodListId, id)
+ .like(StandardProductList::getTree, tree)
+ .select(StandardProductList::getInspectionItemSubclass)
+ .groupBy(StandardProductList::getInspectionItemSubclass)));
+ }
+ return map;
+ }
+
+ /**
+ * 淇敼鏍囧噯搴撳尯闂�
+ * @param list
+ * @return
+ */
+ @Override
+ public boolean updateSection(StandardProductList list) {
+ standardProductListMapper.updateSection(list);
+ return true;
+ }
+
+
+ /**
+ * 鏍囧噯搴撴嫋鎷�
+ * @param resetTreeDragDTO
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void resetTreeDrag(ResetTreeDragDTO resetTreeDragDTO) {
+ Integer beginIndex = Integer.parseInt(resetTreeDragDTO.getBeginIndex());
+ Integer endIndex = Integer.parseInt(resetTreeDragDTO.getEndIndex());
+ Integer methodId = Integer.parseInt(resetTreeDragDTO.getMethodId());
+ Long productionId = Long.parseLong(resetTreeDragDTO.getProductionId());
+ // 鍒ゆ柇鏄粠涓婂線涓嬫嫋鎷借繕鏄粠涓嬪線涓婃斁鎷栨嫿
+ // 浠庝笂寰�涓�
+ if (beginIndex < endIndex) {
+ standardProductListMapper.updateSortUp(beginIndex,
+ endIndex,
+ methodId,
+ resetTreeDragDTO.getTree());
+
+ // 浠庝笅寰�涓�
+ } else if (beginIndex > endIndex){
+ standardProductListMapper.updateSortDown(beginIndex,
+ endIndex,
+ methodId,
+ resetTreeDragDTO.getTree());
+ } else {
+ return;
+ }
+ // 淇敼鏍囧噯搴撻」椤哄簭
+ standardProductListMapper.update(null, Wrappers.<StandardProductList>lambdaUpdate()
+ .eq(StandardProductList::getId, productionId)
+ .set(StandardProductList::getSort, endIndex));
+ }
+
+ @Override
+ public void resetTreeDragBatch(List<StandardProductList> standardProductLists) {
+ standardProductListService2.updateBatchById(standardProductLists);
+ }
+
+ /**
+ * 妫�楠岄」瑕佹眰鍊煎姣�
+ * @param copyDto
+ * @return
+ */
+ @Override
+ public List<StandardProductList> copyStandardProductList(CopyStandardProductListDto copyDto) {
+ List<StandardProductList> productLists = new ArrayList<>();
+
+ // 瀵规瘮妫�楠岄」涓�鏍风殑濉厖瑕佹眰鍊艰姹傛弿杩�
+ for (StandardProductList oldProductList : copyDto.getOldStandardProductList()) {
+ String oldItemName = oldProductList.getInspectionItemClassEn()
+ + oldProductList.getInspectionItem()
+ + oldProductList.getInspectionItemSubclass();
+ for (StandardProductList newProductList : copyDto.getNewStandardProductList()) {
+ String newItemName = newProductList.getInspectionItemClassEn()
+ + newProductList.getInspectionItem()
+ + newProductList.getInspectionItemSubclass();
+ // 鍒ゆ柇鍚嶇О鏄惁涓�鏍�
+ if (oldItemName.equals(newItemName)) {
+ // 鍖洪棿
+ oldProductList.setSection(newProductList.getSection());
+ // 鑺暟
+ oldProductList.setCores(newProductList.getCores());
+ // 瑕佹眰鍊�
+ oldProductList.setAsk(newProductList.getAsk());
+ // 瑕佹眰鎻忚堪
+ oldProductList.setTell(newProductList.getTell());
+ // 鍗曚环
+ oldProductList.setPrice(newProductList.getPrice());
+ // 宸ユ椂鍒嗙粍
+ oldProductList.setManHour(newProductList.getManHour());
+ // 瀵间綋鏉愯川
+ oldProductList.setConductorMaterial(newProductList.getConductorMaterial());
+ // 瀵间綋绫诲瀷
+ oldProductList.setConductorType(newProductList.getConductorType());
+ productLists.add(oldProductList);
+ }
+ }
+ }
+ return productLists;
+ }
+
+ /**
+ * 妫�楠岄」澶嶅埗瀵规瘮涓�涓�
+ * @param dto
+ * @return
+ */
+ @Override
+ public List<StandardProductList> copyStandardProductOne(CopyStandardProductListDto dto) {
+ if (CollectionUtils.isEmpty(dto.getNewStandardProductList()) && dto.getNewStandardProductList().size() == 1 &&
+ CollectionUtils.isEmpty(dto.getOldStandardProductList()) && dto.getOldStandardProductList().size() == 1) {
+ throw new BaseException("闇�瑕佸姣旂殑妫�楠岄」璇烽�夋嫨涓�涓�");
+ }
+ StandardProductList newProductList = dto.getNewStandardProductList().get(0);
+ StandardProductList oldProductList = dto.getOldStandardProductList().get(0);
+ // 鍖洪棿
+ oldProductList.setSection(newProductList.getSection());
+ // 鑺暟
+ oldProductList.setCores(newProductList.getCores());
+ // 瑕佹眰鍊�
+ oldProductList.setAsk(newProductList.getAsk());
+ // 瑕佹眰鎻忚堪
+ oldProductList.setTell(newProductList.getTell());
+ // 鍗曚环
+ oldProductList.setPrice(newProductList.getPrice());
+ // 宸ユ椂鍒嗙粍
+ oldProductList.setManHour(newProductList.getManHour());
+ // 瀵间綋鏉愯川
+ oldProductList.setConductorMaterial(newProductList.getConductorMaterial());
+ // 瀵间綋绫诲瀷
+ oldProductList.setConductorType(newProductList.getConductorType());
+ List<StandardProductList> productLists = new ArrayList<>();
+ productLists.add(oldProductList);
+ return productLists;
+ }
+
+ /**
+ * 妫�楠岄」澶嶅埗鎺掑簭
+ * @param copyDto
+ * @return
+ */
+ @Override
+ public boolean copyStandardProductSort(CopyStandardProductListDto copyDto) {
+ List<StandardProductList> productLists = new ArrayList<>();
+
+ // 瀵规瘮妫�楠岄」涓�鏍风殑濉厖瑕佹眰鍊艰姹傛弿杩�
+ for (StandardProductList oldProductList : copyDto.getOldStandardProductList()) {
+ String oldItemName = oldProductList.getInspectionItemClassEn()
+ + oldProductList.getInspectionItem()
+ + oldProductList.getInspectionItemSubclass();
+ for (StandardProductList newProductList : copyDto.getNewStandardProductList()) {
+ String newItemName = newProductList.getInspectionItemClassEn()
+ + newProductList.getInspectionItem()
+ + newProductList.getInspectionItemSubclass();
+ // 鍒ゆ柇鍚嶇О鏄惁涓�鏍�
+ if (oldItemName.equals(newItemName)) {
+ StandardProductList standardProductList = new StandardProductList();
+ standardProductList.setId(oldProductList.getId());
+ // 澶嶅埗鎺掑簭
+ standardProductList.setSort(newProductList.getSort());
+ productLists.add(standardProductList);
+ }
+ }
+ }
+ this.updateBatchById(productLists);
+ return false;
+ }
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListSupplierAskServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListSupplierAskServiceImpl.java
new file mode 100644
index 0000000..95ac78d
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardProductListSupplierAskServiceImpl.java
@@ -0,0 +1,79 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.basic.mapper.StandardProductListSupplierAskMapper;
+import com.ruoyi.basic.pojo.StandardProductListSupplierAsk;
+import com.ruoyi.basic.service.StandardProductListSupplierAskService;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 妫�楠岄」鐩巶瀹跺瘑搴︾粦瀹氳〃
+ *
+ * @author zhuo
+ * @since 2024-09-23
+ */
+@Service
+public class StandardProductListSupplierAskServiceImpl extends ServiceImpl<StandardProductListSupplierAskMapper, StandardProductListSupplierAsk> implements StandardProductListSupplierAskService {
+
+ /**
+ * 鏌ヨ鍘傚瑕佹眰鍊肩粦瀹�
+ * @param supplierAsk
+ * @return
+ */
+ @Override
+ public List<StandardProductListSupplierAsk> selectByProductId(StandardProductListSupplierAsk supplierAsk) {
+ if (supplierAsk.getProductListId() == null) {
+ throw new BaseException("缂哄皯妫�楠岄」id");
+ }
+ return baseMapper.selectList(Wrappers.<StandardProductListSupplierAsk>lambdaQuery()
+ .eq(StandardProductListSupplierAsk::getProductListId, supplierAsk.getProductListId()));
+ }
+
+ /**
+ * 鏂板鍘傚瑕佹眰鍊肩粦瀹�
+ * @param supplierAsk
+ * @return
+ */
+ @Override
+ public Integer addProductSupplierAsk(StandardProductListSupplierAsk supplierAsk) {
+ if (supplierAsk.getProductListId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ // 鏌ヨ鏀瑰巶瀹舵槸鍚︾粦瀹氳繃
+ Long count = baseMapper.selectCount(Wrappers.<StandardProductListSupplierAsk>lambdaQuery()
+ .eq(StandardProductListSupplierAsk::getProductListId, supplierAsk.getProductListId())
+ .eq(StandardProductListSupplierAsk::getSupplierName, supplierAsk.getSupplierName()));
+ if (count > 0){
+ throw new BaseException("璇ヤ骇鍝佸凡缁戝畾杩囪鍘傚");
+ }
+ baseMapper.insert(supplierAsk);
+ return supplierAsk.getSupplierAskId();
+ }
+
+ /**
+ * 淇敼鍘傚瑕佹眰鍊肩粦瀹�
+ * @param supplierAsk
+ * @return
+ */
+ @Override
+ public Integer updateProductSupplierAsk(StandardProductListSupplierAsk supplierAsk) {
+ if (supplierAsk.getProductListId() == null) {
+ throw new BaseException("缂哄皯妫�楠岄」id");
+ }
+ // 鏌ヨ鏀瑰巶瀹舵槸鍚︾粦瀹氳繃
+ Long count = baseMapper.selectCount(Wrappers.<StandardProductListSupplierAsk>lambdaQuery()
+ .ne(StandardProductListSupplierAsk::getSupplierAskId, supplierAsk.getSupplierAskId())
+ .eq(StandardProductListSupplierAsk::getProductListId, supplierAsk.getProductListId())
+ .eq(StandardProductListSupplierAsk::getSupplierName, supplierAsk.getSupplierName()));
+ if (count > 0){
+ throw new BaseException("璇ユ楠岄」宸茬粦瀹氳繃璇ュ巶瀹�");
+ }
+ baseMapper.updateById(supplierAsk);
+ return supplierAsk.getSupplierAskId();
+ }
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java
new file mode 100644
index 0000000..f1f3ba4
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTemplateServiceImpl.java
@@ -0,0 +1,130 @@
+package com.ruoyi.basic.service.impl;
+
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.numgen.NumberGenerator;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.mapper.StandardTemplateMapper;
+import com.ruoyi.basic.pojo.StandardTemplate;
+import com.ruoyi.basic.service.StandardTemplateService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.List;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恠tandard_template(鏍囧噯妯℃澘)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+* @createDate 2024-03-11 13:47:52
+*/
+@Service
+@AllArgsConstructor
+public class StandardTemplateServiceImpl extends ServiceImpl<StandardTemplateMapper, StandardTemplate>
+ implements StandardTemplateService{
+
+ private StandardTemplateMapper standardTemplateMapper;
+
+
+ private final NumberGenerator<StandardTemplate> numberGenerator;
+
+ @Override
+ public IPage<StandardTemplate> selectStandardTemplatePageList(Page page, StandardTemplate standardTemplate) {
+ return standardTemplateMapper.selectStandardTemplatePageList(page, QueryWrappers.queryWrappers(standardTemplate));
+ }
+
+ @Override
+ public int addStandardTemplate(StandardTemplate standardTemplate) {
+ if (StringUtils.isBlank(standardTemplate.getNumber())) {
+ String giveCode = numberGenerator.generateNumberWithPrefix(5,
+ "MB" + DateUtil.format(new Date(), "yyMM"),
+ StandardTemplate::getNumber);
+ standardTemplate.setNumber(giveCode);
+ }
+ return standardTemplateMapper.insert(standardTemplate);
+ }
+
+ @Override
+ public int upStandardTemplate(StandardTemplate standardTemplate) {
+ if(standardTemplate.getThing().equals("")){
+ standardTemplate.setThing(null);
+ }
+ return standardTemplateMapper.updateById(standardTemplate);
+ }
+
+ @Override
+ public int delStandardTemplate(Integer id) {
+ return standardTemplateMapper.deleteById(id);
+ }
+
+ @Override
+ public List<StandardTemplate> getStandardTemplate() {
+ return standardTemplateMapper.selectList(Wrappers.<StandardTemplate>lambdaQuery().select(StandardTemplate::getId,StandardTemplate::getName));
+ }
+
+ @Override
+ public String getStandTempThingById(Integer templateId) {
+ StandardTemplate standardTemplate = standardTemplateMapper.selectOne(Wrappers.<StandardTemplate>lambdaQuery()
+ .eq(StandardTemplate::getId, templateId)
+ .select(StandardTemplate::getThing));
+ if(standardTemplate==null){
+ return null;
+ }else{
+ return standardTemplate.getThing();
+ }
+ // 鏌ヨ鍘嬬缉鍚庣殑鏁版嵁
+// String thing = standardTemplateMapper.selectCompressThing(templateId);
+// if (StringUtils.isNotBlank(thing)) {
+// try {
+// return DecompressMySQLData.decompress(java.util.Base64.getDecoder().decode(thing));
+// } catch (Exception e) {
+// throw new RuntimeException(e);
+// }
+// } else {
+// return null;
+// }
+ }
+
+ @Override
+ public String getStandTempNameById(Integer templateId) {
+ StandardTemplate standardTemplate = standardTemplateMapper.selectOne(Wrappers.<StandardTemplate>lambdaQuery()
+ .eq(StandardTemplate::getId, templateId)
+ .select(StandardTemplate::getName));
+ if(standardTemplate==null){
+ return null;
+ }else{
+ return standardTemplate.getName();
+ }
+ }
+
+ @Override
+ public StandardTemplate getStandTempIdByName(String name) {
+ return standardTemplateMapper.getStandTempIdByName(name);
+ }
+
+ /**
+ * 澶嶅埗鍘熷璁板綍妯℃澘
+ * @param newTemplate
+ * @return
+ */
+ @Override
+ public int copyStandardTemplate(StandardTemplate newTemplate) {
+ // 鏌ヨ鏃фā鏉�
+ StandardTemplate standardTemplate = baseMapper.selectById(newTemplate.getId());
+ newTemplate.setThing(standardTemplate.getThing());
+
+ if (StringUtils.isBlank(newTemplate.getNumber())) {
+ String giveCode = numberGenerator.generateNumberWithPrefix(5,
+ "MB" + DateUtil.format(new Date(), "yyMM"),
+ StandardTemplate::getNumber);
+ newTemplate.setNumber(giveCode);
+ }
+ newTemplate.setId(null);
+
+ return standardTemplateMapper.insert(newTemplate);
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
new file mode 100644
index 0000000..b64ab41
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StandardTreeServiceImpl.java
@@ -0,0 +1,535 @@
+package com.ruoyi.basic.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.poi.excel.ExcelUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.basic.dto.FactoryDto;
+import com.ruoyi.basic.dto.LaboratoryDto;
+import com.ruoyi.basic.dto.SampleTypeDto;
+import com.ruoyi.basic.mapper.StandardProductListMapper;
+import com.ruoyi.basic.mapper.StandardTreeMapper;
+import com.ruoyi.basic.pojo.StandardProductList;
+import com.ruoyi.basic.pojo.StandardTemplate;
+import com.ruoyi.basic.pojo.StandardTree;
+import com.ruoyi.basic.pojo.StructureTestObject;
+import com.ruoyi.basic.service.*;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.ObjectUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
+
+/**
+ * @author Administrator
+ * @description 閽堝琛ㄣ�恠tandard_tree(鏍囧噯鏍�)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+ * @createDate 2024-03-01 15:06:44
+ */
+@Service
+@AllArgsConstructor
+public class StandardTreeServiceImpl extends ServiceImpl<StandardTreeMapper, StandardTree>
+ implements StandardTreeService {
+
+
+ private StandardTreeMapper standardTreeMapper;
+
+ private StandardMethodListService standardMethodListService;
+
+ private StandardProductListMapper standardProductListMapper;
+
+ private StandardProductListService standardProductListService;
+
+ private StandardTemplateService standardTemplateService;
+
+ private StructureTestObjectService structureTestObjectService;
+
+
+ @Override
+ public List<FactoryDto> selectStandardTreeList() {
+ List<FactoryDto> factoryDtos = standardTreeMapper.selectStandardTreeList();
+ for (FactoryDto factoryDto : factoryDtos) {
+ for (LaboratoryDto laboratoryDto : factoryDto.getChildren()) {
+ laboratoryDto.getChildren().sort((o1, o2) -> (o1.getSort() == null ? 0 : o1.getSort())
+ - (o2.getSort() == null ? 0 : o2.getSort()));
+ for (SampleTypeDto sampleTypeDto : laboratoryDto.getChildren()) {
+// if (sampleTypeDto.getChildren().size() == 0) {
+ sampleTypeDto.getChildren().addAll(standardTreeMapper.getStandardTree3(sampleTypeDto.getValue()));
+// }
+ }
+ }
+ }
+ return factoryDtos;
+ }
+
+
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int addStandardTree(StandardTree standardTree) {
+ LambdaQueryWrapper<StandardTree> wrapper = Wrappers.<StandardTree>lambdaQuery()
+ .eq(StandardTree::getFactory, standardTree.getFactory())
+ .eq(StandardTree::getLaboratory, standardTree.getLaboratory())
+ .eq(StandardTree::getSampleType, standardTree.getSampleType())
+ .eq(StandardTree::getSample, standardTree.getSample())
+ .eq(StandardTree::getModel, standardTree.getModel());
+ if (StringUtils.isNotBlank(standardTree.getSample())) {
+ wrapper.eq(StandardTree::getSample, standardTree.getSample());
+ }
+
+ StandardTree tree = standardTreeMapper.selectOne(wrapper);
+ if (tree != null) {
+ throw new BaseException("璇ュ瀷鍙峰凡瀛樺湪");
+ }
+ return standardTreeMapper.insert(standardTree);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int delStandardTree(String tree) {
+ String[] trees = tree.split(" - ");
+ switch (trees.length) {
+ case 5:
+ if (trees[3].equals("null")) {
+ standardTreeMapper.delete(Wrappers.<StandardTree>lambdaUpdate().eq(StandardTree::getFactory, trees[0]).eq(StandardTree::getLaboratory, trees[1]).eq(StandardTree::getSampleType, trees[2]).isNull(StandardTree::getSample).eq(StandardTree::getModel, trees[4]));
+ } else {
+ standardTreeMapper.delete(Wrappers.<StandardTree>lambdaUpdate().eq(StandardTree::getFactory, trees[0]).eq(StandardTree::getLaboratory, trees[1]).eq(StandardTree::getSampleType, trees[2]).eq(StandardTree::getSample, trees[3]).eq(StandardTree::getModel, trees[4]));
+ }
+ break;
+ /*case 4:
+ standardTreeMapper.delete(Wrappers.<StandardTree>lambdaUpdate().eq(StandardTree::getFactory, trees[0]).eq(StandardTree::getLaboratory, trees[1]).eq(StandardTree::getSampleType, trees[2]).eq(StandardTree::getSample, trees[3]));
+ break;
+ case 3:
+ standardTreeMapper.delete(Wrappers.<StandardTree>lambdaUpdate().eq(StandardTree::getFactory, trees[0]).eq(StandardTree::getLaboratory, trees[1]).eq(StandardTree::getSampleType, trees[2]));
+ break;
+ case 2:
+ standardTreeMapper.delete(Wrappers.<StandardTree>lambdaUpdate().eq(StandardTree::getFactory, trees[0]).eq(StandardTree::getLaboratory, trees[1]));
+ break;
+ case 1:
+ standardTreeMapper.delete(Wrappers.<StandardTree>lambdaUpdate().eq(StandardTree::getFactory, trees[0]));
+ break;*/
+ }
+ return 1;
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int addStandardProduct(String ids, String tree) {
+ String[] trees = tree.split(" - ");
+ JSONArray jsonArray = JSON.parseArray(ids);
+ for (Object o : jsonArray) {
+ StandardProductList standardProductList = standardTreeMapper.selectStandardProductById(Integer.parseInt("" + o));
+ standardProductList.setFactory(trees[0]);
+ try {
+ standardProductList.setLaboratory(trees[1]);
+ } catch (Exception e) {
+ }
+ try {
+ standardProductList.setSampleType(trees[2]);
+ } catch (Exception e) {
+ }
+ try {
+ standardProductList.setSample(trees[3]);
+ } catch (Exception e) {
+ }
+ try {
+ standardProductList.setModel(trees[4]);
+ } catch (Exception e) {
+ }
+ standardProductListMapper.insert(standardProductList);
+ }
+ return 1;
+ }
+
+ @Override
+ public List<SampleTypeDto> getStandardTree2() {
+ return standardTreeMapper.getStandardTree2();
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int upStandardProducts(Map<String, Object> product) {
+ List<Integer> ids = JSON.parseArray(product.get("ids") + "");
+ StandardProductList productList = JSON.parseObject(JSON.toJSONString(product.get("standardProductList")), StandardProductList.class);
+ if (productList.getMethodS() != null) {
+ standardProductListMapper.update(productList, Wrappers.<StandardProductList>lambdaUpdate().in(StandardProductList::getId, ids).like(StandardProductList::getMethod, productList.getMethodS()));
+ return 1;
+ }
+ if (productList.getRadiusList() != null) {
+ standardProductListMapper.update(productList, Wrappers.<StandardProductList>lambdaUpdate().in(StandardProductList::getId, ids).like(StandardProductList::getRadiusList, productList.getRadius()));
+ return 1;
+ }
+ standardProductListMapper.update(productList, Wrappers.<StandardProductList>lambdaUpdate().in(StandardProductList::getId, ids));
+ return 1;
+ }
+
+ @Override
+ public List<StandardTree> getStandTreeBySampleType(String laboratory, String sampleType) {
+ return standardTreeMapper.selectList(Wrappers.<StandardTree>lambdaQuery()
+ .eq(StandardTree::getLaboratory, laboratory)
+ .eq(StandardTree::getSampleType, sampleType)
+ .select(StandardTree::getModel, StandardTree::getSample));
+ }
+
+ /**
+ * 娌冲彛妫�娴嬩腑蹇冨鍏�
+ * @param file
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void inExcelOfTree(MultipartFile file) {
+ InputStream inputStream;
+ try {
+ inputStream = file.getInputStream();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ List<StandardProductList> lists = new ArrayList<>();
+ AtomicReference<String> laboratory = new AtomicReference<>();
+ ExcelUtil.readBySax(inputStream, 0, (i, l, list) -> {
+ StandardProductList str = new StandardProductList();
+ if (i == 0 && l == 1) {
+ laboratory.set(standardTreeMapper.getLaboratory(list.get(1) + ""));
+ if (laboratory.get() == null) {
+ throw new BaseException("妫�楠屽璞′笉瀛樺湪锛�" + list.get(1));
+ }
+ }
+ if (i == 0 && l >= 1) {
+ Integer standardMethodId = standardMethodListService.getStandardMethodId(list.get(0) + "");
+ if (standardMethodId == null) {
+ throw new BaseException("鏍囧噯缂栧彿涓嶅瓨鍦細" + list.get(0));
+ }
+ str.setStandardMethodListId(standardMethodId);
+ str.setSampleType(list.get(1) + "");
+ if (list.get(2) != null) {
+ String sample = baseMapper.selSample(list.get(2) + "");
+ if (sample == null) {
+ throw new BaseException("鏍峰搧涓嶅瓨鍦細" + list.get(2));
+ }
+ str.setSample(list.get(2) + "");
+ } else {
+ str.setSample(null);
+ }
+ if (list.get(3) != null) {
+ str.setModel(list.get(3) + "");
+ Long aLong = standardTreeMapper.selectCount(Wrappers.<StandardTree>lambdaQuery()
+ .eq(StandardTree::getModel, str.getModel())
+ .eq(StandardTree::getSampleType, list.get(1) + ""));
+ if (aLong == 0) {
+ StandardTree standardTree = new StandardTree();
+ standardTree.setFactory("涓ぉ绉戞妧妫�娴嬩腑蹇�");
+ standardTree.setLaboratory(laboratory.get());
+ standardTree.setSampleType(str.getSampleType());
+ standardTree.setSample(str.getSample());
+ standardTree.setModel(str.getModel());
+ standardTreeMapper.insert(standardTree);
+ }
+ } else {
+ str.setModel(null);
+ }
+ str.setInspectionItem(list.get(4) + "");
+ if (list.get(6) == null) {
+ str.setInspectionItemSubclass("");
+ } else {
+ str.setInspectionItemSubclass(list.get(6).toString());
+ }
+ StandardProductList db_str;
+ try {
+ db_str = standardProductListMapper.getOne(str.getStandardMethodListId(), str.getInspectionItem(), str.getSample(), str.getInspectionItemSubclass(), str.getModel(), str.getInspectionItemClass());
+ } catch (Exception e) {
+ throw new BaseException("閲嶅鏌ヨ锛�" + str.getInspectionItem() + " " + str.getInspectionItemSubclass());
+ }
+ if (ObjectUtils.isNotEmpty(db_str)) {
+ str.setId(db_str.getId());
+ str.setStructureItemParameterId(db_str.getStructureItemParameterId());
+ }
+ if (list.get(8) != null) {
+ str.setMethodS(list.get(8) + "");
+ }
+
+ if (list.get(11) == null) {
+ str.setTell(null);
+ } else {
+ str.setTell(list.get(11).toString());
+ }
+
+ if (list.get(12) == null) {
+ str.setAsk(null);
+ } else {
+ str.setAsk(list.get(12).toString());
+ }
+
+ if (list.get(13) == null) {
+ str.setPrice(null);
+ } else {
+ str.setPrice((list.get(13).toString()));
+ }
+
+ if (list.get(14) == null) {
+ str.setManHour(null);
+ } else {
+ str.setManHour(list.get(14).toString());
+ }
+
+ StandardTemplate standTempIdByName = standardTemplateService.getStandTempIdByName(String.valueOf(list.get(21)));
+ if (standTempIdByName != null) {
+ str.setTemplateId(standTempIdByName.getId());
+ } else {
+ throw new BaseException("妯℃澘涓嶅瓨鍦細" + list.get(21));
+ }
+ str.setFactory("涓ぉ绉戞妧妫�娴嬩腑蹇�");
+ str.setLaboratory(laboratory.get());
+ str.setState(1);
+ str.setTree(str.getFactory() + " - " + str.getLaboratory() + " - " + str.getSampleType() + " - " + str.getSample() + " - " + (str.getModel() == null ? "" : str.getModel()));
+ try {
+ str.setStructureItemParameterId(standardTreeMapper.getStructureItemParameterId("\"" + str.getSampleType() + "\"", str.getInspectionItem(), str.getInspectionItemSubclass(), str.getInspectionItemClass()));
+ } catch (Exception e) {
+ str.setStructureItemParameterId(standardTreeMapper.getStructureItemParameterId("\"" + str.getSampleType() + "\",\"" + str.getSample() + "\"", str.getInspectionItem(), str.getInspectionItemSubclass(), str.getInspectionItemClass()));
+ }
+ if (str.getStructureItemParameterId() == null) {
+ throw new BaseException("妫�楠岄」鐩笉瀛樺湪锛�" + str.getInspectionItem() + " " + str.getInspectionItemSubclass());
+ }
+ lists.add(str);
+ }
+ });
+ lists.forEach(a -> {
+ if (a.getId() != null) {
+ standardProductListMapper.updateById(a);
+ } else {
+ standardProductListMapper.insert(a);
+ }
+ });
+ }
+
+ @Override
+ public void importWorkstationExcel(MultipartFile file) {
+ InputStream inputStream;
+ try {
+ inputStream = file.getInputStream();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ List<StandardProductList> lists = new ArrayList<>();
+ AtomicReference<String> laboratory = new AtomicReference<>();
+ ExcelUtil.readBySax(inputStream, 0, (i, l, list) -> {
+ StandardProductList str = new StandardProductList();
+ if (i == 0 && l == 1) {
+ laboratory.set(standardTreeMapper.getLaboratory(list.get(1) + ""));
+ if (laboratory.get() == null) {
+ throw new BaseException("妫�楠屽璞′笉瀛樺湪锛�" + list.get(1));
+ }
+ }
+ if (i == 0 && l >= 1) {
+ Integer standardMethodId = standardMethodListService.getStandardMethodId(list.get(0) + "");
+ if (standardMethodId == null) {
+ throw new BaseException("鏍囧噯缂栧彿涓嶅瓨鍦細" + list.get(0));
+ }
+ str.setStandardMethodListId(standardMethodId);
+ str.setSampleType(list.get(1) + "");
+ if (list.get(2) != null) {
+ String sample = baseMapper.selSample(list.get(2) + "");
+ if (sample == null) {
+ throw new BaseException("鏍峰搧涓嶅瓨鍦細" + list.get(2));
+ }
+ str.setSample(list.get(2) + "");
+ } else {
+ str.setSample(null);
+ }
+ if (list.get(3) != null) {
+ str.setModel(list.get(3) + "");
+ Long aLong = standardTreeMapper.selectCount(Wrappers.<StandardTree>lambdaQuery()
+ .eq(StandardTree::getModel, str.getModel())
+ .eq(StandardTree::getSampleType, list.get(1) + ""));
+ if (aLong == 0) {
+ StandardTree standardTree = new StandardTree();
+ standardTree.setFactory("涓ぉ绉戞妧妫�娴嬩腑蹇�");
+ standardTree.setLaboratory(laboratory.get());
+ standardTree.setSampleType(str.getSampleType());
+ standardTree.setSample(str.getSample());
+ standardTree.setModel(str.getModel());
+ standardTreeMapper.insert(standardTree);
+ }
+ } else {
+ str.setModel(null);
+ }
+ str.setInspectionItemClass(list.get(4).toString());
+ str.setInspectionItemClassEn(list.get(5).toString());
+ // 寮�濮嬪姞2
+ str.setInspectionItem(list.get(6) + "");
+ if (list.get(8) == null) {
+ str.setInspectionItemSubclass("");
+ } else {
+ str.setInspectionItemSubclass(list.get(8).toString());
+ }
+ StandardProductList db_str;
+ try {
+ db_str = standardProductListMapper.getOne(str.getStandardMethodListId(), str.getInspectionItem(), str.getSample(), str.getInspectionItemSubclass(), str.getModel(), str.getInspectionItemClass());
+ } catch (Exception e) {
+ throw new BaseException("閲嶅鏌ヨ锛�" + str.getInspectionItem() + " " + str.getInspectionItemSubclass());
+ }
+ if (ObjectUtils.isNotEmpty(db_str)) {
+ str.setId(db_str.getId());
+ str.setStructureItemParameterId(db_str.getStructureItemParameterId());
+ }
+ if (list.get(10) != null) {
+ str.setMethodS(list.get(10) + "");
+ }
+ if (list.get(13) == null) {
+ str.setTell(null);
+ } else {
+ str.setTell(list.get(13).toString());
+ }
+
+ if (list.get(14) == null) {
+ str.setAsk(null);
+ } else {
+ str.setAsk(list.get(14).toString());
+ }
+
+ if (list.get(15) == null) {
+ str.setPrice(null);
+ } else {
+ str.setPrice((list.get(15).toString()));
+ }
+
+ if (list.get(16) == null) {
+ str.setManHour(null);
+ } else {
+ str.setManHour(list.get(16).toString());
+ }
+
+ StandardTemplate standTempIdByName = standardTemplateService.getStandTempIdByName(String.valueOf(list.get(23)));
+ if (standTempIdByName != null) {
+ str.setTemplateId(standTempIdByName.getId());
+ } else {
+ throw new BaseException("妯℃澘涓嶅瓨鍦細" + list.get(23));
+ }
+ str.setFactory("涓ぉ绉戞妧妫�娴嬩腑蹇�");
+ str.setLaboratory(laboratory.get());
+ str.setState(1);
+ str.setTree(str.getFactory() + " - " + str.getLaboratory() + " - " + str.getSampleType() + " - " + str.getSample() + " - " + (str.getModel() == null ? "" : str.getModel()));
+ try {
+ str.setStructureItemParameterId(standardTreeMapper.getStructureItemParameterId("\"" + str.getSampleType() + "\"", str.getInspectionItem(), str.getInspectionItemSubclass(), str.getInspectionItemClass()));
+ } catch (Exception e) {
+ str.setStructureItemParameterId(standardTreeMapper.getStructureItemParameterId("\"" + str.getSampleType() + "\",\"" + str.getSample() + "\"", str.getInspectionItem(), str.getInspectionItemSubclass(), str.getInspectionItemClass()));
+ }
+ if (str.getStructureItemParameterId() == null) {
+ throw new BaseException("妫�楠岄」鐩笉瀛樺湪锛�" + str.getInspectionItem() + " " + str.getInspectionItemSubclass());
+ }
+ lists.add(str);
+ }
+ });
+ lists.forEach(a -> {
+ if (a.getId() != null) {
+ standardProductListMapper.updateById(a);
+ } else {
+ standardProductListMapper.insert(a);
+ }
+ });
+ }
+
+ @Override
+ public boolean updateTreeSort(List<FactoryDto> list) {
+ List<StructureTestObject> testObjects = new ArrayList<>();
+ for (FactoryDto factoryDto : list) {
+ for (LaboratoryDto laboratoryDto : factoryDto.getChildren()) {
+ List<SampleTypeDto> children = laboratoryDto.getChildren();
+ int sort = 0;
+ // 寰幆绗笁灞�
+ for (SampleTypeDto child : children) {
+ StructureTestObject structureTestObject = new StructureTestObject();
+ structureTestObject.setSort(sort);
+ structureTestObject.setId(child.getSampleTypeId());
+ testObjects.add(structureTestObject);
+ sort++;
+ }
+ }
+ }
+ structureTestObjectService.updateBatchById(testObjects);
+
+ return true;
+ }
+
+ /**
+ * 淇敼鏍囧噯鏁�
+ * @param standardTree
+ * @return
+ */
+ @Override
+ public int updateStandardTree(StandardTree standardTree) {
+ // 淇敼鍚嶇О鍖归厤鐨勬爣鍑嗘爲涓嬬殑妫�楠岄」鐩�
+ // 鏌ヨ鎵�鏈夊璞�+鍚嶇О鐨勬爲
+
+ List<StandardProductList> standardProductLists = standardProductListService.list(Wrappers.<StandardProductList>lambdaUpdate()
+ .eq(StandardProductList::getSample, standardTree.getSample())
+ .eq(StandardProductList::getSampleType, standardTree.getSampleType())
+ .eq(StandardProductList::getModel, standardTree.getOldModel()));
+ if (CollectionUtils.isNotEmpty(standardProductLists)) {
+ for (StandardProductList standardProductList : standardProductLists) {
+ // 淇敼鏍峰搧鍚嶇О
+ standardProductList.setModel(standardTree.getModel());
+ // 淇敼鏍戝悕绉�
+ // 闇�瑕佹埅鍙栫鍥涚骇, 閬垮厤涓夊洓绾у悕绉颁竴鏍蜂慨鏀归敊璇�
+ String[] trees = standardProductList.getTree().split(" - ");
+ trees[4] = standardTree.getModel();
+ List<String> list = CollUtil.newArrayList(trees);
+ String newName = CollUtil.join(list, " - ");
+ standardProductList.setTree(newName);
+ }
+ standardProductListService.updateBatchById(standardProductLists);
+ }
+
+ // 淇敼鏍囧噯鏁版楠岄」鐩�
+ LambdaUpdateWrapper<StandardTree> wrapper = Wrappers.<StandardTree>lambdaUpdate()
+ .eq(StandardTree::getFactory, standardTree.getFactory())
+ .eq(StandardTree::getLaboratory, standardTree.getLaboratory())
+ .eq(StandardTree::getSampleType, standardTree.getSampleType())
+ .eq(StandardTree::getModel, standardTree.getOldModel())
+ .set(StandardTree::getModel, standardTree.getModel());
+ if (StringUtils.isNotBlank(standardTree.getSample())) {
+ wrapper.eq(StandardTree::getSample, standardTree.getSample());
+ }
+ return standardTreeMapper.update(null, wrapper);
+ }
+
+ @Override
+ public void resetTreeOfPrice(String tree, Integer standardId) {
+ standardProductListMapper.update(null, Wrappers.<StandardProductList>lambdaUpdate().like(StandardProductList::getTree, tree).eq(StandardProductList::getStandardMethodListId, standardId).set(StandardProductList::getPrice, null));
+ }
+
+ @Override
+ public void resetTreeOfHour(String tree, Integer standardId) {
+ standardProductListMapper.update(null, Wrappers.<StandardProductList>lambdaUpdate().like(StandardProductList::getTree, tree).eq(StandardProductList::getStandardMethodListId, standardId).set(StandardProductList::getManHour, null));
+ }
+
+ @Override
+ public void resetTreeOfAsk(String tree, Integer standardId) {
+ standardProductListMapper.update(null, Wrappers.<StandardProductList>lambdaUpdate().like(StandardProductList::getTree, tree).eq(StandardProductList::getStandardMethodListId, standardId)
+ .set(StandardProductList::getAsk, null)
+ .set(StandardProductList::getTell, null)
+ .set(StandardProductList::getSection, null)
+ .set(StandardProductList::getCores, null)
+ .set(StandardProductList::getConductorMaterial, null)
+ .set(StandardProductList::getConductorType, null)
+ .set(StandardProductList::getPrice, null)
+ .set(StandardProductList::getManHour, null));
+ }
+
+}
+
+
+
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureItemParameterServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureItemParameterServiceImpl.java
new file mode 100644
index 0000000..4009106
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureItemParameterServiceImpl.java
@@ -0,0 +1,24 @@
+package com.ruoyi.basic.service.impl;
+
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.mapper.StructureItemParameterMapper;
+import com.ruoyi.basic.pojo.StructureItemParameter;
+import com.ruoyi.basic.service.StructureItemParameterService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+
+@Service
+@AllArgsConstructor
+public class StructureItemParameterServiceImpl extends ServiceImpl<StructureItemParameterMapper, StructureItemParameter> implements StructureItemParameterService {
+
+ @Resource
+ private StructureItemParameterMapper structureItemParameterMapper;
+
+ @Override
+ public void removeNoSample(String sample) {
+ structureItemParameterMapper.removeNoSample("\""+sample+"\"");
+ }
+}
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectPartServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectPartServiceImpl.java
new file mode 100644
index 0000000..819ef16
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectPartServiceImpl.java
@@ -0,0 +1,75 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.basic.mapper.ProductPartMapper;
+import com.ruoyi.basic.mapper.StructureTestObjectPartMapper;
+import com.ruoyi.basic.pojo.ProductPart;
+import com.ruoyi.basic.pojo.StructureTestObjectPart;
+import com.ruoyi.basic.service.StructureTestObjectPartService;
+
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 妫�楠屽璞¢浂浠惰〃
+ *
+ * @author zhuo
+ * @since 2024-08-07
+ */
+@Transactional
+@Service
+@AllArgsConstructor
+public class StructureTestObjectPartServiceImpl extends ServiceImpl<StructureTestObjectPartMapper, StructureTestObjectPart> implements StructureTestObjectPartService {
+
+ private ProductPartMapper productPartMapper;
+
+ @Override
+ public IPage<StructureTestObjectPart> selectByTestObjectId(Page page, StructureTestObjectPart structureTestObjectPart) {
+ return baseMapper.selectListByTestObjectId(page, QueryWrappers.queryWrappers(structureTestObjectPart),structureTestObjectPart.getTestObjectId());
+ }
+
+ @Override
+ public void addTestObjectPart(StructureTestObjectPart structureTestObjectPart) {
+ this.isPartNoExist(structureTestObjectPart.getPartNo(), null);
+ if (structureTestObjectPart.getTestObjectId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ baseMapper.insert(structureTestObjectPart);
+ }
+
+ @Override
+ public void updateTestObjectPart(StructureTestObjectPart structureTestObjectPart) {
+ this.isPartNoExist(structureTestObjectPart.getPartNo(), structureTestObjectPart.getId());
+ if (structureTestObjectPart.getTestObjectId() == null) {
+ throw new BaseException("缂哄皯浜у搧瀵硅薄id");
+ }
+ baseMapper.updateById(structureTestObjectPart);
+ }
+
+ // 鍒ゆ柇闆朵欢鍙锋槸鍚﹀瓨鍦�
+ public void isPartNoExist(String partNo, Integer id) {
+ // 闆朵欢鍙峰敮涓� 浣嗕笉蹇呭~
+ if (StringUtils.isNotBlank(partNo)) {
+ Long count = productPartMapper.selectCount(new LambdaQueryWrapper<ProductPart>()
+ .eq(ProductPart::getPartNo, partNo));
+ Long selectCount = baseMapper.selectCount(Wrappers.<StructureTestObjectPart>lambdaQuery()
+ .eq(StructureTestObjectPart::getPartNo, partNo)
+ .ne(id != null, StructureTestObjectPart::getId, id));
+ if (count > 0 || selectCount > 0) {
+ throw new BaseException("璇ラ浂浠跺彿宸茬粦瀹氳繃妫�楠屽璞�");
+ }
+ } else {
+ throw new BaseException("璇疯緭鍏ラ浂浠跺彿");
+ }
+ }
+}
+
diff --git a/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectServiceImpl.java b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectServiceImpl.java
new file mode 100644
index 0000000..60f0f40
--- /dev/null
+++ b/basic-server/src/main/java/com/ruoyi/basic/service/impl/StructureTestObjectServiceImpl.java
@@ -0,0 +1,19 @@
+package com.ruoyi.basic.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.basic.mapper.StructureTestObjectMapper;
+import com.ruoyi.basic.pojo.StructureTestObject;
+import com.ruoyi.basic.service.StructureTestObjectService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 妫�娴嬪璞�
+ *
+ * @author zhuo
+ * @since 2024-09-13
+ */
+@Service
+public class StructureTestObjectServiceImpl extends ServiceImpl<StructureTestObjectMapper, StructureTestObject> implements StructureTestObjectService {
+
+}
+
diff --git a/basic-server/src/main/resources/mapper/CertificationMapper.xml b/basic-server/src/main/resources/mapper/CertificationMapper.xml
new file mode 100644
index 0000000..4926d05
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/CertificationMapper.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.basic.mapper.CertificationMapper">
+ <select id="getCertificationDetail" resultType="com.ruoyi.basic.pojo.Certification">
+ select b.*
+ from ( select a.`name`, a.`code`,a.organization,a.explanation,a.first_issuance_date,a.latest_issuance_date,c.expire_time FROM
+ (SELECT id,name,MIN(date_of_issuance) AS first_issuance_date,
+ MAX(date_of_issuance) AS latest_issuance_date,
+ c.`code`,c.organization,c.explanation
+ FROM
+ certification c
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ GROUP BY
+ name) a left join certification c on a.id=c.id
+ ) b
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/IfsInventoryQuantityMapper.xml b/basic-server/src/main/resources/mapper/IfsInventoryQuantityMapper.xml
new file mode 100644
index 0000000..2b615be
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/IfsInventoryQuantityMapper.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.basic.mapper.IfsInventoryQuantityMapper">
+
+ <select id="printLabel" resultType="com.ruoyi.basic.dto.IfsInventoryQuantityDto">
+ SELECT io.sample sample_name,
+ iiq.supplier_name,
+ io.part_detail part_desc,
+ io.send_time,
+ io.prepare_user,
+ io.entrust_code,
+ iiq.qty_arrived,
+ iiq.buy_unit_meas,
+ CASE
+ WHEN pp.color IS NOT NULL
+ THEN pp.color
+ ELSE sto.color
+ END color,
+ case
+ when iiq.state = 2 then '2'
+ when iiq.state = 1 then case
+ when ROUND((select count(*)
+ from ins_product ip
+ where state = 1
+ and ins_result is not null
+ and ip.ins_sample_id in (select id
+ from ins_sample
+ where ins_sample.ins_order_id = io.id)) /
+ (select count(*)
+ from ins_product ip2
+ where state = 1
+ and ip2.ins_sample_id in
+ (select id from ins_sample where ins_sample.ins_order_id = io.id)) *
+ 100, 2) != 100 then '0'
+ else '1' end
+ end labelStatus,
+ JSON_OBJECT(
+ 'sample_ame', io.sample,
+ 'supplier_name', iiq.supplier_name,
+ 'part_desc', iiq.part_desc,
+ 'entrust_code', io.entrust_code
+ ) labelBarCode
+ FROM ifs_inventory_quantity iiq
+ LEFT JOIN ins_order io on io.id = (SELECT io2.id
+ FROM ins_order io2
+ WHERE io2.ifs_inventory_id = iiq.id
+ and io2.state != -1
+ order by io2.send_time desc
+ limit 1) COLLATE utf8mb4_general_ci
+ LEFT JOIN product_part pp ON pp.part_no = iiq.part_no COLLATE utf8mb4_general_ci
+ LEFT JOIN structure_test_object_part sto ON sto.part_no = iiq.part_no COLLATE utf8mb4_general_ci
+ WHERE iiq.id in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </select>
+ <select id="selectReportCountById" resultType="java.lang.Integer">
+ select count(*)
+ from ifs_inventory_quantity iiq
+ left join ins_order io on io.ifs_inventory_id = iiq.id and io.state
+ left join ins_report ir on ir.ins_order_id = io.id
+ where iiq.id = #{ifsInventoryId}
+ and ir.id is not null
+ </select>
+ <select id="selectIsFirst" resultType="java.lang.Integer">
+ select count(*)
+ from ifs_inventory_quantity iiq
+ LEFT JOIN ins_order io1 on io1.ifs_inventory_id = iiq.id
+ and io1.state != -1
+ where io1.part_detail = #{partDetail}
+ and iiq.supplier_name = #{supplierName}
+ and iiq.receiver_date between #{startOfNextQuarter} and #{endOfQuarter}
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/LaboratoryMapper.xml b/basic-server/src/main/resources/mapper/LaboratoryMapper.xml
new file mode 100644
index 0000000..c3ab2b4
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/LaboratoryMapper.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.LaboratoryMapper">
+
+ <select id="selectItemParameter" resultType="com.ruoyi.basic.pojo.Laboratory">
+ select * from
+ (
+ select l.id,
+ laboratory_name,
+ laboratory_number,
+ laboratory_code,
+ phone_number,
+ head,
+ l.address,
+ u1.name create_user_name,
+ l.create_time
+ from laboratory l
+ left join user u1 on l.create_user = u1.id
+ ) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+
+ <select id="obtainItemParameterList" resultType="java.lang.Object">
+ select * from
+ (
+ select l.id,
+ laboratory_name,
+ laboratory_number,
+ phone_number,
+ head,
+ l.address,
+ u1.name create_user_name,
+ l.create_time
+ from laboratory l
+ left join user u1 on l.create_user = u1.id
+ ) a
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/ProductMapper.xml b/basic-server/src/main/resources/mapper/ProductMapper.xml
new file mode 100644
index 0000000..a13b18d
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/ProductMapper.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.ProductMapper">
+
+ <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.Product">
+ <id property="id" column="id" jdbcType="INTEGER"/>
+ <result property="name" column="name" jdbcType="VARCHAR"/>
+ <result property="nameEn" column="name_en" jdbcType="VARCHAR"/>
+ <result property="createUser" column="create_user" jdbcType="INTEGER"/>
+ <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
+ <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+ <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+ <result property="objectId" column="object_id" jdbcType="INTEGER"/>
+ </resultMap>
+
+ <sql id="Base_Column_List">
+ id,name,name_en,
+ create_user,update_user,create_time,
+ update_time,object_id
+ </sql>
+ <select id="selectProductListByObjectId" resultType="com.ruoyi.basic.pojo.Product">
+ select * from (
+ select p.id,
+ p.name,
+ p.name_en,
+ p.create_user,
+ p.update_user,
+ p.create_time,
+ p.update_time,
+ p.object_id
+ from product p
+ WHERE 1=1
+ <if test="partNo != null and partNo != ''">
+ and p.id = (select pp.product_id
+ from product_part pp
+ where pp.part_no = #{partNo})
+ </if>) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/ProductPartMapper.xml b/basic-server/src/main/resources/mapper/ProductPartMapper.xml
new file mode 100644
index 0000000..f883d3c
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/ProductPartMapper.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.ProductPartMapper">
+ <select id="selectListByProductId" resultType="com.ruoyi.basic.pojo.ProductPart">
+ SELECT * from product_part pp
+ where pp.product_id=#{productId}
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/ProductSupplierDensityMapper.xml b/basic-server/src/main/resources/mapper/ProductSupplierDensityMapper.xml
new file mode 100644
index 0000000..4f47e62
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/ProductSupplierDensityMapper.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.basic.mapper.ProductSupplierDensityMapper">
+ <select id="selectListByProductId" resultType="com.ruoyi.basic.pojo.ProductSupplierDensity">
+ SELECT * from product_supplier_density pp
+ where pp.product_id=#{productId}
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/SealMapper.xml b/basic-server/src/main/resources/mapper/SealMapper.xml
new file mode 100644
index 0000000..5cb3595
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/SealMapper.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.SealMapper">
+ <select id="selectSeal" resultType="com.ruoyi.basic.pojo.Seal">
+ select l.id,s.lab_id,l.laboratory_name ,s.address, s.type as Type,s.create_time
+ from seal s LEFT JOIN laboratory l on s.lab_id=l.id
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+
+ </select>
+ <select id="selectLaboratory" resultType="com.ruoyi.basic.pojo.Laboratory">
+ SELECT *
+ from laboratory
+ WHERE id = #{labId}
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StandardMethodListMapper.xml b/basic-server/src/main/resources/mapper/StandardMethodListMapper.xml
new file mode 100644
index 0000000..957fd1f
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StandardMethodListMapper.xml
@@ -0,0 +1,99 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.StandardMethodListMapper">
+
+ <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StandardMethodList">
+ <id property="id" column="id" jdbcType="INTEGER"/>
+ <result property="code" column="code" jdbcType="VARCHAR"/>
+ <result property="name" column="name" jdbcType="VARCHAR"/>
+ <result property="remark" column="remark" jdbcType="VARCHAR"/>
+ <result property="createUser" column="create_user" jdbcType="INTEGER"/>
+ <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+ <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
+ <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+ </resultMap>
+
+ <select id="selectStandardMethodById" resultType="java.util.Map">
+ select code, name, remark
+ from standard_method
+ where id = #{id}
+ </select>
+ <select id="selectUserById" resultType="java.lang.String">
+ select name
+ from user
+ where id = #{id}
+ </select>
+ <select id="selectStandardMethodLists" resultType="com.ruoyi.basic.pojo.StandardMethodList">
+ select id, code, name, remark
+ from standard_method
+ where is_use = 1
+ and is_product = 1
+ and structure_test_object_id LIKE CONCAT('%[', #{tree}, ']%')
+ </select>
+ <select id="selectParameterList" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select inspection_item,
+ inspection_item_subclass,
+ laboratory,
+ unit,
+ price,
+ man_hour,
+ man_hour_group,
+ inspection_item_type,
+ inspection_value_type,
+ checkout_number,
+ section,
+ method,
+ man_day,
+ bsm,
+ template_id,
+ son_laboratory
+ from structure_item_parameter
+ where method = #{code}
+ </select>
+ <select id="selectStandardMethodLists2" resultType="com.ruoyi.basic.pojo.StandardMethodList">
+ select sml.id, sml.code, sml.name,sml.remark, sml.create_time, u.name create_user_name
+ from standard_method_list sml
+ left join user u on u.id = sml.create_user
+ where factory = #{data1}
+ <if test="data2 != null">
+ and laboratory = #{data2}
+ </if>
+ <if test="data3 != null">
+ and sample_type = #{data3}
+ </if>
+ <if test="data4 != null">
+ and sample = #{data4}
+ </if>
+ <if test="data5 != null">
+ and model = #{data5}
+ </if>
+ </select>
+ <select id="selectStandardMethodLists3" resultType="com.ruoyi.basic.pojo.StandardMethodList">
+ select id, code, name, remark
+ from standard_method
+ where is_use = 1
+ and is_product = 1
+ and structure_test_object_id LIKE CONCAT('%', #{tree}, '%')
+ </select>
+ <select id="selectListEnum" resultType="com.ruoyi.basic.pojo.StandardMethodList">
+ select id,code,name from standard_method
+ where is_product = 1
+ and is_use = 1
+ </select>
+ <select id="selectStandardMethodListsByNull" resultType="com.ruoyi.basic.pojo.StandardMethodList">
+ select id, code, name, remark
+ from standard_method
+ where is_use = 1
+ and is_product = 1
+ and (
+ structure_test_object_id is null
+ OR structure_test_object_id = ''
+ OR structure_test_object_id = '[]'
+ )
+ </select>
+ <select id="getStandardMethodId" resultType="java.lang.Integer">
+ select id from standard_method where code = #{code}
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StandardMethodMapper.xml b/basic-server/src/main/resources/mapper/StandardMethodMapper.xml
new file mode 100644
index 0000000..739d2d4
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StandardMethodMapper.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.StandardMethodMapper">
+
+ <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StandardMethod">
+ <id property="id" column="id" jdbcType="INTEGER"/>
+ <result property="code" column="code" jdbcType="VARCHAR"/>
+ <result property="name" column="name" jdbcType="VARCHAR"/>
+ <result property="remark" column="remark" jdbcType="VARCHAR"/>
+ <result property="createUser" column="create_user" jdbcType="INTEGER"/>
+ <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+ <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
+ <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+ </resultMap>
+
+ <select id="selectStandardMethodList" resultType="com.ruoyi.basic.pojo.StandardMethod">
+ select * from (
+ select sm.id,
+ sm.code,
+ sm.name,
+ sm.structure_test_object_id,
+ sto.specimen_name sample_type,
+ sm.remark,
+ u1.name create_user_name,
+ sm.create_time,
+ u2.name update_user_name,
+ sm.update_time,
+ sm.is_product,
+ sm.field,
+ sm.name_en,
+ sm.is_use,
+ sm.qualification_id
+ from standard_method sm
+ left join user u1 on sm.create_user = u1.id
+ left join user u2 on sm.update_user = u2.id
+ left join structure_test_object sto on sm.structure_test_object_id = sto.id
+ where sm.code != '鎶�鏈姹�'
+ ) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="selectStandMethodById" resultType="com.ruoyi.basic.pojo.StandardMethod">
+ select sm.id,
+ sm.code,
+ sm.name,
+ sm.structure_test_object_id,
+ sto.specimen_name sample_type,
+ sm.remark,
+ u1.name create_user_name,
+ sm.create_time,
+ u2.name update_user_name,
+ sm.update_time,
+ sm.is_product,
+ sm.field,
+ sm.name_en,
+ sm.is_use,
+ sm.qualification_id
+ from standard_method sm
+ left join user u1 on sm.create_user = u1.id
+ left join user u2 on sm.update_user = u2.id
+ left join structure_test_object sto on sm.structure_test_object_id = sto.id
+ where sm.id = #{id}
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StandardProductListMapper.xml b/basic-server/src/main/resources/mapper/StandardProductListMapper.xml
new file mode 100644
index 0000000..52d6bfe
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StandardProductListMapper.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.StandardProductListMapper">
+
+ <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StandardProductList">
+ <id property="id" column="id" jdbcType="INTEGER"/>
+ <result property="inspectionItem" column="inspection_item" jdbcType="VARCHAR"/>
+ <result property="inspectionItemSubclass" column="inspection_item_subclass" jdbcType="VARCHAR"/>
+ <result property="laboratory" column="laboratory" jdbcType="VARCHAR"/>
+ <result property="unit" column="unit" jdbcType="VARCHAR"/>
+ <result property="price" column="price" jdbcType="DECIMAL"/>
+ <result property="manHour" column="man_hour" jdbcType="INTEGER"/>
+ <result property="manHourGroup" column="man_hour_group" jdbcType="VARCHAR"/>
+ <result property="inspectionItemType" column="inspection_item_type" jdbcType="VARCHAR"/>
+ <result property="inspectionValueType" column="inspection_value_type" jdbcType="VARCHAR"/>
+ <result property="checkoutNumber" column="checkout_number" jdbcType="INTEGER"/>
+ <result property="section" column="section" jdbcType="VARCHAR"/>
+ <result property="method" column="method" jdbcType="VARCHAR"/>
+ <result property="manDay" column="man_day" jdbcType="INTEGER"/>
+ <result property="bsm" column="bsm" jdbcType="VARCHAR"/>
+ <result property="ask" column="ask" jdbcType="VARCHAR"/>
+ <result property="standardMethodListId" column="standard_method_list_id" jdbcType="INTEGER"/>
+ <result property="createUser" column="create_user" jdbcType="INTEGER"/>
+ <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
+ <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+ <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+ </resultMap>
+ <update id="updateSection">
+ UPDATE standard_product_list
+ SET price=#{productList.price},
+ man_hour=#{productList.manHour},
+ section=#{productList.section},
+ cores=#{productList.cores},
+ conductor_material=#{productList.conductorMaterial},
+ conductor_type=#{productList.conductorType},
+ ask=#{productList.ask},
+ tell=#{productList.tell},
+ update_user=#{productList.updateUser},
+ update_time=#{productList.updateTime}
+ WHERE id = #{productList.id}
+ </update>
+ <update id="updateSortUp">
+ update standard_product_list
+ set sort = sort - 1
+ where tree = #{tree}
+ and standard_method_list_id = #{methodId}
+ and sort between #{beginIndex} + 1 and #{endIndex}
+ </update>
+ <update id="updateSortDown">
+ update standard_product_list
+ set sort = sort + 1
+ where tree = #{tree}
+ and standard_method_list_id = #{methodId}
+ and sort between #{endIndex} and #{beginIndex} - 1
+ </update>
+ <select id="standardProductListIPage" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select spl.* from standard_product_list spl
+ left join product p on spl.sample = p.name
+ where standard_method_list_id = #{id}
+ and tree like concat('%',#{tree},'%')
+ <if test="laboratory != ''">
+ and son_laboratory = #{laboratory}
+ </if>
+ <if test="insItem != ''">
+ and inspection_item = #{insItem}
+ </if>
+ <if test="insItems != ''">
+ and inspection_item_subclass = #{insItems}
+ </if>
+ order by p.id
+ group by spl.id
+ </select>
+ <select id="getOne" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select * from standard_product_list
+ where standard_method_list_id = #{standardMethodListId}
+ and inspection_item = #{inspectionItem}
+ <if test="sample!=null">
+ and sample = #{sample}
+ </if>
+ <if test="inspectionItemSubclass!=null">
+ and inspection_item_subclass = #{inspectionItemSubclass}
+ </if>
+ <if test="inspectionItemSubclass == null">
+ and (inspection_item_subclass is null or inspection_item_subclass = '')
+ </if>
+ <if test="model!=null">
+ and model = #{model}
+ </if>
+ <if test="inspectionItemClass != null and inspectionItemClass != ''">
+ and inspection_item_class = #{inspectionItemClass}
+ </if>
+ </select>
+ <select id="selectDetail" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select * from standard_product_list
+ where standard_method_list_id = #{standardMethodListId}
+ and state =#{state}
+ and model=#{model}
+ <if test="isCableTag != null and isCableTag != ''">
+ and (inspection_item_class like concat('%缁撴瀯灏哄%') or
+ inspection_item_class like concat('%鐢电紗鐢垫�ц兘%')or
+ inspection_item_class like concat('%缁濈紭%')or
+ inspection_item_class like concat('%鐢电紗鐕冪儳鎬ц兘%'))
+ </if>
+ order by sort asc,
+ case when man_hour_group is NULL then 1
+ when man_hour_group ='' then 1 else 0 end,
+ CASE
+ WHEN man_hour_group REGEXP '^[0-9]' THEN CAST(man_hour_group AS UNSIGNED) -- 濡傛灉浠ユ暟瀛楀紑澶达紝鍒欐寜鐓ф暟瀛楀ぇ灏忔帓搴�
+ WHEN man_hour_group REGEXP '[0-9]+' THEN CAST(SUBSTRING(man_hour_group, 2)AS UNSIGNED) END -- 鎻愬彇瀛楁瘝鍚庨潰鐨勬暟瀛楅儴鍒�
+ ,id asc
+ </select>
+ <select id="selectDetail2" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select * from standard_product_list
+ where standard_method_list_id = #{standardMethodListId}
+ and state =#{state}
+ and tree =#{tree}
+ <if test="isCableTag != null and isCableTag != ''">
+ and (inspection_item_class like concat('%缁撴瀯灏哄%') or
+ inspection_item_class like concat('%鐢电紗鐢垫�ц兘%')or
+ inspection_item_class like concat('%缁濈紭%')or
+ inspection_item_class like concat('%鐢电紗鐕冪儳鎬ц兘%'))
+ </if>
+ order by sort asc,
+ case when man_hour_group is NULL then 1
+ when man_hour_group ='' then 1 else 0 end,
+ CASE
+ WHEN man_hour_group REGEXP '^[0-9]' THEN CAST(man_hour_group AS UNSIGNED) -- 濡傛灉浠ユ暟瀛楀紑澶达紝鍒欐寜鐓ф暟瀛楀ぇ灏忔帓搴�
+ WHEN man_hour_group REGEXP '[0-9]+' THEN CAST(SUBSTRING(man_hour_group, 2)AS UNSIGNED) END -- 鎻愬彇瀛楁瘝鍚庨潰鐨勬暟瀛楅儴鍒�
+ ,id asc
+ </select>
+ <select id="selectPartColor" resultType="java.util.Map">
+ select color,
+ color_code
+ from product_part
+ where part_no = #{partNo}
+ union all
+ select color,
+ color_code
+ from structure_test_object_part
+ where part_no = #{partNo}
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StandardProductListSupplierAskMapper.xml b/basic-server/src/main/resources/mapper/StandardProductListSupplierAskMapper.xml
new file mode 100644
index 0000000..9c9c6b1
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StandardProductListSupplierAskMapper.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.basic.mapper.StandardProductListSupplierAskMapper">
+
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StandardTemplateMapper.xml b/basic-server/src/main/resources/mapper/StandardTemplateMapper.xml
new file mode 100644
index 0000000..34a8b0e
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StandardTemplateMapper.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.StandardTemplateMapper">
+
+ <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StandardTemplate">
+ <id property="id" column="id" jdbcType="INTEGER"/>
+ <result property="name" column="name" jdbcType="VARCHAR"/>
+ <result property="remark" column="remark" jdbcType="VARCHAR"/>
+ <result property="thing" column="thing" jdbcType="VARCHAR"/>
+ <result property="createUser" column="create_user" jdbcType="INTEGER"/>
+ <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
+ <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+ <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+ </resultMap>
+
+ <select id="selectStandardTemplatePageList" resultType="com.ruoyi.basic.pojo.StandardTemplate">
+ select * from (
+ select st.id, st.name,st.number, st.remark, u2.name create_user_name, u3.name update_user_name, st.create_time, st.update_time
+ from standard_template st
+ left join user u2 on u2.id = st.create_user
+ left join user u3 on u3.id = st.update_user
+ ) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="getStandTempIdByName" resultType="com.ruoyi.basic.pojo.StandardTemplate">
+ select id from standard_template where name=#{name}
+ </select>
+ <!-- 鏌ヨ鍘嬬缉鍚庣殑鏁版嵁 -->
+ <select id="selectCompressThing" resultType="java.lang.String">
+ SELECT COMPRESS(thing)
+ from standard_template b
+ WHERE id = #{templateId}
+ </select>
+
+
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StandardTreeMapper.xml b/basic-server/src/main/resources/mapper/StandardTreeMapper.xml
new file mode 100644
index 0000000..74ded82
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StandardTreeMapper.xml
@@ -0,0 +1,384 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.StandardTreeMapper">
+ <resultMap id="BaseResultMap" type="com.ruoyi.basic.pojo.StandardTree">
+ <id property="id" column="id" jdbcType="INTEGER"/>
+ <result property="factory" column="factory" jdbcType="VARCHAR"/>
+ <result property="laboratory" column="laboratory" jdbcType="VARCHAR"/>
+ <result property="sampleType" column="sample_type" jdbcType="VARCHAR"/>
+ <result property="sample" column="sample" jdbcType="VARCHAR"/>
+ <result property="model" column="model" jdbcType="VARCHAR"/>
+ <result property="createUser" column="create_user" jdbcType="INTEGER"/>
+ <result property="createTime" column="create_time" jdbcType="TIMESTAMP"/>
+ <result property="updateUser" column="update_user" jdbcType="INTEGER"/>
+ <result property="updateTime" column="update_time" jdbcType="TIMESTAMP"/>
+ </resultMap>
+
+ <resultMap id="FactoryDto" type="com.ruoyi.basic.dto.FactoryDto">
+ <result property="label" column="factory"/>
+ <result property="value" column="factory"/>
+ <collection property="children" resultMap="LaboratoryDto"/>
+ </resultMap>
+
+ <resultMap id="LaboratoryDto" type="com.ruoyi.basic.dto.LaboratoryDto">
+ <result property="label" column="laboratory"/>
+ <result property="value" column="laboratory"/>
+ <collection property="children" resultMap="SampleTypeDto"/>
+ </resultMap>
+
+ <resultMap id="SampleTypeDto" type="com.ruoyi.basic.dto.SampleTypeDto">
+ <result property="label" column="sample_type"/>
+ <result property="value" column="sample_type"/>
+ <result property="sampleTypeId" column="sample_type_id"/>
+ <result property="sort" column="sort"/>
+ <result property="partNo" column="part_no"/>
+ <result property="sampleTypeEn" column="sample_type_en"/>
+ <collection property="children" resultMap="SampleDto"/>
+ </resultMap>
+
+ <resultMap id="SampleDto" type="com.ruoyi.basic.dto.SampleDto">
+ <result property="label" column="sample"/>
+ <result property="value" column="sample"/>
+ <result property="partNo" column="sample_part_no"/>
+ <result property="sampleEn" column="sample_en"/>
+ <collection property="children" resultMap="ModelDto"/>
+ </resultMap>
+
+ <resultMap id="ModelDto" type="com.ruoyi.basic.dto.ModelDto">
+ <result property="label" column="model"/>
+ <result property="value" column="model"/>
+ </resultMap>
+
+ <sql id="selectStandardTree">
+ sample sample2,
+ inspection_item,
+ inspection_item_en,
+ inspection_item_subclass,
+ inspection_item_subclass_en,
+ inspection_item_class,
+ inspection_item_class_en,
+ method,
+ son_laboratory,
+ unit,
+ ask_tell tell,
+ ask,
+ price,
+ man_hour,
+ man_hour_group,
+ man_day,
+ inspection_item_type,
+ inspection_value_type,
+ bsm,
+ template_id,
+ laboratory,
+ checkout_number,
+ section,
+ dic,
+ 0 state,
+ #{model}
+ model,
+ #{sample}
+ sample,
+ #{trees}
+ tree,
+ id
+ structure_item_parameter_id,
+ radius_list,
+ rates
+ </sql>
+
+ <select id="selectStandardTreeList" resultMap="FactoryDto">
+ select '涓ぉ绉戞妧妫�娴嬩腑蹇�' factory,
+ l.laboratory_name laboratory,
+ sto.specimen_name sample_type,
+ p.name sample,
+ st.model,
+ sto.code,
+ sto.id sample_type_id,
+ sto.sort,
+ sto.specimen_name_en sample_type_en,
+ p.name_en sample_en
+ from laboratory l
+ left join structure_test_object sto on sto.laboratory_id = l.id
+ left join product p on p.object_id = sto.id
+ left join standard_tree st on st.sample_type = sto.specimen_name
+ and st.sample = p.name
+ order by l.id, CAST(sto.code AS DECIMAL), p.id, ISNULL(st.id), st.id
+ </select>
+
+ <select id="selectStandardProductById" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select inspection_item,
+ inspection_item_subclass,
+ laboratory,
+ son_laboratory,
+ unit,
+ price,
+ man_hour,
+ man_hour_group,
+ inspection_item_type,
+ inspection_value_type,
+ checkout_number,
+ section,
+ method,
+ man_day,
+ bsm,
+ template_id
+ from structure_item_parameter
+ where id = #{id}
+ </select>
+ <select id="getStandardProductListBySample" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select inspection_item,
+ inspection_item_subclass,
+ laboratory,
+ son_laboratory,
+ unit,
+ price,
+ man_hour,
+ man_hour_group,
+ inspection_item_type,
+ inspection_value_type,
+ checkout_number,
+ section,
+ method,
+ man_day,
+ sample,
+ bsm,
+ template_id,
+ dic,
+ ask,
+ ask_tell as tell
+ from structure_item_parameter sp
+ where sp.sample = #{sampleType}
+ or sp.sample = ''
+ or sp.sample = '[]'
+ </select>
+ <select id="getStandardMethodListBySample" resultType="com.ruoyi.basic.pojo.StandardMethodList">
+ select sm.code,sm.name,sm.remark from standard_method sm
+ left join structure_test_object sto on sm.structure_test_object_id = sto.id
+ where is_use = 1
+ and is_product = 1
+ <if test="sampleType != null">
+ and sto.specimen_name = #{sampleType}
+ </if>
+ </select>
+ <select id="selectStandardTreeList2" resultType="com.ruoyi.basic.pojo.StandardTree">
+ select '涓ぉ绉戞妧妫�娴嬩腑蹇�' factory,
+ l.laboratory_name laboratory,
+ sto.specimen_name sample_type,
+ p.name sample
+ from laboratory l
+ left join structure_test_object sto on sto.laboratory_id = l.id
+ left join product p on p.object_id = sto.id
+ left join standard_tree st on st.laboratory = l.laboratory_name
+ and st.sample_type = sto.specimen_name
+ and st.sample = p.name
+ where sto.specimen_name = #{sampleType}
+ group by sto.specimen_name
+ </select>
+ <select id="selectStandardProductListByTree" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select <include refid="selectStandardTree"/>
+ from structure_item_parameter
+ where (
+ sample is NULL
+ OR sample = ''
+ or sample = '[]'
+ OR sample LIKE CONCAT('%[', #{tree}, ']%')
+ )
+ and (laboratory is null
+ or laboratory = ''
+ or laboratory = #{laboratory})
+ order by inspection_item_class, inspection_item, id asc
+ </select>
+
+ <select id="selectStandardProductListByTree2" resultType="com.ruoyi.basic.pojo.StandardProductList">
+ select <include refid="selectStandardTree"/>
+ from structure_item_parameter
+ where sample LIKE CONCAT('%[', #{tree}, ']%')
+ and (laboratory is null
+ or laboratory = ''
+ or laboratory = #{laboratory})
+ order by inspection_item_class, inspection_item, id asc
+ </select>
+
+ <select id="getStandardTree2" resultMap="SampleTypeDto">
+ select sto.specimen_name sample_type,
+ p.name sample,
+ st.model
+ from structure_test_object sto
+ left join product p on p.object_id = sto.id
+ left join standard_tree st on st.sample_type = sto.specimen_name
+ and st.sample = p.name
+ </select>
+
+ <select id="getStandardTree3" resultType="com.ruoyi.basic.dto.SampleDto">
+ select model label,
+ model value
+ from standard_tree
+ where sample_type = #{sampleType}
+ and sample is null
+ </select>
+
+ <select id="getLaboratory" resultType="java.lang.String">
+ select l.laboratory_name
+ from structure_test_object sto
+ left join laboratory l on sto.laboratory_id = l.id
+ where sto.specimen_name = #{str}
+ </select>
+ <select id="getStructureItemParameterId" resultType="java.lang.Integer">
+ select id from structure_item_parameter
+ where sample like concat('%', #{sampleType}, '%')
+ and inspection_item = #{item}
+ <if test="itemChild != null and itemChild != ''">
+ and inspection_item_subclass = #{itemChild}
+ </if>
+ <if test="inspectionItemClass != null and inspectionItemClass != ''">
+ and inspection_item_class = #{inspectionItemClass}
+ </if>
+ <if test="itemChild == null or itemChild == ''">
+ and (inspection_item_subclass is null or inspection_item_subclass = '')
+ </if>
+ </select>
+ <select id="selectPList" resultType="com.ruoyi.basic.dto.ProductDto">
+ select p.name
+ from structure_test_object sto
+ left join product p on p.object_id = sto.id
+ where sto.specimen_name = #{name}
+ order by p.id
+ </select>
+ <select id="selSample" resultType="java.lang.String">
+ select name
+ from product
+ where name = #{name}
+ </select>
+ <select id="selectStandardTreeListByPartNo" resultMap="FactoryDto">
+ select '涓ぉ绉戞妧妫�娴嬩腑蹇�' factory,
+ l.laboratory_name laboratory,
+ sto.specimen_name sample_type,
+ p.name sample,
+ st.model,
+ CASE
+ WHEN p.id = (SELECT pp.product_id
+ FROM product_part pp
+ WHERE pp.part_no = #{partNo})
+ THEN #{partNo}
+ ELSE NULL
+ END AS sample_part_no,
+ CASE
+ WHEN sto.id = (SELECT sto.test_object_id
+ FROM structure_test_object_part sto
+ WHERE sto.part_no = #{partNo})
+ THEN #{partNo}
+ ELSE NULL
+ END AS part_no
+ from laboratory l
+ left join structure_test_object sto on sto.laboratory_id = l.id
+ left join product p on p.object_id = sto.id
+ left join standard_tree st on st.sample_type = sto.specimen_name
+ and st.sample = p.name
+ where (p.id = (select pp.product_id
+ from product_part pp
+ where pp.part_no = #{partNo})
+ or sto.id = (select sto.test_object_id
+ from structure_test_object_part sto
+ where sto.part_no = #{partNo}))
+ order by l.id, CAST(sto.code AS DECIMAL), p.id, ISNULL(st.id), st.id
+ </select>
+
+ <sql id="getIfsOrder">
+ select *
+ from (SELECT ifs.*,
+ COALESCE(io1.create_user, io2.create_user) create_user,
+ COALESCE(io1.entrust_code, io2.entrust_code) entrust_code,
+ COALESCE(io1.send_time, io2.send_time) send_time,
+ io1.id enter_order_id,
+ ir1.id enter_report_id,
+ ir1.url enter_url,
+ ir1.url_s enter_url_s,
+ io2.id quarter_order_id,
+ ir2.id quarter_report_id,
+ ir2.url quarter_url,
+ ir2.url_s quarter_url_s,
+ group_concat(distinct isa.sample_code, ' ') sample_code,
+ group_concat(distinct isa.sample, ' ') sample_name,
+ group_concat(distinct isa.model, ' ') sample_model,
+ COALESCE(io1.state, io2.state) order_state,
+ COALESCE(isu.userName, COALESCE(u1.name, u2.name)) user_name,
+ group_concat(distinct iuh.unqualified_desc, ' ') unqualified_desc,
+ io1.is_exemption
+ FROM ifs_inventory_quantity ifs
+ LEFT JOIN ins_order io1 ON io1.ifs_inventory_id = ifs.id and io1.order_type = '杩涘巶妫�楠�' and io1.state != -1
+ left join ins_report ir1 on io1.id = ir1.ins_order_id
+ left join user u1 on io1.create_user = u1.id
+ LEFT JOIN ins_order io2 ON io2.ifs_inventory_id = ifs.id and io2.order_type = 'Quarterly inspection' and io2.state != -1
+ left join ins_report ir2 on io2.id = ir2.ins_order_id
+ left join user u2 on io2.create_user = u2.id
+ LEFT JOIN ins_sample isa ON COALESCE(io1.id, io2.id) = isa.ins_order_id
+ LEFT JOIN (SELECT ins_sample_id, GROUP_CONCAT(DISTINCT uu.name SEPARATOR ',') AS userName
+ FROM ins_sample_user u
+ LEFT JOIN user uu ON u.user_id = uu.id
+ WHERE u.state = 0
+ GROUP BY ins_sample_id
+ ORDER BY ins_sample_id) isu ON isu.ins_sample_id = COALESCE(io1.id, io2.id)
+ left join ins_unqualified_handler iuh on iuh.inventory_quantity_id = ifs.id
+ group by ifs.id) a
+ </sql>
+
+ <select id="getIfsByStateOne" resultType="com.ruoyi.basic.dto.IfsInventoryQuantityDto">
+ <include refid="getIfsOrder"/>
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+
+ <select id="selectIfsPage" resultType="com.ruoyi.basic.pojo.IfsInventoryQuantity">
+ SELECT * from ifs_inventory_quantity ifs
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="selectIfsInventoryQuantity" resultType="com.ruoyi.basic.dto.IfsInventoryQuantityCheckDto">
+ SELECT * from ifs_inventory_quantity ifs
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="getIfsByOver" resultType="com.ruoyi.basic.dto.IfsInventoryQuantitySupplierDto">
+ select * from (<include refid="getIfsOrder"/>
+ <where>
+ <if test="beginDeclareDate != null and beginDeclareDate != '' and endDeclareDate != null and endDeclareDate != ''">
+ send_time between #{beginDeclareDate} and #{endDeclareDate}
+ </if>
+ </where>
+ ) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="getIfsByOverList" resultType="com.ruoyi.basic.dto.IfsInventoryQuantitySupplierDto">
+ select * from (<include refid="getIfsOrder"/>
+ <where>
+ <if test="beginDeclareDate != null and beginDeclareDate != '' and endDeclareDate != null and endDeclareDate != ''">
+ send_time between #{beginDeclareDate} and #{endDeclareDate}
+ </if>
+ </where>
+ ) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="getIfsByQuarter" resultType="com.ruoyi.basic.dto.IfsInventoryQuantitySupplierDto">
+ select * from (<include refid="getIfsOrder"/>
+ <where>
+ and (quarter_order_id is not null)
+ <if test="beginDeclareDate != null and beginDeclareDate != '' and endDeclareDate != null and endDeclareDate != ''">
+ and send_time between #{beginDeclareDate} and #{endDeclareDate}
+ </if>
+ </where>
+ ) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StructureItemParameterMapper.xml b/basic-server/src/main/resources/mapper/StructureItemParameterMapper.xml
new file mode 100644
index 0000000..fd67dfc
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StructureItemParameterMapper.xml
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.StructureItemParameterMapper">
+ <delete id="removeNoSample">
+ delete
+ from structure_item_parameter
+ where sample like concat('%', #{sample}, '%')
+ </delete>
+ <select id="selectItemParameterList" resultType="com.ruoyi.basic.pojo.StructureItemParameter">
+ select * from (select A.id,
+ inspection_item,
+ inspection_item_en,
+ inspection_item_subclass,
+ inspection_item_subclass_en,
+ laboratory,
+ unit,
+ price,
+ man_hour,
+ man_hour_group,
+ inspection_item_type,
+ checkout_number,
+ section,
+ A.create_user,
+ A.update_user,
+ A.create_time,
+ A.update_time,
+ method,
+ man_day,
+ bsm,
+ sample,
+ inspection_value_type,
+ dic,
+ template_id,
+ son_laboratory,
+ ask,
+ ask_tell,
+ inspection_item_class,
+ inspection_item_class_en,
+ code,
+ radius_list,
+ rates
+ from (select *,
+ CASE
+ WHEN INSTR(sample, ',') > 0 THEN
+ SUBSTRING_INDEX(SUBSTRING_INDEX(sample, '","', 1), '"', -1)
+ when sample = '[""]' then null
+ when sample = '[]' then null
+ ELSE
+ TRIM(BOTH '["]' FROM SUBSTRING_INDEX(REPLACE(sample, '[["', ''), '"]]', 1))
+ END AS samples
+ from structure_item_parameter) A
+ left join structure_test_object sto on samples = specimen_name
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>)B
+ order by CASE
+ WHEN code IS NULL THEN 1
+ ELSE 0
+ END,
+ CAST(code AS UNSIGNED),
+ case when man_hour_group is NULL then 1
+ when man_hour_group ='' then 1 else 0 end,
+ CASE
+ WHEN man_hour_group REGEXP '^[0-9]' THEN CAST(man_hour_group AS UNSIGNED) -- 濡傛灉浠ユ暟瀛楀紑澶达紝鍒欐寜鐓ф暟瀛楀ぇ灏忔帓搴�
+ WHEN man_hour_group REGEXP '[0-9]+' THEN CAST(SUBSTRING(man_hour_group, 2)AS UNSIGNED) END -- 鎻愬彇瀛楁瘝鍚庨潰鐨勬暟瀛楅儴鍒�
+ ,id asc
+ </select>
+
+ <resultMap id="getInsProductions" type="map">
+ <result property="name" column="sample"/>
+ <collection property="children" resultMap="itemClass" javaType="List"/>
+ </resultMap>
+ <resultMap id="itemClass" type="map">
+ <result property="name" column="item_class"/>
+ <collection property="children" resultMap="item" javaType="List"/>
+ </resultMap>
+ <resultMap id="item" type="map">
+ <result property="name" column="inspection_item"/>
+ <collection property="children" resultMap="itemSubClass" javaType="List"/>
+ </resultMap>
+ <resultMap id="itemSubClass" type="map">
+ <id property="id" column="id"/>
+ <result property="name" column="subclass"/>
+ </resultMap>
+ <select id="getInsProduction" resultMap="getInsProductions">
+ select distinct id,
+ CASE
+ WHEN INSTR(sample, ',') > 0 THEN
+ SUBSTRING_INDEX(SUBSTRING_INDEX(sample, '","', 1), '"', -1)
+ when sample = '[""]' then '*'
+ ELSE
+ TRIM(BOTH '["]' FROM SUBSTRING_INDEX(REPLACE(sample, '[["', ''), '"]]', 1))
+ END
+ as sample,
+ inspection_item,
+ case
+ when inspection_item_subclass is null or inspection_item_subclass = '' then inspection_item
+ else inspection_item_subclass end as subclass,
+ case
+ when inspection_item_class is null or inspection_item_class = '' then inspection_item
+ else inspection_item_class end as item_class
+ from structure_item_parameter
+ </select>
+ <select id="getItemTree" resultMap="itemDto">
+ select sto.id sId, sto.specimen_name sName, p.id pId, p.name pName
+ from structure_test_object sto
+ left join product p on p.object_id = sto.id
+ </select>
+
+ <resultMap id="itemDto" type="com.ruoyi.basic.dto.TestItemDto">
+ <result column="sId" property="id"/>
+ <result column="sName" property="name"/>
+ <collection property="children" resultMap="productDto"/>
+ </resultMap>
+ <resultMap id="productDto" type="com.ruoyi.basic.dto.ProductDto">
+ <result column="pId" property="id"/>
+ <result column="pName" property="name"/>
+ </resultMap>
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StructureTestMapper.xml b/basic-server/src/main/resources/mapper/StructureTestMapper.xml
new file mode 100644
index 0000000..05c7ae7
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StructureTestMapper.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.basic.mapper.StructureTestObjectMapper">
+
+ <select id="selectTestObjectList" resultType="com.ruoyi.basic.dto.PageTestObjectDto">
+ select * from (
+ select sto.id,
+ sto.specimen_name,
+ u1.name create_user_name,
+ sto.create_time,
+ u2.name update_user_name,
+ sto.update_time,
+ sto.code,
+ sto.laboratory_id,
+ GROUP_CONCAT(p.name) product,
+ sto.specimen_name_en,
+ sto.object_type
+ from structure_test_object sto
+ left join user u1 on sto.create_user = u1.id
+ left join user u2 on sto.update_user = u2.id
+ left join product p on p.object_id = sto.id
+ left join product_part pp on pp.product_id = p.id
+ left join structure_test_object_part stop ON stop.test_object_id = sto.id
+ <if test="partNo != null and partNo != ''" >
+ where pp.part_no = #{partNo} or stop.part_no = #{partNo}
+ </if>
+ group by sto.id
+ ) a
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+
+</mapper>
diff --git a/basic-server/src/main/resources/mapper/StructureTestObjectPartMapper.xml b/basic-server/src/main/resources/mapper/StructureTestObjectPartMapper.xml
new file mode 100644
index 0000000..ee26497
--- /dev/null
+++ b/basic-server/src/main/resources/mapper/StructureTestObjectPartMapper.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.basic.mapper.StructureTestObjectPartMapper">
+ <select id="selectListByTestObjectId" resultType="com.ruoyi.basic.pojo.StructureTestObjectPart">
+ SELECT * from structure_test_object_part pp
+ where pp.test_object_id = #{testObjectId}
+ </select>
+</mapper>
diff --git a/bin/clean.bat b/bin/clean.bat
new file mode 100644
index 0000000..24c0974
--- /dev/null
+++ b/bin/clean.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 清理工程target生成路径。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+call mvn clean
+
+pause
\ No newline at end of file
diff --git a/bin/package.bat b/bin/package.bat
new file mode 100644
index 0000000..c693ec0
--- /dev/null
+++ b/bin/package.bat
@@ -0,0 +1,12 @@
+@echo off
+echo.
+echo [信息] 打包Web工程,生成war/jar包文件。
+echo.
+
+%~d0
+cd %~dp0
+
+cd ..
+call mvn clean package -Dmaven.test.skip=true
+
+pause
\ No newline at end of file
diff --git a/bin/run.bat b/bin/run.bat
new file mode 100644
index 0000000..41efbd0
--- /dev/null
+++ b/bin/run.bat
@@ -0,0 +1,14 @@
+@echo off
+echo.
+echo [信息] 使用Jar命令运行Web工程。
+echo.
+
+cd %~dp0
+cd ../ruoyi-admin/target
+
+set JAVA_OPTS=-Xms256m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m
+
+java -jar %JAVA_OPTS% ruoyi-admin.jar
+
+cd bin
+pause
\ No newline at end of file
diff --git a/inspect-server/pom.xml b/inspect-server/pom.xml
new file mode 100644
index 0000000..fc8d299
--- /dev/null
+++ b/inspect-server/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>inspect-server</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-framework</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-system</artifactId>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ </properties>
+
+</project>
diff --git a/inspect-server/src/main/java/com/ruoyi/basic/pojo/InsSample.java b/inspect-server/src/main/java/com/ruoyi/basic/pojo/InsSample.java
new file mode 100644
index 0000000..fc15a45
--- /dev/null
+++ b/inspect-server/src/main/java/com/ruoyi/basic/pojo/InsSample.java
@@ -0,0 +1,123 @@
+package com.ruoyi.basic.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * 妫�楠屾牱鍝�
+ * @TableName ins_sample
+ */
+@TableName(value ="ins_sample")
+@Data
+public class InsSample implements Serializable {
+ /**
+ *
+ */
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ /**
+ * 1锛氬悎鏍� 0锛氫笉鍚堟牸
+ */
+ private Integer insResult;
+
+ /**
+ * 澶栭敭锛歩ns_order琛╥d
+ */
+ private Integer insOrderId;
+
+ /**
+ * 閰嶅鏍峰搧鍨嬪彿
+ */
+ private String joinModel;
+
+ /**
+ * 閰嶅鏍峰搧鍚嶇О
+ */
+ private String joinName;
+
+ /**
+ * 閰嶅鏍峰搧鏁伴噺
+ */
+ private Integer joinNum;
+
+ /**
+ * 鏍峰搧缂栫爜
+ */
+ private String sampleCode;
+
+ /**
+ * 妫�楠屽伐鍘�
+ */
+ private String factory;
+
+ /**
+ * 瀹為獙瀹ゅ悕绉�
+ */
+ private String laboratory;
+
+ /**
+ * 鏍峰搧绫诲瀷
+ */
+ private String sampleType;
+
+ /**
+ * 鏍峰搧鍚嶇О
+ */
+ private String sample;
+
+ /**
+ * 瑙勬牸鍨嬪彿
+ */
+ private String model;
+
+ /**
+ * 妫�楠岀姸鎬�(0锛氬緟妫�楠�1:妫�楠屼腑 2:宸叉楠�3锛氬緟澶嶆牳4锛氬鏍告湭閫氳繃5锛氬鏍搁�氳繃)
+ */
+ private Integer insState;
+
+ /**
+ * 澶囨敞
+ */
+ private String remark;
+
+ private Integer standardMethodListId;
+
+ @ApiModelProperty("鏍峰搧鍗曚綅")
+ private String unit;
+
+ private Integer cellId;
+
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ private Integer parentId;
+
+ @ApiModelProperty("鏁伴噺")
+ private Integer quantity;
+
+ @ApiModelProperty("鐗规畩鏍囧噯鏂规硶")
+ private String specialStandardMethod;
+
+ @TableField(select = false,exist = false)
+ private Integer num=1;
+
+}
diff --git a/performance-server/pom.xml b/performance-server/pom.xml
new file mode 100644
index 0000000..12db53e
--- /dev/null
+++ b/performance-server/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>performance-server</artifactId>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-framework</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-system</artifactId>
+ </dependency>
+ </dependencies>
+
+ <properties>
+ <maven.compiler.source>8</maven.compiler.source>
+ <maven.compiler.target>8</maven.compiler.target>
+ </properties>
+
+</project>
diff --git a/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryCorrectionHoursController.java b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryCorrectionHoursController.java
new file mode 100644
index 0000000..290e0f2
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryCorrectionHoursController.java
@@ -0,0 +1,59 @@
+package com.ruoyi.performance.controller;
+
+import com.alibaba.excel.EasyExcel;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.utils.JackSonUtil;
+import com.ruoyi.performance.dto.AuxiliaryCorrectionHoursDto;
+import com.ruoyi.performance.excel.AuxiliaryCorrectionHoursListener;
+import com.ruoyi.performance.service.AuxiliaryCorrectionHoursService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * <p>
+ * 宸ユ椂缁熻鐨勪慨姝e伐鏃� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-29 02:38:19
+ */
+@Api(tags = "宸ユ椂缁熻-淇宸ユ椂")
+@AllArgsConstructor
+@RestController
+@RequestMapping("/auxiliaryCorrectionHours")
+public class AuxiliaryCorrectionHoursController {
+
+ @Resource
+ AuxiliaryCorrectionHoursService auxiliaryCorrectionHoursService;
+
+ @ApiOperation(value = "鏌ヨ淇宸ユ椂")
+ @PostMapping("/selectAuxiliaryCorrectionHours")
+ public Result selectAuxiliaryCorrectionHours(Page page,AuxiliaryCorrectionHoursDto entity) throws Exception {
+ return Result.success(auxiliaryCorrectionHoursService.selectAuxiliaryCorrectionHours(page, entity));
+ }
+
+ /**
+ * excel涓婁紶
+ *
+ * @return
+ */
+ @ApiOperation(value = "瀵煎叆淇宸ユ椂")
+ @PostMapping("/upload")
+ public Result upload(@RequestParam("file") MultipartFile file) {
+ try {
+ EasyExcel.read(file.getInputStream(), AuxiliaryCorrectionHoursDto.class, new AuxiliaryCorrectionHoursListener(auxiliaryCorrectionHoursService)).sheet().doRead();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return Result.success();
+ }
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOriginalHoursController.java b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOriginalHoursController.java
new file mode 100644
index 0000000..e70636c
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOriginalHoursController.java
@@ -0,0 +1,44 @@
+package com.ruoyi.performance.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.utils.JackSonUtil;
+import com.ruoyi.performance.dto.AuxiliaryOriginalHoursLookDto;
+import com.ruoyi.performance.service.AuxiliaryOriginalHoursService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Map;
+
+@Api(tags = "宸ユ椂缁熻-鍘熷宸ユ椂")
+@AllArgsConstructor
+@RestController
+@RequestMapping("/auxiliaryOriginalHours")
+public class AuxiliaryOriginalHoursController {
+
+ @Resource
+ AuxiliaryOriginalHoursService auxiliaryOriginalHoursService;
+
+ @ApiOperation(value = "鏌ヨ鍘熷宸ユ椂")
+ @PostMapping("/selectAuxiliaryOriginalHours")
+ public Result selectAuxiliaryOriginalHours(Page page, AuxiliaryOriginalHoursLookDto entity) throws Exception {
+ return Result.success(auxiliaryOriginalHoursService.selectAuxiliaryOriginalHours(page, entity));
+ }
+
+ @ApiOperation(value = "瀵煎嚭鍘熷宸ユ椂")
+ @PostMapping("/exportOriginalHours")
+ public void exportOriginalHours(@RequestParam("month") String month, @RequestParam("name") String name, @RequestParam("departLims") String departLims,HttpServletResponse response) throws IOException {
+ auxiliaryOriginalHoursService.exportWorkingHours(month,name,departLims,response);
+ }
+
+ @ApiOperation(value = "鏌ヨ鏈堜唤鍏ㄩ儴宸ユ椂")
+ @PostMapping("/selectAuxiliaryAllByMonth")
+ public Result selectAuxiliaryAllByMonth(@RequestBody AuxiliaryOriginalHoursLookDto dto){
+ return Result.success(auxiliaryOriginalHoursService.selectAuxiliaryAllByMonth(dto));
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOutputWorkingHoursController.java b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOutputWorkingHoursController.java
new file mode 100644
index 0000000..5fb7d13
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryOutputWorkingHoursController.java
@@ -0,0 +1,74 @@
+package com.ruoyi.performance.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.utils.JackSonUtil;
+import com.ruoyi.performance.dto.AuxiliaryOutputWorkingHoursDto;
+import com.ruoyi.performance.service.AuxiliaryOutputWorkingHoursService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑浜ч噺宸ユ椂 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 03:48:48
+ */
+@Api(tags = "鏃ュ伐鏃剁鐞�-浜ч噺宸ユ椂")
+@AllArgsConstructor
+@RestController
+@RequestMapping("/auxiliaryOutputWorkingHours")
+public class AuxiliaryOutputWorkingHoursController {
+
+ @Resource
+ private AuxiliaryOutputWorkingHoursService auxiliaryOutputWorkingHoursService;
+
+ @ApiOperation(value = "鏌ヨ浜ч噺宸ユ椂")
+ @PostMapping("/selectAuxiliaryOutputWorkingHours")
+ public Result selectAuxiliaryOutputWorkingHours(Page page,AuxiliaryOutputWorkingHoursDto entity) throws Exception {
+ return Result.success(auxiliaryOutputWorkingHoursService.selectAuxiliaryOutputWorkingHours(page, entity));
+ }
+
+ @ApiOperation(value = "缁熻浜ч噺宸ユ椂姹囨�诲拰杈呭姪宸ユ椂姹囨��")
+ @PostMapping("/collectWorkingHours")
+ public Result collectWorkingHours(@RequestBody Map<String, Object> data)throws Exception{
+ AuxiliaryOutputWorkingHoursDto entity = JackSonUtil.unmarshal(JackSonUtil.marshal(data.get("entity")), AuxiliaryOutputWorkingHoursDto.class);
+ return Result.success(auxiliaryOutputWorkingHoursService.collectWorkingHours(entity));
+ }
+
+
+ @ApiOperation(value = "瀵煎嚭浜ч噺宸ユ椂+杈呭姪宸ユ椂")
+ @GetMapping("/exportWorkingHours")
+ public void exportWorkingHours(HttpServletResponse response) throws IOException {
+ auxiliaryOutputWorkingHoursService.exportWorkingHours(response);
+ }
+
+ @ApiOperation(value = "缁勯暱鏉冮檺")
+ @PostMapping("/leader")
+ public Result leader() {
+ return Result.success();
+ }
+
+
+ /**
+ * 瀵煎嚭浜ч噺宸ユ椂
+ * @param response
+ * @throws IOException
+ */
+ @ApiOperation(value = "瀵煎嚭浜ч噺宸ユ椂")
+ @PostMapping("/exportOutputHours")
+ public void exportOutputHours(@RequestBody Map<String, Object> data, HttpServletResponse response) throws Exception {
+ AuxiliaryOutputWorkingHoursDto entity = JackSonUtil.unmarshal(JackSonUtil.marshal(data.get("entity")), AuxiliaryOutputWorkingHoursDto.class);
+ auxiliaryOutputWorkingHoursService.exportOutputHours(entity, response);
+ }
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursController.java b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursController.java
new file mode 100644
index 0000000..bab8fc7
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursController.java
@@ -0,0 +1,59 @@
+package com.ruoyi.performance.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.utils.JackSonUtil;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHours;
+import com.ruoyi.performance.service.AuxiliaryWorkingHoursService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import java.util.Map;
+
+/**
+ * <p>
+ * 杈呭姪宸ユ椂 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-09 06:58:31
+ */
+@Api(tags = "缁╂晥绠$悊-杈呭姪宸ユ椂璁剧疆")
+@AllArgsConstructor
+@RestController
+@RequestMapping("/auxiliaryWorkingHours")
+public class AuxiliaryWorkingHoursController {
+ @Resource
+ private AuxiliaryWorkingHoursService auxiliaryWorkingHoursService;
+
+ @ApiOperation(value="鏌ヨ杈呭姪宸ユ椂")
+ @PostMapping("/selectAuxiliaryWorkingHours")
+ public Result selectAuxiliaryWorkingHours(Page page,AuxiliaryWorkingHours entity) throws Exception {
+ return Result.success(auxiliaryWorkingHoursService.selectAuxiliaryWorkingHours(page,entity));
+ }
+
+ @ApiOperation(value="鍒犻櫎杈呭姪宸ユ椂")
+ @PostMapping("/deleteAuxiliaryWorkingHours")
+ public Result deleteAuxiliaryWorkingHours(Integer id){
+ return Result.success(auxiliaryWorkingHoursService.deleteAuxiliaryWorkingHours(id));
+ }
+
+ @ApiOperation(value="淇敼杈呭姪宸ユ椂")
+ @PostMapping("/upAuxiliaryWorkingHours")
+ public Result upAuxiliaryWorkingHours(@RequestBody AuxiliaryWorkingHours auxiliaryWorkingHours){
+ return Result.success(auxiliaryWorkingHoursService.upAuxiliaryWorkingHours(auxiliaryWorkingHours));
+ }
+
+ @ApiOperation(value="鏂板杈呭姪宸ユ椂")
+ @PostMapping("/insertAuxiliaryWorkingHours")
+ public Result insertAuxiliaryWorkingHours(@RequestBody AuxiliaryWorkingHours auxiliaryWorkingHours){
+ return Result.success(auxiliaryWorkingHoursService.insertAuxiliaryWorkingHours(auxiliaryWorkingHours));
+ }
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursDayController.java b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursDayController.java
new file mode 100644
index 0000000..97b0a81
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/controller/AuxiliaryWorkingHoursDayController.java
@@ -0,0 +1,101 @@
+package com.ruoyi.performance.controller;
+
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.utils.JackSonUtil;
+import com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto;
+import com.ruoyi.performance.dto.HoursDay;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay;
+import com.ruoyi.performance.service.AuxiliaryWorkingHoursDayService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import lombok.AllArgsConstructor;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.time.LocalDateTime;
+import java.util.Map;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑杈呭姪宸ユ椂 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 02:22:19
+ */
+@Api(tags = "鏃ュ伐鏃剁鐞�-杈呭姪宸ユ椂")
+@AllArgsConstructor
+@RestController
+@RequestMapping("/auxiliaryWorkingHoursDay")
+public class AuxiliaryWorkingHoursDayController {
+
+ @Resource
+ private AuxiliaryWorkingHoursDayService auxiliaryWorkingHoursDayService;
+
+ @ApiOperation(value = "鏌ヨ宸ユ椂缁熻鐨勮緟鍔╁伐鏃�")
+ @PostMapping("/selectAuxiliaryWorkingHoursDay")
+ public Result selectAuxiliaryWorkingHoursDay(Page page,AuxiliaryWorkingHoursDayDto entity) throws Exception {
+ return Result.success(auxiliaryWorkingHoursDayService.selectAuxiliaryWorkingHoursDay(page, entity));
+ }
+
+ @ApiOperation(value = "鏍规嵁缂栧彿鏌ヨ杈呭姪宸ユ椂閰嶇疆淇℃伅")
+ @PostMapping("/selectAuxiliaryWorkingHoursByNumber")
+ public Result selectAuxiliaryWorkingHoursByNumber(String number) {
+ return Result.success(auxiliaryWorkingHoursDayService.selectAuxiliaryWorkingHoursByNumber(number));
+ }
+
+ @ApiOperation(value = "鏍规嵁缂栧彿褰撳墠鐢ㄦ埛淇℃伅鏌ヨ鎵�鍦ㄧ彮娆�")
+ @PostMapping("/selectshiftByUser")
+ public Result selectshiftByUser(LocalDateTime dateTime) {
+ return Result.success(auxiliaryWorkingHoursDayService.selectshiftByUser(dateTime));
+ }
+
+ @ApiOperation(value = "褰曞叆鏁版嵁(宸ユ椂缁熻鐨勮緟鍔╁伐鏃�)")
+ @PostMapping("/insertAuxiliaryWorkingHoursDay")
+ public Result insertAuxiliaryWorkingHoursDay(@RequestBody AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay) {
+ return Result.success(auxiliaryWorkingHoursDayService.insertAuxiliaryWorkingHoursDay(auxiliaryWorkingHoursDay));
+ }
+
+ @ApiOperation(value = "鎵瑰噯宸ユ椂缁熻鐨勮緟鍔╁伐鏃�")
+ @PostMapping("/approve")
+ public Result approve(@RequestBody HoursDay hoursDay ) {
+ return Result.success(auxiliaryWorkingHoursDayService.checkOrApprove(hoursDay));
+ }
+
+ @ApiOperation(value = "瀹℃牳宸ユ椂缁熻鐨勮緟鍔╁伐鏃�")
+ @PostMapping("/check")
+ public Result check(@RequestBody HoursDay hoursDay ) {
+ return Result.success(auxiliaryWorkingHoursDayService.checkOrApprove(hoursDay));
+ }
+
+ @ApiOperation(value = "缂栬緫宸ユ椂缁熻鐨勮緟鍔╁伐鏃�")
+ @PostMapping("/updateAuxiliaryWorkingHoursDay")
+ public Result updateAuxiliaryWorkingHoursDay(@RequestBody AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay) {
+ return Result.success(auxiliaryWorkingHoursDayService.updateAuxiliaryWorkingHoursDay(auxiliaryWorkingHoursDay));
+ }
+
+ @ApiOperation(value = "鍒犻櫎宸ユ椂缁熻鐨勮緟鍔╁伐鏃�")
+ @PostMapping("/deleteAuxiliaryWorkingHoursDay")
+ public Result deleteAuxiliaryWorkingHoursDay(Integer id) {
+ return Result.success(auxiliaryWorkingHoursDayService.deleteAuxiliaryWorkingHoursDay(id));
+ }
+
+ /**
+ * 瀵煎嚭杈呭姪宸ユ椂
+ * @param response
+ * @throws IOException
+ */
+ @ApiOperation(value = "瀵煎嚭杈呭姪宸ユ椂")
+ @PostMapping("/exportAssistantHours")
+ public void exportAssistantHours(@RequestBody Map<String, Object> data, HttpServletResponse response) throws Exception {
+ AuxiliaryWorkingHoursDayDto entity = JackSonUtil.unmarshal(JackSonUtil.marshal(data.get("entity")), AuxiliaryWorkingHoursDayDto.class);
+ auxiliaryWorkingHoursDayService.exportWorkingHours(entity, response);
+ }
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/controller/PerformanceShiftController.java b/performance-server/src/main/java/com/ruoyi/performance/controller/PerformanceShiftController.java
new file mode 100644
index 0000000..ecdabdb
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/controller/PerformanceShiftController.java
@@ -0,0 +1,152 @@
+package com.ruoyi.performance.controller;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.performance.dto.PerformanceShiftAddDto;
+import com.ruoyi.performance.pojo.PerformanceShift;
+import com.ruoyi.performance.service.PerformanceShiftService;
+import com.ruoyi.performance.utils.StyleMonthUtils;
+import com.ruoyi.performance.utils.StyleYearUtils;
+import com.ruoyi.system.service.ISysDictTypeService;
+import com.ruoyi.system.service.UserService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import javax.validation.constraints.NotNull;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.temporal.TemporalAdjusters;
+import java.time.temporal.WeekFields;
+import java.util.Collection;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+
+/**
+ * <p>
+ * 缁╂晥绠$悊-鐝 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-08 09:12:04
+ */
+@Api(tags = "缁╂晥绠$悊-鐝")
+@RestController
+@RequestMapping("/performanceShift")
+public class PerformanceShiftController {
+
+ @Autowired
+ private PerformanceShiftService performanceShiftService;
+
+ @Resource
+ private ISysDictTypeService dictTypeService;
+
+ @Resource
+ private UserService userService;
+
+ @ApiOperation(value = "鎺掔彮")
+ @PostMapping("add")
+ public Result<?> performanceShiftAdd(@RequestBody PerformanceShiftAddDto performanceShiftAddDto) {
+ performanceShiftService.performanceShiftAdd(performanceShiftAddDto);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鏈堜唤鍒嗛〉鏌ヨ")
+ @PostMapping("page")
+ public Result<?> performanceShiftPage(Integer size, Integer current, String time, String userName, String laboratory) {
+ return Result.success(performanceShiftService.performanceShiftPage(new Page<>(current, size), time, userName, laboratory));
+ }
+
+ @ApiOperation(value = "骞翠唤鍒嗛〉鏌ヨ")
+ @PostMapping("pageYear")
+ public Result<?> performanceShiftPageYear(Integer size, Integer current, String time, String userName, String laboratory) {
+ return Result.success(performanceShiftService.performanceShiftPageYear(new Page<>(current, size), time, userName, laboratory));
+ }
+
+ @ApiOperation(value = "鐝鐘舵�佷慨鏀�")
+ @PutMapping("update")
+ public Result<?> performanceShiftUpdate(@RequestBody PerformanceShift performanceShift) {
+ performanceShiftService.performanceShiftUpdate(performanceShift);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "瀵煎嚭")
+ @GetMapping("export")
+ public void exportToExcel(@NotNull(message = "鏃堕棿涓嶈兘涓虹┖锛�") String time, String userName, String laboratory, Boolean isMonth, HttpServletResponse response) throws Exception {
+ Map<Object, Object> data;
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ response.setHeader("requestType","excel");
+ response.setHeader("Access-Control-Expose-Headers", "requestType");
+ if (!isMonth) {
+ data = performanceShiftService.exportToYearExcel(time, userName, laboratory);
+ // 璁剧疆鍗曞厓鏍兼牱寮�
+ HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(StyleYearUtils.getHeadStyle(), StyleYearUtils.getContentStyle());
+ // 淇濆瓨鍒扮涓�涓猻heet涓�
+ EasyExcel.write(response.getOutputStream())
+ .head((List<List<String>>) data.get("header"))
+ .registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()) // 鑷�傚簲鍒楀
+ .registerWriteHandler(horizontalCellStyleStrategy)
+ .sheet("骞村害")
+ .doWrite((Collection<?>) data.get("data"));
+ } else {
+ data = performanceShiftService.exportToMonthExcel(time, userName, laboratory);
+ // 璁剧疆鍗曞厓鏍兼牱寮�
+ HorizontalCellStyleStrategy horizontalCellStyleStrategy = new HorizontalCellStyleStrategy(StyleMonthUtils.getHeadStyle(), StyleMonthUtils.getContentStyle());
+ EasyExcel.write(response.getOutputStream())
+ .head((List<List<String>>) data.get("header"))
+ .registerWriteHandler(horizontalCellStyleStrategy)
+ .sheet("鏈堝害")
+ .doWrite((Collection<?>) data.get("data"));
+ }
+ }
+
+ @ApiOperation(value = "涓存椂鎺ュ彛-娣诲姞7鏈堜唤8鏈堜唤鐨勬暟鎹�")
+ @GetMapping("temporaryInterface")
+ public void temporaryInterface() {
+ System.out.println("寮�濮嬬粰姣忎釜浜鸿繘琛屾帓鐝�,榛樿鏃╃彮======start");
+ // TODO 缁欐瘡涓汉閮借繘琛屾帓鐝�(榛樿鏃╃彮)
+ PerformanceShiftAddDto performanceShiftAddDto = new PerformanceShiftAddDto();
+ //鐝--鏃�(鏌ヨ瀛楀吀)
+ List<SysDictData> shiftType = dictTypeService.selectDictDataByName("鐝绫诲瀷");
+ List<String> collect = shiftType.stream().filter(enums -> enums.getDictLabel().equals("鏃�")).map(enums -> enums.getDictValue()).collect(Collectors.toList());
+ performanceShiftAddDto.setShift(collect.get(0));
+ //浜哄憳--鎵�鏈変汉
+ String userIds = userService.list().stream().map(user -> user.getId().toString()).distinct().collect(Collectors.joining(","));
+ performanceShiftAddDto.setUserId(userIds);
+ //鍛ㄦ--褰撴湀鎵�鏈�
+ // 鑾峰彇褰撳墠鏃ユ湡
+ LocalDate today = LocalDate.of(2024, 8, 15);
+ // 鑾峰彇鏈湀鐨勭涓�澶╁拰鏈�鍚庝竴澶�
+ LocalDate firstDayOfMonth = today.with(TemporalAdjusters.firstDayOfMonth());
+ LocalDate lastDayOfMonth = today.with(TemporalAdjusters.lastDayOfMonth());
+ // 鑾峰彇鍛ㄥ瓧娈典俊鎭紙鏍规嵁鍖哄煙璁剧疆锛�
+ WeekFields weekFields = WeekFields.of(Locale.getDefault());
+ // 鑾峰彇鏈湀绗竴澶╃殑鍛ㄤ竴
+ LocalDate startOfWeek = firstDayOfMonth.with(TemporalAdjusters.previousOrSame(weekFields.getFirstDayOfWeek()));
+ // 閬嶅巻鏈湀鎵�鏈夊ぉ鏁帮紝鎵惧嚭姣忓懆鐨勭涓�澶╁拰鏈�鍚庝竴澶�
+ LocalDate endOfWeek;
+ while (startOfWeek.isBefore(firstDayOfMonth.plusMonths(1))) {
+ endOfWeek = startOfWeek.plusDays(6);
+ LocalDateTime startDateTime = LocalDateTime.of(startOfWeek, LocalTime.MIDNIGHT);
+ LocalDateTime endDateTime = LocalDateTime.of(endOfWeek, LocalTime.MIDNIGHT);
+ System.out.println("Week starts on " + startDateTime + " and ends on " + endDateTime);
+ performanceShiftAddDto.setStartWeek(startDateTime);
+ performanceShiftAddDto.setEndWeek(endDateTime);
+ performanceShiftService.performanceShiftAdd(performanceShiftAddDto);
+ startOfWeek = startOfWeek.plusWeeks(1);
+ }
+
+ System.out.println("鎺掔彮缁撴潫======end");
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/controller/ShiftTimeController.java b/performance-server/src/main/java/com/ruoyi/performance/controller/ShiftTimeController.java
new file mode 100644
index 0000000..96364e1
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/controller/ShiftTimeController.java
@@ -0,0 +1,55 @@
+package com.ruoyi.performance.controller;
+
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.performance.pojo.ShiftTime;
+import com.ruoyi.performance.service.ShiftTimeService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ * 鐝瀵瑰簲鐨勬椂闂� 鍓嶇鎺у埗鍣�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-07-24 11:22:17
+ */
+@Api(tags = "缁╂晥绠$悊-鐝鎺掔彮")
+@RestController
+@RequestMapping("/shiftTime")
+public class ShiftTimeController {
+
+ @Autowired
+ private ShiftTimeService shiftTimeService;
+
+ @ApiOperation(value = "鎺掔彮鏃堕棿閰嶇疆")
+ @PostMapping("add")
+ public Result<?> shiftTimeAdd(@RequestBody ShiftTime shiftTime) {
+ shiftTimeService.shiftTimeAdd(shiftTime);
+ return Result.success();
+ }
+
+ @ApiOperation(value = "鎺掔彮鏃堕棿閰嶇疆鏌ヨ")
+ @PostMapping("list")
+ public Result<?> shiftTimeList() {
+ return Result.success(shiftTimeService.shiftTimeList());
+ }
+
+ @ApiOperation(value = "鎺掔彮鏃堕棿閰嶇疆鍒犻櫎")
+ @PostMapping("remove")
+ public Result<?> shiftTimeRemove(Long id) {
+ return Result.success(shiftTimeService.removeById(id));
+ }
+
+ @ApiOperation(value = "鎺掔彮鏃堕棿閰嶇疆淇敼")
+ @PostMapping("update")
+ public Result<?> shiftTimeUpdate(@RequestBody ShiftTime shiftTime) {
+ return Result.success(shiftTimeService.updateById(shiftTime));
+ }
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryAllDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryAllDto.java
new file mode 100644
index 0000000..8b3afb1
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryAllDto.java
@@ -0,0 +1,35 @@
+package com.ruoyi.performance.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * 宸ユ椂缁熻鍒楄〃
+ *
+ * @Author zhuo
+ * @Date 2024/10/25
+ */
+@Data
+public class AuxiliaryAllDto {
+
+ @ApiModelProperty("浜ч噺宸ユ椂")
+ private BigDecimal yieldHour;
+
+ @ApiModelProperty("杈呭姪宸ユ椂")
+ private BigDecimal subsidiaryHour;
+
+ @ApiModelProperty("鎬诲伐鏃�")
+ private BigDecimal totalHour;
+
+ @ApiModelProperty("浜哄憳id")
+ private Integer userId;
+
+ @ApiModelProperty("濮撳悕")
+ private String userName;
+
+ @ApiModelProperty("鏈堜唤")
+ private String month;
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryCorrectionHoursDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryCorrectionHoursDto.java
new file mode 100644
index 0000000..b6066cf
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryCorrectionHoursDto.java
@@ -0,0 +1,22 @@
+package com.ruoyi.performance.dto;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ruoyi.performance.pojo.AuxiliaryCorrectionHours;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+public class AuxiliaryCorrectionHoursDto extends AuxiliaryCorrectionHours {
+
+ @ApiModelProperty("濮撳悕")
+ @ExcelProperty(value = "濮撳悕")
+ private String name;
+
+ @ApiModelProperty("閮ㄩ棬")
+ private String departLims;
+
+ @ApiModelProperty("鎬诲伐鏃�")
+ private BigDecimal total;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursDto.java
new file mode 100644
index 0000000..e037f05
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursDto.java
@@ -0,0 +1,251 @@
+package com.ruoyi.performance.dto;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ruoyi.performance.pojo.AuxiliaryCorrectionHours;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+@Data
+//鍘熷宸ユ椂
+public class AuxiliaryOriginalHoursDto {
+
+ @ApiModelProperty("濮撳悕")
+ @ExcelProperty(value = "濮撳悕")
+ private String name;
+
+ //淇宸ユ椂
+ private AuxiliaryCorrectionHours auxiliaryCorrectionHours;
+
+ @ApiModelProperty("绫诲瀷")
+ @ExcelProperty(value = "绫诲瀷")
+ private String type;
+
+ @ApiModelProperty("1鏃ュ伐鏃�")
+ @ExcelProperty(value = "1鏃�")
+ private BigDecimal oneHours;
+
+ @ExcelIgnore
+ private Integer one;
+
+ @ApiModelProperty("2鏃ュ伐鏃�")
+ @ExcelProperty(value = "2鏃�")
+ private BigDecimal twoHours;
+
+ @ExcelIgnore
+ private Integer two;
+
+ @ApiModelProperty("3鏃ュ伐鏃�")
+ @ExcelProperty(value = "3鏃�")
+ private BigDecimal threeHours;
+
+ @ExcelIgnore
+ private Integer three;
+
+ @ApiModelProperty("4鏃ュ伐鏃�")
+ @ExcelProperty(value = "4鏃�")
+ private BigDecimal fourHours;
+
+ @ExcelIgnore
+ private Integer four;
+
+ @ApiModelProperty("5鏃ュ伐鏃�")
+ @ExcelProperty(value = "5鏃�")
+ private BigDecimal fiveHours;
+
+ @ExcelIgnore
+ private Integer five;
+
+ @ApiModelProperty("6鏃ュ伐鏃�")
+ @ExcelProperty(value = "6鏃�")
+ private BigDecimal sixHours;
+
+ @ExcelIgnore
+ private Integer six;
+
+ @ApiModelProperty("7鏃ュ伐鏃�")
+ @ExcelProperty(value = "7鏃�")
+ private BigDecimal sevenHours;
+
+ @ExcelIgnore
+ private Integer seven;
+
+ @ApiModelProperty("8鏃ュ伐鏃�")
+ @ExcelProperty(value = "8鏃�")
+ private BigDecimal eightHours;
+
+ @ExcelIgnore
+ private Integer eight;
+
+ @ApiModelProperty("9鏃ュ伐鏃�")
+ @ExcelProperty(value = "9鏃�")
+ private BigDecimal nineHours;
+
+ @ExcelIgnore
+ private Integer nine;
+
+ @ApiModelProperty("10鏃ュ伐鏃�")
+ @ExcelProperty(value = "10鏃�")
+ private BigDecimal tenHours;
+
+ @ExcelIgnore
+ private Integer ten;
+
+ @ApiModelProperty("11鏃ュ伐鏃�")
+ @ExcelProperty(value = "11鏃�")
+ private BigDecimal elevenHours;
+
+ @ExcelIgnore
+ private Integer eleven;
+
+ @ApiModelProperty("12鏃ュ伐鏃�")
+ @ExcelProperty(value = "12鏃�")
+ private BigDecimal twelveHours;
+
+ @ExcelIgnore
+ private Integer twelve;
+
+ @ApiModelProperty("13鏃ュ伐鏃�")
+ @ExcelProperty(value = "13鏃�")
+ private BigDecimal thirteenHours;
+
+ @ExcelIgnore
+ private Integer thirteen;
+
+ @ApiModelProperty("14鏃ュ伐鏃�")
+ @ExcelProperty(value = "14鏃�")
+ private BigDecimal fourteenHours;
+
+ @ExcelIgnore
+ private Integer fourteen;
+
+ @ApiModelProperty("15鏃ュ伐鏃�")
+ @ExcelProperty(value = "15鏃�")
+ private BigDecimal fifteenHours;
+
+ @ExcelIgnore
+ private Integer fifteen;
+
+ @ApiModelProperty("16鏃ュ伐鏃�")
+ @ExcelProperty(value = "16鏃�")
+ private BigDecimal sixteenHours;
+
+ @ExcelIgnore
+ private Integer sixteen;
+
+ @ApiModelProperty("17鏃ュ伐鏃�")
+ @ExcelProperty(value = "17鏃�")
+ private BigDecimal seventeenHours;
+
+ @ExcelIgnore
+ private Integer seventeen;
+
+ @ApiModelProperty("18鏃ュ伐鏃�")
+ @ExcelProperty(value = "18鏃�")
+ private BigDecimal eighteenHours;
+
+ @ExcelIgnore
+ private Integer eighteen;
+
+ @ApiModelProperty("19鏃ュ伐鏃�")
+ @ExcelProperty(value = "19鏃�")
+ private BigDecimal nineteenHours;
+
+ @ExcelIgnore
+ private Integer nineteen;
+
+ @ApiModelProperty("20鏃ュ伐鏃�")
+ @ExcelProperty(value = "20鏃�")
+ private BigDecimal twentyHours;
+
+ @ExcelIgnore
+ private Integer twenty;
+
+ @ApiModelProperty("21鏃ュ伐鏃�")
+ @ExcelProperty(value = "21鏃�")
+ private BigDecimal twentyOneHours;
+
+ @ExcelIgnore
+ private Integer twentyOne;
+
+ @ApiModelProperty("22鏃ュ伐鏃�")
+ @ExcelProperty(value = "22鏃�")
+ private BigDecimal twentyTwoHours;
+
+ @ExcelIgnore
+ private Integer twentyTwo;
+
+ @ApiModelProperty("23鏃ュ伐鏃�")
+ @ExcelProperty(value = "23鏃�")
+ private BigDecimal twentyThreeHours;
+
+ @ExcelIgnore
+ private Integer twentyThree;
+
+ @ApiModelProperty("24鏃ュ伐鏃�")
+ @ExcelProperty(value = "24鏃�")
+ private BigDecimal twentyFourHours;
+
+ @ExcelIgnore
+ private Integer twentyFour;
+
+ @ApiModelProperty("25鏃ュ伐鏃�")
+ @ExcelProperty(value = "25鏃�")
+ private BigDecimal twentyFiveHours;
+
+ @ExcelIgnore
+ private Integer twentyFive;
+
+ @ApiModelProperty("26鏃ュ伐鏃�")
+ @ExcelProperty(value = "26鏃�")
+ private BigDecimal twentySixHours;
+
+ @ExcelIgnore
+ private Integer twentySix;
+
+ @ApiModelProperty("27鏃ュ伐鏃�")
+ @ExcelProperty(value = "27鏃�")
+ private BigDecimal twentySevenHours;
+
+ @ExcelIgnore
+ private Integer twentySeven;
+
+ @ApiModelProperty("28鏃ュ伐鏃�")
+ @ExcelProperty(value = "28鏃�")
+ private BigDecimal twentyEightHours;
+
+ @ExcelIgnore
+ private Integer twentyEight;
+
+ @ApiModelProperty("29鏃ュ伐鏃�")
+ @ExcelProperty(value = "29鏃�")
+ private BigDecimal twentyNineHours;
+
+ @ExcelIgnore
+ private Integer twentyNine;
+
+ @ApiModelProperty("30鏃ュ伐鏃�")
+ @ExcelProperty(value = "30鏃�")
+ private BigDecimal thirtyHours;
+
+ @ExcelIgnore
+ private Integer thirty;
+
+ @ApiModelProperty("31鏃ュ伐鏃�")
+ @ExcelProperty(value = "31鏃�")
+ private BigDecimal thirtyOneHours;
+
+ @ExcelIgnore
+ private Integer thirtyOne;
+
+ @ApiModelProperty("鎬诲伐鏃�")
+ @ExcelProperty(value = "鎬诲伐鏃�")
+ private BigDecimal total;
+
+ @ApiModelProperty("鏈堜唤")
+ @ExcelProperty(value = "鏈堜唤")
+ private String month;
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursLookDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursLookDto.java
new file mode 100644
index 0000000..8ccf68d
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOriginalHoursLookDto.java
@@ -0,0 +1,26 @@
+package com.ruoyi.performance.dto;
+
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+
+@Data
+//鍘熷宸ユ椂缁熻鐨勬煡璇㈡潯浠�
+public class AuxiliaryOriginalHoursLookDto {
+
+ @NotNull
+ private String month;//鏈堜唤
+
+ private String name;
+
+ private String departLims;
+
+
+ @ApiModelProperty("寮�濮嬫椂闂�")
+ private String beginDate;
+
+ @ApiModelProperty("缁撴潫鏃堕棿")
+ private String endDate;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOutputWorkingHoursDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOutputWorkingHoursDto.java
new file mode 100644
index 0000000..0b5699a
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryOutputWorkingHoursDto.java
@@ -0,0 +1,19 @@
+package com.ruoyi.performance.dto;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ExcelIgnoreUnannotated
+public class AuxiliaryOutputWorkingHoursDto extends AuxiliaryOutputWorkingHours {
+
+ @ApiModelProperty("妫�娴嬩汉")
+ @ExcelProperty(index = 1, value = "妫�娴嬩汉")
+ private String name;
+
+ @ApiModelProperty("鐢电紗鏍囪瘑")
+ private String cableTag;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryWorkingHoursDayDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryWorkingHoursDayDto.java
new file mode 100644
index 0000000..92f3b2e
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/AuxiliaryWorkingHoursDayDto.java
@@ -0,0 +1,16 @@
+package com.ruoyi.performance.dto;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ExcelIgnoreUnannotated
+public class AuxiliaryWorkingHoursDayDto extends AuxiliaryWorkingHoursDay {
+
+ @ApiModelProperty("濮撳悕")
+ @ExcelProperty(index = 1, value = "濮撳悕")
+ private String name;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/HoursDay.java b/performance-server/src/main/java/com/ruoyi/performance/dto/HoursDay.java
new file mode 100644
index 0000000..3add587
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/HoursDay.java
@@ -0,0 +1,15 @@
+package com.ruoyi.performance.dto;
+
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class HoursDay {
+
+ // 鎿嶄綔, 1閫氳繃, 2閫�鍥�
+ private String operation;
+
+ private List<AuxiliaryWorkingHoursDay> auxiliaryWorkingHoursDays;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftAddDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftAddDto.java
new file mode 100644
index 0000000..a1811b9
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftAddDto.java
@@ -0,0 +1,27 @@
+package com.ruoyi.performance.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.NotNull;
+import java.time.LocalDateTime;
+
+@Data
+public class PerformanceShiftAddDto {
+
+ @NotNull(message = "璇烽�夋嫨鐝")
+ @ApiModelProperty("鐝")
+ private String shift;
+
+ @NotNull(message = "璇烽�夋嫨鍛樺伐")
+ @ApiModelProperty("鍛樺伐id")
+ private String userId;
+
+ @NotNull(message = "璇烽�夋嫨鍛ㄦ")
+ @ApiModelProperty("寮�濮嬪懆娆�")
+ private LocalDateTime startWeek;
+
+ @NotNull(message = "璇烽�夋嫨鍛ㄦ")
+ @ApiModelProperty("缁撴潫鍛ㄦ")
+ private LocalDateTime endWeek;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftMapDto.java b/performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftMapDto.java
new file mode 100644
index 0000000..1405d71
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/dto/PerformanceShiftMapDto.java
@@ -0,0 +1,27 @@
+package com.ruoyi.performance.dto;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Data
+public class PerformanceShiftMapDto {
+
+ private String name;
+
+ private String shiftTime;
+
+ private String userId;
+
+ private String department;
+
+ private Map<String, Object> monthlyAttendance = new HashMap<>();
+
+ private Map<String, Object> sidebarAnnualAttendance = new HashMap<>();;
+ private List<Map<String, Object>> list = new ArrayList<>();
+
+ private List<Map<Object, Object>> headerList = new ArrayList<>();
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/excel/AuxiliaryCorrectionHoursListener.java b/performance-server/src/main/java/com/ruoyi/performance/excel/AuxiliaryCorrectionHoursListener.java
new file mode 100644
index 0000000..f022143
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/excel/AuxiliaryCorrectionHoursListener.java
@@ -0,0 +1,41 @@
+package com.ruoyi.performance.excel;
+
+
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.ruoyi.performance.dto.AuxiliaryCorrectionHoursDto;
+import com.ruoyi.performance.service.AuxiliaryCorrectionHoursService;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class AuxiliaryCorrectionHoursListener extends AnalysisEventListener<AuxiliaryCorrectionHoursDto> {
+
+ private static final int BATCH_COUNT = 1000;
+ List<AuxiliaryCorrectionHoursDto> list = new ArrayList<>();
+
+ private AuxiliaryCorrectionHoursService auxiliaryCorrectionHoursService;
+
+ public AuxiliaryCorrectionHoursListener(AuxiliaryCorrectionHoursService auxiliaryCorrectionHoursService) {
+ this.auxiliaryCorrectionHoursService = auxiliaryCorrectionHoursService;
+ }
+
+ @Override
+ public void invoke(AuxiliaryCorrectionHoursDto data, AnalysisContext analysisContext) {
+ list.add(data);
+ if (list.size() >= BATCH_COUNT) {
+ save();
+ list.clear();
+ }
+ }
+
+ @Override
+ public void doAfterAllAnalysed(AnalysisContext analysisContext) {
+ save();
+ }
+
+
+ private void save() {
+ auxiliaryCorrectionHoursService.importExcel(list);
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryCorrectionHoursMapper.java b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryCorrectionHoursMapper.java
new file mode 100644
index 0000000..96db341
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryCorrectionHoursMapper.java
@@ -0,0 +1,27 @@
+package com.ruoyi.performance.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.performance.dto.AuxiliaryCorrectionHoursDto;
+import com.ruoyi.performance.pojo.AuxiliaryCorrectionHours;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 宸ユ椂缁熻鐨勪慨姝e伐鏃� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-29 02:38:19
+ */
+public interface AuxiliaryCorrectionHoursMapper extends BaseMapper<AuxiliaryCorrectionHours> {
+
+ IPage<AuxiliaryCorrectionHoursDto> selectAuxiliaryCorrectionHours(Page page, @Param("ew") QueryWrapper<AuxiliaryCorrectionHoursDto> ew, @Param("ids") List<Long> ids);
+
+ List<Integer> selDepartLimsByName(String departLims);
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOriginalHoursMapper.java b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOriginalHoursMapper.java
new file mode 100644
index 0000000..e55ca6d
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOriginalHoursMapper.java
@@ -0,0 +1,13 @@
+package com.ruoyi.performance.mapper;
+
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+public interface AuxiliaryOriginalHoursMapper {
+
+ //鏌ヨ璇ユ湀鐨勬�诲伐鏃�
+ List<Map<String, Object>> totalHours(@Param("month") String month, @Param("ids") List<Integer> ids);
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOutputWorkingHoursMapper.java b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOutputWorkingHoursMapper.java
new file mode 100644
index 0000000..a563f4a
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryOutputWorkingHoursMapper.java
@@ -0,0 +1,55 @@
+package com.ruoyi.performance.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.performance.dto.AuxiliaryAllDto;
+import com.ruoyi.performance.dto.AuxiliaryOriginalHoursLookDto;
+import com.ruoyi.performance.dto.AuxiliaryOutputWorkingHoursDto;
+import com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑浜ч噺宸ユ椂 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 03:48:48
+ */
+public interface AuxiliaryOutputWorkingHoursMapper extends BaseMapper<AuxiliaryOutputWorkingHours> {
+
+ IPage<AuxiliaryOutputWorkingHoursDto> selectAuxiliaryOutputWorkingHours(Page page, @Param("ew") QueryWrapper<AuxiliaryOutputWorkingHoursDto> ew, @Param("ids") List<Long> ids);
+
+ //鏌ヨ缁熻宸ユ椂瀵煎嚭鏁版嵁
+ List<AuxiliaryOutputWorkingHoursDto> selectDataByUser(@Param("ids") List<Long> ids);
+
+ //鏌ヨ璇ユ湀鐨勪骇閲忓伐鏃�
+ List<Map<String, Object>> totalHours(@Param("month") String month, @Param("ids") List<Long> ids, @Param("type") String type);
+
+
+ List<AuxiliaryOutputWorkingHours> selectListByIds(@Param("ids") List<Long> ids);
+
+ List<AuxiliaryOutputWorkingHours> selectLists(@Param("ew") QueryWrapper<AuxiliaryOutputWorkingHours> ew, @Param("ids") List<Long> ids);
+
+ /**
+ * 鏌ヨ
+ * @param dto
+ * @return
+ */
+ List<AuxiliaryAllDto> selectAuxiliaryAllByMonth(@Param("dto") AuxiliaryOriginalHoursLookDto dto, @Param("userIds") List<Long> userIds);
+
+ /**
+ * 鏌ヨ杈呭姪宸ユ椂
+ * @param dto
+ * @param userIds
+ * @return
+ */
+ List<AuxiliaryAllDto> selectSubsidiaryAllByMonth(@Param("dto") AuxiliaryOriginalHoursLookDto dto, @Param("userIds") List<Long> userIds);
+
+ List<AuxiliaryOutputWorkingHoursDto> selectAuxiliaryOutputWorkingHoursList(@Param("ew") QueryWrapper<AuxiliaryOutputWorkingHoursDto> ew, @Param("ids") List<Long> ids);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursDayMapper.java b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursDayMapper.java
new file mode 100644
index 0000000..58d7e12
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursDayMapper.java
@@ -0,0 +1,43 @@
+package com.ruoyi.performance.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑杈呭姪宸ユ椂 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 02:22:19
+ */
+public interface AuxiliaryWorkingHoursDayMapper extends BaseMapper<AuxiliaryWorkingHoursDay> {
+
+ IPage<AuxiliaryWorkingHoursDayDto> selectAuxiliaryWorkingHoursDay(Page page, @Param("ew") QueryWrapper<AuxiliaryWorkingHoursDayDto> ew, @Param("ids") List<Long> ids);
+
+ //鏌ヨ杈呭姪宸ユ椂瀵煎嚭淇℃伅
+ List<AuxiliaryWorkingHoursDayDto> selectDataByUser(@Param("ids") List<Long> ids);
+
+ List<AuxiliaryWorkingHoursDay> selectListByIds(@Param("ids") List<Long> ids);
+
+ //鏌ヨ璇ユ湀鐨勮緟鍔╁伐鏃�
+ List<Map<String, Object>> totalHours(@Param("month") String month, @Param("ids") List<Long> ids);
+
+ List<AuxiliaryWorkingHoursDay> selectLists(@Param("ew") QueryWrapper<AuxiliaryWorkingHoursDay> ew, @Param("ids") List<Long> ids);
+
+ /**
+ * 鏌ヨ杈呭姪宸ユ椂闆嗗悎
+ * @param ew
+ * @param ids
+ * @return
+ */
+ List<AuxiliaryWorkingHoursDayDto> selectAuxiliaryWorkingHoursDayList(@Param("ew") QueryWrapper<AuxiliaryWorkingHoursDayDto> ew, @Param("ids") List<Long> ids);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursMapper.java b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursMapper.java
new file mode 100644
index 0000000..46f2c6a
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/mapper/AuxiliaryWorkingHoursMapper.java
@@ -0,0 +1,19 @@
+package com.ruoyi.performance.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHours;
+
+/**
+ * <p>
+ * 杈呭姪宸ユ椂 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-09 06:58:31
+ */
+public interface AuxiliaryWorkingHoursMapper extends BaseMapper<AuxiliaryWorkingHours> {
+ IPage<AuxiliaryWorkingHours> selectAuxiliaryWorkingHours(Page page, QueryWrapper<AuxiliaryWorkingHours> ew);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/mapper/PerformanceShiftMapper.java b/performance-server/src/main/java/com/ruoyi/performance/mapper/PerformanceShiftMapper.java
new file mode 100644
index 0000000..091ad29
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/mapper/PerformanceShiftMapper.java
@@ -0,0 +1,41 @@
+package com.ruoyi.performance.mapper;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.framework.mybatis_config.MyBaseMapper;
+import com.ruoyi.performance.dto.PerformanceShiftMapDto;
+import com.ruoyi.performance.pojo.PerformanceShift;
+import org.springframework.data.repository.query.Param;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 缁╂晥绠$悊-鐝 Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-08 09:12:04
+ */
+public interface PerformanceShiftMapper extends MyBaseMapper<PerformanceShift> {
+
+ IPage<PerformanceShiftMapDto> performanceShiftPage(
+ Page<Object> page,
+ @Param("time") String time,
+ @Param("userName") String userName,
+ @Param("laboratory") String laboratory
+ );
+
+ List<Map<String, Object>> performanceShiftYearPage(@Param("time") String time,
+ @Param("userName") String userName,
+ @Param("laboratory") String laboratory);
+
+ IPage<Map<String, Object>> performanceShiftYear(Page<Object> page, String time, String userName, String laboratory);
+
+ List<Map<String, Object>> performanceShiftYearList(String time, String userName, String laboratory);
+
+ List<PerformanceShiftMapDto> performanceShiftList(String time, String userName, String laboratory);
+
+ String seldepLimsId(int depLimsId);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/mapper/ShiftTimeMapper.java b/performance-server/src/main/java/com/ruoyi/performance/mapper/ShiftTimeMapper.java
new file mode 100644
index 0000000..192e8ee
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/mapper/ShiftTimeMapper.java
@@ -0,0 +1,16 @@
+package com.ruoyi.performance.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.performance.pojo.ShiftTime;
+
+/**
+ * <p>
+ * 鐝瀵瑰簲鐨勬椂闂� Mapper 鎺ュ彛
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-07-24 11:22:17
+ */
+public interface ShiftTimeMapper extends BaseMapper<ShiftTime> {
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryCorrectionHours.java b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryCorrectionHours.java
new file mode 100644
index 0000000..e786968
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryCorrectionHours.java
@@ -0,0 +1,181 @@
+package com.ruoyi.performance.pojo;
+
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 宸ユ椂缁熻鐨勪慨姝e伐鏃�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-29 02:38:19
+ */
+@Getter
+@Setter
+@TableName("auxiliary_correction_hours")
+@ApiModel(value = "AuxiliaryCorrectionHours瀵硅薄", description = "宸ユ椂缁熻鐨勪慨姝e伐鏃�")
+public class AuxiliaryCorrectionHours implements Serializable {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("濮撳悕id")
+ private Integer nameUser;
+
+ @ApiModelProperty("绫诲瀷")
+ @ExcelProperty(value = "绫诲瀷")
+ private String type;
+
+ @ApiModelProperty("1")
+ @ExcelProperty(value = "1鏃�")
+ private BigDecimal oneHours;
+
+ @ApiModelProperty("2")
+ @ExcelProperty(value = "2鏃�")
+ private BigDecimal twoHours;
+
+ @ApiModelProperty("3")
+ @ExcelProperty(value = "3鏃�")
+ private BigDecimal threeHours;
+
+ @ApiModelProperty("4")
+ @ExcelProperty(value = "4鏃�")
+ private BigDecimal fourHours;
+
+ @ApiModelProperty("5")
+ @ExcelProperty(value = "5鏃�")
+ private BigDecimal fiveHours;
+
+ @ApiModelProperty("6")
+ @ExcelProperty(value = "6鏃�")
+ private BigDecimal sixHours;
+
+ @ApiModelProperty("7")
+ @ExcelProperty(value = "7鏃�")
+ private BigDecimal sevenHours;
+
+ @ApiModelProperty("8")
+ @ExcelProperty(value = "8鏃�")
+ private BigDecimal eightHours;
+
+ @ApiModelProperty("9")
+ @ExcelProperty(value = "9鏃�")
+ private BigDecimal nineHours;
+
+ @ApiModelProperty("10")
+ @ExcelProperty(value = "10鏃�")
+ private BigDecimal tenHours;
+
+ @ApiModelProperty("11")
+ @ExcelProperty(value = "11鏃�")
+ private BigDecimal elevenHours;
+
+ @ApiModelProperty("12")
+ @ExcelProperty(value = "12鏃�")
+ private BigDecimal twelveHours;
+
+ @ApiModelProperty("13")
+ @ExcelProperty(value = "13鏃�")
+ private BigDecimal thirteenHours;
+
+ @ApiModelProperty("14")
+ @ExcelProperty(value = "14鏃�")
+ private BigDecimal fourteenHours;
+
+ @ApiModelProperty("15")
+ @ExcelProperty(value = "15鏃�")
+ private BigDecimal fifteenHours;
+
+ @ApiModelProperty("16")
+ @ExcelProperty(value = "16鏃�")
+ private BigDecimal sixteenHours;
+
+ @ApiModelProperty("17")
+ @ExcelProperty(value = "17鏃�")
+ private BigDecimal seventeenHours;
+
+ @ApiModelProperty("18")
+ @ExcelProperty(value = "18鏃�")
+ private BigDecimal eighteenHours;
+
+ @ApiModelProperty("19")
+ @ExcelProperty(value = "19鏃�")
+ private BigDecimal nineteenHours;
+
+ @ApiModelProperty("20")
+ @ExcelProperty(value = "20鏃�")
+ private BigDecimal twentyHours;
+
+ @ApiModelProperty("21")
+ @ExcelProperty(value = "21鏃�")
+ private BigDecimal twentyOneHours;
+
+ @ApiModelProperty("22")
+ @ExcelProperty(value = "22鏃�")
+ private BigDecimal twentyTwoHours;
+
+ @ApiModelProperty("23")
+ @ExcelProperty(value = "23鏃�")
+ private BigDecimal twentyThreeHours;
+
+ @ApiModelProperty("24")
+ @ExcelProperty(value = "24鏃�")
+ private BigDecimal twentyFourHours;
+
+ @ApiModelProperty("25")
+ @ExcelProperty(value = "25鏃�")
+ private BigDecimal twentyFiveHours;
+
+ @ApiModelProperty("26")
+ @ExcelProperty(value = "26鏃�")
+ private BigDecimal twentySixHours;
+
+ @ApiModelProperty("27")
+ @ExcelProperty(value = "27鏃�")
+ private BigDecimal twentySevenHours;
+
+ @ApiModelProperty("28")
+ @ExcelProperty(value = "28鏃�")
+ private BigDecimal twentyEightHours;
+
+ @ApiModelProperty("29")
+ @ExcelProperty(value = "29鏃�")
+ private BigDecimal twentyNineHours;
+
+ @ApiModelProperty("30")
+ @ExcelProperty(value = "30鏃�")
+ private BigDecimal thirtyHours;
+
+ @ApiModelProperty("31")
+ @ExcelProperty(value = "31鏃�")
+ private BigDecimal thirtyOneHours;
+
+ @ApiModelProperty("鏈堜唤")
+ @ExcelProperty(value = "鏈堜唤")
+ private String month;
+
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty("鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryOutputWorkingHours.java b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryOutputWorkingHours.java
new file mode 100644
index 0000000..45fecbe
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryOutputWorkingHours.java
@@ -0,0 +1,123 @@
+package com.ruoyi.performance.pojo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑浜ч噺宸ユ椂
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 03:48:48
+ */
+@Getter
+@Setter
+@TableName("auxiliary_output_working_hours")
+@ApiModel(value = "AuxiliaryOutputWorkingHours瀵硅薄", description = "鏃ュ伐鏃剁鐞嗙殑浜ч噺宸ユ椂")
+@ExcelIgnoreUnannotated
+public class AuxiliaryOutputWorkingHours implements Serializable {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("妫�娴嬮」鍒嗙被")
+ @ExcelProperty(index = 2, value = "妫�娴嬮」鍒嗙被")
+ private String inspectionItemClass;
+
+ @ApiModelProperty("妫�娴嬮」")
+ @ExcelProperty(index = 3, value = "妫�娴嬮」")
+ private String inspectionItem;
+
+ @ApiModelProperty("妫�娴嬪瓙椤�")
+ @ExcelProperty(index = 4, value = "妫�娴嬪瓙椤�")
+ private String inspectionItemSubclass;
+
+ @ApiModelProperty("鏍峰搧id")
+ private Integer sampleId;
+
+ @ApiModelProperty("鏍峰搧缂栧彿")
+ @ExcelProperty(index = 6, value = "鏍峰搧缂栧彿")
+ private String sample;
+
+ @ApiModelProperty("鍔犵彮濮旀墭鍗曞彿")
+ private String overtimeOrderNo;
+
+ @ApiModelProperty("鍔犵彮宸ユ椂")
+ private BigDecimal overtimeWorkTime;
+
+ @ApiModelProperty("鍔犵彮鏁伴噺")
+ private Integer overtimeAmount;
+
+ @ApiModelProperty("闈炲姞鐝鎵樺崟鍙�")
+ private Integer orderId;
+
+ @ApiModelProperty("濮旀墭鍗曞彿")
+ @ExcelProperty(index = 5, value = "濮旀墭鍗曞彿")
+ private String orderNo;
+
+ @ApiModelProperty("宸ユ椂")
+ private BigDecimal workTime;
+
+ @ApiModelProperty("鏁伴噺")
+ private Integer amount;
+
+ @ApiModelProperty("浜ч噺宸ユ椂")
+ @ExcelProperty(index = 7, value = "浜ч噺宸ユ椂")
+ private BigDecimal outputWorkTime;
+
+ @ApiModelProperty("鏃ユ湡")
+ @ExcelProperty(index = 10, value = "鏃ユ湡")
+ private String dateTime;
+
+ @ApiModelProperty("鍛ㄦ")
+ @ExcelProperty(index = 11, value = "鍛ㄦ")
+ private String week;
+
+ @ApiModelProperty("鏄熸湡")
+ @ExcelProperty(index = 12, value = "鏄熸湡")
+ private String weekDay;
+
+ @ApiModelProperty("妫�娴嬩汉id")
+ @TableField("`check`")
+ private Integer check;
+
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty("鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty("宸ユ椂鍒嗙粍")
+ @ExcelProperty(index = 8, value = "宸ユ椂鍒嗙粍")
+ private String manHourGroup;
+
+ @ApiModelProperty("鍗曚环")
+ @ExcelProperty(index = 9, value = "鍗曚环")
+ private BigDecimal price;
+
+ @ApiModelProperty("妫�楠岄」id")
+ private Integer insProductId;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHours.java b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHours.java
new file mode 100644
index 0000000..8dd3516
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHours.java
@@ -0,0 +1,60 @@
+package com.ruoyi.performance.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 杈呭姪宸ユ椂
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-09 06:58:31
+ */
+@Getter
+@Setter
+@TableName("auxiliary_working_hours")
+@ApiModel(value = "AuxiliaryWorkingHours瀵硅薄", description = "杈呭姪宸ユ椂")
+public class AuxiliaryWorkingHours implements Serializable {
+ @ApiModelProperty("涓婚敭ID")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+ @ApiModelProperty("缂栧彿")
+ private String number;
+ @ApiModelProperty("杈呭姪椤圭洰鍚嶇О")
+ private String auxiliaryProject;
+ @ApiModelProperty("鏍稿噯宸ユ椂")
+ private BigDecimal approvedWorkingHour;
+ @ApiModelProperty("澶囨敞")
+ private String remarks;
+
+ @ApiModelProperty("鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty("閮ㄩ棬")
+ private String department;
+ @ApiModelProperty("瀹為獙瀹�")
+ private String laboratory;
+ @ApiModelProperty("鍗曚綅")
+ private String unit;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHoursDay.java b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHoursDay.java
new file mode 100644
index 0000000..a4fef6a
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/pojo/AuxiliaryWorkingHoursDay.java
@@ -0,0 +1,113 @@
+package com.ruoyi.performance.pojo;
+
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑杈呭姪宸ユ椂
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 02:22:19
+ */
+@Data
+@TableName("auxiliary_working_hours_day")
+@ApiModel(value = "AuxiliaryWorkingHoursDay瀵硅薄", description = "鏃ュ伐鏃剁鐞嗙殑杈呭姪宸ユ椂")
+@ExcelIgnoreUnannotated
+public class AuxiliaryWorkingHoursDay implements Serializable {
+
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("濮撳悕id")
+ private Integer nameUser;
+
+ @ApiModelProperty("缂栧彿")
+ @ExcelProperty(index = 2, value = "缂栧彿")
+ private String number;
+
+ @ApiModelProperty("杈呭姪椤圭洰鍚嶇О")
+ @ExcelProperty(index = 3, value = "杈呭姪椤圭洰鍚嶇О")
+ private String auxiliaryProject;
+
+ @ApiModelProperty("鏍稿噯宸ユ椂")
+ @ExcelProperty(index = 5, value = "鏍稿噯宸ユ椂")
+ private BigDecimal approvedWorkingHour;
+
+ @ApiModelProperty("鏁伴噺")
+ @ExcelProperty(index = 6, value = "鏁伴噺")
+ private Integer amount;
+
+ @ApiModelProperty("杈呭姪宸ユ椂")
+ @ExcelProperty(index = 7, value = "杈呭姪宸ユ椂")
+ private BigDecimal nonproductiveTime;
+
+ @ApiModelProperty("杈呭姪璇存槑")
+ @ExcelProperty(index = 8, value = "杈呭姪璇存槑")
+ private String remarks;
+
+ @ApiModelProperty("澶嶆牳浜�")
+ @ExcelProperty(index = 9, value = "澶嶆牳浜�")
+ private String reviewer;
+
+ @ApiModelProperty("澶嶆牳鏁伴噺")
+ @ExcelProperty(index = 10, value = "澶嶆牳鏁伴噺")
+ private Integer reviewerNumber;
+
+ @ApiModelProperty("澶嶆牳宸ユ椂")
+ @ExcelProperty(index = 11, value = "澶嶆牳宸ユ椂")
+ private BigDecimal reviewerNonproductiveTime;
+
+ @ApiModelProperty("澶嶆牳璇存槑")
+ @ExcelProperty(index = 12, value = "澶嶆牳璇存槑")
+ private String reviewerRemark;
+
+ @ApiModelProperty("骞�")
+ @ExcelProperty(index = 13, value = "骞�")
+ private String year;
+
+ @ApiModelProperty("鐝")
+ @ExcelProperty(index = 14, value = "鐝")
+ private String shift;
+
+ @ApiModelProperty("鍛ㄦ")
+ @ExcelProperty(index = 15, value = "鍛ㄦ")
+ private String week;
+
+ @ApiModelProperty("鏄熸湡")
+ @ExcelProperty(index = 16, value = "鏄熸湡")
+ private String weekDay;
+
+ @ApiModelProperty("鍒涘缓鏃堕棿")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @ApiModelProperty("淇敼鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty("鍒涘缓浜篿d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("淇敼浜篿d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty("鐘舵��")
+ @ExcelProperty(index = 4, value = "鐘舵��")
+ private String state;
+
+ @ApiModelProperty("鏃ユ湡")
+ @ExcelProperty(index = 17, value = "鏃ユ湡")
+ private String dateTime;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/pojo/PerformanceShift.java b/performance-server/src/main/java/com/ruoyi/performance/pojo/PerformanceShift.java
new file mode 100644
index 0000000..bad6986
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/pojo/PerformanceShift.java
@@ -0,0 +1,54 @@
+package com.ruoyi.performance.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 缁╂晥绠$悊-鐝
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-08 09:12:04
+ */
+@Data
+@TableName("performance_shift")
+@ApiModel(value = "PerformanceShift瀵硅薄", description = "缁╂晥绠$悊-鐝")
+public class PerformanceShift implements Serializable {
+
+ private static final long serialVersionUID = 1L;
+
+ @ApiModelProperty("涓婚敭ID")
+ @TableId(type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("鐝")
+ private String shift;
+
+ @ApiModelProperty("鍛樺伐id")
+ private Integer userId;
+
+ @ApiModelProperty("鎺掔彮鏃ユ湡")
+ private LocalDateTime workTime;
+
+ @ApiModelProperty("鍒涘缓浜篒d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("鍒涘缓鏃ユ湡")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @ApiModelProperty("鏇存柊浜�")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty("鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/pojo/ShiftTime.java b/performance-server/src/main/java/com/ruoyi/performance/pojo/ShiftTime.java
new file mode 100644
index 0000000..ba7018e
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/pojo/ShiftTime.java
@@ -0,0 +1,54 @@
+package com.ruoyi.performance.pojo;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 鐝瀵瑰簲鐨勬椂闂�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-07-24 11:22:17
+ */
+@Getter
+@Setter
+@TableName("shift_time")
+@ApiModel(value = "ShiftTime瀵硅薄", description = "鐝瀵瑰簲鐨勬椂闂�")
+public class ShiftTime implements Serializable {
+
+ @ApiModelProperty("涓婚敭ID")
+ @TableId(value = "id", type = IdType.AUTO)
+ private Integer id;
+
+ @ApiModelProperty("鐝")
+ private String shift;
+
+ @ApiModelProperty("寮�濮嬫椂闂�")
+ private String startTime;
+
+ @ApiModelProperty("缁撴潫鏃堕棿")
+ private String endTime;
+
+ @ApiModelProperty("鍒涘缓浜篒d")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty("鍒涘缓鏃ユ湡")
+ @TableField(fill = FieldFill.INSERT)
+ private LocalDateTime createTime;
+
+ @ApiModelProperty("鏇存柊浜篒d")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty("鏇存柊鏃堕棿")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private LocalDateTime updateTime;
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryCorrectionHoursService.java b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryCorrectionHoursService.java
new file mode 100644
index 0000000..36ae0c9
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryCorrectionHoursService.java
@@ -0,0 +1,29 @@
+package com.ruoyi.performance.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.performance.dto.AuxiliaryCorrectionHoursDto;
+import com.ruoyi.performance.pojo.AuxiliaryCorrectionHours;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>
+ * 宸ユ椂缁熻鐨勪慨姝e伐鏃� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-29 02:38:19
+ */
+public interface AuxiliaryCorrectionHoursService extends IService<AuxiliaryCorrectionHours> {
+
+ IPage<AuxiliaryCorrectionHoursDto> selectAuxiliaryCorrectionHours(Page page, AuxiliaryCorrectionHoursDto auxiliaryCorrectionHoursDto);
+
+ /**
+ * 瀵煎叆涓婁紶
+ * @param list
+ */
+ void importExcel(List<AuxiliaryCorrectionHoursDto> list);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOriginalHoursService.java b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOriginalHoursService.java
new file mode 100644
index 0000000..05dd08c
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOriginalHoursService.java
@@ -0,0 +1,30 @@
+package com.ruoyi.performance.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.performance.dto.AuxiliaryAllDto;
+import com.ruoyi.performance.dto.AuxiliaryOriginalHoursDto;
+import com.ruoyi.performance.dto.AuxiliaryOriginalHoursLookDto;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public interface AuxiliaryOriginalHoursService {
+
+ IPage<AuxiliaryOriginalHoursDto> selectAuxiliaryOriginalHours(Page page, AuxiliaryOriginalHoursLookDto auxiliaryOriginalHoursLookDto);
+
+ /**
+ * 瀵煎嚭鍘熷宸ユ椂
+ *
+ * @param response
+ */
+ void exportWorkingHours(String month, String name, String departLims,HttpServletResponse response) throws IOException;
+
+ /**
+ * 鏌ヨ鏈堜唤鍏ㄩ儴宸ユ椂
+ * @return
+ */
+ List<AuxiliaryAllDto> selectAuxiliaryAllByMonth(AuxiliaryOriginalHoursLookDto dto);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOutputWorkingHoursService.java b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOutputWorkingHoursService.java
new file mode 100644
index 0000000..c3f4818
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryOutputWorkingHoursService.java
@@ -0,0 +1,44 @@
+package com.ruoyi.performance.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.performance.dto.AuxiliaryOutputWorkingHoursDto;
+import com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Map;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑浜ч噺宸ユ椂 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 03:48:48
+ */
+public interface AuxiliaryOutputWorkingHoursService extends IService<AuxiliaryOutputWorkingHours> {
+
+ IPage<AuxiliaryOutputWorkingHoursDto> selectAuxiliaryOutputWorkingHours(Page page, AuxiliaryOutputWorkingHoursDto auxiliaryOutputWorkingHoursDto);
+
+ /**
+ * 缁熻浜ч噺宸ユ椂姹囨�诲拰杈呭姪宸ユ椂姹囨��
+ * @return
+ */
+ Map<String,Object> collectWorkingHours(AuxiliaryOutputWorkingHoursDto auxiliaryOutputWorkingHoursDto);
+
+ /**
+ * 瀵煎嚭
+ * @param response
+ * @throws IOException
+ */
+ void exportWorkingHours(HttpServletResponse response)throws IOException;
+
+ /**
+ * 瀵煎嚭浜ч噺宸ユ椂
+ * @param entity
+ * @param response
+ */
+ void exportOutputHours(AuxiliaryOutputWorkingHoursDto entity, HttpServletResponse response);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursDayService.java b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursDayService.java
new file mode 100644
index 0000000..5c04cff
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursDayService.java
@@ -0,0 +1,44 @@
+package com.ruoyi.performance.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto;
+import com.ruoyi.performance.dto.HoursDay;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay;
+
+import javax.servlet.http.HttpServletResponse;
+import java.time.LocalDateTime;
+import java.util.Map;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑杈呭姪宸ユ椂 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 02:22:19
+ */
+public interface AuxiliaryWorkingHoursDayService extends IService<AuxiliaryWorkingHoursDay> {
+
+ IPage<AuxiliaryWorkingHoursDayDto> selectAuxiliaryWorkingHoursDay(Page page, AuxiliaryWorkingHoursDayDto auxiliaryWorkingHoursDayDto);
+
+ int insertAuxiliaryWorkingHoursDay(AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay);
+
+ AuxiliaryWorkingHoursDay selectAuxiliaryWorkingHoursByNumber(String number);
+
+ boolean checkOrApprove(HoursDay hoursDay);
+
+ int updateAuxiliaryWorkingHoursDay(AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay);
+
+ int deleteAuxiliaryWorkingHoursDay(Integer id);
+
+ String selectshiftByUser(LocalDateTime dateTime);
+
+ /**
+ * 瀵煎嚭杈呭姪宸ユ椂
+ * @param entity
+ * @param response
+ */
+ void exportWorkingHours(AuxiliaryWorkingHoursDayDto entity, HttpServletResponse response);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursService.java b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursService.java
new file mode 100644
index 0000000..d8a6000
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/AuxiliaryWorkingHoursService.java
@@ -0,0 +1,26 @@
+package com.ruoyi.performance.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHours;
+
+import java.util.Map;
+
+/**
+ * <p>
+ * 杈呭姪宸ユ椂 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-09 06:58:31
+ */
+public interface AuxiliaryWorkingHoursService extends IService<AuxiliaryWorkingHours> {
+ IPage<AuxiliaryWorkingHours> selectAuxiliaryWorkingHours(Page page, AuxiliaryWorkingHours auxiliaryWorkingHours);
+
+ int deleteAuxiliaryWorkingHours(Integer id);
+
+ int upAuxiliaryWorkingHours(AuxiliaryWorkingHours auxiliaryWorkingHours);
+
+ int insertAuxiliaryWorkingHours(AuxiliaryWorkingHours auxiliaryWorkingHours);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/PerformanceShiftService.java b/performance-server/src/main/java/com/ruoyi/performance/service/PerformanceShiftService.java
new file mode 100644
index 0000000..dce8d3a
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/PerformanceShiftService.java
@@ -0,0 +1,32 @@
+package com.ruoyi.performance.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.performance.dto.PerformanceShiftAddDto;
+import com.ruoyi.performance.pojo.PerformanceShift;
+
+import java.util.Map;
+
+/**
+ * <p>
+ * 缁╂晥绠$悊-鐝 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-08 09:12:04
+ */
+public interface PerformanceShiftService extends IService<PerformanceShift> {
+
+ void performanceShiftAdd(PerformanceShiftAddDto performanceShiftAddDto);
+
+ Map<String, Object> performanceShiftPage(Page<Object> page, String time, String userName, String laboratory);
+
+ void performanceShiftUpdate(PerformanceShift performanceShift);
+
+ IPage<Map<String, Object>> performanceShiftPageYear(Page<Object> page, String time, String userName, String laboratory);
+
+ Map<Object, Object> exportToYearExcel(String time, String userName, String laboratory) throws Exception;
+
+ Map<Object, Object> exportToMonthExcel(String time, String userName, String laboratory);
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/ShiftTimeService.java b/performance-server/src/main/java/com/ruoyi/performance/service/ShiftTimeService.java
new file mode 100644
index 0000000..617a20c
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/ShiftTimeService.java
@@ -0,0 +1,22 @@
+package com.ruoyi.performance.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.performance.pojo.ShiftTime;
+
+import java.util.List;
+
+/**
+ * <p>
+ * 鐝瀵瑰簲鐨勬椂闂� 鏈嶅姟绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-07-24 11:22:17
+ */
+public interface ShiftTimeService extends IService<ShiftTime> {
+
+ void shiftTimeAdd(ShiftTime shiftTime);
+
+ List<ShiftTime> shiftTimeList();
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryCorrectionHoursServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryCorrectionHoursServiceImpl.java
new file mode 100644
index 0000000..3cc5139
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryCorrectionHoursServiceImpl.java
@@ -0,0 +1,104 @@
+package com.ruoyi.performance.service.impl;
+
+import cn.hutool.core.collection.CollectionUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.performance.dto.AuxiliaryCorrectionHoursDto;
+import com.ruoyi.performance.mapper.AuxiliaryCorrectionHoursMapper;
+import com.ruoyi.performance.pojo.AuxiliaryCorrectionHours;
+import com.ruoyi.performance.service.AuxiliaryCorrectionHoursService;
+import com.ruoyi.system.mapper.UserMapper;
+import org.apache.commons.math3.analysis.function.Power;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 宸ユ椂缁熻鐨勪慨姝e伐鏃� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-29 02:38:19
+ */
+@Service
+public class AuxiliaryCorrectionHoursServiceImpl extends ServiceImpl<AuxiliaryCorrectionHoursMapper, AuxiliaryCorrectionHours> implements AuxiliaryCorrectionHoursService {
+
+ @Resource
+ AuxiliaryCorrectionHoursMapper auxiliaryCorrectionHoursMapper;
+
+ @Resource
+ UserMapper userMapper;
+
+
+ @Override
+ public IPage<AuxiliaryCorrectionHoursDto> selectAuxiliaryCorrectionHours(Page page, AuxiliaryCorrectionHoursDto auxiliaryCorrectionHoursDto) {
+ List<Long> ids = new ArrayList<>();
+ String departLims = auxiliaryCorrectionHoursDto.getDepartLims();
+ auxiliaryCorrectionHoursDto.setDepartLims(null);
+ if (ObjectUtils.isNotEmpty(departLims)) {
+ //鍏堟ā绯婃煡璇㈠嚭鏉d
+ List<Integer> ides = auxiliaryCorrectionHoursMapper.selDepartLimsByName(departLims);
+ for (Integer ide : ides) {
+ List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery()
+ .like(User::getDepartLimsId, ide));
+ if (ObjectUtils.isNotEmpty(users)) {
+ ids.clear();
+ ids.addAll(users.stream().map(User::getId).distinct().collect(Collectors.toList()));
+ }
+ }
+ }
+ if (ids.size() == 0) {
+ ids = null;
+ }
+ return auxiliaryCorrectionHoursMapper.selectAuxiliaryCorrectionHours(page, QueryWrappers.queryWrappers(auxiliaryCorrectionHoursDto).eq("month", auxiliaryCorrectionHoursDto.getMonth()), ids);
+ }
+
+ //瀵煎叆涓婁紶
+ @Override
+ public void importExcel(List<AuxiliaryCorrectionHoursDto> list) {
+ if (CollectionUtil.isEmpty(list)) {
+ return;
+ }
+ List<AuxiliaryCorrectionHours> auxiliaryCorrectionHoursList = new ArrayList<>();
+ List<AuxiliaryCorrectionHours> auxiliaryCorrectionHoursList1 = new ArrayList<>();
+ for (AuxiliaryCorrectionHoursDto auxiliaryCorrectionHoursDto : list) {
+ AuxiliaryCorrectionHours auxiliaryCorrectionHours = new AuxiliaryCorrectionHours();
+ User user = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getName, auxiliaryCorrectionHoursDto.getName()));
+ if (ObjectUtils.isEmpty(user)) {
+ throw new RuntimeException("绯荤粺娌℃湁鏌ュ埌" + auxiliaryCorrectionHoursDto.getName() + "杩欎釜鐢ㄦ埛淇℃伅!");
+ }
+ String regex = "\\d{4}-\\d{2}";
+ if (!Pattern.matches(regex, auxiliaryCorrectionHoursDto.getMonth())) {
+ throw new RuntimeException(auxiliaryCorrectionHoursDto.getMonth() + "鏍煎紡涓嶆纭�,鏈堜唤鏍煎紡搴斾负yyyy-MM");
+ }
+ BeanUtils.copyProperties(auxiliaryCorrectionHoursDto, auxiliaryCorrectionHours);
+ auxiliaryCorrectionHours.setNameUser(user.getId().intValue());
+ AuxiliaryCorrectionHours auxiliaryCorrectionHours1 = auxiliaryCorrectionHoursMapper.selectOne(Wrappers.<AuxiliaryCorrectionHours>lambdaQuery()
+ .eq(AuxiliaryCorrectionHours::getNameUser, user.getId())
+ .eq(AuxiliaryCorrectionHours::getType, auxiliaryCorrectionHours.getType())
+ .eq(AuxiliaryCorrectionHours::getMonth, auxiliaryCorrectionHours.getMonth()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours1)) {
+ auxiliaryCorrectionHoursList1.add(auxiliaryCorrectionHours);
+ } else {
+ auxiliaryCorrectionHoursList.add(auxiliaryCorrectionHours);
+ }
+ }
+ //鎵归噺鏂板
+ saveBatch(auxiliaryCorrectionHoursList);
+ //鎵归噺淇敼
+ updateBatchById(auxiliaryCorrectionHoursList1);
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOriginalHoursServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOriginalHoursServiceImpl.java
new file mode 100644
index 0000000..490b042
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOriginalHoursServiceImpl.java
@@ -0,0 +1,635 @@
+package com.ruoyi.performance.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.performance.dto.AuxiliaryAllDto;
+import com.ruoyi.performance.dto.AuxiliaryCorrectionHoursDto;
+import com.ruoyi.performance.dto.AuxiliaryOriginalHoursDto;
+import com.ruoyi.performance.dto.AuxiliaryOriginalHoursLookDto;
+import com.ruoyi.performance.mapper.AuxiliaryCorrectionHoursMapper;
+import com.ruoyi.performance.mapper.AuxiliaryOriginalHoursMapper;
+import com.ruoyi.performance.mapper.AuxiliaryOutputWorkingHoursMapper;
+import com.ruoyi.performance.mapper.AuxiliaryWorkingHoursDayMapper;
+import com.ruoyi.performance.pojo.AuxiliaryCorrectionHours;
+import com.ruoyi.performance.service.AuxiliaryOriginalHoursService;
+import com.ruoyi.system.mapper.UserMapper;
+import org.apache.commons.math3.analysis.function.Power;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.net.URLEncoder;
+import java.time.LocalDate;
+import java.time.format.DateTimeFormatter;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Service
+public class AuxiliaryOriginalHoursServiceImpl implements AuxiliaryOriginalHoursService {
+
+ @Resource
+ UserMapper userMapper;
+
+ @Resource
+ AuxiliaryOriginalHoursMapper auxiliaryOriginalHoursMapper;
+
+ @Resource
+ AuxiliaryOutputWorkingHoursMapper auxiliaryOutputWorkingHoursMapper;
+
+ @Resource
+ AuxiliaryWorkingHoursDayMapper auxiliaryWorkingHoursDayMapper;
+
+ @Resource
+ AuxiliaryCorrectionHoursMapper auxiliaryCorrectionHoursMapper;
+
+ @Override
+ public IPage<AuxiliaryOriginalHoursDto> selectAuxiliaryOriginalHours(Page page, AuxiliaryOriginalHoursLookDto auxiliaryOriginalHoursLookDto) {
+ List<Long> ids = new ArrayList<>();
+ String departLims = auxiliaryOriginalHoursLookDto.getDepartLims();
+ auxiliaryOriginalHoursLookDto.setDepartLims(null);
+ String name = auxiliaryOriginalHoursLookDto.getName();
+ auxiliaryOriginalHoursLookDto.setName(null);
+ if (ObjectUtils.isNotEmpty(departLims)) {
+ //鍏堟ā绯婃煡璇㈠嚭鏉d
+ List<Integer> ides = auxiliaryCorrectionHoursMapper.selDepartLimsByName(departLims);
+ for (Integer ide : ides) {
+ List<User> users = userMapper.selectList(Wrappers.<User>lambdaQuery()
+ .like(User::getDepartLimsId, ide));
+ if (ObjectUtils.isNotEmpty(users)) {
+ ides.clear();
+ ids.addAll(users.stream().map(User::getId).distinct().collect(Collectors.toList()));
+ }
+ }
+ }
+ if (ObjectUtils.isNotEmpty(name)) {
+ ids.clear();
+ ids.add(userMapper.selectOne(Wrappers.<User>lambdaQuery().like(User::getName, name)).getId());
+ }
+ if (ids.size() == 0) {
+ ids = null;
+ }
+ IPage<AuxiliaryOriginalHoursDto> originalHoursDtoIPage = new Page<>();
+ originalHoursDtoIPage.setSize(page.getSize());
+ originalHoursDtoIPage.setCurrent(page.getCurrent());
+ List<AuxiliaryOriginalHoursDto> auxiliaryOriginalHoursDtos = new ArrayList<>();
+ Map<String, AuxiliaryOriginalHoursDto> data1 = new HashMap<>();
+ Map<String, AuxiliaryOriginalHoursDto> data2 = new HashMap<>();
+ Map<String, AuxiliaryOriginalHoursDto> data3 = new HashMap<>();
+ //浜ч噺宸ユ椂
+ List<Map<String, Object>> maps = auxiliaryOutputWorkingHoursMapper.totalHours(auxiliaryOriginalHoursLookDto.getMonth(), ids, "浜ч噺宸ユ椂");
+ if (ObjectUtils.isNotEmpty(maps)) {
+ data1 = getData(maps, "浜ч噺宸ユ椂");
+ auxiliaryOriginalHoursDtos.addAll(data1.values());
+ }
+ //杈呭姪宸ユ椂
+ List<Map<String, Object>> maps1 = auxiliaryWorkingHoursDayMapper.totalHours(auxiliaryOriginalHoursLookDto.getMonth(), ids);
+ if (ObjectUtils.isNotEmpty(maps1)) {
+ data2 = getData(maps1, "杈呭姪宸ユ椂");
+ auxiliaryOriginalHoursDtos.addAll(data2.values());
+ }
+ //鍔犵彮宸ユ椂
+ List<Map<String, Object>> maps2 = auxiliaryOutputWorkingHoursMapper.totalHours(auxiliaryOriginalHoursLookDto.getMonth(), ids, "鍔犵彮宸ユ椂");
+ if (ObjectUtils.isNotEmpty(maps2)) {
+ data3 = getData(maps2, "鍔犵彮宸ユ椂");
+ auxiliaryOriginalHoursDtos.addAll(data3.values());
+ }
+ //鎬诲伐鏃�=浜ч噺宸ユ椂+杈呭姪宸ユ椂+鍔犵彮宸ユ椂
+ Map<String, AuxiliaryOriginalHoursDto> data4 = new HashMap<String, AuxiliaryOriginalHoursDto>();
+ if (data1.size() > 0) {
+ Map<String, AuxiliaryOriginalHoursDto> data5 = data1;
+ if (data2.size() > 0) {
+ merge(data5, data4, data2);
+ }
+ if (data3.size() > 0) {
+// merge(data5,data4,data3);
+ }
+ if (data2.size() == 0 && data3.size() == 0) {
+ for (Map.Entry<String, AuxiliaryOriginalHoursDto> entry : data5.entrySet()) {
+ AuxiliaryOriginalHoursDto dto = entry.getValue();
+ AuxiliaryOriginalHoursDto originalHoursDto = new AuxiliaryOriginalHoursDto();
+ BeanUtils.copyProperties(dto, originalHoursDto);
+ originalHoursDto.setType("鎬诲伐鏃�");
+ data4.put(entry.getKey(), originalHoursDto);
+ }
+ }
+ auxiliaryOriginalHoursDtos.addAll(data4.values());
+ }
+
+ auxiliaryOriginalHoursDtos = auxiliaryOriginalHoursDtos.stream().sorted(Comparator.comparing(AuxiliaryOriginalHoursDto::getName)).collect(Collectors.toList());
+ // 妫�鏌ユ瘡涓汉鐨勫伐鏃剁被鍨嬶紝琛ュ叏缂哄皯鐨勫伐鏃�
+ Map<String, Set<String>> workHoursMap = new HashMap<>();
+ String[] requiredHours = {"浜ч噺宸ユ椂", "杈呭姪宸ユ椂", "鍔犵彮宸ユ椂", "鎬诲伐鏃�"};
+ for (AuxiliaryOriginalHoursDto dto : auxiliaryOriginalHoursDtos) {
+ workHoursMap.computeIfAbsent(dto.getName(), k -> new HashSet<>()).add(dto.getType());
+ }
+ List<AuxiliaryOriginalHoursDto> result = auxiliaryOriginalHoursDtos;
+ for (String name1 : workHoursMap.keySet()) {
+ Set<String> workTypes = workHoursMap.get(name1);
+ for (String requiredHour : requiredHours) {
+ if (!workTypes.contains(requiredHour)) {
+ AuxiliaryOriginalHoursDto auxiliaryOriginalHoursDto = new AuxiliaryOriginalHoursDto();
+ auxiliaryOriginalHoursDto.setName(name1);
+ auxiliaryOriginalHoursDto.setAuxiliaryCorrectionHours(null);
+ auxiliaryOriginalHoursDto.setType(requiredHour);
+ auxiliaryOriginalHoursDto.setMonth(auxiliaryOriginalHoursLookDto.getMonth());
+ result.add(auxiliaryOriginalHoursDto);
+ }
+ }
+ }
+ List<String> order = Arrays.asList("浜ч噺宸ユ椂", "杈呭姪宸ユ椂", "鍔犵彮宸ユ椂", "鎬诲伐鏃�");
+ Comparator<AuxiliaryOriginalHoursDto> comparator = Comparator.comparingInt(dto -> {
+ String type = dto.getType();
+ return order.indexOf(type) == -1 ? order.size() : order.indexOf(type);
+ });
+ result = result.stream().sorted(Comparator.comparing(AuxiliaryOriginalHoursDto::getName).thenComparing(comparator)).collect(Collectors.toList());
+ originalHoursDtoIPage.setRecords(result);
+ originalHoursDtoIPage.setTotal(result.size());
+ return originalHoursDtoIPage;
+ }
+
+
+ //瀵煎嚭鍘熷宸ユ椂
+ @Override
+ public void exportWorkingHours(String month, String name, String departLims, HttpServletResponse response) throws IOException {
+ List<AuxiliaryOriginalHoursDto> auxiliaryOriginalHoursDtos = new ArrayList<AuxiliaryOriginalHoursDto>();
+ //鏌ヨ鍘熷宸ユ椂(浣跨敤鍒嗛〉鏌ヨ)
+ AuxiliaryOriginalHoursLookDto auxiliaryOriginalHoursLookDto = new AuxiliaryOriginalHoursLookDto();
+ if (ObjectUtils.isNotEmpty(month)) {
+ auxiliaryOriginalHoursLookDto.setMonth(month);
+ }
+ if (ObjectUtils.isNotEmpty(name)) {
+ auxiliaryOriginalHoursLookDto.setName(name);
+ }
+ if (ObjectUtils.isNotEmpty(departLims)) {
+ auxiliaryOriginalHoursLookDto.setDepartLims(departLims);
+ }
+ IPage<AuxiliaryOriginalHoursDto> body = selectAuxiliaryOriginalHours(new Page(-1, -1), auxiliaryOriginalHoursLookDto);
+ auxiliaryOriginalHoursDtos = body.getRecords();
+ response.setContentType("application/vnd.ms-excel");
+ response.setCharacterEncoding("UTF-8");
+ // 杩欓噷URLEncoder.encode鍙互闃叉涓枃涔辩爜 褰撶劧鍜宔asyexcel娌℃湁鍏崇郴
+ String fileName = URLEncoder.encode("宸ユ椂缁熻瀵煎嚭", "UTF-8");
+ response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+ try {
+ // 鏂板缓ExcelWriter
+ ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
+ WriteSheet mainSheet = EasyExcel.writerSheet(0, "鍘熷宸ユ椂瀵煎嚭").head(AuxiliaryOriginalHoursDto.class).build();
+ excelWriter.write(auxiliaryOriginalHoursDtos, mainSheet);
+ // 鍏抽棴娴�
+ excelWriter.finish();
+ } catch (IOException e) {
+ throw new RuntimeException("瀵煎嚭澶辫触");
+ }
+
+ }
+
+ /**
+ * 鏌ヨ鏈堜唤鍏ㄩ儴宸ユ椂
+ *
+ * @return
+ */
+ @Override
+ public List<AuxiliaryAllDto> selectAuxiliaryAllByMonth(AuxiliaryOriginalHoursLookDto dto) {
+ if (StringUtils.isBlank(dto.getMonth())) {
+ throw new BaseException("缂哄皯鏈堜唤");
+ }
+ List<Long> userIds = new ArrayList<>();
+
+ String name = dto.getName();
+ if (ObjectUtils.isNotEmpty(name)) {
+ userIds.addAll(userMapper.selectList(Wrappers.<User>lambdaQuery().like(User::getName, name)).stream().map(User::getId).collect(Collectors.toList()));
+ }
+ // 瑙f瀽杈撳叆鐨勬椂闂村瓧绗︿覆
+ LocalDate date = LocalDate.parse(dto.getMonth() + "-01", DateTimeFormatter.ofPattern("yyyy-MM-dd"));
+
+ // 鑾峰彇鍓嶄竴涓湀鐨�26鍙�
+ LocalDate previousMonth26th = date.minusMonths(1).withDayOfMonth(26);
+
+ // 鑾峰彇褰撳墠鏈堢殑25鍙�
+ LocalDate currentMonth25th = date.withDayOfMonth(25);
+
+ // 鏍煎紡鍖栨棩鏈熶负 yyyy-MM-dd HH:mm:ss
+ DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ String beginDate = previousMonth26th.atStartOfDay().format(outputFormatter);
+ String endDate = currentMonth25th.atStartOfDay().format(outputFormatter);
+// dto.setBeginDate(beginDate + " 00:00:00");
+// dto.setEndDate(endDate + " 23:59:59");
+ dto.setBeginDate(beginDate);
+ dto.setEndDate(endDate);
+
+
+ // 鏌ヨ浜ч噺宸ユ椂
+ List<AuxiliaryAllDto> auxiliaryAllDtos = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryAllByMonth(dto, userIds);
+
+ // 鏌ヨ杈呭姪宸ユ椂
+ List<AuxiliaryAllDto> auxiliarySubsidiary = auxiliaryOutputWorkingHoursMapper.selectSubsidiaryAllByMonth(dto, userIds);
+
+ //浜ч噺宸ユ椂杩涜浜哄憳鍒嗙粍, 鎶婅緟鍔╁伐鏃舵坊鍔�
+ Map<Integer, List<AuxiliaryAllDto>> groupIds = auxiliaryAllDtos.stream().collect(Collectors.groupingBy(AuxiliaryAllDto::getUserId));
+
+ for (AuxiliaryAllDto auxiliaryAllDto : auxiliarySubsidiary) {
+ List<AuxiliaryAllDto> allDtos = groupIds.get(auxiliaryAllDto.getUserId());
+ // 鍒ゆ柇鏄惁涓虹┖
+ if (CollectionUtils.isNotEmpty(allDtos)) {
+ // 娣诲姞杈呭姪宸ユ椂
+ allDtos.get(0).setSubsidiaryHour(auxiliaryAllDto.getSubsidiaryHour());
+
+ } else {
+ // 娌℃湁鏀逛汉鍛樻坊鍔犱竴琛�
+ auxiliaryAllDtos.add(auxiliaryAllDto);
+ }
+ }
+ for (AuxiliaryAllDto auxiliaryAllDto : auxiliaryAllDtos) {
+ BigDecimal total = (auxiliaryAllDto.getYieldHour() != null ? auxiliaryAllDto.getYieldHour() : BigDecimal.ZERO)
+ .add(auxiliaryAllDto.getSubsidiaryHour() != null ? auxiliaryAllDto.getSubsidiaryHour() : BigDecimal.ZERO);
+ auxiliaryAllDto.setTotalHour(total);
+ }
+
+ return auxiliaryAllDtos;
+ }
+
+ private Map<String, AuxiliaryOriginalHoursDto> getData(List<Map<String, Object>> objectMaps, String type) {
+ Map<String, AuxiliaryOriginalHoursDto> dtoMap = new HashMap<>();
+ for (Map<String, Object> objectMap : objectMaps) {
+ String name = objectMap.get("name").toString();
+ String month = objectMap.get("month").toString().substring(0, 7);
+ AuxiliaryOriginalHoursDto auxiliaryOriginalHoursDto = dtoMap.get(name);
+ if (auxiliaryOriginalHoursDto == null) {
+ auxiliaryOriginalHoursDto = new AuxiliaryOriginalHoursDto();
+ auxiliaryOriginalHoursDto.setName(name);
+ auxiliaryOriginalHoursDto.setType(type);
+ auxiliaryOriginalHoursDto.setMonth(month);
+ // 鏌ヨ杩欎釜浜鸿繖涓湀鏄惁鏈変慨姝g殑浜ч噺宸ユ椂
+ AuxiliaryCorrectionHours auxiliaryCorrectionHours = auxiliaryCorrectionHoursMapper.selectOne(Wrappers.<AuxiliaryCorrectionHours>lambdaQuery()
+ .eq(AuxiliaryCorrectionHours::getNameUser, userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getName, auxiliaryOriginalHoursDto.getName())).getId())
+ .eq(AuxiliaryCorrectionHours::getType, auxiliaryOriginalHoursDto.getType())
+ .eq(AuxiliaryCorrectionHours::getMonth, auxiliaryOriginalHoursDto.getMonth()));
+ auxiliaryOriginalHoursDto.setAuxiliaryCorrectionHours(auxiliaryCorrectionHours);
+ }
+ AuxiliaryCorrectionHours auxiliaryCorrectionHours = auxiliaryOriginalHoursDto.getAuxiliaryCorrectionHours();
+ switch (objectMap.get("month").toString().substring(8, 10)) {
+ case "01":
+ auxiliaryOriginalHoursDto.setOneHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getOneHours().compareTo(auxiliaryOriginalHoursDto.getOneHours()) != 0) {
+ auxiliaryOriginalHoursDto.setOne(1);
+ }
+ }
+ break;
+ case "02":
+ auxiliaryOriginalHoursDto.setTwoHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwoHours().compareTo(auxiliaryOriginalHoursDto.getTwoHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwo(1);
+ }
+ }
+ break;
+ case "03":
+ auxiliaryOriginalHoursDto.setThreeHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getThreeHours().compareTo(auxiliaryOriginalHoursDto.getThreeHours()) != 0) {
+ auxiliaryOriginalHoursDto.setThree(1);
+ }
+ }
+ break;
+ case "04":
+ auxiliaryOriginalHoursDto.setFourHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getFourHours().compareTo(auxiliaryOriginalHoursDto.getFourHours()) != 0) {
+ auxiliaryOriginalHoursDto.setFour(1);
+ }
+ }
+ break;
+ case "05":
+ auxiliaryOriginalHoursDto.setFiveHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getFiveHours().compareTo(auxiliaryOriginalHoursDto.getFiveHours()) != 0) {
+ auxiliaryOriginalHoursDto.setFive(1);
+ }
+ }
+ break;
+ case "06":
+ auxiliaryOriginalHoursDto.setSixHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getSixHours().compareTo(auxiliaryOriginalHoursDto.getSixHours()) != 0) {
+ auxiliaryOriginalHoursDto.setSix(1);
+ }
+ }
+ break;
+ case "07":
+ auxiliaryOriginalHoursDto.setSevenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getSevenHours().compareTo(auxiliaryOriginalHoursDto.getSevenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setSeven(1);
+ }
+ }
+ break;
+ case "08":
+ auxiliaryOriginalHoursDto.setEightHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getEightHours().compareTo(auxiliaryOriginalHoursDto.getEightHours()) != 0) {
+ auxiliaryOriginalHoursDto.setEight(1);
+ }
+ }
+ break;
+ case "09":
+ auxiliaryOriginalHoursDto.setNineHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getNineHours().compareTo(auxiliaryOriginalHoursDto.getNineHours()) != 0) {
+ auxiliaryOriginalHoursDto.setNine(1);
+ }
+ }
+ break;
+ case "10":
+ auxiliaryOriginalHoursDto.setTenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTenHours().compareTo(auxiliaryOriginalHoursDto.getTenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTen(1);
+ }
+ }
+ break;
+ case "11":
+ auxiliaryOriginalHoursDto.setElevenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getElevenHours().compareTo(auxiliaryOriginalHoursDto.getElevenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setEleven(1);
+ }
+ }
+ break;
+ case "12":
+ auxiliaryOriginalHoursDto.setTwelveHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwelveHours().compareTo(auxiliaryOriginalHoursDto.getTwelveHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwelve(1);
+ }
+ }
+ break;
+ case "13":
+ auxiliaryOriginalHoursDto.setThirteenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getThirteenHours().compareTo(auxiliaryOriginalHoursDto.getThirteenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setThirteen(1);
+ }
+ }
+ break;
+ case "14":
+ auxiliaryOriginalHoursDto.setFourteenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getFourteenHours().compareTo(auxiliaryOriginalHoursDto.getFourteenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setFourteen(1);
+ }
+ }
+ break;
+ case "15":
+ auxiliaryOriginalHoursDto.setFifteenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getFifteenHours().compareTo(auxiliaryOriginalHoursDto.getFifteenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setFifteen(1);
+ }
+ }
+ break;
+ case "16":
+ auxiliaryOriginalHoursDto.setSixteenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getSixteenHours().compareTo(auxiliaryOriginalHoursDto.getSixteenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setSixteen(1);
+ }
+ }
+ break;
+ case "17":
+ auxiliaryOriginalHoursDto.setSeventeenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getSeventeenHours().compareTo(auxiliaryOriginalHoursDto.getSeventeenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setSeventeen(1);
+ }
+ }
+ break;
+ case "18":
+ auxiliaryOriginalHoursDto.setEighteenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getEighteenHours().compareTo(auxiliaryOriginalHoursDto.getEighteenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setEighteen(1);
+ }
+ }
+ break;
+ case "19":
+ auxiliaryOriginalHoursDto.setNineteenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getNineteenHours().compareTo(auxiliaryOriginalHoursDto.getNineteenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setNineteen(1);
+ }
+ }
+ break;
+ case "20":
+ auxiliaryOriginalHoursDto.setTwentyHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyHours().compareTo(auxiliaryOriginalHoursDto.getTwentyHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwenty(1);
+ }
+ }
+ break;
+ case "21":
+ auxiliaryOriginalHoursDto.setTwentyOneHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyOneHours().compareTo(auxiliaryOriginalHoursDto.getTwentyOneHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentyOne(1);
+ }
+ }
+ break;
+ case "22":
+ auxiliaryOriginalHoursDto.setTwentyTwoHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyTwoHours().compareTo(auxiliaryOriginalHoursDto.getTwentyTwoHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentyTwo(1);
+ }
+ }
+ break;
+ case "23":
+ auxiliaryOriginalHoursDto.setTwentyThreeHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyThreeHours().compareTo(auxiliaryOriginalHoursDto.getTwentyThreeHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentyThree(1);
+ }
+ }
+ break;
+ case "24":
+ auxiliaryOriginalHoursDto.setTwentyFourHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyFourHours().compareTo(auxiliaryOriginalHoursDto.getTwentyFourHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentyFour(1);
+ }
+ }
+ break;
+ case "25":
+ auxiliaryOriginalHoursDto.setTwentyFiveHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyFiveHours().compareTo(auxiliaryOriginalHoursDto.getTwentyFiveHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentyFive(1);
+ }
+ }
+ break;
+ case "26":
+ auxiliaryOriginalHoursDto.setTwentySixHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentySixHours().compareTo(auxiliaryOriginalHoursDto.getTwentySixHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentySix(1);
+ }
+ }
+ break;
+ case "27":
+ auxiliaryOriginalHoursDto.setTwentySevenHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentySevenHours().compareTo(auxiliaryOriginalHoursDto.getTwentySevenHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentySeven(1);
+ }
+ }
+ break;
+ case "28":
+ auxiliaryOriginalHoursDto.setTwentyEightHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyEightHours().compareTo(auxiliaryOriginalHoursDto.getTwentyEightHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentyEight(1);
+ }
+ }
+ break;
+ case "29":
+ auxiliaryOriginalHoursDto.setTwentyNineHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getTwentyNineHours().compareTo(auxiliaryOriginalHoursDto.getTwentyNineHours()) != 0) {
+ auxiliaryOriginalHoursDto.setTwentyNine(1);
+ }
+ }
+ break;
+ case "30":
+ auxiliaryOriginalHoursDto.setThirtyHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getThirtyHours().compareTo(auxiliaryOriginalHoursDto.getThirtyHours()) != 0) {
+ auxiliaryOriginalHoursDto.setThirty(1);
+ }
+ }
+ break;
+ case "31":
+ auxiliaryOriginalHoursDto.setThirtyOneHours(new BigDecimal(objectMap.get("manHours").toString()));
+ if (ObjectUtils.isNotEmpty(auxiliaryCorrectionHours)) {
+ if (auxiliaryCorrectionHours.getThirtyOneHours().compareTo(auxiliaryOriginalHoursDto.getThirtyOneHours()) != 0) {
+ auxiliaryOriginalHoursDto.setThirtyOne(1);
+ }
+ }
+ break;
+ }
+ auxiliaryOriginalHoursDto.setTotal((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getOneHours()) ? auxiliaryOriginalHoursDto.getOneHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThreeHours()) ? auxiliaryOriginalHoursDto.getThreeHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFourHours()) ? auxiliaryOriginalHoursDto.getFourHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFiveHours()) ? auxiliaryOriginalHoursDto.getFiveHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSixHours()) ? auxiliaryOriginalHoursDto.getSixHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSevenHours()) ? auxiliaryOriginalHoursDto.getSevenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getEightHours()) ? auxiliaryOriginalHoursDto.getEightHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getNineHours()) ? auxiliaryOriginalHoursDto.getNineHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTenHours()) ? auxiliaryOriginalHoursDto.getTenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getElevenHours()) ? auxiliaryOriginalHoursDto.getElevenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwelveHours()) ? auxiliaryOriginalHoursDto.getTwelveHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThirteenHours()) ? auxiliaryOriginalHoursDto.getThirteenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFourteenHours()) ? auxiliaryOriginalHoursDto.getFourteenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFifteenHours()) ? auxiliaryOriginalHoursDto.getFifteenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSixteenHours()) ? auxiliaryOriginalHoursDto.getSixteenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSeventeenHours()) ? auxiliaryOriginalHoursDto.getSeventeenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getEighteenHours()) ? auxiliaryOriginalHoursDto.getEighteenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getNineteenHours()) ? auxiliaryOriginalHoursDto.getNineteenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyHours()) ? auxiliaryOriginalHoursDto.getTwentyHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyOneHours()) ? auxiliaryOriginalHoursDto.getTwentyOneHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyTwoHours()) ? auxiliaryOriginalHoursDto.getTwentyTwoHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyThreeHours()) ? auxiliaryOriginalHoursDto.getTwentyThreeHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyFourHours()) ? auxiliaryOriginalHoursDto.getTwentyFourHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyFiveHours()) ? auxiliaryOriginalHoursDto.getTwentyFiveHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentySixHours()) ? auxiliaryOriginalHoursDto.getTwentySixHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentySevenHours()) ? auxiliaryOriginalHoursDto.getTwentySevenHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyEightHours()) ? auxiliaryOriginalHoursDto.getTwentyEightHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyNineHours()) ? auxiliaryOriginalHoursDto.getTwentyNineHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThirtyHours()) ? auxiliaryOriginalHoursDto.getThirtyHours() : BigDecimal.ZERO)
+ .add(ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThirtyOneHours()) ? auxiliaryOriginalHoursDto.getThirtyOneHours() : BigDecimal.ZERO)
+ );
+ auxiliaryOriginalHoursDto.setTotal(auxiliaryOriginalHoursDto.getTotal().setScale(4, RoundingMode.HALF_UP));
+
+ dtoMap.put(name, auxiliaryOriginalHoursDto);
+ }
+ return dtoMap;
+ }
+
+ //鍚堝苟
+ private void merge(Map<String, AuxiliaryOriginalHoursDto> data5, Map<String, AuxiliaryOriginalHoursDto> data4, Map<String, AuxiliaryOriginalHoursDto> data2) {
+ for (Map.Entry<String, AuxiliaryOriginalHoursDto> entry : data2.entrySet()) {
+ String key = entry.getKey();
+ AuxiliaryOriginalHoursDto value = entry.getValue();
+ if (data5.containsKey(key)) {
+ for (Map.Entry<String, AuxiliaryOriginalHoursDto> dtoEntry : data5.entrySet()) {
+ if (dtoEntry.getKey().equals(key)) {
+ AuxiliaryOriginalHoursDto auxiliaryOriginalHoursDto = new AuxiliaryOriginalHoursDto();
+ AuxiliaryOriginalHoursDto hoursDto = data5.get(key);
+ BeanUtils.copyProperties(hoursDto, auxiliaryOriginalHoursDto);
+ auxiliaryOriginalHoursDto.setType("鎬诲伐鏃�");
+ auxiliaryOriginalHoursDto.setOneHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getOneHours()) ? auxiliaryOriginalHoursDto.getOneHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getOneHours()) ? value.getOneHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwoHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwoHours()) ? auxiliaryOriginalHoursDto.getTwoHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwoHours()) ? value.getTwoHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setThreeHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThreeHours()) ? auxiliaryOriginalHoursDto.getThreeHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getThreeHours()) ? value.getThreeHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setFourHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFourHours()) ? auxiliaryOriginalHoursDto.getFourHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getFourHours()) ? value.getFourHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setFiveHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFiveHours()) ? auxiliaryOriginalHoursDto.getFiveHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getFiveHours()) ? value.getFiveHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setSixHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSixHours()) ? auxiliaryOriginalHoursDto.getSixHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getSixHours()) ? value.getSixHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setSevenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSevenHours()) ? auxiliaryOriginalHoursDto.getSevenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getSevenHours()) ? value.getSevenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setEightHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getEightHours()) ? auxiliaryOriginalHoursDto.getEightHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getEightHours()) ? value.getEightHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setNineHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getNineHours()) ? auxiliaryOriginalHoursDto.getNineHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getNineHours()) ? value.getNineHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTenHours()) ? auxiliaryOriginalHoursDto.getTenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTenHours()) ? value.getTenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setElevenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getElevenHours()) ? auxiliaryOriginalHoursDto.getElevenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getElevenHours()) ? value.getElevenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwelveHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwelveHours()) ? auxiliaryOriginalHoursDto.getTwelveHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwelveHours()) ? value.getTwelveHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setThirteenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThirteenHours()) ? auxiliaryOriginalHoursDto.getThirteenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getThirteenHours()) ? value.getThirteenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setFourteenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFourteenHours()) ? auxiliaryOriginalHoursDto.getFourteenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getFourteenHours()) ? value.getFourteenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setFifteenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getFifteenHours()) ? auxiliaryOriginalHoursDto.getFifteenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getFifteenHours()) ? value.getFifteenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setSixteenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSixteenHours()) ? auxiliaryOriginalHoursDto.getSixteenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getSixteenHours()) ? value.getSixteenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setSeventeenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getSeventeenHours()) ? auxiliaryOriginalHoursDto.getSeventeenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getSeventeenHours()) ? value.getSeventeenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setEighteenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getEighteenHours()) ? auxiliaryOriginalHoursDto.getEighteenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getEighteenHours()) ? value.getEighteenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setNineteenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getNineteenHours()) ? auxiliaryOriginalHoursDto.getNineteenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getNineteenHours()) ? value.getNineteenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwelveHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwelveHours()) ? auxiliaryOriginalHoursDto.getTwelveHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwelveHours()) ? value.getTwelveHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentyOneHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyOneHours()) ? auxiliaryOriginalHoursDto.getTwentyOneHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentyOneHours()) ? value.getTwentyOneHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentyTwoHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyTwoHours()) ? auxiliaryOriginalHoursDto.getTwentyTwoHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentyTwoHours()) ? value.getTwentyTwoHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentyThreeHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyThreeHours()) ? auxiliaryOriginalHoursDto.getTwentyThreeHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentyThreeHours()) ? value.getTwentyThreeHours() : BigDecimal.ZERO));
+ BigDecimal v = ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyFourHours()) ? auxiliaryOriginalHoursDto.getTwentyFourHours() : BigDecimal.ZERO;
+ BigDecimal v1 = ObjectUtils.isNotEmpty(value.getTwentyFourHours()) ? value.getTwentyFourHours() : BigDecimal.ZERO;
+ BigDecimal v2 = v.add(v1);
+ auxiliaryOriginalHoursDto.setTwentyFourHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyFourHours()) ? auxiliaryOriginalHoursDto.getTwentyFourHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentyFourHours()) ? value.getTwentyFourHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentyFiveHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyFiveHours()) ? auxiliaryOriginalHoursDto.getTwentyFiveHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentyFiveHours()) ? value.getTwentyFiveHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentySixHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentySixHours()) ? auxiliaryOriginalHoursDto.getTwentySixHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentySixHours()) ? value.getTwentySixHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentySevenHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentySevenHours()) ? auxiliaryOriginalHoursDto.getTwentySevenHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentySevenHours()) ? value.getTwentySevenHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentyEightHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyEightHours()) ? auxiliaryOriginalHoursDto.getTwentyEightHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentyEightHours()) ? value.getTwentyEightHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTwentyNineHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTwentyNineHours()) ? auxiliaryOriginalHoursDto.getTwentyNineHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTwentyNineHours()) ? value.getTwentyNineHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setThirtyHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThirtyHours()) ? auxiliaryOriginalHoursDto.getThirtyHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getThirtyHours()) ? value.getThirtyHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setThirtyOneHours((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getThirtyOneHours()) ? auxiliaryOriginalHoursDto.getThirtyOneHours() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getThirtyOneHours()) ? value.getThirtyOneHours() : BigDecimal.ZERO));
+ auxiliaryOriginalHoursDto.setTotal((ObjectUtils.isNotEmpty(auxiliaryOriginalHoursDto.getTotal()) ? auxiliaryOriginalHoursDto.getTotal() : BigDecimal.ZERO).add(ObjectUtils.isNotEmpty(value.getTotal()) ? value.getTotal() : BigDecimal.ZERO));
+ data4.put(key, auxiliaryOriginalHoursDto);
+ } /*else {
+ AuxiliaryOriginalHoursDto hoursDto = data5.get(dtoEntry.getKey());
+ AuxiliaryOriginalHoursDto dto = new AuxiliaryOriginalHoursDto();
+ BeanUtils.copyProperties(hoursDto, dto);
+ dto.setType("鎬诲伐鏃�");
+ data4.put(dtoEntry.getKey(), dto);
+ }*/
+ }
+ } else {
+ value.setType("鎬诲伐鏃�");
+ data4.put(key, value);
+ }
+ }
+
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOutputWorkingHoursServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOutputWorkingHoursServiceImpl.java
new file mode 100644
index 0000000..d087d07
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryOutputWorkingHoursServiceImpl.java
@@ -0,0 +1,260 @@
+package com.ruoyi.performance.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.performance.dto.AuxiliaryOutputWorkingHoursDto;
+import com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto;
+import com.ruoyi.performance.mapper.AuxiliaryOutputWorkingHoursMapper;
+import com.ruoyi.performance.mapper.AuxiliaryWorkingHoursDayMapper;
+import com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay;
+import com.ruoyi.performance.service.AuxiliaryOutputWorkingHoursService;
+import com.ruoyi.system.mapper.UserMapper;
+import org.apache.commons.math3.analysis.function.Power;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.math.BigDecimal;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑浜ч噺宸ユ椂 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 03:48:48
+ */
+@Service
+public class AuxiliaryOutputWorkingHoursServiceImpl extends ServiceImpl<AuxiliaryOutputWorkingHoursMapper, AuxiliaryOutputWorkingHours> implements AuxiliaryOutputWorkingHoursService {
+
+ @Resource
+ AuxiliaryOutputWorkingHoursMapper auxiliaryOutputWorkingHoursMapper;
+
+ @Resource
+ AuxiliaryWorkingHoursDayMapper auxiliaryWorkingHoursDayMapper;
+
+ @Resource
+ UserMapper userMapper;
+
+ @Override
+ public IPage<AuxiliaryOutputWorkingHoursDto> selectAuxiliaryOutputWorkingHours(Page page, AuxiliaryOutputWorkingHoursDto auxiliaryOutputWorkingHoursDto) {
+ String dates = auxiliaryOutputWorkingHoursDto.getDateTime();
+ String week = auxiliaryOutputWorkingHoursDto.getWeek();
+ auxiliaryOutputWorkingHoursDto.setDateTime(null);
+ auxiliaryOutputWorkingHoursDto.setWeek(null);
+ List<Long> ids = new ArrayList<>();
+ if (ids.size() == 0) {
+ ids = null;
+ }
+ if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ IPage<AuxiliaryOutputWorkingHoursDto> auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHours(page,
+ QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59")
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+ for (AuxiliaryOutputWorkingHoursDto record : auxiliaryOutputWorkingHoursDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0,10));
+ }
+ return auxiliaryOutputWorkingHoursDtoIPage ;
+ } else if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ IPage<AuxiliaryOutputWorkingHoursDto> auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHours(page,
+ QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59"), ids);
+ for (AuxiliaryOutputWorkingHoursDto record : auxiliaryOutputWorkingHoursDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0,10));
+ }
+ return auxiliaryOutputWorkingHoursDtoIPage ;
+ } else if (ObjectUtils.isEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ IPage<AuxiliaryOutputWorkingHoursDto> auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHours(page,
+ QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto)
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+ for (AuxiliaryOutputWorkingHoursDto record : auxiliaryOutputWorkingHoursDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0,10));
+ }
+ return auxiliaryOutputWorkingHoursDtoIPage ;
+ } else {
+ IPage<AuxiliaryOutputWorkingHoursDto> auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHours(page, QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto), ids);
+ for (AuxiliaryOutputWorkingHoursDto record : auxiliaryOutputWorkingHoursDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0,10));
+ }
+ return auxiliaryOutputWorkingHoursDtoIPage ;
+ }
+ }
+
+ //缁熻浜ч噺宸ユ椂姹囨�诲拰杈呭姪宸ユ椂姹囨��
+ @Override
+ public Map<String, Object> collectWorkingHours(AuxiliaryOutputWorkingHoursDto auxiliaryOutputWorkingHoursDto) {
+ AuxiliaryOutputWorkingHours outputWorkingHours = new AuxiliaryOutputWorkingHours();
+ AuxiliaryWorkingHoursDay workingHoursDay = new AuxiliaryWorkingHoursDay();
+ List<Long> ids = new ArrayList<>();
+ if (ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHoursDto.getWeekDay())){
+ outputWorkingHours.setWeekDay(auxiliaryOutputWorkingHoursDto.getWeekDay());
+ workingHoursDay.setWeekDay(auxiliaryOutputWorkingHoursDto.getWeekDay());
+ }
+ if (ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHoursDto.getName())){
+ List<User> user = userMapper.selectList(Wrappers.<User>lambdaQuery().like(User::getName, auxiliaryOutputWorkingHoursDto.getName()));
+ ids.addAll(user.stream().map(User::getId).collect(Collectors.toList()));
+ }
+ String dates = auxiliaryOutputWorkingHoursDto.getDateTime();
+ auxiliaryOutputWorkingHoursDto.setDateTime(null);
+ Map<String, Object> map = new HashMap<>();
+ BigDecimal sumOutputWorkTime = BigDecimal.ZERO;
+ BigDecimal sumApprovedWorkingHour = BigDecimal.ZERO;
+
+ //鍒ゆ柇鏄粍闀胯繕鏄粍鍛樿繕鏄鐞嗗憳
+ List<AuxiliaryOutputWorkingHours> auxiliaryOutputWorkingHours = new ArrayList<>();
+ List<AuxiliaryWorkingHoursDay> auxiliaryWorkingHoursDays = new ArrayList<>();
+ if (ids.size() == 0) {
+ ids=null;
+ }
+ if (ObjectUtils.isNotEmpty(dates)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ //缁熻褰撳墠鐢ㄦ埛鐨勪骇鍝佸伐鏃�
+ auxiliaryOutputWorkingHours = auxiliaryOutputWorkingHoursMapper.selectLists(QueryWrappers.queryWrappers(outputWorkingHours)
+ .ge("date_time", split[0])
+ .le("date_time", split[1] + " 23:59:59"),ids);
+ //缁熻褰撳墠鐢ㄦ埛鐨勮緟鍔╁伐鏃�
+ auxiliaryWorkingHoursDays = auxiliaryWorkingHoursDayMapper.selectLists(QueryWrappers.queryWrappers(workingHoursDay)
+ .eq("state","宸叉壒鍑�")
+ .ge("date_time", split[0])
+ .le("date_time", split[1] + " 23:59:59"),ids);
+ }else if (ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHoursDto.getWeekDay())){
+ //缁熻褰撳墠鐢ㄦ埛鐨勪骇鍝佸伐鏃�
+ auxiliaryOutputWorkingHours = auxiliaryOutputWorkingHoursMapper.selectLists(QueryWrappers.queryWrappers(outputWorkingHours),ids);
+ //缁熻褰撳墠鐢ㄦ埛鐨勮緟鍔╁伐鏃�
+ auxiliaryWorkingHoursDays = auxiliaryWorkingHoursDayMapper.selectLists(QueryWrappers.queryWrappers(workingHoursDay).eq("state","宸叉壒鍑�"),ids);
+ }
+ else {
+ auxiliaryOutputWorkingHours = auxiliaryOutputWorkingHoursMapper.selectListByIds(ids);
+ auxiliaryWorkingHoursDays = auxiliaryWorkingHoursDayMapper.selectListByIds(ids);
+ }
+ if (ObjectUtils.isNotEmpty(auxiliaryOutputWorkingHours)) {
+ Map<String, BigDecimal> sumMap = new HashMap<>();
+ for (AuxiliaryOutputWorkingHours auxiliaryOutputWorkingHour : auxiliaryOutputWorkingHours) {
+ if (!sumMap.containsKey(auxiliaryOutputWorkingHour.getManHourGroup()+auxiliaryOutputWorkingHour.getOrderNo()+auxiliaryOutputWorkingHour.getSample())) {
+ sumMap.put(auxiliaryOutputWorkingHour.getManHourGroup()+auxiliaryOutputWorkingHour.getOrderNo()+auxiliaryOutputWorkingHour.getSample(), auxiliaryOutputWorkingHour.getOutputWorkTime());
+ }
+ }
+ sumOutputWorkTime = sumMap.values().stream().reduce(BigDecimal.ZERO, BigDecimal::add);
+ }
+ map.put("浜ч噺宸ユ椂姹囨��", sumOutputWorkTime);
+ if (ObjectUtils.isNotEmpty(auxiliaryWorkingHoursDays)) {
+ for (AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay : auxiliaryWorkingHoursDays) {
+ sumApprovedWorkingHour = sumApprovedWorkingHour.add(auxiliaryWorkingHoursDay.getReviewerNonproductiveTime());//澶嶆牳宸ユ椂
+ }
+ }
+ map.put("杈呭姪宸ユ椂姹囨��", sumApprovedWorkingHour);
+ return map;
+ }
+
+ //瀵煎嚭
+ @Override
+ public void exportWorkingHours(HttpServletResponse response) throws IOException {
+ List<AuxiliaryOutputWorkingHoursDto> auxiliaryOutputWorkingHoursDtos = new ArrayList<>();
+ List<AuxiliaryWorkingHoursDayDto> auxiliaryWorkingHoursDayDtos = new ArrayList<>();
+ List<Long> ids = new ArrayList<>();
+ //鏌ヨ杈呭姪宸ユ椂
+ auxiliaryWorkingHoursDayDtos = auxiliaryWorkingHoursDayMapper.selectDataByUser(ids);
+ //鏌ヨ缁熻宸ユ椂
+ auxiliaryOutputWorkingHoursDtos = auxiliaryOutputWorkingHoursMapper.selectDataByUser(ids);
+ response.setContentType("application/vnd.ms-excel");
+ response.setCharacterEncoding("UTF-8");
+ // 杩欓噷URLEncoder.encode鍙互闃叉涓枃涔辩爜 褰撶劧鍜宔asyexcel娌℃湁鍏崇郴
+ String fileName = URLEncoder.encode("鏃ュ伐鏃剁鐞嗗鍑�", "UTF-8");
+ response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+ try {
+ // 鏂板缓ExcelWriter
+ ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
+
+ WriteSheet mainSheet = EasyExcel.writerSheet(0, "杈呭姪宸ユ椂瀵煎嚭").head(AuxiliaryWorkingHoursDayDto.class).build();
+ excelWriter.write(auxiliaryWorkingHoursDayDtos, mainSheet);
+
+ WriteSheet mainSheet1 = EasyExcel.writerSheet(1, "浜ч噺宸ユ椂瀵煎嚭").head(AuxiliaryOutputWorkingHoursDto.class).build();
+ excelWriter.write(auxiliaryOutputWorkingHoursDtos, mainSheet1);
+ // 鍏抽棴娴�
+ excelWriter.finish();
+ } catch (IOException e) {
+ throw new RuntimeException("瀵煎嚭澶辫触");
+ }
+ }
+
+ /**
+ * 瀵煎嚭浜ч噺宸ユ椂
+ * @param response
+ */
+ @Override
+ public void exportOutputHours(AuxiliaryOutputWorkingHoursDto auxiliaryOutputWorkingHoursDto, HttpServletResponse response) {
+ //鏌ヨ瀵煎嚭鐨勮垂鐢ㄧ粺璁℃暟鎹�
+ String dates = auxiliaryOutputWorkingHoursDto.getDateTime();
+ String week = auxiliaryOutputWorkingHoursDto.getWeek();
+ auxiliaryOutputWorkingHoursDto.setDateTime(null);
+ auxiliaryOutputWorkingHoursDto.setWeek(null);
+
+ List<Long> ids = new ArrayList<>();
+ String name = auxiliaryOutputWorkingHoursDto.getName();
+ if (ObjectUtils.isNotEmpty(name)) {
+ ids.addAll(userMapper.selectList(Wrappers.<User>lambdaQuery().like(User::getName, name)).stream().map(User::getId).collect(Collectors.toList()));
+ }
+
+ List<AuxiliaryOutputWorkingHoursDto> auxiliaryOutputWorkingHoursDtoIPage = new ArrayList<>();
+ if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHoursList(QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59")
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+
+ } else if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHoursList(QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59"), ids);
+
+ } else if (ObjectUtils.isEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHoursList(QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto)
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+
+ } else {
+ auxiliaryOutputWorkingHoursDtoIPage = auxiliaryOutputWorkingHoursMapper.selectAuxiliaryOutputWorkingHoursList(QueryWrappers.queryWrappers(auxiliaryOutputWorkingHoursDto), ids);
+ }
+
+ try {
+ response.setContentType("application/vnd.ms-excel");
+ response.setCharacterEncoding("UTF-8");
+ // 杩欓噷URLEncoder.encode鍙互闃叉涓枃涔辩爜 褰撶劧鍜宔asyexcel娌℃湁鍏崇郴
+ String fileName = URLEncoder.encode("浜ч噺宸ユ椂淇℃伅瀵煎嚭", "UTF-8");
+ response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+ //鏂板缓ExcelWriter
+ ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
+ //鑾峰彇sheet0瀵硅薄
+ WriteSheet mainSheet = EasyExcel.writerSheet(0, "浜ч噺宸ユ椂淇℃伅瀵煎嚭").head(AuxiliaryOutputWorkingHoursDto.class).build();
+
+ //鍚憇heet0鍐欏叆鏁版嵁 浼犲叆绌簂ist杩欐牱鍙鍑鸿〃澶�
+ excelWriter.write(auxiliaryOutputWorkingHoursDtoIPage, mainSheet);
+ //鍏抽棴娴�
+ excelWriter.finish();
+ } catch (IOException e) {
+ throw new RuntimeException("瀵煎嚭澶辫触");
+ }
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursDayServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursDayServiceImpl.java
new file mode 100644
index 0000000..55fa4c2
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursDayServiceImpl.java
@@ -0,0 +1,232 @@
+package com.ruoyi.performance.service.impl;
+
+import com.alibaba.excel.EasyExcel;
+import com.alibaba.excel.ExcelWriter;
+import com.alibaba.excel.write.metadata.WriteSheet;
+import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto;
+import com.ruoyi.performance.dto.HoursDay;
+import com.ruoyi.performance.mapper.AuxiliaryWorkingHoursDayMapper;
+import com.ruoyi.performance.mapper.AuxiliaryWorkingHoursMapper;
+import com.ruoyi.performance.mapper.PerformanceShiftMapper;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHours;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay;
+import com.ruoyi.performance.pojo.PerformanceShift;
+import com.ruoyi.performance.service.AuxiliaryWorkingHoursDayService;
+import com.ruoyi.system.mapper.UserMapper;
+import org.apache.commons.math3.analysis.function.Power;
+import org.springframework.beans.BeanUtils;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URLEncoder;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 鏃ュ伐鏃剁鐞嗙殑杈呭姪宸ユ椂 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-28 02:22:19
+ */
+@Service
+public class AuxiliaryWorkingHoursDayServiceImpl extends ServiceImpl<AuxiliaryWorkingHoursDayMapper, AuxiliaryWorkingHoursDay> implements AuxiliaryWorkingHoursDayService {
+
+ @Resource
+ AuxiliaryWorkingHoursDayMapper auxiliaryWorkingHoursDayMapper;
+
+ @Resource
+ AuxiliaryWorkingHoursMapper auxiliaryWorkingHoursMapper;
+
+ @Resource
+ UserMapper userMapper;
+
+ @Resource
+ PerformanceShiftMapper performanceShiftMapper;
+
+ @Override
+ public IPage<AuxiliaryWorkingHoursDayDto> selectAuxiliaryWorkingHoursDay(Page page, AuxiliaryWorkingHoursDayDto auxiliaryWorkingHoursDayDto) {
+ String dates = auxiliaryWorkingHoursDayDto.getDateTime();
+ String week = auxiliaryWorkingHoursDayDto.getWeek();
+ auxiliaryWorkingHoursDayDto.setDateTime(null);
+ auxiliaryWorkingHoursDayDto.setWeek(null);
+ Map<String, Object> map = new HashMap<>();
+ List<Long> ids = new ArrayList<>();
+ if (ids.size() == 0) {
+ ids = null;
+ }
+ if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ IPage<AuxiliaryWorkingHoursDayDto> auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDay(page,
+ QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59")
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+ for (AuxiliaryWorkingHoursDayDto record : auxiliaryWorkingHoursDayDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0, 10));
+ }
+ return auxiliaryWorkingHoursDayDtoIPage;
+ } else if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ IPage<AuxiliaryWorkingHoursDayDto> auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDay(page,
+ QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59"), ids);
+ for (AuxiliaryWorkingHoursDayDto record : auxiliaryWorkingHoursDayDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0, 10));
+ }
+ return auxiliaryWorkingHoursDayDtoIPage;
+ } else if (ObjectUtils.isEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ IPage<AuxiliaryWorkingHoursDayDto> auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDay(page,
+ QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto)
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+ for (AuxiliaryWorkingHoursDayDto record : auxiliaryWorkingHoursDayDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0, 10));
+ }
+ return auxiliaryWorkingHoursDayDtoIPage;
+ } else {
+ IPage<AuxiliaryWorkingHoursDayDto> auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDay(page, QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto), ids);
+ for (AuxiliaryWorkingHoursDayDto record : auxiliaryWorkingHoursDayDtoIPage.getRecords()) {
+ record.setDateTime(record.getDateTime().substring(0, 10));
+ }
+ return auxiliaryWorkingHoursDayDtoIPage;
+ }
+
+ }
+
+ //鏍规嵁缂栧彿鏌ヨ杈呭姪宸ユ椂閰嶇疆淇℃伅
+ @Override
+ public AuxiliaryWorkingHoursDay selectAuxiliaryWorkingHoursByNumber(String number) {
+ //鏍规嵁濉啓鐨勭紪鍙锋煡璇㈣緟鍔╁伐鏃堕厤缃�
+ AuxiliaryWorkingHours auxiliaryWorkingHours = auxiliaryWorkingHoursMapper.selectOne(Wrappers.<AuxiliaryWorkingHours>lambdaQuery().eq(AuxiliaryWorkingHours::getNumber, number));
+ if (ObjectUtils.isEmpty(auxiliaryWorkingHours)) {
+ throw new BaseException("璇ョ紪鍙锋病鏈夊搴旂殑杈呭姪宸ユ椂閰嶇疆");
+ }
+ AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay = new AuxiliaryWorkingHoursDay();
+ BeanUtils.copyProperties(auxiliaryWorkingHours, auxiliaryWorkingHoursDay);
+ return auxiliaryWorkingHoursDay;
+ }
+
+ //褰曞叆鏁版嵁(鏂板)
+ @Override
+ public int insertAuxiliaryWorkingHoursDay(AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay) {
+ Integer userId = SecurityUtils.getUserId().intValue();
+ auxiliaryWorkingHoursDay.setNameUser(userId);//濮撳悕id
+ auxiliaryWorkingHoursDay.setState("宸叉彁浜�");
+ return auxiliaryWorkingHoursDayMapper.insert(auxiliaryWorkingHoursDay);
+ }
+
+ //瀹℃牳/鎵瑰噯
+ @Override
+ public boolean checkOrApprove(HoursDay hoursDay) {
+ List<AuxiliaryWorkingHoursDay> auxiliaryWorkingHoursDays = hoursDay.getAuxiliaryWorkingHoursDays();
+ for (AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay : auxiliaryWorkingHoursDays) {
+ Integer userId = SecurityUtils.getUserId().intValue();
+ auxiliaryWorkingHoursDay.setReviewer(userMapper.selectById(userId).getName());
+ if (auxiliaryWorkingHoursDay.getReviewerNumber() == null) {
+ auxiliaryWorkingHoursDay.setReviewerNumber(auxiliaryWorkingHoursDay.getAmount());//澶嶆牳鏁伴噺
+ auxiliaryWorkingHoursDay.setReviewerNonproductiveTime(auxiliaryWorkingHoursDay.getNonproductiveTime());//澶嶆牳宸ユ椂
+ }
+ }
+ return updateBatchById(auxiliaryWorkingHoursDays);
+ }
+
+ //缂栬緫
+ @Override
+ public int updateAuxiliaryWorkingHoursDay(AuxiliaryWorkingHoursDay auxiliaryWorkingHoursDay) {
+ Integer userId = SecurityUtils.getUserId().intValue();
+ auxiliaryWorkingHoursDay.setNameUser(userId);//濮撳悕id
+ return auxiliaryWorkingHoursDayMapper.updateById(auxiliaryWorkingHoursDay);
+ }
+
+ //鍒犻櫎
+ @Override
+ public int deleteAuxiliaryWorkingHoursDay(Integer id) {
+ return auxiliaryWorkingHoursDayMapper.deleteById(id);
+ }
+
+ //鏍规嵁缂栧彿褰撳墠鐢ㄦ埛淇℃伅鏌ヨ鎵�鍦ㄧ彮娆�
+ @Override
+ public String selectshiftByUser(LocalDateTime dateTime) {
+ Integer userId = SecurityUtils.getUserId().intValue();
+ PerformanceShift performanceShift = performanceShiftMapper.selectOne(Wrappers.<PerformanceShift>lambdaQuery().eq(PerformanceShift::getUserId, userId).eq(PerformanceShift::getWorkTime, dateTime));
+ if (ObjectUtils.isEmpty(performanceShift)) {
+ return null;
+ }
+ return performanceShift.getShift();
+ }
+
+ /**
+ * 瀵煎嚭杈呭姪宸ユ椂
+ * @param
+ * @param response
+ */
+ @Override
+ public void exportWorkingHours(AuxiliaryWorkingHoursDayDto auxiliaryWorkingHoursDayDto, HttpServletResponse response) {
+ String dates = auxiliaryWorkingHoursDayDto.getDateTime();
+ String week = auxiliaryWorkingHoursDayDto.getWeek();
+ auxiliaryWorkingHoursDayDto.setDateTime(null);
+ auxiliaryWorkingHoursDayDto.setWeek(null);
+ List<Long> ids = new ArrayList<>();
+ String name = auxiliaryWorkingHoursDayDto.getName();
+ if (ObjectUtils.isNotEmpty(name)) {
+ ids.addAll(userMapper.selectList(Wrappers.<User>lambdaQuery().like(User::getName, name)).stream().map(User::getId).collect(Collectors.toList()));
+ }
+ List<AuxiliaryWorkingHoursDayDto> auxiliaryWorkingHoursDayDtoIPage = new ArrayList<>();
+ if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDayList(QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59")
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+ } else if (ObjectUtils.isNotEmpty(dates) && ObjectUtils.isEmpty(week)) {
+ String[] split = dates.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDayList(QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto)
+ .ge("date_time", split[0]).le("date_time", split[1] + " 23:59:59"), ids);
+ } else if (ObjectUtils.isEmpty(dates) && ObjectUtils.isNotEmpty(week)) {
+ String[] weeks = week.replaceAll("\\[", "").replaceAll("]", "").replaceAll("\"", "").split(",");
+ auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDayList(QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto)
+ .ge("week", weeks[0]).le("week", weeks[1]), ids);
+ } else {
+ auxiliaryWorkingHoursDayDtoIPage = auxiliaryWorkingHoursDayMapper.selectAuxiliaryWorkingHoursDayList( QueryWrappers.queryWrappers(auxiliaryWorkingHoursDayDto), ids);
+ }
+
+ try {
+ response.setContentType("application/vnd.ms-excel");
+ response.setCharacterEncoding("UTF-8");
+ // 杩欓噷URLEncoder.encode鍙互闃叉涓枃涔辩爜 褰撶劧鍜宔asyexcel娌℃湁鍏崇郴
+ String fileName = URLEncoder.encode("杈呭姪宸ユ椂淇℃伅瀵煎嚭", "UTF-8");
+ response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
+ //鏂板缓ExcelWriter
+ ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).registerWriteHandler(new LongestMatchColumnWidthStyleStrategy()).build();
+ //鑾峰彇sheet0瀵硅薄
+ WriteSheet mainSheet = EasyExcel.writerSheet(0, "杈呭姪宸ユ椂淇℃伅瀵煎嚭").head(AuxiliaryWorkingHoursDayDto.class).build();
+
+ //鍚憇heet0鍐欏叆鏁版嵁 浼犲叆绌簂ist杩欐牱鍙鍑鸿〃澶�
+ excelWriter.write(auxiliaryWorkingHoursDayDtoIPage, mainSheet);
+ //鍏抽棴娴�
+ excelWriter.finish();
+ } catch (IOException e) {
+ throw new RuntimeException("瀵煎嚭澶辫触");
+ }
+ }
+
+
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursServiceImpl.java
new file mode 100644
index 0000000..9863d69
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/AuxiliaryWorkingHoursServiceImpl.java
@@ -0,0 +1,55 @@
+package com.ruoyi.performance.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.performance.mapper.AuxiliaryWorkingHoursMapper;
+import com.ruoyi.performance.pojo.AuxiliaryWorkingHours;
+import com.ruoyi.performance.service.AuxiliaryWorkingHoursService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * <p>
+ * 杈呭姪宸ユ椂 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-09 06:58:31
+ */
+@Service
+public class AuxiliaryWorkingHoursServiceImpl extends ServiceImpl<AuxiliaryWorkingHoursMapper, AuxiliaryWorkingHours> implements AuxiliaryWorkingHoursService {
+
+ @Resource
+ private AuxiliaryWorkingHoursMapper auxiliaryWorkingHoursMapper;
+ @Override
+ public IPage<AuxiliaryWorkingHours> selectAuxiliaryWorkingHours(Page page, AuxiliaryWorkingHours auxiliaryWorkingHours) {
+ return auxiliaryWorkingHoursMapper.selectAuxiliaryWorkingHours(page, QueryWrappers.queryWrappers(auxiliaryWorkingHours));
+ }
+
+ @Override
+ public int deleteAuxiliaryWorkingHours(Integer id) {
+ return auxiliaryWorkingHoursMapper.deleteById(id);
+ }
+
+ @Override
+ public int upAuxiliaryWorkingHours(AuxiliaryWorkingHours auxiliaryWorkingHours) {
+ return auxiliaryWorkingHoursMapper.updateById(auxiliaryWorkingHours);
+ }
+
+ @Override
+ public int insertAuxiliaryWorkingHours(AuxiliaryWorkingHours auxiliaryWorkingHours) {
+ //缂栧彿涓嶈兘閲嶅
+ List<String> strings = auxiliaryWorkingHoursMapper.selectList(null).stream().map(AuxiliaryWorkingHours::getNumber).distinct().collect(Collectors.toList());
+ if (strings.contains(auxiliaryWorkingHours.getNumber())){
+ throw new RuntimeException("缂栧彿涓嶈兘閲嶅!");
+ }
+ return auxiliaryWorkingHoursMapper.insert(auxiliaryWorkingHours);
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java
new file mode 100644
index 0000000..966317f
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/PerformanceShiftServiceImpl.java
@@ -0,0 +1,563 @@
+package com.ruoyi.performance.service.impl;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.common.utils.JackSonUtil;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.performance.dto.PerformanceShiftAddDto;
+import com.ruoyi.performance.dto.PerformanceShiftMapDto;
+import com.ruoyi.performance.mapper.PerformanceShiftMapper;
+import com.ruoyi.performance.pojo.PerformanceShift;
+import com.ruoyi.performance.service.PerformanceShiftService;
+import com.ruoyi.system.mapper.UserMapper;
+import com.ruoyi.system.service.ISysDictTypeService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.ObjectUtils;
+
+import java.math.BigDecimal;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.TemporalAdjusters;
+import java.util.*;
+
+/**
+ * <p>
+ * 缁╂晥绠$悊-鐝 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-05-08 09:12:04
+ */
+@Service
+public class PerformanceShiftServiceImpl extends ServiceImpl<PerformanceShiftMapper, PerformanceShift> implements PerformanceShiftService {
+
+ @Autowired
+ private ISysDictTypeService dictTypeService;
+
+ @Autowired
+ UserMapper userMapper;
+
+ @Transactional(rollbackFor = Exception.class)
+ @Override
+ public void performanceShiftAdd(PerformanceShiftAddDto performanceShiftAddDto) {
+ List<PerformanceShift> list = new ArrayList<>();
+ LocalDateTime startWeek = performanceShiftAddDto.getStartWeek();
+ LocalDateTime endWeek = performanceShiftAddDto.getEndWeek();
+
+
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ String formattedDateTime = performanceShiftAddDto.getStartWeek().format(formatter);
+ String[] splitUserId = performanceShiftAddDto.getUserId().split(",");
+ for (String userId : splitUserId) {
+ //鍒ゆ柇鏄惁璺ㄦ湀
+ boolean isMonth = startWeek.getMonthValue() != endWeek.getMonthValue();
+ if (isMonth){
+ //濡傛灉璺ㄦ湀,鍒欎袱涓湀閮藉垽鏂竴涓嬬湅鏁版嵁搴撴槸鍝釜鏈堜唤鐨勬暟鎹病鏈�
+ boolean exists1 = baseMapper.exists(Wrappers.<PerformanceShift>lambdaQuery()
+ .eq(PerformanceShift::getWorkTime, startWeek)
+ .eq(PerformanceShift::getUserId, userId));
+ boolean exists2 = baseMapper.exists(Wrappers.<PerformanceShift>lambdaQuery()
+ .eq(PerformanceShift::getWorkTime, endWeek)
+ .eq(PerformanceShift::getUserId, userId));
+ if (!exists1 && !exists2){
+ //涓や釜鏈堥兘涓嶅瓨鍦ㄦ暟鎹�
+ list = saveMonth(performanceShiftAddDto.getStartWeek(), userId, list);
+ list = saveMonth(performanceShiftAddDto.getEndWeek(), userId, list);
+ }else if (!exists1 && exists2){
+ //寮�濮嬬殑鏈堜唤涓嶅瓨鍦ㄦ暟鎹�
+ list = saveMonth(performanceShiftAddDto.getStartWeek(), userId, list);
+ }else if (exists1 && !exists2){
+ //缁撴潫鐨勬湀浠戒笉瀛樺湪鏁版嵁
+ list = saveMonth(performanceShiftAddDto.getEndWeek(), userId, list);
+ }
+ }else {
+ //涓嶈法鏈�
+ boolean exists = baseMapper.exists(Wrappers.<PerformanceShift>lambdaQuery()
+ .in(PerformanceShift::getWorkTime, formattedDateTime)
+ .eq(PerformanceShift::getUserId, userId));
+ // 濡傛灉涓嶅瓨鍦ㄦ坊鍔犳暟鎹�
+ if (!exists) {
+ list = saveMonth(performanceShiftAddDto.getEndWeek(), userId, list);
+ }
+ }
+ }
+ if (!list.isEmpty()) {
+ baseMapper.insertBatchSomeColumn(list);
+ list.clear();
+ }
+ // 鍐嶆鏇存柊
+ List<LocalDateTime> datesBetween = getLocalDateTimesBetween(performanceShiftAddDto.getStartWeek(), performanceShiftAddDto.getEndWeek());
+ for (LocalDateTime date : datesBetween) {
+ for (String s : splitUserId) {
+ PerformanceShift performanceShift = new PerformanceShift();
+ performanceShift.setShift(performanceShiftAddDto.getShift());
+ performanceShift.setUserId(Integer.valueOf(s));
+ performanceShift.setWorkTime(date);
+ String formatterDateTime = date.format(formatter);
+ baseMapper.update(new PerformanceShift(), Wrappers.<PerformanceShift>lambdaUpdate()
+ .set(PerformanceShift::getShift, performanceShiftAddDto.getShift())
+ .eq(PerformanceShift::getUserId, s)
+ .eq(PerformanceShift::getWorkTime, formatterDateTime));
+ }
+ }
+ }
+
+ private List<PerformanceShift> saveMonth (LocalDateTime week,String userId,List<PerformanceShift> list){
+ LocalDate firstDayOfMonth = week.toLocalDate().withDayOfMonth(1);
+ LocalDate lastDayOfMonth = week.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
+ List<LocalDateTime> localDateTimesBetween = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay());
+ localDateTimesBetween.forEach(i -> {
+ PerformanceShift performanceShift = new PerformanceShift();
+ performanceShift.setUserId(Integer.valueOf(userId));
+ performanceShift.setWorkTime(i);
+ performanceShift.setShift("");
+ list.add(performanceShift);
+ if (list.size() >= 1000) {
+ baseMapper.insertBatchSomeColumn(list);
+ list.clear();
+ }
+ });
+ return list;
+ }
+
+ @Override
+ public Map<String, Object> performanceShiftPage(Page<Object> page, String time, String userName, String laboratory) {
+ //鏌ヨ褰撳墠鐧诲綍浜哄憳鐨勬灦鏋�
+ Integer userId = SecurityUtils.getUserId().intValue();
+ //鍒ゆ柇鍏ㄩ儴,涓汉,缁勭粐鐨勬潈闄�
+ User user = userMapper.selectById(userId);//褰撳墠鐧诲綍鐨勪汉
+ //鑾峰彇褰撳墠浜烘墍灞炲疄楠屽id
+ String departLimsId = user.getDepartLimsId();
+ if (com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotEmpty(departLimsId) && !departLimsId.equals("")) {
+ String[] split = departLimsId.split(",");
+ //鏌ヨ瀵瑰簲鏋舵瀯鍚嶇О(閫氫俊瀹為獙瀹�,鐢靛姏瀹為獙瀹�,妫�娴嬪姙)
+ String departLims = baseMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
+ if (departLims.contains("瀹為獙瀹�")) {
+ laboratory = departLims;
+ }
+ }
+ IPage<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftPage(page, time, userName, laboratory);
+
+ List<SysDictData> shiftType = dictTypeService.selectDictDataByName("鐝绫诲瀷");
+ List<Map<String, Object>> mapYearIPage = baseMapper.performanceShiftYearPage(time, userName, laboratory);
+ mapIPage.getRecords().forEach(i -> {
+ String[] shiftTimes = i.getShiftTime().split(";");
+ double totalAttendance = 0;
+ List<Map<String, Object>> map = new ArrayList<>();
+ // 鍒嗗壊鏃ユ湡
+ for (String shiftTime : shiftTimes) {
+ Map<String, Object> hashMap = new HashMap<>();
+ String[] shiftTimeAndShift = shiftTime.split("锛�");
+ for (SysDictData enums : shiftType) {
+ if (!i.getMonthlyAttendance().containsKey(enums.getDictLabel())) {
+ i.getMonthlyAttendance().put(enums.getDictLabel(), 0);
+ }
+ if (enums.getDictValue().equals(shiftTimeAndShift[1])) {
+ BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(enums.getDictLabel()).toString());
+ i.getMonthlyAttendance().put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("1")));
+ }
+ // 鍗婏紝鍙﹀鍗婂ぉ绠楃粰鏃�
+ if (shiftTimeAndShift[1].equals("5") && enums.getDictValue().equals("0")) {
+ BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(enums.getDictLabel()).toString());
+ i.getMonthlyAttendance().put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("0.5")));
+ }
+ }
+ // 鏃╋紝涓紝澶滐紝宸�
+ if (shiftTimeAndShift[1].equals("1") || shiftTimeAndShift[1].equals("2") || shiftTimeAndShift[1].equals("0") || shiftTimeAndShift[1].equals("6")) {
+ i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 1);
+ }
+ // 鍗�
+ if (shiftTimeAndShift[1].equals("5")) {
+ i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 0.5);
+ }
+ hashMap.put("id", shiftTimeAndShift[2]);
+ hashMap.put("shift", shiftTimeAndShift[1]);
+ hashMap.put("time", shiftTimeAndShift[0]);
+ map.add(hashMap);
+ }
+ double totalYearAttendance = 0;
+ Map<String, Object> hashMap = new HashMap<>();
+ for (Map<String, Object> record : mapYearIPage) {
+ if (record.get("user_id").toString().equals(i.getUserId())) {
+ for (SysDictData enums : shiftType) {
+ if (!hashMap.containsKey(enums.getDictLabel())) {
+ hashMap.put(enums.getDictLabel(), 0);
+ }
+ if (enums.getDictValue().equals(record.get("shift"))) {
+ BigDecimal num = new BigDecimal(hashMap.get(enums.getDictLabel()).toString());
+ hashMap.put(enums.getDictLabel(), num.add(new BigDecimal("1")));
+ }
+ // 鍗婏紝鍙﹀鍗婂ぉ绠楃粰鏃�
+ if (record.get("shift").equals("5") && enums.getDictValue().equals("0")) {
+ BigDecimal bigDecimal = new BigDecimal(hashMap.get(enums.getDictLabel()).toString());
+ hashMap.put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("0.5")));
+ }
+ }
+ if (record.get("shift").equals("1") || record.get("shift").equals("2") || record.get("shift").equals("0") || record.get("shift").equals("6")) {
+ hashMap.put("totalAttendance", totalYearAttendance += 1);
+ }
+ // 鍗�
+ if (record.get("shift").equals("5")) {
+ hashMap.put("totalAttendance", totalYearAttendance += 0.5);
+ }
+ }
+ }
+ i.setSidebarAnnualAttendance(hashMap);
+ i.setList(map);
+ i.setShiftTime(null);
+ });
+ // 鑾峰彇header鏃堕棿
+ DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+ DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ // 灏嗗瓧绗︿覆鏃堕棿杞崲涓� LocalDateTime 绫诲瀷鏃堕棿
+ LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
+ LocalDate firstDayOfMonth = localDateTime.toLocalDate().withDayOfMonth(1);
+ LocalDate lastDayOfMonth = localDateTime.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
+ List<LocalDateTime> localDateTimesBetween = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay());
+ List<Object> list1 = new ArrayList<>();
+ for (LocalDateTime dateTime : localDateTimesBetween) {
+ Map<Object, Object> hashMap = new HashMap<>();
+ DateTime parse = DateUtil.parse(dateTime.format(formatter));
+ hashMap.put("weekly", DateUtil.weekOfYear(DateUtil.offsetDay(parse, 1)));
+ hashMap.put("headerTime", getWeek(dateTime.format(formatters)));
+ list1.add(hashMap);
+ }
+ Map<String, Object> resultMap = new HashMap<>();
+ resultMap.put("page", mapIPage);
+ resultMap.put("headerList", list1);
+ return resultMap;
+ }
+
+ @Override
+ public void performanceShiftUpdate(PerformanceShift performanceShift) {
+ baseMapper.update(new PerformanceShift(), Wrappers.<PerformanceShift>lambdaUpdate()
+ .eq(PerformanceShift::getId, performanceShift.getId())
+ .set(PerformanceShift::getShift, performanceShift.getShift()));
+ }
+
+ @Override
+ public IPage<Map<String, Object>> performanceShiftPageYear(Page<Object> page, String time, String userName, String laboratory) {
+ //鏌ヨ褰撳墠鐧诲綍浜哄憳鐨勬灦鏋�
+ Integer userId = SecurityUtils.getUserId().intValue();
+ //鍒ゆ柇鍏ㄩ儴,涓汉,缁勭粐鐨勬潈闄�
+ User user = userMapper.selectById(userId);//褰撳墠鐧诲綍鐨勪汉
+ //鑾峰彇褰撳墠浜烘墍灞炲疄楠屽id
+ String departLimsId = user.getDepartLimsId();
+ if (com.baomidou.mybatisplus.core.toolkit.ObjectUtils.isNotEmpty(departLimsId) && !departLimsId.equals("")) {
+ String[] split = departLimsId.split(",");
+ //鏌ヨ瀵瑰簲鏋舵瀯鍚嶇О(閫氫俊瀹為獙瀹�,鐢靛姏瀹為獙瀹�,妫�娴嬪姙)
+ String departLims = baseMapper.seldepLimsId(Integer.parseInt(split[split.length - 1]));
+ if (departLims.contains("瀹為獙瀹�")) {
+ laboratory = departLims;
+ }
+ }
+ IPage<Map<String, Object>> mapYearIPage = baseMapper.performanceShiftYear(page, time, userName, laboratory);
+ List<SysDictData> shiftType = dictTypeService.selectDictDataByName("鐝绫诲瀷");
+ mapYearIPage.setRecords(annualAttendanceProcessing(mapYearIPage.getRecords(), shiftType));
+ return mapYearIPage;
+ }
+
+ // 骞村垎椤典笌瀵煎嚭鍏卞悓浣跨敤
+ public List<Map<String, Object>> annualAttendanceProcessing(List<Map<String, Object>> mapYearList, List<SysDictData> shiftType) {
+ for (Map<String, Object> map : mapYearList) {
+ Map<String, Object> resultMap = new LinkedHashMap<>();
+ Map<String, Object> hashMapYear = new LinkedHashMap<>();
+ double totalYearAttendance = 0;
+ // 涓�骞�12涓湀
+ for (int i = 1; i < 13; i++) {
+ Map<String, Object> hashMapMonth = new LinkedHashMap<>();
+ double totalMonthAttendance = 0;
+ for (SysDictData shift : shiftType) {
+ // 鍒濆鍖栬祴鍊�
+ if (!hashMapYear.containsKey(shift.getDictLabel())) {
+ hashMapYear.put(shift.getDictLabel(), 0);
+ }
+ // 鏈�
+ if (!ObjectUtils.isEmpty(map.get("month_str"))) {
+ String charArray = map.get("month_str").toString();
+ int count = countOccurrences(charArray, i + "锛�" + shift.getDictValue());
+ hashMapMonth.put(shift.getDictLabel(), count);
+ hashMapYear.put(shift.getDictLabel(), new BigDecimal(hashMapYear.get(shift.getDictLabel()).toString()).add(new BigDecimal(count)));
+ // 鏃╋紝涓紝澶滐紝宸�
+ if (shift.getDictValue().equals("0") || shift.getDictValue().equals("1") || shift.getDictValue().equals("2") || shift.getDictValue().equals("6")) {
+ totalMonthAttendance += count;
+ totalYearAttendance += count;
+ }
+// 鍗婏紝鍙﹀鍗婂ぉ绠楃粰鏃�
+ if (shift.getDictValue().equals("5")) {
+ BigDecimal multiply = new BigDecimal("0.5").multiply(new BigDecimal(count)).setScale(1, BigDecimal.ROUND_CEILING);
+ hashMapMonth.put(shiftType.get(0).getDictLabel(), new BigDecimal(hashMapMonth.get(shiftType.get(0).getDictLabel()).toString()).add(multiply));
+ hashMapYear.put(shiftType.get(0).getDictLabel(), new BigDecimal(hashMapYear.get(shiftType.get(0).getDictLabel()).toString()).add(multiply));
+ totalMonthAttendance += multiply.doubleValue();
+ totalYearAttendance += multiply.doubleValue();
+ }
+ }
+ // 绌烘暟鎹�
+ else {
+ map.put("work_time", i);
+ hashMapMonth.put(shift.getDictLabel(), 0);
+ }
+ }
+ hashMapMonth.put("totalMonthAttendance", totalMonthAttendance);
+ hashMapYear.put("totalYearAttendance", totalYearAttendance);
+ resultMap.put(i + "", hashMapMonth);
+ }
+ map.remove("month_str");
+ map.remove("year_str");
+ map.put("year", hashMapYear);
+ map.put("month", resultMap);
+ }
+ return mapYearList;
+ }
+
+ public static int countOccurrences(String str, String target) {
+ int count = 0;
+ int index = 0;
+ while ((index = str.indexOf(target, index)) != -1) {
+ count++;
+ index += target.length();
+ }
+ return count;
+ }
+
+ public List<List<Object>> dataRequiredForProcessingIntoExcel(List<Map<String, Object>> list, List<SysDictData> enums) throws Exception {
+ List<List<Object>> data = new ArrayList<>();
+ for (int i = 0; i < list.size(); i++) {
+ List<Object> excelRowList = new ArrayList<>();
+ excelRowList.add(i + 1);
+ excelRowList.add(list.get(i).get("account"));
+ excelRowList.add(list.get(i).get("name"));
+ Map<String, Object> year = JackSonUtil.unmarshal(JackSonUtil.marshal(list.get(i).get("year")), Map.class);
+ excelRowList.add(year.get("totalYearAttendance"));
+ enums.forEach(j -> {
+ if (!j.getDictValue().equals("5")) {
+ excelRowList.add(year.get(j.getDictLabel()));
+ }
+ });
+ Map<String, Map<String, Object>> month = JackSonUtil.unmarshal(JackSonUtil.marshal(list.get(i).get("month")), Map.class);
+ for (int j = 1; j < 13; j++) {
+ Object totalMonthAttendance = month.get(j + "").get("totalMonthAttendance");
+ excelRowList.add(totalMonthAttendance);
+ for (SysDictData anEnum : enums) {
+ if (!anEnum.getDictValue().equals("5")) {
+ excelRowList.add(month.get(j + "").get(anEnum.getDictLabel()));
+ }
+ }
+ }
+ data.add(excelRowList);
+ }
+ return data;
+ }
+
+ @Override
+ public Map<Object, Object> exportToYearExcel(String time, String userName, String laboratory) throws Exception {
+ Map<Object, Object> map = new HashMap<>();
+ List<SysDictData> shiftType = dictTypeService.selectDictDataByName("鐝绫诲瀷");
+ DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ // 灏嗗瓧绗︿覆鏃堕棿杞崲涓� LocalDateTime 绫诲瀷鏃堕棿
+ LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
+ map.put("header", getYearHeader(localDateTime.getYear() + " 骞�", shiftType));
+ List<Map<String, Object>> mapYearList = baseMapper.performanceShiftYearList(time, userName, laboratory);
+ annualAttendanceProcessing(mapYearList, shiftType);
+ List<List<Object>> lists = dataRequiredForProcessingIntoExcel(mapYearList, shiftType);
+ map.put("data", lists);
+ return map;
+ }
+
+ @Override
+ public Map<Object, Object> exportToMonthExcel(String time, String userName, String laboratory) {
+ List<SysDictData> shiftType = dictTypeService.selectDictDataByName("鐝绫诲瀷");
+ List<PerformanceShiftMapDto> mapIPage = baseMapper.performanceShiftList(time, userName, laboratory);
+ mapIPage.forEach(i -> {
+ String[] shiftTimes = i.getShiftTime().split(";");
+ double totalAttendance = 0;
+ List<Map<String, Object>> map = new ArrayList<>();
+ // 鍒嗗壊鏃ユ湡
+ for (String shiftTime : shiftTimes) {
+ Map<String, Object> hashMap = new HashMap<>();
+ String[] shiftTimeAndShift = shiftTime.split("锛�");
+ for (SysDictData enums : shiftType) {
+ if (!i.getMonthlyAttendance().containsKey(enums.getDictLabel())) {
+ i.getMonthlyAttendance().put(enums.getDictLabel(), 0);
+ }
+ if (enums.getDictValue().equals(shiftTimeAndShift[1])) {
+ BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(enums.getDictLabel()).toString());
+ i.getMonthlyAttendance().put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("1")));
+ }
+ // 鍗婏紝鍙﹀鍗婂ぉ绠楃粰鏃�
+ if (shiftTimeAndShift[1].equals("5") && enums.getDictValue().equals("0")) {
+ BigDecimal bigDecimal = new BigDecimal(i.getMonthlyAttendance().get(enums.getDictLabel()).toString());
+ i.getMonthlyAttendance().put(enums.getDictLabel(), bigDecimal.add(new BigDecimal("0.5")));
+ }
+ }
+ // 鏃╋紝涓紝澶滐紝宸�
+ if (shiftTimeAndShift[1].equals("1") || shiftTimeAndShift[1].equals("2") || shiftTimeAndShift[1].equals("0") || shiftTimeAndShift[1].equals("6")) {
+ i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 1);
+ }
+ // 鍗�
+ if (shiftTimeAndShift[1].equals("5")) {
+ i.getMonthlyAttendance().put("totalAttendance", totalAttendance += 0.5);
+ }
+ hashMap.put("id", shiftTimeAndShift[2]);
+ hashMap.put("shift", shiftTimeAndShift[1]);
+ hashMap.put("time", shiftTimeAndShift[0]);
+ map.add(hashMap);
+ }
+ i.setList(map);
+ i.setShiftTime(null);
+ });
+ Map<Object, Object> map = new HashMap<>();
+ DateTimeFormatter formatters = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+ // 灏嗗瓧绗︿覆鏃堕棿杞崲涓� LocalDateTime 绫诲瀷鏃堕棿
+ LocalDateTime localDateTime = LocalDateTime.parse(time, formatters);
+ map.put("header", getMonthHeader(localDateTime, shiftType));
+ List<List<Object>> lists = dataRequiredForProcessingIntoExcelMonth(mapIPage, shiftType);
+ map.put("data", lists);
+ return map;
+ }
+
+ // 鑾峰彇涓や釜localDateTime鐨勬瘡涓�澶�
+ public static List<LocalDateTime> getLocalDateTimesBetween(LocalDateTime start, LocalDateTime end) {
+ List<LocalDateTime> localDateTimes = new ArrayList<>();
+ LocalDate currentDate = start.toLocalDate();
+ LocalDateTime currentLocalDateTime = start;
+ while (!currentDate.isAfter(end.toLocalDate())) {
+ localDateTimes.add(currentLocalDateTime);
+ currentLocalDateTime = currentLocalDateTime.plusDays(1);
+ currentDate = currentDate.plusDays(1);
+ }
+ return localDateTimes;
+ }
+
+ public static String getWeek(String dayStr) {
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+ try {
+ Date date = sdf.parse(dayStr);
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTime(date);
+ int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
+ int day = calendar.get(Calendar.DAY_OF_MONTH);
+ return day + " " + getWeekDay(dayOfWeek);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ public static String getWeekDay(int dayOfWeek) {
+ switch (dayOfWeek) {
+ case Calendar.MONDAY:
+ return "鍛ㄤ竴";
+ case Calendar.TUESDAY:
+ return "鍛ㄤ簩";
+ case Calendar.WEDNESDAY:
+ return "鍛ㄤ笁";
+ case Calendar.THURSDAY:
+ return "鍛ㄥ洓";
+ case Calendar.FRIDAY:
+ return "鍛ㄤ簲";
+ case Calendar.SATURDAY:
+ return "鍛ㄥ叚";
+ case Calendar.SUNDAY:
+ return "鍛ㄦ棩";
+ default:
+ return "鏈煡";
+ }
+ }
+
+ /**
+ * 杩斿洖琛ㄥご
+ * <p>
+ * 澶栧眰List浠h〃琛屽唴灞� List浠h〃鍒� 鐩稿悓鐨勫垪鏁版嵁浼氳涓诲姩鍚堝苟
+ * 鏋勯�犲弻鍒楄〃澶�
+ *
+ * @return List<List < String>>
+ */
+ private static List<List<String>> getYearHeader(String year, List<SysDictData> enums) {
+ List<List<String>> line = new ArrayList<>();
+ line.add(Arrays.asList("鑰冨嫟姹囨��", "搴忓彿", "搴忓彿"));
+ line.add(Arrays.asList("鑰冨嫟姹囨��", "宸ュ彿", "宸ュ彿"));
+ line.add(Arrays.asList("鑰冨嫟姹囨��", "濮撳悕", "濮撳悕"));
+ line.add(Arrays.asList("鍑哄嫟璇︽儏", year, "鍑哄嫟"));
+ // 骞� header
+ for (SysDictData anEnum : enums) {
+ if (!anEnum.getDictValue().equals("5")) {
+ line.add(Arrays.asList("鑰冨嫟姹囨��", year, anEnum.getDictLabel()));
+ }
+ }
+ // 鏈坔eader
+ for (int i = 1; i < 13; i++) {
+ line.add(Arrays.asList("鍑哄嫟璇︽儏", i + " 鏈�", "鍑哄嫟"));
+ for (SysDictData anEnum : enums) {
+ if (!anEnum.getDictValue().equals("5")) {
+ line.add(Arrays.asList("鍑哄嫟璇︽儏", i + " 鏈�", anEnum.getDictLabel()));
+ }
+ }
+ }
+ return line;
+ }
+
+ private static List<List<String>> getMonthHeader(LocalDateTime localDateTimeYear, List<SysDictData> enums) {
+ String year = localDateTimeYear.getYear() + " 骞翠汉鍛樼彮娆�";
+ List<List<String>> line = new ArrayList<>();
+ line.add(Arrays.asList(year, "搴忓彿", "搴忓彿", "搴忓彿"));
+ line.add(Arrays.asList(year, "濮撳悕", "濮撳悕", "濮撳悕"));
+ line.add(Arrays.asList(year, "瀹為獙瀹�", "瀹為獙瀹�", "瀹為獙瀹�"));
+ line.add(Arrays.asList(year, localDateTimeYear.getYear() + "", localDateTimeYear.getYear() + "", "鍑哄嫟"));
+ line.add(Arrays.asList(year, localDateTimeYear.getYear() + "", localDateTimeYear.getYear() + "", enums.get(3).getDictLabel()));
+ line.add(Arrays.asList(year, "骞�", "骞�", enums.get(4).getDictLabel()));
+ line.add(Arrays.asList(year, localDateTimeYear.getMonthValue() + "", localDateTimeYear.getMonthValue() + "", enums.get(0).getDictLabel()));
+ line.add(Arrays.asList(year, "鏈�", "鏈�", enums.get(1).getDictLabel()));
+ line.add(Arrays.asList(year, "", "", enums.get(2).getDictLabel()));
+ line.add(Arrays.asList(year, "鍛ㄦ", "鏄熸湡", "鍑哄樊"));
+ LocalDate firstDayOfMonth = localDateTimeYear.toLocalDate().withDayOfMonth(1);
+ LocalDate lastDayOfMonth = localDateTimeYear.toLocalDate().with(TemporalAdjusters.lastDayOfMonth());
+ List<LocalDateTime> timeList = getLocalDateTimesBetween(firstDayOfMonth.atStartOfDay(), lastDayOfMonth.atStartOfDay());
+ timeList.forEach(i -> {
+ int dayOfYear = i.getDayOfMonth();
+ Date from = Date.from(i.atZone(ZoneId.systemDefault()).toInstant());
+ String weekDay = getWeekDay(i.getDayOfWeek().getValue());
+ line.add(Arrays.asList(year, DateUtil.weekOfYear(DateUtil.offsetDay(from, 1)) + "", weekDay, dayOfYear + ""));
+ });
+ return line;
+ }
+
+ public List<List<Object>> dataRequiredForProcessingIntoExcelMonth(List<PerformanceShiftMapDto> list, List<SysDictData> enums) {
+ List<List<Object>> data = new ArrayList<>();
+ for (int i = 0; i < list.size(); i++) {
+ List<Object> excelRowList = new ArrayList<>();
+ excelRowList.add(i + 1);
+ excelRowList.add(list.get(i).getName());
+ excelRowList.add(list.get(i).getDepartment());
+ excelRowList.add(list.get(i).getMonthlyAttendance().get("totalAttendance"));
+ excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(3).getDictLabel())); // 浼�
+ excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(4).getDictLabel())); // 鍋�
+ excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(0).getDictLabel())); // 鏃�
+ excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(1).getDictLabel())); // 涓�
+ excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(2).getDictLabel())); // 澶�
+ excelRowList.add(list.get(i).getMonthlyAttendance().get(enums.get(6).getDictLabel())); // 宸�
+ for (Map<String, Object> o : list.get(i).getList()) {
+ String enumLabel = "";
+ for (SysDictData anEnum : enums) {
+ if (anEnum.getDictValue().equals(o.get("shift"))) {
+ enumLabel = anEnum.getDictLabel();
+ }
+ }
+ excelRowList.add(ObjectUtils.isEmpty(enumLabel) ? "-" : enumLabel);
+ }
+ data.add(excelRowList);
+ }
+ return data;
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/service/impl/ShiftTimeServiceImpl.java b/performance-server/src/main/java/com/ruoyi/performance/service/impl/ShiftTimeServiceImpl.java
new file mode 100644
index 0000000..cff7cbc
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/service/impl/ShiftTimeServiceImpl.java
@@ -0,0 +1,41 @@
+package com.ruoyi.performance.service.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.base.BaseException;
+import com.ruoyi.performance.mapper.ShiftTimeMapper;
+import com.ruoyi.performance.pojo.ShiftTime;
+import com.ruoyi.performance.service.ShiftTimeService;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * <p>
+ * 鐝瀵瑰簲鐨勬椂闂� 鏈嶅姟瀹炵幇绫�
+ * </p>
+ *
+ * @author 姹熻嫃榈烽洀缃戠粶绉戞妧鏈夐檺鍏徃
+ * @since 2024-07-24 11:22:17
+ */
+@Service
+public class ShiftTimeServiceImpl extends ServiceImpl<ShiftTimeMapper, ShiftTime> implements ShiftTimeService {
+
+ @Resource
+ ShiftTimeMapper shiftTimeMapper;
+
+ @Override
+ public void shiftTimeAdd(ShiftTime shiftTime) {
+ List<ShiftTime> shiftTimes = shiftTimeMapper.selectList(Wrappers.<ShiftTime>lambdaQuery().eq(ShiftTime::getShift, shiftTime.getShift()));
+ if (shiftTimes.size() > 0) {
+ throw new BaseException("宸插瓨鍦ㄨ鐝鐨勬椂闂撮厤缃�,璇峰垹鎺夊悗鍐嶆柊澧�!");
+ }
+ shiftTimeMapper.insert(shiftTime);
+ }
+
+ @Override
+ public List<ShiftTime> shiftTimeList() {
+ return shiftTimeMapper.selectList(null);
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/utils/CustomerDoubleSerialize.java b/performance-server/src/main/java/com/ruoyi/performance/utils/CustomerDoubleSerialize.java
new file mode 100644
index 0000000..576ae14
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/utils/CustomerDoubleSerialize.java
@@ -0,0 +1,26 @@
+package com.ruoyi.performance.utils;
+
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+
+import java.io.IOException;
+import java.text.DecimalFormat;
+
+public class CustomerDoubleSerialize extends JsonSerializer {
+ private DecimalFormat df = new DecimalFormat("0.0000");
+
+ @Override
+ public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
+ if(o.toString() != null && !o.toString().equals("0.0")) {
+ Double dd=Double.parseDouble(o.toString());
+ jsonGenerator.writeString(df.format(dd));
+ } else{
+ if(o.toString().equals("0.0")) {
+ jsonGenerator.writeString("0");
+ } else {
+ jsonGenerator.writeString(o.toString());
+ }
+ }
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/utils/StyleMonthUtils.java b/performance-server/src/main/java/com/ruoyi/performance/utils/StyleMonthUtils.java
new file mode 100644
index 0000000..3edee60
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/utils/StyleMonthUtils.java
@@ -0,0 +1,86 @@
+package com.ruoyi.performance.utils;
+
+import com.alibaba.excel.write.metadata.style.WriteCellStyle;
+import com.alibaba.excel.write.metadata.style.WriteFont;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+
+public class StyleMonthUtils {
+ /**
+ * 鏍囬鏍峰紡
+ * @return
+ */
+ public static WriteCellStyle getHeadStyle(){
+ // 澶寸殑绛栫暐
+ WriteCellStyle headWriteCellStyle = new WriteCellStyle();
+ // 鑳屾櫙棰滆壊
+// headWriteCellStyle.setFillForegroundColor(IndexedColors.WHITE.getIndex());
+// headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
+
+ // 瀛椾綋
+ WriteFont headWriteFont = new WriteFont();
+ headWriteFont.setFontName("绛夌嚎");//璁剧疆瀛椾綋鍚嶅瓧
+ headWriteFont.setFontHeightInPoints((short)9);//璁剧疆瀛椾綋澶у皬
+ headWriteFont.setBold(true);//瀛椾綋鍔犵矖
+ headWriteFont.setColor((short) 0);
+ headWriteCellStyle.setWriteFont(headWriteFont); //鍦ㄦ牱寮忕敤搴旂敤璁剧疆鐨勫瓧浣�;
+
+ // 鏍峰紡
+ headWriteCellStyle.setBorderBottom(BorderStyle.THIN);//璁剧疆搴曡竟妗�;
+ headWriteCellStyle.setBottomBorderColor((short) 0);//璁剧疆搴曡竟妗嗛鑹�;
+ headWriteCellStyle.setBorderLeft(BorderStyle.THIN); //璁剧疆宸﹁竟妗�;
+ headWriteCellStyle.setLeftBorderColor((short) 0);//璁剧疆宸﹁竟妗嗛鑹�;
+ headWriteCellStyle.setBorderRight(BorderStyle.THIN);//璁剧疆鍙宠竟妗�;
+ headWriteCellStyle.setRightBorderColor((short) 0);//璁剧疆鍙宠竟妗嗛鑹�;
+ headWriteCellStyle.setBorderTop(BorderStyle.THIN);//璁剧疆椤惰竟妗�;
+ headWriteCellStyle.setTopBorderColor((short) 0); //璁剧疆椤惰竟妗嗛鑹�;
+
+ headWriteCellStyle.setWrapped(false); //璁剧疆鑷姩鎹㈣;
+
+ headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//璁剧疆姘村钩瀵归綈鐨勬牱寮忎负灞呬腑瀵归綈;
+ headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //璁剧疆鍨傜洿瀵归綈鐨勬牱寮忎负灞呬腑瀵归綈;
+ headWriteCellStyle.setShrinkToFit(true);//璁剧疆鏂囨湰鏀剁缉鑷冲悎閫�
+
+ return headWriteCellStyle;
+ }
+
+
+ /**
+ * 鍐呭鏍峰紡
+ * @return
+ */
+ public static WriteCellStyle getContentStyle(){
+ // 鍐呭鐨勭瓥鐣�
+ WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
+
+ // 杩欓噷闇�瑕佹寚瀹� FillPatternType 涓篎illPatternType.SOLID_FOREGROUND 涓嶇劧鏃犳硶鏄剧ず鑳屾櫙棰滆壊.澶撮粯璁や簡 FillPatternType鎵�浠ュ彲浠ヤ笉鎸囧畾
+// contentWriteCellStyle.setFillForegroundColor(IndexedColors.LIGHT_GREEN.getIndex());
+ contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
+
+ // 璁剧疆瀛椾綋
+ WriteFont contentWriteFont = new WriteFont();
+ contentWriteFont.setFontHeightInPoints((short) 10);//璁剧疆瀛椾綋澶у皬
+ contentWriteFont.setFontName("绛夌嚎"); //璁剧疆瀛椾綋鍚嶅瓧
+ contentWriteCellStyle.setWriteFont(contentWriteFont);//鍦ㄦ牱寮忕敤搴旂敤璁剧疆鐨勫瓧浣�;
+
+ //璁剧疆鏍峰紡;
+ contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);//璁剧疆搴曡竟妗�;
+ contentWriteCellStyle.setBottomBorderColor((short) 0);//璁剧疆搴曡竟妗嗛鑹�;
+ contentWriteCellStyle.setBorderLeft(BorderStyle.THIN); //璁剧疆宸﹁竟妗�;
+ contentWriteCellStyle.setLeftBorderColor((short) 0);//璁剧疆宸﹁竟妗嗛鑹�;
+ contentWriteCellStyle.setBorderRight(BorderStyle.THIN);//璁剧疆鍙宠竟妗�;
+ contentWriteCellStyle.setRightBorderColor((short) 0);//璁剧疆鍙宠竟妗嗛鑹�;
+ contentWriteCellStyle.setBorderTop(BorderStyle.THIN);//璁剧疆椤惰竟妗�;
+ contentWriteCellStyle.setTopBorderColor((short) 0); ///璁剧疆椤惰竟妗嗛鑹�;
+
+ contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 姘村钩灞呬腑
+ contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 鍨傜洿灞呬腑
+ contentWriteCellStyle.setWrapped(false); //璁剧疆鑷姩鎹㈣;
+
+// contentWriteCellStyle.setShrinkToFit(true);//璁剧疆鏂囨湰鏀剁缉鑷冲悎閫�
+
+ return contentWriteCellStyle;
+ }
+}
diff --git a/performance-server/src/main/java/com/ruoyi/performance/utils/StyleYearUtils.java b/performance-server/src/main/java/com/ruoyi/performance/utils/StyleYearUtils.java
new file mode 100644
index 0000000..0076249
--- /dev/null
+++ b/performance-server/src/main/java/com/ruoyi/performance/utils/StyleYearUtils.java
@@ -0,0 +1,89 @@
+package com.ruoyi.performance.utils;
+
+import com.alibaba.excel.write.metadata.style.WriteCellStyle;
+import com.alibaba.excel.write.metadata.style.WriteFont;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+
+public class StyleYearUtils {
+ /**
+ * 鏍囬鏍峰紡
+ *
+ * @return
+ */
+ public static WriteCellStyle getHeadStyle() {
+ // 澶寸殑绛栫暐
+ WriteCellStyle headWriteCellStyle = new WriteCellStyle();
+ // 鑳屾櫙棰滆壊
+// headWriteCellStyle.setFillForegroundColor(IndexedColors.GREEN.getIndex());
+ headWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
+
+ // 瀛椾綋
+ WriteFont headWriteFont = new WriteFont();
+ headWriteFont.setFontName("浠垮畫");//璁剧疆瀛椾綋鍚嶅瓧
+ headWriteFont.setFontHeightInPoints((short) 9);//璁剧疆瀛椾綋澶у皬
+ headWriteFont.setBold(true);//瀛椾綋鍔犵矖
+ headWriteFont.setColor((short) 1);
+ headWriteCellStyle.setWriteFont(headWriteFont); //鍦ㄦ牱寮忕敤搴旂敤璁剧疆鐨勫瓧浣�;
+
+ // 鏍峰紡
+ headWriteCellStyle.setBorderBottom(BorderStyle.THIN);//璁剧疆搴曡竟妗�;
+ headWriteCellStyle.setBottomBorderColor((short) 1);//璁剧疆搴曡竟妗嗛鑹�;
+ headWriteCellStyle.setBorderLeft(BorderStyle.THIN); //璁剧疆宸﹁竟妗�;
+ headWriteCellStyle.setLeftBorderColor((short) 1);//璁剧疆宸﹁竟妗嗛鑹�;
+ headWriteCellStyle.setBorderRight(BorderStyle.THIN);//璁剧疆鍙宠竟妗�;
+ headWriteCellStyle.setRightBorderColor((short) 1);//璁剧疆鍙宠竟妗嗛鑹�;
+ headWriteCellStyle.setBorderTop(BorderStyle.THIN);//璁剧疆椤惰竟妗�;
+ headWriteCellStyle.setTopBorderColor((short) 1); //璁剧疆椤惰竟妗嗛鑹�;
+
+ headWriteCellStyle.setWrapped(false); //璁剧疆鑷姩鎹㈣;
+
+ headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);//璁剧疆姘村钩瀵归綈鐨勬牱寮忎负灞呬腑瀵归綈;
+ headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER); //璁剧疆鍨傜洿瀵归綈鐨勬牱寮忎负灞呬腑瀵归綈;
+ headWriteCellStyle.setShrinkToFit(true);//璁剧疆鏂囨湰鏀剁缉鑷冲悎閫�
+
+ return headWriteCellStyle;
+ }
+
+
+ /**
+ * 鍐呭鏍峰紡
+ *
+ * @return
+ */
+ public static WriteCellStyle getContentStyle() {
+ // 鍐呭鐨勭瓥鐣�
+ WriteCellStyle contentWriteCellStyle = new WriteCellStyle();
+
+ // 杩欓噷闇�瑕佹寚瀹� FillPatternType 涓篎illPatternType.SOLID_FOREGROUND 涓嶇劧鏃犳硶鏄剧ず鑳屾櫙棰滆壊.澶撮粯璁や簡 FillPatternType鎵�浠ュ彲浠ヤ笉鎸囧畾
+// contentWriteCellStyle.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.getIndex());
+ contentWriteCellStyle.setFillPatternType(FillPatternType.SOLID_FOREGROUND);
+
+ // 璁剧疆瀛椾綋
+ WriteFont contentWriteFont = new WriteFont();
+ contentWriteFont.setFontHeightInPoints((short) 9);//璁剧疆瀛椾綋澶у皬
+ contentWriteFont.setFontName("浠垮畫"); //璁剧疆瀛椾綋鍚嶅瓧
+ contentWriteCellStyle.setWriteFont(contentWriteFont);//鍦ㄦ牱寮忕敤搴旂敤璁剧疆鐨勫瓧浣�;
+
+ //璁剧疆鏍峰紡;
+ contentWriteCellStyle.setBorderBottom(BorderStyle.THIN);//璁剧疆搴曡竟妗�;
+ contentWriteCellStyle.setBottomBorderColor((short) 0);//璁剧疆搴曡竟妗嗛鑹�;
+ contentWriteCellStyle.setBorderLeft(BorderStyle.THIN); //璁剧疆宸﹁竟妗�;
+ contentWriteCellStyle.setLeftBorderColor((short) 0);//璁剧疆宸﹁竟妗嗛鑹�;
+ contentWriteCellStyle.setBorderRight(BorderStyle.THIN);//璁剧疆鍙宠竟妗�;
+ contentWriteCellStyle.setRightBorderColor((short) 0);//璁剧疆鍙宠竟妗嗛鑹�;
+ contentWriteCellStyle.setBorderTop(BorderStyle.THIN);//璁剧疆椤惰竟妗�;
+ contentWriteCellStyle.setTopBorderColor((short) 0); ///璁剧疆椤惰竟妗嗛鑹�;
+
+ contentWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);// 姘村钩灞呬腑
+ contentWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);// 鍨傜洿灞呬腑
+ contentWriteCellStyle.setWrapped(false); //璁剧疆鑷姩鎹㈣;
+
+// contentWriteCellStyle.setShrinkToFit(true);//璁剧疆鏂囨湰鏀剁缉鑷冲悎閫�
+
+ return contentWriteCellStyle;
+ }
+
+}
diff --git a/performance-server/src/main/resources/mapper/AuxiliaryCorrectionHoursMapper.xml b/performance-server/src/main/resources/mapper/AuxiliaryCorrectionHoursMapper.xml
new file mode 100644
index 0000000..ec609d0
--- /dev/null
+++ b/performance-server/src/main/resources/mapper/AuxiliaryCorrectionHoursMapper.xml
@@ -0,0 +1,75 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.performance.mapper.AuxiliaryCorrectionHoursMapper">
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.performance.pojo.AuxiliaryCorrectionHours">
+ <id column="id" property="id"/>
+ <result column="name_user" property="nameUser"/>
+ <result column="type" property="type"/>
+ <result column="one_hours" property="oneHours"/>
+ <result column="two_hours" property="twoHours"/>
+ <result column="three_hours" property="threeHours"/>
+ <result column="four_hours" property="fourHours"/>
+ <result column="five_hours" property="fiveHours"/>
+ <result column="six_hours" property="sixHours"/>
+ <result column="seven_hours" property="sevenHours"/>
+ <result column="eight_hours" property="eightHours"/>
+ <result column="nine_hours" property="nineHours"/>
+ <result column="ten_hours" property="tenHours"/>
+ <result column="eleven_hours" property="elevenHours"/>
+ <result column="twelve_hours" property="twelveHours"/>
+ <result column="thirteen_hours" property="thirteenHours"/>
+ <result column="fourteen_hours" property="fourteenHours"/>
+ <result column="fifteen_hours" property="fifteenHours"/>
+ <result column="sixteen_hours" property="sixteenHours"/>
+ <result column="seventeen_hours" property="seventeenHours"/>
+ <result column="eighteen_hours" property="eighteenHours"/>
+ <result column="nineteen_hours" property="nineteenHours"/>
+ <result column="twenty_hours" property="twentyHours"/>
+ <result column="twenty_one_hours" property="twentyOneHours"/>
+ <result column="twenty_two_hours" property="twentyTwoHours"/>
+ <result column="twenty_three_hours" property="twentyThreeHours"/>
+ <result column="twenty_four_hours" property="twentyFourHours"/>
+ <result column="twenty_five_hours" property="twentyFiveHours"/>
+ <result column="twenty_six_hours" property="twentySixHours"/>
+ <result column="twenty_seven_hours" property="twentySevenHours"/>
+ <result column="twenty_eight_hours" property="twentyEightHours"/>
+ <result column="twenty_nine_hours" property="twentyNineHours"/>
+ <result column="thirty_hours" property="thirtyHours"/>
+ <result column="thirty_one_hours" property="thirtyOneHours"/>
+ <result column="month" property="month"/>
+ <result column="create_time" property="createTime"/>
+ <result column="update_time" property="updateTime"/>
+ <result column="create_user" property="createUser"/>
+ <result column="update_user" property="updateUser"/>
+ </resultMap>
+ <select id="selectAuxiliaryCorrectionHours" resultType="com.ruoyi.performance.dto.AuxiliaryCorrectionHoursDto">
+ select A.*
+ from (
+ select ach.*,
+ name,
+ sum(one_hours+two_hours+ three_hours+ four_hours+ five_hours+ six_hours+ seven_hours+ eight_hours+ nine_hours+
+ ten_hours+ eleven_hours+ twelve_hours+thirteen_hours+ fourteen_hours+ fifteen_hours+ sixteen_hours+
+ seventeen_hours+ eighteen_hours+ nineteen_hours+ twenty_hours+ twenty_one_hours+ twenty_two_hours+
+ twenty_three_hours+ twenty_four_hours+ twenty_five_hours+ twenty_six_hours+ twenty_seven_hours+
+ twenty_eight_hours+ twenty_nine_hours+ thirty_hours+ thirty_one_hours) as total
+ FROM auxiliary_correction_hours ach
+ left join user on user.id=ach.name_user
+ WHERE 1=1
+ <if test="ids !=null and ids != ''">
+ and name_user in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ ) A
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="selDepartLimsByName" resultType="java.lang.Integer">
+ select id
+ from department_lims
+ where name LIKE CONCAT('%', #{departLims}, '%');
+ </select>
+</mapper>
diff --git a/performance-server/src/main/resources/mapper/AuxiliaryOriginalHoursMapper.xml b/performance-server/src/main/resources/mapper/AuxiliaryOriginalHoursMapper.xml
new file mode 100644
index 0000000..71e2892
--- /dev/null
+++ b/performance-server/src/main/resources/mapper/AuxiliaryOriginalHoursMapper.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.performance.mapper.AuxiliaryOriginalHoursMapper">
+ <select id="totalHours" resultType="java.util.Map">
+ select E.name, E.month, E.total manHours
+ from (select C.name, C.month, C.manHours + D.manHours as total
+ from (select A.name,
+ A.month,
+ FORMAT(SUM(manHour), 4) as manHours
+ from (
+ select user.name,
+ case
+ when reviewer_nonproductive_time is null then nonproductive_time
+ else reviewer_nonproductive_time end as manHour,
+ date_time as month
+ from auxiliary_working_hours_day awhd
+ left join user on user.id = awhd.name_user
+ left join department_lims dl on depart_lims_id = dl.id
+ where date_time LIKE CONCAT('%', #{month}, '%')
+ and awhd.state='宸叉壒鍑�'
+ <!--and name_user in(#{ids})-->
+ <if test="ids !=null and ids != ''">
+ and name_user in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ order by month
+ ) A
+ group by A.name, A.month) C
+ INNER JOIN
+ (select B.name,
+ B.month,
+ B.manHours
+ from (
+ select user.name,
+ date_time as month,
+ FORMAT(SUM(output_work_time), 4) as manHours
+ from auxiliary_output_working_hours aowh
+ left join user on user.id = aowh.`check`
+ left join department_lims dl on depart_lims_id = dl.id
+ where date_time LIKE CONCAT('%', #{month}, '%')
+ <!--and `check` in(#{ids})-->
+ <if test="ids !=null and ids != ''">
+ and `check` in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ group by user.name, month
+ order by user.name, month
+ ) B
+ group by B.name, B.month) D
+ on C.month = D.month
+ where C.name = D.name
+ ) E
+ group by E.name, E.month
+ </select>
+</mapper>
diff --git a/performance-server/src/main/resources/mapper/AuxiliaryOutputWorkingHoursMapper.xml b/performance-server/src/main/resources/mapper/AuxiliaryOutputWorkingHoursMapper.xml
new file mode 100644
index 0000000..9229c98
--- /dev/null
+++ b/performance-server/src/main/resources/mapper/AuxiliaryOutputWorkingHoursMapper.xml
@@ -0,0 +1,186 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.performance.mapper.AuxiliaryOutputWorkingHoursMapper">
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours">
+ <id column="id" property="id"/>
+ <result column="inspection_item" property="inspectionItem"/>
+ <result column="inspection_item_subclass" property="inspectionItemSubclass"/>
+ <result column="sample" property="sample"/>
+ <result column="overtime_order_no" property="overtimeOrderNo"/>
+ <result column="overtime_work_time" property="overtimeWorkTime"/>
+ <result column="overtime_amount" property="overtimeAmount"/>
+ <result column="order_no" property="orderNo"/>
+ <result column="work_time" property="workTime"/>
+ <result column="amount" property="amount"/>
+ <result column="output_work_time" property="outputWorkTime"/>
+ <result column="date_time" property="dateTime"/>
+ <result column="week" property="week"/>
+ <result column="week_day" property="weekDay"/>
+ <result column="check" property="check"/>
+ <result column="create_time" property="createTime"/>
+ <result column="update_time" property="updateTime"/>
+ <result column="create_user" property="createUser"/>
+ <result column="update_user" property="updateUser"/>
+ </resultMap>
+
+ <sql id="selectAuxiliaryOutputWorking">
+ select *
+ from (
+ select aowh.id,
+ aowh.inspection_item_class,
+ aowh.inspection_item,
+ aowh.inspection_item_subclass,
+ aowh.overtime_order_no,
+ aowh.overtime_work_time,
+ aowh.overtime_amount,
+ aowh.order_no,
+ aowh.work_time,
+ aowh.amount,
+ aowh.output_work_time,
+ aowh.date_time,
+ aowh.week,
+ aowh.week_day,
+ user.name,
+ aowh.sample,
+ aowh.price,
+ aowh.man_hour_group,
+ ip.cable_tag
+ FROM auxiliary_output_working_hours aowh
+ left join ins_product ip on ip.id = aowh.ins_product_id
+ left join user on user.id=aowh.`check`
+ WHERE 1=1
+ <if test="ids !=null and ids.size() > 0">
+ and `check` in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ ) A
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </sql>
+ <select id="selectAuxiliaryOutputWorkingHours" resultType="com.ruoyi.performance.dto.AuxiliaryOutputWorkingHoursDto">
+ <include refid="selectAuxiliaryOutputWorking"/>
+ </select>
+ <select id="selectDataByUser" resultType="com.ruoyi.performance.dto.AuxiliaryOutputWorkingHoursDto">
+ select aowh.*, name, ip.cable_tag cableTag
+ FROM auxiliary_output_working_hours aowh
+ left join ins_product ip on ip.id = aowh.ins_product_id
+ left join user on user.id = aowh.`check`
+ WHERE 1 = 1
+ <if test="ids !=null and ids.size() > 0">
+ and `check` in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ </select>
+ <select id="totalHours" resultType="java.util.Map">
+ select A.name,
+ A.month,
+ FORMAT(SUM(A.manHours), 4) manHours
+ from(
+ select user.name,
+ date_time as month,
+ order_no,
+ sample,
+ man_hour_group,
+ case when #{type}='鍔犵彮宸ユ椂' then case when overtime_work_time is null then 0 else overtime_work_time end
+ else case when work_time is null then 0 else work_time end end as manHours
+ -- FORMAT(SUM(output_work_time), 4) as manHours
+ from auxiliary_output_working_hours aowh
+ left join user on user.id=aowh.`check`
+ left join department_lims dl on depart_lims_id=dl.id
+ where date_time LIKE CONCAT('%', #{month}, '%')
+ <if test="ids !=null and ids != ''">
+ and `check` in
+ <foreach collection="ids" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ group by user.name,date_time,order_no,
+ sample,
+ man_hour_group
+ order by user.name,date_time,order_no,
+ sample,
+ man_hour_group
+ )A
+ group by A.name,
+ A.month
+ order by A.name,
+ A.month
+ </select>
+ <select id="selectListByIds" resultType="com.ruoyi.performance.pojo.AuxiliaryOutputWorkingHours">
+ select * from auxiliary_output_working_hours
+ where 1=1
+ <if test="ids !=null and ids != ''">
+ and `check` in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ </select>
+
+ <select id="selectLists" resultMap="BaseResultMap">
+ select * from(select * from auxiliary_output_working_hours
+ WHERE 1=1
+ <if test="ids !=null and ids != ''">
+ and `check` in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ ) A
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="selectAuxiliaryAllByMonth" resultType="com.ruoyi.performance.dto.AuxiliaryAllDto">
+ select sum(aowh.work_time) yieldHour,
+ u.name userName,
+ aowh.`check` userId,
+ #{dto.month} month
+ from (SELECT *
+ FROM auxiliary_output_working_hours
+ GROUP BY CASE
+ WHEN man_hour_group IS NOT NULL AND man_hour_group != '' THEN man_hour_group
+ ELSE id
+ END
+ , CASE
+ WHEN man_hour_group IS NOT NULL AND man_hour_group != '' THEN order_id
+ ELSE id
+ END) aowh
+ left join user u on u.id = aowh.`check`
+ where aowh.date_time between #{dto.beginDate} and #{dto.endDate}
+ <if test="userIds !=null and userIds.size() > 0">
+ and aowh.`check` in
+ <foreach collection="userIds" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ group by aowh.`check`
+ </select>
+ <select id="selectSubsidiaryAllByMonth" resultType="com.ruoyi.performance.dto.AuxiliaryAllDto">
+ select sum(awhd.reviewer_nonproductive_time) subsidiaryHour,
+ u.name userName,
+ awhd.name_user userId,
+ #{dto.month} month
+ from auxiliary_working_hours_day awhd
+ left join user u on u.id = awhd.name_user
+ where awhd.date_time between #{dto.beginDate} and #{dto.endDate}
+ and awhd.state = '宸叉壒鍑�'
+ <if test="userIds !=null and userIds.size() > 0">
+ and awhd.name_user in
+ <foreach collection="userIds" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ group by awhd.name_user
+ </select>
+ <!-- 鏌ヨ浜ч噺宸ユ椂闆嗗悎 -->
+ <select id="selectAuxiliaryOutputWorkingHoursList" resultType="com.ruoyi.performance.dto.AuxiliaryOutputWorkingHoursDto">
+ <include refid="selectAuxiliaryOutputWorking"/>
+ </select>
+</mapper>
diff --git a/performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursDayMapper.xml b/performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursDayMapper.xml
new file mode 100644
index 0000000..48e6bb2
--- /dev/null
+++ b/performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursDayMapper.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.performance.mapper.AuxiliaryWorkingHoursDayMapper">
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay">
+ <id column="id" property="id"/>
+ <result column="nameUser" property="nameUser"/>
+ <result column="number" property="number"/>
+ <result column="auxiliary_project" property="auxiliaryProject"/>
+ <result column="approved_working_hour" property="approvedWorkingHour"/>
+ <result column="amount" property="amount"/>
+ <result column="nonproductive_time" property="nonproductiveTime"/>
+ <result column="remarks" property="remarks"/>
+ <result column="reviewer" property="reviewer"/>
+ <result column="reviewer_number" property="reviewerNumber"/>
+ <result column="reviewer_nonproductive_time" property="reviewerNonproductiveTime"/>
+ <result column="reviewer_remark" property="reviewerRemark"/>
+ <result column="year" property="year"/>
+ <result column="shift" property="shift"/>
+ <result column="week" property="week"/>
+ <result column="week_day" property="weekDay"/>
+ <result column="create_time" property="createTime"/>
+ <result column="update_time" property="updateTime"/>
+ <result column="create_user" property="createUser"/>
+ <result column="update_user" property="updateUser"/>
+ <result column="state" property="state"/>
+ </resultMap>
+
+ <sql id="selectAuxiliaryWorkingHours">
+ select A.*
+ from (
+ select awhd.*,name
+ FROM auxiliary_working_hours_day awhd
+ left join user on name_user=user.id
+ WHERE 1=1
+ <if test="ids !=null and ids.size() > 0">
+ and name_user in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ ) A
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </sql>
+
+ <select id="selectAuxiliaryWorkingHoursDay" resultType="com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto">
+ <include refid="selectAuxiliaryWorkingHours"/>
+ </select>
+ <select id="selectDataByUser" resultType="com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto">
+ select awhd.*,name
+ FROM auxiliary_working_hours_day awhd
+ left join user on name_user=user.id
+ WHERE 1=1
+ <if test="ids !=null and ids.size() > 0">
+ and name_user in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ </select>
+ <select id="selectListByIds" resultType="com.ruoyi.performance.pojo.AuxiliaryWorkingHoursDay">
+ select * from auxiliary_working_hours_day
+ where state='宸插鏍�'
+ <if test="ids !=null and ids != ''">
+ and name_user in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ </select>
+ <select id="totalHours" resultType="java.util.Map">
+ select A.name,
+ A.month,
+ FORMAT(SUM(manHour), 4)as manHours
+ from(
+ select user.name,
+ case when reviewer_nonproductive_time is null then nonproductive_time
+ else reviewer_nonproductive_time end as manHour,
+ date_time as month
+ from auxiliary_working_hours_day awhd
+ left join user on user.id=awhd.name_user
+ left join department_lims dl on depart_lims_id=dl.id
+ where date_time LIKE CONCAT('%', #{month}, '%')
+ and awhd.state='宸叉壒鍑�'
+ <if test="ids !=null and ids.size() > 0">
+ and name_user in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ order by month,user.name
+ )A
+ group by A.name,A.month
+ order by A.name,A.month
+ </select>
+
+ <select id="selectLists" resultMap="BaseResultMap">
+ select * from(select * from auxiliary_working_hours_day
+ WHERE 1=1
+ <if test="ids !=null and ids.size() > 0">
+ and name_user in
+ <foreach collection="ids" index="index" open="(" separator="," close=")" item="val">
+ #{val}
+ </foreach>
+ </if>
+ ) A
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+ <select id="selectAuxiliaryWorkingHoursDayList" resultType="com.ruoyi.performance.dto.AuxiliaryWorkingHoursDayDto">
+ <include refid="selectAuxiliaryWorkingHours"/>
+ </select>
+</mapper>
diff --git a/performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursMapper.xml b/performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursMapper.xml
new file mode 100644
index 0000000..0c4fd2c
--- /dev/null
+++ b/performance-server/src/main/resources/mapper/AuxiliaryWorkingHoursMapper.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.performance.mapper.AuxiliaryWorkingHoursMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.performance.pojo.AuxiliaryWorkingHours">
+ <id column="id" property="id" />
+ <result column="number" property="number"/>
+ <result column="AuxiliaryProject" property="auxiliaryProject" />
+ <result column="approved_working_hour" property="approvedWorkingHour" />
+ <result column="remarks" property="remarks" />
+ <result column="create_user" property="createUser" />
+ <result column="update_user" property="updateUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_time" property="updateTime" />
+ <result column="department" property="department" />
+ <result column="laboratory" property="laboratory" />
+ <result column="unit" property="unit"/>
+ </resultMap>
+ <select id="selectAuxiliaryWorkingHours" resultType="com.ruoyi.performance.pojo.AuxiliaryWorkingHours">
+ select data.*
+ from (
+ select
+ awh.id,
+ awh.number,
+ awh.auxiliary_project,
+ awh.laboratory,
+ awh.unit,
+ awh.approved_working_hour,
+ awh.department,
+ awh.remarks
+ FROM auxiliary_working_hours awh
+ ) data
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+</mapper>
diff --git a/performance-server/src/main/resources/mapper/PerformanceShiftMapper.xml b/performance-server/src/main/resources/mapper/PerformanceShiftMapper.xml
new file mode 100644
index 0000000..751ca1a
--- /dev/null
+++ b/performance-server/src/main/resources/mapper/PerformanceShiftMapper.xml
@@ -0,0 +1,135 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.performance.mapper.PerformanceShiftMapper">
+
+ <resultMap id="performanceShiftPageMap" type="com.ruoyi.performance.dto.PerformanceShiftMapDto">
+ <result column="name" property="name"/>
+ <result column="shift_time" property="shiftTime"/>
+ <result column="user_id" property="userId" />
+ <result column="department" property="department" />
+ </resultMap>
+
+ <select id="performanceShiftPage" resultMap="performanceShiftPageMap">
+ SELECT
+ if(u2.department is not null and u2.department != '', CONCAT(u2.name, '锛�', u2.department, '锛�'), u2.name) name,
+ GROUP_CONCAT(s.work_time, '锛�', s.shift, '锛�', s.id order by s.work_time SEPARATOR ';') AS shift_time, u2.id user_id
+ FROM performance_shift s
+ LEFT JOIN (SELECT distinct u.* from
+ user u
+ left join department_lims dl on FIND_IN_SET(dl.id,u.depart_lims_id)
+ where state=1
+ <if test="laboratory != null and laboratory != ''">
+ and dl.name=#{laboratory}
+ </if>
+ ) u2 on u2.id = s.user_id
+ <where>
+ name is not null
+ <if test="time != null and time != ''">
+ and DATE_FORMAT(s.work_time, '%Y-%m') = DATE_FORMAT(#{time}, '%Y-%m' )
+ </if>
+ <if test="userName != null and userName != ''">
+ and u2.name like concat('%', #{userName}, '%')
+ </if>
+ </where>
+ order by s.create_time
+ GROUP BY u2.id
+ </select>
+
+ <select id="performanceShiftYearPage" resultType="map">
+ SELECT
+ s.user_id, s.shift
+ FROM performance_shift s
+ LEFT JOIN (SELECT u.* from
+ user u
+ left join department_lims dl on FIND_IN_SET(dl.id,u.depart_lims_id)
+ where state=1
+ <if test="laboratory != null and laboratory != ''">
+ and dl.name=#{laboratory}
+ </if>
+ ) u2 on u2.id = s.user_id
+ where s.shift is not NULL
+ and s.shift != ''
+ and name is not null
+ <if test="time != null and time != ''">
+ and DATE_FORMAT(s.work_time, '%Y') = DATE_FORMAT(#{time}, '%Y' )
+ </if>
+ <if test="userName != null and userName != ''">
+ and u2.name like concat('%', #{userName}, '%')
+ </if>
+ order by s.create_time
+ </select>
+
+ <select id="performanceShiftYear" resultType="java.util.Map">
+ SELECT if(u2.department is not null and u2.department != '', CONCAT(u2.name, '锛�', u2.department, '锛�'), u2.name) name,
+ s.user_id, u2.account,
+ DATE_FORMAT(s.work_time, '%c') work_time,
+ GROUP_CONCAT(DATE_FORMAT(s.work_time, '%c'), '锛�', s.shift order by s.work_time SEPARATOR ';') month_str
+ FROM performance_shift s
+ LEFT JOIN (SELECT u.* from
+ user u
+ left join department_lims dl on FIND_IN_SET(dl.id,u.depart_lims_id)
+ where state=1
+ <if test="laboratory != null and laboratory != ''">
+ and dl.name=#{laboratory}
+ </if>
+ ) u2 on u2.id = s.user_id
+ where s.shift is not NULL
+ and s.shift != ''
+ and name is not null
+ <if test="time != null and time != ''">
+ and DATE_FORMAT(s.work_time, '%Y') = DATE_FORMAT(#{time}, '%Y' )
+ </if>
+ <if test="userName != null and userName != ''">
+ and u.name like concat('%', #{userName}, '%')
+ </if>
+ GROUP BY u2.id
+ order by s.create_time
+ </select>
+
+ <select id="performanceShiftYearList" resultType="map">
+ SELECT if(u.department is not null and u.department != '', CONCAT(u.name, '锛�', u.department, '锛�'), u.name) name,
+ s.user_id, u.account,
+ DATE_FORMAT(s.work_time, '%c') work_time,
+ GROUP_CONCAT(DATE_FORMAT(s.work_time, '%c'), '锛�', s.shift order by s.work_time SEPARATOR ';') month_str
+ FROM performance_shift s
+ LEFT JOIN user u on u.id = s.user_id
+ where s.shift is not NULL
+ and s.shift != ''
+ <if test="time != null and time != ''">
+ and DATE_FORMAT(s.work_time, '%Y') = DATE_FORMAT(#{time}, '%Y' )
+ </if>
+ <if test="userName != null and userName != ''">
+ and u.name like concat('%', #{userName}, '%')
+ </if>
+ <if test="laboratory != null and laboratory != ''">
+ </if>
+ GROUP BY u.id
+ order by s.create_time
+ </select>
+
+ <select id="performanceShiftList" resultMap="performanceShiftPageMap">
+ SELECT
+ if(u.department is not null and u.department != '', CONCAT(u.name, '锛�', u.department, '锛�'), u.name) name,
+ GROUP_CONCAT(s.work_time, '锛�', s.shift, '锛�', s.id order by s.work_time SEPARATOR ';') AS shift_time, u.id user_id, u.department
+ FROM performance_shift s
+ LEFT JOIN user u on u.id = s.user_id
+ <where>
+ <if test="time != null and time != ''">
+ and DATE_FORMAT(s.work_time, '%Y-%m') = DATE_FORMAT(#{time}, '%Y-%m' )
+ </if>
+ <if test="userName != null and userName != ''">
+ and u.name like concat('%', #{userName}, '%')
+ </if>
+ <if test="laboratory != null and laboratory != ''">
+ </if>
+ </where>
+ order by s.create_time
+ GROUP BY u.id
+ </select>
+
+ <select id="seldepLimsId" resultType="java.lang.String">
+ select name
+ from department_lims
+ where id = #{depLimsId}
+ </select>
+</mapper>
diff --git a/performance-server/src/main/resources/mapper/ShiftTimeMapper.xml b/performance-server/src/main/resources/mapper/ShiftTimeMapper.xml
new file mode 100644
index 0000000..49ac714
--- /dev/null
+++ b/performance-server/src/main/resources/mapper/ShiftTimeMapper.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.performance.mapper.ShiftTimeMapper">
+
+ <!-- 閫氱敤鏌ヨ鏄犲皠缁撴灉 -->
+ <resultMap id="BaseResultMap" type="com.ruoyi.performance.pojo.ShiftTime">
+ <id column="id" property="id" />
+ <result column="shift" property="shift" />
+ <result column="start_time" property="startTime" />
+ <result column="end_time" property="endTime" />
+ <result column="create_user" property="createUser" />
+ <result column="create_time" property="createTime" />
+ <result column="update_user" property="updateUser" />
+ <result column="update_time" property="updateTime" />
+ </resultMap>
+
+</mapper>
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..ab947ba
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,385 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi</artifactId>
+ <version>3.8.9</version>
+
+ <name>ruoyi</name>
+ <url>http://www.ruoyi.vip</url>
+ <description>鑻ヤ緷绠$悊绯荤粺</description>
+
+ <properties>
+ <ruoyi.version>3.8.9</ruoyi.version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+ <java.version>1.8</java.version>
+ <maven-jar-plugin.version>3.1.1</maven-jar-plugin.version>
+ <spring-boot.version>2.5.15</spring-boot.version>
+ <druid.version>1.2.23</druid.version>
+ <bitwalker.version>1.21</bitwalker.version>
+ <swagger.version>3.0.0</swagger.version>
+ <kaptcha.version>2.3.3</kaptcha.version>
+ <pagehelper.boot.version>1.4.7</pagehelper.boot.version>
+ <fastjson.version>2.0.53</fastjson.version>
+ <oshi.version>6.6.5</oshi.version>
+ <commons.io.version>2.13.0</commons.io.version>
+ <poi.version>4.1.2</poi.version>
+ <velocity.version>2.3</velocity.version>
+ <jwt.version>0.9.1</jwt.version>
+ <!-- override dependency version -->
+ <tomcat.version>9.0.96</tomcat.version>
+ <logback.version>1.2.13</logback.version>
+ <spring-security.version>5.7.12</spring-security.version>
+ <spring-framework.version>5.3.39</spring-framework.version>
+ <mybatis-plus.version>3.5.3.1</mybatis-plus.version>
+ <freemarker.version>2.3.30</freemarker.version>
+ <knife4j-spring-ui.version>3.0.3</knife4j-spring-ui.version>
+ <core.version>3.4.1</core.version>
+ <javase.version>3.4.1</javase.version>
+ <minio.version>8.4.3</minio.version>
+ <okhttp.version>4.9.0</okhttp.version>
+ <hutool.version>5.8.18</hutool.version>
+ <easyexcel.version>3.3.2</easyexcel.version>
+ </properties>
+
+ <!-- 渚濊禆澹版槑 -->
+ <dependencyManagement>
+ <dependencies>
+
+ <!-- 瑕嗙洊SpringFramework鐨勪緷璧栭厤缃�-->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-framework-bom</artifactId>
+ <version>${spring-framework.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <!-- 瑕嗙洊SpringSecurity鐨勪緷璧栭厤缃�-->
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-bom</artifactId>
+ <version>${spring-security.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <!-- SpringBoot鐨勪緷璧栭厤缃�-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+
+ <!--鍚庣娉ㄩ噴妫�楠屽伐鍏�-->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ <version>${spring-boot.version}</version>
+ </dependency>
+
+ <!-- 瑕嗙洊logback鐨勪緷璧栭厤缃�-->
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-core</artifactId>
+ <version>${logback.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <version>${logback.version}</version>
+ </dependency>
+
+ <!-- 瑕嗙洊tomcat鐨勪緷璧栭厤缃�-->
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-core</artifactId>
+ <version>${tomcat.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-el</artifactId>
+ <version>${tomcat.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.tomcat.embed</groupId>
+ <artifactId>tomcat-embed-websocket</artifactId>
+ <version>${tomcat.version}</version>
+ </dependency>
+
+ <!-- 闃块噷鏁版嵁搴撹繛鎺ユ睜 -->
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ <version>${druid.version}</version>
+ </dependency>
+
+ <!-- 瑙f瀽瀹㈡埛绔搷浣滅郴缁熴�佹祻瑙堝櫒绛� -->
+ <dependency>
+ <groupId>eu.bitwalker</groupId>
+ <artifactId>UserAgentUtils</artifactId>
+ <version>${bitwalker.version}</version>
+ </dependency>
+
+ <!-- pagehelper 鍒嗛〉鎻掍欢 -->
+ <dependency>
+ <groupId>com.github.pagehelper</groupId>
+ <artifactId>pagehelper-spring-boot-starter</artifactId>
+ <version>${pagehelper.boot.version}</version>
+ </dependency>
+
+ <!-- 鑾峰彇绯荤粺淇℃伅 -->
+ <dependency>
+ <groupId>com.github.oshi</groupId>
+ <artifactId>oshi-core</artifactId>
+ <version>${oshi.version}</version>
+ </dependency>
+
+ <!-- Swagger3渚濊禆 -->
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-boot-starter</artifactId>
+ <version>${swagger.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-models</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- io甯哥敤宸ュ叿绫� -->
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>${commons.io.version}</version>
+ </dependency>
+
+ <!-- excel宸ュ叿 -->
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-ooxml</artifactId>
+ <version>${poi.version}</version>
+ </dependency>
+
+ <!-- velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity-engine-core</artifactId>
+ <version>${velocity.version}</version>
+ </dependency>
+
+ <!-- 闃块噷JSON瑙f瀽鍣� -->
+ <dependency>
+ <groupId>com.alibaba.fastjson2</groupId>
+ <artifactId>fastjson2</artifactId>
+ <version>${fastjson.version}</version>
+ </dependency>
+
+ <!-- Token鐢熸垚涓庤В鏋�-->
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt</artifactId>
+ <version>${jwt.version}</version>
+ </dependency>
+
+ <!-- 楠岃瘉鐮� -->
+ <dependency>
+ <groupId>pro.fessional</groupId>
+ <artifactId>kaptcha</artifactId>
+ <version>${kaptcha.version}</version>
+ </dependency>
+
+ <!-- 瀹氭椂浠诲姟-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-quartz</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+ <!-- 浠g爜鐢熸垚-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-generator</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+ <!-- 鏍稿績妯″潡-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-framework</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+ <!-- 绯荤粺妯″潡-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-system</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+ <!-- 閫氱敤宸ュ叿-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+
+ <!-- minio -->
+ <dependency>
+ <groupId>io.minio</groupId>
+ <artifactId>minio</artifactId>
+ <version>${minio.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>okhttp</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- minio渚濊禆okhttp 涓嶇劧鎶ラ敊 -->
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>okhttp</artifactId>
+ <version>${okhttp.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <!-- 鍏ㄥ眬寮曞叆 -->
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>easyexcel</artifactId>
+ <version>${easyexcel.version}</version>
+ </dependency>
+
+ <!--mybatis-plus-->
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-boot-starter</artifactId>
+ <version>${mybatis-plus.version}</version>
+ </dependency>
+
+ <!--mybatis-plus浠g爜鐢熸垚鍣�-->
+ <dependency>
+ <groupId>com.baomidou</groupId>
+ <artifactId>mybatis-plus-generator</artifactId>
+ <version>${mybatis-plus.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.freemarker</groupId>
+ <artifactId>freemarker</artifactId>
+ <version>${freemarker.version}</version>
+ </dependency>
+
+ <!-- Swagger3渚濊禆 -->
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-boot-starter</artifactId>
+ <version>${swagger.version}</version>
+ </dependency>
+
+ <!--Swagger3-Ui缇庡寲-->
+ <dependency>
+ <groupId>com.github.xiaoymin</groupId>
+ <artifactId>knife4j-spring-ui</artifactId>
+ <version>${knife4j-spring-ui.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.zxing</groupId>
+ <artifactId>core</artifactId>
+ <version>${core.version}</version> <!-- 鎴栬�呮洿楂樼増鏈� -->
+ </dependency>
+ <dependency>
+ <groupId>com.google.zxing</groupId>
+ <artifactId>javase</artifactId>
+ <version>${javase.version}</version> <!-- 鎴栬�呮洿楂樼増鏈� -->
+ </dependency>
+
+ <!--hutool宸ュ叿鍖�-->
+ <dependency>
+ <groupId>cn.hutool</groupId>
+ <artifactId>hutool-all</artifactId>
+ <version>${hutool.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>fastjson</artifactId>
+ <version>2.0.23</version>
+ </dependency>
+ </dependencies>
+
+ <modules>
+ <module>ruoyi-admin</module>
+ <module>ruoyi-framework</module>
+ <module>ruoyi-system</module>
+ <module>ruoyi-quartz</module>
+ <module>ruoyi-generator</module>
+ <module>ruoyi-common</module>
+ <module>basic-server</module>
+ <module>inspect-server</module>
+ <module>performance-server</module>
+ </modules>
+ <packaging>pom</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ <encoding>${project.build.sourceEncoding}</encoding>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <repositories>
+ <repository>
+ <id>public</id>
+ <name>aliyun nexus</name>
+ <url>https://maven.aliyun.com/repository/public</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ </repository>
+ </repositories>
+
+ <pluginRepositories>
+ <pluginRepository>
+ <id>public</id>
+ <name>aliyun nexus</name>
+ <url>https://maven.aliyun.com/repository/public</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </pluginRepository>
+ </pluginRepositories>
+
+</project>
diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml
new file mode 100644
index 0000000..0009314
--- /dev/null
+++ b/ruoyi-admin/pom.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <packaging>jar</packaging>
+ <artifactId>ruoyi-admin</artifactId>
+
+ <description>
+ web鏈嶅姟鍏ュ彛
+ </description>
+
+ <dependencies>
+
+ <!-- spring-boot-devtools -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-devtools</artifactId>
+ <optional>true</optional> <!-- 琛ㄧず渚濊禆涓嶄細浼犻�� -->
+ </dependency>
+
+ <!-- swagger3-->
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-boot-starter</artifactId>
+ </dependency>
+
+ <!-- 闃叉杩涘叆swagger椤甸潰鎶ョ被鍨嬭浆鎹㈤敊璇紝鎺掗櫎3.0.0涓殑寮曠敤锛屾墜鍔ㄥ鍔�1.6.2鐗堟湰 -->
+ <dependency>
+ <groupId>io.swagger</groupId>
+ <artifactId>swagger-models</artifactId>
+ <version>1.6.2</version>
+ </dependency>
+
+ <!-- Mysql椹卞姩鍖� -->
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ </dependency>
+
+ <!-- 鏍稿績妯″潡-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-framework</artifactId>
+ </dependency>
+
+ <!-- 瀹氭椂浠诲姟-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-quartz</artifactId>
+ </dependency>
+
+ <!-- 浠g爜鐢熸垚-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-generator</artifactId>
+ </dependency>
+
+ <!--鍩虹妯″潡-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>basic-server</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+ <!--涓氬姟妯″潡-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>inspect-server</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+ <!--缁╂晥妯″潡-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>performance-server</artifactId>
+ <version>${ruoyi.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>2.5.15</version>
+ <configuration>
+ <fork>true</fork> <!-- 濡傛灉娌℃湁璇ラ厤缃紝devtools涓嶄細鐢熸晥 -->
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-war-plugin</artifactId>
+ <version>3.1.0</version>
+ <configuration>
+ <failOnMissingWebXml>false</failOnMissingWebXml>
+ <warName>${project.artifactId}</warName>
+ </configuration>
+ </plugin>
+ </plugins>
+ <finalName>${project.artifactId}</finalName>
+ </build>
+
+</project>
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/CodeGenerator.java b/ruoyi-admin/src/main/java/com/ruoyi/CodeGenerator.java
new file mode 100644
index 0000000..c78cf33
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/CodeGenerator.java
@@ -0,0 +1,104 @@
+package com.ruoyi;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.generator.FastAutoGenerator;
+import com.baomidou.mybatisplus.generator.config.OutputFile;
+import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
+import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
+import com.baomidou.mybatisplus.generator.fill.Column;
+
+import java.util.Collections;
+import java.util.Scanner;
+
+// 婕旂ず渚嬪瓙锛屾墽琛� main 鏂规硶鎺у埗鍙拌緭鍏ユā鍧楄〃鍚嶅洖杞﹁嚜鍔ㄧ敓鎴愬搴旈」鐩洰褰曚腑
+public class CodeGenerator {
+
+ public static String database_url = "jdbc:mysql://114.132.189.42:9004/lims-zb";
+ public static String database_username = "root";
+ public static String database_password= "123456";
+ public static String author = "鑺杞欢锛堟睙鑻忥級鏈夐檺鍏徃";
+ public static String model_name = "/mes-technical"; // 濡傛灉涓哄垎甯冨紡濉瓙妯″潡鍚嶇О锛屽鏋滀笉鏄垎甯冨紡涓虹┖鍗冲彲
+ public static String setParent = "com.ruoyi.technical"; // 鍖呰矾寰�
+ public static String tablePrefix = "technical"; // 璁剧疆杩囨护琛ㄥ墠缂�
+ public static void main(String[] args) {
+ String projectPath = System.getProperty("user.dir");
+ FastAutoGenerator.create(database_url, database_username, database_password)
+ // 鍏ㄥ眬閰嶇疆
+ .globalConfig(builder -> {
+ builder.author(author) // 璁剧疆浣滆��
+ .commentDate("yyyy-MM-dd hh:mm:ss") //娉ㄩ噴鏃ユ湡
+ .outputDir(projectPath + model_name + "/src/main/java") // 鎸囧畾杈撳嚭鐩綍
+ .disableOpenDir() //绂佹鎵撳紑杈撳嚭鐩綍锛岄粯璁ゆ墦寮�
+ .enableSwagger() // 寮�鍚痵wagger
+
+ ;
+ })
+ // 鍖呴厤缃�
+ .packageConfig(builder -> {
+ builder.entity("pojo");
+ builder.parent(setParent) // 璁剧疆鐖跺寘鍚�
+ .pathInfo(Collections.singletonMap(OutputFile.xml, projectPath + model_name + "/src/main/resources/mapper")); // 璁剧疆mapperXml鐢熸垚璺緞
+ })
+ // 绛栫暐閰嶇疆
+ .strategyConfig(builder -> {
+ builder.addInclude(scanner("琛ㄥ悕锛屽涓┖鏍煎垎鍓�").split(" ")) // 璁剧疆闇�瑕佺敓鎴愮殑琛ㄥ悕
+ .addTablePrefix(tablePrefix) // 璁剧疆杩囨护琛ㄥ墠缂�
+ // Entity 绛栫暐閰嶇疆
+ .entityBuilder()
+ .enableLombok() //寮�鍚� Lombok
+ .naming(NamingStrategy.underline_to_camel) //鏁版嵁搴撹〃鏄犲皠鍒板疄浣撶殑鍛藉悕绛栫暐锛氫笅鍒掔嚎杞┘宄板懡
+ .columnNaming(NamingStrategy.underline_to_camel) //鏁版嵁搴撹〃瀛楁鏄犲皠鍒板疄浣撶殑鍛藉悕绛栫暐锛氫笅鍒掔嚎杞┘宄板懡
+ .enableFileOverride() // 瑕嗙洊宸茬粡鐢熸垚鐨凟ntity鏂囦欢
+ .logicDeleteColumnName("state")
+ .addTableFills(
+ new Column("create_time", FieldFill.INSERT),
+ new Column("update_time", FieldFill.INSERT_UPDATE),
+ new Column("create_user", FieldFill.INSERT),
+ new Column("update_user", FieldFill.INSERT_UPDATE)
+ )
+ .idType(IdType.AUTO) // 鑷涓婚敭
+
+ // Mapper 绛栫暐閰嶇疆
+ .mapperBuilder()
+ .enableFileOverride() // 瑕嗙洊宸茬敓鎴怣apper鏂囦欢
+ .enableBaseResultMap() // 鑷姩鐢熸垚resultMap
+ // Service 绛栫暐閰嶇疆
+ .serviceBuilder()
+ .formatServiceFileName("%sService") //鏍煎紡鍖� service 鎺ュ彛鏂囦欢鍚嶇О锛�%s杩涜鍖归厤琛ㄥ悕锛屽 UserService
+ .formatServiceImplFileName("%sServiceImpl") //鏍煎紡鍖� service 瀹炵幇绫绘枃浠跺悕绉帮紝%s杩涜鍖归厤琛ㄥ悕锛屽 UserServiceImpl
+ .enableFileOverride() // 瑕嗙洊宸茬敓鎴愭枃浠�
+
+ // Controller 绛栫暐閰嶇疆
+ .controllerBuilder()
+ .enableFileOverride() // 瑕嗙洊宸茬敓鎴愭枃浠�
+ .enableRestStyle() // 寮�鍚敓鎴怈RestController 鎺у埗鍣�
+ ;
+ })
+ //5銆佹ā鏉垮紩鎿�
+ .templateEngine(new FreemarkerTemplateEngine()) //榛樿
+ .execute();
+ }
+
+ /**
+ * <p>
+ * 璇诲彇鎺у埗鍙板唴瀹�
+ * </p>
+ */
+ public static String scanner(String tip) {
+ Scanner scanner = new Scanner(System.in);
+ StringBuilder help = new StringBuilder();
+ help.append("璇疯緭鍏�" + tip + "锛�");
+ System.out.println(help.toString());
+ if (scanner.hasNext()) {
+ String ipt = scanner.next();
+
+ if (StringUtils.isNotBlank(ipt)) {
+ return ipt;
+ }
+ }
+ throw new MybatisPlusException("璇疯緭鍏ユ纭殑" + tip + "锛�");
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
new file mode 100644
index 0000000..1133e0c
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiApplication.java
@@ -0,0 +1,20 @@
+package com.ruoyi;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
+
+/**
+ * 鍚姩绋嬪簭
+ *
+ * @author ruoyi
+ */
+@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })
+public class RuoYiApplication
+{
+ public static void main(String[] args)
+ {
+ System.setProperty("spring.devtools.restart.enabled", "false");
+ SpringApplication.run(RuoYiApplication.class, args);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
new file mode 100644
index 0000000..6de67dc
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/RuoYiServletInitializer.java
@@ -0,0 +1,18 @@
+package com.ruoyi;
+
+import org.springframework.boot.builder.SpringApplicationBuilder;
+import org.springframework.boot.web.servlet.support.SpringBootServletInitializer;
+
+/**
+ * web瀹瑰櫒涓繘琛岄儴缃�
+ *
+ * @author ruoyi
+ */
+public class RuoYiServletInitializer extends SpringBootServletInitializer
+{
+ @Override
+ protected SpringApplicationBuilder configure(SpringApplicationBuilder application)
+ {
+ return application.sources(RuoYiApplication.class);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
new file mode 100644
index 0000000..a6f4a3b
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CaptchaController.java
@@ -0,0 +1,94 @@
+package com.ruoyi.web.controller.common;
+
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+import javax.annotation.Resource;
+import javax.imageio.ImageIO;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.util.FastByteArrayOutputStream;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.google.code.kaptcha.Producer;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.sign.Base64;
+import com.ruoyi.common.utils.uuid.IdUtils;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * 楠岃瘉鐮佹搷浣滃鐞�
+ *
+ * @author ruoyi
+ */
+@RestController
+public class CaptchaController
+{
+ @Resource(name = "captchaProducer")
+ private Producer captchaProducer;
+
+ @Resource(name = "captchaProducerMath")
+ private Producer captchaProducerMath;
+
+ @Autowired
+ private RedisCache redisCache;
+
+ @Autowired
+ private ISysConfigService configService;
+ /**
+ * 鐢熸垚楠岃瘉鐮�
+ */
+ @GetMapping("/captchaImage")
+ public AjaxResult getCode(HttpServletResponse response) throws IOException
+ {
+ AjaxResult ajax = AjaxResult.success();
+ boolean captchaEnabled = configService.selectCaptchaEnabled();
+ ajax.put("captchaEnabled", captchaEnabled);
+ if (!captchaEnabled)
+ {
+ return ajax;
+ }
+
+ // 淇濆瓨楠岃瘉鐮佷俊鎭�
+ String uuid = IdUtils.simpleUUID();
+ String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + uuid;
+
+ String capStr = null, code = null;
+ BufferedImage image = null;
+
+ // 鐢熸垚楠岃瘉鐮�
+ String captchaType = RuoYiConfig.getCaptchaType();
+ if ("math".equals(captchaType))
+ {
+ String capText = captchaProducerMath.createText();
+ capStr = capText.substring(0, capText.lastIndexOf("@"));
+ code = capText.substring(capText.lastIndexOf("@") + 1);
+ image = captchaProducerMath.createImage(capStr);
+ }
+ else if ("char".equals(captchaType))
+ {
+ capStr = code = captchaProducer.createText();
+ image = captchaProducer.createImage(capStr);
+ }
+
+ redisCache.setCacheObject(verifyKey, code, Constants.CAPTCHA_EXPIRATION, TimeUnit.MINUTES);
+ // 杞崲娴佷俊鎭啓鍑�
+ FastByteArrayOutputStream os = new FastByteArrayOutputStream();
+ try
+ {
+ ImageIO.write(image, "jpg", os);
+ }
+ catch (IOException e)
+ {
+ return AjaxResult.error(e.getMessage());
+ }
+
+ ajax.put("uuid", uuid);
+ ajax.put("img", Base64.encode(os.toByteArray()));
+ return ajax;
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
new file mode 100644
index 0000000..d58b107
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/common/CommonController.java
@@ -0,0 +1,163 @@
+package com.ruoyi.web.controller.common;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.file.FileUtils;
+import com.ruoyi.framework.config.ServerConfig;
+
+/**
+ * 閫氱敤璇锋眰澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/common")
+public class CommonController
+{
+ private static final Logger log = LoggerFactory.getLogger(CommonController.class);
+
+ @Autowired
+ private ServerConfig serverConfig;
+
+ private static final String FILE_DELIMETER = ",";
+
+ /**
+ * 閫氱敤涓嬭浇璇锋眰
+ *
+ * @param fileName 鏂囦欢鍚嶇О
+ * @param delete 鏄惁鍒犻櫎
+ */
+ @GetMapping("/download")
+ public void fileDownload(String fileName, Boolean delete, HttpServletResponse response, HttpServletRequest request)
+ {
+ try
+ {
+ if (!FileUtils.checkAllowDownload(fileName))
+ {
+ throw new Exception(StringUtils.format("鏂囦欢鍚嶇О({})闈炴硶锛屼笉鍏佽涓嬭浇銆� ", fileName));
+ }
+ String realFileName = System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
+ String filePath = RuoYiConfig.getDownloadPath() + fileName;
+
+ response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+ FileUtils.setAttachmentResponseHeader(response, realFileName);
+ FileUtils.writeBytes(filePath, response.getOutputStream());
+ if (delete)
+ {
+ FileUtils.deleteFile(filePath);
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("涓嬭浇鏂囦欢澶辫触", e);
+ }
+ }
+
+ /**
+ * 閫氱敤涓婁紶璇锋眰锛堝崟涓級
+ */
+ @PostMapping("/upload")
+ public AjaxResult uploadFile(MultipartFile file) throws Exception
+ {
+ try
+ {
+ // 涓婁紶鏂囦欢璺緞
+ String filePath = RuoYiConfig.getUploadPath();
+ // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
+ String fileName = FileUploadUtils.upload(filePath, file);
+ String url = serverConfig.getUrl() + fileName;
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("url", url);
+ ajax.put("fileName", fileName);
+ ajax.put("newFileName", FileUtils.getName(fileName));
+ ajax.put("originalFilename", file.getOriginalFilename());
+ return ajax;
+ }
+ catch (Exception e)
+ {
+ return AjaxResult.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 閫氱敤涓婁紶璇锋眰锛堝涓級
+ */
+ @PostMapping("/uploads")
+ public AjaxResult uploadFiles(List<MultipartFile> files) throws Exception
+ {
+ try
+ {
+ // 涓婁紶鏂囦欢璺緞
+ String filePath = RuoYiConfig.getUploadPath();
+ List<String> urls = new ArrayList<String>();
+ List<String> fileNames = new ArrayList<String>();
+ List<String> newFileNames = new ArrayList<String>();
+ List<String> originalFilenames = new ArrayList<String>();
+ for (MultipartFile file : files)
+ {
+ // 涓婁紶骞惰繑鍥炴柊鏂囦欢鍚嶇О
+ String fileName = FileUploadUtils.upload(filePath, file);
+ String url = serverConfig.getUrl() + fileName;
+ urls.add(url);
+ fileNames.add(fileName);
+ newFileNames.add(FileUtils.getName(fileName));
+ originalFilenames.add(file.getOriginalFilename());
+ }
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("urls", StringUtils.join(urls, FILE_DELIMETER));
+ ajax.put("fileNames", StringUtils.join(fileNames, FILE_DELIMETER));
+ ajax.put("newFileNames", StringUtils.join(newFileNames, FILE_DELIMETER));
+ ajax.put("originalFilenames", StringUtils.join(originalFilenames, FILE_DELIMETER));
+ return ajax;
+ }
+ catch (Exception e)
+ {
+ return AjaxResult.error(e.getMessage());
+ }
+ }
+
+ /**
+ * 鏈湴璧勬簮閫氱敤涓嬭浇
+ */
+ @GetMapping("/download/resource")
+ public void resourceDownload(String resource, HttpServletRequest request, HttpServletResponse response)
+ throws Exception
+ {
+ try
+ {
+ if (!FileUtils.checkAllowDownload(resource))
+ {
+ throw new Exception(StringUtils.format("璧勬簮鏂囦欢({})闈炴硶锛屼笉鍏佽涓嬭浇銆� ", resource));
+ }
+ // 鏈湴璧勬簮璺緞
+ String localPath = RuoYiConfig.getProfile();
+ // 鏁版嵁搴撹祫婧愬湴鍧�
+ String downloadPath = localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
+ // 涓嬭浇鍚嶇О
+ String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
+ response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
+ FileUtils.setAttachmentResponseHeader(response, downloadName);
+ FileUtils.writeBytes(downloadPath, response.getOutputStream());
+ }
+ catch (Exception e)
+ {
+ log.error("涓嬭浇鏂囦欢澶辫触", e);
+ }
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
new file mode 100644
index 0000000..b3859cb
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/CacheController.java
@@ -0,0 +1,121 @@
+package com.ruoyi.web.controller.monitor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisCallback;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysCache;
+
+/**
+ * 缂撳瓨鐩戞帶
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/cache")
+public class CacheController
+{
+ @Autowired
+ private RedisTemplate<String, String> redisTemplate;
+
+ private final static List<SysCache> caches = new ArrayList<SysCache>();
+ {
+ caches.add(new SysCache(CacheConstants.LOGIN_TOKEN_KEY, "鐢ㄦ埛淇℃伅"));
+ caches.add(new SysCache(CacheConstants.SYS_CONFIG_KEY, "閰嶇疆淇℃伅"));
+ caches.add(new SysCache(CacheConstants.SYS_DICT_KEY, "鏁版嵁瀛楀吀"));
+ caches.add(new SysCache(CacheConstants.CAPTCHA_CODE_KEY, "楠岃瘉鐮�"));
+ caches.add(new SysCache(CacheConstants.REPEAT_SUBMIT_KEY, "闃查噸鎻愪氦"));
+ caches.add(new SysCache(CacheConstants.RATE_LIMIT_KEY, "闄愭祦澶勭悊"));
+ caches.add(new SysCache(CacheConstants.PWD_ERR_CNT_KEY, "瀵嗙爜閿欒娆℃暟"));
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping()
+ public AjaxResult getInfo() throws Exception
+ {
+ Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
+ Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
+ Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());
+
+ Map<String, Object> result = new HashMap<>(3);
+ result.put("info", info);
+ result.put("dbSize", dbSize);
+
+ List<Map<String, String>> pieList = new ArrayList<>();
+ commandStats.stringPropertyNames().forEach(key -> {
+ Map<String, String> data = new HashMap<>(2);
+ String property = commandStats.getProperty(key);
+ data.put("name", StringUtils.removeStart(key, "cmdstat_"));
+ data.put("value", StringUtils.substringBetween(property, "calls=", ",usec"));
+ pieList.add(data);
+ });
+ result.put("commandStats", pieList);
+ return AjaxResult.success(result);
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping("/getNames")
+ public AjaxResult cache()
+ {
+ return AjaxResult.success(caches);
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping("/getKeys/{cacheName}")
+ public AjaxResult getCacheKeys(@PathVariable String cacheName)
+ {
+ Set<String> cacheKeys = redisTemplate.keys(cacheName + "*");
+ return AjaxResult.success(new TreeSet<>(cacheKeys));
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @GetMapping("/getValue/{cacheName}/{cacheKey}")
+ public AjaxResult getCacheValue(@PathVariable String cacheName, @PathVariable String cacheKey)
+ {
+ String cacheValue = redisTemplate.opsForValue().get(cacheKey);
+ SysCache sysCache = new SysCache(cacheName, cacheKey, cacheValue);
+ return AjaxResult.success(sysCache);
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @DeleteMapping("/clearCacheName/{cacheName}")
+ public AjaxResult clearCacheName(@PathVariable String cacheName)
+ {
+ Collection<String> cacheKeys = redisTemplate.keys(cacheName + "*");
+ redisTemplate.delete(cacheKeys);
+ return AjaxResult.success();
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @DeleteMapping("/clearCacheKey/{cacheKey}")
+ public AjaxResult clearCacheKey(@PathVariable String cacheKey)
+ {
+ redisTemplate.delete(cacheKey);
+ return AjaxResult.success();
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
+ @DeleteMapping("/clearCacheAll")
+ public AjaxResult clearCacheAll()
+ {
+ Collection<String> cacheKeys = redisTemplate.keys("*");
+ redisTemplate.delete(cacheKeys);
+ return AjaxResult.success();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java
new file mode 100644
index 0000000..aab1419
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/ServerController.java
@@ -0,0 +1,27 @@
+package com.ruoyi.web.controller.monitor;
+
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.framework.web.domain.Server;
+
+/**
+ * 鏈嶅姟鍣ㄧ洃鎺�
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/server")
+public class ServerController
+{
+ @PreAuthorize("@ss.hasPermi('monitor:server:list')")
+ @GetMapping()
+ public AjaxResult getInfo() throws Exception
+ {
+ Server server = new Server();
+ server.copyTo();
+ return AjaxResult.success(server);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
new file mode 100644
index 0000000..7e4fb7f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysLogininforController.java
@@ -0,0 +1,82 @@
+package com.ruoyi.web.controller.monitor;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.service.SysPasswordService;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.service.ISysLogininforService;
+
+/**
+ * 绯荤粺璁块棶璁板綍
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/logininfor")
+public class SysLogininforController extends BaseController
+{
+ @Autowired
+ private ISysLogininforService logininforService;
+
+ @Autowired
+ private SysPasswordService passwordService;
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysLogininfor logininfor)
+ {
+ startPage();
+ List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+ return getDataTable(list);
+ }
+
+ @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysLogininfor logininfor)
+ {
+ List<SysLogininfor> list = logininforService.selectLogininforList(logininfor);
+ ExcelUtil<SysLogininfor> util = new ExcelUtil<SysLogininfor>(SysLogininfor.class);
+ util.exportExcel(response, list, "鐧诲綍鏃ュ織");
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
+ @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{infoIds}")
+ public AjaxResult remove(@PathVariable Long[] infoIds)
+ {
+ return toAjax(logininforService.deleteLogininforByIds(infoIds));
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:remove')")
+ @Log(title = "鐧诲綍鏃ュ織", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/clean")
+ public AjaxResult clean()
+ {
+ logininforService.cleanLogininfor();
+ return success();
+ }
+
+ @PreAuthorize("@ss.hasPermi('monitor:logininfor:unlock')")
+ @Log(title = "璐︽埛瑙i攣", businessType = BusinessType.OTHER)
+ @GetMapping("/unlock/{userName}")
+ public AjaxResult unlock(@PathVariable("userName") String userName)
+ {
+ passwordService.clearLoginRecordCache(userName);
+ return success();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
new file mode 100644
index 0000000..5e17574
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysOperlogController.java
@@ -0,0 +1,69 @@
+package com.ruoyi.web.controller.monitor;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.service.ISysOperLogService;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/operlog")
+public class SysOperlogController extends BaseController
+{
+ @Autowired
+ private ISysOperLogService operLogService;
+
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysOperLog operLog)
+ {
+ startPage();
+ List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+ return getDataTable(list);
+ }
+
+ @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysOperLog operLog)
+ {
+ List<SysOperLog> list = operLogService.selectOperLogList(operLog);
+ ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
+ util.exportExcel(response, list, "鎿嶄綔鏃ュ織");
+ }
+
+ @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.DELETE)
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
+ @DeleteMapping("/{operIds}")
+ public AjaxResult remove(@PathVariable Long[] operIds)
+ {
+ return toAjax(operLogService.deleteOperLogByIds(operIds));
+ }
+
+ @Log(title = "鎿嶄綔鏃ュ織", businessType = BusinessType.CLEAN)
+ @PreAuthorize("@ss.hasPermi('monitor:operlog:remove')")
+ @DeleteMapping("/clean")
+ public AjaxResult clean()
+ {
+ operLogService.cleanOperLog();
+ return success();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
new file mode 100644
index 0000000..a26dcf5
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/monitor/SysUserOnlineController.java
@@ -0,0 +1,83 @@
+package com.ruoyi.web.controller.monitor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysUserOnline;
+import com.ruoyi.system.service.ISysUserOnlineService;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛鐩戞帶
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/online")
+public class SysUserOnlineController extends BaseController
+{
+ @Autowired
+ private ISysUserOnlineService userOnlineService;
+
+ @Autowired
+ private RedisCache redisCache;
+
+ @PreAuthorize("@ss.hasPermi('monitor:online:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(String ipaddr, String userName)
+ {
+ Collection<String> keys = redisCache.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
+ List<SysUserOnline> userOnlineList = new ArrayList<SysUserOnline>();
+ for (String key : keys)
+ {
+ LoginUser user = redisCache.getCacheObject(key);
+ if (StringUtils.isNotEmpty(ipaddr) && StringUtils.isNotEmpty(userName))
+ {
+ userOnlineList.add(userOnlineService.selectOnlineByInfo(ipaddr, userName, user));
+ }
+ else if (StringUtils.isNotEmpty(ipaddr))
+ {
+ userOnlineList.add(userOnlineService.selectOnlineByIpaddr(ipaddr, user));
+ }
+ else if (StringUtils.isNotEmpty(userName) && StringUtils.isNotNull(user.getUser()))
+ {
+ userOnlineList.add(userOnlineService.selectOnlineByUserName(userName, user));
+ }
+ else
+ {
+ userOnlineList.add(userOnlineService.loginUserToUserOnline(user));
+ }
+ }
+ Collections.reverse(userOnlineList);
+ userOnlineList.removeAll(Collections.singleton(null));
+ return getDataTable(userOnlineList);
+ }
+
+ /**
+ * 寮洪��鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
+ @Log(title = "鍦ㄧ嚎鐢ㄦ埛", businessType = BusinessType.FORCE)
+ @DeleteMapping("/{tokenId}")
+ public AjaxResult forceLogout(@PathVariable String tokenId)
+ {
+ redisCache.deleteObject(CacheConstants.LOGIN_TOKEN_KEY + tokenId);
+ return success();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/CustomController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/CustomController.java
new file mode 100644
index 0000000..040af38
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/CustomController.java
@@ -0,0 +1,62 @@
+package com.ruoyi.web.controller.system;
+
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.core.domain.entity.Custom;
+import com.ruoyi.system.service.CustomService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.springframework.web.bind.annotation.*;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+
+/**
+ * 瀹㈡埛绠$悊
+ *
+ * @author zhuo
+ * @since 2025-02-13
+ */
+@Api(tags = "瀹㈡埛绠$悊")
+@RestController
+@RequestMapping("/system/custom")
+public class CustomController {
+
+ @Resource
+ private CustomService customService;
+
+ @ApiOperation(value = "鑾峰彇瀹㈡埛鍒楄〃")
+ @GetMapping("/selectCustomPageList")
+ public Result<IPage<Custom>> selectCustomPageList(Page page, Custom custom) throws Exception {
+ return Result.success(customService.selectCustomPageList(page, custom));
+ }
+ @ApiOperation(value = "鍒犻櫎瀹㈡埛淇℃伅")
+ @PostMapping("/delCustomById")
+ public Result delCustomById(Long id) {
+ return Result.success(customService.delCustomById(id));
+ }
+
+ @ApiOperation(value = "鏂板瀹㈡埛淇℃伅")
+ @PostMapping("/addCustom")
+ public Result addCustom(@RequestBody Custom custom) {
+ return Result.success(customService.addCustom(custom));
+ }
+
+
+ @ApiOperation(value = "淇敼瀹㈡埛淇℃伅")
+ @PostMapping("/upCustom")
+ public Result upCustom(@RequestBody Custom custom) {
+ return Result.success(customService.upCustom(custom));
+ }
+
+ @ApiOperation(value = "鑾峰彇瀹㈡埛鏋氫妇")
+ @GetMapping ("/selectCustomEnum")
+ public Result<List<Custom>> selectCustomEnum(){
+ return Result.success(customService.selectCustomEnum());
+ }
+
+}
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
new file mode 100644
index 0000000..69499bb
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysConfigController.java
@@ -0,0 +1,133 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysConfig;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * 鍙傛暟閰嶇疆 淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/config")
+public class SysConfigController extends BaseController
+{
+ @Autowired
+ private ISysConfigService configService;
+
+ /**
+ * 鑾峰彇鍙傛暟閰嶇疆鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysConfig config)
+ {
+ startPage();
+ List<SysConfig> list = configService.selectConfigList(config);
+ return getDataTable(list);
+ }
+
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:config:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysConfig config)
+ {
+ List<SysConfig> list = configService.selectConfigList(config);
+ ExcelUtil<SysConfig> util = new ExcelUtil<SysConfig>(SysConfig.class);
+ util.exportExcel(response, list, "鍙傛暟鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁鍙傛暟缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:query')")
+ @GetMapping(value = "/{configId}")
+ public AjaxResult getInfo(@PathVariable Long configId)
+ {
+ return success(configService.selectConfigById(configId));
+ }
+
+ /**
+ * 鏍规嵁鍙傛暟閿悕鏌ヨ鍙傛暟鍊�
+ */
+ @GetMapping(value = "/configKey/{configKey}")
+ public AjaxResult getConfigKey(@PathVariable String configKey)
+ {
+ return success(configService.selectConfigByKey(configKey));
+ }
+
+ /**
+ * 鏂板鍙傛暟閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:add')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysConfig config)
+ {
+ if (!configService.checkConfigKeyUnique(config))
+ {
+ return error("鏂板鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+ }
+ config.setCreateBy(getUsername());
+ return toAjax(configService.insertConfig(config));
+ }
+
+ /**
+ * 淇敼鍙傛暟閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:edit')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysConfig config)
+ {
+ if (!configService.checkConfigKeyUnique(config))
+ {
+ return error("淇敼鍙傛暟'" + config.getConfigName() + "'澶辫触锛屽弬鏁伴敭鍚嶅凡瀛樺湪");
+ }
+ config.setUpdateBy(getUsername());
+ return toAjax(configService.updateConfig(config));
+ }
+
+ /**
+ * 鍒犻櫎鍙傛暟閰嶇疆
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:remove')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{configIds}")
+ public AjaxResult remove(@PathVariable Long[] configIds)
+ {
+ configService.deleteConfigByIds(configIds);
+ return success();
+ }
+
+ /**
+ * 鍒锋柊鍙傛暟缂撳瓨
+ */
+ @PreAuthorize("@ss.hasPermi('system:config:remove')")
+ @Log(title = "鍙傛暟绠$悊", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/refreshCache")
+ public AjaxResult refreshCache()
+ {
+ configService.resetConfigCache();
+ return success();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
new file mode 100644
index 0000000..1315ed3
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDeptController.java
@@ -0,0 +1,132 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysDeptService;
+
+/**
+ * 閮ㄩ棬淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/dept")
+public class SysDeptController extends BaseController
+{
+ @Autowired
+ private ISysDeptService deptService;
+
+ /**
+ * 鑾峰彇閮ㄩ棬鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:list')")
+ @GetMapping("/list")
+ public AjaxResult list(SysDept dept)
+ {
+ List<SysDept> depts = deptService.selectDeptList(dept);
+ return success(depts);
+ }
+
+ /**
+ * 鏌ヨ閮ㄩ棬鍒楄〃锛堟帓闄よ妭鐐癸級
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:list')")
+ @GetMapping("/list/exclude/{deptId}")
+ public AjaxResult excludeChild(@PathVariable(value = "deptId", required = false) Long deptId)
+ {
+ List<SysDept> depts = deptService.selectDeptList(new SysDept());
+ depts.removeIf(d -> d.getDeptId().intValue() == deptId || ArrayUtils.contains(StringUtils.split(d.getAncestors(), ","), deptId + ""));
+ return success(depts);
+ }
+
+ /**
+ * 鏍规嵁閮ㄩ棬缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:query')")
+ @GetMapping(value = "/{deptId}")
+ public AjaxResult getInfo(@PathVariable Long deptId)
+ {
+ deptService.checkDeptDataScope(deptId);
+ return success(deptService.selectDeptById(deptId));
+ }
+
+ /**
+ * 鏂板閮ㄩ棬
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:add')")
+ @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysDept dept)
+ {
+ if (!deptService.checkDeptNameUnique(dept))
+ {
+ return error("鏂板閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+ }
+ dept.setCreateBy(getUsername());
+ return toAjax(deptService.insertDept(dept));
+ }
+
+ /**
+ * 淇敼閮ㄩ棬
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:edit')")
+ @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysDept dept)
+ {
+ Long deptId = dept.getDeptId();
+ deptService.checkDeptDataScope(deptId);
+ if (!deptService.checkDeptNameUnique(dept))
+ {
+ return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛岄儴闂ㄥ悕绉板凡瀛樺湪");
+ }
+ else if (dept.getParentId().equals(deptId))
+ {
+ return error("淇敼閮ㄩ棬'" + dept.getDeptName() + "'澶辫触锛屼笂绾ч儴闂ㄤ笉鑳芥槸鑷繁");
+ }
+ else if (StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus()) && deptService.selectNormalChildrenDeptById(deptId) > 0)
+ {
+ return error("璇ラ儴闂ㄥ寘鍚湭鍋滅敤鐨勫瓙閮ㄩ棬锛�");
+ }
+ dept.setUpdateBy(getUsername());
+ return toAjax(deptService.updateDept(dept));
+ }
+
+ /**
+ * 鍒犻櫎閮ㄩ棬
+ */
+ @PreAuthorize("@ss.hasPermi('system:dept:remove')")
+ @Log(title = "閮ㄩ棬绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{deptId}")
+ public AjaxResult remove(@PathVariable Long deptId)
+ {
+ if (deptService.hasChildByDeptId(deptId))
+ {
+ return warn("瀛樺湪涓嬬骇閮ㄩ棬,涓嶅厑璁稿垹闄�");
+ }
+ if (deptService.checkDeptExistUser(deptId))
+ {
+ return warn("閮ㄩ棬瀛樺湪鐢ㄦ埛,涓嶅厑璁稿垹闄�");
+ }
+ deptService.checkDeptDataScope(deptId);
+ return toAjax(deptService.deleteDeptById(deptId));
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
new file mode 100644
index 0000000..4d4d2e5
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictDataController.java
@@ -0,0 +1,121 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.service.ISysDictDataService;
+import com.ruoyi.system.service.ISysDictTypeService;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/dict/data")
+public class SysDictDataController extends BaseController
+{
+ @Autowired
+ private ISysDictDataService dictDataService;
+
+ @Autowired
+ private ISysDictTypeService dictTypeService;
+
+ @PreAuthorize("@ss.hasPermi('system:dict:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysDictData dictData)
+ {
+ startPage();
+ List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+ return getDataTable(list);
+ }
+
+ @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:dict:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysDictData dictData)
+ {
+ List<SysDictData> list = dictDataService.selectDictDataList(dictData);
+ ExcelUtil<SysDictData> util = new ExcelUtil<SysDictData>(SysDictData.class);
+ util.exportExcel(response, list, "瀛楀吀鏁版嵁");
+ }
+
+ /**
+ * 鏌ヨ瀛楀吀鏁版嵁璇︾粏
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:query')")
+ @GetMapping(value = "/{dictCode}")
+ public AjaxResult getInfo(@PathVariable Long dictCode)
+ {
+ return success(dictDataService.selectDictDataById(dictCode));
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁淇℃伅
+ */
+ @GetMapping(value = "/type/{dictType}")
+ public AjaxResult dictType(@PathVariable String dictType)
+ {
+ List<SysDictData> data = dictTypeService.selectDictDataByType(dictType);
+ if (StringUtils.isNull(data))
+ {
+ data = new ArrayList<SysDictData>();
+ }
+ return success(data);
+ }
+
+ /**
+ * 鏂板瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:add')")
+ @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysDictData dict)
+ {
+ dict.setCreateBy(getUsername());
+ return toAjax(dictDataService.insertDictData(dict));
+ }
+
+ /**
+ * 淇敼淇濆瓨瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:edit')")
+ @Log(title = "瀛楀吀鏁版嵁", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysDictData dict)
+ {
+ dict.setUpdateBy(getUsername());
+ return toAjax(dictDataService.updateDictData(dict));
+ }
+
+ /**
+ * 鍒犻櫎瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{dictCodes}")
+ public AjaxResult remove(@PathVariable Long[] dictCodes)
+ {
+ dictDataService.deleteDictDataByIds(dictCodes);
+ return success();
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
new file mode 100644
index 0000000..7e3a519
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysDictTypeController.java
@@ -0,0 +1,131 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.service.ISysDictTypeService;
+
+/**
+ * 鏁版嵁瀛楀吀淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/dict/type")
+public class SysDictTypeController extends BaseController
+{
+ @Autowired
+ private ISysDictTypeService dictTypeService;
+
+ @PreAuthorize("@ss.hasPermi('system:dict:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysDictType dictType)
+ {
+ startPage();
+ List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+ return getDataTable(list);
+ }
+
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:dict:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysDictType dictType)
+ {
+ List<SysDictType> list = dictTypeService.selectDictTypeList(dictType);
+ ExcelUtil<SysDictType> util = new ExcelUtil<SysDictType>(SysDictType.class);
+ util.exportExcel(response, list, "瀛楀吀绫诲瀷");
+ }
+
+ /**
+ * 鏌ヨ瀛楀吀绫诲瀷璇︾粏
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:query')")
+ @GetMapping(value = "/{dictId}")
+ public AjaxResult getInfo(@PathVariable Long dictId)
+ {
+ return success(dictTypeService.selectDictTypeById(dictId));
+ }
+
+ /**
+ * 鏂板瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:add')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysDictType dict)
+ {
+ if (!dictTypeService.checkDictTypeUnique(dict))
+ {
+ return error("鏂板瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+ }
+ dict.setCreateBy(getUsername());
+ return toAjax(dictTypeService.insertDictType(dict));
+ }
+
+ /**
+ * 淇敼瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:edit')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysDictType dict)
+ {
+ if (!dictTypeService.checkDictTypeUnique(dict))
+ {
+ return error("淇敼瀛楀吀'" + dict.getDictName() + "'澶辫触锛屽瓧鍏哥被鍨嬪凡瀛樺湪");
+ }
+ dict.setUpdateBy(getUsername());
+ return toAjax(dictTypeService.updateDictType(dict));
+ }
+
+ /**
+ * 鍒犻櫎瀛楀吀绫诲瀷
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{dictIds}")
+ public AjaxResult remove(@PathVariable Long[] dictIds)
+ {
+ dictTypeService.deleteDictTypeByIds(dictIds);
+ return success();
+ }
+
+ /**
+ * 鍒锋柊瀛楀吀缂撳瓨
+ */
+ @PreAuthorize("@ss.hasPermi('system:dict:remove')")
+ @Log(title = "瀛楀吀绫诲瀷", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/refreshCache")
+ public AjaxResult refreshCache()
+ {
+ dictTypeService.resetDictCache();
+ return success();
+ }
+
+ /**
+ * 鑾峰彇瀛楀吀閫夋嫨妗嗗垪琛�
+ */
+ @GetMapping("/optionselect")
+ public AjaxResult optionselect()
+ {
+ List<SysDictType> dictTypes = dictTypeService.selectDictTypeAll();
+ return success(dictTypes);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
new file mode 100644
index 0000000..13007eb
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysIndexController.java
@@ -0,0 +1,29 @@
+package com.ruoyi.web.controller.system;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 棣栭〉
+ *
+ * @author ruoyi
+ */
+@RestController
+public class SysIndexController
+{
+ /** 绯荤粺鍩虹閰嶇疆 */
+ @Autowired
+ private RuoYiConfig ruoyiConfig;
+
+ /**
+ * 璁块棶棣栭〉锛屾彁绀鸿
+ */
+ @RequestMapping("/")
+ public String index()
+ {
+ return StringUtils.format("娆㈣繋浣跨敤{}鍚庡彴绠$悊妗嗘灦锛屽綋鍓嶇増鏈細v{}锛岃閫氳繃鍓嶇鍦板潃璁块棶銆�", ruoyiConfig.getName(), ruoyiConfig.getVersion());
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
new file mode 100644
index 0000000..ae31b90
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java
@@ -0,0 +1,97 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginBody;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.web.service.SysLoginService;
+import com.ruoyi.framework.web.service.SysPermissionService;
+import com.ruoyi.framework.web.service.TokenService;
+import com.ruoyi.system.service.ISysMenuService;
+
+/**
+ * 鐧诲綍楠岃瘉
+ *
+ * @author ruoyi
+ */
+@RestController
+public class SysLoginController
+{
+ @Autowired
+ private SysLoginService loginService;
+
+ @Autowired
+ private ISysMenuService menuService;
+
+ @Autowired
+ private SysPermissionService permissionService;
+
+ @Autowired
+ private TokenService tokenService;
+
+ /**
+ * 鐧诲綍鏂规硶
+ *
+ * @param loginBody 鐧诲綍淇℃伅
+ * @return 缁撴灉
+ */
+ @PostMapping("/login")
+ public AjaxResult login(@RequestBody LoginBody loginBody)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ // 鐢熸垚浠ょ墝
+ String token = loginService.login(loginBody.getUsername(), loginBody.getPassword(), loginBody.getCode(),
+ loginBody.getUuid());
+ ajax.put(Constants.TOKEN, token);
+ return ajax;
+ }
+
+ /**
+ * 鑾峰彇鐢ㄦ埛淇℃伅
+ *
+ * @return 鐢ㄦ埛淇℃伅
+ */
+ @GetMapping("getInfo")
+ public AjaxResult getInfo()
+ {
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ SysUser user = loginUser.getUser();
+ // 瑙掕壊闆嗗悎
+ Set<String> roles = permissionService.getRolePermission(user);
+ // 鏉冮檺闆嗗悎
+ Set<String> permissions = permissionService.getMenuPermission(user);
+ if (!loginUser.getPermissions().equals(permissions))
+ {
+ loginUser.setPermissions(permissions);
+ tokenService.refreshToken(loginUser);
+ }
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("user", user);
+ ajax.put("roles", roles);
+ ajax.put("permissions", permissions);
+ return ajax;
+ }
+
+ /**
+ * 鑾峰彇璺敱淇℃伅
+ *
+ * @return 璺敱淇℃伅
+ */
+ @GetMapping("getRouters")
+ public AjaxResult getRouters()
+ {
+ Long userId = SecurityUtils.getUserId();
+ List<SysMenu> menus = menuService.selectMenuTreeByUserId(userId);
+ return AjaxResult.success(menuService.buildMenus(menus));
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
new file mode 100644
index 0000000..fa6d4c6
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysMenuController.java
@@ -0,0 +1,142 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysMenuService;
+
+/**
+ * 鑿滃崟淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/menu")
+public class SysMenuController extends BaseController
+{
+ @Autowired
+ private ISysMenuService menuService;
+
+ /**
+ * 鑾峰彇鑿滃崟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:list')")
+ @GetMapping("/list")
+ public AjaxResult list(SysMenu menu)
+ {
+ List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
+ return success(menus);
+ }
+
+ /**
+ * 鏍规嵁鑿滃崟缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:query')")
+ @GetMapping(value = "/{menuId}")
+ public AjaxResult getInfo(@PathVariable Long menuId)
+ {
+ return success(menuService.selectMenuById(menuId));
+ }
+
+ /**
+ * 鑾峰彇鑿滃崟涓嬫媺鏍戝垪琛�
+ */
+ @GetMapping("/treeselect")
+ public AjaxResult treeselect(SysMenu menu)
+ {
+ List<SysMenu> menus = menuService.selectMenuList(menu, getUserId());
+ return success(menuService.buildMenuTreeSelect(menus));
+ }
+
+ /**
+ * 鍔犺浇瀵瑰簲瑙掕壊鑿滃崟鍒楄〃鏍�
+ */
+ @GetMapping(value = "/roleMenuTreeselect/{roleId}")
+ public AjaxResult roleMenuTreeselect(@PathVariable("roleId") Long roleId)
+ {
+ List<SysMenu> menus = menuService.selectMenuList(getUserId());
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("checkedKeys", menuService.selectMenuListByRoleId(roleId));
+ ajax.put("menus", menuService.buildMenuTreeSelect(menus));
+ return ajax;
+ }
+
+ /**
+ * 鏂板鑿滃崟
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:add')")
+ @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysMenu menu)
+ {
+ if (!menuService.checkMenuNameUnique(menu))
+ {
+ return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+ }
+ else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
+ {
+ return error("鏂板鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+ }
+ menu.setCreateBy(getUsername());
+ return toAjax(menuService.insertMenu(menu));
+ }
+
+ /**
+ * 淇敼鑿滃崟
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:edit')")
+ @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysMenu menu)
+ {
+ if (!menuService.checkMenuNameUnique(menu))
+ {
+ return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛岃彍鍗曞悕绉板凡瀛樺湪");
+ }
+ else if (UserConstants.YES_FRAME.equals(menu.getIsFrame()) && !StringUtils.ishttp(menu.getPath()))
+ {
+ return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屽湴鍧�蹇呴』浠ttp(s)://寮�澶�");
+ }
+ else if (menu.getMenuId().equals(menu.getParentId()))
+ {
+ return error("淇敼鑿滃崟'" + menu.getMenuName() + "'澶辫触锛屼笂绾ц彍鍗曚笉鑳介�夋嫨鑷繁");
+ }
+ menu.setUpdateBy(getUsername());
+ return toAjax(menuService.updateMenu(menu));
+ }
+
+ /**
+ * 鍒犻櫎鑿滃崟
+ */
+ @PreAuthorize("@ss.hasPermi('system:menu:remove')")
+ @Log(title = "鑿滃崟绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{menuId}")
+ public AjaxResult remove(@PathVariable("menuId") Long menuId)
+ {
+ if (menuService.hasChildByMenuId(menuId))
+ {
+ return warn("瀛樺湪瀛愯彍鍗�,涓嶅厑璁稿垹闄�");
+ }
+ if (menuService.checkMenuExistRole(menuId))
+ {
+ return warn("鑿滃崟宸插垎閰�,涓嶅厑璁稿垹闄�");
+ }
+ return toAjax(menuService.deleteMenuById(menuId));
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
new file mode 100644
index 0000000..18d4384
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysNoticeController.java
@@ -0,0 +1,91 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.system.domain.SysNotice;
+import com.ruoyi.system.service.ISysNoticeService;
+
+/**
+ * 鍏憡 淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/notice")
+public class SysNoticeController extends BaseController
+{
+ @Autowired
+ private ISysNoticeService noticeService;
+
+ /**
+ * 鑾峰彇閫氱煡鍏憡鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:notice:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysNotice notice)
+ {
+ startPage();
+ List<SysNotice> list = noticeService.selectNoticeList(notice);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鏍规嵁閫氱煡鍏憡缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:notice:query')")
+ @GetMapping(value = "/{noticeId}")
+ public AjaxResult getInfo(@PathVariable Long noticeId)
+ {
+ return success(noticeService.selectNoticeById(noticeId));
+ }
+
+ /**
+ * 鏂板閫氱煡鍏憡
+ */
+ @PreAuthorize("@ss.hasPermi('system:notice:add')")
+ @Log(title = "閫氱煡鍏憡", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysNotice notice)
+ {
+ notice.setCreateBy(getUsername());
+ return toAjax(noticeService.insertNotice(notice));
+ }
+
+ /**
+ * 淇敼閫氱煡鍏憡
+ */
+ @PreAuthorize("@ss.hasPermi('system:notice:edit')")
+ @Log(title = "閫氱煡鍏憡", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysNotice notice)
+ {
+ notice.setUpdateBy(getUsername());
+ return toAjax(noticeService.updateNotice(notice));
+ }
+
+ /**
+ * 鍒犻櫎閫氱煡鍏憡
+ */
+ @PreAuthorize("@ss.hasPermi('system:notice:remove')")
+ @Log(title = "閫氱煡鍏憡", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{noticeIds}")
+ public AjaxResult remove(@PathVariable Long[] noticeIds)
+ {
+ return toAjax(noticeService.deleteNoticeByIds(noticeIds));
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
new file mode 100644
index 0000000..56bb00f
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysPostController.java
@@ -0,0 +1,129 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.service.ISysPostService;
+
+/**
+ * 宀椾綅淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/post")
+public class SysPostController extends BaseController
+{
+ @Autowired
+ private ISysPostService postService;
+
+ /**
+ * 鑾峰彇宀椾綅鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysPost post)
+ {
+ startPage();
+ List<SysPost> list = postService.selectPostList(post);
+ return getDataTable(list);
+ }
+
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:post:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysPost post)
+ {
+ List<SysPost> list = postService.selectPostList(post);
+ ExcelUtil<SysPost> util = new ExcelUtil<SysPost>(SysPost.class);
+ util.exportExcel(response, list, "宀椾綅鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁宀椾綅缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:query')")
+ @GetMapping(value = "/{postId}")
+ public AjaxResult getInfo(@PathVariable Long postId)
+ {
+ return success(postService.selectPostById(postId));
+ }
+
+ /**
+ * 鏂板宀椾綅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:add')")
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysPost post)
+ {
+ if (!postService.checkPostNameUnique(post))
+ {
+ return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+ }
+ else if (!postService.checkPostCodeUnique(post))
+ {
+ return error("鏂板宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+ }
+ post.setCreateBy(getUsername());
+ return toAjax(postService.insertPost(post));
+ }
+
+ /**
+ * 淇敼宀椾綅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:edit')")
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysPost post)
+ {
+ if (!postService.checkPostNameUnique(post))
+ {
+ return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶅悕绉板凡瀛樺湪");
+ }
+ else if (!postService.checkPostCodeUnique(post))
+ {
+ return error("淇敼宀椾綅'" + post.getPostName() + "'澶辫触锛屽矖浣嶇紪鐮佸凡瀛樺湪");
+ }
+ post.setUpdateBy(getUsername());
+ return toAjax(postService.updatePost(post));
+ }
+
+ /**
+ * 鍒犻櫎宀椾綅
+ */
+ @PreAuthorize("@ss.hasPermi('system:post:remove')")
+ @Log(title = "宀椾綅绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{postIds}")
+ public AjaxResult remove(@PathVariable Long[] postIds)
+ {
+ return toAjax(postService.deletePostByIds(postIds));
+ }
+
+ /**
+ * 鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+ */
+ @GetMapping("/optionselect")
+ public AjaxResult optionselect()
+ {
+ List<SysPost> posts = postService.selectPostAll();
+ return success(posts);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
new file mode 100644
index 0000000..24c4b2b
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
@@ -0,0 +1,140 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.Map;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileUploadUtils;
+import com.ruoyi.common.utils.file.MimeTypeUtils;
+import com.ruoyi.framework.web.service.TokenService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 涓汉淇℃伅 涓氬姟澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/user/profile")
+public class SysProfileController extends BaseController
+{
+ @Autowired
+ private ISysUserService userService;
+
+ @Autowired
+ private TokenService tokenService;
+
+ /**
+ * 涓汉淇℃伅
+ */
+ @GetMapping
+ public AjaxResult profile()
+ {
+ LoginUser loginUser = getLoginUser();
+ SysUser user = loginUser.getUser();
+ AjaxResult ajax = AjaxResult.success(user);
+ ajax.put("roleGroup", userService.selectUserRoleGroup(loginUser.getUsername()));
+ ajax.put("postGroup", userService.selectUserPostGroup(loginUser.getUsername()));
+ return ajax;
+ }
+
+ /**
+ * 淇敼鐢ㄦ埛
+ */
+ @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult updateProfile(@RequestBody SysUser user)
+ {
+ LoginUser loginUser = getLoginUser();
+ SysUser currentUser = loginUser.getUser();
+ currentUser.setNickName(user.getNickName());
+ currentUser.setEmail(user.getEmail());
+ currentUser.setPhonenumber(user.getPhonenumber());
+ currentUser.setSex(user.getSex());
+ if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(currentUser))
+ {
+ return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+ }
+ if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(currentUser))
+ {
+ return error("淇敼鐢ㄦ埛'" + loginUser.getUsername() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+ }
+ if (userService.updateUserProfile(currentUser) > 0)
+ {
+ // 鏇存柊缂撳瓨鐢ㄦ埛淇℃伅
+ tokenService.setLoginUser(loginUser);
+ return success();
+ }
+ return error("淇敼涓汉淇℃伅寮傚父锛岃鑱旂郴绠$悊鍛�");
+ }
+
+ /**
+ * 閲嶇疆瀵嗙爜
+ */
+ @Log(title = "涓汉淇℃伅", businessType = BusinessType.UPDATE)
+ @PutMapping("/updatePwd")
+ public AjaxResult updatePwd(@RequestBody Map<String, String> params)
+ {
+ String oldPassword = params.get("oldPassword");
+ String newPassword = params.get("newPassword");
+ LoginUser loginUser = getLoginUser();
+ String userName = loginUser.getUsername();
+ String password = loginUser.getPassword();
+ if (!SecurityUtils.matchesPassword(oldPassword, password))
+ {
+ return error("淇敼瀵嗙爜澶辫触锛屾棫瀵嗙爜閿欒");
+ }
+ if (SecurityUtils.matchesPassword(newPassword, password))
+ {
+ return error("鏂板瘑鐮佷笉鑳戒笌鏃у瘑鐮佺浉鍚�");
+ }
+ newPassword = SecurityUtils.encryptPassword(newPassword);
+ if (userService.resetUserPwd(userName, newPassword) > 0)
+ {
+ // 鏇存柊缂撳瓨鐢ㄦ埛瀵嗙爜
+ loginUser.getUser().setPassword(newPassword);
+ tokenService.setLoginUser(loginUser);
+ return success();
+ }
+ return error("淇敼瀵嗙爜寮傚父锛岃鑱旂郴绠$悊鍛�");
+ }
+
+ /**
+ * 澶村儚涓婁紶
+ */
+ @Log(title = "鐢ㄦ埛澶村儚", businessType = BusinessType.UPDATE)
+ @PostMapping("/avatar")
+ public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception
+ {
+ if (!file.isEmpty())
+ {
+ LoginUser loginUser = getLoginUser();
+ String avatar = FileUploadUtils.upload(RuoYiConfig.getAvatarPath(), file, MimeTypeUtils.IMAGE_EXTENSION);
+ if (userService.updateUserAvatar(loginUser.getUsername(), avatar))
+ {
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("imgUrl", avatar);
+ // 鏇存柊缂撳瓨鐢ㄦ埛澶村儚
+ loginUser.getUser().setAvatar(avatar);
+ tokenService.setLoginUser(loginUser);
+ return ajax;
+ }
+ }
+ return error("涓婁紶鍥剧墖寮傚父锛岃鑱旂郴绠$悊鍛�");
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
new file mode 100644
index 0000000..6599809
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java
@@ -0,0 +1,38 @@
+package com.ruoyi.web.controller.system;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.RegisterBody;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.service.SysRegisterService;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * 娉ㄥ唽楠岃瘉
+ *
+ * @author ruoyi
+ */
+@RestController
+public class SysRegisterController extends BaseController
+{
+ @Autowired
+ private SysRegisterService registerService;
+
+ @Autowired
+ private ISysConfigService configService;
+
+ @PostMapping("/register")
+ public AjaxResult register(@RequestBody RegisterBody user)
+ {
+ if (!("true".equals(configService.selectConfigByKey("sys.account.registerUser"))))
+ {
+ return error("褰撳墠绯荤粺娌℃湁寮�鍚敞鍐屽姛鑳斤紒");
+ }
+ String msg = registerService.register(user);
+ return StringUtils.isEmpty(msg) ? success() : error(msg);
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
new file mode 100644
index 0000000..abe942b
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRoleController.java
@@ -0,0 +1,262 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.framework.web.service.SysPermissionService;
+import com.ruoyi.framework.web.service.TokenService;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysRoleService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 瑙掕壊淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/role")
+public class SysRoleController extends BaseController
+{
+ @Autowired
+ private ISysRoleService roleService;
+
+ @Autowired
+ private TokenService tokenService;
+
+ @Autowired
+ private SysPermissionService permissionService;
+
+ @Autowired
+ private ISysUserService userService;
+
+ @Autowired
+ private ISysDeptService deptService;
+
+ @PreAuthorize("@ss.hasPermi('system:role:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysRole role)
+ {
+ startPage();
+ List<SysRole> list = roleService.selectRoleList(role);
+ return getDataTable(list);
+ }
+
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:role:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysRole role)
+ {
+ List<SysRole> list = roleService.selectRoleList(role);
+ ExcelUtil<SysRole> util = new ExcelUtil<SysRole>(SysRole.class);
+ util.exportExcel(response, list, "瑙掕壊鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁瑙掕壊缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:query')")
+ @GetMapping(value = "/{roleId}")
+ public AjaxResult getInfo(@PathVariable Long roleId)
+ {
+ roleService.checkRoleDataScope(roleId);
+ return success(roleService.selectRoleById(roleId));
+ }
+
+ /**
+ * 鏂板瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:add')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysRole role)
+ {
+ if (!roleService.checkRoleNameUnique(role))
+ {
+ return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+ }
+ else if (!roleService.checkRoleKeyUnique(role))
+ {
+ return error("鏂板瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+ }
+ role.setCreateBy(getUsername());
+ return toAjax(roleService.insertRole(role));
+
+ }
+
+ /**
+ * 淇敼淇濆瓨瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysRole role)
+ {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ if (!roleService.checkRoleNameUnique(role))
+ {
+ return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹插悕绉板凡瀛樺湪");
+ }
+ else if (!roleService.checkRoleKeyUnique(role))
+ {
+ return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑹叉潈闄愬凡瀛樺湪");
+ }
+ role.setUpdateBy(getUsername());
+
+ if (roleService.updateRole(role) > 0)
+ {
+ // 鏇存柊缂撳瓨鐢ㄦ埛鏉冮檺
+ LoginUser loginUser = getLoginUser();
+ if (StringUtils.isNotNull(loginUser.getUser()) && !loginUser.getUser().isAdmin())
+ {
+ loginUser.setUser(userService.selectUserByUserName(loginUser.getUser().getUserName()));
+ loginUser.setPermissions(permissionService.getMenuPermission(loginUser.getUser()));
+ tokenService.setLoginUser(loginUser);
+ }
+ return success();
+ }
+ return error("淇敼瑙掕壊'" + role.getRoleName() + "'澶辫触锛岃鑱旂郴绠$悊鍛�");
+ }
+
+ /**
+ * 淇敼淇濆瓨鏁版嵁鏉冮檺
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/dataScope")
+ public AjaxResult dataScope(@RequestBody SysRole role)
+ {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ return toAjax(roleService.authDataScope(role));
+ }
+
+ /**
+ * 鐘舵�佷慨鏀�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysRole role)
+ {
+ roleService.checkRoleAllowed(role);
+ roleService.checkRoleDataScope(role.getRoleId());
+ role.setUpdateBy(getUsername());
+ return toAjax(roleService.updateRoleStatus(role));
+ }
+
+ /**
+ * 鍒犻櫎瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:remove')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{roleIds}")
+ public AjaxResult remove(@PathVariable Long[] roleIds)
+ {
+ return toAjax(roleService.deleteRoleByIds(roleIds));
+ }
+
+ /**
+ * 鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:query')")
+ @GetMapping("/optionselect")
+ public AjaxResult optionselect()
+ {
+ return success(roleService.selectRoleAll());
+ }
+
+ /**
+ * 鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:list')")
+ @GetMapping("/authUser/allocatedList")
+ public TableDataInfo allocatedList(SysUser user)
+ {
+ startPage();
+ List<SysUser> list = userService.selectAllocatedList(user);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:list')")
+ @GetMapping("/authUser/unallocatedList")
+ public TableDataInfo unallocatedList(SysUser user)
+ {
+ startPage();
+ List<SysUser> list = userService.selectUnallocatedList(user);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鍙栨秷鎺堟潈鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/cancel")
+ public AjaxResult cancelAuthUser(@RequestBody SysUserRole userRole)
+ {
+ return toAjax(roleService.deleteAuthUser(userRole));
+ }
+
+ /**
+ * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/cancelAll")
+ public AjaxResult cancelAuthUserAll(Long roleId, Long[] userIds)
+ {
+ return toAjax(roleService.deleteAuthUsers(roleId, userIds));
+ }
+
+ /**
+ * 鎵归噺閫夋嫨鐢ㄦ埛鎺堟潈
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:edit')")
+ @Log(title = "瑙掕壊绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authUser/selectAll")
+ public AjaxResult selectAuthUserAll(Long roleId, Long[] userIds)
+ {
+ roleService.checkRoleDataScope(roleId);
+ return toAjax(roleService.insertAuthUsers(roleId, userIds));
+ }
+
+ /**
+ * 鑾峰彇瀵瑰簲瑙掕壊閮ㄩ棬鏍戝垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:role:query')")
+ @GetMapping(value = "/deptTree/{roleId}")
+ public AjaxResult deptTree(@PathVariable("roleId") Long roleId)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ ajax.put("checkedKeys", deptService.selectDeptListByRoleId(roleId));
+ ajax.put("depts", deptService.selectDeptTreeList(new SysDept()));
+ return ajax;
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
new file mode 100644
index 0000000..a6b0865
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysUserController.java
@@ -0,0 +1,256 @@
+package com.ruoyi.web.controller.system;
+
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysPostService;
+import com.ruoyi.system.service.ISysRoleService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 鐢ㄦ埛淇℃伅
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/system/user")
+public class SysUserController extends BaseController
+{
+ @Autowired
+ private ISysUserService userService;
+
+ @Autowired
+ private ISysRoleService roleService;
+
+ @Autowired
+ private ISysDeptService deptService;
+
+ @Autowired
+ private ISysPostService postService;
+
+ /**
+ * 鑾峰彇鐢ㄦ埛鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysUser user)
+ {
+ startPage();
+ List<SysUser> list = userService.selectUserList(user);
+ return getDataTable(list);
+ }
+
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.EXPORT)
+ @PreAuthorize("@ss.hasPermi('system:user:export')")
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysUser user)
+ {
+ List<SysUser> list = userService.selectUserList(user);
+ ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+ util.exportExcel(response, list, "鐢ㄦ埛鏁版嵁");
+ }
+
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.IMPORT)
+ @PreAuthorize("@ss.hasPermi('system:user:import')")
+ @PostMapping("/importData")
+ public AjaxResult importData(MultipartFile file, boolean updateSupport) throws Exception
+ {
+ ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+ List<SysUser> userList = util.importExcel(file.getInputStream());
+ String operName = getUsername();
+ String message = userService.importUser(userList, updateSupport, operName);
+ return success(message);
+ }
+
+ @PostMapping("/importTemplate")
+ public void importTemplate(HttpServletResponse response)
+ {
+ ExcelUtil<SysUser> util = new ExcelUtil<SysUser>(SysUser.class);
+ util.importTemplateExcel(response, "鐢ㄦ埛鏁版嵁");
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:query')")
+ @GetMapping(value = { "/", "/{userId}" })
+ public AjaxResult getInfo(@PathVariable(value = "userId", required = false) Long userId)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ if (StringUtils.isNotNull(userId))
+ {
+ userService.checkUserDataScope(userId);
+ SysUser sysUser = userService.selectUserById(userId);
+ ajax.put(AjaxResult.DATA_TAG, sysUser);
+ ajax.put("postIds", postService.selectPostListByUserId(userId));
+ ajax.put("roleIds", sysUser.getRoles().stream().map(SysRole::getRoleId).collect(Collectors.toList()));
+ }
+ List<SysRole> roles = roleService.selectRoleAll();
+ ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+ ajax.put("posts", postService.selectPostAll());
+ return ajax;
+ }
+
+ /**
+ * 鏂板鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:add')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@Validated @RequestBody SysUser user)
+ {
+ deptService.checkDeptDataScope(user.getDeptId());
+ roleService.checkRoleDataScope(user.getRoleIds());
+ if (!userService.checkUserNameUnique(user))
+ {
+ return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+ {
+ return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+ {
+ return error("鏂板鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+ }
+ user.setCreateBy(getUsername());
+ user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+ return toAjax(userService.insertUser(user));
+ }
+
+ /**
+ * 淇敼鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:edit')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@Validated @RequestBody SysUser user)
+ {
+ userService.checkUserAllowed(user);
+ userService.checkUserDataScope(user.getUserId());
+ deptService.checkDeptDataScope(user.getDeptId());
+ roleService.checkRoleDataScope(user.getRoleIds());
+ if (!userService.checkUserNameUnique(user))
+ {
+ return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岀櫥褰曡处鍙峰凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getPhonenumber()) && !userService.checkPhoneUnique(user))
+ {
+ return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛屾墜鏈哄彿鐮佸凡瀛樺湪");
+ }
+ else if (StringUtils.isNotEmpty(user.getEmail()) && !userService.checkEmailUnique(user))
+ {
+ return error("淇敼鐢ㄦ埛'" + user.getUserName() + "'澶辫触锛岄偖绠辫处鍙峰凡瀛樺湪");
+ }
+ user.setUpdateBy(getUsername());
+ return toAjax(userService.updateUser(user));
+ }
+
+ /**
+ * 鍒犻櫎鐢ㄦ埛
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:remove')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{userIds}")
+ public AjaxResult remove(@PathVariable Long[] userIds)
+ {
+ if (ArrayUtils.contains(userIds, getUserId()))
+ {
+ return error("褰撳墠鐢ㄦ埛涓嶈兘鍒犻櫎");
+ }
+ return toAjax(userService.deleteUserByIds(userIds));
+ }
+
+ /**
+ * 閲嶇疆瀵嗙爜
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:resetPwd')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/resetPwd")
+ public AjaxResult resetPwd(@RequestBody SysUser user)
+ {
+ userService.checkUserAllowed(user);
+ userService.checkUserDataScope(user.getUserId());
+ user.setPassword(SecurityUtils.encryptPassword(user.getPassword()));
+ user.setUpdateBy(getUsername());
+ return toAjax(userService.resetPwd(user));
+ }
+
+ /**
+ * 鐘舵�佷慨鏀�
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:edit')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysUser user)
+ {
+ userService.checkUserAllowed(user);
+ userService.checkUserDataScope(user.getUserId());
+ user.setUpdateBy(getUsername());
+ return toAjax(userService.updateUserStatus(user));
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛缂栧彿鑾峰彇鎺堟潈瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:query')")
+ @GetMapping("/authRole/{userId}")
+ public AjaxResult authRole(@PathVariable("userId") Long userId)
+ {
+ AjaxResult ajax = AjaxResult.success();
+ SysUser user = userService.selectUserById(userId);
+ List<SysRole> roles = roleService.selectRolesByUserId(userId);
+ ajax.put("user", user);
+ ajax.put("roles", SysUser.isAdmin(userId) ? roles : roles.stream().filter(r -> !r.isAdmin()).collect(Collectors.toList()));
+ return ajax;
+ }
+
+ /**
+ * 鐢ㄦ埛鎺堟潈瑙掕壊
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:edit')")
+ @Log(title = "鐢ㄦ埛绠$悊", businessType = BusinessType.GRANT)
+ @PutMapping("/authRole")
+ public AjaxResult insertAuthRole(Long userId, Long[] roleIds)
+ {
+ userService.checkUserDataScope(userId);
+ roleService.checkRoleDataScope(roleIds);
+ userService.insertUserAuth(userId, roleIds);
+ return success();
+ }
+
+ /**
+ * 鑾峰彇閮ㄩ棬鏍戝垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('system:user:list')")
+ @GetMapping("/deptTree")
+ public AjaxResult deptTree(SysDept dept)
+ {
+ return success(deptService.selectDeptTreeList(dept));
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/UserController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/UserController.java
new file mode 100644
index 0000000..eb0bfd5
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/UserController.java
@@ -0,0 +1,25 @@
+package com.ruoyi.web.controller.system;
+
+
+import com.ruoyi.system.service.UserService;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+
+/**
+ * 鐢ㄦ埛淇℃伅琛�
+ *
+ * @author zhuo
+ * @since 2025-02-13
+ */
+@RestController
+@RequestMapping("/system/newUser")
+public class UserController {
+
+ @Resource
+ private UserService userService;
+
+}
+
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
new file mode 100644
index 0000000..5618863
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/TestController.java
@@ -0,0 +1,183 @@
+package com.ruoyi.web.controller.tool;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.Result;
+import com.ruoyi.common.utils.StringUtils;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import io.swagger.annotations.ApiOperation;
+
+/**
+ * swagger 鐢ㄦ埛娴嬭瘯鏂规硶
+ *
+ * @author ruoyi
+ */
+@Api("鐢ㄦ埛淇℃伅绠$悊")
+@RestController
+@RequestMapping("/test/user")
+public class TestController extends BaseController
+{
+ private final static Map<Integer, UserEntity> users = new LinkedHashMap<Integer, UserEntity>();
+ {
+ users.put(1, new UserEntity(1, "admin", "admin123", "15888888888"));
+ users.put(2, new UserEntity(2, "ry", "admin123", "15666666666"));
+ }
+
+ @ApiOperation("鑾峰彇鐢ㄦ埛鍒楄〃")
+ @GetMapping("/list")
+ public Result<List<UserEntity>> userList()
+ {
+ List<UserEntity> userList = new ArrayList<UserEntity>(users.values());
+ return Result.success(userList);
+ }
+
+ @ApiOperation("鑾峰彇鐢ㄦ埛璇︾粏")
+ @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
+ @GetMapping("/{userId}")
+ public Result<UserEntity> getUser(@PathVariable Integer userId)
+ {
+ if (!users.isEmpty() && users.containsKey(userId))
+ {
+ return Result.success(users.get(userId));
+ }
+ else
+ {
+ return Result.fail("鐢ㄦ埛涓嶅瓨鍦�");
+ }
+ }
+
+ @ApiOperation("鏂板鐢ㄦ埛")
+ @ApiImplicitParams({
+ @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛id", dataType = "Integer", dataTypeClass = Integer.class),
+ @ApiImplicitParam(name = "username", value = "鐢ㄦ埛鍚嶇О", dataType = "String", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "password", value = "鐢ㄦ埛瀵嗙爜", dataType = "String", dataTypeClass = String.class),
+ @ApiImplicitParam(name = "mobile", value = "鐢ㄦ埛鎵嬫満", dataType = "String", dataTypeClass = String.class)
+ })
+ @PostMapping("/save")
+ public Result<String> save(UserEntity user)
+ {
+ if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
+ {
+ return Result.fail("鐢ㄦ埛ID涓嶈兘涓虹┖");
+ }
+ users.put(user.getUserId(), user);
+ return Result.success();
+ }
+
+ @ApiOperation("鏇存柊鐢ㄦ埛")
+ @PutMapping("/update")
+ public Result<String> update(@RequestBody UserEntity user)
+ {
+ if (StringUtils.isNull(user) || StringUtils.isNull(user.getUserId()))
+ {
+ return Result.fail("鐢ㄦ埛ID涓嶈兘涓虹┖");
+ }
+ if (users.isEmpty() || !users.containsKey(user.getUserId()))
+ {
+ return Result.fail("鐢ㄦ埛涓嶅瓨鍦�");
+ }
+ users.remove(user.getUserId());
+ users.put(user.getUserId(), user);
+ return Result.success();
+ }
+
+ @ApiOperation("鍒犻櫎鐢ㄦ埛淇℃伅")
+ @ApiImplicitParam(name = "userId", value = "鐢ㄦ埛ID", required = true, dataType = "int", paramType = "path", dataTypeClass = Integer.class)
+ @DeleteMapping("/{userId}")
+ public Result<String> delete(@PathVariable Integer userId)
+ {
+ if (!users.isEmpty() && users.containsKey(userId))
+ {
+ users.remove(userId);
+ return Result.success();
+ }
+ else
+ {
+ return Result.fail("鐢ㄦ埛涓嶅瓨鍦�");
+ }
+ }
+}
+
+@ApiModel(value = "UserEntity", description = "鐢ㄦ埛瀹炰綋")
+class UserEntity
+{
+ @ApiModelProperty("鐢ㄦ埛ID")
+ private Integer userId;
+
+ @ApiModelProperty("鐢ㄦ埛鍚嶇О")
+ private String username;
+
+ @ApiModelProperty("鐢ㄦ埛瀵嗙爜")
+ private String password;
+
+ @ApiModelProperty("鐢ㄦ埛鎵嬫満")
+ private String mobile;
+
+ public UserEntity()
+ {
+
+ }
+
+ public UserEntity(Integer userId, String username, String password, String mobile)
+ {
+ this.userId = userId;
+ this.username = username;
+ this.password = password;
+ this.mobile = mobile;
+ }
+
+ public Integer getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Integer userId)
+ {
+ this.userId = userId;
+ }
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getMobile()
+ {
+ return mobile;
+ }
+
+ public void setMobile(String mobile)
+ {
+ this.mobile = mobile;
+ }
+}
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
new file mode 100644
index 0000000..3822cfd
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SwaggerConfig.java
@@ -0,0 +1,120 @@
+package com.ruoyi.web.core.config;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.ruoyi.common.config.RuoYiConfig;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.models.auth.In;
+import springfox.documentation.builders.ApiInfoBuilder;
+import springfox.documentation.builders.PathSelectors;
+import springfox.documentation.builders.RequestHandlerSelectors;
+import springfox.documentation.service.ApiInfo;
+import springfox.documentation.service.ApiKey;
+import springfox.documentation.service.AuthorizationScope;
+import springfox.documentation.service.Contact;
+import springfox.documentation.service.SecurityReference;
+import springfox.documentation.service.SecurityScheme;
+import springfox.documentation.spi.DocumentationType;
+import springfox.documentation.spi.service.contexts.SecurityContext;
+import springfox.documentation.spring.web.plugins.Docket;
+
+/**
+ * Swagger2鐨勬帴鍙i厤缃�
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class SwaggerConfig
+{
+ /** 绯荤粺鍩虹閰嶇疆 */
+ @Autowired
+ private RuoYiConfig ruoyiConfig;
+
+ /** 鏄惁寮�鍚痵wagger */
+ @Value("${swagger.enabled}")
+ private boolean enabled;
+
+ /**
+ * 鍒涘缓API
+ */
+ @Bean
+ public Docket createRestApi()
+ {
+ return new Docket(DocumentationType.OAS_30)
+ // 鏄惁鍚敤Swagger
+ .enable(enabled)
+ // 鐢ㄦ潵鍒涘缓璇PI鐨勫熀鏈俊鎭紝灞曠ず鍦ㄦ枃妗g殑椤甸潰涓紙鑷畾涔夊睍绀虹殑淇℃伅锛�
+ .apiInfo(apiInfo())
+ // 璁剧疆鍝簺鎺ュ彛鏆撮湶缁橲wagger灞曠ず
+ .select()
+ // 鎵弿鎵�鏈夋湁娉ㄨВ鐨刟pi锛岀敤杩欑鏂瑰紡鏇寸伒娲�
+ .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
+ // 鎵弿鎸囧畾鍖呬腑鐨剆wagger娉ㄨВ
+ // .apis(RequestHandlerSelectors.basePackage("com.ruoyi.project.tool.swagger"))
+ // 鎵弿鎵�鏈� .apis(RequestHandlerSelectors.any())
+ .paths(PathSelectors.any())
+ .build()
+ /* 璁剧疆瀹夊叏妯″紡锛宻wagger鍙互璁剧疆璁块棶token */
+ .securitySchemes(securitySchemes())
+ .securityContexts(securityContexts());
+ }
+
+ /**
+ * 瀹夊叏妯″紡锛岃繖閲屾寚瀹歵oken閫氳繃Authorization澶磋姹傚ご浼犻��
+ */
+ private List<SecurityScheme> securitySchemes()
+ {
+ List<SecurityScheme> apiKeyList = new ArrayList<SecurityScheme>();
+ apiKeyList.add(new ApiKey("Authorization", "Authorization", In.HEADER.toValue()));
+ return apiKeyList;
+ }
+
+ /**
+ * 瀹夊叏涓婁笅鏂�
+ */
+ private List<SecurityContext> securityContexts()
+ {
+ List<SecurityContext> securityContexts = new ArrayList<>();
+ securityContexts.add(
+ SecurityContext.builder()
+ .securityReferences(defaultAuth())
+ .operationSelector(o -> o.requestMappingPattern().matches("/.*"))
+ .build());
+ return securityContexts;
+ }
+
+ /**
+ * 榛樿鐨勫畨鍏ㄤ笂寮曠敤
+ */
+ private List<SecurityReference> defaultAuth()
+ {
+ AuthorizationScope authorizationScope = new AuthorizationScope("global", "accessEverything");
+ AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
+ authorizationScopes[0] = authorizationScope;
+ List<SecurityReference> securityReferences = new ArrayList<>();
+ securityReferences.add(new SecurityReference("Authorization", authorizationScopes));
+ return securityReferences;
+ }
+
+ /**
+ * 娣诲姞鎽樿淇℃伅
+ */
+ private ApiInfo apiInfo()
+ {
+ // 鐢ˋpiInfoBuilder杩涜瀹氬埗
+ return new ApiInfoBuilder()
+ // 璁剧疆鏍囬
+ .title("鏍囬锛氳嫢渚濈鐞嗙郴缁焈鎺ュ彛鏂囨。")
+ // 鎻忚堪
+ .description("鎻忚堪锛氱敤浜庣鐞嗛泦鍥㈡棗涓嬪叕鍙哥殑浜哄憳淇℃伅,鍏蜂綋鍖呮嫭XXX,XXX妯″潡...")
+ // 浣滆�呬俊鎭�
+ .contact(new Contact(ruoyiConfig.getName(), null, null))
+ // 鐗堟湰
+ .version("鐗堟湰鍙�:" + ruoyiConfig.getVersion())
+ .build();
+ }
+}
diff --git a/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties
new file mode 100644
index 0000000..37e7b58
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/META-INF/spring-devtools.properties
@@ -0,0 +1 @@
+restart.include.json=/com.alibaba.fastjson2.*.jar
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/application-druid.yml b/ruoyi-admin/src/main/resources/application-druid.yml
new file mode 100644
index 0000000..1db419e
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application-druid.yml
@@ -0,0 +1,71 @@
+# 鏁版嵁婧愰厤缃�
+spring:
+ datasource:
+ type: com.alibaba.druid.pool.DruidDataSource
+ driverClassName: com.mysql.cj.jdbc.Driver
+ druid:
+ # 涓诲簱鏁版嵁婧�
+ master:
+# url: jdbc:mysql://114.132.189.42:9004/lims-ruoyi?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ url: jdbc:mysql://127.0.0.1:3307/center-lims-test?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+ username: root
+ password: 123456
+ # 浠庡簱鏁版嵁婧�
+ slave:
+ # 浠庢暟鎹簮寮�鍏�/榛樿鍏抽棴
+ enabled: false
+ url:
+ username:
+ password:
+ # 鍒濆杩炴帴鏁�
+ initialSize: 5
+ # 鏈�灏忚繛鎺ユ睜鏁伴噺
+ minIdle: 10
+ # 鏈�澶ц繛鎺ユ睜鏁伴噺
+ maxActive: 20
+ # 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂�
+ maxWait: 60000
+ # 閰嶇疆杩炴帴瓒呮椂鏃堕棿
+ connectTimeout: 30000
+ # 閰嶇疆缃戠粶瓒呮椂鏃堕棿
+ socketTimeout: 60000
+ # 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣
+ timeBetweenEvictionRunsMillis: 60000
+ # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忕敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+ minEvictableIdleTimeMillis: 300000
+ # 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣
+ maxEvictableIdleTimeMillis: 900000
+ # 閰嶇疆妫�娴嬭繛鎺ユ槸鍚︽湁鏁�
+ validationQuery: SELECT 1 FROM DUAL
+ testWhileIdle: true
+ testOnBorrow: false
+ testOnReturn: false
+ webStatFilter:
+ enabled: true
+ statViewServlet:
+ enabled: true
+ # 璁剧疆鐧藉悕鍗曪紝涓嶅~鍒欏厑璁告墍鏈夎闂�
+ allow:
+ url-pattern: /druid/*
+ # 鎺у埗鍙扮鐞嗙敤鎴峰悕鍜屽瘑鐮�
+ login-username: ruoyi
+ login-password: 123456
+ filter:
+ stat:
+ enabled: true
+ # 鎱QL璁板綍
+ log-slow-sql: true
+ slow-sql-millis: 1000
+ merge-sql: true
+ wall:
+ config:
+ multi-statement-allow: true
+
+
+minio:
+ endpoint: http://114.132.189.42/
+ port: 7019
+ secure: false
+ accessKey: admin
+ secretKey: 12345678
+ preview-expiry: 24 # 棰勮鍦板潃榛樿24灏忔椂
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
new file mode 100644
index 0000000..9147fdd
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -0,0 +1,132 @@
+# 椤圭洰鐩稿叧閰嶇疆
+ruoyi:
+ # 鍚嶇О
+ name: RuoYi
+ # 鐗堟湰
+ version: 3.8.9
+ # 鐗堟潈骞翠唤
+ copyrightYear: 2025
+ # 鏂囦欢璺緞 绀轰緥锛� Windows閰嶇疆D:/ruoyi/uploadPath锛孡inux閰嶇疆 /home/ruoyi/uploadPath锛�
+ profile: D:/ruoyi/uploadPath
+ # 鑾峰彇ip鍦板潃寮�鍏�
+ addressEnabled: false
+ # 楠岃瘉鐮佺被鍨� math 鏁板瓧璁$畻 char 瀛楃楠岃瘉
+ captchaType: math
+
+# 寮�鍙戠幆澧冮厤缃�
+server:
+ # 鏈嶅姟鍣ㄧ殑HTTP绔彛锛岄粯璁や负8080
+ port: 8002
+ servlet:
+ # 搴旂敤鐨勮闂矾寰�
+ context-path: /
+ tomcat:
+ # tomcat鐨刄RI缂栫爜
+ uri-encoding: UTF-8
+ # 杩炴帴鏁版弧鍚庣殑鎺掗槦鏁帮紝榛樿涓�100
+ accept-count: 1000
+ threads:
+ # tomcat鏈�澶х嚎绋嬫暟锛岄粯璁や负200
+ max: 800
+ # Tomcat鍚姩鍒濆鍖栫殑绾跨▼鏁帮紝榛樿鍊�10
+ min-spare: 100
+
+# 鏃ュ織閰嶇疆
+logging:
+ level:
+ com.ruoyi: debug
+ org.springframework: warn
+
+# 鐢ㄦ埛閰嶇疆
+user:
+ password:
+ # 瀵嗙爜鏈�澶ч敊璇鏁�
+ maxRetryCount: 5
+ # 瀵嗙爜閿佸畾鏃堕棿锛堥粯璁�10鍒嗛挓锛�
+ lockTime: 10
+
+# Spring閰嶇疆
+spring:
+ # 璧勬簮淇℃伅
+ messages:
+ # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
+ basename: i18n/messages
+ profiles:
+ active: druid
+ # 鏂囦欢涓婁紶
+ servlet:
+ multipart:
+ # 鍗曚釜鏂囦欢澶у皬
+ max-file-size: 10MB
+ # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
+ max-request-size: 20MB
+ # 鏈嶅姟妯″潡
+ devtools:
+ restart:
+ # 鐑儴缃插紑鍏�
+ enabled: true
+ # redis 閰嶇疆
+ redis:
+ # 鍦板潃
+ host: localhost
+ # 绔彛锛岄粯璁や负6379
+ port: 6379
+ # 鏁版嵁搴撶储寮�
+ database: 0
+ # 瀵嗙爜
+ password: 123456
+ # 杩炴帴瓒呮椂鏃堕棿
+ timeout: 10s
+ lettuce:
+ pool:
+ # 杩炴帴姹犱腑鐨勬渶灏忕┖闂茶繛鎺�
+ min-idle: 0
+ # 杩炴帴姹犱腑鐨勬渶澶х┖闂茶繛鎺�
+ max-idle: 8
+ # 杩炴帴姹犵殑鏈�澶ф暟鎹簱杩炴帴鏁�
+ max-active: 8
+ # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
+ max-wait: -1ms
+
+# token閰嶇疆
+token:
+ # 浠ょ墝鑷畾涔夋爣璇�
+ header: Authorization
+ # 浠ょ墝瀵嗛挜
+ secret: abcdefghijklmnopqrstuvwxyz
+ # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+ expireTime: 30
+
+# PageHelper鍒嗛〉鎻掍欢
+pagehelper:
+ helperDialect: mysql
+ supportMethodsArguments: true
+ params: count=countSql
+
+# Swagger閰嶇疆
+swagger:
+ # 鏄惁寮�鍚痵wagger
+ enabled: true
+
+# 闃叉XSS鏀诲嚮
+xss:
+ # 杩囨护寮�鍏�
+ enabled: true
+ # 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
+ excludes: /system/notice
+ # 鍖归厤閾炬帴
+ urlPatterns: /system/*,/monitor/*,/tool/*
+
+# mybatis-plus閰嶇疆
+mybatis-plus:
+ mapper-locations: classpath*:mapper/**/*Mapper.xml
+ type-aliases-package: com.ruoyi.**.domain
+ global-config:
+ banner: off
+ db-config:
+ id-type: auto
+ configuration:
+ map-underscore-to-camel-case: true
+ cache-enabled: false
+ log-impl: # org.apache.ibatis.logging.stdout.StdOutImpl
+
diff --git a/ruoyi-admin/src/main/resources/banner.txt b/ruoyi-admin/src/main/resources/banner.txt
new file mode 100644
index 0000000..0931cb8
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/banner.txt
@@ -0,0 +1,24 @@
+Application Version: ${ruoyi.version}
+Spring Boot Version: ${spring-boot.version}
+////////////////////////////////////////////////////////////////////
+// _ooOoo_ //
+// o8888888o //
+// 88" . "88 //
+// (| ^_^ |) //
+// O\ = /O //
+// ____/`---'\____ //
+// .' \\| |// `. //
+// / \\||| : |||// \ //
+// / _||||| -:- |||||- \ //
+// | | \\\ - /// | | //
+// | \_| ''\---/'' | | //
+// \ .-\__ `-` ___/-. / //
+// ___`. .' /--.--\ `. . ___ //
+// ."" '< `.___\_<|>_/___.' >'"". //
+// | | : `- \`.;`\ _ /`;.`/ - ` : | | //
+// \ \ `-. \_ __\ /__ _/ .-` / / //
+// ========`-.____`-.___\_____/___.-`____.-'======== //
+// `=---=' //
+// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ //
+// 浣涚淇濅綉 姘镐笉瀹曟満 姘告棤BUG //
+////////////////////////////////////////////////////////////////////
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/i18n/messages.properties b/ruoyi-admin/src/main/resources/i18n/messages.properties
new file mode 100644
index 0000000..93de005
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/i18n/messages.properties
@@ -0,0 +1,38 @@
+#閿欒娑堟伅
+not.null=* 蹇呴』濉啓
+user.jcaptcha.error=楠岃瘉鐮侀敊璇�
+user.jcaptcha.expire=楠岃瘉鐮佸凡澶辨晥
+user.not.exists=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
+user.password.not.match=鐢ㄦ埛涓嶅瓨鍦�/瀵嗙爜閿欒
+user.password.retry.limit.count=瀵嗙爜杈撳叆閿欒{0}娆�
+user.password.retry.limit.exceed=瀵嗙爜杈撳叆閿欒{0}娆★紝甯愭埛閿佸畾{1}鍒嗛挓
+user.password.delete=瀵逛笉璧凤紝鎮ㄧ殑璐﹀彿宸茶鍒犻櫎
+user.blocked=鐢ㄦ埛宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
+role.blocked=瑙掕壊宸插皝绂侊紝璇疯仈绯荤鐞嗗憳
+login.blocked=寰堥仐鎲撅紝璁块棶IP宸茶鍒楀叆绯荤粺榛戝悕鍗�
+user.logout.success=閫�鍑烘垚鍔�
+
+length.not.valid=闀垮害蹇呴』鍦▄min}鍒皗max}涓瓧绗︿箣闂�
+
+user.username.not.valid=* 2鍒�20涓眽瀛椼�佸瓧姣嶃�佹暟瀛楁垨涓嬪垝绾跨粍鎴愶紝涓斿繀椤讳互闈炴暟瀛楀紑澶�
+user.password.not.valid=* 5-50涓瓧绗�
+
+user.email.not.valid=閭鏍煎紡閿欒
+user.mobile.phone.number.not.valid=鎵嬫満鍙锋牸寮忛敊璇�
+user.login.success=鐧诲綍鎴愬姛
+user.register.success=娉ㄥ唽鎴愬姛
+user.notfound=璇烽噸鏂扮櫥褰�
+user.forcelogout=绠$悊鍛樺己鍒堕��鍑猴紝璇烽噸鏂扮櫥褰�
+user.unknown.error=鏈煡閿欒锛岃閲嶆柊鐧诲綍
+
+##鏂囦欢涓婁紶娑堟伅
+upload.exceed.maxSize=涓婁紶鐨勬枃浠跺ぇ灏忚秴鍑洪檺鍒剁殑鏂囦欢澶у皬锛�<br/>鍏佽鐨勬枃浠舵渶澶уぇ灏忔槸锛歿0}MB锛�
+upload.filename.exceed.length=涓婁紶鐨勬枃浠跺悕鏈�闀縶0}涓瓧绗�
+
+##鏉冮檺
+no.permission=鎮ㄦ病鏈夋暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.create.permission=鎮ㄦ病鏈夊垱寤烘暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.update.permission=鎮ㄦ病鏈変慨鏀规暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.delete.permission=鎮ㄦ病鏈夊垹闄ゆ暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.export.permission=鎮ㄦ病鏈夊鍑烘暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
+no.view.permission=鎮ㄦ病鏈夋煡鐪嬫暟鎹殑鏉冮檺锛岃鑱旂郴绠$悊鍛樻坊鍔犳潈闄� [{0}]
diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml
new file mode 100644
index 0000000..a360583
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/logback.xml
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<configuration>
+ <!-- 鏃ュ織瀛樻斁璺緞 -->
+ <property name="log.path" value="/home/ruoyi/logs" />
+ <!-- 鏃ュ織杈撳嚭鏍煎紡 -->
+ <property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
+
+ <!-- 鎺у埗鍙拌緭鍑� -->
+ <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
+ <encoder>
+ <pattern>${log.pattern}</pattern>
+ </encoder>
+ </appender>
+
+ <!-- 绯荤粺鏃ュ織杈撳嚭 -->
+ <appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${log.path}/sys-info.log</file>
+ <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
+ <fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+ <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+ <maxHistory>60</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${log.pattern}</pattern>
+ </encoder>
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <!-- 杩囨护鐨勭骇鍒� -->
+ <level>INFO</level>
+ <!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
+ <onMatch>ACCEPT</onMatch>
+ <!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ </appender>
+
+ <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${log.path}/sys-error.log</file>
+ <!-- 寰幆鏀跨瓥锛氬熀浜庢椂闂村垱寤烘棩蹇楁枃浠� -->
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!-- 鏃ュ織鏂囦欢鍚嶆牸寮� -->
+ <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+ <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+ <maxHistory>60</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${log.pattern}</pattern>
+ </encoder>
+ <filter class="ch.qos.logback.classic.filter.LevelFilter">
+ <!-- 杩囨护鐨勭骇鍒� -->
+ <level>ERROR</level>
+ <!-- 鍖归厤鏃剁殑鎿嶄綔锛氭帴鏀讹紙璁板綍锛� -->
+ <onMatch>ACCEPT</onMatch>
+ <!-- 涓嶅尮閰嶆椂鐨勬搷浣滐細鎷掔粷锛堜笉璁板綍锛� -->
+ <onMismatch>DENY</onMismatch>
+ </filter>
+ </appender>
+
+ <!-- 鐢ㄦ埛璁块棶鏃ュ織杈撳嚭 -->
+ <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
+ <file>${log.path}/sys-user.log</file>
+ <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
+ <!-- 鎸夊ぉ鍥炴粴 daily -->
+ <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
+ <!-- 鏃ュ織鏈�澶х殑鍘嗗彶 60澶� -->
+ <maxHistory>60</maxHistory>
+ </rollingPolicy>
+ <encoder>
+ <pattern>${log.pattern}</pattern>
+ </encoder>
+ </appender>
+
+ <!-- 绯荤粺妯″潡鏃ュ織绾у埆鎺у埗 -->
+ <logger name="com.ruoyi" level="info" />
+ <!-- Spring鏃ュ織绾у埆鎺у埗 -->
+ <logger name="org.springframework" level="warn" />
+
+ <root level="info">
+ <appender-ref ref="console" />
+ </root>
+
+ <!--绯荤粺鎿嶄綔鏃ュ織-->
+ <root level="info">
+ <appender-ref ref="file_info" />
+ <appender-ref ref="file_error" />
+ </root>
+
+ <!--绯荤粺鐢ㄦ埛鎿嶄綔鏃ュ織-->
+ <logger name="sys-user" level="info">
+ <appender-ref ref="sys-user"/>
+ </logger>
+</configuration>
\ No newline at end of file
diff --git a/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
new file mode 100644
index 0000000..ac47c03
--- /dev/null
+++ b/ruoyi-admin/src/main/resources/mybatis/mybatis-config.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE configuration
+PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-config.dtd">
+<configuration>
+ <!-- 鍏ㄥ眬鍙傛暟 -->
+ <settings>
+ <!-- 浣垮叏灞�鐨勬槧灏勫櫒鍚敤鎴栫鐢ㄧ紦瀛� -->
+ <setting name="cacheEnabled" value="true" />
+ <!-- 鍏佽JDBC 鏀寔鑷姩鐢熸垚涓婚敭 -->
+ <setting name="useGeneratedKeys" value="true" />
+ <!-- 閰嶇疆榛樿鐨勬墽琛屽櫒.SIMPLE灏辨槸鏅�氭墽琛屽櫒;REUSE鎵ц鍣ㄤ細閲嶇敤棰勫鐞嗚鍙�(prepared statements);BATCH鎵ц鍣ㄥ皢閲嶇敤璇彞骞舵墽琛屾壒閲忔洿鏂� -->
+ <setting name="defaultExecutorType" value="SIMPLE" />
+ <!-- 鎸囧畾 MyBatis 鎵�鐢ㄦ棩蹇楃殑鍏蜂綋瀹炵幇 -->
+ <setting name="logImpl" value="SLF4J" />
+ <!-- 浣跨敤椹煎嘲鍛藉悕娉曡浆鎹㈠瓧娈� -->
+ <!-- <setting name="mapUnderscoreToCamelCase" value="true"/> -->
+ </settings>
+
+</configuration>
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
new file mode 100644
index 0000000..ef7ea58
--- /dev/null
+++ b/ruoyi-common/pom.xml
@@ -0,0 +1,150 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>ruoyi-common</artifactId>
+
+ <description>
+ common閫氱敤宸ュ叿
+ </description>
+
+ <dependencies>
+
+ <!-- Spring妗嗘灦鍩烘湰鐨勬牳蹇冨伐鍏� -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context-support</artifactId>
+ </dependency>
+
+ <!-- SpringWeb妯″潡 -->
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ </dependency>
+
+ <!-- spring security 瀹夊叏璁よ瘉 -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-security</artifactId>
+ </dependency>
+
+ <!-- pagehelper 鍒嗛〉鎻掍欢 -->
+ <dependency>
+ <groupId>com.github.pagehelper</groupId>
+ <artifactId>pagehelper-spring-boot-starter</artifactId>
+ </dependency>
+
+ <!-- 鑷畾涔夐獙璇佹敞瑙� -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+
+ <!--甯哥敤宸ュ叿绫� -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+
+ <!-- JSON宸ュ叿绫� -->
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+
+ <!-- 闃块噷JSON瑙f瀽鍣� -->
+ <dependency>
+ <groupId>com.alibaba.fastjson2</groupId>
+ <artifactId>fastjson2</artifactId>
+ </dependency>
+
+ <!-- io甯哥敤宸ュ叿绫� -->
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <!-- excel宸ュ叿 -->
+ <dependency>
+ <groupId>org.apache.poi</groupId>
+ <artifactId>poi-ooxml</artifactId>
+ </dependency>
+
+ <!-- yml瑙f瀽鍣� -->
+ <dependency>
+ <groupId>org.yaml</groupId>
+ <artifactId>snakeyaml</artifactId>
+ </dependency>
+
+ <!-- Token鐢熸垚涓庤В鏋�-->
+ <dependency>
+ <groupId>io.jsonwebtoken</groupId>
+ <artifactId>jjwt</artifactId>
+ </dependency>
+
+ <!-- Jaxb -->
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ </dependency>
+
+ <!-- redis 缂撳瓨鎿嶄綔 -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-data-redis</artifactId>
+ </dependency>
+
+ <!-- pool 瀵硅薄姹� -->
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-pool2</artifactId>
+ </dependency>
+
+ <!-- 瑙f瀽瀹㈡埛绔搷浣滅郴缁熴�佹祻瑙堝櫒绛� -->
+ <dependency>
+ <groupId>eu.bitwalker</groupId>
+ <artifactId>UserAgentUtils</artifactId>
+ </dependency>
+
+ <!-- servlet鍖� -->
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+
+ <!-- minio -->
+ <dependency>
+ <groupId>io.minio</groupId>
+ <artifactId>minio</artifactId>
+ </dependency>
+
+ <!-- minio渚濊禆okhttp 涓嶇劧鎶ラ敊 -->
+ <dependency>
+ <groupId>com.squareup.okhttp3</groupId>
+ <artifactId>okhttp</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</artifactId>
+ <version>1.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.datatype</groupId>
+ <artifactId>jackson-datatype-jsr310</artifactId>
+ </dependency>
+ </dependencies>
+
+</project>
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
new file mode 100644
index 0000000..1d6d4f4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Anonymous.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.annotation;
+
+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;
+
+/**
+ * 鍖垮悕璁块棶涓嶉壌鏉冩敞瑙�
+ *
+ * @author ruoyi
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Anonymous
+{
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
new file mode 100644
index 0000000..be49c80
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataScope.java
@@ -0,0 +1,33 @@
+package com.ruoyi.common.annotation;
+
+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;
+
+/**
+ * 鏁版嵁鏉冮檺杩囨护娉ㄨВ
+ *
+ * @author ruoyi
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface DataScope
+{
+ /**
+ * 閮ㄩ棬琛ㄧ殑鍒悕
+ */
+ public String deptAlias() default "";
+
+ /**
+ * 鐢ㄦ埛琛ㄧ殑鍒悕
+ */
+ public String userAlias() default "";
+
+ /**
+ * 鏉冮檺瀛楃锛堢敤浜庡涓鑹插尮閰嶇鍚堣姹傜殑鏉冮檺锛夐粯璁ゆ牴鎹潈闄愭敞瑙ss鑾峰彇锛屽涓潈闄愮敤閫楀彿鍒嗛殧寮�鏉�
+ */
+ public String permission() default "";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
new file mode 100644
index 0000000..79cd191
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/DataSource.java
@@ -0,0 +1,28 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.ruoyi.common.enums.DataSourceType;
+
+/**
+ * 鑷畾涔夊鏁版嵁婧愬垏鎹㈡敞瑙�
+ *
+ * 浼樺厛绾э細鍏堟柟娉曪紝鍚庣被锛屽鏋滄柟娉曡鐩栦簡绫讳笂鐨勬暟鎹簮绫诲瀷锛屼互鏂规硶鐨勪负鍑嗭紝鍚﹀垯浠ョ被涓婄殑涓哄噯
+ *
+ * @author ruoyi
+ */
+@Target({ ElementType.METHOD, ElementType.TYPE })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@Inherited
+public @interface DataSource
+{
+ /**
+ * 鍒囨崲鏁版嵁婧愬悕绉�
+ */
+ public DataSourceType value() default DataSourceType.MASTER;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
new file mode 100644
index 0000000..765d8e3
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excel.java
@@ -0,0 +1,197 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.math.BigDecimal;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import com.ruoyi.common.utils.poi.ExcelHandlerAdapter;
+
+/**
+ * 鑷畾涔夊鍑篍xcel鏁版嵁娉ㄨВ
+ *
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+public @interface Excel
+{
+ /**
+ * 瀵煎嚭鏃跺湪excel涓帓搴�
+ */
+ public int sort() default Integer.MAX_VALUE;
+
+ /**
+ * 瀵煎嚭鍒癊xcel涓殑鍚嶅瓧.
+ */
+ public String name() default "";
+
+ /**
+ * 鏃ユ湡鏍煎紡, 濡�: yyyy-MM-dd
+ */
+ public String dateFormat() default "";
+
+ /**
+ * 濡傛灉鏄瓧鍏哥被鍨嬶紝璇疯缃瓧鍏哥殑type鍊� (濡�: sys_user_sex)
+ */
+ public String dictType() default "";
+
+ /**
+ * 璇诲彇鍐呭杞〃杈惧紡 (濡�: 0=鐢�,1=濂�,2=鏈煡)
+ */
+ public String readConverterExp() default "";
+
+ /**
+ * 鍒嗛殧绗︼紝璇诲彇瀛楃涓茬粍鍐呭
+ */
+ public String separator() default ",";
+
+ /**
+ * BigDecimal 绮惧害 榛樿:-1(榛樿涓嶅紑鍚疊igDecimal鏍煎紡鍖�)
+ */
+ public int scale() default -1;
+
+ /**
+ * BigDecimal 鑸嶅叆瑙勫垯 榛樿:BigDecimal.ROUND_HALF_EVEN
+ */
+ public int roundingMode() default BigDecimal.ROUND_HALF_EVEN;
+
+ /**
+ * 瀵煎嚭鏃跺湪excel涓瘡涓垪鐨勯珮搴�
+ */
+ public double height() default 14;
+
+ /**
+ * 瀵煎嚭鏃跺湪excel涓瘡涓垪鐨勫搴�
+ */
+ public double width() default 16;
+
+ /**
+ * 鏂囧瓧鍚庣紑,濡�% 90 鍙樻垚90%
+ */
+ public String suffix() default "";
+
+ /**
+ * 褰撳�间负绌烘椂,瀛楁鐨勯粯璁ゅ��
+ */
+ public String defaultValue() default "";
+
+ /**
+ * 鎻愮ず淇℃伅
+ */
+ public String prompt() default "";
+
+ /**
+ * 鏄惁鍏佽鍐呭鎹㈣
+ */
+ public boolean wrapText() default false;
+
+ /**
+ * 璁剧疆鍙兘閫夋嫨涓嶈兘杈撳叆鐨勫垪鍐呭.
+ */
+ public String[] combo() default {};
+
+ /**
+ * 鏄惁浠庡瓧鍏歌鏁版嵁鍒癱ombo,榛樿涓嶈鍙�,濡傝鍙栭渶瑕佽缃甦ictType娉ㄨВ.
+ */
+ public boolean comboReadDict() default false;
+
+ /**
+ * 鏄惁闇�瑕佺旱鍚戝悎骞跺崟鍏冩牸,搴斿闇�姹�:鍚湁list闆嗗悎鍗曞厓鏍�)
+ */
+ public boolean needMerge() default false;
+
+ /**
+ * 鏄惁瀵煎嚭鏁版嵁,搴斿闇�姹�:鏈夋椂鎴戜滑闇�瑕佸鍑轰竴浠芥ā鏉�,杩欐槸鏍囬闇�瑕佷絾鍐呭闇�瑕佺敤鎴锋墜宸ュ~鍐�.
+ */
+ public boolean isExport() default true;
+
+ /**
+ * 鍙︿竴涓被涓殑灞炴�у悕绉�,鏀寔澶氱骇鑾峰彇,浠ュ皬鏁扮偣闅斿紑
+ */
+ public String targetAttr() default "";
+
+ /**
+ * 鏄惁鑷姩缁熻鏁版嵁,鍦ㄦ渶鍚庤拷鍔犱竴琛岀粺璁℃暟鎹�诲拰
+ */
+ public boolean isStatistics() default false;
+
+ /**
+ * 瀵煎嚭绫诲瀷锛�0鏁板瓧 1瀛楃涓� 2鍥剧墖锛�
+ */
+ public ColumnType cellType() default ColumnType.STRING;
+
+ /**
+ * 瀵煎嚭鍒楀ご鑳屾櫙棰滆壊
+ */
+ public IndexedColors headerBackgroundColor() default IndexedColors.GREY_50_PERCENT;
+
+ /**
+ * 瀵煎嚭鍒楀ご瀛椾綋棰滆壊
+ */
+ public IndexedColors headerColor() default IndexedColors.WHITE;
+
+ /**
+ * 瀵煎嚭鍗曞厓鏍艰儗鏅鑹�
+ */
+ public IndexedColors backgroundColor() default IndexedColors.WHITE;
+
+ /**
+ * 瀵煎嚭鍗曞厓鏍煎瓧浣撻鑹�
+ */
+ public IndexedColors color() default IndexedColors.BLACK;
+
+ /**
+ * 瀵煎嚭瀛楁瀵归綈鏂瑰紡
+ */
+ public HorizontalAlignment align() default HorizontalAlignment.CENTER;
+
+ /**
+ * 鑷畾涔夋暟鎹鐞嗗櫒
+ */
+ public Class<?> handler() default ExcelHandlerAdapter.class;
+
+ /**
+ * 鑷畾涔夋暟鎹鐞嗗櫒鍙傛暟
+ */
+ public String[] args() default {};
+
+ /**
+ * 瀛楁绫诲瀷锛�0锛氬鍑哄鍏ワ紱1锛氫粎瀵煎嚭锛�2锛氫粎瀵煎叆锛�
+ */
+ Type type() default Type.ALL;
+
+ public enum Type
+ {
+ ALL(0), EXPORT(1), IMPORT(2);
+ private final int value;
+
+ Type(int value)
+ {
+ this.value = value;
+ }
+
+ public int value()
+ {
+ return this.value;
+ }
+ }
+
+ public enum ColumnType
+ {
+ NUMERIC(0), STRING(1), IMAGE(2), TEXT(3);
+ private final int value;
+
+ ColumnType(int value)
+ {
+ this.value = value;
+ }
+
+ public int value()
+ {
+ return this.value;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
new file mode 100644
index 0000000..1f1cc81
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Excels.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Excel娉ㄨВ闆�
+ *
+ * @author ruoyi
+ */
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Excels
+{
+ public Excel[] value();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
new file mode 100644
index 0000000..1eb8e49
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Log.java
@@ -0,0 +1,51 @@
+package com.ruoyi.common.annotation;
+
+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;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.enums.OperatorType;
+
+/**
+ * 鑷畾涔夋搷浣滄棩蹇楄褰曟敞瑙�
+ *
+ * @author ruoyi
+ *
+ */
+@Target({ ElementType.PARAMETER, ElementType.METHOD })
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface Log
+{
+ /**
+ * 妯″潡
+ */
+ public String title() default "";
+
+ /**
+ * 鍔熻兘
+ */
+ public BusinessType businessType() default BusinessType.OTHER;
+
+ /**
+ * 鎿嶄綔浜虹被鍒�
+ */
+ public OperatorType operatorType() default OperatorType.MANAGE;
+
+ /**
+ * 鏄惁淇濆瓨璇锋眰鐨勫弬鏁�
+ */
+ public boolean isSaveRequestData() default true;
+
+ /**
+ * 鏄惁淇濆瓨鍝嶅簲鐨勫弬鏁�
+ */
+ public boolean isSaveResponseData() default true;
+
+ /**
+ * 鎺掗櫎鎸囧畾鐨勮姹傚弬鏁�
+ */
+ public String[] excludeParamNames() default {};
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
new file mode 100644
index 0000000..0f024c7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RateLimiter.java
@@ -0,0 +1,40 @@
+package com.ruoyi.common.annotation;
+
+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;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.enums.LimitType;
+
+/**
+ * 闄愭祦娉ㄨВ
+ *
+ * @author ruoyi
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RateLimiter
+{
+ /**
+ * 闄愭祦key
+ */
+ public String key() default CacheConstants.RATE_LIMIT_KEY;
+
+ /**
+ * 闄愭祦鏃堕棿,鍗曚綅绉�
+ */
+ public int time() default 60;
+
+ /**
+ * 闄愭祦娆℃暟
+ */
+ public int count() default 100;
+
+ /**
+ * 闄愭祦绫诲瀷
+ */
+ public LimitType limitType() default LimitType.DEFAULT;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
new file mode 100644
index 0000000..b769748
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/RepeatSubmit.java
@@ -0,0 +1,31 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Inherited;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鑷畾涔夋敞瑙i槻姝㈣〃鍗曢噸澶嶆彁浜�
+ *
+ * @author ruoyi
+ *
+ */
+@Inherited
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface RepeatSubmit
+{
+ /**
+ * 闂撮殧鏃堕棿(ms)锛屽皬浜庢鏃堕棿瑙嗕负閲嶅鎻愪氦
+ */
+ public int interval() default 5000;
+
+ /**
+ * 鎻愮ず娑堟伅
+ */
+ public String message() default "涓嶅厑璁搁噸澶嶆彁浜わ紝璇风◢鍊欏啀璇�";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
new file mode 100644
index 0000000..c0621e9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/annotation/Sensitive.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.annotation;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import com.fasterxml.jackson.annotation.JacksonAnnotationsInside;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.ruoyi.common.config.serializer.SensitiveJsonSerializer;
+import com.ruoyi.common.enums.DesensitizedType;
+
+/**
+ * 鏁版嵁鑴辨晱娉ㄨВ
+ *
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.FIELD)
+@JacksonAnnotationsInside
+@JsonSerialize(using = SensitiveJsonSerializer.class)
+public @interface Sensitive
+{
+ DesensitizedType desensitizedType();
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java
new file mode 100644
index 0000000..28f489f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.config;
+
+import io.minio.MinioClient;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+@Configuration
+@Component
+@ConfigurationProperties(prefix = "minio")
+@Data
+public class MinioConfig {
+ private String endpoint;
+ private int port;
+ private String accessKey;
+ private String secretKey;
+ private Boolean secure;
+
+ @Bean
+ public MinioClient getMinioClient() {
+ return MinioClient.builder().endpoint(endpoint, port, secure)
+ .credentials(accessKey, secretKey)
+ .build();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
new file mode 100644
index 0000000..29281cf
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/RuoYiConfig.java
@@ -0,0 +1,122 @@
+package com.ruoyi.common.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+/**
+ * 璇诲彇椤圭洰鐩稿叧閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "ruoyi")
+public class RuoYiConfig
+{
+ /** 椤圭洰鍚嶇О */
+ private String name;
+
+ /** 鐗堟湰 */
+ private String version;
+
+ /** 鐗堟潈骞翠唤 */
+ private String copyrightYear;
+
+ /** 涓婁紶璺緞 */
+ private static String profile;
+
+ /** 鑾峰彇鍦板潃寮�鍏� */
+ private static boolean addressEnabled;
+
+ /** 楠岃瘉鐮佺被鍨� */
+ private static String captchaType;
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(String version)
+ {
+ this.version = version;
+ }
+
+ public String getCopyrightYear()
+ {
+ return copyrightYear;
+ }
+
+ public void setCopyrightYear(String copyrightYear)
+ {
+ this.copyrightYear = copyrightYear;
+ }
+
+ public static String getProfile()
+ {
+ return profile;
+ }
+
+ public void setProfile(String profile)
+ {
+ RuoYiConfig.profile = profile;
+ }
+
+ public static boolean isAddressEnabled()
+ {
+ return addressEnabled;
+ }
+
+ public void setAddressEnabled(boolean addressEnabled)
+ {
+ RuoYiConfig.addressEnabled = addressEnabled;
+ }
+
+ public static String getCaptchaType() {
+ return captchaType;
+ }
+
+ public void setCaptchaType(String captchaType) {
+ RuoYiConfig.captchaType = captchaType;
+ }
+
+ /**
+ * 鑾峰彇瀵煎叆涓婁紶璺緞
+ */
+ public static String getImportPath()
+ {
+ return getProfile() + "/import";
+ }
+
+ /**
+ * 鑾峰彇澶村儚涓婁紶璺緞
+ */
+ public static String getAvatarPath()
+ {
+ return getProfile() + "/avatar";
+ }
+
+ /**
+ * 鑾峰彇涓嬭浇璺緞
+ */
+ public static String getDownloadPath()
+ {
+ return getProfile() + "/download/";
+ }
+
+ /**
+ * 鑾峰彇涓婁紶璺緞
+ */
+ public static String getUploadPath()
+ {
+ return getProfile() + "/upload";
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java
new file mode 100644
index 0000000..e819a1d
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/serializer/SensitiveJsonSerializer.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.config.serializer;
+
+import java.io.IOException;
+import java.util.Objects;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.databind.BeanProperty;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.JsonSerializer;
+import com.fasterxml.jackson.databind.SerializerProvider;
+import com.fasterxml.jackson.databind.ser.ContextualSerializer;
+import com.ruoyi.common.annotation.Sensitive;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.enums.DesensitizedType;
+import com.ruoyi.common.utils.SecurityUtils;
+
+/**
+ * 鏁版嵁鑴辨晱搴忓垪鍖栬繃婊�
+ *
+ * @author ruoyi
+ */
+public class SensitiveJsonSerializer extends JsonSerializer<String> implements ContextualSerializer
+{
+ private DesensitizedType desensitizedType;
+
+ @Override
+ public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException
+ {
+ if (desensitization())
+ {
+ gen.writeString(desensitizedType.desensitizer().apply(value));
+ }
+ else
+ {
+ gen.writeString(value);
+ }
+ }
+
+ @Override
+ public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property)
+ throws JsonMappingException
+ {
+ Sensitive annotation = property.getAnnotation(Sensitive.class);
+ if (Objects.nonNull(annotation) && Objects.equals(String.class, property.getType().getRawClass()))
+ {
+ this.desensitizedType = annotation.desensitizedType();
+ return this;
+ }
+ return prov.findValueSerializer(property.getType(), property);
+ }
+
+ /**
+ * 鏄惁闇�瑕佽劚鏁忓鐞�
+ */
+ private boolean desensitization()
+ {
+ try
+ {
+ LoginUser securityUser = SecurityUtils.getLoginUser();
+ // 绠$悊鍛樹笉鑴辨晱
+ return !securityUser.getUser().isAdmin();
+ }
+ catch (Exception e)
+ {
+ return true;
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
new file mode 100644
index 0000000..0080343
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/CacheConstants.java
@@ -0,0 +1,44 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 缂撳瓨鐨刱ey 甯搁噺
+ *
+ * @author ruoyi
+ */
+public class CacheConstants
+{
+ /**
+ * 鐧诲綍鐢ㄦ埛 redis key
+ */
+ public static final String LOGIN_TOKEN_KEY = "login_tokens:";
+
+ /**
+ * 楠岃瘉鐮� redis key
+ */
+ public static final String CAPTCHA_CODE_KEY = "captcha_codes:";
+
+ /**
+ * 鍙傛暟绠$悊 cache key
+ */
+ public static final String SYS_CONFIG_KEY = "sys_config:";
+
+ /**
+ * 瀛楀吀绠$悊 cache key
+ */
+ public static final String SYS_DICT_KEY = "sys_dict:";
+
+ /**
+ * 闃查噸鎻愪氦 redis key
+ */
+ public static final String REPEAT_SUBMIT_KEY = "repeat_submit:";
+
+ /**
+ * 闄愭祦 redis key
+ */
+ public static final String RATE_LIMIT_KEY = "rate_limit:";
+
+ /**
+ * 鐧诲綍璐︽埛瀵嗙爜閿欒娆℃暟 redis key
+ */
+ public static final String PWD_ERR_CNT_KEY = "pwd_err_cnt:";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
new file mode 100644
index 0000000..0c384c6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java
@@ -0,0 +1,173 @@
+package com.ruoyi.common.constant;
+
+import java.util.Locale;
+import io.jsonwebtoken.Claims;
+
+/**
+ * 閫氱敤甯搁噺淇℃伅
+ *
+ * @author ruoyi
+ */
+public class Constants
+{
+ /**
+ * UTF-8 瀛楃闆�
+ */
+ public static final String UTF8 = "UTF-8";
+
+ /**
+ * GBK 瀛楃闆�
+ */
+ public static final String GBK = "GBK";
+
+ /**
+ * 绯荤粺璇█
+ */
+ public static final Locale DEFAULT_LOCALE = Locale.SIMPLIFIED_CHINESE;
+
+ /**
+ * www涓诲煙
+ */
+ public static final String WWW = "www.";
+
+ /**
+ * http璇锋眰
+ */
+ public static final String HTTP = "http://";
+
+ /**
+ * https璇锋眰
+ */
+ public static final String HTTPS = "https://";
+
+ /**
+ * 閫氱敤鎴愬姛鏍囪瘑
+ */
+ public static final String SUCCESS = "0";
+
+ /**
+ * 閫氱敤澶辫触鏍囪瘑
+ */
+ public static final String FAIL = "1";
+
+ /**
+ * 鐧诲綍鎴愬姛
+ */
+ public static final String LOGIN_SUCCESS = "Success";
+
+ /**
+ * 娉ㄩ攢
+ */
+ public static final String LOGOUT = "Logout";
+
+ /**
+ * 娉ㄥ唽
+ */
+ public static final String REGISTER = "Register";
+
+ /**
+ * 鐧诲綍澶辫触
+ */
+ public static final String LOGIN_FAIL = "Error";
+
+ /**
+ * 鎵�鏈夋潈闄愭爣璇�
+ */
+ public static final String ALL_PERMISSION = "*:*:*";
+
+ /**
+ * 绠$悊鍛樿鑹叉潈闄愭爣璇�
+ */
+ public static final String SUPER_ADMIN = "admin";
+
+ /**
+ * 瑙掕壊鏉冮檺鍒嗛殧绗�
+ */
+ public static final String ROLE_DELIMETER = ",";
+
+ /**
+ * 鏉冮檺鏍囪瘑鍒嗛殧绗�
+ */
+ public static final String PERMISSION_DELIMETER = ",";
+
+ /**
+ * 楠岃瘉鐮佹湁鏁堟湡锛堝垎閽燂級
+ */
+ public static final Integer CAPTCHA_EXPIRATION = 2;
+
+ /**
+ * 浠ょ墝
+ */
+ public static final String TOKEN = "token";
+
+ /**
+ * 浠ょ墝鍓嶇紑
+ */
+ public static final String TOKEN_PREFIX = "Bearer ";
+
+ /**
+ * 浠ょ墝鍓嶇紑
+ */
+ public static final String LOGIN_USER_KEY = "login_user_key";
+
+ /**
+ * 鐢ㄦ埛ID
+ */
+ public static final String JWT_USERID = "userid";
+
+ /**
+ * 鐢ㄦ埛鍚嶇О
+ */
+ public static final String JWT_USERNAME = Claims.SUBJECT;
+
+ /**
+ * 鐢ㄦ埛澶村儚
+ */
+ public static final String JWT_AVATAR = "avatar";
+
+ /**
+ * 鍒涘缓鏃堕棿
+ */
+ public static final String JWT_CREATED = "created";
+
+ /**
+ * 鐢ㄦ埛鏉冮檺
+ */
+ public static final String JWT_AUTHORITIES = "authorities";
+
+ /**
+ * 璧勬簮鏄犲皠璺緞 鍓嶇紑
+ */
+ public static final String RESOURCE_PREFIX = "/profile";
+
+ /**
+ * RMI 杩滅▼鏂规硶璋冪敤
+ */
+ public static final String LOOKUP_RMI = "rmi:";
+
+ /**
+ * LDAP 杩滅▼鏂规硶璋冪敤
+ */
+ public static final String LOOKUP_LDAP = "ldap:";
+
+ /**
+ * LDAPS 杩滅▼鏂规硶璋冪敤
+ */
+ public static final String LOOKUP_LDAPS = "ldaps:";
+
+ /**
+ * 鑷姩璇嗗埆json瀵硅薄鐧藉悕鍗曢厤缃紙浠呭厑璁歌В鏋愮殑鍖呭悕锛岃寖鍥磋秺灏忚秺瀹夊叏锛�
+ */
+ public static final String[] JSON_WHITELIST_STR = { "org.springframework", "com.ruoyi" };
+
+ /**
+ * 瀹氭椂浠诲姟鐧藉悕鍗曢厤缃紙浠呭厑璁歌闂殑鍖呭悕锛屽鍏朵粬闇�瑕佸彲浠ヨ嚜琛屾坊鍔狅級
+ */
+ public static final String[] JOB_WHITELIST_STR = { "com.ruoyi.quartz.task" };
+
+ /**
+ * 瀹氭椂浠诲姟杩濊鐨勫瓧绗�
+ */
+ public static final String[] JOB_ERROR_STR = { "java.net.URL", "javax.naming.InitialContext", "org.yaml.snakeyaml",
+ "org.springframework", "org.apache", "com.ruoyi.common.utils.file", "com.ruoyi.common.config", "com.ruoyi.generator" };
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
new file mode 100644
index 0000000..7d899d4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/GenConstants.java
@@ -0,0 +1,117 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 浠g爜鐢熸垚閫氱敤甯搁噺
+ *
+ * @author ruoyi
+ */
+public class GenConstants
+{
+ /** 鍗曡〃锛堝鍒犳敼鏌ワ級 */
+ public static final String TPL_CRUD = "crud";
+
+ /** 鏍戣〃锛堝鍒犳敼鏌ワ級 */
+ public static final String TPL_TREE = "tree";
+
+ /** 涓诲瓙琛紙澧炲垹鏀规煡锛� */
+ public static final String TPL_SUB = "sub";
+
+ /** 鏍戠紪鐮佸瓧娈� */
+ public static final String TREE_CODE = "treeCode";
+
+ /** 鏍戠埗缂栫爜瀛楁 */
+ public static final String TREE_PARENT_CODE = "treeParentCode";
+
+ /** 鏍戝悕绉板瓧娈� */
+ public static final String TREE_NAME = "treeName";
+
+ /** 涓婄骇鑿滃崟ID瀛楁 */
+ public static final String PARENT_MENU_ID = "parentMenuId";
+
+ /** 涓婄骇鑿滃崟鍚嶇О瀛楁 */
+ public static final String PARENT_MENU_NAME = "parentMenuName";
+
+ /** 鏁版嵁搴撳瓧绗︿覆绫诲瀷 */
+ public static final String[] COLUMNTYPE_STR = { "char", "varchar", "nvarchar", "varchar2" };
+
+ /** 鏁版嵁搴撴枃鏈被鍨� */
+ public static final String[] COLUMNTYPE_TEXT = { "tinytext", "text", "mediumtext", "longtext" };
+
+ /** 鏁版嵁搴撴椂闂寸被鍨� */
+ public static final String[] COLUMNTYPE_TIME = { "datetime", "time", "date", "timestamp" };
+
+ /** 鏁版嵁搴撴暟瀛楃被鍨� */
+ public static final String[] COLUMNTYPE_NUMBER = { "tinyint", "smallint", "mediumint", "int", "number", "integer",
+ "bit", "bigint", "float", "double", "decimal" };
+
+ /** 椤甸潰涓嶉渶瑕佺紪杈戝瓧娈� */
+ public static final String[] COLUMNNAME_NOT_EDIT = { "id", "create_by", "create_time", "del_flag" };
+
+ /** 椤甸潰涓嶉渶瑕佹樉绀虹殑鍒楄〃瀛楁 */
+ public static final String[] COLUMNNAME_NOT_LIST = { "id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time" };
+
+ /** 椤甸潰涓嶉渶瑕佹煡璇㈠瓧娈� */
+ public static final String[] COLUMNNAME_NOT_QUERY = { "id", "create_by", "create_time", "del_flag", "update_by",
+ "update_time", "remark" };
+
+ /** Entity鍩虹被瀛楁 */
+ public static final String[] BASE_ENTITY = { "createBy", "createTime", "updateBy", "updateTime", "remark" };
+
+ /** Tree鍩虹被瀛楁 */
+ public static final String[] TREE_ENTITY = { "parentName", "parentId", "orderNum", "ancestors", "children" };
+
+ /** 鏂囨湰妗� */
+ public static final String HTML_INPUT = "input";
+
+ /** 鏂囨湰鍩� */
+ public static final String HTML_TEXTAREA = "textarea";
+
+ /** 涓嬫媺妗� */
+ public static final String HTML_SELECT = "select";
+
+ /** 鍗曢�夋 */
+ public static final String HTML_RADIO = "radio";
+
+ /** 澶嶉�夋 */
+ public static final String HTML_CHECKBOX = "checkbox";
+
+ /** 鏃ユ湡鎺т欢 */
+ public static final String HTML_DATETIME = "datetime";
+
+ /** 鍥剧墖涓婁紶鎺т欢 */
+ public static final String HTML_IMAGE_UPLOAD = "imageUpload";
+
+ /** 鏂囦欢涓婁紶鎺т欢 */
+ public static final String HTML_FILE_UPLOAD = "fileUpload";
+
+ /** 瀵屾枃鏈帶浠� */
+ public static final String HTML_EDITOR = "editor";
+
+ /** 瀛楃涓茬被鍨� */
+ public static final String TYPE_STRING = "String";
+
+ /** 鏁村瀷 */
+ public static final String TYPE_INTEGER = "Integer";
+
+ /** 闀挎暣鍨� */
+ public static final String TYPE_LONG = "Long";
+
+ /** 娴偣鍨� */
+ public static final String TYPE_DOUBLE = "Double";
+
+ /** 楂樼簿搴﹁绠楃被鍨� */
+ public static final String TYPE_BIGDECIMAL = "BigDecimal";
+
+ /** 鏃堕棿绫诲瀷 */
+ public static final String TYPE_DATE = "Date";
+
+ /** 妯$硦鏌ヨ */
+ public static final String QUERY_LIKE = "LIKE";
+
+ /** 鐩哥瓑鏌ヨ */
+ public static final String QUERY_EQ = "EQ";
+
+ /** 闇�瑕� */
+ public static final String REQUIRE = "1";
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
new file mode 100644
index 0000000..a983c77
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java
@@ -0,0 +1,94 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 杩斿洖鐘舵�佺爜
+ *
+ * @author ruoyi
+ */
+public class HttpStatus
+{
+ /**
+ * 鎿嶄綔鎴愬姛
+ */
+ public static final int SUCCESS = 200;
+
+ /**
+ * 瀵硅薄鍒涘缓鎴愬姛
+ */
+ public static final int CREATED = 201;
+
+ /**
+ * 璇锋眰宸茬粡琚帴鍙�
+ */
+ public static final int ACCEPTED = 202;
+
+ /**
+ * 鎿嶄綔宸茬粡鎵ц鎴愬姛锛屼絾鏄病鏈夎繑鍥炴暟鎹�
+ */
+ public static final int NO_CONTENT = 204;
+
+ /**
+ * 璧勬簮宸茶绉婚櫎
+ */
+ public static final int MOVED_PERM = 301;
+
+ /**
+ * 閲嶅畾鍚�
+ */
+ public static final int SEE_OTHER = 303;
+
+ /**
+ * 璧勬簮娌℃湁琚慨鏀�
+ */
+ public static final int NOT_MODIFIED = 304;
+
+ /**
+ * 鍙傛暟鍒楄〃閿欒锛堢己灏戯紝鏍煎紡涓嶅尮閰嶏級
+ */
+ public static final int BAD_REQUEST = 400;
+
+ /**
+ * 鏈巿鏉�
+ */
+ public static final int UNAUTHORIZED = 401;
+
+ /**
+ * 璁块棶鍙楅檺锛屾巿鏉冭繃鏈�
+ */
+ public static final int FORBIDDEN = 403;
+
+ /**
+ * 璧勬簮锛屾湇鍔℃湭鎵惧埌
+ */
+ public static final int NOT_FOUND = 404;
+
+ /**
+ * 涓嶅厑璁哥殑http鏂规硶
+ */
+ public static final int BAD_METHOD = 405;
+
+ /**
+ * 璧勬簮鍐茬獊锛屾垨鑰呰祫婧愯閿�
+ */
+ public static final int CONFLICT = 409;
+
+ /**
+ * 涓嶆敮鎸佺殑鏁版嵁锛屽獟浣撶被鍨�
+ */
+ public static final int UNSUPPORTED_TYPE = 415;
+
+ /**
+ * 绯荤粺鍐呴儴閿欒
+ */
+ public static final int ERROR = 500;
+
+ /**
+ * 鎺ュ彛鏈疄鐜�
+ */
+ public static final int NOT_IMPLEMENTED = 501;
+
+ /**
+ * 绯荤粺璀﹀憡娑堟伅
+ */
+ public static final int WARN = 601;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
new file mode 100644
index 0000000..62ad815
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/ScheduleConstants.java
@@ -0,0 +1,50 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 浠诲姟璋冨害閫氱敤甯搁噺
+ *
+ * @author ruoyi
+ */
+public class ScheduleConstants
+{
+ public static final String TASK_CLASS_NAME = "TASK_CLASS_NAME";
+
+ /** 鎵ц鐩爣key */
+ public static final String TASK_PROPERTIES = "TASK_PROPERTIES";
+
+ /** 榛樿 */
+ public static final String MISFIRE_DEFAULT = "0";
+
+ /** 绔嬪嵆瑙﹀彂鎵ц */
+ public static final String MISFIRE_IGNORE_MISFIRES = "1";
+
+ /** 瑙﹀彂涓�娆℃墽琛� */
+ public static final String MISFIRE_FIRE_AND_PROCEED = "2";
+
+ /** 涓嶈Е鍙戠珛鍗虫墽琛� */
+ public static final String MISFIRE_DO_NOTHING = "3";
+
+ public enum Status
+ {
+ /**
+ * 姝e父
+ */
+ NORMAL("0"),
+ /**
+ * 鏆傚仠
+ */
+ PAUSE("1");
+
+ private String value;
+
+ private Status(String value)
+ {
+ this.value = value;
+ }
+
+ public String getValue()
+ {
+ return value;
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
new file mode 100644
index 0000000..8dc7faa
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/UserConstants.java
@@ -0,0 +1,81 @@
+package com.ruoyi.common.constant;
+
+/**
+ * 鐢ㄦ埛甯搁噺淇℃伅
+ *
+ * @author ruoyi
+ */
+public class UserConstants
+{
+ /**
+ * 骞冲彴鍐呯郴缁熺敤鎴风殑鍞竴鏍囧織
+ */
+ public static final String SYS_USER = "SYS_USER";
+
+ /** 姝e父鐘舵�� */
+ public static final String NORMAL = "0";
+
+ /** 寮傚父鐘舵�� */
+ public static final String EXCEPTION = "1";
+
+ /** 鐢ㄦ埛灏佺鐘舵�� */
+ public static final String USER_DISABLE = "1";
+
+ /** 瑙掕壊姝e父鐘舵�� */
+ public static final String ROLE_NORMAL = "0";
+
+ /** 瑙掕壊灏佺鐘舵�� */
+ public static final String ROLE_DISABLE = "1";
+
+ /** 閮ㄩ棬姝e父鐘舵�� */
+ public static final String DEPT_NORMAL = "0";
+
+ /** 閮ㄩ棬鍋滅敤鐘舵�� */
+ public static final String DEPT_DISABLE = "1";
+
+ /** 瀛楀吀姝e父鐘舵�� */
+ public static final String DICT_NORMAL = "0";
+
+ /** 鏄惁涓虹郴缁熼粯璁わ紙鏄級 */
+ public static final String YES = "Y";
+
+ /** 鏄惁鑿滃崟澶栭摼锛堟槸锛� */
+ public static final String YES_FRAME = "0";
+
+ /** 鏄惁鑿滃崟澶栭摼锛堝惁锛� */
+ public static final String NO_FRAME = "1";
+
+ /** 鑿滃崟绫诲瀷锛堢洰褰曪級 */
+ public static final String TYPE_DIR = "M";
+
+ /** 鑿滃崟绫诲瀷锛堣彍鍗曪級 */
+ public static final String TYPE_MENU = "C";
+
+ /** 鑿滃崟绫诲瀷锛堟寜閽級 */
+ public static final String TYPE_BUTTON = "F";
+
+ /** Layout缁勪欢鏍囪瘑 */
+ public final static String LAYOUT = "Layout";
+
+ /** ParentView缁勪欢鏍囪瘑 */
+ public final static String PARENT_VIEW = "ParentView";
+
+ /** InnerLink缁勪欢鏍囪瘑 */
+ public final static String INNER_LINK = "InnerLink";
+
+ /** 鏍¢獙鏄惁鍞竴鐨勮繑鍥炴爣璇� */
+ public final static boolean UNIQUE = true;
+ public final static boolean NOT_UNIQUE = false;
+
+ /**
+ * 鐢ㄦ埛鍚嶉暱搴﹂檺鍒�
+ */
+ public static final int USERNAME_MIN_LENGTH = 2;
+ public static final int USERNAME_MAX_LENGTH = 20;
+
+ /**
+ * 瀵嗙爜闀垮害闄愬埗
+ */
+ public static final int PASSWORD_MIN_LENGTH = 5;
+ public static final int PASSWORD_MAX_LENGTH = 20;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
new file mode 100644
index 0000000..b29a15e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/controller/BaseController.java
@@ -0,0 +1,202 @@
+package com.ruoyi.common.core.controller;
+
+import java.beans.PropertyEditorSupport;
+import java.util.Date;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.PageUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+
+/**
+ * web灞傞�氱敤鏁版嵁澶勭悊
+ *
+ * @author ruoyi
+ */
+public class BaseController
+{
+ protected final Logger logger = LoggerFactory.getLogger(this.getClass());
+
+ /**
+ * 灏嗗墠鍙颁紶閫掕繃鏉ョ殑鏃ユ湡鏍煎紡鐨勫瓧绗︿覆锛岃嚜鍔ㄨ浆鍖栦负Date绫诲瀷
+ */
+ @InitBinder
+ public void initBinder(WebDataBinder binder)
+ {
+ // Date 绫诲瀷杞崲
+ binder.registerCustomEditor(Date.class, new PropertyEditorSupport()
+ {
+ @Override
+ public void setAsText(String text)
+ {
+ setValue(DateUtils.parseDate(text));
+ }
+ });
+ }
+
+ /**
+ * 璁剧疆璇锋眰鍒嗛〉鏁版嵁
+ */
+ protected void startPage()
+ {
+ PageUtils.startPage();
+ }
+
+ /**
+ * 璁剧疆璇锋眰鎺掑簭鏁版嵁
+ */
+ protected void startOrderBy()
+ {
+ PageDomain pageDomain = TableSupport.buildPageRequest();
+ if (StringUtils.isNotEmpty(pageDomain.getOrderBy()))
+ {
+ String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+ PageHelper.orderBy(orderBy);
+ }
+ }
+
+ /**
+ * 娓呯悊鍒嗛〉鐨勭嚎绋嬪彉閲�
+ */
+ protected void clearPage()
+ {
+ PageUtils.clearPage();
+ }
+
+ /**
+ * 鍝嶅簲璇锋眰鍒嗛〉鏁版嵁
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ protected TableDataInfo getDataTable(List<?> list)
+ {
+ TableDataInfo rspData = new TableDataInfo();
+ rspData.setCode(HttpStatus.SUCCESS);
+ rspData.setMsg("鏌ヨ鎴愬姛");
+ rspData.setRows(list);
+ rspData.setTotal(new PageInfo(list).getTotal());
+ return rspData;
+ }
+
+ /**
+ * 杩斿洖鎴愬姛
+ */
+ public AjaxResult success()
+ {
+ return AjaxResult.success();
+ }
+
+ /**
+ * 杩斿洖澶辫触娑堟伅
+ */
+ public AjaxResult error()
+ {
+ return AjaxResult.error();
+ }
+
+ /**
+ * 杩斿洖鎴愬姛娑堟伅
+ */
+ public AjaxResult success(String message)
+ {
+ return AjaxResult.success(message);
+ }
+
+ /**
+ * 杩斿洖鎴愬姛娑堟伅
+ */
+ public AjaxResult success(Object data)
+ {
+ return AjaxResult.success(data);
+ }
+
+ /**
+ * 杩斿洖澶辫触娑堟伅
+ */
+ public AjaxResult error(String message)
+ {
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 杩斿洖璀﹀憡娑堟伅
+ */
+ public AjaxResult warn(String message)
+ {
+ return AjaxResult.warn(message);
+ }
+
+ /**
+ * 鍝嶅簲杩斿洖缁撴灉
+ *
+ * @param rows 褰卞搷琛屾暟
+ * @return 鎿嶄綔缁撴灉
+ */
+ protected AjaxResult toAjax(int rows)
+ {
+ return rows > 0 ? AjaxResult.success() : AjaxResult.error();
+ }
+
+ /**
+ * 鍝嶅簲杩斿洖缁撴灉
+ *
+ * @param result 缁撴灉
+ * @return 鎿嶄綔缁撴灉
+ */
+ protected AjaxResult toAjax(boolean result)
+ {
+ return result ? success() : error();
+ }
+
+ /**
+ * 椤甸潰璺宠浆
+ */
+ public String redirect(String url)
+ {
+ return StringUtils.format("redirect:{}", url);
+ }
+
+ /**
+ * 鑾峰彇鐢ㄦ埛缂撳瓨淇℃伅
+ */
+ public LoginUser getLoginUser()
+ {
+ return SecurityUtils.getLoginUser();
+ }
+
+ /**
+ * 鑾峰彇鐧诲綍鐢ㄦ埛id
+ */
+ public Long getUserId()
+ {
+ return getLoginUser().getUserId();
+ }
+
+ /**
+ * 鑾峰彇鐧诲綍閮ㄩ棬id
+ */
+ public Long getDeptId()
+ {
+ return getLoginUser().getDeptId();
+ }
+
+ /**
+ * 鑾峰彇鐧诲綍鐢ㄦ埛鍚�
+ */
+ public String getUsername()
+ {
+ return getLoginUser().getUsername();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java
new file mode 100644
index 0000000..81c92c0
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/AjaxResult.java
@@ -0,0 +1,216 @@
+package com.ruoyi.common.core.domain;
+
+import java.util.HashMap;
+import java.util.Objects;
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 鎿嶄綔娑堟伅鎻愰啋
+ *
+ * @author ruoyi
+ */
+public class AjaxResult extends HashMap<String, Object>
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鐘舵�佺爜 */
+ public static final String CODE_TAG = "code";
+
+ /** 杩斿洖鍐呭 */
+ public static final String MSG_TAG = "msg";
+
+ /** 鏁版嵁瀵硅薄 */
+ public static final String DATA_TAG = "data";
+
+ /**
+ * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄锛屼娇鍏惰〃绀轰竴涓┖娑堟伅銆�
+ */
+ public AjaxResult()
+ {
+ }
+
+ /**
+ * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+ *
+ * @param code 鐘舵�佺爜
+ * @param msg 杩斿洖鍐呭
+ */
+ public AjaxResult(int code, String msg)
+ {
+ super.put(CODE_TAG, code);
+ super.put(MSG_TAG, msg);
+ }
+
+ /**
+ * 鍒濆鍖栦竴涓柊鍒涘缓鐨� AjaxResult 瀵硅薄
+ *
+ * @param code 鐘舵�佺爜
+ * @param msg 杩斿洖鍐呭
+ * @param data 鏁版嵁瀵硅薄
+ */
+ public AjaxResult(int code, String msg, Object data)
+ {
+ super.put(CODE_TAG, code);
+ super.put(MSG_TAG, msg);
+ if (StringUtils.isNotNull(data))
+ {
+ super.put(DATA_TAG, data);
+ }
+ }
+
+ /**
+ * 杩斿洖鎴愬姛娑堟伅
+ *
+ * @return 鎴愬姛娑堟伅
+ */
+ public static AjaxResult success()
+ {
+ return AjaxResult.success("鎿嶄綔鎴愬姛");
+ }
+
+ /**
+ * 杩斿洖鎴愬姛鏁版嵁
+ *
+ * @return 鎴愬姛娑堟伅
+ */
+ public static AjaxResult success(Object data)
+ {
+ return AjaxResult.success("鎿嶄綔鎴愬姛", data);
+ }
+
+ /**
+ * 杩斿洖鎴愬姛娑堟伅
+ *
+ * @param msg 杩斿洖鍐呭
+ * @return 鎴愬姛娑堟伅
+ */
+ public static AjaxResult success(String msg)
+ {
+ return AjaxResult.success(msg, null);
+ }
+
+ /**
+ * 杩斿洖鎴愬姛娑堟伅
+ *
+ * @param msg 杩斿洖鍐呭
+ * @param data 鏁版嵁瀵硅薄
+ * @return 鎴愬姛娑堟伅
+ */
+ public static AjaxResult success(String msg, Object data)
+ {
+ return new AjaxResult(HttpStatus.SUCCESS, msg, data);
+ }
+
+ /**
+ * 杩斿洖璀﹀憡娑堟伅
+ *
+ * @param msg 杩斿洖鍐呭
+ * @return 璀﹀憡娑堟伅
+ */
+ public static AjaxResult warn(String msg)
+ {
+ return AjaxResult.warn(msg, null);
+ }
+
+ /**
+ * 杩斿洖璀﹀憡娑堟伅
+ *
+ * @param msg 杩斿洖鍐呭
+ * @param data 鏁版嵁瀵硅薄
+ * @return 璀﹀憡娑堟伅
+ */
+ public static AjaxResult warn(String msg, Object data)
+ {
+ return new AjaxResult(HttpStatus.WARN, msg, data);
+ }
+
+ /**
+ * 杩斿洖閿欒娑堟伅
+ *
+ * @return 閿欒娑堟伅
+ */
+ public static AjaxResult error()
+ {
+ return AjaxResult.error("鎿嶄綔澶辫触");
+ }
+
+ /**
+ * 杩斿洖閿欒娑堟伅
+ *
+ * @param msg 杩斿洖鍐呭
+ * @return 閿欒娑堟伅
+ */
+ public static AjaxResult error(String msg)
+ {
+ return AjaxResult.error(msg, null);
+ }
+
+ /**
+ * 杩斿洖閿欒娑堟伅
+ *
+ * @param msg 杩斿洖鍐呭
+ * @param data 鏁版嵁瀵硅薄
+ * @return 閿欒娑堟伅
+ */
+ public static AjaxResult error(String msg, Object data)
+ {
+ return new AjaxResult(HttpStatus.ERROR, msg, data);
+ }
+
+ /**
+ * 杩斿洖閿欒娑堟伅
+ *
+ * @param code 鐘舵�佺爜
+ * @param msg 杩斿洖鍐呭
+ * @return 閿欒娑堟伅
+ */
+ public static AjaxResult error(int code, String msg)
+ {
+ return new AjaxResult(code, msg, null);
+ }
+
+ /**
+ * 鏄惁涓烘垚鍔熸秷鎭�
+ *
+ * @return 缁撴灉
+ */
+ public boolean isSuccess()
+ {
+ return Objects.equals(HttpStatus.SUCCESS, this.get(CODE_TAG));
+ }
+
+ /**
+ * 鏄惁涓鸿鍛婃秷鎭�
+ *
+ * @return 缁撴灉
+ */
+ public boolean isWarn()
+ {
+ return Objects.equals(HttpStatus.WARN, this.get(CODE_TAG));
+ }
+
+ /**
+ * 鏄惁涓洪敊璇秷鎭�
+ *
+ * @return 缁撴灉
+ */
+ public boolean isError()
+ {
+ return Objects.equals(HttpStatus.ERROR, this.get(CODE_TAG));
+ }
+
+ /**
+ * 鏂逛究閾惧紡璋冪敤
+ *
+ * @param key 閿�
+ * @param value 鍊�
+ * @return 鏁版嵁瀵硅薄
+ */
+ @Override
+ public AjaxResult put(String key, Object value)
+ {
+ super.put(key, value);
+ return this;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
new file mode 100644
index 0000000..15bf66b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/BaseEntity.java
@@ -0,0 +1,118 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+
+/**
+ * Entity鍩虹被
+ *
+ * @author ruoyi
+ */
+public class BaseEntity implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鎼滅储鍊� */
+ @JsonIgnore
+ private String searchValue;
+
+ /** 鍒涘缓鑰� */
+ private String createBy;
+
+ /** 鍒涘缓鏃堕棿 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date createTime;
+
+ /** 鏇存柊鑰� */
+ private String updateBy;
+
+ /** 鏇存柊鏃堕棿 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private Date updateTime;
+
+ /** 澶囨敞 */
+ private String remark;
+
+ /** 璇锋眰鍙傛暟 */
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ private Map<String, Object> params;
+
+ public String getSearchValue()
+ {
+ return searchValue;
+ }
+
+ public void setSearchValue(String searchValue)
+ {
+ this.searchValue = searchValue;
+ }
+
+ public String getCreateBy()
+ {
+ return createBy;
+ }
+
+ public void setCreateBy(String createBy)
+ {
+ this.createBy = createBy;
+ }
+
+ public Date getCreateTime()
+ {
+ return createTime;
+ }
+
+ public void setCreateTime(Date createTime)
+ {
+ this.createTime = createTime;
+ }
+
+ public String getUpdateBy()
+ {
+ return updateBy;
+ }
+
+ public void setUpdateBy(String updateBy)
+ {
+ this.updateBy = updateBy;
+ }
+
+ public Date getUpdateTime()
+ {
+ return updateTime;
+ }
+
+ public void setUpdateTime(Date updateTime)
+ {
+ this.updateTime = updateTime;
+ }
+
+ public String getRemark()
+ {
+ return remark;
+ }
+
+ public void setRemark(String remark)
+ {
+ this.remark = remark;
+ }
+
+ public Map<String, Object> getParams()
+ {
+ if (params == null)
+ {
+ params = new HashMap<>();
+ }
+ return params;
+ }
+
+ public void setParams(Map<String, Object> params)
+ {
+ this.params = params;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/MinioResult.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/MinioResult.java
new file mode 100644
index 0000000..07b7eef
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/MinioResult.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.core.domain;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class MinioResult {
+ @ApiModelProperty("minio涓殑鏂囦欢鍚嶇О")
+ private String bucketFileName;
+
+ @ApiModelProperty("婧愭枃浠跺悕绉�")
+ private String originalName;
+
+ @ApiModelProperty("棰勮璺緞")
+ private String previewExpiry;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java
new file mode 100644
index 0000000..2703c59
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java
@@ -0,0 +1,115 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+import com.ruoyi.common.constant.HttpStatus;
+
+/**
+ * 鍝嶅簲淇℃伅涓讳綋
+ *
+ * @author ruoyi
+ */
+public class Result<T> implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鎴愬姛 */
+ public static final int SUCCESS = HttpStatus.SUCCESS;
+
+ /** 澶辫触 */
+ public static final int FAIL = HttpStatus.ERROR;
+
+ private int code;
+
+ private String msg;
+
+ private T data;
+
+ public static <T> Result<T> success()
+ {
+ return restResult(null, SUCCESS, "鎿嶄綔鎴愬姛");
+ }
+
+ public static <T> Result<T> success(T data)
+ {
+ return restResult(data, SUCCESS, "鎿嶄綔鎴愬姛");
+ }
+
+ public static <T> Result<T> success(T data, String msg)
+ {
+ return restResult(data, SUCCESS, msg);
+ }
+
+ public static <T> Result<T> fail()
+ {
+ return restResult(null, FAIL, "鎿嶄綔澶辫触");
+ }
+
+ public static <T> Result<T> fail(String msg)
+ {
+ return restResult(null, FAIL, msg);
+ }
+
+ public static <T> Result<T> fail(T data)
+ {
+ return restResult(data, FAIL, "鎿嶄綔澶辫触");
+ }
+
+ public static <T> Result<T> fail(T data, String msg)
+ {
+ return restResult(data, FAIL, msg);
+ }
+
+ public static <T> Result<T> fail(int code, String msg)
+ {
+ return restResult(null, code, msg);
+ }
+
+ private static <T> Result<T> restResult(T data, int code, String msg)
+ {
+ Result<T> apiResult = new Result<>();
+ apiResult.setCode(code);
+ apiResult.setData(data);
+ apiResult.setMsg(msg);
+ return apiResult;
+ }
+
+ public int getCode()
+ {
+ return code;
+ }
+
+ public void setCode(int code)
+ {
+ this.code = code;
+ }
+
+ public String getMsg()
+ {
+ return msg;
+ }
+
+ public void setMsg(String msg)
+ {
+ this.msg = msg;
+ }
+
+ public T getData()
+ {
+ return data;
+ }
+
+ public void setData(T data)
+ {
+ this.data = data;
+ }
+
+ public static <T> Boolean isError(Result<T> ret)
+ {
+ return !isSuccess(ret);
+ }
+
+ public static <T> Boolean isSuccess(Result<T> ret)
+ {
+ return Result.SUCCESS == ret.getCode();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
new file mode 100644
index 0000000..a180a18
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeEntity.java
@@ -0,0 +1,79 @@
+package com.ruoyi.common.core.domain;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Tree鍩虹被
+ *
+ * @author ruoyi
+ */
+public class TreeEntity extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鐖惰彍鍗曞悕绉� */
+ private String parentName;
+
+ /** 鐖惰彍鍗旾D */
+ private Long parentId;
+
+ /** 鏄剧ず椤哄簭 */
+ private Integer orderNum;
+
+ /** 绁栫骇鍒楄〃 */
+ private String ancestors;
+
+ /** 瀛愰儴闂� */
+ private List<?> children = new ArrayList<>();
+
+ public String getParentName()
+ {
+ return parentName;
+ }
+
+ public void setParentName(String parentName)
+ {
+ this.parentName = parentName;
+ }
+
+ public Long getParentId()
+ {
+ return parentId;
+ }
+
+ public void setParentId(Long parentId)
+ {
+ this.parentId = parentId;
+ }
+
+ public Integer getOrderNum()
+ {
+ return orderNum;
+ }
+
+ public void setOrderNum(Integer orderNum)
+ {
+ this.orderNum = orderNum;
+ }
+
+ public String getAncestors()
+ {
+ return ancestors;
+ }
+
+ public void setAncestors(String ancestors)
+ {
+ this.ancestors = ancestors;
+ }
+
+ public List<?> getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List<?> children)
+ {
+ this.children = children;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
new file mode 100644
index 0000000..ae25df2
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/TreeSelect.java
@@ -0,0 +1,93 @@
+package com.ruoyi.common.core.domain;
+
+import java.io.Serializable;
+import java.util.List;
+import java.util.stream.Collectors;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * Treeselect鏍戠粨鏋勫疄浣撶被
+ *
+ * @author ruoyi
+ */
+public class TreeSelect implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鑺傜偣ID */
+ private Long id;
+
+ /** 鑺傜偣鍚嶇О */
+ private String label;
+
+ /** 鑺傜偣绂佺敤 */
+ private boolean disabled = false;
+
+ /** 瀛愯妭鐐� */
+ @JsonInclude(JsonInclude.Include.NON_EMPTY)
+ private List<TreeSelect> children;
+
+ public TreeSelect()
+ {
+
+ }
+
+ public TreeSelect(SysDept dept)
+ {
+ this.id = dept.getDeptId();
+ this.label = dept.getDeptName();
+ this.disabled = StringUtils.equals(UserConstants.DEPT_DISABLE, dept.getStatus());
+ this.children = dept.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ public TreeSelect(SysMenu menu)
+ {
+ this.id = menu.getMenuId();
+ this.label = menu.getMenuName();
+ this.children = menu.getChildren().stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ public Long getId()
+ {
+ return id;
+ }
+
+ public void setId(Long id)
+ {
+ this.id = id;
+ }
+
+ public String getLabel()
+ {
+ return label;
+ }
+
+ public void setLabel(String label)
+ {
+ this.label = label;
+ }
+
+ public boolean isDisabled()
+ {
+ return disabled;
+ }
+
+ public void setDisabled(boolean disabled)
+ {
+ this.disabled = disabled;
+ }
+
+ public List<TreeSelect> getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List<TreeSelect> children)
+ {
+ this.children = children;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Custom.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Custom.java
new file mode 100644
index 0000000..97d05ba
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/Custom.java
@@ -0,0 +1,65 @@
+package com.ruoyi.common.core.domain.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+@TableName("custom")
+public class Custom implements Serializable {
+
+ @ApiModelProperty(value = "涓婚敭")
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "瀹㈡埛鍚嶇О")
+ private String company;
+
+ @ApiModelProperty(value = "鍗曚綅鍦板潃")
+ private String address;
+
+ @ApiModelProperty(value = "宸ュ巶鍩�")
+ private String code;
+
+ @ApiModelProperty(value = "瀹㈡埛缂栧彿")
+ private String code2;
+
+ @TableField(fill = FieldFill.INSERT)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime createTime;
+
+ @ApiModelProperty(value = "鍒涘缓鏃ユ湡")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ private LocalDateTime updateTime;
+
+ @ApiModelProperty(value = "鍒涘缓鐢ㄦ埛")
+ @TableField(fill = FieldFill.INSERT)
+ private Integer createUser;
+
+ @ApiModelProperty(value = "鏇存柊鐢ㄦ埛")
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ private Integer updateUser;
+
+ @ApiModelProperty(value = "瀹㈡埛鍗曚綅EN")
+ private String companyEn;
+
+ @ApiModelProperty(value = "鍗曚綅鍦板潃EN")
+ private String addressEn;
+
+ @ApiModelProperty(value = "鍔犳�ラ搴�")
+ private Integer num;
+
+ @ApiModelProperty(value = "鍗曚綅鐢佃瘽")
+ private String phone;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
new file mode 100644
index 0000000..fb18c5c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDept.java
@@ -0,0 +1,203 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.constraints.Email;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 閮ㄩ棬琛� sys_dept
+ *
+ * @author ruoyi
+ */
+public class SysDept extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 閮ㄩ棬ID */
+ private Long deptId;
+
+ /** 鐖堕儴闂↖D */
+ private Long parentId;
+
+ /** 绁栫骇鍒楄〃 */
+ private String ancestors;
+
+ /** 閮ㄩ棬鍚嶇О */
+ private String deptName;
+
+ /** 鏄剧ず椤哄簭 */
+ private Integer orderNum;
+
+ /** 璐熻矗浜� */
+ private String leader;
+
+ /** 鑱旂郴鐢佃瘽 */
+ private String phone;
+
+ /** 閭 */
+ private String email;
+
+ /** 閮ㄩ棬鐘舵��:0姝e父,1鍋滅敤 */
+ private String status;
+
+ /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+ private String delFlag;
+
+ /** 鐖堕儴闂ㄥ悕绉� */
+ private String parentName;
+
+ /** 瀛愰儴闂� */
+ private List<SysDept> children = new ArrayList<SysDept>();
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ public Long getParentId()
+ {
+ return parentId;
+ }
+
+ public void setParentId(Long parentId)
+ {
+ this.parentId = parentId;
+ }
+
+ public String getAncestors()
+ {
+ return ancestors;
+ }
+
+ public void setAncestors(String ancestors)
+ {
+ this.ancestors = ancestors;
+ }
+
+ @NotBlank(message = "閮ㄩ棬鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 30, message = "閮ㄩ棬鍚嶇О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+ public Integer getOrderNum()
+ {
+ return orderNum;
+ }
+
+ public void setOrderNum(Integer orderNum)
+ {
+ this.orderNum = orderNum;
+ }
+
+ public String getLeader()
+ {
+ return leader;
+ }
+
+ public void setLeader(String leader)
+ {
+ this.leader = leader;
+ }
+
+ @Size(min = 0, max = 11, message = "鑱旂郴鐢佃瘽闀垮害涓嶈兘瓒呰繃11涓瓧绗�")
+ public String getPhone()
+ {
+ return phone;
+ }
+
+ public void setPhone(String phone)
+ {
+ this.phone = phone;
+ }
+
+ @Email(message = "閭鏍煎紡涓嶆纭�")
+ @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+ public String getEmail()
+ {
+ return email;
+ }
+
+ public void setEmail(String email)
+ {
+ this.email = email;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getDelFlag()
+ {
+ return delFlag;
+ }
+
+ public void setDelFlag(String delFlag)
+ {
+ this.delFlag = delFlag;
+ }
+
+ public String getParentName()
+ {
+ return parentName;
+ }
+
+ public void setParentName(String parentName)
+ {
+ this.parentName = parentName;
+ }
+
+ public List<SysDept> getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List<SysDept> children)
+ {
+ this.children = children;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("deptId", getDeptId())
+ .append("parentId", getParentId())
+ .append("ancestors", getAncestors())
+ .append("deptName", getDeptName())
+ .append("orderNum", getOrderNum())
+ .append("leader", getLeader())
+ .append("phone", getPhone())
+ .append("email", getEmail())
+ .append("status", getStatus())
+ .append("delFlag", getDelFlag())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
new file mode 100644
index 0000000..738f12c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictData.java
@@ -0,0 +1,176 @@
+package com.ruoyi.common.core.domain.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 瀛楀吀鏁版嵁琛� sys_dict_data
+ *
+ * @author ruoyi
+ */
+public class SysDictData extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 瀛楀吀缂栫爜 */
+ @Excel(name = "瀛楀吀缂栫爜", cellType = ColumnType.NUMERIC)
+ private Long dictCode;
+
+ /** 瀛楀吀鎺掑簭 */
+ @Excel(name = "瀛楀吀鎺掑簭", cellType = ColumnType.NUMERIC)
+ private Long dictSort;
+
+ /** 瀛楀吀鏍囩 */
+ @Excel(name = "瀛楀吀鏍囩")
+ private String dictLabel;
+
+ /** 瀛楀吀閿�� */
+ @Excel(name = "瀛楀吀閿��")
+ private String dictValue;
+
+ /** 瀛楀吀绫诲瀷 */
+ @Excel(name = "瀛楀吀绫诲瀷")
+ private String dictType;
+
+ /** 鏍峰紡灞炴�э紙鍏朵粬鏍峰紡鎵╁睍锛� */
+ private String cssClass;
+
+ /** 琛ㄦ牸瀛楀吀鏍峰紡 */
+ private String listClass;
+
+ /** 鏄惁榛樿锛圷鏄� N鍚︼級 */
+ @Excel(name = "鏄惁榛樿", readConverterExp = "Y=鏄�,N=鍚�")
+ private String isDefault;
+
+ /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+ @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+ private String status;
+
+ public Long getDictCode()
+ {
+ return dictCode;
+ }
+
+ public void setDictCode(Long dictCode)
+ {
+ this.dictCode = dictCode;
+ }
+
+ public Long getDictSort()
+ {
+ return dictSort;
+ }
+
+ public void setDictSort(Long dictSort)
+ {
+ this.dictSort = dictSort;
+ }
+
+ @NotBlank(message = "瀛楀吀鏍囩涓嶈兘涓虹┖")
+ @Size(min = 0, max = 100, message = "瀛楀吀鏍囩闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+ public String getDictLabel()
+ {
+ return dictLabel;
+ }
+
+ public void setDictLabel(String dictLabel)
+ {
+ this.dictLabel = dictLabel;
+ }
+
+ @NotBlank(message = "瀛楀吀閿�间笉鑳戒负绌�")
+ @Size(min = 0, max = 100, message = "瀛楀吀閿�奸暱搴︿笉鑳借秴杩�100涓瓧绗�")
+ public String getDictValue()
+ {
+ return dictValue;
+ }
+
+ public void setDictValue(String dictValue)
+ {
+ this.dictValue = dictValue;
+ }
+
+ @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
+ @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+ public String getDictType()
+ {
+ return dictType;
+ }
+
+ public void setDictType(String dictType)
+ {
+ this.dictType = dictType;
+ }
+
+ @Size(min = 0, max = 100, message = "鏍峰紡灞炴�ч暱搴︿笉鑳借秴杩�100涓瓧绗�")
+ public String getCssClass()
+ {
+ return cssClass;
+ }
+
+ public void setCssClass(String cssClass)
+ {
+ this.cssClass = cssClass;
+ }
+
+ public String getListClass()
+ {
+ return listClass;
+ }
+
+ public void setListClass(String listClass)
+ {
+ this.listClass = listClass;
+ }
+
+ public boolean getDefault()
+ {
+ return UserConstants.YES.equals(this.isDefault);
+ }
+
+ public String getIsDefault()
+ {
+ return isDefault;
+ }
+
+ public void setIsDefault(String isDefault)
+ {
+ this.isDefault = isDefault;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("dictCode", getDictCode())
+ .append("dictSort", getDictSort())
+ .append("dictLabel", getDictLabel())
+ .append("dictValue", getDictValue())
+ .append("dictType", getDictType())
+ .append("cssClass", getCssClass())
+ .append("listClass", getListClass())
+ .append("isDefault", getIsDefault())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java
new file mode 100644
index 0000000..e324fcf
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysDictType.java
@@ -0,0 +1,96 @@
+package com.ruoyi.common.core.domain.entity;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Pattern;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 瀛楀吀绫诲瀷琛� sys_dict_type
+ *
+ * @author ruoyi
+ */
+public class SysDictType extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 瀛楀吀涓婚敭 */
+ @Excel(name = "瀛楀吀涓婚敭", cellType = ColumnType.NUMERIC)
+ private Long dictId;
+
+ /** 瀛楀吀鍚嶇О */
+ @Excel(name = "瀛楀吀鍚嶇О")
+ private String dictName;
+
+ /** 瀛楀吀绫诲瀷 */
+ @Excel(name = "瀛楀吀绫诲瀷")
+ private String dictType;
+
+ /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+ @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+ private String status;
+
+ public Long getDictId()
+ {
+ return dictId;
+ }
+
+ public void setDictId(Long dictId)
+ {
+ this.dictId = dictId;
+ }
+
+ @NotBlank(message = "瀛楀吀鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷鍚嶇О闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+ public String getDictName()
+ {
+ return dictName;
+ }
+
+ public void setDictName(String dictName)
+ {
+ this.dictName = dictName;
+ }
+
+ @NotBlank(message = "瀛楀吀绫诲瀷涓嶈兘涓虹┖")
+ @Size(min = 0, max = 100, message = "瀛楀吀绫诲瀷绫诲瀷闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+ @Pattern(regexp = "^[a-z][a-z0-9_]*$", message = "瀛楀吀绫诲瀷蹇呴』浠ュ瓧姣嶅紑澶达紝涓斿彧鑳戒负锛堝皬鍐欏瓧姣嶏紝鏁板瓧锛屼笅婊戠嚎锛�")
+ public String getDictType()
+ {
+ return dictType;
+ }
+
+ public void setDictType(String dictType)
+ {
+ this.dictType = dictType;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("dictId", getDictId())
+ .append("dictName", getDictName())
+ .append("dictType", getDictType())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
new file mode 100644
index 0000000..ad73692
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysMenu.java
@@ -0,0 +1,274 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 鑿滃崟鏉冮檺琛� sys_menu
+ *
+ * @author ruoyi
+ */
+public class SysMenu extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鑿滃崟ID */
+ private Long menuId;
+
+ /** 鑿滃崟鍚嶇О */
+ private String menuName;
+
+ /** 鐖惰彍鍗曞悕绉� */
+ private String parentName;
+
+ /** 鐖惰彍鍗旾D */
+ private Long parentId;
+
+ /** 鏄剧ず椤哄簭 */
+ private Integer orderNum;
+
+ /** 璺敱鍦板潃 */
+ private String path;
+
+ /** 缁勪欢璺緞 */
+ private String component;
+
+ /** 璺敱鍙傛暟 */
+ private String query;
+
+ /** 璺敱鍚嶇О锛岄粯璁ゅ拰璺敱鍦板潃鐩稿悓鐨勯┘宄版牸寮忥紙娉ㄦ剰锛氬洜涓簐ue3鐗堟湰鐨剅outer浼氬垹闄ゅ悕绉扮浉鍚岃矾鐢憋紝涓洪伩鍏嶅悕瀛楃殑鍐茬獊锛岀壒娈婃儏鍐靛彲浠ヨ嚜瀹氫箟锛� */
+ private String routeName;
+
+ /** 鏄惁涓哄閾撅紙0鏄� 1鍚︼級 */
+ private String isFrame;
+
+ /** 鏄惁缂撳瓨锛�0缂撳瓨 1涓嶇紦瀛橈級 */
+ private String isCache;
+
+ /** 绫诲瀷锛圡鐩綍 C鑿滃崟 F鎸夐挳锛� */
+ private String menuType;
+
+ /** 鏄剧ず鐘舵�侊紙0鏄剧ず 1闅愯棌锛� */
+ private String visible;
+
+ /** 鑿滃崟鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+ private String status;
+
+ /** 鏉冮檺瀛楃涓� */
+ private String perms;
+
+ /** 鑿滃崟鍥炬爣 */
+ private String icon;
+
+ /** 瀛愯彍鍗� */
+ private List<SysMenu> children = new ArrayList<SysMenu>();
+
+ public Long getMenuId()
+ {
+ return menuId;
+ }
+
+ public void setMenuId(Long menuId)
+ {
+ this.menuId = menuId;
+ }
+
+ @NotBlank(message = "鑿滃崟鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 50, message = "鑿滃崟鍚嶇О闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+ public String getMenuName()
+ {
+ return menuName;
+ }
+
+ public void setMenuName(String menuName)
+ {
+ this.menuName = menuName;
+ }
+
+ public String getParentName()
+ {
+ return parentName;
+ }
+
+ public void setParentName(String parentName)
+ {
+ this.parentName = parentName;
+ }
+
+ public Long getParentId()
+ {
+ return parentId;
+ }
+
+ public void setParentId(Long parentId)
+ {
+ this.parentId = parentId;
+ }
+
+ @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+ public Integer getOrderNum()
+ {
+ return orderNum;
+ }
+
+ public void setOrderNum(Integer orderNum)
+ {
+ this.orderNum = orderNum;
+ }
+
+ @Size(min = 0, max = 200, message = "璺敱鍦板潃涓嶈兘瓒呰繃200涓瓧绗�")
+ public String getPath()
+ {
+ return path;
+ }
+
+ public void setPath(String path)
+ {
+ this.path = path;
+ }
+
+ @Size(min = 0, max = 200, message = "缁勪欢璺緞涓嶈兘瓒呰繃255涓瓧绗�")
+ public String getComponent()
+ {
+ return component;
+ }
+
+ public void setComponent(String component)
+ {
+ this.component = component;
+ }
+
+ public String getQuery()
+ {
+ return query;
+ }
+
+ public void setQuery(String query)
+ {
+ this.query = query;
+ }
+
+ public String getRouteName()
+ {
+ return routeName;
+ }
+
+ public void setRouteName(String routeName)
+ {
+ this.routeName = routeName;
+ }
+
+ public String getIsFrame()
+ {
+ return isFrame;
+ }
+
+ public void setIsFrame(String isFrame)
+ {
+ this.isFrame = isFrame;
+ }
+
+ public String getIsCache()
+ {
+ return isCache;
+ }
+
+ public void setIsCache(String isCache)
+ {
+ this.isCache = isCache;
+ }
+
+ @NotBlank(message = "鑿滃崟绫诲瀷涓嶈兘涓虹┖")
+ public String getMenuType()
+ {
+ return menuType;
+ }
+
+ public void setMenuType(String menuType)
+ {
+ this.menuType = menuType;
+ }
+
+ public String getVisible()
+ {
+ return visible;
+ }
+
+ public void setVisible(String visible)
+ {
+ this.visible = visible;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ @Size(min = 0, max = 100, message = "鏉冮檺鏍囪瘑闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+ public String getPerms()
+ {
+ return perms;
+ }
+
+ public void setPerms(String perms)
+ {
+ this.perms = perms;
+ }
+
+ public String getIcon()
+ {
+ return icon;
+ }
+
+ public void setIcon(String icon)
+ {
+ this.icon = icon;
+ }
+
+ public List<SysMenu> getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List<SysMenu> children)
+ {
+ this.children = children;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("menuId", getMenuId())
+ .append("menuName", getMenuName())
+ .append("parentId", getParentId())
+ .append("orderNum", getOrderNum())
+ .append("path", getPath())
+ .append("component", getComponent())
+ .append("query", getQuery())
+ .append("routeName", getRouteName())
+ .append("isFrame", getIsFrame())
+ .append("IsCache", getIsCache())
+ .append("menuType", getMenuType())
+ .append("visible", getVisible())
+ .append("status ", getStatus())
+ .append("perms", getPerms())
+ .append("icon", getIcon())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
new file mode 100644
index 0000000..488d49c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysRole.java
@@ -0,0 +1,241 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.Set;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 瑙掕壊琛� sys_role
+ *
+ * @author ruoyi
+ */
+public class SysRole extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 瑙掕壊ID */
+ @Excel(name = "瑙掕壊搴忓彿", cellType = ColumnType.NUMERIC)
+ private Long roleId;
+
+ /** 瑙掕壊鍚嶇О */
+ @Excel(name = "瑙掕壊鍚嶇О")
+ private String roleName;
+
+ /** 瑙掕壊鏉冮檺 */
+ @Excel(name = "瑙掕壊鏉冮檺")
+ private String roleKey;
+
+ /** 瑙掕壊鎺掑簭 */
+ @Excel(name = "瑙掕壊鎺掑簭")
+ private Integer roleSort;
+
+ /** 鏁版嵁鑼冨洿锛�1锛氭墍鏈夋暟鎹潈闄愶紱2锛氳嚜瀹氫箟鏁版嵁鏉冮檺锛�3锛氭湰閮ㄩ棬鏁版嵁鏉冮檺锛�4锛氭湰閮ㄩ棬鍙婁互涓嬫暟鎹潈闄愶紱5锛氫粎鏈汉鏁版嵁鏉冮檺锛� */
+ @Excel(name = "鏁版嵁鑼冨洿", readConverterExp = "1=鎵�鏈夋暟鎹潈闄�,2=鑷畾涔夋暟鎹潈闄�,3=鏈儴闂ㄦ暟鎹潈闄�,4=鏈儴闂ㄥ強浠ヤ笅鏁版嵁鏉冮檺,5=浠呮湰浜烘暟鎹潈闄�")
+ private String dataScope;
+
+ /** 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙 0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀猴級 */
+ private boolean menuCheckStrictly;
+
+ /** 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀猴紙0锛氱埗瀛愪笉浜掔浉鍏宠仈鏄剧ず 1锛氱埗瀛愪簰鐩稿叧鑱旀樉绀� 锛� */
+ private boolean deptCheckStrictly;
+
+ /** 瑙掕壊鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+ @Excel(name = "瑙掕壊鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+ private String status;
+
+ /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+ private String delFlag;
+
+ /** 鐢ㄦ埛鏄惁瀛樺湪姝よ鑹叉爣璇� 榛樿涓嶅瓨鍦� */
+ private boolean flag = false;
+
+ /** 鑿滃崟缁� */
+ private Long[] menuIds;
+
+ /** 閮ㄩ棬缁勶紙鏁版嵁鏉冮檺锛� */
+ private Long[] deptIds;
+
+ /** 瑙掕壊鑿滃崟鏉冮檺 */
+ private Set<String> permissions;
+
+ public SysRole()
+ {
+
+ }
+
+ public SysRole(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public Long getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public boolean isAdmin()
+ {
+ return isAdmin(this.roleId);
+ }
+
+ public static boolean isAdmin(Long roleId)
+ {
+ return roleId != null && 1L == roleId;
+ }
+
+ @NotBlank(message = "瑙掕壊鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 30, message = "瑙掕壊鍚嶇О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+ public String getRoleName()
+ {
+ return roleName;
+ }
+
+ public void setRoleName(String roleName)
+ {
+ this.roleName = roleName;
+ }
+
+ @NotBlank(message = "鏉冮檺瀛楃涓嶈兘涓虹┖")
+ @Size(min = 0, max = 100, message = "鏉冮檺瀛楃闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+ public String getRoleKey()
+ {
+ return roleKey;
+ }
+
+ public void setRoleKey(String roleKey)
+ {
+ this.roleKey = roleKey;
+ }
+
+ @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+ public Integer getRoleSort()
+ {
+ return roleSort;
+ }
+
+ public void setRoleSort(Integer roleSort)
+ {
+ this.roleSort = roleSort;
+ }
+
+ public String getDataScope()
+ {
+ return dataScope;
+ }
+
+ public void setDataScope(String dataScope)
+ {
+ this.dataScope = dataScope;
+ }
+
+ public boolean isMenuCheckStrictly()
+ {
+ return menuCheckStrictly;
+ }
+
+ public void setMenuCheckStrictly(boolean menuCheckStrictly)
+ {
+ this.menuCheckStrictly = menuCheckStrictly;
+ }
+
+ public boolean isDeptCheckStrictly()
+ {
+ return deptCheckStrictly;
+ }
+
+ public void setDeptCheckStrictly(boolean deptCheckStrictly)
+ {
+ this.deptCheckStrictly = deptCheckStrictly;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getDelFlag()
+ {
+ return delFlag;
+ }
+
+ public void setDelFlag(String delFlag)
+ {
+ this.delFlag = delFlag;
+ }
+
+ public boolean isFlag()
+ {
+ return flag;
+ }
+
+ public void setFlag(boolean flag)
+ {
+ this.flag = flag;
+ }
+
+ public Long[] getMenuIds()
+ {
+ return menuIds;
+ }
+
+ public void setMenuIds(Long[] menuIds)
+ {
+ this.menuIds = menuIds;
+ }
+
+ public Long[] getDeptIds()
+ {
+ return deptIds;
+ }
+
+ public void setDeptIds(Long[] deptIds)
+ {
+ this.deptIds = deptIds;
+ }
+
+ public Set<String> getPermissions()
+ {
+ return permissions;
+ }
+
+ public void setPermissions(Set<String> permissions)
+ {
+ this.permissions = permissions;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("roleId", getRoleId())
+ .append("roleName", getRoleName())
+ .append("roleKey", getRoleKey())
+ .append("roleSort", getRoleSort())
+ .append("dataScope", getDataScope())
+ .append("menuCheckStrictly", isMenuCheckStrictly())
+ .append("deptCheckStrictly", isDeptCheckStrictly())
+ .append("status", getStatus())
+ .append("delFlag", getDelFlag())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
new file mode 100644
index 0000000..b56f0b5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
@@ -0,0 +1,363 @@
+package com.ruoyi.common.core.domain.entity;
+
+import java.util.Date;
+import java.util.List;
+import javax.validation.constraints.*;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.annotation.Excel.Type;
+import com.ruoyi.common.annotation.Excels;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.xss.Xss;
+
+/**
+ * 鐢ㄦ埛瀵硅薄 sys_user
+ *
+ * @author ruoyi
+ */
+public class SysUser extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鐢ㄦ埛ID */
+ @Excel(name = "鐢ㄦ埛搴忓彿", type = Type.EXPORT, cellType = ColumnType.NUMERIC, prompt = "鐢ㄦ埛缂栧彿")
+ private Long userId;
+
+ /** 閮ㄩ棬ID */
+ @Excel(name = "閮ㄩ棬缂栧彿", type = Type.IMPORT)
+ private Long deptId;
+
+ /** 鐢ㄦ埛璐﹀彿 */
+ @Excel(name = "鐧诲綍鍚嶇О")
+ private String userName;
+
+ /** 鐢ㄦ埛鏄电О */
+ @Excel(name = "鐢ㄦ埛鍚嶇О")
+ private String nickName;
+
+ /** 鑻辨枃鍚嶇О */
+ private String nameEn;
+
+ /** 鐢ㄦ埛閭 */
+ @Excel(name = "鐢ㄦ埛閭")
+ private String email;
+
+ /** 鎵嬫満鍙风爜 */
+ @Excel(name = "鎵嬫満鍙风爜", cellType = ColumnType.TEXT)
+ private String phonenumber;
+
+ /** 鐢ㄦ埛鎬у埆 */
+ @Excel(name = "鐢ㄦ埛鎬у埆", readConverterExp = "0=鐢�,1=濂�,2=鏈煡")
+ private String sex;
+
+ /** 鐢ㄦ埛澶村儚 */
+ private String avatar;
+
+ /** 绛惧悕鍦板潃 */
+ private String signatureUrl;
+
+ /** 鍗曚綅id */
+ private String company;
+
+ /** 瀵嗙爜 */
+ private String password;
+
+ /** 甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+ @Excel(name = "甯愬彿鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+ private String status;
+
+ /** 鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛� */
+ private String delFlag;
+
+ /** 鏈�鍚庣櫥褰旾P */
+ @Excel(name = "鏈�鍚庣櫥褰旾P", type = Type.EXPORT)
+ private String loginIp;
+
+ /** 鏈�鍚庣櫥褰曟椂闂� */
+ @Excel(name = "鏈�鍚庣櫥褰曟椂闂�", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss", type = Type.EXPORT)
+ private Date loginDate;
+
+ /** 閮ㄩ棬瀵硅薄 */
+ @Excels({
+ @Excel(name = "閮ㄩ棬鍚嶇О", targetAttr = "deptName", type = Type.EXPORT),
+ @Excel(name = "閮ㄩ棬璐熻矗浜�", targetAttr = "leader", type = Type.EXPORT)
+ })
+ private SysDept dept;
+
+ /** 瑙掕壊瀵硅薄 */
+ private List<SysRole> roles;
+
+ /** 瑙掕壊缁� */
+ private Long[] roleIds;
+
+ /** 宀椾綅缁� */
+ private Long[] postIds;
+
+ /** 瑙掕壊ID */
+ private Long roleId;
+
+ public SysUser()
+ {
+
+ }
+
+ public SysUser(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public boolean isAdmin()
+ {
+ return isAdmin(this.userId);
+ }
+
+ public static boolean isAdmin(Long userId)
+ {
+ return userId != null && 1L == userId;
+ }
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ @Xss(message = "鐢ㄦ埛鏄电О涓嶈兘鍖呭惈鑴氭湰瀛楃")
+ @Size(min = 0, max = 30, message = "鐢ㄦ埛鏄电О闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+ public String getNickName()
+ {
+ return nickName;
+ }
+
+ public void setNickName(String nickName)
+ {
+ this.nickName = nickName;
+ }
+
+ @Xss(message = "鐢ㄦ埛璐﹀彿涓嶈兘鍖呭惈鑴氭湰瀛楃")
+ @NotBlank(message = "鐢ㄦ埛璐﹀彿涓嶈兘涓虹┖")
+ @Size(min = 0, max = 30, message = "鐢ㄦ埛璐﹀彿闀垮害涓嶈兘瓒呰繃30涓瓧绗�")
+ public String getUserName()
+ {
+ return userName;
+ }
+
+ public void setUserName(String userName)
+ {
+ this.userName = userName;
+ }
+
+ @Email(message = "閭鏍煎紡涓嶆纭�")
+ @Size(min = 0, max = 50, message = "閭闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+ public String getEmail()
+ {
+ return email;
+ }
+
+ public void setEmail(String email)
+ {
+ this.email = email;
+ }
+
+ @Size(min = 0, max = 11, message = "鎵嬫満鍙风爜闀垮害涓嶈兘瓒呰繃11涓瓧绗�")
+ public String getPhonenumber()
+ {
+ return phonenumber;
+ }
+
+ public void setPhonenumber(String phonenumber)
+ {
+ this.phonenumber = phonenumber;
+ }
+
+ public String getSex()
+ {
+ return sex;
+ }
+
+ public void setSex(String sex)
+ {
+ this.sex = sex;
+ }
+
+ public String getAvatar()
+ {
+ return avatar;
+ }
+
+ public void setAvatar(String avatar)
+ {
+ this.avatar = avatar;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getDelFlag()
+ {
+ return delFlag;
+ }
+
+ public void setDelFlag(String delFlag)
+ {
+ this.delFlag = delFlag;
+ }
+
+ public String getLoginIp()
+ {
+ return loginIp;
+ }
+
+ public void setLoginIp(String loginIp)
+ {
+ this.loginIp = loginIp;
+ }
+
+ public Date getLoginDate()
+ {
+ return loginDate;
+ }
+
+ public void setLoginDate(Date loginDate)
+ {
+ this.loginDate = loginDate;
+ }
+
+ public SysDept getDept()
+ {
+ return dept;
+ }
+
+ public void setDept(SysDept dept)
+ {
+ this.dept = dept;
+ }
+
+ public List<SysRole> getRoles()
+ {
+ return roles;
+ }
+
+ public void setRoles(List<SysRole> roles)
+ {
+ this.roles = roles;
+ }
+
+ public Long[] getRoleIds()
+ {
+ return roleIds;
+ }
+
+ public void setRoleIds(Long[] roleIds)
+ {
+ this.roleIds = roleIds;
+ }
+
+ public Long[] getPostIds()
+ {
+ return postIds;
+ }
+
+ public void setPostIds(Long[] postIds)
+ {
+ this.postIds = postIds;
+ }
+
+ public Long getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public String getNameEn()
+ {
+ return nameEn;
+ }
+
+ public void setNameEn(String nameEn)
+ {
+ this.nameEn = nameEn;
+ }
+
+ public String getSignatureUrl()
+ {
+ return signatureUrl;
+ }
+
+ public void setSignatureUrl(String signatureUrl)
+ {
+ this.signatureUrl = signatureUrl;
+ }
+
+ public String getCompany()
+ {
+ return company;
+ }
+
+ public void setCompany(String company)
+ {
+ this.company = company;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("userId", getUserId())
+ .append("deptId", getDeptId())
+ .append("userName", getUserName())
+ .append("nickName", getNickName())
+ .append("email", getEmail())
+ .append("phonenumber", getPhonenumber())
+ .append("sex", getSex())
+ .append("avatar", getAvatar())
+ .append("password", getPassword())
+ .append("status", getStatus())
+ .append("delFlag", getDelFlag())
+ .append("loginIp", getLoginIp())
+ .append("loginDate", getLoginDate())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .append("dept", getDept())
+ .toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/User.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/User.java
new file mode 100644
index 0000000..29d18a7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/User.java
@@ -0,0 +1,100 @@
+package com.ruoyi.common.core.domain.entity;
+
+import com.baomidou.mybatisplus.annotation.*;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.Date;
+
+/**
+ * 鐢ㄦ埛淇℃伅琛�
+ *
+ * @author zhuo
+ * @since 2025-02-13
+ */
+@Data
+@TableName("user")
+public class User {
+
+ @ApiModelProperty(value = "涓婚敭")
+ @TableId(type = IdType.AUTO)
+ private Long id;
+
+ @ApiModelProperty(value = "閮ㄩ棬ID")
+ private Long deptId;
+
+ @ApiModelProperty(value = "鐢ㄦ埛璐﹀彿")
+ private String account;
+
+ @ApiModelProperty(value = "鐢ㄦ埛鏄电О")
+ private String name;
+
+ @ApiModelProperty(value = "鑻辨枃鍚�")
+ private String nameEn;
+
+ @ApiModelProperty(value = "鐢ㄦ埛绫诲瀷锛�00绯荤粺鐢ㄦ埛锛�")
+ private String userType;
+
+ @ApiModelProperty(value = "鐢ㄦ埛閭")
+ private String email;
+
+ @ApiModelProperty(value = "鎵嬫満鍙风爜")
+ private String phone;
+
+ @ApiModelProperty(value = "鐢ㄦ埛鎬у埆锛�0鐢� 1濂� 2鏈煡锛�")
+ private String sex;
+
+ @ApiModelProperty(value = "骞撮緞")
+ private Integer age;
+
+ @ApiModelProperty(value = "绛惧悕鍦板潃")
+ private String signatureUrl;
+
+ @ApiModelProperty(value = "澶村儚鍦板潃")
+ private String pictureUrl;
+
+ @ApiModelProperty(value = "瀵嗙爜")
+ private String password;
+
+ @ApiModelProperty(value = "甯愬彿鐘舵�侊紙0姝e父 1鍋滅敤锛�")
+ private String status;
+
+ @ApiModelProperty(value = "鍒犻櫎鏍囧織锛�0浠h〃瀛樺湪 2浠h〃鍒犻櫎锛�")
+ private String delFlag;
+
+ @ApiModelProperty(value = "鏈�鍚庣櫥褰旾P")
+ private String loginIp;
+
+ @ApiModelProperty(value = "鏈�鍚庣櫥褰曟椂闂�")
+ private Date loginDate;
+
+ @ApiModelProperty(value = "cnas瀹為獙瀹d")
+ private String departLimsId;
+
+ @ApiModelProperty(value = "鍗曚綅id")
+ private String company;
+
+ @ApiModelProperty(value = "鏄惁瀹㈡埛 0: 鍚�, 1:鏄�")
+ private Integer isCustom;
+
+ @TableField(fill = FieldFill.INSERT)
+ @ApiModelProperty(value = "鍒涘缓鑰�")
+ private String createBy;
+
+ @TableField(fill = FieldFill.INSERT)
+ @ApiModelProperty(value = "鍒涘缓鏃堕棿")
+ private Date createTime;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @ApiModelProperty(value = "鏇存柊鑰�")
+ private String updateBy;
+
+ @TableField(fill = FieldFill.INSERT_UPDATE)
+ @ApiModelProperty(value = "鏇存柊鏃堕棿")
+ private Date updateTime;
+
+ @ApiModelProperty(value = "澶囨敞")
+ private String remark;
+
+}
+
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
new file mode 100644
index 0000000..b5bc8c8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginBody.java
@@ -0,0 +1,69 @@
+package com.ruoyi.common.core.domain.model;
+
+/**
+ * 鐢ㄦ埛鐧诲綍瀵硅薄
+ *
+ * @author ruoyi
+ */
+public class LoginBody
+{
+ /**
+ * 鐢ㄦ埛鍚�
+ */
+ private String username;
+
+ /**
+ * 鐢ㄦ埛瀵嗙爜
+ */
+ private String password;
+
+ /**
+ * 楠岃瘉鐮�
+ */
+ private String code;
+
+ /**
+ * 鍞竴鏍囪瘑
+ */
+ private String uuid;
+
+ public String getUsername()
+ {
+ return username;
+ }
+
+ public void setUsername(String username)
+ {
+ this.username = username;
+ }
+
+ public String getPassword()
+ {
+ return password;
+ }
+
+ public void setPassword(String password)
+ {
+ this.password = password;
+ }
+
+ public String getCode()
+ {
+ return code;
+ }
+
+ public void setCode(String code)
+ {
+ this.code = code;
+ }
+
+ public String getUuid()
+ {
+ return uuid;
+ }
+
+ public void setUuid(String uuid)
+ {
+ this.uuid = uuid;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
new file mode 100644
index 0000000..670e6b3
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/LoginUser.java
@@ -0,0 +1,266 @@
+package com.ruoyi.common.core.domain.model;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * 鐧诲綍鐢ㄦ埛韬唤鏉冮檺
+ *
+ * @author ruoyi
+ */
+public class LoginUser implements UserDetails
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 鐢ㄦ埛ID
+ */
+ private Long userId;
+
+ /**
+ * 閮ㄩ棬ID
+ */
+ private Long deptId;
+
+ /**
+ * 鐢ㄦ埛鍞竴鏍囪瘑
+ */
+ private String token;
+
+ /**
+ * 鐧诲綍鏃堕棿
+ */
+ private Long loginTime;
+
+ /**
+ * 杩囨湡鏃堕棿
+ */
+ private Long expireTime;
+
+ /**
+ * 鐧诲綍IP鍦板潃
+ */
+ private String ipaddr;
+
+ /**
+ * 鐧诲綍鍦扮偣
+ */
+ private String loginLocation;
+
+ /**
+ * 娴忚鍣ㄧ被鍨�
+ */
+ private String browser;
+
+ /**
+ * 鎿嶄綔绯荤粺
+ */
+ private String os;
+
+ /**
+ * 鏉冮檺鍒楄〃
+ */
+ private Set<String> permissions;
+
+ /**
+ * 鐢ㄦ埛淇℃伅
+ */
+ private SysUser user;
+
+ public LoginUser()
+ {
+ }
+
+ public LoginUser(SysUser user, Set<String> permissions)
+ {
+ this.user = user;
+ this.permissions = permissions;
+ }
+
+ public LoginUser(Long userId, Long deptId, SysUser user, Set<String> permissions)
+ {
+ this.userId = userId;
+ this.deptId = deptId;
+ this.user = user;
+ this.permissions = permissions;
+ }
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
+
+ public void setToken(String token)
+ {
+ this.token = token;
+ }
+
+ @JSONField(serialize = false)
+ @Override
+ public String getPassword()
+ {
+ return user.getPassword();
+ }
+
+ @Override
+ public String getUsername()
+ {
+ return user.getUserName();
+ }
+
+ /**
+ * 璐︽埛鏄惁鏈繃鏈�,杩囨湡鏃犳硶楠岃瘉
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isAccountNonExpired()
+ {
+ return true;
+ }
+
+ /**
+ * 鎸囧畾鐢ㄦ埛鏄惁瑙i攣,閿佸畾鐨勭敤鎴锋棤娉曡繘琛岃韩浠介獙璇�
+ *
+ * @return
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isAccountNonLocked()
+ {
+ return true;
+ }
+
+ /**
+ * 鎸囩ず鏄惁宸茶繃鏈熺殑鐢ㄦ埛鐨勫嚟鎹�(瀵嗙爜),杩囨湡鐨勫嚟鎹槻姝㈣璇�
+ *
+ * @return
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isCredentialsNonExpired()
+ {
+ return true;
+ }
+
+ /**
+ * 鏄惁鍙敤 ,绂佺敤鐨勭敤鎴蜂笉鑳借韩浠介獙璇�
+ *
+ * @return
+ */
+ @JSONField(serialize = false)
+ @Override
+ public boolean isEnabled()
+ {
+ return true;
+ }
+
+ public Long getLoginTime()
+ {
+ return loginTime;
+ }
+
+ public void setLoginTime(Long loginTime)
+ {
+ this.loginTime = loginTime;
+ }
+
+ public String getIpaddr()
+ {
+ return ipaddr;
+ }
+
+ public void setIpaddr(String ipaddr)
+ {
+ this.ipaddr = ipaddr;
+ }
+
+ public String getLoginLocation()
+ {
+ return loginLocation;
+ }
+
+ public void setLoginLocation(String loginLocation)
+ {
+ this.loginLocation = loginLocation;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public Long getExpireTime()
+ {
+ return expireTime;
+ }
+
+ public void setExpireTime(Long expireTime)
+ {
+ this.expireTime = expireTime;
+ }
+
+ public Set<String> getPermissions()
+ {
+ return permissions;
+ }
+
+ public void setPermissions(Set<String> permissions)
+ {
+ this.permissions = permissions;
+ }
+
+ public SysUser getUser()
+ {
+ return user;
+ }
+
+ public void setUser(SysUser user)
+ {
+ this.user = user;
+ }
+
+ @Override
+ public Collection<? extends GrantedAuthority> getAuthorities()
+ {
+ return null;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
new file mode 100644
index 0000000..868a1fc
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/model/RegisterBody.java
@@ -0,0 +1,11 @@
+package com.ruoyi.common.core.domain.model;
+
+/**
+ * 鐢ㄦ埛娉ㄥ唽瀵硅薄
+ *
+ * @author ruoyi
+ */
+public class RegisterBody extends LoginBody
+{
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
new file mode 100644
index 0000000..8966cb4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/PageDomain.java
@@ -0,0 +1,101 @@
+package com.ruoyi.common.core.page;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 鍒嗛〉鏁版嵁
+ *
+ * @author ruoyi
+ */
+public class PageDomain
+{
+ /** 褰撳墠璁板綍璧峰绱㈠紩 */
+ private Integer pageNum;
+
+ /** 姣忛〉鏄剧ず璁板綍鏁� */
+ private Integer pageSize;
+
+ /** 鎺掑簭鍒� */
+ private String orderByColumn;
+
+ /** 鎺掑簭鐨勬柟鍚慸esc鎴栬�卆sc */
+ private String isAsc = "asc";
+
+ /** 鍒嗛〉鍙傛暟鍚堢悊鍖� */
+ private Boolean reasonable = true;
+
+ public String getOrderBy()
+ {
+ if (StringUtils.isEmpty(orderByColumn))
+ {
+ return "";
+ }
+ return StringUtils.toUnderScoreCase(orderByColumn) + " " + isAsc;
+ }
+
+ public Integer getPageNum()
+ {
+ return pageNum;
+ }
+
+ public void setPageNum(Integer pageNum)
+ {
+ this.pageNum = pageNum;
+ }
+
+ public Integer getPageSize()
+ {
+ return pageSize;
+ }
+
+ public void setPageSize(Integer pageSize)
+ {
+ this.pageSize = pageSize;
+ }
+
+ public String getOrderByColumn()
+ {
+ return orderByColumn;
+ }
+
+ public void setOrderByColumn(String orderByColumn)
+ {
+ this.orderByColumn = orderByColumn;
+ }
+
+ public String getIsAsc()
+ {
+ return isAsc;
+ }
+
+ public void setIsAsc(String isAsc)
+ {
+ if (StringUtils.isNotEmpty(isAsc))
+ {
+ // 鍏煎鍓嶇鎺掑簭绫诲瀷
+ if ("ascending".equals(isAsc))
+ {
+ isAsc = "asc";
+ }
+ else if ("descending".equals(isAsc))
+ {
+ isAsc = "desc";
+ }
+ this.isAsc = isAsc;
+ }
+ }
+
+ public Boolean getReasonable()
+ {
+ if (StringUtils.isNull(reasonable))
+ {
+ return Boolean.TRUE;
+ }
+ return reasonable;
+ }
+
+ public void setReasonable(Boolean reasonable)
+ {
+ this.reasonable = reasonable;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
new file mode 100644
index 0000000..847685b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableDataInfo.java
@@ -0,0 +1,85 @@
+package com.ruoyi.common.core.page;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 琛ㄦ牸鍒嗛〉鏁版嵁瀵硅薄
+ *
+ * @author ruoyi
+ */
+public class TableDataInfo implements Serializable
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鎬昏褰曟暟 */
+ private long total;
+
+ /** 鍒楄〃鏁版嵁 */
+ private List<?> rows;
+
+ /** 娑堟伅鐘舵�佺爜 */
+ private int code;
+
+ /** 娑堟伅鍐呭 */
+ private String msg;
+
+ /**
+ * 琛ㄦ牸鏁版嵁瀵硅薄
+ */
+ public TableDataInfo()
+ {
+ }
+
+ /**
+ * 鍒嗛〉
+ *
+ * @param list 鍒楄〃鏁版嵁
+ * @param total 鎬昏褰曟暟
+ */
+ public TableDataInfo(List<?> list, int total)
+ {
+ this.rows = list;
+ this.total = total;
+ }
+
+ public long getTotal()
+ {
+ return total;
+ }
+
+ public void setTotal(long total)
+ {
+ this.total = total;
+ }
+
+ public List<?> getRows()
+ {
+ return rows;
+ }
+
+ public void setRows(List<?> rows)
+ {
+ this.rows = rows;
+ }
+
+ public int getCode()
+ {
+ return code;
+ }
+
+ public void setCode(int code)
+ {
+ this.code = code;
+ }
+
+ public String getMsg()
+ {
+ return msg;
+ }
+
+ public void setMsg(String msg)
+ {
+ this.msg = msg;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java
new file mode 100644
index 0000000..a120c30
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/page/TableSupport.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.core.page;
+
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.ServletUtils;
+
+/**
+ * 琛ㄦ牸鏁版嵁澶勭悊
+ *
+ * @author ruoyi
+ */
+public class TableSupport
+{
+ /**
+ * 褰撳墠璁板綍璧峰绱㈠紩
+ */
+ public static final String PAGE_NUM = "pageNum";
+
+ /**
+ * 姣忛〉鏄剧ず璁板綍鏁�
+ */
+ public static final String PAGE_SIZE = "pageSize";
+
+ /**
+ * 鎺掑簭鍒�
+ */
+ public static final String ORDER_BY_COLUMN = "orderByColumn";
+
+ /**
+ * 鎺掑簭鐨勬柟鍚� "desc" 鎴栬�� "asc".
+ */
+ public static final String IS_ASC = "isAsc";
+
+ /**
+ * 鍒嗛〉鍙傛暟鍚堢悊鍖�
+ */
+ public static final String REASONABLE = "reasonable";
+
+ /**
+ * 灏佽鍒嗛〉瀵硅薄
+ */
+ public static PageDomain getPageDomain()
+ {
+ PageDomain pageDomain = new PageDomain();
+ pageDomain.setPageNum(Convert.toInt(ServletUtils.getParameter(PAGE_NUM), 1));
+ pageDomain.setPageSize(Convert.toInt(ServletUtils.getParameter(PAGE_SIZE), 10));
+ pageDomain.setOrderByColumn(ServletUtils.getParameter(ORDER_BY_COLUMN));
+ pageDomain.setIsAsc(ServletUtils.getParameter(IS_ASC));
+ pageDomain.setReasonable(ServletUtils.getParameterToBool(REASONABLE));
+ return pageDomain;
+ }
+
+ public static PageDomain buildPageRequest()
+ {
+ return getPageDomain();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
new file mode 100644
index 0000000..44e80d8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java
@@ -0,0 +1,268 @@
+package com.ruoyi.common.core.redis;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.BoundSetOperations;
+import org.springframework.data.redis.core.HashOperations;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.ValueOperations;
+import org.springframework.stereotype.Component;
+
+/**
+ * spring redis 宸ュ叿绫�
+ *
+ * @author ruoyi
+ **/
+@SuppressWarnings(value = { "unchecked", "rawtypes" })
+@Component
+public class RedisCache
+{
+ @Autowired
+ public RedisTemplate redisTemplate;
+
+ /**
+ * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+ *
+ * @param key 缂撳瓨鐨勯敭鍊�
+ * @param value 缂撳瓨鐨勫��
+ */
+ public <T> void setCacheObject(final String key, final T value)
+ {
+ redisTemplate.opsForValue().set(key, value);
+ }
+
+ /**
+ * 缂撳瓨鍩烘湰鐨勫璞★紝Integer銆丼tring銆佸疄浣撶被绛�
+ *
+ * @param key 缂撳瓨鐨勯敭鍊�
+ * @param value 缂撳瓨鐨勫��
+ * @param timeout 鏃堕棿
+ * @param timeUnit 鏃堕棿棰楃矑搴�
+ */
+ public <T> void setCacheObject(final String key, final T value, final Integer timeout, final TimeUnit timeUnit)
+ {
+ redisTemplate.opsForValue().set(key, value, timeout, timeUnit);
+ }
+
+ /**
+ * 璁剧疆鏈夋晥鏃堕棿
+ *
+ * @param key Redis閿�
+ * @param timeout 瓒呮椂鏃堕棿
+ * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+ */
+ public boolean expire(final String key, final long timeout)
+ {
+ return expire(key, timeout, TimeUnit.SECONDS);
+ }
+
+ /**
+ * 璁剧疆鏈夋晥鏃堕棿
+ *
+ * @param key Redis閿�
+ * @param timeout 瓒呮椂鏃堕棿
+ * @param unit 鏃堕棿鍗曚綅
+ * @return true=璁剧疆鎴愬姛锛沠alse=璁剧疆澶辫触
+ */
+ public boolean expire(final String key, final long timeout, final TimeUnit unit)
+ {
+ return redisTemplate.expire(key, timeout, unit);
+ }
+
+ /**
+ * 鑾峰彇鏈夋晥鏃堕棿
+ *
+ * @param key Redis閿�
+ * @return 鏈夋晥鏃堕棿
+ */
+ public long getExpire(final String key)
+ {
+ return redisTemplate.getExpire(key);
+ }
+
+ /**
+ * 鍒ゆ柇 key鏄惁瀛樺湪
+ *
+ * @param key 閿�
+ * @return true 瀛樺湪 false涓嶅瓨鍦�
+ */
+ public Boolean hasKey(String key)
+ {
+ return redisTemplate.hasKey(key);
+ }
+
+ /**
+ * 鑾峰緱缂撳瓨鐨勫熀鏈璞°��
+ *
+ * @param key 缂撳瓨閿��
+ * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+ */
+ public <T> T getCacheObject(final String key)
+ {
+ ValueOperations<String, T> operation = redisTemplate.opsForValue();
+ return operation.get(key);
+ }
+
+ /**
+ * 鍒犻櫎鍗曚釜瀵硅薄
+ *
+ * @param key
+ */
+ public boolean deleteObject(final String key)
+ {
+ return redisTemplate.delete(key);
+ }
+
+ /**
+ * 鍒犻櫎闆嗗悎瀵硅薄
+ *
+ * @param collection 澶氫釜瀵硅薄
+ * @return
+ */
+ public boolean deleteObject(final Collection collection)
+ {
+ return redisTemplate.delete(collection) > 0;
+ }
+
+ /**
+ * 缂撳瓨List鏁版嵁
+ *
+ * @param key 缂撳瓨鐨勯敭鍊�
+ * @param dataList 寰呯紦瀛樼殑List鏁版嵁
+ * @return 缂撳瓨鐨勫璞�
+ */
+ public <T> long setCacheList(final String key, final List<T> dataList)
+ {
+ Long count = redisTemplate.opsForList().rightPushAll(key, dataList);
+ return count == null ? 0 : count;
+ }
+
+ /**
+ * 鑾峰緱缂撳瓨鐨刲ist瀵硅薄
+ *
+ * @param key 缂撳瓨鐨勯敭鍊�
+ * @return 缂撳瓨閿�煎搴旂殑鏁版嵁
+ */
+ public <T> List<T> getCacheList(final String key)
+ {
+ return redisTemplate.opsForList().range(key, 0, -1);
+ }
+
+ /**
+ * 缂撳瓨Set
+ *
+ * @param key 缂撳瓨閿��
+ * @param dataSet 缂撳瓨鐨勬暟鎹�
+ * @return 缂撳瓨鏁版嵁鐨勫璞�
+ */
+ public <T> BoundSetOperations<String, T> setCacheSet(final String key, final Set<T> dataSet)
+ {
+ BoundSetOperations<String, T> setOperation = redisTemplate.boundSetOps(key);
+ Iterator<T> it = dataSet.iterator();
+ while (it.hasNext())
+ {
+ setOperation.add(it.next());
+ }
+ return setOperation;
+ }
+
+ /**
+ * 鑾峰緱缂撳瓨鐨剆et
+ *
+ * @param key
+ * @return
+ */
+ public <T> Set<T> getCacheSet(final String key)
+ {
+ return redisTemplate.opsForSet().members(key);
+ }
+
+ /**
+ * 缂撳瓨Map
+ *
+ * @param key
+ * @param dataMap
+ */
+ public <T> void setCacheMap(final String key, final Map<String, T> dataMap)
+ {
+ if (dataMap != null) {
+ redisTemplate.opsForHash().putAll(key, dataMap);
+ }
+ }
+
+ /**
+ * 鑾峰緱缂撳瓨鐨凪ap
+ *
+ * @param key
+ * @return
+ */
+ public <T> Map<String, T> getCacheMap(final String key)
+ {
+ return redisTemplate.opsForHash().entries(key);
+ }
+
+ /**
+ * 寰�Hash涓瓨鍏ユ暟鎹�
+ *
+ * @param key Redis閿�
+ * @param hKey Hash閿�
+ * @param value 鍊�
+ */
+ public <T> void setCacheMapValue(final String key, final String hKey, final T value)
+ {
+ redisTemplate.opsForHash().put(key, hKey, value);
+ }
+
+ /**
+ * 鑾峰彇Hash涓殑鏁版嵁
+ *
+ * @param key Redis閿�
+ * @param hKey Hash閿�
+ * @return Hash涓殑瀵硅薄
+ */
+ public <T> T getCacheMapValue(final String key, final String hKey)
+ {
+ HashOperations<String, String, T> opsForHash = redisTemplate.opsForHash();
+ return opsForHash.get(key, hKey);
+ }
+
+ /**
+ * 鑾峰彇澶氫釜Hash涓殑鏁版嵁
+ *
+ * @param key Redis閿�
+ * @param hKeys Hash閿泦鍚�
+ * @return Hash瀵硅薄闆嗗悎
+ */
+ public <T> List<T> getMultiCacheMapValue(final String key, final Collection<Object> hKeys)
+ {
+ return redisTemplate.opsForHash().multiGet(key, hKeys);
+ }
+
+ /**
+ * 鍒犻櫎Hash涓殑鏌愭潯鏁版嵁
+ *
+ * @param key Redis閿�
+ * @param hKey Hash閿�
+ * @return 鏄惁鎴愬姛
+ */
+ public boolean deleteCacheMapValue(final String key, final String hKey)
+ {
+ return redisTemplate.opsForHash().delete(key, hKey) > 0;
+ }
+
+ /**
+ * 鑾峰緱缂撳瓨鐨勫熀鏈璞″垪琛�
+ *
+ * @param pattern 瀛楃涓插墠缂�
+ * @return 瀵硅薄鍒楄〃
+ */
+ public Collection<String> keys(final String pattern)
+ {
+ return redisTemplate.keys(pattern);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
new file mode 100644
index 0000000..84124aa
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/CharsetKit.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.core.text;
+
+import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 瀛楃闆嗗伐鍏风被
+ *
+ * @author ruoyi
+ */
+public class CharsetKit
+{
+ /** ISO-8859-1 */
+ public static final String ISO_8859_1 = "ISO-8859-1";
+ /** UTF-8 */
+ public static final String UTF_8 = "UTF-8";
+ /** GBK */
+ public static final String GBK = "GBK";
+
+ /** ISO-8859-1 */
+ public static final Charset CHARSET_ISO_8859_1 = Charset.forName(ISO_8859_1);
+ /** UTF-8 */
+ public static final Charset CHARSET_UTF_8 = Charset.forName(UTF_8);
+ /** GBK */
+ public static final Charset CHARSET_GBK = Charset.forName(GBK);
+
+ /**
+ * 杞崲涓篊harset瀵硅薄
+ *
+ * @param charset 瀛楃闆嗭紝涓虹┖鍒欒繑鍥為粯璁ゅ瓧绗﹂泦
+ * @return Charset
+ */
+ public static Charset charset(String charset)
+ {
+ return StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset);
+ }
+
+ /**
+ * 杞崲瀛楃涓茬殑瀛楃闆嗙紪鐮�
+ *
+ * @param source 瀛楃涓�
+ * @param srcCharset 婧愬瓧绗﹂泦锛岄粯璁SO-8859-1
+ * @param destCharset 鐩爣瀛楃闆嗭紝榛樿UTF-8
+ * @return 杞崲鍚庣殑瀛楃闆�
+ */
+ public static String convert(String source, String srcCharset, String destCharset)
+ {
+ return convert(source, Charset.forName(srcCharset), Charset.forName(destCharset));
+ }
+
+ /**
+ * 杞崲瀛楃涓茬殑瀛楃闆嗙紪鐮�
+ *
+ * @param source 瀛楃涓�
+ * @param srcCharset 婧愬瓧绗﹂泦锛岄粯璁SO-8859-1
+ * @param destCharset 鐩爣瀛楃闆嗭紝榛樿UTF-8
+ * @return 杞崲鍚庣殑瀛楃闆�
+ */
+ public static String convert(String source, Charset srcCharset, Charset destCharset)
+ {
+ if (null == srcCharset)
+ {
+ srcCharset = StandardCharsets.ISO_8859_1;
+ }
+
+ if (null == destCharset)
+ {
+ destCharset = StandardCharsets.UTF_8;
+ }
+
+ if (StringUtils.isEmpty(source) || srcCharset.equals(destCharset))
+ {
+ return source;
+ }
+ return new String(source.getBytes(srcCharset), destCharset);
+ }
+
+ /**
+ * @return 绯荤粺瀛楃闆嗙紪鐮�
+ */
+ public static String systemCharset()
+ {
+ return Charset.defaultCharset().name();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
new file mode 100644
index 0000000..edf9afc
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/Convert.java
@@ -0,0 +1,1010 @@
+package com.ruoyi.common.core.text;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.math.RoundingMode;
+import java.nio.ByteBuffer;
+import java.nio.charset.Charset;
+import java.text.NumberFormat;
+import java.util.Set;
+import com.ruoyi.common.utils.StringUtils;
+import org.apache.commons.lang3.ArrayUtils;
+
+/**
+ * 绫诲瀷杞崲鍣�
+ *
+ * @author ruoyi
+ */
+public class Convert
+{
+ /**
+ * 杞崲涓哄瓧绗︿覆<br>
+ * 濡傛灉缁欏畾鐨勫�间负null锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static String toStr(Object value, String defaultValue)
+ {
+ if (null == value)
+ {
+ return defaultValue;
+ }
+ if (value instanceof String)
+ {
+ return (String) value;
+ }
+ return value.toString();
+ }
+
+ /**
+ * 杞崲涓哄瓧绗︿覆<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static String toStr(Object value)
+ {
+ return toStr(value, null);
+ }
+
+ /**
+ * 杞崲涓哄瓧绗�<br>
+ * 濡傛灉缁欏畾鐨勫�间负null锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Character toChar(Object value, Character defaultValue)
+ {
+ if (null == value)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Character)
+ {
+ return (Character) value;
+ }
+
+ final String valueStr = toStr(value, null);
+ return StringUtils.isEmpty(valueStr) ? defaultValue : valueStr.charAt(0);
+ }
+
+ /**
+ * 杞崲涓哄瓧绗�<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Character toChar(Object value)
+ {
+ return toChar(value, null);
+ }
+
+ /**
+ * 杞崲涓篵yte<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Byte toByte(Object value, Byte defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Byte)
+ {
+ return (Byte) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).byteValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Byte.parseByte(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篵yte<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Byte toByte(Object value)
+ {
+ return toByte(value, null);
+ }
+
+ /**
+ * 杞崲涓篠hort<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Short toShort(Object value, Short defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Short)
+ {
+ return (Short) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).shortValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Short.parseShort(valueStr.trim());
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篠hort<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Short toShort(Object value)
+ {
+ return toShort(value, null);
+ }
+
+ /**
+ * 杞崲涓篘umber<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Number toNumber(Object value, Number defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Number)
+ {
+ return (Number) value;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return NumberFormat.getInstance().parse(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篘umber<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Number toNumber(Object value)
+ {
+ return toNumber(value, null);
+ }
+
+ /**
+ * 杞崲涓篿nt<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Integer toInt(Object value, Integer defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Integer)
+ {
+ return (Integer) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).intValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Integer.parseInt(valueStr.trim());
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篿nt<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Integer toInt(Object value)
+ {
+ return toInt(value, null);
+ }
+
+ /**
+ * 杞崲涓篒nteger鏁扮粍<br>
+ *
+ * @param str 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Integer[] toIntArray(String str)
+ {
+ return toIntArray(",", str);
+ }
+
+ /**
+ * 杞崲涓篖ong鏁扮粍<br>
+ *
+ * @param str 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Long[] toLongArray(String str)
+ {
+ return toLongArray(",", str);
+ }
+
+ /**
+ * 杞崲涓篒nteger鏁扮粍<br>
+ *
+ * @param split 鍒嗛殧绗�
+ * @param split 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Integer[] toIntArray(String split, String str)
+ {
+ if (StringUtils.isEmpty(str))
+ {
+ return new Integer[] {};
+ }
+ String[] arr = str.split(split);
+ final Integer[] ints = new Integer[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ {
+ final Integer v = toInt(arr[i], 0);
+ ints[i] = v;
+ }
+ return ints;
+ }
+
+ /**
+ * 杞崲涓篖ong鏁扮粍<br>
+ *
+ * @param split 鍒嗛殧绗�
+ * @param str 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Long[] toLongArray(String split, String str)
+ {
+ if (StringUtils.isEmpty(str))
+ {
+ return new Long[] {};
+ }
+ String[] arr = str.split(split);
+ final Long[] longs = new Long[arr.length];
+ for (int i = 0; i < arr.length; i++)
+ {
+ final Long v = toLong(arr[i], null);
+ longs[i] = v;
+ }
+ return longs;
+ }
+
+ /**
+ * 杞崲涓篠tring鏁扮粍<br>
+ *
+ * @param str 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static String[] toStrArray(String str)
+ {
+ if (StringUtils.isEmpty(str))
+ {
+ return new String[] {};
+ }
+ return toStrArray(",", str);
+ }
+
+ /**
+ * 杞崲涓篠tring鏁扮粍<br>
+ *
+ * @param split 鍒嗛殧绗�
+ * @param split 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static String[] toStrArray(String split, String str)
+ {
+ return str.split(split);
+ }
+
+ /**
+ * 杞崲涓簂ong<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Long toLong(Object value, Long defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Long)
+ {
+ return (Long) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).longValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ // 鏀寔绉戝璁℃暟娉�
+ return new BigDecimal(valueStr.trim()).longValue();
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓簂ong<br>
+ * 濡傛灉缁欏畾鐨勫�间负<code>null</code>锛屾垨鑰呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Long toLong(Object value)
+ {
+ return toLong(value, null);
+ }
+
+ /**
+ * 杞崲涓篸ouble<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Double toDouble(Object value, Double defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Double)
+ {
+ return (Double) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).doubleValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ // 鏀寔绉戝璁℃暟娉�
+ return new BigDecimal(valueStr.trim()).doubleValue();
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篸ouble<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Double toDouble(Object value)
+ {
+ return toDouble(value, null);
+ }
+
+ /**
+ * 杞崲涓篎loat<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Float toFloat(Object value, Float defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Float)
+ {
+ return (Float) value;
+ }
+ if (value instanceof Number)
+ {
+ return ((Number) value).floatValue();
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Float.parseFloat(valueStr.trim());
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篎loat<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Float toFloat(Object value)
+ {
+ return toFloat(value, null);
+ }
+
+ /**
+ * 杞崲涓篵oolean<br>
+ * String鏀寔鐨勫�间负锛歵rue銆乫alse銆亂es銆乷k銆乶o锛�1,0 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static Boolean toBool(Object value, Boolean defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof Boolean)
+ {
+ return (Boolean) value;
+ }
+ String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ valueStr = valueStr.trim().toLowerCase();
+ switch (valueStr)
+ {
+ case "true":
+ case "yes":
+ case "ok":
+ case "1":
+ return true;
+ case "false":
+ case "no":
+ case "0":
+ return false;
+ default:
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篵oolean<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static Boolean toBool(Object value)
+ {
+ return toBool(value, null);
+ }
+
+ /**
+ * 杞崲涓篍num瀵硅薄<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ *
+ * @param clazz Enum鐨凜lass
+ * @param value 鍊�
+ * @param defaultValue 榛樿鍊�
+ * @return Enum
+ */
+ public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value, E defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (clazz.isAssignableFrom(value.getClass()))
+ {
+ @SuppressWarnings("unchecked")
+ E myE = (E) value;
+ return myE;
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return Enum.valueOf(clazz, valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓篍num瀵硅薄<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ *
+ * @param clazz Enum鐨凜lass
+ * @param value 鍊�
+ * @return Enum
+ */
+ public static <E extends Enum<E>> E toEnum(Class<E> clazz, Object value)
+ {
+ return toEnum(clazz, value, null);
+ }
+
+ /**
+ * 杞崲涓築igInteger<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static BigInteger toBigInteger(Object value, BigInteger defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof BigInteger)
+ {
+ return (BigInteger) value;
+ }
+ if (value instanceof Long)
+ {
+ return BigInteger.valueOf((Long) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return new BigInteger(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓築igInteger<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<code>null</code><br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static BigInteger toBigInteger(Object value)
+ {
+ return toBigInteger(value, null);
+ }
+
+ /**
+ * 杞崲涓築igDecimal<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @param defaultValue 杞崲閿欒鏃剁殑榛樿鍊�
+ * @return 缁撴灉
+ */
+ public static BigDecimal toBigDecimal(Object value, BigDecimal defaultValue)
+ {
+ if (value == null)
+ {
+ return defaultValue;
+ }
+ if (value instanceof BigDecimal)
+ {
+ return (BigDecimal) value;
+ }
+ if (value instanceof Long)
+ {
+ return new BigDecimal((Long) value);
+ }
+ if (value instanceof Double)
+ {
+ return BigDecimal.valueOf((Double) value);
+ }
+ if (value instanceof Integer)
+ {
+ return new BigDecimal((Integer) value);
+ }
+ final String valueStr = toStr(value, null);
+ if (StringUtils.isEmpty(valueStr))
+ {
+ return defaultValue;
+ }
+ try
+ {
+ return new BigDecimal(valueStr);
+ }
+ catch (Exception e)
+ {
+ return defaultValue;
+ }
+ }
+
+ /**
+ * 杞崲涓築igDecimal<br>
+ * 濡傛灉缁欏畾鐨勫�间负绌猴紝鎴栬�呰浆鎹㈠け璐ワ紝杩斿洖榛樿鍊�<br>
+ * 杞崲澶辫触涓嶄細鎶ラ敊
+ *
+ * @param value 琚浆鎹㈢殑鍊�
+ * @return 缁撴灉
+ */
+ public static BigDecimal toBigDecimal(Object value)
+ {
+ return toBigDecimal(value, null);
+ }
+
+ /**
+ * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+ * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+ *
+ * @param obj 瀵硅薄
+ * @return 瀛楃涓�
+ */
+ public static String utf8Str(Object obj)
+ {
+ return str(obj, CharsetKit.CHARSET_UTF_8);
+ }
+
+ /**
+ * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+ * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+ *
+ * @param obj 瀵硅薄
+ * @param charsetName 瀛楃闆�
+ * @return 瀛楃涓�
+ */
+ public static String str(Object obj, String charsetName)
+ {
+ return str(obj, Charset.forName(charsetName));
+ }
+
+ /**
+ * 灏嗗璞¤浆涓哄瓧绗︿覆<br>
+ * 1銆丅yte鏁扮粍鍜孊yteBuffer浼氳杞崲涓哄搴斿瓧绗︿覆鐨勬暟缁� 2銆佸璞℃暟缁勪細璋冪敤Arrays.toString鏂规硶
+ *
+ * @param obj 瀵硅薄
+ * @param charset 瀛楃闆�
+ * @return 瀛楃涓�
+ */
+ public static String str(Object obj, Charset charset)
+ {
+ if (null == obj)
+ {
+ return null;
+ }
+
+ if (obj instanceof String)
+ {
+ return (String) obj;
+ }
+ else if (obj instanceof byte[])
+ {
+ return str((byte[]) obj, charset);
+ }
+ else if (obj instanceof Byte[])
+ {
+ byte[] bytes = ArrayUtils.toPrimitive((Byte[]) obj);
+ return str(bytes, charset);
+ }
+ else if (obj instanceof ByteBuffer)
+ {
+ return str((ByteBuffer) obj, charset);
+ }
+ return obj.toString();
+ }
+
+ /**
+ * 灏哹yte鏁扮粍杞负瀛楃涓�
+ *
+ * @param bytes byte鏁扮粍
+ * @param charset 瀛楃闆�
+ * @return 瀛楃涓�
+ */
+ public static String str(byte[] bytes, String charset)
+ {
+ return str(bytes, StringUtils.isEmpty(charset) ? Charset.defaultCharset() : Charset.forName(charset));
+ }
+
+ /**
+ * 瑙g爜瀛楄妭鐮�
+ *
+ * @param data 瀛楃涓�
+ * @param charset 瀛楃闆嗭紝濡傛灉姝ゅ瓧娈典负绌猴紝鍒欒В鐮佺殑缁撴灉鍙栧喅浜庡钩鍙�
+ * @return 瑙g爜鍚庣殑瀛楃涓�
+ */
+ public static String str(byte[] data, Charset charset)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+
+ if (null == charset)
+ {
+ return new String(data);
+ }
+ return new String(data, charset);
+ }
+
+ /**
+ * 灏嗙紪鐮佺殑byteBuffer鏁版嵁杞崲涓哄瓧绗︿覆
+ *
+ * @param data 鏁版嵁
+ * @param charset 瀛楃闆嗭紝濡傛灉涓虹┖浣跨敤褰撳墠绯荤粺瀛楃闆�
+ * @return 瀛楃涓�
+ */
+ public static String str(ByteBuffer data, String charset)
+ {
+ if (data == null)
+ {
+ return null;
+ }
+
+ return str(data, Charset.forName(charset));
+ }
+
+ /**
+ * 灏嗙紪鐮佺殑byteBuffer鏁版嵁杞崲涓哄瓧绗︿覆
+ *
+ * @param data 鏁版嵁
+ * @param charset 瀛楃闆嗭紝濡傛灉涓虹┖浣跨敤褰撳墠绯荤粺瀛楃闆�
+ * @return 瀛楃涓�
+ */
+ public static String str(ByteBuffer data, Charset charset)
+ {
+ if (null == charset)
+ {
+ charset = Charset.defaultCharset();
+ }
+ return charset.decode(data).toString();
+ }
+
+ // ----------------------------------------------------------------------- 鍏ㄨ鍗婅杞崲
+ /**
+ * 鍗婅杞叏瑙�
+ *
+ * @param input String.
+ * @return 鍏ㄨ瀛楃涓�.
+ */
+ public static String toSBC(String input)
+ {
+ return toSBC(input, null);
+ }
+
+ /**
+ * 鍗婅杞叏瑙�
+ *
+ * @param input String
+ * @param notConvertSet 涓嶆浛鎹㈢殑瀛楃闆嗗悎
+ * @return 鍏ㄨ瀛楃涓�.
+ */
+ public static String toSBC(String input, Set<Character> notConvertSet)
+ {
+ char[] c = input.toCharArray();
+ for (int i = 0; i < c.length; i++)
+ {
+ if (null != notConvertSet && notConvertSet.contains(c[i]))
+ {
+ // 璺宠繃涓嶆浛鎹㈢殑瀛楃
+ continue;
+ }
+
+ if (c[i] == ' ')
+ {
+ c[i] = '\u3000';
+ }
+ else if (c[i] < '\177')
+ {
+ c[i] = (char) (c[i] + 65248);
+
+ }
+ }
+ return new String(c);
+ }
+
+ /**
+ * 鍏ㄨ杞崐瑙�
+ *
+ * @param input String.
+ * @return 鍗婅瀛楃涓�
+ */
+ public static String toDBC(String input)
+ {
+ return toDBC(input, null);
+ }
+
+ /**
+ * 鏇挎崲鍏ㄨ涓哄崐瑙�
+ *
+ * @param text 鏂囨湰
+ * @param notConvertSet 涓嶆浛鎹㈢殑瀛楃闆嗗悎
+ * @return 鏇挎崲鍚庣殑瀛楃
+ */
+ public static String toDBC(String text, Set<Character> notConvertSet)
+ {
+ char[] c = text.toCharArray();
+ for (int i = 0; i < c.length; i++)
+ {
+ if (null != notConvertSet && notConvertSet.contains(c[i]))
+ {
+ // 璺宠繃涓嶆浛鎹㈢殑瀛楃
+ continue;
+ }
+
+ if (c[i] == '\u3000')
+ {
+ c[i] = ' ';
+ }
+ else if (c[i] > '\uFF00' && c[i] < '\uFF5F')
+ {
+ c[i] = (char) (c[i] - 65248);
+ }
+ }
+ String returnString = new String(c);
+
+ return returnString;
+ }
+
+ /**
+ * 鏁板瓧閲戦澶у啓杞崲 鍏堝啓涓畬鏁寸殑鐒跺悗灏嗗闆舵嬀鏇挎崲鎴愰浂
+ *
+ * @param n 鏁板瓧
+ * @return 涓枃澶у啓鏁板瓧
+ */
+ public static String digitUppercase(double n)
+ {
+ String[] fraction = { "瑙�", "鍒�" };
+ String[] digit = { "闆�", "澹�", "璐�", "鍙�", "鑲�", "浼�", "闄�", "鏌�", "鎹�", "鐜�" };
+ String[][] unit = { { "鍏�", "涓�", "浜�" }, { "", "鎷�", "浣�", "浠�" } };
+
+ String head = n < 0 ? "璐�" : "";
+ n = Math.abs(n);
+
+ String s = "";
+ for (int i = 0; i < fraction.length; i++)
+ {
+ // 浼樺寲double璁$畻绮惧害涓㈠け闂
+ BigDecimal nNum = new BigDecimal(n);
+ BigDecimal decimal = new BigDecimal(10);
+ BigDecimal scale = nNum.multiply(decimal).setScale(2, RoundingMode.HALF_EVEN);
+ double d = scale.doubleValue();
+ s += (digit[(int) (Math.floor(d * Math.pow(10, i)) % 10)] + fraction[i]).replaceAll("(闆�.)+", "");
+ }
+ if (s.length() < 1)
+ {
+ s = "鏁�";
+ }
+ int integerPart = (int) Math.floor(n);
+
+ for (int i = 0; i < unit[0].length && integerPart > 0; i++)
+ {
+ String p = "";
+ for (int j = 0; j < unit[1].length && n > 0; j++)
+ {
+ p = digit[integerPart % 10] + unit[1][j] + p;
+ integerPart = integerPart / 10;
+ }
+ s = p.replaceAll("(闆�.)*闆�$", "").replaceAll("^$", "闆�") + unit[0][i] + s;
+ }
+ return head + s.replaceAll("(闆�.)*闆跺厓", "鍏�").replaceFirst("(闆�.)+", "").replaceAll("(闆�.)+", "闆�").replaceAll("^鏁�$", "闆跺厓鏁�");
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
new file mode 100644
index 0000000..c78ac77
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/text/StrFormatter.java
@@ -0,0 +1,92 @@
+package com.ruoyi.common.core.text;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 瀛楃涓叉牸寮忓寲
+ *
+ * @author ruoyi
+ */
+public class StrFormatter
+{
+ public static final String EMPTY_JSON = "{}";
+ public static final char C_BACKSLASH = '\\';
+ public static final char C_DELIM_START = '{';
+ public static final char C_DELIM_END = '}';
+
+ /**
+ * 鏍煎紡鍖栧瓧绗︿覆<br>
+ * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
+ * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
+ * 渚嬶細<br>
+ * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
+ * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+ * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+ *
+ * @param strPattern 瀛楃涓叉ā鏉�
+ * @param argArray 鍙傛暟鍒楄〃
+ * @return 缁撴灉
+ */
+ public static String format(final String strPattern, final Object... argArray)
+ {
+ if (StringUtils.isEmpty(strPattern) || StringUtils.isEmpty(argArray))
+ {
+ return strPattern;
+ }
+ final int strPatternLength = strPattern.length();
+
+ // 鍒濆鍖栧畾涔夊ソ鐨勯暱搴︿互鑾峰緱鏇村ソ鐨勬�ц兘
+ StringBuilder sbuf = new StringBuilder(strPatternLength + 50);
+
+ int handledPosition = 0;
+ int delimIndex;// 鍗犱綅绗︽墍鍦ㄤ綅缃�
+ for (int argIndex = 0; argIndex < argArray.length; argIndex++)
+ {
+ delimIndex = strPattern.indexOf(EMPTY_JSON, handledPosition);
+ if (delimIndex == -1)
+ {
+ if (handledPosition == 0)
+ {
+ return strPattern;
+ }
+ else
+ { // 瀛楃涓叉ā鏉垮墿浣欓儴鍒嗕笉鍐嶅寘鍚崰浣嶇锛屽姞鍏ュ墿浣欓儴鍒嗗悗杩斿洖缁撴灉
+ sbuf.append(strPattern, handledPosition, strPatternLength);
+ return sbuf.toString();
+ }
+ }
+ else
+ {
+ if (delimIndex > 0 && strPattern.charAt(delimIndex - 1) == C_BACKSLASH)
+ {
+ if (delimIndex > 1 && strPattern.charAt(delimIndex - 2) == C_BACKSLASH)
+ {
+ // 杞箟绗︿箣鍓嶈繕鏈変竴涓浆涔夌锛屽崰浣嶇渚濇棫鏈夋晥
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ }
+ else
+ {
+ // 鍗犱綅绗﹁杞箟
+ argIndex--;
+ sbuf.append(strPattern, handledPosition, delimIndex - 1);
+ sbuf.append(C_DELIM_START);
+ handledPosition = delimIndex + 1;
+ }
+ }
+ else
+ {
+ // 姝e父鍗犱綅绗�
+ sbuf.append(strPattern, handledPosition, delimIndex);
+ sbuf.append(Convert.utf8Str(argArray[argIndex]));
+ handledPosition = delimIndex + 2;
+ }
+ }
+ }
+ // 鍔犲叆鏈�鍚庝竴涓崰浣嶇鍚庢墍鏈夌殑瀛楃
+ sbuf.append(strPattern, handledPosition, strPattern.length());
+
+ return sbuf.toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
new file mode 100644
index 0000000..10b7306
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessStatus.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 鎿嶄綔鐘舵��
+ *
+ * @author ruoyi
+ *
+ */
+public enum BusinessStatus
+{
+ /**
+ * 鎴愬姛
+ */
+ SUCCESS,
+
+ /**
+ * 澶辫触
+ */
+ FAIL,
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
new file mode 100644
index 0000000..2e17c4a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/BusinessType.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 涓氬姟鎿嶄綔绫诲瀷
+ *
+ * @author ruoyi
+ */
+public enum BusinessType
+{
+ /**
+ * 鍏跺畠
+ */
+ OTHER,
+
+ /**
+ * 鏂板
+ */
+ INSERT,
+
+ /**
+ * 淇敼
+ */
+ UPDATE,
+
+ /**
+ * 鍒犻櫎
+ */
+ DELETE,
+
+ /**
+ * 鎺堟潈
+ */
+ GRANT,
+
+ /**
+ * 瀵煎嚭
+ */
+ EXPORT,
+
+ /**
+ * 瀵煎叆
+ */
+ IMPORT,
+
+ /**
+ * 寮洪��
+ */
+ FORCE,
+
+ /**
+ * 鐢熸垚浠g爜
+ */
+ GENCODE,
+
+ /**
+ * 娓呯┖鏁版嵁
+ */
+ CLEAN,
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
new file mode 100644
index 0000000..0d945be
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DataSourceType.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 鏁版嵁婧�
+ *
+ * @author ruoyi
+ */
+public enum DataSourceType
+{
+ /**
+ * 涓诲簱
+ */
+ MASTER,
+
+ /**
+ * 浠庡簱
+ */
+ SLAVE
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
new file mode 100644
index 0000000..07f02ee
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/DesensitizedType.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.enums;
+
+import java.util.function.Function;
+import com.ruoyi.common.utils.DesensitizedUtil;
+
+/**
+ * 鑴辨晱绫诲瀷
+ *
+ * @author ruoyi
+ */
+public enum DesensitizedType
+{
+ /**
+ * 濮撳悕锛岀2浣嶆槦鍙锋浛鎹�
+ */
+ USERNAME(s -> s.replaceAll("(\\S)\\S(\\S*)", "$1*$2")),
+
+ /**
+ * 瀵嗙爜锛屽叏閮ㄥ瓧绗﹂兘鐢�*浠f浛
+ */
+ PASSWORD(DesensitizedUtil::password),
+
+ /**
+ * 韬唤璇侊紝涓棿10浣嶆槦鍙锋浛鎹�
+ */
+ ID_CARD(s -> s.replaceAll("(\\d{4})\\d{10}(\\d{3}[Xx]|\\d{4})", "$1** **** ****$2")),
+
+ /**
+ * 鎵嬫満鍙凤紝涓棿4浣嶆槦鍙锋浛鎹�
+ */
+ PHONE(s -> s.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2")),
+
+ /**
+ * 鐢靛瓙閭锛屼粎鏄剧ず绗竴涓瓧姣嶅拰@鍚庨潰鐨勫湴鍧�鏄剧ず锛屽叾浠栨槦鍙锋浛鎹�
+ */
+ EMAIL(s -> s.replaceAll("(^.)[^@]*(@.*$)", "$1****$2")),
+
+ /**
+ * 閾惰鍗″彿锛屼繚鐣欐渶鍚�4浣嶏紝鍏朵粬鏄熷彿鏇挎崲
+ */
+ BANK_CARD(s -> s.replaceAll("\\d{15}(\\d{3})", "**** **** **** **** $1")),
+
+ /**
+ * 杞︾墝鍙风爜锛屽寘鍚櫘閫氳溅杈嗐�佹柊鑳芥簮杞﹁締
+ */
+ CAR_LICENSE(DesensitizedUtil::carLicense);
+
+ private final Function<String, String> desensitizer;
+
+ DesensitizedType(Function<String, String> desensitizer)
+ {
+ this.desensitizer = desensitizer;
+ }
+
+ public Function<String, String> desensitizer()
+ {
+ return desensitizer;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java
new file mode 100644
index 0000000..be6f739
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/HttpMethod.java
@@ -0,0 +1,36 @@
+package com.ruoyi.common.enums;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.springframework.lang.Nullable;
+
+/**
+ * 璇锋眰鏂瑰紡
+ *
+ * @author ruoyi
+ */
+public enum HttpMethod
+{
+ GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, TRACE;
+
+ private static final Map<String, HttpMethod> mappings = new HashMap<>(16);
+
+ static
+ {
+ for (HttpMethod httpMethod : values())
+ {
+ mappings.put(httpMethod.name(), httpMethod);
+ }
+ }
+
+ @Nullable
+ public static HttpMethod resolve(@Nullable String method)
+ {
+ return (method != null ? mappings.get(method) : null);
+ }
+
+ public boolean matches(String method)
+ {
+ return (this == resolve(method));
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
new file mode 100644
index 0000000..c609fd8
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/LimitType.java
@@ -0,0 +1,20 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 闄愭祦绫诲瀷
+ *
+ * @author ruoyi
+ */
+
+public enum LimitType
+{
+ /**
+ * 榛樿绛栫暐鍏ㄥ眬闄愭祦
+ */
+ DEFAULT,
+
+ /**
+ * 鏍规嵁璇锋眰鑰匢P杩涜闄愭祦
+ */
+ IP
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
new file mode 100644
index 0000000..bdd143c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/OperatorType.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 鎿嶄綔浜虹被鍒�
+ *
+ * @author ruoyi
+ */
+public enum OperatorType
+{
+ /**
+ * 鍏跺畠
+ */
+ OTHER,
+
+ /**
+ * 鍚庡彴鐢ㄦ埛
+ */
+ MANAGE,
+
+ /**
+ * 鎵嬫満绔敤鎴�
+ */
+ MOBILE
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
new file mode 100644
index 0000000..d7ff44a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/enums/UserStatus.java
@@ -0,0 +1,30 @@
+package com.ruoyi.common.enums;
+
+/**
+ * 鐢ㄦ埛鐘舵��
+ *
+ * @author ruoyi
+ */
+public enum UserStatus
+{
+ OK("0", "姝e父"), DISABLE("1", "鍋滅敤"), DELETED("2", "鍒犻櫎");
+
+ private final String code;
+ private final String info;
+
+ UserStatus(String code, String info)
+ {
+ this.code = code;
+ this.info = info;
+ }
+
+ public String getCode()
+ {
+ return code;
+ }
+
+ public String getInfo()
+ {
+ return info;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
new file mode 100644
index 0000000..f6ad2ab
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/DemoModeException.java
@@ -0,0 +1,15 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 婕旂ず妯″紡寮傚父
+ *
+ * @author ruoyi
+ */
+public class DemoModeException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ public DemoModeException()
+ {
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
new file mode 100644
index 0000000..81a71b5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/GlobalException.java
@@ -0,0 +1,58 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 鍏ㄥ眬寮傚父
+ *
+ * @author ruoyi
+ */
+public class GlobalException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 閿欒鎻愮ず
+ */
+ private String message;
+
+ /**
+ * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+ *
+ * 鍜� {@link CommonResult#getDetailMessage()} 涓�鑷寸殑璁捐
+ */
+ private String detailMessage;
+
+ /**
+ * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+ */
+ public GlobalException()
+ {
+ }
+
+ public GlobalException(String message)
+ {
+ this.message = message;
+ }
+
+ public String getDetailMessage()
+ {
+ return detailMessage;
+ }
+
+ public GlobalException setDetailMessage(String detailMessage)
+ {
+ this.detailMessage = detailMessage;
+ return this;
+ }
+
+ @Override
+ public String getMessage()
+ {
+ return message;
+ }
+
+ public GlobalException setMessage(String message)
+ {
+ this.message = message;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
new file mode 100644
index 0000000..fcc7ab6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/ServiceException.java
@@ -0,0 +1,74 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 涓氬姟寮傚父
+ *
+ * @author ruoyi
+ */
+public final class ServiceException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 閿欒鐮�
+ */
+ private Integer code;
+
+ /**
+ * 閿欒鎻愮ず
+ */
+ private String message;
+
+ /**
+ * 閿欒鏄庣粏锛屽唴閮ㄨ皟璇曢敊璇�
+ *
+ * 鍜� {@link CommonResult#getDetailMessage()} 涓�鑷寸殑璁捐
+ */
+ private String detailMessage;
+
+ /**
+ * 绌烘瀯閫犳柟娉曪紝閬垮厤鍙嶅簭鍒楀寲闂
+ */
+ public ServiceException()
+ {
+ }
+
+ public ServiceException(String message)
+ {
+ this.message = message;
+ }
+
+ public ServiceException(String message, Integer code)
+ {
+ this.message = message;
+ this.code = code;
+ }
+
+ public String getDetailMessage()
+ {
+ return detailMessage;
+ }
+
+ @Override
+ public String getMessage()
+ {
+ return message;
+ }
+
+ public Integer getCode()
+ {
+ return code;
+ }
+
+ public ServiceException setMessage(String message)
+ {
+ this.message = message;
+ return this;
+ }
+
+ public ServiceException setDetailMessage(String detailMessage)
+ {
+ this.detailMessage = detailMessage;
+ return this;
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
new file mode 100644
index 0000000..980fa46
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/UtilException.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.exception;
+
+/**
+ * 宸ュ叿绫诲紓甯�
+ *
+ * @author ruoyi
+ */
+public class UtilException extends RuntimeException
+{
+ private static final long serialVersionUID = 8247610319171014183L;
+
+ public UtilException(Throwable e)
+ {
+ super(e.getMessage(), e);
+ }
+
+ public UtilException(String message)
+ {
+ super(message);
+ }
+
+ public UtilException(String message, Throwable throwable)
+ {
+ super(message, throwable);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
new file mode 100644
index 0000000..b55d72e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/base/BaseException.java
@@ -0,0 +1,97 @@
+package com.ruoyi.common.exception.base;
+
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 鍩虹寮傚父
+ *
+ * @author ruoyi
+ */
+public class BaseException extends RuntimeException
+{
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * 鎵�灞炴ā鍧�
+ */
+ private String module;
+
+ /**
+ * 閿欒鐮�
+ */
+ private String code;
+
+ /**
+ * 閿欒鐮佸搴旂殑鍙傛暟
+ */
+ private Object[] args;
+
+ /**
+ * 閿欒娑堟伅
+ */
+ private String defaultMessage;
+
+ public BaseException(String module, String code, Object[] args, String defaultMessage)
+ {
+ this.module = module;
+ this.code = code;
+ this.args = args;
+ this.defaultMessage = defaultMessage;
+ }
+
+ public BaseException(String module, String code, Object[] args)
+ {
+ this(module, code, args, null);
+ }
+
+ public BaseException(String module, String defaultMessage)
+ {
+ this(module, null, null, defaultMessage);
+ }
+
+ public BaseException(String code, Object[] args)
+ {
+ this(null, code, args, null);
+ }
+
+ public BaseException(String defaultMessage)
+ {
+ this(null, null, null, defaultMessage);
+ }
+
+ @Override
+ public String getMessage()
+ {
+ String message = null;
+ if (!StringUtils.isEmpty(code))
+ {
+ message = MessageUtils.message(code, args);
+ }
+ if (message == null)
+ {
+ message = defaultMessage;
+ }
+ return message;
+ }
+
+ public String getModule()
+ {
+ return module;
+ }
+
+ public String getCode()
+ {
+ return code;
+ }
+
+ public Object[] getArgs()
+ {
+ return args;
+ }
+
+ public String getDefaultMessage()
+ {
+ return defaultMessage;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
new file mode 100644
index 0000000..871f09b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileException.java
@@ -0,0 +1,19 @@
+package com.ruoyi.common.exception.file;
+
+import com.ruoyi.common.exception.base.BaseException;
+
+/**
+ * 鏂囦欢淇℃伅寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class FileException extends BaseException
+{
+ private static final long serialVersionUID = 1L;
+
+ public FileException(String code, Object[] args)
+ {
+ super("file", code, args, null);
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
new file mode 100644
index 0000000..70e0ec9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileNameLengthLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.file;
+
+/**
+ * 鏂囦欢鍚嶇О瓒呴暱闄愬埗寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class FileNameLengthLimitExceededException extends FileException
+{
+ private static final long serialVersionUID = 1L;
+
+ public FileNameLengthLimitExceededException(int defaultFileNameLength)
+ {
+ super("upload.filename.exceed.length", new Object[] { defaultFileNameLength });
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
new file mode 100644
index 0000000..ec6ab05
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileSizeLimitExceededException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.file;
+
+/**
+ * 鏂囦欢鍚嶅ぇ灏忛檺鍒跺紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class FileSizeLimitExceededException extends FileException
+{
+ private static final long serialVersionUID = 1L;
+
+ public FileSizeLimitExceededException(long defaultMaxSize)
+ {
+ super("upload.exceed.maxSize", new Object[] { defaultMaxSize });
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java
new file mode 100644
index 0000000..f45e7ef
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/FileUploadException.java
@@ -0,0 +1,61 @@
+package com.ruoyi.common.exception.file;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * 鏂囦欢涓婁紶寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class FileUploadException extends Exception
+{
+
+ private static final long serialVersionUID = 1L;
+
+ private final Throwable cause;
+
+ public FileUploadException()
+ {
+ this(null, null);
+ }
+
+ public FileUploadException(final String msg)
+ {
+ this(msg, null);
+ }
+
+ public FileUploadException(String msg, Throwable cause)
+ {
+ super(msg);
+ this.cause = cause;
+ }
+
+ @Override
+ public void printStackTrace(PrintStream stream)
+ {
+ super.printStackTrace(stream);
+ if (cause != null)
+ {
+ stream.println("Caused by:");
+ cause.printStackTrace(stream);
+ }
+ }
+
+ @Override
+ public void printStackTrace(PrintWriter writer)
+ {
+ super.printStackTrace(writer);
+ if (cause != null)
+ {
+ writer.println("Caused by:");
+ cause.printStackTrace(writer);
+ }
+ }
+
+ @Override
+ public Throwable getCause()
+ {
+ return cause;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java
new file mode 100644
index 0000000..011f308
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/file/InvalidExtensionException.java
@@ -0,0 +1,80 @@
+package com.ruoyi.common.exception.file;
+
+import java.util.Arrays;
+
+/**
+ * 鏂囦欢涓婁紶 璇紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class InvalidExtensionException extends FileUploadException
+{
+ private static final long serialVersionUID = 1L;
+
+ private String[] allowedExtension;
+ private String extension;
+ private String filename;
+
+ public InvalidExtensionException(String[] allowedExtension, String extension, String filename)
+ {
+ super("鏂囦欢[" + filename + "]鍚庣紑[" + extension + "]涓嶆纭紝璇蜂笂浼�" + Arrays.toString(allowedExtension) + "鏍煎紡");
+ this.allowedExtension = allowedExtension;
+ this.extension = extension;
+ this.filename = filename;
+ }
+
+ public String[] getAllowedExtension()
+ {
+ return allowedExtension;
+ }
+
+ public String getExtension()
+ {
+ return extension;
+ }
+
+ public String getFilename()
+ {
+ return filename;
+ }
+
+ public static class InvalidImageExtensionException extends InvalidExtensionException
+ {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidImageExtensionException(String[] allowedExtension, String extension, String filename)
+ {
+ super(allowedExtension, extension, filename);
+ }
+ }
+
+ public static class InvalidFlashExtensionException extends InvalidExtensionException
+ {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidFlashExtensionException(String[] allowedExtension, String extension, String filename)
+ {
+ super(allowedExtension, extension, filename);
+ }
+ }
+
+ public static class InvalidMediaExtensionException extends InvalidExtensionException
+ {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidMediaExtensionException(String[] allowedExtension, String extension, String filename)
+ {
+ super(allowedExtension, extension, filename);
+ }
+ }
+
+ public static class InvalidVideoExtensionException extends InvalidExtensionException
+ {
+ private static final long serialVersionUID = 1L;
+
+ public InvalidVideoExtensionException(String[] allowedExtension, String extension, String filename)
+ {
+ super(allowedExtension, extension, filename);
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java
new file mode 100644
index 0000000..a567b40
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/job/TaskException.java
@@ -0,0 +1,34 @@
+package com.ruoyi.common.exception.job;
+
+/**
+ * 璁″垝绛栫暐寮傚父
+ *
+ * @author ruoyi
+ */
+public class TaskException extends Exception
+{
+ private static final long serialVersionUID = 1L;
+
+ private Code code;
+
+ public TaskException(String msg, Code code)
+ {
+ this(msg, code, null);
+ }
+
+ public TaskException(String msg, Code code, Exception nestedEx)
+ {
+ super(msg, nestedEx);
+ this.code = code;
+ }
+
+ public Code getCode()
+ {
+ return code;
+ }
+
+ public enum Code
+ {
+ TASK_EXISTS, NO_TASK_EXISTS, TASK_ALREADY_STARTED, UNKNOWN, CONFIG_ERROR, TASK_NODE_NOT_AVAILABLE
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java
new file mode 100644
index 0000000..2bf5038
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/BlackListException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 榛戝悕鍗旾P寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class BlackListException extends UserException
+{
+ private static final long serialVersionUID = 1L;
+
+ public BlackListException()
+ {
+ super("login.blocked", null);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
new file mode 100644
index 0000000..389dbc7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 楠岃瘉鐮侀敊璇紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class CaptchaException extends UserException
+{
+ private static final long serialVersionUID = 1L;
+
+ public CaptchaException()
+ {
+ super("user.jcaptcha.error", null);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java
new file mode 100644
index 0000000..85f9486
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/CaptchaExpireException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 楠岃瘉鐮佸け鏁堝紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class CaptchaExpireException extends UserException
+{
+ private static final long serialVersionUID = 1L;
+
+ public CaptchaExpireException()
+ {
+ super("user.jcaptcha.expire", null);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
new file mode 100644
index 0000000..c292d70
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserException.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.exception.user;
+
+import com.ruoyi.common.exception.base.BaseException;
+
+/**
+ * 鐢ㄦ埛淇℃伅寮傚父绫�
+ *
+ * @author ruoyi
+ */
+public class UserException extends BaseException
+{
+ private static final long serialVersionUID = 1L;
+
+ public UserException(String code, Object[] args)
+ {
+ super("user", code, args, null);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java
new file mode 100644
index 0000000..eff8181
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserNotExistsException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 鐢ㄦ埛涓嶅瓨鍦ㄥ紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class UserNotExistsException extends UserException
+{
+ private static final long serialVersionUID = 1L;
+
+ public UserNotExistsException()
+ {
+ super("user.not.exists", null);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
new file mode 100644
index 0000000..a7f3e5f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordNotMatchException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 鐢ㄦ埛瀵嗙爜涓嶆纭垨涓嶇鍚堣鑼冨紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class UserPasswordNotMatchException extends UserException
+{
+ private static final long serialVersionUID = 1L;
+
+ public UserPasswordNotMatchException()
+ {
+ super("user.password.not.match", null);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
new file mode 100644
index 0000000..c887cf1
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/exception/user/UserPasswordRetryLimitExceedException.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.exception.user;
+
+/**
+ * 鐢ㄦ埛閿欒鏈�澶ф鏁板紓甯哥被
+ *
+ * @author ruoyi
+ */
+public class UserPasswordRetryLimitExceedException extends UserException
+{
+ private static final long serialVersionUID = 1L;
+
+ public UserPasswordRetryLimitExceedException(int retryLimitCount, int lockTime)
+ {
+ super("user.password.retry.limit.exceed", new Object[] { retryLimitCount, lockTime });
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java
new file mode 100644
index 0000000..e1e431b
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/PropertyPreExcludeFilter.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.filter;
+
+import com.alibaba.fastjson2.filter.SimplePropertyPreFilter;
+
+/**
+ * 鎺掗櫎JSON鏁忔劅灞炴��
+ *
+ * @author ruoyi
+ */
+public class PropertyPreExcludeFilter extends SimplePropertyPreFilter
+{
+ public PropertyPreExcludeFilter()
+ {
+ }
+
+ public PropertyPreExcludeFilter addExcludes(String... filters)
+ {
+ for (int i = 0; i < filters.length; i++)
+ {
+ this.getExcludes().add(filters[i]);
+ }
+ return this;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
new file mode 100644
index 0000000..a1bcfe2
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatableFilter.java
@@ -0,0 +1,52 @@
+package com.ruoyi.common.filter;
+
+import java.io.IOException;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.http.MediaType;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * Repeatable 杩囨护鍣�
+ *
+ * @author ruoyi
+ */
+public class RepeatableFilter implements Filter
+{
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException
+ {
+ ServletRequest requestWrapper = null;
+ if (request instanceof HttpServletRequest
+ && StringUtils.startsWithIgnoreCase(request.getContentType(), MediaType.APPLICATION_JSON_VALUE))
+ {
+ requestWrapper = new RepeatedlyRequestWrapper((HttpServletRequest) request, response);
+ }
+ if (null == requestWrapper)
+ {
+ chain.doFilter(request, response);
+ }
+ else
+ {
+ chain.doFilter(requestWrapper, response);
+ }
+ }
+
+ @Override
+ public void destroy()
+ {
+
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
new file mode 100644
index 0000000..407d1ba
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/RepeatedlyRequestWrapper.java
@@ -0,0 +1,76 @@
+package com.ruoyi.common.filter;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import com.ruoyi.common.utils.http.HttpHelper;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * 鏋勫缓鍙噸澶嶈鍙杋nputStream鐨剅equest
+ *
+ * @author ruoyi
+ */
+public class RepeatedlyRequestWrapper extends HttpServletRequestWrapper
+{
+ private final byte[] body;
+
+ public RepeatedlyRequestWrapper(HttpServletRequest request, ServletResponse response) throws IOException
+ {
+ super(request);
+ request.setCharacterEncoding(Constants.UTF8);
+ response.setCharacterEncoding(Constants.UTF8);
+
+ body = HttpHelper.getBodyString(request).getBytes(Constants.UTF8);
+ }
+
+ @Override
+ public BufferedReader getReader() throws IOException
+ {
+ return new BufferedReader(new InputStreamReader(getInputStream()));
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException
+ {
+ final ByteArrayInputStream bais = new ByteArrayInputStream(body);
+ return new ServletInputStream()
+ {
+ @Override
+ public int read() throws IOException
+ {
+ return bais.read();
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ return body.length;
+ }
+
+ @Override
+ public boolean isFinished()
+ {
+ return false;
+ }
+
+ @Override
+ public boolean isReady()
+ {
+ return false;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener)
+ {
+
+ }
+ };
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
new file mode 100644
index 0000000..5c4cbe4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssFilter.java
@@ -0,0 +1,75 @@
+package com.ruoyi.common.filter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.enums.HttpMethod;
+
+/**
+ * 闃叉XSS鏀诲嚮鐨勮繃婊ゅ櫒
+ *
+ * @author ruoyi
+ */
+public class XssFilter implements Filter
+{
+ /**
+ * 鎺掗櫎閾炬帴
+ */
+ public List<String> excludes = new ArrayList<>();
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException
+ {
+ String tempExcludes = filterConfig.getInitParameter("excludes");
+ if (StringUtils.isNotEmpty(tempExcludes))
+ {
+ String[] urls = tempExcludes.split(",");
+ for (String url : urls)
+ {
+ excludes.add(url);
+ }
+ }
+ }
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException
+ {
+ HttpServletRequest req = (HttpServletRequest) request;
+ HttpServletResponse resp = (HttpServletResponse) response;
+ if (handleExcludeURL(req, resp))
+ {
+ chain.doFilter(request, response);
+ return;
+ }
+ XssHttpServletRequestWrapper xssRequest = new XssHttpServletRequestWrapper((HttpServletRequest) request);
+ chain.doFilter(xssRequest, response);
+ }
+
+ private boolean handleExcludeURL(HttpServletRequest request, HttpServletResponse response)
+ {
+ String url = request.getServletPath();
+ String method = request.getMethod();
+ // GET DELETE 涓嶈繃婊�
+ if (method == null || HttpMethod.GET.matches(method) || HttpMethod.DELETE.matches(method))
+ {
+ return true;
+ }
+ return StringUtils.matches(url, excludes);
+ }
+
+ @Override
+ public void destroy()
+ {
+
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
new file mode 100644
index 0000000..05149f0
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/filter/XssHttpServletRequestWrapper.java
@@ -0,0 +1,111 @@
+package com.ruoyi.common.filter;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import javax.servlet.ReadListener;
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import org.apache.commons.io.IOUtils;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.html.EscapeUtil;
+
+/**
+ * XSS杩囨护澶勭悊
+ *
+ * @author ruoyi
+ */
+public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper
+{
+ /**
+ * @param request
+ */
+ public XssHttpServletRequestWrapper(HttpServletRequest request)
+ {
+ super(request);
+ }
+
+ @Override
+ public String[] getParameterValues(String name)
+ {
+ String[] values = super.getParameterValues(name);
+ if (values != null)
+ {
+ int length = values.length;
+ String[] escapesValues = new String[length];
+ for (int i = 0; i < length; i++)
+ {
+ // 闃瞲ss鏀诲嚮鍜岃繃婊ゅ墠鍚庣┖鏍�
+ escapesValues[i] = EscapeUtil.clean(values[i]).trim();
+ }
+ return escapesValues;
+ }
+ return super.getParameterValues(name);
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws IOException
+ {
+ // 闈瀓son绫诲瀷锛岀洿鎺ヨ繑鍥�
+ if (!isJsonRequest())
+ {
+ return super.getInputStream();
+ }
+
+ // 涓虹┖锛岀洿鎺ヨ繑鍥�
+ String json = IOUtils.toString(super.getInputStream(), "utf-8");
+ if (StringUtils.isEmpty(json))
+ {
+ return super.getInputStream();
+ }
+
+ // xss杩囨护
+ json = EscapeUtil.clean(json).trim();
+ byte[] jsonBytes = json.getBytes("utf-8");
+ final ByteArrayInputStream bis = new ByteArrayInputStream(jsonBytes);
+ return new ServletInputStream()
+ {
+ @Override
+ public boolean isFinished()
+ {
+ return true;
+ }
+
+ @Override
+ public boolean isReady()
+ {
+ return true;
+ }
+
+ @Override
+ public int available() throws IOException
+ {
+ return jsonBytes.length;
+ }
+
+ @Override
+ public void setReadListener(ReadListener readListener)
+ {
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ return bis.read();
+ }
+ };
+ }
+
+ /**
+ * 鏄惁鏄疛son璇锋眰
+ *
+ * @param request
+ */
+ public boolean isJsonRequest()
+ {
+ String header = super.getHeader(HttpHeaders.CONTENT_TYPE);
+ return StringUtils.startsWithIgnoreCase(header, MediaType.APPLICATION_JSON_VALUE);
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/handler/MybatisHandler.java b/ruoyi-common/src/main/java/com/ruoyi/common/handler/MybatisHandler.java
new file mode 100644
index 0000000..3f0d883
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/handler/MybatisHandler.java
@@ -0,0 +1,38 @@
+package com.ruoyi.common.handler;
+
+import cn.hutool.json.JSONUtil;
+import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import org.apache.ibatis.reflection.MetaObject;
+import org.springframework.stereotype.Component;
+
+import java.time.LocalDateTime;
+
+@Component
+public class MybatisHandler implements MetaObjectHandler {
+ @Override
+ public void insertFill(MetaObject metaObject) {
+ Integer userId = null;
+ try {
+ userId = SecurityUtils.getUserId().intValue();
+ } catch (Exception ignored) {
+ }
+ System.out.println("鎵ц鎻掑叆濉厖...");
+ this.strictInsertFill(metaObject, "createTime", LocalDateTime.class, LocalDateTime.now());
+ this.strictInsertFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now());
+ this.strictInsertFill(metaObject, "createUser", Integer.class, userId);
+ this.strictInsertFill(metaObject, "updateUser", Integer.class, userId);
+ }
+
+ @Override
+ public void updateFill(MetaObject metaObject) {
+ Integer userId = null;
+ try {
+ userId = SecurityUtils.getUserId().intValue();
+ } catch (Exception ignored) {
+ }
+ this.strictUpdateFill(metaObject, "updateTime", LocalDateTime.class, LocalDateTime.now()); // 璧峰鐗堟湰 3.3.0(鎺ㄨ崘)
+ this.strictUpdateFill(metaObject, "updateUser", Integer.class, userId);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/numgen/LambdaUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/LambdaUtils.java
new file mode 100644
index 0000000..f8288ce
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/LambdaUtils.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <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 com.ruoyi.common.numgen;
+
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.baomidou.mybatisplus.core.toolkit.support.ColumnCache;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+
+import java.lang.ref.WeakReference;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.ConcurrentHashMap;
+
+import static java.util.Locale.ENGLISH;
+
+/**
+ * Lambda 瑙f瀽宸ュ叿绫�
+ *
+ * @author HCL, MieMie
+ * @since 2018-05-10
+ */
+public final class LambdaUtils {
+
+ /**
+ * 瀛楁鏄犲皠
+ */
+ private static final Map<String, Map<String, ColumnCache>> COLUMN_CACHE_MAP = new ConcurrentHashMap<>();
+
+ /**
+ * SerializedLambda 鍙嶅簭鍒楀寲缂撳瓨
+ */
+ private static final Map<String, WeakReference<SerializedLambda>> FUNC_CACHE = new ConcurrentHashMap<>();
+
+ /**
+ * 瑙f瀽 lambda 琛ㄨ揪寮�, 璇ユ柟娉曞彧鏄皟鐢ㄤ簡 {@link SerializedLambda#resolve(SFunction)} 涓殑鏂规硶锛屽湪姝ゅ熀纭�涓婂姞浜嗙紦瀛樸��
+ * 璇ョ紦瀛樺彲鑳戒細鍦ㄤ换鎰忎笉瀹氱殑鏃堕棿琚竻闄�
+ *
+ * @param func 闇�瑕佽В鏋愮殑 lambda 瀵硅薄
+ * @param <T> 绫诲瀷锛岃璋冪敤鐨� Function 瀵硅薄鐨勭洰鏍囩被鍨�
+ * @return 杩斿洖瑙f瀽鍚庣殑缁撴灉
+ * @see SerializedLambda#resolve(SFunction)
+ */
+ public static <T> SerializedLambda resolve(SFunction<T, ?> func) {
+ Class<?> clazz = func.getClass();
+ String canonicalName = clazz.getCanonicalName();
+ return Optional.ofNullable(FUNC_CACHE.get(canonicalName))
+ .map(WeakReference::get)
+ .orElseGet(() -> {
+ SerializedLambda lambda = SerializedLambda.resolve(func);
+ FUNC_CACHE.put(canonicalName, new WeakReference<>(lambda));
+ return lambda;
+ });
+ }
+
+ /**
+ * 鏍煎紡鍖� key 灏嗕紶鍏ョ殑 key 鍙樻洿涓哄ぇ鍐欐牸寮�
+ *
+ * <pre>
+ * Assert.assertEquals("USERID", formatKey("userId"))
+ * </pre>
+ *
+ * @param key key
+ * @return 澶у啓鐨� key
+ */
+ public static String formatKey(String key) {
+ return key.toUpperCase(ENGLISH);
+ }
+
+ /**
+ * 灏嗕紶鍏ョ殑琛ㄤ俊鎭姞鍏ョ紦瀛�
+ *
+ * @param tableInfo 琛ㄤ俊鎭�
+ */
+ public static void installCache(TableInfo tableInfo) {
+ COLUMN_CACHE_MAP.put(tableInfo.getEntityType().getName(), createColumnCacheMap(tableInfo));
+ }
+
+ /**
+ * 缂撳瓨瀹炰綋瀛楁 MAP 淇℃伅
+ *
+ * @param info 琛ㄤ俊鎭�
+ * @return 缂撳瓨 map
+ */
+ private static Map<String, ColumnCache> createColumnCacheMap(TableInfo info) {
+ Map<String, ColumnCache> map = new HashMap<>();
+
+ String kp = info.getKeyProperty();
+ if (StringUtils.isNotBlank(kp)) {
+ map.put(formatKey(kp), new ColumnCache(info.getKeyColumn(), info.getKeySqlSelect()));
+ }
+
+ info.getFieldList().forEach(i ->
+ map.put(formatKey(i.getProperty()), new ColumnCache(i.getColumn(), i.getSqlSelect()))
+ );
+ return map;
+ }
+
+ /**
+ * 鑾峰彇瀹炰綋瀵瑰簲瀛楁 MAP
+ *
+ * @param clazz 瀹炰綋绫�
+ * @return 缂撳瓨 map
+ */
+ public static Map<String, ColumnCache> getColumnMap(Class<?> clazz) {
+ return COLUMN_CACHE_MAP.computeIfAbsent(clazz.getName(), key -> {
+ TableInfo info = TableInfoHelper.getTableInfo(clazz);
+ return info == null ? null : createColumnCacheMap(info);
+ });
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGenerator.java b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGenerator.java
new file mode 100644
index 0000000..3b933bb
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGenerator.java
@@ -0,0 +1,146 @@
+package com.ruoyi.common.numgen;
+
+import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.core.metadata.TableInfoHelper;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+import lombok.AllArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.ibatis.reflection.property.PropertyNamer;
+import org.springframework.stereotype.Service;
+
+import java.util.Optional;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+
+/**
+ * 缂栧彿鐢熸垚鍣�
+ *
+ * @Author: zhangxy
+ * @Date: 2020-09-08 16:31
+ */
+@Slf4j
+@Service
+@AllArgsConstructor
+public class NumberGenerator<T> {
+
+ private static Pattern NUMBER_PATTERN = Pattern.compile("(.+)\\((\\d+)\\)");
+
+ private NumberGeneratorModelHelper numberGeneratorModelHelper;
+
+
+ public String getCopyValueOfUniqueField(final String value, SFunction<T, ?> column) {
+ if (value == null) {
+ return null;
+ } else {
+ Matcher matcher = NUMBER_PATTERN.matcher(value);
+ String oldValue = value;
+ int index = 1;
+ if (matcher.matches()) {
+ oldValue = matcher.group(1);
+ index = Integer.valueOf(matcher.group(2)) + 1;
+ }
+
+ NumberTableInfo info = initDbInfo(column);
+ while (true) {
+ String newValue = oldValue + "(" + (index++) + ")";
+ boolean exist = numberGeneratorModelHelper.numberExist(newValue, info);
+ if (!exist) {
+ return newValue;
+ }
+ }
+ }
+ }
+
+
+ /**
+ * 鐢熸垚缂栧彿
+ *
+ * @param numOfDigits
+ * @param column
+ * @return
+ */
+ public String generateNumber(final int numOfDigits, SFunction<T, ?> column) {
+ return generateNumberWithPrefix(numOfDigits, null, column);
+ }
+
+ /**
+ * 鐢熸垚甯﹀墠缂�鐨勭紪鍙�
+ *
+ * @param numOfDigits
+ * @param prefix
+ * @param column
+ * @return
+ */
+ public String generateNumberWithPrefix(final int numOfDigits, final String prefix, SFunction<T, ?> column) {
+ NumberTableInfo info = initDbInfo(column);
+ String generatedNumber = generateNumberWithExtension(info, numOfDigits, prefix, "");
+ return prependPrefix(prefix, generatedNumber);
+ }
+
+
+ /**
+ * 鐢熸垚甯﹀悗缂�鐨勭紪鍙�
+ *
+ * @param numOfDigits
+ * @param suffix
+ * @param column
+ * @return
+ */
+ public String generateNumberWithSuffix(final int numOfDigits, final String suffix, SFunction<T, ?> column) {
+ NumberTableInfo info = initDbInfo(column);
+ String generatedNumber = generateNumberWithExtension(info, numOfDigits, "", suffix);
+ return appendSuffix(suffix, generatedNumber);
+ }
+
+ /**
+ * 鍒濆鍖栨暟鎹簱琛ㄥ悕銆佸瓧娈靛悕
+ *
+ * @param column
+ * @return
+ */
+ private NumberTableInfo initDbInfo(SFunction<T, ?> column) {
+ SerializedLambda ld = LambdaUtils.resolve(column);
+ TableInfo tableInfo = TableInfoHelper.getTableInfo(ld.getImplClass());
+ String fieldName = PropertyNamer.methodToProperty(ld.getImplMethodName());
+ Optional<TableFieldInfo> op = tableInfo.getFieldList().stream().filter(f -> fieldName.equals(f.getProperty())).findFirst();
+ if (!op.isPresent()) {
+ throw new RuntimeException("鑾峰彇鏁版嵁搴撳瓧娈靛嚭閿欙紝璇锋鏌ユ槧灏�");
+ }
+ TableFieldInfo fieldInfo = op.get();
+
+ NumberTableInfo info = new NumberTableInfo();
+ info.setLogicDelete(tableInfo.isLogicDelete());
+ info.setNumberFieldName(fieldInfo.getColumn());
+ info.setTableName(tableInfo.getTableName());
+ return info;
+ }
+
+
+ private String generateNumberWithExtension(NumberTableInfo numberTableInfo, int numOfDigits, String prefix, String suffix) {
+ Long dbMax = numberGeneratorModelHelper.getNumbersProjection(numberTableInfo, prefix, suffix);
+ Long greatestNumber = 0L;
+ if (dbMax != null) {
+ greatestNumber = dbMax;
+ }
+ return String.format("%0" + numOfDigits + "d", greatestNumber + 1);
+ }
+
+ private String prependPrefix(final String prefix, final String generatedNumber) {
+ if (prefix == null) {
+ return generatedNumber;
+ }
+ return prefix + generatedNumber;
+ }
+
+
+ private String appendSuffix(final String suffix, final String generatedNumber) {
+ if (suffix == null) {
+ return generatedNumber;
+ }
+ return generatedNumber + suffix;
+ }
+
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGeneratorModelHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGeneratorModelHelper.java
new file mode 100644
index 0000000..6b921b6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberGeneratorModelHelper.java
@@ -0,0 +1,107 @@
+/**
+ * ***************************************************************************
+ * Copyright (c) 2010 Qcadoo Limited
+ * Project: Qcadoo Framework
+ * Version: 1.4
+ * <p>
+ * This file is part of Qcadoo.
+ * <p>
+ * Qcadoo is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as published
+ * by the Free Software Foundation; either version 3 of the License,
+ * or (at your option) any later version.
+ * <p>
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Affero General Public License for more details.
+ * <p>
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ * ***************************************************************************
+ */
+package com.ruoyi.common.numgen;
+
+import com.google.common.collect.Maps;
+import lombok.AllArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringSubstitutor;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.Map;
+
+/**
+ * @author zhangxy
+ */
+@AllArgsConstructor
+@Service
+public class NumberGeneratorModelHelper {
+
+ private JdbcTemplate jdbcTemplate;
+
+
+ private static final String NUMBER_EXIST_QUERY_TEMPLATE = "select count(*) from ${TABLE_NAME} where ${NUMBER_FIELD}='${VALUE}'";
+
+
+ private static final String GET_NUMBERS_QUERY_TEMPLATE = "select MAX( CAST( "
+ + " coalesce(TRIM(LEADING '0' from ${NUMBER_FIELD}), '0') "
+ + " AS UNSIGNED ) ) "
+ + "from ${TABLE_NAME} where 1=1";
+
+ private static final String GET_PREFIX_AWARE_NUMBERS_QUERY_TEMPLATE = "select MAX( CAST( "
+ + " TRIM(LEADING '0' from SUBSTRING(${NUMBER_FIELD}, ${NUMBER_STARTS_AT})) "
+ + " AS UNSIGNED ) ) "
+ + "from ${TABLE_NAME} where ${NUMBER_FIELD} like '${PREFIX}%'";
+
+ private static final String GET_SUFFIX_AWARE_NUMBERS_QUERY_TEMPLATE = "select MAX( CAST( "
+ + " TRIM(LEADING '0' from SUBSTRING(${NUMBER_FIELD}, 1, POSITION('${SUFFIX}' IN ${NUMBER_FIELD}) - 1)) "
+ + " AS UNSIGNED )) "
+ + "from ${TABLE_NAME} where ${NUMBER_FIELD} like '%${SUFFIX}'";
+
+
+ public boolean numberExist(final String value, final NumberTableInfo numberTableInfo) {
+ Map<String, String> placeholderValues = Maps.newHashMap();
+
+ placeholderValues.put("TABLE_NAME", numberTableInfo.getTableName());
+ placeholderValues.put("NUMBER_FIELD", numberTableInfo.getNumberFieldName());
+ placeholderValues.put("VALUE", value);
+ String query = new StringSubstitutor(placeholderValues, "${", "}").replace(NUMBER_EXIST_QUERY_TEMPLATE);
+ Long count = jdbcTemplate.queryForObject(query, Long.class);
+ return count > 0;
+ }
+
+ public Long getNumbersProjection(final NumberTableInfo numberTableInfo, final String prefix, final String suffix) {
+ String sqlQuery = buildQuery(numberTableInfo, prefix, suffix);
+ return jdbcTemplate.queryForObject(sqlQuery, Long.class);
+ }
+
+ private String buildQuery(final NumberTableInfo numberTableInfo,
+ final String prefix, final String suffix) {
+ Map<String, String> placeholderValues = Maps.newHashMap();
+
+ placeholderValues.put("TABLE_NAME", numberTableInfo.getTableName());
+ placeholderValues.put("NUMBER_FIELD", numberTableInfo.getNumberFieldName());
+
+ String query;
+ if (StringUtils.isNotEmpty(prefix)) {
+ placeholderValues.put("PREFIX", prefix);
+ int prefixLength = StringUtils.length(prefix);
+ placeholderValues.put("NUMBER_STARTS_AT", String.valueOf(prefixLength + 1));
+ query = GET_PREFIX_AWARE_NUMBERS_QUERY_TEMPLATE;
+ } else if (StringUtils.isNotEmpty(suffix)) {
+ placeholderValues.put("SUFFIX", suffix);
+ query = GET_SUFFIX_AWARE_NUMBERS_QUERY_TEMPLATE;
+ } else {
+ query = GET_NUMBERS_QUERY_TEMPLATE;
+ }
+
+ if(numberTableInfo.isLogicDelete()){
+ query += " and active=true";
+ }
+ StringSubstitutor substitutor = new StringSubstitutor(placeholderValues, "${", "}");
+ return substitutor.replace(query);
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberTableInfo.java b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberTableInfo.java
new file mode 100644
index 0000000..15c721f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/NumberTableInfo.java
@@ -0,0 +1,16 @@
+package com.ruoyi.common.numgen;
+
+import lombok.Data;
+
+/**
+ * @Author: zhangxy
+ * @Date: 2020-09-11 16:48
+ */
+@Data
+public class NumberTableInfo {
+
+ private String tableName;
+ private String numberFieldName;
+
+ private boolean logicDelete;
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/numgen/SerializedLambda.java b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/SerializedLambda.java
new file mode 100644
index 0000000..49cdc30
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/numgen/SerializedLambda.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2011-2020, baomidou (jobob@qq.com).
+ * <p>
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * <p>
+ * https://www.apache.org/licenses/LICENSE-2.0
+ * <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 com.ruoyi.common.numgen;
+
+import com.baomidou.mybatisplus.core.toolkit.ClassUtils;
+import com.baomidou.mybatisplus.core.toolkit.ExceptionUtils;
+import com.baomidou.mybatisplus.core.toolkit.SerializationUtils;
+import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
+
+import java.io.*;
+
+/**
+ * 杩欎釜绫绘槸浠� {@link java.lang.invoke.SerializedLambda} 閲岄潰 copy 杩囨潵鐨勶紝
+ * 瀛楁淇℃伅瀹屽叏涓�鏍�
+ * <p>璐熻矗灏嗕竴涓敮鎸佸簭鍒楃殑 Function 搴忓垪鍖栦负 SerializedLambda</p>
+ *
+ * @author HCL
+ * @since 2018/05/10
+ */
+public class SerializedLambda implements Serializable {
+
+ private static final long serialVersionUID = 8025925345765570181L;
+
+ private Class<?> capturingClass;
+ private String functionalInterfaceClass;
+ private String functionalInterfaceMethodName;
+ private String functionalInterfaceMethodSignature;
+ private String implClass;
+ private String implMethodName;
+ private String implMethodSignature;
+ private int implMethodKind;
+ private String instantiatedMethodType;
+ private Object[] capturedArgs;
+
+ /**
+ * 閫氳繃鍙嶅簭鍒楀寲杞崲 lambda 琛ㄨ揪寮忥紝璇ユ柟娉曞彧鑳藉簭鍒楀寲 lambda 琛ㄨ揪寮忥紝涓嶈兘搴忓垪鍖栨帴鍙e疄鐜版垨鑰呮甯搁潪 lambda 鍐欐硶鐨勫璞�
+ *
+ * @param lambda lambda瀵硅薄
+ * @return 杩斿洖瑙f瀽鍚庣殑 SerializedLambda
+ */
+ public static SerializedLambda resolve(SFunction<?, ?> lambda) {
+ if (!lambda.getClass().isSynthetic()) {
+ throw ExceptionUtils.mpe("璇ユ柟娉曚粎鑳戒紶鍏� lambda 琛ㄨ揪寮忎骇鐢熺殑鍚堟垚绫�");
+ }
+ try (ObjectInputStream objIn = new ObjectInputStream(new ByteArrayInputStream(SerializationUtils.serialize(lambda))) {
+ @Override
+ protected Class<?> resolveClass(ObjectStreamClass objectStreamClass) throws IOException, ClassNotFoundException {
+ Class<?> clazz;
+ try {
+ clazz = ClassUtils.toClassConfident(objectStreamClass.getName());
+ } catch (Exception ex) {
+ clazz = super.resolveClass(objectStreamClass);
+ }
+ return clazz == java.lang.invoke.SerializedLambda.class ? SerializedLambda.class : clazz;
+ }
+ }) {
+ return (SerializedLambda) objIn.readObject();
+ } catch (ClassNotFoundException | IOException e) {
+ throw ExceptionUtils.mpe("This is impossible to happen", e);
+ }
+ }
+
+ /**
+ * 鑾峰彇鎺ュ彛 class
+ *
+ * @return 杩斿洖 class 鍚嶇О
+ */
+ public String getFunctionalInterfaceClassName() {
+ return normalizedName(functionalInterfaceClass);
+ }
+
+ /**
+ * 鑾峰彇瀹炵幇鐨� class
+ *
+ * @return 瀹炵幇绫�
+ */
+ public Class<?> getImplClass() {
+ return ClassUtils.toClassConfident(getImplClassName());
+ }
+
+ /**
+ * 鑾峰彇 class 鐨勫悕绉�
+ *
+ * @return 绫诲悕
+ */
+ public String getImplClassName() {
+ return normalizedName(implClass);
+ }
+
+ /**
+ * 鑾峰彇瀹炵幇鑰呯殑鏂规硶鍚嶇О
+ *
+ * @return 鏂规硶鍚嶇О
+ */
+ public String getImplMethodName() {
+ return implMethodName;
+ }
+
+ /**
+ * 姝e父鍖栫被鍚嶇О锛屽皢绫诲悕绉颁腑鐨� / 鏇挎崲涓� .
+ *
+ * @param name 鍚嶇О
+ * @return 姝e父鐨勭被鍚�
+ */
+ private String normalizedName(String name) {
+ return name.replace('/', '.');
+ }
+
+ /**
+ * @return 鑾峰彇瀹炰緥鍖栨柟娉曠殑绫诲瀷
+ */
+ public Class<?> getInstantiatedType() {
+ String instantiatedTypeName = normalizedName(instantiatedMethodType.substring(2, instantiatedMethodType.indexOf(';')));
+ return ClassUtils.toClassConfident(instantiatedTypeName);
+ }
+
+ /**
+ * @return 瀛楃涓插舰寮�
+ */
+ @Override
+ public String toString() {
+ String interfaceName = getFunctionalInterfaceClassName();
+ String implName = getImplClassName();
+ return String.format("%s -> %s::%s",
+ interfaceName.substring(interfaceName.lastIndexOf('.') + 1),
+ implName.substring(implName.lastIndexOf('.') + 1),
+ implMethodName);
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
new file mode 100644
index 0000000..b6326c2
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Arith.java
@@ -0,0 +1,114 @@
+package com.ruoyi.common.utils;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * 绮剧‘鐨勬诞鐐规暟杩愮畻
+ *
+ * @author ruoyi
+ */
+public class Arith
+{
+
+ /** 榛樿闄ゆ硶杩愮畻绮惧害 */
+ private static final int DEF_DIV_SCALE = 10;
+
+ /** 杩欎釜绫讳笉鑳藉疄渚嬪寲 */
+ private Arith()
+ {
+ }
+
+ /**
+ * 鎻愪緵绮剧‘鐨勫姞娉曡繍绠椼��
+ * @param v1 琚姞鏁�
+ * @param v2 鍔犳暟
+ * @return 涓や釜鍙傛暟鐨勫拰
+ */
+ public static double add(double v1, double v2)
+ {
+ BigDecimal b1 = new BigDecimal(Double.toString(v1));
+ BigDecimal b2 = new BigDecimal(Double.toString(v2));
+ return b1.add(b2).doubleValue();
+ }
+
+ /**
+ * 鎻愪緵绮剧‘鐨勫噺娉曡繍绠椼��
+ * @param v1 琚噺鏁�
+ * @param v2 鍑忔暟
+ * @return 涓や釜鍙傛暟鐨勫樊
+ */
+ public static double sub(double v1, double v2)
+ {
+ BigDecimal b1 = new BigDecimal(Double.toString(v1));
+ BigDecimal b2 = new BigDecimal(Double.toString(v2));
+ return b1.subtract(b2).doubleValue();
+ }
+
+ /**
+ * 鎻愪緵绮剧‘鐨勪箻娉曡繍绠椼��
+ * @param v1 琚箻鏁�
+ * @param v2 涔樻暟
+ * @return 涓や釜鍙傛暟鐨勭Н
+ */
+ public static double mul(double v1, double v2)
+ {
+ BigDecimal b1 = new BigDecimal(Double.toString(v1));
+ BigDecimal b2 = new BigDecimal(Double.toString(v2));
+ return b1.multiply(b2).doubleValue();
+ }
+
+ /**
+ * 鎻愪緵锛堢浉瀵癸級绮剧‘鐨勯櫎娉曡繍绠楋紝褰撳彂鐢熼櫎涓嶅敖鐨勬儏鍐垫椂锛岀簿纭埌
+ * 灏忔暟鐐逛互鍚�10浣嶏紝浠ュ悗鐨勬暟瀛楀洓鑸嶄簲鍏ャ��
+ * @param v1 琚櫎鏁�
+ * @param v2 闄ゆ暟
+ * @return 涓や釜鍙傛暟鐨勫晢
+ */
+ public static double div(double v1, double v2)
+ {
+ return div(v1, v2, DEF_DIV_SCALE);
+ }
+
+ /**
+ * 鎻愪緵锛堢浉瀵癸級绮剧‘鐨勯櫎娉曡繍绠椼�傚綋鍙戠敓闄や笉灏界殑鎯呭喌鏃讹紝鐢眘cale鍙傛暟鎸�
+ * 瀹氱簿搴︼紝浠ュ悗鐨勬暟瀛楀洓鑸嶄簲鍏ャ��
+ * @param v1 琚櫎鏁�
+ * @param v2 闄ゆ暟
+ * @param scale 琛ㄧず琛ㄧず闇�瑕佺簿纭埌灏忔暟鐐逛互鍚庡嚑浣嶃��
+ * @return 涓や釜鍙傛暟鐨勫晢
+ */
+ public static double div(double v1, double v2, int scale)
+ {
+ if (scale < 0)
+ {
+ throw new IllegalArgumentException(
+ "The scale must be a positive integer or zero");
+ }
+ BigDecimal b1 = new BigDecimal(Double.toString(v1));
+ BigDecimal b2 = new BigDecimal(Double.toString(v2));
+ if (b1.compareTo(BigDecimal.ZERO) == 0)
+ {
+ return BigDecimal.ZERO.doubleValue();
+ }
+ return b1.divide(b2, scale, RoundingMode.HALF_UP).doubleValue();
+ }
+
+ /**
+ * 鎻愪緵绮剧‘鐨勫皬鏁颁綅鍥涜垗浜斿叆澶勭悊銆�
+ * @param v 闇�瑕佸洓鑸嶄簲鍏ョ殑鏁板瓧
+ * @param scale 灏忔暟鐐瑰悗淇濈暀鍑犱綅
+ * @return 鍥涜垗浜斿叆鍚庣殑缁撴灉
+ */
+ public static double round(double v, int scale)
+ {
+ if (scale < 0)
+ {
+ throw new IllegalArgumentException(
+ "The scale must be a positive integer or zero");
+ }
+ BigDecimal b = new BigDecimal(Double.toString(v));
+ BigDecimal one = BigDecimal.ONE;
+ return b.divide(one, scale, RoundingMode.HALF_UP).doubleValue();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
new file mode 100644
index 0000000..fb2ae21
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
@@ -0,0 +1,191 @@
+package com.ruoyi.common.utils;
+
+import java.lang.management.ManagementFactory;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.ZoneId;
+import java.time.ZonedDateTime;
+import java.util.Date;
+import org.apache.commons.lang3.time.DateFormatUtils;
+
+/**
+ * 鏃堕棿宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class DateUtils extends org.apache.commons.lang3.time.DateUtils
+{
+ public static String YYYY = "yyyy";
+
+ public static String YYYY_MM = "yyyy-MM";
+
+ public static String YYYY_MM_DD = "yyyy-MM-dd";
+
+ public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
+
+ public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
+
+ private static String[] parsePatterns = {
+ "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+ "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
+ "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
+
+ /**
+ * 鑾峰彇褰撳墠Date鍨嬫棩鏈�
+ *
+ * @return Date() 褰撳墠鏃ユ湡
+ */
+ public static Date getNowDate()
+ {
+ return new Date();
+ }
+
+ /**
+ * 鑾峰彇褰撳墠鏃ユ湡, 榛樿鏍煎紡涓簓yyy-MM-dd
+ *
+ * @return String
+ */
+ public static String getDate()
+ {
+ return dateTimeNow(YYYY_MM_DD);
+ }
+
+ public static final String getTime()
+ {
+ return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
+ }
+
+ public static final String dateTimeNow()
+ {
+ return dateTimeNow(YYYYMMDDHHMMSS);
+ }
+
+ public static final String dateTimeNow(final String format)
+ {
+ return parseDateToStr(format, new Date());
+ }
+
+ public static final String dateTime(final Date date)
+ {
+ return parseDateToStr(YYYY_MM_DD, date);
+ }
+
+ public static final String parseDateToStr(final String format, final Date date)
+ {
+ return new SimpleDateFormat(format).format(date);
+ }
+
+ public static final Date dateTime(final String format, final String ts)
+ {
+ try
+ {
+ return new SimpleDateFormat(format).parse(ts);
+ }
+ catch (ParseException e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+
+ /**
+ * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�2018/08/08
+ */
+ public static final String datePath()
+ {
+ Date now = new Date();
+ return DateFormatUtils.format(now, "yyyy/MM/dd");
+ }
+
+ /**
+ * 鏃ユ湡璺緞 鍗冲勾/鏈�/鏃� 濡�20180808
+ */
+ public static final String dateTime()
+ {
+ Date now = new Date();
+ return DateFormatUtils.format(now, "yyyyMMdd");
+ }
+
+ /**
+ * 鏃ユ湡鍨嬪瓧绗︿覆杞寲涓烘棩鏈� 鏍煎紡
+ */
+ public static Date parseDate(Object str)
+ {
+ if (str == null)
+ {
+ return null;
+ }
+ try
+ {
+ return parseDate(str.toString(), parsePatterns);
+ }
+ catch (ParseException e)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * 鑾峰彇鏈嶅姟鍣ㄥ惎鍔ㄦ椂闂�
+ */
+ public static Date getServerStartDate()
+ {
+ long time = ManagementFactory.getRuntimeMXBean().getStartTime();
+ return new Date(time);
+ }
+
+ /**
+ * 璁$畻鐩稿樊澶╂暟
+ */
+ public static int differentDaysByMillisecond(Date date1, Date date2)
+ {
+ return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
+ }
+
+ /**
+ * 璁$畻鏃堕棿宸�
+ *
+ * @param endDate 鏈�鍚庢椂闂�
+ * @param startTime 寮�濮嬫椂闂�
+ * @return 鏃堕棿宸紙澶�/灏忔椂/鍒嗛挓锛�
+ */
+ public static String timeDistance(Date endDate, Date startTime)
+ {
+ long nd = 1000 * 24 * 60 * 60;
+ long nh = 1000 * 60 * 60;
+ long nm = 1000 * 60;
+ // long ns = 1000;
+ // 鑾峰緱涓や釜鏃堕棿鐨勬绉掓椂闂村樊寮�
+ long diff = endDate.getTime() - startTime.getTime();
+ // 璁$畻宸灏戝ぉ
+ long day = diff / nd;
+ // 璁$畻宸灏戝皬鏃�
+ long hour = diff % nd / nh;
+ // 璁$畻宸灏戝垎閽�
+ long min = diff % nd % nh / nm;
+ // 璁$畻宸灏戠//杈撳嚭缁撴灉
+ // long sec = diff % nd % nh % nm / ns;
+ return day + "澶�" + hour + "灏忔椂" + min + "鍒嗛挓";
+ }
+
+ /**
+ * 澧炲姞 LocalDateTime ==> Date
+ */
+ public static Date toDate(LocalDateTime temporalAccessor)
+ {
+ ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
+ return Date.from(zdt.toInstant());
+ }
+
+ /**
+ * 澧炲姞 LocalDate ==> Date
+ */
+ public static Date toDate(LocalDate temporalAccessor)
+ {
+ LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
+ ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
+ return Date.from(zdt.toInstant());
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java
new file mode 100644
index 0000000..f8a4c02
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DesensitizedUtil.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.utils;
+
+/**
+ * 鑴辨晱宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class DesensitizedUtil
+{
+ /**
+ * 瀵嗙爜鐨勫叏閮ㄥ瓧绗﹂兘鐢�*浠f浛锛屾瘮濡傦細******
+ *
+ * @param password 瀵嗙爜
+ * @return 鑴辨晱鍚庣殑瀵嗙爜
+ */
+ public static String password(String password)
+ {
+ if (StringUtils.isBlank(password))
+ {
+ return StringUtils.EMPTY;
+ }
+ return StringUtils.repeat('*', password.length());
+ }
+
+ /**
+ * 杞︾墝涓棿鐢�*浠f浛锛屽鏋滄槸閿欒鐨勮溅鐗岋紝涓嶅鐞�
+ *
+ * @param carLicense 瀹屾暣鐨勮溅鐗屽彿
+ * @return 鑴辨晱鍚庣殑杞︾墝
+ */
+ public static String carLicense(String carLicense)
+ {
+ if (StringUtils.isBlank(carLicense))
+ {
+ return StringUtils.EMPTY;
+ }
+ // 鏅�氳溅鐗�
+ if (carLicense.length() == 7)
+ {
+ carLicense = StringUtils.hide(carLicense, 3, 6);
+ }
+ else if (carLicense.length() == 8)
+ {
+ // 鏂拌兘婧愯溅鐗�
+ carLicense = StringUtils.hide(carLicense, 3, 7);
+ }
+ return carLicense;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
new file mode 100644
index 0000000..f198462
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/DictUtils.java
@@ -0,0 +1,239 @@
+package com.ruoyi.common.utils;
+
+import java.util.Collection;
+import java.util.List;
+import com.alibaba.fastjson2.JSONArray;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.spring.SpringUtils;
+
+/**
+ * 瀛楀吀宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class DictUtils
+{
+ /**
+ * 鍒嗛殧绗�
+ */
+ public static final String SEPARATOR = ",";
+
+ /**
+ * 璁剧疆瀛楀吀缂撳瓨
+ *
+ * @param key 鍙傛暟閿�
+ * @param dictDatas 瀛楀吀鏁版嵁鍒楄〃
+ */
+ public static void setDictCache(String key, List<SysDictData> dictDatas)
+ {
+ SpringUtils.getBean(RedisCache.class).setCacheObject(getCacheKey(key), dictDatas);
+ }
+
+ /**
+ * 鑾峰彇瀛楀吀缂撳瓨
+ *
+ * @param key 鍙傛暟閿�
+ * @return dictDatas 瀛楀吀鏁版嵁鍒楄〃
+ */
+ public static List<SysDictData> getDictCache(String key)
+ {
+ JSONArray arrayCache = SpringUtils.getBean(RedisCache.class).getCacheObject(getCacheKey(key));
+ if (StringUtils.isNotNull(arrayCache))
+ {
+ return arrayCache.toList(SysDictData.class);
+ }
+ return null;
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param dictValue 瀛楀吀鍊�
+ * @return 瀛楀吀鏍囩
+ */
+ public static String getDictLabel(String dictType, String dictValue)
+ {
+ if (StringUtils.isEmpty(dictValue))
+ {
+ return StringUtils.EMPTY;
+ }
+ return getDictLabel(dictType, dictValue, SEPARATOR);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param dictLabel 瀛楀吀鏍囩
+ * @return 瀛楀吀鍊�
+ */
+ public static String getDictValue(String dictType, String dictLabel)
+ {
+ if (StringUtils.isEmpty(dictLabel))
+ {
+ return StringUtils.EMPTY;
+ }
+ return getDictValue(dictType, dictLabel, SEPARATOR);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏稿�艰幏鍙栧瓧鍏告爣绛�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param dictValue 瀛楀吀鍊�
+ * @param separator 鍒嗛殧绗�
+ * @return 瀛楀吀鏍囩
+ */
+ public static String getDictLabel(String dictType, String dictValue, String separator)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ List<SysDictData> datas = getDictCache(dictType);
+ if (StringUtils.isNull(datas))
+ {
+ return StringUtils.EMPTY;
+ }
+ if (StringUtils.containsAny(separator, dictValue))
+ {
+ for (SysDictData dict : datas)
+ {
+ for (String value : dictValue.split(separator))
+ {
+ if (value.equals(dict.getDictValue()))
+ {
+ propertyString.append(dict.getDictLabel()).append(separator);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (SysDictData dict : datas)
+ {
+ if (dictValue.equals(dict.getDictValue()))
+ {
+ return dict.getDictLabel();
+ }
+ }
+ }
+ return StringUtils.stripEnd(propertyString.toString(), separator);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏告爣绛捐幏鍙栧瓧鍏稿��
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param dictLabel 瀛楀吀鏍囩
+ * @param separator 鍒嗛殧绗�
+ * @return 瀛楀吀鍊�
+ */
+ public static String getDictValue(String dictType, String dictLabel, String separator)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ List<SysDictData> datas = getDictCache(dictType);
+ if (StringUtils.isNull(datas))
+ {
+ return StringUtils.EMPTY;
+ }
+ if (StringUtils.containsAny(separator, dictLabel))
+ {
+ for (SysDictData dict : datas)
+ {
+ for (String label : dictLabel.split(separator))
+ {
+ if (label.equals(dict.getDictLabel()))
+ {
+ propertyString.append(dict.getDictValue()).append(separator);
+ break;
+ }
+ }
+ }
+ }
+ else
+ {
+ for (SysDictData dict : datas)
+ {
+ if (dictLabel.equals(dict.getDictLabel()))
+ {
+ return dict.getDictValue();
+ }
+ }
+ }
+ return StringUtils.stripEnd(propertyString.toString(), separator);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鑾峰彇瀛楀吀鎵�鏈夊��
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀鍊�
+ */
+ public static String getDictValues(String dictType)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ List<SysDictData> datas = getDictCache(dictType);
+ if (StringUtils.isNull(datas))
+ {
+ return StringUtils.EMPTY;
+ }
+ for (SysDictData dict : datas)
+ {
+ propertyString.append(dict.getDictValue()).append(SEPARATOR);
+ }
+ return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鑾峰彇瀛楀吀鎵�鏈夋爣绛�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀鍊�
+ */
+ public static String getDictLabels(String dictType)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ List<SysDictData> datas = getDictCache(dictType);
+ if (StringUtils.isNull(datas))
+ {
+ return StringUtils.EMPTY;
+ }
+ for (SysDictData dict : datas)
+ {
+ propertyString.append(dict.getDictLabel()).append(SEPARATOR);
+ }
+ return StringUtils.stripEnd(propertyString.toString(), SEPARATOR);
+ }
+
+ /**
+ * 鍒犻櫎鎸囧畾瀛楀吀缂撳瓨
+ *
+ * @param key 瀛楀吀閿�
+ */
+ public static void removeDictCache(String key)
+ {
+ SpringUtils.getBean(RedisCache.class).deleteObject(getCacheKey(key));
+ }
+
+ /**
+ * 娓呯┖瀛楀吀缂撳瓨
+ */
+ public static void clearDictCache()
+ {
+ Collection<String> keys = SpringUtils.getBean(RedisCache.class).keys(CacheConstants.SYS_DICT_KEY + "*");
+ SpringUtils.getBean(RedisCache.class).deleteObject(keys);
+ }
+
+ /**
+ * 璁剧疆cache key
+ *
+ * @param configKey 鍙傛暟閿�
+ * @return 缂撳瓨閿甼ey
+ */
+ public static String getCacheKey(String configKey)
+ {
+ return CacheConstants.SYS_DICT_KEY + configKey;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
new file mode 100644
index 0000000..214e4a0
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ExceptionUtil.java
@@ -0,0 +1,39 @@
+package com.ruoyi.common.utils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+
+/**
+ * 閿欒淇℃伅澶勭悊绫汇��
+ *
+ * @author ruoyi
+ */
+public class ExceptionUtil
+{
+ /**
+ * 鑾峰彇exception鐨勮缁嗛敊璇俊鎭��
+ */
+ public static String getExceptionMessage(Throwable e)
+ {
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw, true));
+ return sw.toString();
+ }
+
+ public static String getRootErrorMessage(Exception e)
+ {
+ Throwable root = ExceptionUtils.getRootCause(e);
+ root = (root == null ? e : root);
+ if (root == null)
+ {
+ return "";
+ }
+ String msg = root.getMessage();
+ if (msg == null)
+ {
+ return "null";
+ }
+ return StringUtils.defaultString(msg);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/JackSonUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JackSonUtil.java
new file mode 100644
index 0000000..f463e6f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/JackSonUtil.java
@@ -0,0 +1,133 @@
+package com.ruoyi.common.utils;
+
+import com.fasterxml.jackson.core.JsonGenerationException;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.ObjectWriter;
+import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
+import org.springframework.stereotype.Component;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+/**
+ * JSON瑙f瀽澶勭悊
+ *
+ * @author 寮犲
+ */
+@Component
+public class JackSonUtil {
+ private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
+ private static final ObjectWriter OBJECT_WRITER = OBJECT_MAPPER.writerWithDefaultPrettyPrinter();
+
+ public static void marshal(File file, Object value) throws Exception {
+ try {
+ OBJECT_WRITER.writeValue(file, value);
+ } catch (JsonGenerationException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+
+ public static void marshal(OutputStream os, Object value) throws Exception {
+ try {
+ OBJECT_WRITER.writeValue(os, value);
+ } catch (JsonGenerationException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+
+ public static String marshal(Object value) throws Exception {
+ try {
+ return OBJECT_WRITER.writeValueAsString(value);
+ } catch (JsonGenerationException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+
+ public static byte[] marshalBytes(Object value) throws Exception {
+ try {
+ return OBJECT_WRITER.writeValueAsBytes(value);
+ } catch (JsonGenerationException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+
+ public static <T> T unmarshal(File file, Class<T> valueType) throws Exception {
+ try {
+ return OBJECT_MAPPER.readValue(file, valueType);
+ } catch (JsonParseException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+
+ public static <T> T unmarshal(InputStream is, Class<T> valueType) throws Exception {
+ try {
+ return OBJECT_MAPPER.readValue(is, valueType);
+ } catch (JsonParseException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+
+ /**
+ * 瀛楃涓茶浆瀵硅薄
+ * @param str
+ * @param valueType
+ * @return
+ * @param <T>
+ * @throws Exception
+ */
+ public static <T> T unmarshal(String str, Class<T> valueType) throws Exception {
+ try {
+ OBJECT_MAPPER.registerModule(new JavaTimeModule());
+ return OBJECT_MAPPER.readValue(str, valueType);
+ } catch (JsonParseException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+
+ public static <T> T unmarshal(byte[] bytes, Class<T> valueType) throws Exception {
+ try {
+ if (bytes == null) {
+ bytes = new byte[0];
+ }
+ return OBJECT_MAPPER.readValue(bytes, 0, bytes.length, valueType);
+ } catch (JsonParseException e) {
+ throw new Exception(e);
+ } catch (JsonMappingException e) {
+ throw new Exception(e);
+ } catch (IOException e) {
+ throw new Exception(e);
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java
new file mode 100644
index 0000000..0de30c6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/LogUtils.java
@@ -0,0 +1,18 @@
+package com.ruoyi.common.utils;
+
+/**
+ * 澶勭悊骞惰褰曟棩蹇楁枃浠�
+ *
+ * @author ruoyi
+ */
+public class LogUtils
+{
+ public static String getBlock(Object msg)
+ {
+ if (msg == null)
+ {
+ msg = "";
+ }
+ return "[" + msg.toString() + "]";
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
new file mode 100644
index 0000000..7dac75a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MessageUtils.java
@@ -0,0 +1,26 @@
+package com.ruoyi.common.utils;
+
+import org.springframework.context.MessageSource;
+import org.springframework.context.i18n.LocaleContextHolder;
+import com.ruoyi.common.utils.spring.SpringUtils;
+
+/**
+ * 鑾峰彇i18n璧勬簮鏂囦欢
+ *
+ * @author ruoyi
+ */
+public class MessageUtils
+{
+ /**
+ * 鏍规嵁娑堟伅閿拰鍙傛暟 鑾峰彇娑堟伅 濮旀墭缁檚pring messageSource
+ *
+ * @param code 娑堟伅閿�
+ * @param args 鍙傛暟
+ * @return 鑾峰彇鍥介檯鍖栫炕璇戝��
+ */
+ public static String message(String code, Object... args)
+ {
+ MessageSource messageSource = SpringUtils.getBean(MessageSource.class);
+ return messageSource.getMessage(code, args, LocaleContextHolder.getLocale());
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
new file mode 100644
index 0000000..70e9b08
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/PageUtils.java
@@ -0,0 +1,35 @@
+package com.ruoyi.common.utils;
+
+import com.github.pagehelper.PageHelper;
+import com.ruoyi.common.core.page.PageDomain;
+import com.ruoyi.common.core.page.TableSupport;
+import com.ruoyi.common.utils.sql.SqlUtil;
+
+/**
+ * 鍒嗛〉宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class PageUtils extends PageHelper
+{
+ /**
+ * 璁剧疆璇锋眰鍒嗛〉鏁版嵁
+ */
+ public static void startPage()
+ {
+ PageDomain pageDomain = TableSupport.buildPageRequest();
+ Integer pageNum = pageDomain.getPageNum();
+ Integer pageSize = pageDomain.getPageSize();
+ String orderBy = SqlUtil.escapeOrderBySql(pageDomain.getOrderBy());
+ Boolean reasonable = pageDomain.getReasonable();
+ PageHelper.startPage(pageNum, pageSize, orderBy).setReasonable(reasonable);
+ }
+
+ /**
+ * 娓呯悊鍒嗛〉鐨勭嚎绋嬪彉閲�
+ */
+ public static void clearPage()
+ {
+ PageHelper.clearPage();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/QueryWrappers.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/QueryWrappers.java
new file mode 100644
index 0000000..0878afb
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/QueryWrappers.java
@@ -0,0 +1,68 @@
+package com.ruoyi.common.utils;
+
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Component;
+
+import java.lang.reflect.Field;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+/*
+ * 鏉庢灄
+ * 鐢熸垚SQL璇彞*/
+
+@Component
+@AllArgsConstructor
+public class QueryWrappers<T> {
+
+ public static <T> QueryWrapper<T> queryWrappers(T entity) {
+ if (ObjectUtil.isEmpty(entity)) return null;
+ Class<?> aClass = entity.getClass();
+ QueryWrapper<T> wrapper = Wrappers.<T>query();
+ List<Field> fieldList = new ArrayList<>();
+ while (aClass != null) {
+ fieldList.addAll(new ArrayList<>(Arrays.asList(aClass.getDeclaredFields())));
+ aClass = aClass.getSuperclass();
+ }
+ for (Field field : fieldList) {
+ field.setAccessible(true);
+ Object value;
+ try {
+ value = field.get(entity);
+ } catch (IllegalAccessException e) {
+ e.printStackTrace();
+ throw new RuntimeException("鏌ヨ鏉′欢鐢熸垚閿欒");
+ }
+// System.out.println(field.getName() + "|" + (value == null || value.equals("")) + "|" + value);
+ if(value == null || value.equals("")){
+ continue;
+ }
+ /*boolean bool = field.isAnnotationPresent(TableField.class);
+ if (bool){
+ if(field.getAnnotation(TableField.class).exist()==false)continue;
+ }*/
+ if (!field.getName().equals("orderBy")) {
+ if(value.getClass()== LocalDateTime.class){
+ wrapper.like(StrUtil.toUnderlineCase(field.getName()), ((LocalDateTime) value).format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
+ }else{
+ wrapper.like(StrUtil.toUnderlineCase(field.getName()), value);
+ }
+ } else {
+ Map<String, String> map = (Map<String, String>) value;
+ if(map.get("order")!=null){
+ wrapper.orderBy(true, map.get("order").equals("asc"), StrUtil.toUnderlineCase(map.get("field")));
+ }
+ }
+ }
+// System.out.println(wrapper.getExpression().getSqlSegment());
+ return wrapper;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
new file mode 100644
index 0000000..0d3ac5f
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/SecurityUtils.java
@@ -0,0 +1,178 @@
+package com.ruoyi.common.utils;
+
+import java.util.Collection;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.util.PatternMatchUtils;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.exception.ServiceException;
+
+/**
+ * 瀹夊叏鏈嶅姟宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class SecurityUtils
+{
+
+ /**
+ * 鐢ㄦ埛ID
+ **/
+ public static Long getUserId()
+ {
+ try
+ {
+ return getLoginUser().getUserId();
+ }
+ catch (Exception e)
+ {
+ throw new ServiceException("鑾峰彇鐢ㄦ埛ID寮傚父", HttpStatus.UNAUTHORIZED);
+ }
+ }
+
+ /**
+ * 鑾峰彇閮ㄩ棬ID
+ **/
+ public static Long getDeptId()
+ {
+ try
+ {
+ return getLoginUser().getDeptId();
+ }
+ catch (Exception e)
+ {
+ throw new ServiceException("鑾峰彇閮ㄩ棬ID寮傚父", HttpStatus.UNAUTHORIZED);
+ }
+ }
+
+ /**
+ * 鑾峰彇鐢ㄦ埛璐︽埛
+ **/
+ public static String getUsername()
+ {
+ try
+ {
+ return getLoginUser().getUsername();
+ }
+ catch (Exception e)
+ {
+ throw new ServiceException("鑾峰彇鐢ㄦ埛璐︽埛寮傚父", HttpStatus.UNAUTHORIZED);
+ }
+ }
+
+ /**
+ * 鑾峰彇鐢ㄦ埛
+ **/
+ public static LoginUser getLoginUser()
+ {
+ try
+ {
+ return (LoginUser) getAuthentication().getPrincipal();
+ }
+ catch (Exception e)
+ {
+ throw new ServiceException("鑾峰彇鐢ㄦ埛淇℃伅寮傚父", HttpStatus.UNAUTHORIZED);
+ }
+ }
+
+ /**
+ * 鑾峰彇Authentication
+ */
+ public static Authentication getAuthentication()
+ {
+ return SecurityContextHolder.getContext().getAuthentication();
+ }
+
+ /**
+ * 鐢熸垚BCryptPasswordEncoder瀵嗙爜
+ *
+ * @param password 瀵嗙爜
+ * @return 鍔犲瘑瀛楃涓�
+ */
+ public static String encryptPassword(String password)
+ {
+ BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+ return passwordEncoder.encode(password);
+ }
+
+ /**
+ * 鍒ゆ柇瀵嗙爜鏄惁鐩稿悓
+ *
+ * @param rawPassword 鐪熷疄瀵嗙爜
+ * @param encodedPassword 鍔犲瘑鍚庡瓧绗�
+ * @return 缁撴灉
+ */
+ public static boolean matchesPassword(String rawPassword, String encodedPassword)
+ {
+ BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
+ return passwordEncoder.matches(rawPassword, encodedPassword);
+ }
+
+ /**
+ * 鏄惁涓虹鐞嗗憳
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public static boolean isAdmin(Long userId)
+ {
+ return userId != null && 1L == userId;
+ }
+
+ /**
+ * 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+ *
+ * @param permission 鏉冮檺瀛楃涓�
+ * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+ */
+ public static boolean hasPermi(String permission)
+ {
+ return hasPermi(getLoginUser().getPermissions(), permission);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁鍖呭惈鏉冮檺
+ *
+ * @param authorities 鏉冮檺鍒楄〃
+ * @param permission 鏉冮檺瀛楃涓�
+ * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+ */
+ public static boolean hasPermi(Collection<String> authorities, String permission)
+ {
+ return authorities.stream().filter(StringUtils::hasText)
+ .anyMatch(x -> Constants.ALL_PERMISSION.equals(x) || PatternMatchUtils.simpleMatch(x, permission));
+ }
+
+ /**
+ * 楠岃瘉鐢ㄦ埛鏄惁鎷ユ湁鏌愪釜瑙掕壊
+ *
+ * @param role 瑙掕壊鏍囪瘑
+ * @return 鐢ㄦ埛鏄惁鍏峰鏌愯鑹�
+ */
+ public static boolean hasRole(String role)
+ {
+ List<SysRole> roleList = getLoginUser().getUser().getRoles();
+ Collection<String> roles = roleList.stream().map(SysRole::getRoleKey).collect(Collectors.toSet());
+ return hasRole(roles, role);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁鍖呭惈瑙掕壊
+ *
+ * @param roles 瑙掕壊鍒楄〃
+ * @param role 瑙掕壊
+ * @return 鐢ㄦ埛鏄惁鍏峰鏌愯鑹叉潈闄�
+ */
+ public static boolean hasRole(Collection<String> roles, String role)
+ {
+ return roles.stream().filter(StringUtils::hasText)
+ .anyMatch(x -> Constants.SUPER_ADMIN.equals(x) || PatternMatchUtils.simpleMatch(x, role));
+ }
+
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
new file mode 100644
index 0000000..febb603
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ServletUtils.java
@@ -0,0 +1,218 @@
+package com.ruoyi.common.utils;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.text.Convert;
+
+/**
+ * 瀹㈡埛绔伐鍏风被
+ *
+ * @author ruoyi
+ */
+public class ServletUtils
+{
+ /**
+ * 鑾峰彇String鍙傛暟
+ */
+ public static String getParameter(String name)
+ {
+ return getRequest().getParameter(name);
+ }
+
+ /**
+ * 鑾峰彇String鍙傛暟
+ */
+ public static String getParameter(String name, String defaultValue)
+ {
+ return Convert.toStr(getRequest().getParameter(name), defaultValue);
+ }
+
+ /**
+ * 鑾峰彇Integer鍙傛暟
+ */
+ public static Integer getParameterToInt(String name)
+ {
+ return Convert.toInt(getRequest().getParameter(name));
+ }
+
+ /**
+ * 鑾峰彇Integer鍙傛暟
+ */
+ public static Integer getParameterToInt(String name, Integer defaultValue)
+ {
+ return Convert.toInt(getRequest().getParameter(name), defaultValue);
+ }
+
+ /**
+ * 鑾峰彇Boolean鍙傛暟
+ */
+ public static Boolean getParameterToBool(String name)
+ {
+ return Convert.toBool(getRequest().getParameter(name));
+ }
+
+ /**
+ * 鑾峰彇Boolean鍙傛暟
+ */
+ public static Boolean getParameterToBool(String name, Boolean defaultValue)
+ {
+ return Convert.toBool(getRequest().getParameter(name), defaultValue);
+ }
+
+ /**
+ * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+ *
+ * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+ * @return Map
+ */
+ public static Map<String, String[]> getParams(ServletRequest request)
+ {
+ final Map<String, String[]> map = request.getParameterMap();
+ return Collections.unmodifiableMap(map);
+ }
+
+ /**
+ * 鑾峰緱鎵�鏈夎姹傚弬鏁�
+ *
+ * @param request 璇锋眰瀵硅薄{@link ServletRequest}
+ * @return Map
+ */
+ public static Map<String, String> getParamMap(ServletRequest request)
+ {
+ Map<String, String> params = new HashMap<>();
+ for (Map.Entry<String, String[]> entry : getParams(request).entrySet())
+ {
+ params.put(entry.getKey(), StringUtils.join(entry.getValue(), ","));
+ }
+ return params;
+ }
+
+ /**
+ * 鑾峰彇request
+ */
+ public static HttpServletRequest getRequest()
+ {
+ return getRequestAttributes().getRequest();
+ }
+
+ /**
+ * 鑾峰彇response
+ */
+ public static HttpServletResponse getResponse()
+ {
+ return getRequestAttributes().getResponse();
+ }
+
+ /**
+ * 鑾峰彇session
+ */
+ public static HttpSession getSession()
+ {
+ return getRequest().getSession();
+ }
+
+ public static ServletRequestAttributes getRequestAttributes()
+ {
+ RequestAttributes attributes = RequestContextHolder.getRequestAttributes();
+ return (ServletRequestAttributes) attributes;
+ }
+
+ /**
+ * 灏嗗瓧绗︿覆娓叉煋鍒板鎴风
+ *
+ * @param response 娓叉煋瀵硅薄
+ * @param string 寰呮覆鏌撶殑瀛楃涓�
+ */
+ public static void renderString(HttpServletResponse response, String string)
+ {
+ try
+ {
+ response.setStatus(200);
+ response.setContentType("application/json");
+ response.setCharacterEncoding("utf-8");
+ response.getWriter().print(string);
+ }
+ catch (IOException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 鏄惁鏄疉jax寮傛璇锋眰
+ *
+ * @param request
+ */
+ public static boolean isAjaxRequest(HttpServletRequest request)
+ {
+ String accept = request.getHeader("accept");
+ if (accept != null && accept.contains("application/json"))
+ {
+ return true;
+ }
+
+ String xRequestedWith = request.getHeader("X-Requested-With");
+ if (xRequestedWith != null && xRequestedWith.contains("XMLHttpRequest"))
+ {
+ return true;
+ }
+
+ String uri = request.getRequestURI();
+ if (StringUtils.inStringIgnoreCase(uri, ".json", ".xml"))
+ {
+ return true;
+ }
+
+ String ajax = request.getParameter("__ajax");
+ return StringUtils.inStringIgnoreCase(ajax, "json", "xml");
+ }
+
+ /**
+ * 鍐呭缂栫爜
+ *
+ * @param str 鍐呭
+ * @return 缂栫爜鍚庣殑鍐呭
+ */
+ public static String urlEncode(String str)
+ {
+ try
+ {
+ return URLEncoder.encode(str, Constants.UTF8);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ return StringUtils.EMPTY;
+ }
+ }
+
+ /**
+ * 鍐呭瑙g爜
+ *
+ * @param str 鍐呭
+ * @return 瑙g爜鍚庣殑鍐呭
+ */
+ public static String urlDecode(String str)
+ {
+ try
+ {
+ return URLDecoder.decode(str, Constants.UTF8);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ return StringUtils.EMPTY;
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
new file mode 100644
index 0000000..25c2886
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/StringUtils.java
@@ -0,0 +1,684 @@
+package com.ruoyi.common.utils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.springframework.util.AntPathMatcher;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.text.StrFormatter;
+
+/**
+ * 瀛楃涓插伐鍏风被
+ *
+ * @author ruoyi
+ */
+public class StringUtils extends org.apache.commons.lang3.StringUtils
+{
+ /** 绌哄瓧绗︿覆 */
+ private static final String NULLSTR = "";
+
+ /** 涓嬪垝绾� */
+ private static final char SEPARATOR = '_';
+
+ /** 鏄熷彿 */
+ private static final char ASTERISK = '*';
+
+ /**
+ * 鑾峰彇鍙傛暟涓嶄负绌哄��
+ *
+ * @param value defaultValue 瑕佸垽鏂殑value
+ * @return value 杩斿洖鍊�
+ */
+ public static <T> T nvl(T value, T defaultValue)
+ {
+ return value != null ? value : defaultValue;
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓狢ollection鏄惁涓虹┖锛� 鍖呭惈List锛孲et锛孮ueue
+ *
+ * @param coll 瑕佸垽鏂殑Collection
+ * @return true锛氫负绌� false锛氶潪绌�
+ */
+ public static boolean isEmpty(Collection<?> coll)
+ {
+ return isNull(coll) || coll.isEmpty();
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓狢ollection鏄惁闈炵┖锛屽寘鍚獿ist锛孲et锛孮ueue
+ *
+ * @param coll 瑕佸垽鏂殑Collection
+ * @return true锛氶潪绌� false锛氱┖
+ */
+ public static boolean isNotEmpty(Collection<?> coll)
+ {
+ return !isEmpty(coll);
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓璞℃暟缁勬槸鍚︿负绌�
+ *
+ * @param objects 瑕佸垽鏂殑瀵硅薄鏁扮粍
+ ** @return true锛氫负绌� false锛氶潪绌�
+ */
+ public static boolean isEmpty(Object[] objects)
+ {
+ return isNull(objects) || (objects.length == 0);
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓璞℃暟缁勬槸鍚﹂潪绌�
+ *
+ * @param objects 瑕佸垽鏂殑瀵硅薄鏁扮粍
+ * @return true锛氶潪绌� false锛氱┖
+ */
+ public static boolean isNotEmpty(Object[] objects)
+ {
+ return !isEmpty(objects);
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓狹ap鏄惁涓虹┖
+ *
+ * @param map 瑕佸垽鏂殑Map
+ * @return true锛氫负绌� false锛氶潪绌�
+ */
+ public static boolean isEmpty(Map<?, ?> map)
+ {
+ return isNull(map) || map.isEmpty();
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓狹ap鏄惁涓虹┖
+ *
+ * @param map 瑕佸垽鏂殑Map
+ * @return true锛氶潪绌� false锛氱┖
+ */
+ public static boolean isNotEmpty(Map<?, ?> map)
+ {
+ return !isEmpty(map);
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓虹┖涓�
+ *
+ * @param str String
+ * @return true锛氫负绌� false锛氶潪绌�
+ */
+ public static boolean isEmpty(String str)
+ {
+ return isNull(str) || NULLSTR.equals(str.trim());
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓瓧绗︿覆鏄惁涓洪潪绌轰覆
+ *
+ * @param str String
+ * @return true锛氶潪绌轰覆 false锛氱┖涓�
+ */
+ public static boolean isNotEmpty(String str)
+ {
+ return !isEmpty(str);
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓璞℃槸鍚︿负绌�
+ *
+ * @param object Object
+ * @return true锛氫负绌� false锛氶潪绌�
+ */
+ public static boolean isNull(Object object)
+ {
+ return object == null;
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓璞℃槸鍚﹂潪绌�
+ *
+ * @param object Object
+ * @return true锛氶潪绌� false锛氱┖
+ */
+ public static boolean isNotNull(Object object)
+ {
+ return !isNull(object);
+ }
+
+ /**
+ * * 鍒ゆ柇涓�涓璞℃槸鍚︽槸鏁扮粍绫诲瀷锛圝ava鍩烘湰鍨嬪埆鐨勬暟缁勶級
+ *
+ * @param object 瀵硅薄
+ * @return true锛氭槸鏁扮粍 false锛氫笉鏄暟缁�
+ */
+ public static boolean isArray(Object object)
+ {
+ return isNotNull(object) && object.getClass().isArray();
+ }
+
+ /**
+ * 鍘荤┖鏍�
+ */
+ public static String trim(String str)
+ {
+ return (str == null ? "" : str.trim());
+ }
+
+ /**
+ * 鏇挎崲鎸囧畾瀛楃涓茬殑鎸囧畾鍖洪棿鍐呭瓧绗︿负"*"
+ *
+ * @param str 瀛楃涓�
+ * @param startInclude 寮�濮嬩綅缃紙鍖呭惈锛�
+ * @param endExclude 缁撴潫浣嶇疆锛堜笉鍖呭惈锛�
+ * @return 鏇挎崲鍚庣殑瀛楃涓�
+ */
+ public static String hide(CharSequence str, int startInclude, int endExclude)
+ {
+ if (isEmpty(str))
+ {
+ return NULLSTR;
+ }
+ final int strLength = str.length();
+ if (startInclude > strLength)
+ {
+ return NULLSTR;
+ }
+ if (endExclude > strLength)
+ {
+ endExclude = strLength;
+ }
+ if (startInclude > endExclude)
+ {
+ // 濡傛灉璧峰浣嶇疆澶т簬缁撴潫浣嶇疆锛屼笉鏇挎崲
+ return NULLSTR;
+ }
+ final char[] chars = new char[strLength];
+ for (int i = 0; i < strLength; i++)
+ {
+ if (i >= startInclude && i < endExclude)
+ {
+ chars[i] = ASTERISK;
+ }
+ else
+ {
+ chars[i] = str.charAt(i);
+ }
+ }
+ return new String(chars);
+ }
+
+ /**
+ * 鎴彇瀛楃涓�
+ *
+ * @param str 瀛楃涓�
+ * @param start 寮�濮�
+ * @return 缁撴灉
+ */
+ public static String substring(final String str, int start)
+ {
+ if (str == null)
+ {
+ return NULLSTR;
+ }
+
+ if (start < 0)
+ {
+ start = str.length() + start;
+ }
+
+ if (start < 0)
+ {
+ start = 0;
+ }
+ if (start > str.length())
+ {
+ return NULLSTR;
+ }
+
+ return str.substring(start);
+ }
+
+ /**
+ * 鎴彇瀛楃涓�
+ *
+ * @param str 瀛楃涓�
+ * @param start 寮�濮�
+ * @param end 缁撴潫
+ * @return 缁撴灉
+ */
+ public static String substring(final String str, int start, int end)
+ {
+ if (str == null)
+ {
+ return NULLSTR;
+ }
+
+ if (end < 0)
+ {
+ end = str.length() + end;
+ }
+ if (start < 0)
+ {
+ start = str.length() + start;
+ }
+
+ if (end > str.length())
+ {
+ end = str.length();
+ }
+
+ if (start > end)
+ {
+ return NULLSTR;
+ }
+
+ if (start < 0)
+ {
+ start = 0;
+ }
+ if (end < 0)
+ {
+ end = 0;
+ }
+
+ return str.substring(start, end);
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁涓虹┖锛屽苟涓斾笉鏄┖鐧藉瓧绗�
+ *
+ * @param str 瑕佸垽鏂殑value
+ * @return 缁撴灉
+ */
+ public static boolean hasText(String str)
+ {
+ return (str != null && !str.isEmpty() && containsText(str));
+ }
+
+ private static boolean containsText(CharSequence str)
+ {
+ int strLen = str.length();
+ for (int i = 0; i < strLen; i++)
+ {
+ if (!Character.isWhitespace(str.charAt(i)))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鏍煎紡鍖栨枃鏈�, {} 琛ㄧず鍗犱綅绗�<br>
+ * 姝ゆ柟娉曞彧鏄畝鍗曞皢鍗犱綅绗� {} 鎸夌収椤哄簭鏇挎崲涓哄弬鏁�<br>
+ * 濡傛灉鎯宠緭鍑� {} 浣跨敤 \\杞箟 { 鍗冲彲锛屽鏋滄兂杈撳嚭 {} 涔嬪墠鐨� \ 浣跨敤鍙岃浆涔夌 \\\\ 鍗冲彲<br>
+ * 渚嬶細<br>
+ * 閫氬父浣跨敤锛歠ormat("this is {} for {}", "a", "b") -> this is a for b<br>
+ * 杞箟{}锛� format("this is \\{} for {}", "a", "b") -> this is \{} for a<br>
+ * 杞箟\锛� format("this is \\\\{} for {}", "a", "b") -> this is \a for b<br>
+ *
+ * @param template 鏂囨湰妯℃澘锛岃鏇挎崲鐨勯儴鍒嗙敤 {} 琛ㄧず
+ * @param params 鍙傛暟鍊�
+ * @return 鏍煎紡鍖栧悗鐨勬枃鏈�
+ */
+ public static String format(String template, Object... params)
+ {
+ if (isEmpty(params) || isEmpty(template))
+ {
+ return template;
+ }
+ return StrFormatter.format(template, params);
+ }
+
+ /**
+ * 鏄惁涓篽ttp(s)://寮�澶�
+ *
+ * @param link 閾炬帴
+ * @return 缁撴灉
+ */
+ public static boolean ishttp(String link)
+ {
+ return StringUtils.startsWithAny(link, Constants.HTTP, Constants.HTTPS);
+ }
+
+ /**
+ * 瀛楃涓茶浆set
+ *
+ * @param str 瀛楃涓�
+ * @param sep 鍒嗛殧绗�
+ * @return set闆嗗悎
+ */
+ public static final Set<String> str2Set(String str, String sep)
+ {
+ return new HashSet<String>(str2List(str, sep, true, false));
+ }
+
+ /**
+ * 瀛楃涓茶浆list
+ *
+ * @param str 瀛楃涓�
+ * @param sep 鍒嗛殧绗�
+ * @param filterBlank 杩囨护绾┖鐧�
+ * @param trim 鍘绘帀棣栧熬绌虹櫧
+ * @return list闆嗗悎
+ */
+ public static final List<String> str2List(String str, String sep, boolean filterBlank, boolean trim)
+ {
+ List<String> list = new ArrayList<String>();
+ if (StringUtils.isEmpty(str))
+ {
+ return list;
+ }
+
+ // 杩囨护绌虹櫧瀛楃涓�
+ if (filterBlank && StringUtils.isBlank(str))
+ {
+ return list;
+ }
+ String[] split = str.split(sep);
+ for (String string : split)
+ {
+ if (filterBlank && StringUtils.isBlank(string))
+ {
+ continue;
+ }
+ if (trim)
+ {
+ string = string.trim();
+ }
+ list.add(string);
+ }
+
+ return list;
+ }
+
+ /**
+ * 鍒ゆ柇缁欏畾鐨刢ollection鍒楄〃涓槸鍚﹀寘鍚暟缁刟rray 鍒ゆ柇缁欏畾鐨勬暟缁刟rray涓槸鍚﹀寘鍚粰瀹氱殑鍏冪礌value
+ *
+ * @param collection 缁欏畾鐨勯泦鍚�
+ * @param array 缁欏畾鐨勬暟缁�
+ * @return boolean 缁撴灉
+ */
+ public static boolean containsAny(Collection<String> collection, String... array)
+ {
+ if (isEmpty(collection) || isEmpty(array))
+ {
+ return false;
+ }
+ else
+ {
+ for (String str : array)
+ {
+ if (collection.contains(str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ }
+
+ /**
+ * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀寘鍚寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆鍚屾椂涓插拷鐣ュぇ灏忓啓
+ *
+ * @param cs 鎸囧畾瀛楃涓�
+ * @param searchCharSequences 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+ * @return 鏄惁鍖呭惈浠绘剰涓�涓瓧绗︿覆
+ */
+ public static boolean containsAnyIgnoreCase(CharSequence cs, CharSequence... searchCharSequences)
+ {
+ if (isEmpty(cs) || isEmpty(searchCharSequences))
+ {
+ return false;
+ }
+ for (CharSequence testStr : searchCharSequences)
+ {
+ if (containsIgnoreCase(cs, testStr))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 椹煎嘲杞笅鍒掔嚎鍛藉悕
+ */
+ public static String toUnderScoreCase(String str)
+ {
+ if (str == null)
+ {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder();
+ // 鍓嶇疆瀛楃鏄惁澶у啓
+ boolean preCharIsUpperCase = true;
+ // 褰撳墠瀛楃鏄惁澶у啓
+ boolean curreCharIsUpperCase = true;
+ // 涓嬩竴瀛楃鏄惁澶у啓
+ boolean nexteCharIsUpperCase = true;
+ for (int i = 0; i < str.length(); i++)
+ {
+ char c = str.charAt(i);
+ if (i > 0)
+ {
+ preCharIsUpperCase = Character.isUpperCase(str.charAt(i - 1));
+ }
+ else
+ {
+ preCharIsUpperCase = false;
+ }
+
+ curreCharIsUpperCase = Character.isUpperCase(c);
+
+ if (i < (str.length() - 1))
+ {
+ nexteCharIsUpperCase = Character.isUpperCase(str.charAt(i + 1));
+ }
+
+ if (preCharIsUpperCase && curreCharIsUpperCase && !nexteCharIsUpperCase)
+ {
+ sb.append(SEPARATOR);
+ }
+ else if ((i != 0 && !preCharIsUpperCase) && curreCharIsUpperCase)
+ {
+ sb.append(SEPARATOR);
+ }
+ sb.append(Character.toLowerCase(c));
+ }
+
+ return sb.toString();
+ }
+
+ /**
+ * 鏄惁鍖呭惈瀛楃涓�
+ *
+ * @param str 楠岃瘉瀛楃涓�
+ * @param strs 瀛楃涓茬粍
+ * @return 鍖呭惈杩斿洖true
+ */
+ public static boolean inStringIgnoreCase(String str, String... strs)
+ {
+ if (str != null && strs != null)
+ {
+ for (String s : strs)
+ {
+ if (str.equalsIgnoreCase(trim(s)))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 灏嗕笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆杞崲涓洪┘宄板紡銆傚鏋滆浆鎹㈠墠鐨勪笅鍒掔嚎澶у啓鏂瑰紡鍛藉悕鐨勫瓧绗︿覆涓虹┖锛屽垯杩斿洖绌哄瓧绗︿覆銆� 渚嬪锛欻ELLO_WORLD->HelloWorld
+ *
+ * @param name 杞崲鍓嶇殑涓嬪垝绾垮ぇ鍐欐柟寮忓懡鍚嶇殑瀛楃涓�
+ * @return 杞崲鍚庣殑椹煎嘲寮忓懡鍚嶇殑瀛楃涓�
+ */
+ public static String convertToCamelCase(String name)
+ {
+ StringBuilder result = new StringBuilder();
+ // 蹇�熸鏌�
+ if (name == null || name.isEmpty())
+ {
+ // 娌″繀瑕佽浆鎹�
+ return "";
+ }
+ else if (!name.contains("_"))
+ {
+ // 涓嶅惈涓嬪垝绾匡紝浠呭皢棣栧瓧姣嶅ぇ鍐�
+ return name.substring(0, 1).toUpperCase() + name.substring(1);
+ }
+ // 鐢ㄤ笅鍒掔嚎灏嗗師濮嬪瓧绗︿覆鍒嗗壊
+ String[] camels = name.split("_");
+ for (String camel : camels)
+ {
+ // 璺宠繃鍘熷瀛楃涓蹭腑寮�澶淬�佺粨灏剧殑涓嬫崲绾挎垨鍙岄噸涓嬪垝绾�
+ if (camel.isEmpty())
+ {
+ continue;
+ }
+ // 棣栧瓧姣嶅ぇ鍐�
+ result.append(camel.substring(0, 1).toUpperCase());
+ result.append(camel.substring(1).toLowerCase());
+ }
+ return result.toString();
+ }
+
+ /**
+ * 椹煎嘲寮忓懡鍚嶆硶
+ * 渚嬪锛歶ser_name->userName
+ */
+ public static String toCamelCase(String s)
+ {
+ if (s == null)
+ {
+ return null;
+ }
+ if (s.indexOf(SEPARATOR) == -1)
+ {
+ return s;
+ }
+ s = s.toLowerCase();
+ StringBuilder sb = new StringBuilder(s.length());
+ boolean upperCase = false;
+ for (int i = 0; i < s.length(); i++)
+ {
+ char c = s.charAt(i);
+
+ if (c == SEPARATOR)
+ {
+ upperCase = true;
+ }
+ else if (upperCase)
+ {
+ sb.append(Character.toUpperCase(c));
+ upperCase = false;
+ }
+ else
+ {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ /**
+ * 鏌ユ壘鎸囧畾瀛楃涓叉槸鍚﹀尮閰嶆寚瀹氬瓧绗︿覆鍒楄〃涓殑浠绘剰涓�涓瓧绗︿覆
+ *
+ * @param str 鎸囧畾瀛楃涓�
+ * @param strs 闇�瑕佹鏌ョ殑瀛楃涓叉暟缁�
+ * @return 鏄惁鍖归厤
+ */
+ public static boolean matches(String str, List<String> strs)
+ {
+ if (isEmpty(str) || isEmpty(strs))
+ {
+ return false;
+ }
+ for (String pattern : strs)
+ {
+ if (isMatch(pattern, str))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鍒ゆ柇url鏄惁涓庤鍒欓厤缃�:
+ * ? 琛ㄧず鍗曚釜瀛楃;
+ * * 琛ㄧず涓�灞傝矾寰勫唴鐨勪换鎰忓瓧绗︿覆锛屼笉鍙法灞傜骇;
+ * ** 琛ㄧず浠绘剰灞傝矾寰�;
+ *
+ * @param pattern 鍖归厤瑙勫垯
+ * @param url 闇�瑕佸尮閰嶇殑url
+ * @return
+ */
+ public static boolean isMatch(String pattern, String url)
+ {
+ AntPathMatcher matcher = new AntPathMatcher();
+ return matcher.match(pattern, url);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static <T> T cast(Object obj)
+ {
+ return (T) obj;
+ }
+
+ /**
+ * 鏁板瓧宸﹁竟琛ラ綈0锛屼娇涔嬭揪鍒版寚瀹氶暱搴︺�傛敞鎰忥紝濡傛灉鏁板瓧杞崲涓哄瓧绗︿覆鍚庯紝闀垮害澶т簬size锛屽垯鍙繚鐣� 鏈�鍚巗ize涓瓧绗︺��
+ *
+ * @param num 鏁板瓧瀵硅薄
+ * @param size 瀛楃涓叉寚瀹氶暱搴�
+ * @return 杩斿洖鏁板瓧鐨勫瓧绗︿覆鏍煎紡锛岃瀛楃涓蹭负鎸囧畾闀垮害銆�
+ */
+ public static final String padl(final Number num, final int size)
+ {
+ return padl(num.toString(), size, '0');
+ }
+
+ /**
+ * 瀛楃涓插乏琛ラ綈銆傚鏋滃師濮嬪瓧绗︿覆s闀垮害澶т簬size锛屽垯鍙繚鐣欐渶鍚巗ize涓瓧绗︺��
+ *
+ * @param s 鍘熷瀛楃涓�
+ * @param size 瀛楃涓叉寚瀹氶暱搴�
+ * @param c 鐢ㄤ簬琛ラ綈鐨勫瓧绗�
+ * @return 杩斿洖鎸囧畾闀垮害鐨勫瓧绗︿覆锛岀敱鍘熷瓧绗︿覆宸﹁ˉ榻愭垨鎴彇寰楀埌銆�
+ */
+ public static final String padl(final String s, final int size, final char c)
+ {
+ final StringBuilder sb = new StringBuilder(size);
+ if (s != null)
+ {
+ final int len = s.length();
+ if (s.length() <= size)
+ {
+ for (int i = size - len; i > 0; i--)
+ {
+ sb.append(c);
+ }
+ sb.append(s);
+ }
+ else
+ {
+ return s.substring(len - size, len);
+ }
+ }
+ else
+ {
+ for (int i = size; i > 0; i--)
+ {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
new file mode 100644
index 0000000..71fe6d5
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/Threads.java
@@ -0,0 +1,99 @@
+package com.ruoyi.common.utils;
+
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 绾跨▼鐩稿叧宸ュ叿绫�.
+ *
+ * @author ruoyi
+ */
+public class Threads
+{
+ private static final Logger logger = LoggerFactory.getLogger(Threads.class);
+
+ /**
+ * sleep绛夊緟,鍗曚綅涓烘绉�
+ */
+ public static void sleep(long milliseconds)
+ {
+ try
+ {
+ Thread.sleep(milliseconds);
+ }
+ catch (InterruptedException e)
+ {
+ return;
+ }
+ }
+
+ /**
+ * 鍋滄绾跨▼姹�
+ * 鍏堜娇鐢╯hutdown, 鍋滄鎺ユ敹鏂颁换鍔″苟灏濊瘯瀹屾垚鎵�鏈夊凡瀛樺湪浠诲姟.
+ * 濡傛灉瓒呮椂, 鍒欒皟鐢╯hutdownNow, 鍙栨秷鍦╳orkQueue涓璓ending鐨勪换鍔�,骞朵腑鏂墍鏈夐樆濉炲嚱鏁�.
+ * 濡傛灉浠嶇劧瓒呮檪锛屽墖寮峰埗閫�鍑�.
+ * 鍙﹀鍦╯hutdown鏃剁嚎绋嬫湰韬璋冪敤涓柇鍋氫簡澶勭悊.
+ */
+ public static void shutdownAndAwaitTermination(ExecutorService pool)
+ {
+ if (pool != null && !pool.isShutdown())
+ {
+ pool.shutdown();
+ try
+ {
+ if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+ {
+ pool.shutdownNow();
+ if (!pool.awaitTermination(120, TimeUnit.SECONDS))
+ {
+ logger.info("Pool did not terminate");
+ }
+ }
+ }
+ catch (InterruptedException ie)
+ {
+ pool.shutdownNow();
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ /**
+ * 鎵撳嵃绾跨▼寮傚父淇℃伅
+ */
+ public static void printException(Runnable r, Throwable t)
+ {
+ if (t == null && r instanceof Future<?>)
+ {
+ try
+ {
+ Future<?> future = (Future<?>) r;
+ if (future.isDone())
+ {
+ future.get();
+ }
+ }
+ catch (CancellationException ce)
+ {
+ t = ce;
+ }
+ catch (ExecutionException ee)
+ {
+ t = ee.getCause();
+ }
+ catch (InterruptedException ie)
+ {
+ Thread.currentThread().interrupt();
+ }
+ }
+ if (t != null)
+ {
+ logger.error(t.getMessage(), t);
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java
new file mode 100644
index 0000000..4463662
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanUtils.java
@@ -0,0 +1,110 @@
+package com.ruoyi.common.utils.bean;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Bean 宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class BeanUtils extends org.springframework.beans.BeanUtils
+{
+ /** Bean鏂规硶鍚嶄腑灞炴�у悕寮�濮嬬殑涓嬫爣 */
+ private static final int BEAN_METHOD_PROP_INDEX = 3;
+
+ /** * 鍖归厤getter鏂规硶鐨勬鍒欒〃杈惧紡 */
+ private static final Pattern GET_PATTERN = Pattern.compile("get(\\p{javaUpperCase}\\w*)");
+
+ /** * 鍖归厤setter鏂规硶鐨勬鍒欒〃杈惧紡 */
+ private static final Pattern SET_PATTERN = Pattern.compile("set(\\p{javaUpperCase}\\w*)");
+
+ /**
+ * Bean灞炴�у鍒跺伐鍏锋柟娉曘��
+ *
+ * @param dest 鐩爣瀵硅薄
+ * @param src 婧愬璞�
+ */
+ public static void copyBeanProp(Object dest, Object src)
+ {
+ try
+ {
+ copyProperties(src, dest);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 鑾峰彇瀵硅薄鐨剆etter鏂规硶銆�
+ *
+ * @param obj 瀵硅薄
+ * @return 瀵硅薄鐨剆etter鏂规硶鍒楄〃
+ */
+ public static List<Method> getSetterMethods(Object obj)
+ {
+ // setter鏂规硶鍒楄〃
+ List<Method> setterMethods = new ArrayList<Method>();
+
+ // 鑾峰彇鎵�鏈夋柟娉�
+ Method[] methods = obj.getClass().getMethods();
+
+ // 鏌ユ壘setter鏂规硶
+
+ for (Method method : methods)
+ {
+ Matcher m = SET_PATTERN.matcher(method.getName());
+ if (m.matches() && (method.getParameterTypes().length == 1))
+ {
+ setterMethods.add(method);
+ }
+ }
+ // 杩斿洖setter鏂规硶鍒楄〃
+ return setterMethods;
+ }
+
+ /**
+ * 鑾峰彇瀵硅薄鐨刧etter鏂规硶銆�
+ *
+ * @param obj 瀵硅薄
+ * @return 瀵硅薄鐨刧etter鏂规硶鍒楄〃
+ */
+
+ public static List<Method> getGetterMethods(Object obj)
+ {
+ // getter鏂规硶鍒楄〃
+ List<Method> getterMethods = new ArrayList<Method>();
+ // 鑾峰彇鎵�鏈夋柟娉�
+ Method[] methods = obj.getClass().getMethods();
+ // 鏌ユ壘getter鏂规硶
+ for (Method method : methods)
+ {
+ Matcher m = GET_PATTERN.matcher(method.getName());
+ if (m.matches() && (method.getParameterTypes().length == 0))
+ {
+ getterMethods.add(method);
+ }
+ }
+ // 杩斿洖getter鏂规硶鍒楄〃
+ return getterMethods;
+ }
+
+ /**
+ * 妫�鏌ean鏂规硶鍚嶄腑鐨勫睘鎬у悕鏄惁鐩哥瓑銆�<br>
+ * 濡俫etName()鍜宻etName()灞炴�у悕涓�鏍凤紝getName()鍜宻etAge()灞炴�у悕涓嶄竴鏍枫��
+ *
+ * @param m1 鏂规硶鍚�1
+ * @param m2 鏂规硶鍚�2
+ * @return 灞炴�у悕涓�鏍疯繑鍥瀟rue锛屽惁鍒欒繑鍥瀎alse
+ */
+
+ public static boolean isMethodPropEquals(String m1, String m2)
+ {
+ return m1.substring(BEAN_METHOD_PROP_INDEX).equals(m2.substring(BEAN_METHOD_PROP_INDEX));
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
new file mode 100644
index 0000000..80bfed7
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/bean/BeanValidators.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.utils.bean;
+
+import java.util.Set;
+import javax.validation.ConstraintViolation;
+import javax.validation.ConstraintViolationException;
+import javax.validation.Validator;
+
+/**
+ * bean瀵硅薄灞炴�ч獙璇�
+ *
+ * @author ruoyi
+ */
+public class BeanValidators
+{
+ public static void validateWithException(Validator validator, Object object, Class<?>... groups)
+ throws ConstraintViolationException
+ {
+ Set<ConstraintViolation<Object>> constraintViolations = validator.validate(object, groups);
+ if (!constraintViolations.isEmpty())
+ {
+ throw new ConstraintViolationException(constraintViolations);
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java
new file mode 100644
index 0000000..68130b9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileTypeUtils.java
@@ -0,0 +1,76 @@
+package com.ruoyi.common.utils.file;
+
+import java.io.File;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 鏂囦欢绫诲瀷宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class FileTypeUtils
+{
+ /**
+ * 鑾峰彇鏂囦欢绫诲瀷
+ * <p>
+ * 渚嬪: ruoyi.txt, 杩斿洖: txt
+ *
+ * @param file 鏂囦欢鍚�
+ * @return 鍚庣紑锛堜笉鍚�".")
+ */
+ public static String getFileType(File file)
+ {
+ if (null == file)
+ {
+ return StringUtils.EMPTY;
+ }
+ return getFileType(file.getName());
+ }
+
+ /**
+ * 鑾峰彇鏂囦欢绫诲瀷
+ * <p>
+ * 渚嬪: ruoyi.txt, 杩斿洖: txt
+ *
+ * @param fileName 鏂囦欢鍚�
+ * @return 鍚庣紑锛堜笉鍚�".")
+ */
+ public static String getFileType(String fileName)
+ {
+ int separatorIndex = fileName.lastIndexOf(".");
+ if (separatorIndex < 0)
+ {
+ return "";
+ }
+ return fileName.substring(separatorIndex + 1).toLowerCase();
+ }
+
+ /**
+ * 鑾峰彇鏂囦欢绫诲瀷
+ *
+ * @param photoByte 鏂囦欢瀛楄妭鐮�
+ * @return 鍚庣紑锛堜笉鍚�".")
+ */
+ public static String getFileExtendName(byte[] photoByte)
+ {
+ String strFileExtendName = "JPG";
+ if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+ && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+ {
+ strFileExtendName = "GIF";
+ }
+ else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+ {
+ strFileExtendName = "JPG";
+ }
+ else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+ {
+ strFileExtendName = "BMP";
+ }
+ else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+ {
+ strFileExtendName = "PNG";
+ }
+ return strFileExtendName;
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
new file mode 100644
index 0000000..d5455c4
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
@@ -0,0 +1,232 @@
+package com.ruoyi.common.utils.file;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+import java.util.Objects;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.exception.file.FileNameLengthLimitExceededException;
+import com.ruoyi.common.exception.file.FileSizeLimitExceededException;
+import com.ruoyi.common.exception.file.InvalidExtensionException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.uuid.Seq;
+
+/**
+ * 鏂囦欢涓婁紶宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class FileUploadUtils
+{
+ /**
+ * 榛樿澶у皬 50M
+ */
+ public static final long DEFAULT_MAX_SIZE = 50 * 1024 * 1024L;
+
+ /**
+ * 榛樿鐨勬枃浠跺悕鏈�澶ч暱搴� 100
+ */
+ public static final int DEFAULT_FILE_NAME_LENGTH = 100;
+
+ /**
+ * 榛樿涓婁紶鐨勫湴鍧�
+ */
+ private static String defaultBaseDir = RuoYiConfig.getProfile();
+
+ public static void setDefaultBaseDir(String defaultBaseDir)
+ {
+ FileUploadUtils.defaultBaseDir = defaultBaseDir;
+ }
+
+ public static String getDefaultBaseDir()
+ {
+ return defaultBaseDir;
+ }
+
+ /**
+ * 浠ラ粯璁ら厤缃繘琛屾枃浠朵笂浼�
+ *
+ * @param file 涓婁紶鐨勬枃浠�
+ * @return 鏂囦欢鍚嶇О
+ * @throws Exception
+ */
+ public static final String upload(MultipartFile file) throws IOException
+ {
+ try
+ {
+ return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+ }
+ catch (Exception e)
+ {
+ throw new IOException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 鏍规嵁鏂囦欢璺緞涓婁紶
+ *
+ * @param baseDir 鐩稿搴旂敤鐨勫熀鐩綍
+ * @param file 涓婁紶鐨勬枃浠�
+ * @return 鏂囦欢鍚嶇О
+ * @throws IOException
+ */
+ public static final String upload(String baseDir, MultipartFile file) throws IOException
+ {
+ try
+ {
+ return upload(baseDir, file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+ }
+ catch (Exception e)
+ {
+ throw new IOException(e.getMessage(), e);
+ }
+ }
+
+ /**
+ * 鏂囦欢涓婁紶
+ *
+ * @param baseDir 鐩稿搴旂敤鐨勫熀鐩綍
+ * @param file 涓婁紶鐨勬枃浠�
+ * @param allowedExtension 涓婁紶鏂囦欢绫诲瀷
+ * @return 杩斿洖涓婁紶鎴愬姛鐨勬枃浠跺悕
+ * @throws FileSizeLimitExceededException 濡傛灉瓒呭嚭鏈�澶уぇ灏�
+ * @throws FileNameLengthLimitExceededException 鏂囦欢鍚嶅お闀�
+ * @throws IOException 姣斿璇诲啓鏂囦欢鍑洪敊鏃�
+ * @throws InvalidExtensionException 鏂囦欢鏍¢獙寮傚父
+ */
+ public static final String upload(String baseDir, MultipartFile file, String[] allowedExtension)
+ throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
+ InvalidExtensionException
+ {
+ int fileNamelength = Objects.requireNonNull(file.getOriginalFilename()).length();
+ if (fileNamelength > FileUploadUtils.DEFAULT_FILE_NAME_LENGTH)
+ {
+ throw new FileNameLengthLimitExceededException(FileUploadUtils.DEFAULT_FILE_NAME_LENGTH);
+ }
+
+ assertAllowed(file, allowedExtension);
+
+ String fileName = extractFilename(file);
+
+ String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
+ file.transferTo(Paths.get(absPath));
+ return getPathFileName(baseDir, fileName);
+ }
+
+ /**
+ * 缂栫爜鏂囦欢鍚�
+ */
+ public static final String extractFilename(MultipartFile file)
+ {
+ return StringUtils.format("{}/{}_{}.{}", DateUtils.datePath(),
+ FilenameUtils.getBaseName(file.getOriginalFilename()), Seq.getId(Seq.uploadSeqType), getExtension(file));
+ }
+
+ public static final File getAbsoluteFile(String uploadDir, String fileName) throws IOException
+ {
+ File desc = new File(uploadDir + File.separator + fileName);
+
+ if (!desc.exists())
+ {
+ if (!desc.getParentFile().exists())
+ {
+ desc.getParentFile().mkdirs();
+ }
+ }
+ return desc;
+ }
+
+ public static final String getPathFileName(String uploadDir, String fileName) throws IOException
+ {
+ int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
+ String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
+ return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
+ }
+
+ /**
+ * 鏂囦欢澶у皬鏍¢獙
+ *
+ * @param file 涓婁紶鐨勬枃浠�
+ * @return
+ * @throws FileSizeLimitExceededException 濡傛灉瓒呭嚭鏈�澶уぇ灏�
+ * @throws InvalidExtensionException
+ */
+ public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
+ throws FileSizeLimitExceededException, InvalidExtensionException
+ {
+ long size = file.getSize();
+ if (size > DEFAULT_MAX_SIZE)
+ {
+ throw new FileSizeLimitExceededException(DEFAULT_MAX_SIZE / 1024 / 1024);
+ }
+
+ String fileName = file.getOriginalFilename();
+ String extension = getExtension(file);
+ if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
+ {
+ if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
+ {
+ throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
+ fileName);
+ }
+ else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
+ {
+ throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
+ fileName);
+ }
+ else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
+ {
+ throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
+ fileName);
+ }
+ else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
+ {
+ throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
+ fileName);
+ }
+ else
+ {
+ throw new InvalidExtensionException(allowedExtension, extension, fileName);
+ }
+ }
+ }
+
+ /**
+ * 鍒ゆ柇MIME绫诲瀷鏄惁鏄厑璁哥殑MIME绫诲瀷
+ *
+ * @param extension
+ * @param allowedExtension
+ * @return
+ */
+ public static final boolean isAllowedExtension(String extension, String[] allowedExtension)
+ {
+ for (String str : allowedExtension)
+ {
+ if (str.equalsIgnoreCase(extension))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鑾峰彇鏂囦欢鍚嶇殑鍚庣紑
+ *
+ * @param file 琛ㄥ崟鏂囦欢
+ * @return 鍚庣紑鍚�
+ */
+ public static final String getExtension(MultipartFile file)
+ {
+ String extension = FilenameUtils.getExtension(file.getOriginalFilename());
+ if (StringUtils.isEmpty(extension))
+ {
+ extension = MimeTypeUtils.getExtension(Objects.requireNonNull(file.getContentType()));
+ }
+ return extension;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
new file mode 100644
index 0000000..ed4cbc9
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUtils.java
@@ -0,0 +1,291 @@
+package com.ruoyi.common.utils.file;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.ArrayUtils;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.uuid.IdUtils;
+import org.apache.commons.io.FilenameUtils;
+
+/**
+ * 鏂囦欢澶勭悊宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class FileUtils
+{
+ public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
+
+ /**
+ * 杈撳嚭鎸囧畾鏂囦欢鐨刡yte鏁扮粍
+ *
+ * @param filePath 鏂囦欢璺緞
+ * @param os 杈撳嚭娴�
+ * @return
+ */
+ public static void writeBytes(String filePath, OutputStream os) throws IOException
+ {
+ FileInputStream fis = null;
+ try
+ {
+ File file = new File(filePath);
+ if (!file.exists())
+ {
+ throw new FileNotFoundException(filePath);
+ }
+ fis = new FileInputStream(file);
+ byte[] b = new byte[1024];
+ int length;
+ while ((length = fis.read(b)) > 0)
+ {
+ os.write(b, 0, length);
+ }
+ }
+ catch (IOException e)
+ {
+ throw e;
+ }
+ finally
+ {
+ IOUtils.close(os);
+ IOUtils.close(fis);
+ }
+ }
+
+ /**
+ * 鍐欐暟鎹埌鏂囦欢涓�
+ *
+ * @param data 鏁版嵁
+ * @return 鐩爣鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ public static String writeImportBytes(byte[] data) throws IOException
+ {
+ return writeBytes(data, RuoYiConfig.getImportPath());
+ }
+
+ /**
+ * 鍐欐暟鎹埌鏂囦欢涓�
+ *
+ * @param data 鏁版嵁
+ * @param uploadDir 鐩爣鏂囦欢
+ * @return 鐩爣鏂囦欢
+ * @throws IOException IO寮傚父
+ */
+ public static String writeBytes(byte[] data, String uploadDir) throws IOException
+ {
+ FileOutputStream fos = null;
+ String pathName = "";
+ try
+ {
+ String extension = getFileExtendName(data);
+ pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
+ File file = FileUploadUtils.getAbsoluteFile(uploadDir, pathName);
+ fos = new FileOutputStream(file);
+ fos.write(data);
+ }
+ finally
+ {
+ IOUtils.close(fos);
+ }
+ return FileUploadUtils.getPathFileName(uploadDir, pathName);
+ }
+
+ /**
+ * 鍒犻櫎鏂囦欢
+ *
+ * @param filePath 鏂囦欢
+ * @return
+ */
+ public static boolean deleteFile(String filePath)
+ {
+ boolean flag = false;
+ File file = new File(filePath);
+ // 璺緞涓烘枃浠朵笖涓嶄负绌哄垯杩涜鍒犻櫎
+ if (file.isFile() && file.exists())
+ {
+ flag = file.delete();
+ }
+ return flag;
+ }
+
+ /**
+ * 鏂囦欢鍚嶇О楠岃瘉
+ *
+ * @param filename 鏂囦欢鍚嶇О
+ * @return true 姝e父 false 闈炴硶
+ */
+ public static boolean isValidFilename(String filename)
+ {
+ return filename.matches(FILENAME_PATTERN);
+ }
+
+ /**
+ * 妫�鏌ユ枃浠舵槸鍚﹀彲涓嬭浇
+ *
+ * @param resource 闇�瑕佷笅杞界殑鏂囦欢
+ * @return true 姝e父 false 闈炴硶
+ */
+ public static boolean checkAllowDownload(String resource)
+ {
+ // 绂佹鐩綍涓婅烦绾у埆
+ if (StringUtils.contains(resource, ".."))
+ {
+ return false;
+ }
+
+ // 妫�鏌ュ厑璁镐笅杞界殑鏂囦欢瑙勫垯
+ if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
+ {
+ return true;
+ }
+
+ // 涓嶅湪鍏佽涓嬭浇鐨勬枃浠惰鍒�
+ return false;
+ }
+
+ /**
+ * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+ *
+ * @param request 璇锋眰瀵硅薄
+ * @param fileName 鏂囦欢鍚�
+ * @return 缂栫爜鍚庣殑鏂囦欢鍚�
+ */
+ public static String setFileDownloadHeader(HttpServletRequest request, String fileName) throws UnsupportedEncodingException
+ {
+ final String agent = request.getHeader("USER-AGENT");
+ String filename = fileName;
+ if (agent.contains("MSIE"))
+ {
+ // IE娴忚鍣�
+ filename = URLEncoder.encode(filename, "utf-8");
+ filename = filename.replace("+", " ");
+ }
+ else if (agent.contains("Firefox"))
+ {
+ // 鐏嫄娴忚鍣�
+ filename = new String(fileName.getBytes(), "ISO8859-1");
+ }
+ else if (agent.contains("Chrome"))
+ {
+ // google娴忚鍣�
+ filename = URLEncoder.encode(filename, "utf-8");
+ }
+ else
+ {
+ // 鍏跺畠娴忚鍣�
+ filename = URLEncoder.encode(filename, "utf-8");
+ }
+ return filename;
+ }
+
+ /**
+ * 涓嬭浇鏂囦欢鍚嶉噸鏂扮紪鐮�
+ *
+ * @param response 鍝嶅簲瀵硅薄
+ * @param realFileName 鐪熷疄鏂囦欢鍚�
+ */
+ public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException
+ {
+ String percentEncodedFileName = percentEncode(realFileName);
+
+ StringBuilder contentDispositionValue = new StringBuilder();
+ contentDispositionValue.append("attachment; filename=")
+ .append(percentEncodedFileName)
+ .append(";")
+ .append("filename*=")
+ .append("utf-8''")
+ .append(percentEncodedFileName);
+
+ response.addHeader("Access-Control-Expose-Headers", "Content-Disposition,download-filename");
+ response.setHeader("Content-disposition", contentDispositionValue.toString());
+ response.setHeader("download-filename", percentEncodedFileName);
+ }
+
+ /**
+ * 鐧惧垎鍙风紪鐮佸伐鍏锋柟娉�
+ *
+ * @param s 闇�瑕佺櫨鍒嗗彿缂栫爜鐨勫瓧绗︿覆
+ * @return 鐧惧垎鍙风紪鐮佸悗鐨勫瓧绗︿覆
+ */
+ public static String percentEncode(String s) throws UnsupportedEncodingException
+ {
+ String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
+ return encode.replaceAll("\\+", "%20");
+ }
+
+ /**
+ * 鑾峰彇鍥惧儚鍚庣紑
+ *
+ * @param photoByte 鍥惧儚鏁版嵁
+ * @return 鍚庣紑鍚�
+ */
+ public static String getFileExtendName(byte[] photoByte)
+ {
+ String strFileExtendName = "jpg";
+ if ((photoByte[0] == 71) && (photoByte[1] == 73) && (photoByte[2] == 70) && (photoByte[3] == 56)
+ && ((photoByte[4] == 55) || (photoByte[4] == 57)) && (photoByte[5] == 97))
+ {
+ strFileExtendName = "gif";
+ }
+ else if ((photoByte[6] == 74) && (photoByte[7] == 70) && (photoByte[8] == 73) && (photoByte[9] == 70))
+ {
+ strFileExtendName = "jpg";
+ }
+ else if ((photoByte[0] == 66) && (photoByte[1] == 77))
+ {
+ strFileExtendName = "bmp";
+ }
+ else if ((photoByte[1] == 80) && (photoByte[2] == 78) && (photoByte[3] == 71))
+ {
+ strFileExtendName = "png";
+ }
+ return strFileExtendName;
+ }
+
+ /**
+ * 鑾峰彇鏂囦欢鍚嶇О /profile/upload/2022/04/16/ruoyi.png -- ruoyi.png
+ *
+ * @param fileName 璺緞鍚嶇О
+ * @return 娌℃湁鏂囦欢璺緞鐨勫悕绉�
+ */
+ public static String getName(String fileName)
+ {
+ if (fileName == null)
+ {
+ return null;
+ }
+ int lastUnixPos = fileName.lastIndexOf('/');
+ int lastWindowsPos = fileName.lastIndexOf('\\');
+ int index = Math.max(lastUnixPos, lastWindowsPos);
+ return fileName.substring(index + 1);
+ }
+
+ /**
+ * 鑾峰彇涓嶅甫鍚庣紑鏂囦欢鍚嶇О /profile/upload/2022/04/16/ruoyi.png -- ruoyi
+ *
+ * @param fileName 璺緞鍚嶇О
+ * @return 娌℃湁鏂囦欢璺緞鍜屽悗缂�鐨勫悕绉�
+ */
+ public static String getNameNotSuffix(String fileName)
+ {
+ if (fileName == null)
+ {
+ return null;
+ }
+ String baseName = FilenameUtils.getBaseName(fileName);
+ return baseName;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
new file mode 100644
index 0000000..432dfda
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/ImageUtils.java
@@ -0,0 +1,98 @@
+package com.ruoyi.common.utils.file;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Arrays;
+import org.apache.poi.util.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 鍥剧墖澶勭悊宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class ImageUtils
+{
+ private static final Logger log = LoggerFactory.getLogger(ImageUtils.class);
+
+ public static byte[] getImage(String imagePath)
+ {
+ InputStream is = getFile(imagePath);
+ try
+ {
+ return IOUtils.toByteArray(is);
+ }
+ catch (Exception e)
+ {
+ log.error("鍥剧墖鍔犺浇寮傚父 {}", e);
+ return null;
+ }
+ finally
+ {
+ IOUtils.closeQuietly(is);
+ }
+ }
+
+ public static InputStream getFile(String imagePath)
+ {
+ try
+ {
+ byte[] result = readFile(imagePath);
+ result = Arrays.copyOf(result, result.length);
+ return new ByteArrayInputStream(result);
+ }
+ catch (Exception e)
+ {
+ log.error("鑾峰彇鍥剧墖寮傚父 {}", e);
+ }
+ return null;
+ }
+
+ /**
+ * 璇诲彇鏂囦欢涓哄瓧鑺傛暟鎹�
+ *
+ * @param url 鍦板潃
+ * @return 瀛楄妭鏁版嵁
+ */
+ public static byte[] readFile(String url)
+ {
+ InputStream in = null;
+ try
+ {
+ if (url.startsWith("http"))
+ {
+ // 缃戠粶鍦板潃
+ URL urlObj = new URL(url);
+ URLConnection urlConnection = urlObj.openConnection();
+ urlConnection.setConnectTimeout(30 * 1000);
+ urlConnection.setReadTimeout(60 * 1000);
+ urlConnection.setDoInput(true);
+ in = urlConnection.getInputStream();
+ }
+ else
+ {
+ // 鏈満鍦板潃
+ String localPath = RuoYiConfig.getProfile();
+ String downloadPath = localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
+ in = new FileInputStream(downloadPath);
+ }
+ return IOUtils.toByteArray(in);
+ }
+ catch (Exception e)
+ {
+ log.error("鑾峰彇鏂囦欢璺緞寮傚父 {}", e);
+ return null;
+ }
+ finally
+ {
+ IOUtils.closeQuietly(in);
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
new file mode 100644
index 0000000..f968f1a
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MimeTypeUtils.java
@@ -0,0 +1,59 @@
+package com.ruoyi.common.utils.file;
+
+/**
+ * 濯掍綋绫诲瀷宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class MimeTypeUtils
+{
+ public static final String IMAGE_PNG = "image/png";
+
+ public static final String IMAGE_JPG = "image/jpg";
+
+ public static final String IMAGE_JPEG = "image/jpeg";
+
+ public static final String IMAGE_BMP = "image/bmp";
+
+ public static final String IMAGE_GIF = "image/gif";
+
+ public static final String[] IMAGE_EXTENSION = { "bmp", "gif", "jpg", "jpeg", "png" };
+
+ public static final String[] FLASH_EXTENSION = { "swf", "flv" };
+
+ public static final String[] MEDIA_EXTENSION = { "swf", "flv", "mp3", "wav", "wma", "wmv", "mid", "avi", "mpg",
+ "asf", "rm", "rmvb" };
+
+ public static final String[] VIDEO_EXTENSION = { "mp4", "avi", "rmvb" };
+
+ public static final String[] DEFAULT_ALLOWED_EXTENSION = {
+ // 鍥剧墖
+ "bmp", "gif", "jpg", "jpeg", "png",
+ // word excel powerpoint
+ "doc", "docx", "xls", "xlsx", "ppt", "pptx", "html", "htm", "txt",
+ // 鍘嬬缉鏂囦欢
+ "rar", "zip", "gz", "bz2",
+ // 瑙嗛鏍煎紡
+ "mp4", "avi", "rmvb",
+ // pdf
+ "pdf" };
+
+ public static String getExtension(String prefix)
+ {
+ switch (prefix)
+ {
+ case IMAGE_PNG:
+ return "png";
+ case IMAGE_JPG:
+ return "jpg";
+ case IMAGE_JPEG:
+ return "jpeg";
+ case IMAGE_BMP:
+ return "bmp";
+ case IMAGE_GIF:
+ return "gif";
+ default:
+ return "";
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MinioUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MinioUtils.java
new file mode 100644
index 0000000..25efe7c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/file/MinioUtils.java
@@ -0,0 +1,294 @@
+package com.ruoyi.common.utils.file;
+
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.core.toolkit.StringUtils;
+import com.ruoyi.common.core.domain.MinioResult;
+import com.ruoyi.common.exception.UtilException;
+import com.ruoyi.common.exception.file.InvalidExtensionException;
+import io.minio.*;
+import io.minio.http.Method;
+import io.minio.messages.DeleteError;
+import io.minio.messages.DeleteObject;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import org.springframework.util.FastByteArrayOutputStream;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Component
+public class MinioUtils {
+ @Resource
+ private MinioClient minioClient;
+
+ @Value("${minio.preview-expiry}")
+ private Integer previewExpiry;
+
+ /**
+ * 鍒ゆ柇瀛樺偍妗舵槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯鍒涘缓
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ */
+ public void existBucket(String bucketName) {
+ try {
+ boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+ if (!exists) {
+ minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 鍒涘缓瀛樺偍妗�
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @return 鏄惁鍒涘缓鎴愬姛
+ */
+ public Boolean makeBucket(String bucketName) {
+ try {
+ minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 鍒犻櫎瀛樺偍妗�
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @return 鏄惁鍒犻櫎鎴愬姛
+ */
+ public Boolean removeBucket(String bucketName) {
+ try {
+ minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 鍒ゆ柇瀵硅薄鏄惁瀛樺湪
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param originalFileName MinIO涓瓨鍌ㄥ璞″叏璺緞
+ * @return 瀵硅薄鏄惁瀛樺湪
+ */
+ public boolean existObject(String bucketName, String originalFileName) {
+ try {
+ minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(originalFileName).build());
+ } catch (Exception e) {
+ e.printStackTrace();
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * 鏂囦欢涓婁紶
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param file 鏂囦欢
+ * @return 妗朵腑浣嶇疆
+ */
+ public MinioResult upload(String bucketName, MultipartFile file, Boolean isPreviewExpiry) throws InvalidExtensionException {
+ MultipartFile[] fileArr = {file};
+ List<MinioResult> fileNames = upload(bucketName, fileArr, isPreviewExpiry);
+ return fileNames.isEmpty() ? null : fileNames.get(0);
+ }
+
+ /**
+ * 涓婁紶鏂囦欢
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param fileList 鏂囦欢鍒楄〃
+ * @return 妗朵腑浣嶇疆鍒楄〃
+ */
+ public List<MinioResult> upload(String bucketName, List<MultipartFile> fileList, Boolean isPreviewExpiry) throws InvalidExtensionException {
+ MultipartFile[] fileArr = fileList.toArray(new MultipartFile[0]);
+ return upload(bucketName, fileArr, isPreviewExpiry);
+ }
+
+ /**
+ * description: 涓婁紶鏂囦欢
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param fileArr 鏂囦欢鍒楄〃
+ * @return 妗朵腑浣嶇疆鍒楄〃
+ */
+ public List<MinioResult> upload(String bucketName, MultipartFile[] fileArr, Boolean isPreviewExpiry) throws InvalidExtensionException {
+ for (MultipartFile file : fileArr) {
+ FileUploadUtils.assertAllowed(file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
+ }
+ // 淇濊瘉妗朵竴瀹氬瓨鍦�
+ existBucket(bucketName);
+ // 鎵ц姝e父鎿嶄綔
+ List<MinioResult> bucketFileNames = new ArrayList<>(fileArr.length);
+ for (MultipartFile file : fileArr) {
+ // 鑾峰彇鍘熷鏂囦欢鍚嶇О
+ String originalFileName = file.getOriginalFilename();
+ // 鑾峰彇褰撳墠鏃ユ湡锛屾牸寮忎緥濡傦細2020-11
+ String datePath = new SimpleDateFormat("yyyy-MM").format(new Date());
+ // 鏂囦欢鍚嶇О
+ String uuid = IdWorker.get32UUID();
+ // 鑾峰彇鏂囦欢鍚庣紑
+ String suffix = originalFileName.substring(originalFileName.lastIndexOf("."));
+ String bucketFilePath = datePath + "/" + uuid + suffix;
+
+ // 鎺ㄩ�佹枃浠跺埌MinIO
+ try (InputStream in = file.getInputStream()) {
+ minioClient.putObject(PutObjectArgs.builder()
+ .bucket(bucketName)
+ .object(bucketFilePath)
+ .stream(in, in.available(), -1)
+ .contentType(file.getContentType())
+ .build()
+ );
+ } catch (Exception e) {
+ throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父");
+ }
+ MinioResult minioResult = new MinioResult();
+ minioResult.setBucketFileName(bucketFilePath);
+ // 杩斿洖姘镐箙棰勮鍦板潃
+ if (isPreviewExpiry) {
+ String previewUrl = getPreviewUrl(bucketFilePath, bucketName, isPreviewExpiry);
+ minioResult.setPreviewExpiry(previewUrl);
+ }
+ minioResult.setOriginalName(originalFileName);
+ bucketFileNames.add(minioResult);
+ }
+ return bucketFileNames;
+ }
+
+ /**
+ * 鏂囦欢涓嬭浇
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param bucketFileName 妗朵腑鏂囦欢鍚嶇О
+ * @param originalFileName 鍘熷鏂囦欢鍚嶇О
+ * @param response response瀵硅薄
+ */
+ public void download(String bucketName, String bucketFileName, String originalFileName, HttpServletResponse response) {
+ GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(bucketFileName).build();
+ try (GetObjectResponse objResponse = minioClient.getObject(objectArgs)) {
+ byte[] buf = new byte[1024];
+ int len;
+ try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
+ while ((len = objResponse.read(buf)) != -1) {
+ os.write(buf, 0, len);
+ }
+ os.flush();
+ byte[] bytes = os.toByteArray();
+ response.setCharacterEncoding("utf-8");
+ //璁剧疆寮哄埗涓嬭浇涓嶆墦寮�
+ response.setContentType("application/force-download");
+ // 璁剧疆闄勪欢鍚嶇О缂栫爜
+ originalFileName = new String(originalFileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1);
+ // 璁剧疆闄勪欢鍚嶇О
+ response.addHeader("Content-Disposition", "attachment;fileName=" + originalFileName);
+ // 鍐欏叆鏂囦欢
+ try (ServletOutputStream stream = response.getOutputStream()) {
+ stream.write(bytes);
+ stream.flush();
+ }
+ }
+ } catch (Exception e) {
+ throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父");
+ }
+ }
+
+ /**
+ * 鑾峰彇宸蹭笂浼犲璞$殑鏂囦欢娴侊紙鍚庣鍥犱负涓氬姟闇�瑕佽幏鍙栨枃浠舵祦鍙互璋冪敤璇ユ柟娉曪級
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param bucketFileName 妗朵腑鏂囦欢鍚嶇О
+ * @return 鏂囦欢娴�
+ */
+ public InputStream getFileStream(String bucketName, String bucketFileName) throws Exception {
+ GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName).object(bucketFileName).build();
+ return minioClient.getObject(objectArgs);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鏂囦欢瀵硅薄缁撴灉
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param bucketFileName 妗朵腑鏂囦欢鍚嶇О
+ * @return 鍒犻櫎缁撴灉
+ */
+ public DeleteError removeObjectsResult(String bucketName, String bucketFileName) {
+ List<DeleteError> results = removeObjectsResult(bucketName, Collections.singletonList(bucketFileName));
+ return !results.isEmpty() ? results.get(0) : null;
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鏂囦欢瀵硅薄缁撴灉
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param bucketFileNames 妗朵腑鏂囦欢鍚嶇О闆嗗悎
+ * @return 鍒犻櫎缁撴灉
+ */
+ public List<DeleteError> removeObjectsResult(String bucketName, List<String> bucketFileNames) {
+ Iterable<Result<DeleteError>> results = removeObjects(bucketName, bucketFileNames);
+ List<DeleteError> res = new ArrayList<>();
+ for (Result<DeleteError> result : results) {
+ try {
+ res.add(result.get());
+ } catch (Exception e) {
+ throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父");
+ }
+ }
+ return res;
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鏂囦欢瀵硅薄
+ *
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param bucketFileNames 妗朵腑鏂囦欢鍚嶇О闆嗗悎
+ */
+ private Iterable<Result<DeleteError>> removeObjects(String bucketName, List<String> bucketFileNames) {
+ List<DeleteObject> dos = bucketFileNames.stream().map(DeleteObject::new).collect(Collectors.toList());
+ return minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(dos).build());
+ }
+
+ /**
+ * 鏌ヨ棰勮url
+ * @param bucketFileName minio鏂囦欢鍚嶇О
+ * @param bucketName 瀛樺偍妗跺悕绉�
+ * @param isPreviewExpiry 鏄惁闇�瑕佽繃鏈熸椂闂� 榛樿24灏忔椂
+ * @return
+ */
+ public String getPreviewUrl(String bucketFileName, String bucketName, Boolean isPreviewExpiry) {
+ if (StringUtils.isNotBlank(bucketFileName)) {
+ try {
+ minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(bucketFileName).build());
+ // 涓篺alse鍙敓鎴�24灏忔椂鏈夋晥鏃堕暱鐨剈rl閾炬帴锛屽彲浠ヨ闂鏂囦欢
+ if (isPreviewExpiry){
+ return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(bucketFileName).build());
+ }else {
+ return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(bucketFileName).expiry(previewExpiry, TimeUnit.HOURS).build());
+ }
+ } catch (Exception e) {
+ throw new UtilException("MinioUtils锛氫笂浼犳枃浠跺伐鍏风被寮傚父");
+ }
+ }
+ return null;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java
new file mode 100644
index 0000000..f52e83e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/EscapeUtil.java
@@ -0,0 +1,167 @@
+package com.ruoyi.common.utils.html;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 杞箟鍜屽弽杞箟宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class EscapeUtil
+{
+ public static final String RE_HTML_MARK = "(<[^<]*?>)|(<[\\s]*?/[^<]*?>)|(<[^<]*?/[\\s]*?>)";
+
+ private static final char[][] TEXT = new char[64][];
+
+ static
+ {
+ for (int i = 0; i < 64; i++)
+ {
+ TEXT[i] = new char[] { (char) i };
+ }
+
+ // special HTML characters
+ TEXT['\''] = "'".toCharArray(); // 鍗曞紩鍙�
+ TEXT['"'] = """.toCharArray(); // 鍙屽紩鍙�
+ TEXT['&'] = "&".toCharArray(); // &绗�
+ TEXT['<'] = "<".toCharArray(); // 灏忎簬鍙�
+ TEXT['>'] = ">".toCharArray(); // 澶т簬鍙�
+ }
+
+ /**
+ * 杞箟鏂囨湰涓殑HTML瀛楃涓哄畨鍏ㄧ殑瀛楃
+ *
+ * @param text 琚浆涔夌殑鏂囨湰
+ * @return 杞箟鍚庣殑鏂囨湰
+ */
+ public static String escape(String text)
+ {
+ return encode(text);
+ }
+
+ /**
+ * 杩樺師琚浆涔夌殑HTML鐗规畩瀛楃
+ *
+ * @param content 鍖呭惈杞箟绗︾殑HTML鍐呭
+ * @return 杞崲鍚庣殑瀛楃涓�
+ */
+ public static String unescape(String content)
+ {
+ return decode(content);
+ }
+
+ /**
+ * 娓呴櫎鎵�鏈塇TML鏍囩锛屼絾鏄笉鍒犻櫎鏍囩鍐呯殑鍐呭
+ *
+ * @param content 鏂囨湰
+ * @return 娓呴櫎鏍囩鍚庣殑鏂囨湰
+ */
+ public static String clean(String content)
+ {
+ return new HTMLFilter().filter(content);
+ }
+
+ /**
+ * Escape缂栫爜
+ *
+ * @param text 琚紪鐮佺殑鏂囨湰
+ * @return 缂栫爜鍚庣殑瀛楃
+ */
+ private static String encode(String text)
+ {
+ if (StringUtils.isEmpty(text))
+ {
+ return StringUtils.EMPTY;
+ }
+
+ final StringBuilder tmp = new StringBuilder(text.length() * 6);
+ char c;
+ for (int i = 0; i < text.length(); i++)
+ {
+ c = text.charAt(i);
+ if (c < 256)
+ {
+ tmp.append("%");
+ if (c < 16)
+ {
+ tmp.append("0");
+ }
+ tmp.append(Integer.toString(c, 16));
+ }
+ else
+ {
+ tmp.append("%u");
+ if (c <= 0xfff)
+ {
+ // issue#I49JU8@Gitee
+ tmp.append("0");
+ }
+ tmp.append(Integer.toString(c, 16));
+ }
+ }
+ return tmp.toString();
+ }
+
+ /**
+ * Escape瑙g爜
+ *
+ * @param content 琚浆涔夌殑鍐呭
+ * @return 瑙g爜鍚庣殑瀛楃涓�
+ */
+ public static String decode(String content)
+ {
+ if (StringUtils.isEmpty(content))
+ {
+ return content;
+ }
+
+ StringBuilder tmp = new StringBuilder(content.length());
+ int lastPos = 0, pos = 0;
+ char ch;
+ while (lastPos < content.length())
+ {
+ pos = content.indexOf("%", lastPos);
+ if (pos == lastPos)
+ {
+ if (content.charAt(pos + 1) == 'u')
+ {
+ ch = (char) Integer.parseInt(content.substring(pos + 2, pos + 6), 16);
+ tmp.append(ch);
+ lastPos = pos + 6;
+ }
+ else
+ {
+ ch = (char) Integer.parseInt(content.substring(pos + 1, pos + 3), 16);
+ tmp.append(ch);
+ lastPos = pos + 3;
+ }
+ }
+ else
+ {
+ if (pos == -1)
+ {
+ tmp.append(content.substring(lastPos));
+ lastPos = content.length();
+ }
+ else
+ {
+ tmp.append(content.substring(lastPos, pos));
+ lastPos = pos;
+ }
+ }
+ }
+ return tmp.toString();
+ }
+
+ public static void main(String[] args)
+ {
+ String html = "<script>alert(1);</script>";
+ String escape = EscapeUtil.escape(html);
+ // String html = "<scr<script>ipt>alert(\"XSS\")</scr<script>ipt>";
+ // String html = "<123";
+ // String html = "123>";
+ System.out.println("clean: " + EscapeUtil.clean(html));
+ System.out.println("escape: " + escape);
+ System.out.println("unescape: " + EscapeUtil.unescape(escape));
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java
new file mode 100644
index 0000000..ebff3fd
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/html/HTMLFilter.java
@@ -0,0 +1,570 @@
+package com.ruoyi.common.utils.html;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * HTML杩囨护鍣紝鐢ㄤ簬鍘婚櫎XSS婕忔礊闅愭偅銆�
+ *
+ * @author ruoyi
+ */
+public final class HTMLFilter
+{
+ /**
+ * regex flag union representing /si modifiers in php
+ **/
+ private static final int REGEX_FLAGS_SI = Pattern.CASE_INSENSITIVE | Pattern.DOTALL;
+ private static final Pattern P_COMMENTS = Pattern.compile("<!--(.*?)-->", Pattern.DOTALL);
+ private static final Pattern P_COMMENT = Pattern.compile("^!--(.*)--$", REGEX_FLAGS_SI);
+ private static final Pattern P_TAGS = Pattern.compile("<(.*?)>", Pattern.DOTALL);
+ private static final Pattern P_END_TAG = Pattern.compile("^/([a-z0-9]+)", REGEX_FLAGS_SI);
+ private static final Pattern P_START_TAG = Pattern.compile("^([a-z0-9]+)(.*?)(/?)$", REGEX_FLAGS_SI);
+ private static final Pattern P_QUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)=([\"'])(.*?)\\2", REGEX_FLAGS_SI);
+ private static final Pattern P_UNQUOTED_ATTRIBUTES = Pattern.compile("([a-z0-9]+)(=)([^\"\\s']+)", REGEX_FLAGS_SI);
+ private static final Pattern P_PROTOCOL = Pattern.compile("^([^:]+):", REGEX_FLAGS_SI);
+ private static final Pattern P_ENTITY = Pattern.compile("&#(\\d+);?");
+ private static final Pattern P_ENTITY_UNICODE = Pattern.compile("&#x([0-9a-f]+);?");
+ private static final Pattern P_ENCODE = Pattern.compile("%([0-9a-f]{2});?");
+ private static final Pattern P_VALID_ENTITIES = Pattern.compile("&([^&;]*)(?=(;|&|$))");
+ private static final Pattern P_VALID_QUOTES = Pattern.compile("(>|^)([^<]+?)(<|$)", Pattern.DOTALL);
+ private static final Pattern P_END_ARROW = Pattern.compile("^>");
+ private static final Pattern P_BODY_TO_END = Pattern.compile("<([^>]*?)(?=<|$)");
+ private static final Pattern P_XML_CONTENT = Pattern.compile("(^|>)([^<]*?)(?=>)");
+ private static final Pattern P_STRAY_LEFT_ARROW = Pattern.compile("<([^>]*?)(?=<|$)");
+ private static final Pattern P_STRAY_RIGHT_ARROW = Pattern.compile("(^|>)([^<]*?)(?=>)");
+ private static final Pattern P_AMP = Pattern.compile("&");
+ private static final Pattern P_QUOTE = Pattern.compile("\"");
+ private static final Pattern P_LEFT_ARROW = Pattern.compile("<");
+ private static final Pattern P_RIGHT_ARROW = Pattern.compile(">");
+ private static final Pattern P_BOTH_ARROWS = Pattern.compile("<>");
+
+ // @xxx could grow large... maybe use sesat's ReferenceMap
+ private static final ConcurrentMap<String, Pattern> P_REMOVE_PAIR_BLANKS = new ConcurrentHashMap<>();
+ private static final ConcurrentMap<String, Pattern> P_REMOVE_SELF_BLANKS = new ConcurrentHashMap<>();
+
+ /**
+ * set of allowed html elements, along with allowed attributes for each element
+ **/
+ private final Map<String, List<String>> vAllowed;
+ /**
+ * counts of open tags for each (allowable) html element
+ **/
+ private final Map<String, Integer> vTagCounts = new HashMap<>();
+
+ /**
+ * html elements which must always be self-closing (e.g. "<img />")
+ **/
+ private final String[] vSelfClosingTags;
+ /**
+ * html elements which must always have separate opening and closing tags (e.g. "<b></b>")
+ **/
+ private final String[] vNeedClosingTags;
+ /**
+ * set of disallowed html elements
+ **/
+ private final String[] vDisallowed;
+ /**
+ * attributes which should be checked for valid protocols
+ **/
+ private final String[] vProtocolAtts;
+ /**
+ * allowed protocols
+ **/
+ private final String[] vAllowedProtocols;
+ /**
+ * tags which should be removed if they contain no content (e.g. "<b></b>" or "<b />")
+ **/
+ private final String[] vRemoveBlanks;
+ /**
+ * entities allowed within html markup
+ **/
+ private final String[] vAllowedEntities;
+ /**
+ * flag determining whether comments are allowed in input String.
+ */
+ private final boolean stripComment;
+ private final boolean encodeQuotes;
+ /**
+ * flag determining whether to try to make tags when presented with "unbalanced" angle brackets (e.g. "<b text </b>"
+ * becomes "<b> text </b>"). If set to false, unbalanced angle brackets will be html escaped.
+ */
+ private final boolean alwaysMakeTags;
+
+ /**
+ * Default constructor.
+ */
+ public HTMLFilter()
+ {
+ vAllowed = new HashMap<>();
+
+ final ArrayList<String> a_atts = new ArrayList<>();
+ a_atts.add("href");
+ a_atts.add("target");
+ vAllowed.put("a", a_atts);
+
+ final ArrayList<String> img_atts = new ArrayList<>();
+ img_atts.add("src");
+ img_atts.add("width");
+ img_atts.add("height");
+ img_atts.add("alt");
+ vAllowed.put("img", img_atts);
+
+ final ArrayList<String> no_atts = new ArrayList<>();
+ vAllowed.put("b", no_atts);
+ vAllowed.put("strong", no_atts);
+ vAllowed.put("i", no_atts);
+ vAllowed.put("em", no_atts);
+
+ vSelfClosingTags = new String[] { "img" };
+ vNeedClosingTags = new String[] { "a", "b", "strong", "i", "em" };
+ vDisallowed = new String[] {};
+ vAllowedProtocols = new String[] { "http", "mailto", "https" }; // no ftp.
+ vProtocolAtts = new String[] { "src", "href" };
+ vRemoveBlanks = new String[] { "a", "b", "strong", "i", "em" };
+ vAllowedEntities = new String[] { "amp", "gt", "lt", "quot" };
+ stripComment = true;
+ encodeQuotes = true;
+ alwaysMakeTags = false;
+ }
+
+ /**
+ * Map-parameter configurable constructor.
+ *
+ * @param conf map containing configuration. keys match field names.
+ */
+ @SuppressWarnings("unchecked")
+ public HTMLFilter(final Map<String, Object> conf)
+ {
+
+ assert conf.containsKey("vAllowed") : "configuration requires vAllowed";
+ assert conf.containsKey("vSelfClosingTags") : "configuration requires vSelfClosingTags";
+ assert conf.containsKey("vNeedClosingTags") : "configuration requires vNeedClosingTags";
+ assert conf.containsKey("vDisallowed") : "configuration requires vDisallowed";
+ assert conf.containsKey("vAllowedProtocols") : "configuration requires vAllowedProtocols";
+ assert conf.containsKey("vProtocolAtts") : "configuration requires vProtocolAtts";
+ assert conf.containsKey("vRemoveBlanks") : "configuration requires vRemoveBlanks";
+ assert conf.containsKey("vAllowedEntities") : "configuration requires vAllowedEntities";
+
+ vAllowed = Collections.unmodifiableMap((HashMap<String, List<String>>) conf.get("vAllowed"));
+ vSelfClosingTags = (String[]) conf.get("vSelfClosingTags");
+ vNeedClosingTags = (String[]) conf.get("vNeedClosingTags");
+ vDisallowed = (String[]) conf.get("vDisallowed");
+ vAllowedProtocols = (String[]) conf.get("vAllowedProtocols");
+ vProtocolAtts = (String[]) conf.get("vProtocolAtts");
+ vRemoveBlanks = (String[]) conf.get("vRemoveBlanks");
+ vAllowedEntities = (String[]) conf.get("vAllowedEntities");
+ stripComment = conf.containsKey("stripComment") ? (Boolean) conf.get("stripComment") : true;
+ encodeQuotes = conf.containsKey("encodeQuotes") ? (Boolean) conf.get("encodeQuotes") : true;
+ alwaysMakeTags = conf.containsKey("alwaysMakeTags") ? (Boolean) conf.get("alwaysMakeTags") : true;
+ }
+
+ private void reset()
+ {
+ vTagCounts.clear();
+ }
+
+ // ---------------------------------------------------------------
+ // my versions of some PHP library functions
+ public static String chr(final int decimal)
+ {
+ return String.valueOf((char) decimal);
+ }
+
+ public static String htmlSpecialChars(final String s)
+ {
+ String result = s;
+ result = regexReplace(P_AMP, "&", result);
+ result = regexReplace(P_QUOTE, """, result);
+ result = regexReplace(P_LEFT_ARROW, "<", result);
+ result = regexReplace(P_RIGHT_ARROW, ">", result);
+ return result;
+ }
+
+ // ---------------------------------------------------------------
+
+ /**
+ * given a user submitted input String, filter out any invalid or restricted html.
+ *
+ * @param input text (i.e. submitted by a user) than may contain html
+ * @return "clean" version of input, with only valid, whitelisted html elements allowed
+ */
+ public String filter(final String input)
+ {
+ reset();
+ String s = input;
+
+ s = escapeComments(s);
+
+ s = balanceHTML(s);
+
+ s = checkTags(s);
+
+ s = processRemoveBlanks(s);
+
+ // s = validateEntities(s);
+
+ return s;
+ }
+
+ public boolean isAlwaysMakeTags()
+ {
+ return alwaysMakeTags;
+ }
+
+ public boolean isStripComments()
+ {
+ return stripComment;
+ }
+
+ private String escapeComments(final String s)
+ {
+ final Matcher m = P_COMMENTS.matcher(s);
+ final StringBuffer buf = new StringBuffer();
+ if (m.find())
+ {
+ final String match = m.group(1); // (.*?)
+ m.appendReplacement(buf, Matcher.quoteReplacement("<!--" + htmlSpecialChars(match) + "-->"));
+ }
+ m.appendTail(buf);
+
+ return buf.toString();
+ }
+
+ private String balanceHTML(String s)
+ {
+ if (alwaysMakeTags)
+ {
+ //
+ // try and form html
+ //
+ s = regexReplace(P_END_ARROW, "", s);
+ // 涓嶈拷鍔犵粨鏉熸爣绛�
+ s = regexReplace(P_BODY_TO_END, "<$1>", s);
+ s = regexReplace(P_XML_CONTENT, "$1<$2", s);
+
+ }
+ else
+ {
+ //
+ // escape stray brackets
+ //
+ s = regexReplace(P_STRAY_LEFT_ARROW, "<$1", s);
+ s = regexReplace(P_STRAY_RIGHT_ARROW, "$1$2><", s);
+
+ //
+ // the last regexp causes '<>' entities to appear
+ // (we need to do a lookahead assertion so that the last bracket can
+ // be used in the next pass of the regexp)
+ //
+ s = regexReplace(P_BOTH_ARROWS, "", s);
+ }
+
+ return s;
+ }
+
+ private String checkTags(String s)
+ {
+ Matcher m = P_TAGS.matcher(s);
+
+ final StringBuffer buf = new StringBuffer();
+ while (m.find())
+ {
+ String replaceStr = m.group(1);
+ replaceStr = processTag(replaceStr);
+ m.appendReplacement(buf, Matcher.quoteReplacement(replaceStr));
+ }
+ m.appendTail(buf);
+
+ // these get tallied in processTag
+ // (remember to reset before subsequent calls to filter method)
+ final StringBuilder sBuilder = new StringBuilder(buf.toString());
+ for (String key : vTagCounts.keySet())
+ {
+ for (int ii = 0; ii < vTagCounts.get(key); ii++)
+ {
+ sBuilder.append("</").append(key).append(">");
+ }
+ }
+ s = sBuilder.toString();
+
+ return s;
+ }
+
+ private String processRemoveBlanks(final String s)
+ {
+ String result = s;
+ for (String tag : vRemoveBlanks)
+ {
+ if (!P_REMOVE_PAIR_BLANKS.containsKey(tag))
+ {
+ P_REMOVE_PAIR_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?></" + tag + ">"));
+ }
+ result = regexReplace(P_REMOVE_PAIR_BLANKS.get(tag), "", result);
+ if (!P_REMOVE_SELF_BLANKS.containsKey(tag))
+ {
+ P_REMOVE_SELF_BLANKS.putIfAbsent(tag, Pattern.compile("<" + tag + "(\\s[^>]*)?/>"));
+ }
+ result = regexReplace(P_REMOVE_SELF_BLANKS.get(tag), "", result);
+ }
+
+ return result;
+ }
+
+ private static String regexReplace(final Pattern regex_pattern, final String replacement, final String s)
+ {
+ Matcher m = regex_pattern.matcher(s);
+ return m.replaceAll(replacement);
+ }
+
+ private String processTag(final String s)
+ {
+ // ending tags
+ Matcher m = P_END_TAG.matcher(s);
+ if (m.find())
+ {
+ final String name = m.group(1).toLowerCase();
+ if (allowed(name))
+ {
+ if (!inArray(name, vSelfClosingTags))
+ {
+ if (vTagCounts.containsKey(name))
+ {
+ vTagCounts.put(name, vTagCounts.get(name) - 1);
+ return "</" + name + ">";
+ }
+ }
+ }
+ }
+
+ // starting tags
+ m = P_START_TAG.matcher(s);
+ if (m.find())
+ {
+ final String name = m.group(1).toLowerCase();
+ final String body = m.group(2);
+ String ending = m.group(3);
+
+ // debug( "in a starting tag, name='" + name + "'; body='" + body + "'; ending='" + ending + "'" );
+ if (allowed(name))
+ {
+ final StringBuilder params = new StringBuilder();
+
+ final Matcher m2 = P_QUOTED_ATTRIBUTES.matcher(body);
+ final Matcher m3 = P_UNQUOTED_ATTRIBUTES.matcher(body);
+ final List<String> paramNames = new ArrayList<>();
+ final List<String> paramValues = new ArrayList<>();
+ while (m2.find())
+ {
+ paramNames.add(m2.group(1)); // ([a-z0-9]+)
+ paramValues.add(m2.group(3)); // (.*?)
+ }
+ while (m3.find())
+ {
+ paramNames.add(m3.group(1)); // ([a-z0-9]+)
+ paramValues.add(m3.group(3)); // ([^\"\\s']+)
+ }
+
+ String paramName, paramValue;
+ for (int ii = 0; ii < paramNames.size(); ii++)
+ {
+ paramName = paramNames.get(ii).toLowerCase();
+ paramValue = paramValues.get(ii);
+
+ // debug( "paramName='" + paramName + "'" );
+ // debug( "paramValue='" + paramValue + "'" );
+ // debug( "allowed? " + vAllowed.get( name ).contains( paramName ) );
+
+ if (allowedAttribute(name, paramName))
+ {
+ if (inArray(paramName, vProtocolAtts))
+ {
+ paramValue = processParamProtocol(paramValue);
+ }
+ params.append(' ').append(paramName).append("=\\\"").append(paramValue).append("\\\"");
+ }
+ }
+
+ if (inArray(name, vSelfClosingTags))
+ {
+ ending = " /";
+ }
+
+ if (inArray(name, vNeedClosingTags))
+ {
+ ending = "";
+ }
+
+ if (ending == null || ending.length() < 1)
+ {
+ if (vTagCounts.containsKey(name))
+ {
+ vTagCounts.put(name, vTagCounts.get(name) + 1);
+ }
+ else
+ {
+ vTagCounts.put(name, 1);
+ }
+ }
+ else
+ {
+ ending = " /";
+ }
+ return "<" + name + params + ending + ">";
+ }
+ else
+ {
+ return "";
+ }
+ }
+
+ // comments
+ m = P_COMMENT.matcher(s);
+ if (!stripComment && m.find())
+ {
+ return "<" + m.group() + ">";
+ }
+
+ return "";
+ }
+
+ private String processParamProtocol(String s)
+ {
+ s = decodeEntities(s);
+ final Matcher m = P_PROTOCOL.matcher(s);
+ if (m.find())
+ {
+ final String protocol = m.group(1);
+ if (!inArray(protocol, vAllowedProtocols))
+ {
+ // bad protocol, turn into local anchor link instead
+ s = "#" + s.substring(protocol.length() + 1);
+ if (s.startsWith("#//"))
+ {
+ s = "#" + s.substring(3);
+ }
+ }
+ }
+
+ return s;
+ }
+
+ private String decodeEntities(String s)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ Matcher m = P_ENTITY.matcher(s);
+ while (m.find())
+ {
+ final String match = m.group(1);
+ final int decimal = Integer.decode(match).intValue();
+ m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+ }
+ m.appendTail(buf);
+ s = buf.toString();
+
+ buf = new StringBuffer();
+ m = P_ENTITY_UNICODE.matcher(s);
+ while (m.find())
+ {
+ final String match = m.group(1);
+ final int decimal = Integer.valueOf(match, 16).intValue();
+ m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+ }
+ m.appendTail(buf);
+ s = buf.toString();
+
+ buf = new StringBuffer();
+ m = P_ENCODE.matcher(s);
+ while (m.find())
+ {
+ final String match = m.group(1);
+ final int decimal = Integer.valueOf(match, 16).intValue();
+ m.appendReplacement(buf, Matcher.quoteReplacement(chr(decimal)));
+ }
+ m.appendTail(buf);
+ s = buf.toString();
+
+ s = validateEntities(s);
+ return s;
+ }
+
+ private String validateEntities(final String s)
+ {
+ StringBuffer buf = new StringBuffer();
+
+ // validate entities throughout the string
+ Matcher m = P_VALID_ENTITIES.matcher(s);
+ while (m.find())
+ {
+ final String one = m.group(1); // ([^&;]*)
+ final String two = m.group(2); // (?=(;|&|$))
+ m.appendReplacement(buf, Matcher.quoteReplacement(checkEntity(one, two)));
+ }
+ m.appendTail(buf);
+
+ return encodeQuotes(buf.toString());
+ }
+
+ private String encodeQuotes(final String s)
+ {
+ if (encodeQuotes)
+ {
+ StringBuffer buf = new StringBuffer();
+ Matcher m = P_VALID_QUOTES.matcher(s);
+ while (m.find())
+ {
+ final String one = m.group(1); // (>|^)
+ final String two = m.group(2); // ([^<]+?)
+ final String three = m.group(3); // (<|$)
+ // 涓嶆浛鎹㈠弻寮曞彿涓�"锛岄槻姝son鏍煎紡鏃犳晥 regexReplace(P_QUOTE, """, two)
+ m.appendReplacement(buf, Matcher.quoteReplacement(one + two + three));
+ }
+ m.appendTail(buf);
+ return buf.toString();
+ }
+ else
+ {
+ return s;
+ }
+ }
+
+ private String checkEntity(final String preamble, final String term)
+ {
+
+ return ";".equals(term) && isValidEntity(preamble) ? '&' + preamble : "&" + preamble;
+ }
+
+ private boolean isValidEntity(final String entity)
+ {
+ return inArray(entity, vAllowedEntities);
+ }
+
+ private static boolean inArray(final String s, final String[] array)
+ {
+ for (String item : array)
+ {
+ if (item != null && item.equals(s))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private boolean allowed(final String name)
+ {
+ return (vAllowed.isEmpty() || vAllowed.containsKey(name)) && !inArray(name, vDisallowed);
+ }
+
+ private boolean allowedAttribute(final String name, final String paramName)
+ {
+ return allowed(name) && (vAllowed.isEmpty() || vAllowed.get(name).contains(paramName));
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
new file mode 100644
index 0000000..589d123
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpHelper.java
@@ -0,0 +1,55 @@
+package com.ruoyi.common.utils.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
+import javax.servlet.ServletRequest;
+import org.apache.commons.lang3.exception.ExceptionUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 閫氱敤http宸ュ叿灏佽
+ *
+ * @author ruoyi
+ */
+public class HttpHelper
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(HttpHelper.class);
+
+ public static String getBodyString(ServletRequest request)
+ {
+ StringBuilder sb = new StringBuilder();
+ BufferedReader reader = null;
+ try (InputStream inputStream = request.getInputStream())
+ {
+ reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8));
+ String line = "";
+ while ((line = reader.readLine()) != null)
+ {
+ sb.append(line);
+ }
+ }
+ catch (IOException e)
+ {
+ LOGGER.warn("getBodyString鍑虹幇闂锛�");
+ }
+ finally
+ {
+ if (reader != null)
+ {
+ try
+ {
+ reader.close();
+ }
+ catch (IOException e)
+ {
+ LOGGER.error(ExceptionUtils.getMessage(e));
+ }
+ }
+ }
+ return sb.toString();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
new file mode 100644
index 0000000..ef5eb28
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/http/HttpUtils.java
@@ -0,0 +1,274 @@
+package com.ruoyi.common.utils.http;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintWriter;
+import java.net.ConnectException;
+import java.net.SocketTimeoutException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.nio.charset.StandardCharsets;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 閫氱敤http鍙戦�佹柟娉�
+ *
+ * @author ruoyi
+ */
+public class HttpUtils
+{
+ private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
+
+ /**
+ * 鍚戞寚瀹� URL 鍙戦�丟ET鏂规硶鐨勮姹�
+ *
+ * @param url 鍙戦�佽姹傜殑 URL
+ * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+ */
+ public static String sendGet(String url)
+ {
+ return sendGet(url, StringUtils.EMPTY);
+ }
+
+ /**
+ * 鍚戞寚瀹� URL 鍙戦�丟ET鏂规硶鐨勮姹�
+ *
+ * @param url 鍙戦�佽姹傜殑 URL
+ * @param param 璇锋眰鍙傛暟锛岃姹傚弬鏁板簲璇ユ槸 name1=value1&name2=value2 鐨勫舰寮忋��
+ * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+ */
+ public static String sendGet(String url, String param)
+ {
+ return sendGet(url, param, Constants.UTF8);
+ }
+
+ /**
+ * 鍚戞寚瀹� URL 鍙戦�丟ET鏂规硶鐨勮姹�
+ *
+ * @param url 鍙戦�佽姹傜殑 URL
+ * @param param 璇锋眰鍙傛暟锛岃姹傚弬鏁板簲璇ユ槸 name1=value1&name2=value2 鐨勫舰寮忋��
+ * @param contentType 缂栫爜绫诲瀷
+ * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+ */
+ public static String sendGet(String url, String param, String contentType)
+ {
+ StringBuilder result = new StringBuilder();
+ BufferedReader in = null;
+ try
+ {
+ String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
+ log.info("sendGet - {}", urlNameString);
+ URL realUrl = new URL(urlNameString);
+ URLConnection connection = realUrl.openConnection();
+ connection.setRequestProperty("accept", "*/*");
+ connection.setRequestProperty("connection", "Keep-Alive");
+ connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
+ connection.connect();
+ in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
+ String line;
+ while ((line = in.readLine()) != null)
+ {
+ result.append(line);
+ }
+ log.info("recv - {}", result);
+ }
+ catch (ConnectException e)
+ {
+ log.error("璋冪敤HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
+ }
+ catch (SocketTimeoutException e)
+ {
+ log.error("璋冪敤HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
+ }
+ catch (IOException e)
+ {
+ log.error("璋冪敤HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
+ }
+ catch (Exception e)
+ {
+ log.error("璋冪敤HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
+ }
+ finally
+ {
+ try
+ {
+ if (in != null)
+ {
+ in.close();
+ }
+ }
+ catch (Exception ex)
+ {
+ log.error("璋冪敤in.close Exception, url=" + url + ",param=" + param, ex);
+ }
+ }
+ return result.toString();
+ }
+
+ /**
+ * 鍚戞寚瀹� URL 鍙戦�丳OST鏂规硶鐨勮姹�
+ *
+ * @param url 鍙戦�佽姹傜殑 URL
+ * @param param 璇锋眰鍙傛暟锛岃姹傚弬鏁板簲璇ユ槸 name1=value1&name2=value2 鐨勫舰寮忋��
+ * @return 鎵�浠h〃杩滅▼璧勬簮鐨勫搷搴旂粨鏋�
+ */
+ public static String sendPost(String url, String param)
+ {
+ PrintWriter out = null;
+ BufferedReader in = null;
+ StringBuilder result = new StringBuilder();
+ try
+ {
+ log.info("sendPost - {}", url);
+ URL realUrl = new URL(url);
+ URLConnection conn = realUrl.openConnection();
+ conn.setRequestProperty("accept", "*/*");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
+ conn.setRequestProperty("Accept-Charset", "utf-8");
+ conn.setRequestProperty("contentType", "utf-8");
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+ out = new PrintWriter(conn.getOutputStream());
+ out.print(param);
+ out.flush();
+ in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
+ String line;
+ while ((line = in.readLine()) != null)
+ {
+ result.append(line);
+ }
+ log.info("recv - {}", result);
+ }
+ catch (ConnectException e)
+ {
+ log.error("璋冪敤HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
+ }
+ catch (SocketTimeoutException e)
+ {
+ log.error("璋冪敤HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+ }
+ catch (IOException e)
+ {
+ log.error("璋冪敤HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
+ }
+ catch (Exception e)
+ {
+ log.error("璋冪敤HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
+ }
+ finally
+ {
+ try
+ {
+ if (out != null)
+ {
+ out.close();
+ }
+ if (in != null)
+ {
+ in.close();
+ }
+ }
+ catch (IOException ex)
+ {
+ log.error("璋冪敤in.close Exception, url=" + url + ",param=" + param, ex);
+ }
+ }
+ return result.toString();
+ }
+
+ public static String sendSSLPost(String url, String param)
+ {
+ StringBuilder result = new StringBuilder();
+ String urlNameString = url + "?" + param;
+ try
+ {
+ log.info("sendSSLPost - {}", urlNameString);
+ SSLContext sc = SSLContext.getInstance("SSL");
+ sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
+ URL console = new URL(urlNameString);
+ HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
+ conn.setRequestProperty("accept", "*/*");
+ conn.setRequestProperty("connection", "Keep-Alive");
+ conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
+ conn.setRequestProperty("Accept-Charset", "utf-8");
+ conn.setRequestProperty("contentType", "utf-8");
+ conn.setDoOutput(true);
+ conn.setDoInput(true);
+
+ conn.setSSLSocketFactory(sc.getSocketFactory());
+ conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
+ conn.connect();
+ InputStream is = conn.getInputStream();
+ BufferedReader br = new BufferedReader(new InputStreamReader(is));
+ String ret = "";
+ while ((ret = br.readLine()) != null)
+ {
+ if (ret != null && !"".equals(ret.trim()))
+ {
+ result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
+ }
+ }
+ log.info("recv - {}", result);
+ conn.disconnect();
+ br.close();
+ }
+ catch (ConnectException e)
+ {
+ log.error("璋冪敤HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
+ }
+ catch (SocketTimeoutException e)
+ {
+ log.error("璋冪敤HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
+ }
+ catch (IOException e)
+ {
+ log.error("璋冪敤HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
+ }
+ catch (Exception e)
+ {
+ log.error("璋冪敤HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
+ }
+ return result.toString();
+ }
+
+ private static class TrustAnyTrustManager implements X509TrustManager
+ {
+ @Override
+ public void checkClientTrusted(X509Certificate[] chain, String authType)
+ {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] chain, String authType)
+ {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers()
+ {
+ return new X509Certificate[] {};
+ }
+ }
+
+ private static class TrustAnyHostnameVerifier implements HostnameVerifier
+ {
+ @Override
+ public boolean verify(String hostname, SSLSession session)
+ {
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
new file mode 100644
index 0000000..edfe419
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/AddressUtils.java
@@ -0,0 +1,56 @@
+package com.ruoyi.common.utils.ip;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.http.HttpUtils;
+
+/**
+ * 鑾峰彇鍦板潃绫�
+ *
+ * @author ruoyi
+ */
+public class AddressUtils
+{
+ private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
+
+ // IP鍦板潃鏌ヨ
+ public static final String IP_URL = "http://whois.pconline.com.cn/ipJson.jsp";
+
+ // 鏈煡鍦板潃
+ public static final String UNKNOWN = "XX XX";
+
+ public static String getRealAddressByIP(String ip)
+ {
+ // 鍐呯綉涓嶆煡璇�
+ if (IpUtils.internalIp(ip))
+ {
+ return "鍐呯綉IP";
+ }
+ if (RuoYiConfig.isAddressEnabled())
+ {
+ try
+ {
+ String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", Constants.GBK);
+ if (StringUtils.isEmpty(rspStr))
+ {
+ log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
+ return UNKNOWN;
+ }
+ JSONObject obj = JSON.parseObject(rspStr);
+ String region = obj.getString("pro");
+ String city = obj.getString("city");
+ return String.format("%s %s", region, city);
+ }
+ catch (Exception e)
+ {
+ log.error("鑾峰彇鍦扮悊浣嶇疆寮傚父 {}", ip);
+ }
+ }
+ return UNKNOWN;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
new file mode 100644
index 0000000..8e89e30
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/ip/IpUtils.java
@@ -0,0 +1,382 @@
+package com.ruoyi.common.utils.ip;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import javax.servlet.http.HttpServletRequest;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 鑾峰彇IP鏂规硶
+ *
+ * @author ruoyi
+ */
+public class IpUtils
+{
+ public final static String REGX_0_255 = "(25[0-5]|2[0-4]\\d|1\\d{2}|[1-9]\\d|\\d)";
+ // 鍖归厤 ip
+ public final static String REGX_IP = "((" + REGX_0_255 + "\\.){3}" + REGX_0_255 + ")";
+ public final static String REGX_IP_WILDCARD = "(((\\*\\.){3}\\*)|(" + REGX_0_255 + "(\\.\\*){3})|(" + REGX_0_255 + "\\." + REGX_0_255 + ")(\\.\\*){2}" + "|((" + REGX_0_255 + "\\.){3}\\*))";
+ // 鍖归厤缃戞
+ public final static String REGX_IP_SEG = "(" + REGX_IP + "\\-" + REGX_IP + ")";
+
+ /**
+ * 鑾峰彇瀹㈡埛绔疘P
+ *
+ * @return IP鍦板潃
+ */
+ public static String getIpAddr()
+ {
+ return getIpAddr(ServletUtils.getRequest());
+ }
+
+ /**
+ * 鑾峰彇瀹㈡埛绔疘P
+ *
+ * @param request 璇锋眰瀵硅薄
+ * @return IP鍦板潃
+ */
+ public static String getIpAddr(HttpServletRequest request)
+ {
+ if (request == null)
+ {
+ return "unknown";
+ }
+ String ip = request.getHeader("x-forwarded-for");
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+ {
+ ip = request.getHeader("Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+ {
+ ip = request.getHeader("X-Forwarded-For");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+ {
+ ip = request.getHeader("WL-Proxy-Client-IP");
+ }
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+ {
+ ip = request.getHeader("X-Real-IP");
+ }
+
+ if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip))
+ {
+ ip = request.getRemoteAddr();
+ }
+
+ return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
+ }
+
+ /**
+ * 妫�鏌ユ槸鍚︿负鍐呴儴IP鍦板潃
+ *
+ * @param ip IP鍦板潃
+ * @return 缁撴灉
+ */
+ public static boolean internalIp(String ip)
+ {
+ byte[] addr = textToNumericFormatV4(ip);
+ return internalIp(addr) || "127.0.0.1".equals(ip);
+ }
+
+ /**
+ * 妫�鏌ユ槸鍚︿负鍐呴儴IP鍦板潃
+ *
+ * @param addr byte鍦板潃
+ * @return 缁撴灉
+ */
+ private static boolean internalIp(byte[] addr)
+ {
+ if (StringUtils.isNull(addr) || addr.length < 2)
+ {
+ return true;
+ }
+ final byte b0 = addr[0];
+ final byte b1 = addr[1];
+ // 10.x.x.x/8
+ final byte SECTION_1 = 0x0A;
+ // 172.16.x.x/12
+ final byte SECTION_2 = (byte) 0xAC;
+ final byte SECTION_3 = (byte) 0x10;
+ final byte SECTION_4 = (byte) 0x1F;
+ // 192.168.x.x/16
+ final byte SECTION_5 = (byte) 0xC0;
+ final byte SECTION_6 = (byte) 0xA8;
+ switch (b0)
+ {
+ case SECTION_1:
+ return true;
+ case SECTION_2:
+ if (b1 >= SECTION_3 && b1 <= SECTION_4)
+ {
+ return true;
+ }
+ case SECTION_5:
+ switch (b1)
+ {
+ case SECTION_6:
+ return true;
+ }
+ default:
+ return false;
+ }
+ }
+
+ /**
+ * 灏咺Pv4鍦板潃杞崲鎴愬瓧鑺�
+ *
+ * @param text IPv4鍦板潃
+ * @return byte 瀛楄妭
+ */
+ public static byte[] textToNumericFormatV4(String text)
+ {
+ if (text.length() == 0)
+ {
+ return null;
+ }
+
+ byte[] bytes = new byte[4];
+ String[] elements = text.split("\\.", -1);
+ try
+ {
+ long l;
+ int i;
+ switch (elements.length)
+ {
+ case 1:
+ l = Long.parseLong(elements[0]);
+ if ((l < 0L) || (l > 4294967295L))
+ {
+ return null;
+ }
+ bytes[0] = (byte) (int) (l >> 24 & 0xFF);
+ bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
+ bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+ bytes[3] = (byte) (int) (l & 0xFF);
+ break;
+ case 2:
+ l = Integer.parseInt(elements[0]);
+ if ((l < 0L) || (l > 255L))
+ {
+ return null;
+ }
+ bytes[0] = (byte) (int) (l & 0xFF);
+ l = Integer.parseInt(elements[1]);
+ if ((l < 0L) || (l > 16777215L))
+ {
+ return null;
+ }
+ bytes[1] = (byte) (int) (l >> 16 & 0xFF);
+ bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
+ bytes[3] = (byte) (int) (l & 0xFF);
+ break;
+ case 3:
+ for (i = 0; i < 2; ++i)
+ {
+ l = Integer.parseInt(elements[i]);
+ if ((l < 0L) || (l > 255L))
+ {
+ return null;
+ }
+ bytes[i] = (byte) (int) (l & 0xFF);
+ }
+ l = Integer.parseInt(elements[2]);
+ if ((l < 0L) || (l > 65535L))
+ {
+ return null;
+ }
+ bytes[2] = (byte) (int) (l >> 8 & 0xFF);
+ bytes[3] = (byte) (int) (l & 0xFF);
+ break;
+ case 4:
+ for (i = 0; i < 4; ++i)
+ {
+ l = Integer.parseInt(elements[i]);
+ if ((l < 0L) || (l > 255L))
+ {
+ return null;
+ }
+ bytes[i] = (byte) (int) (l & 0xFF);
+ }
+ break;
+ default:
+ return null;
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ return null;
+ }
+ return bytes;
+ }
+
+ /**
+ * 鑾峰彇IP鍦板潃
+ *
+ * @return 鏈湴IP鍦板潃
+ */
+ public static String getHostIp()
+ {
+ try
+ {
+ return InetAddress.getLocalHost().getHostAddress();
+ }
+ catch (UnknownHostException e)
+ {
+ }
+ return "127.0.0.1";
+ }
+
+ /**
+ * 鑾峰彇涓绘満鍚�
+ *
+ * @return 鏈湴涓绘満鍚�
+ */
+ public static String getHostName()
+ {
+ try
+ {
+ return InetAddress.getLocalHost().getHostName();
+ }
+ catch (UnknownHostException e)
+ {
+ }
+ return "鏈煡";
+ }
+
+ /**
+ * 浠庡绾у弽鍚戜唬鐞嗕腑鑾峰緱绗竴涓潪unknown IP鍦板潃
+ *
+ * @param ip 鑾峰緱鐨処P鍦板潃
+ * @return 绗竴涓潪unknown IP鍦板潃
+ */
+ public static String getMultistageReverseProxyIp(String ip)
+ {
+ // 澶氱骇鍙嶅悜浠g悊妫�娴�
+ if (ip != null && ip.indexOf(",") > 0)
+ {
+ final String[] ips = ip.trim().split(",");
+ for (String subIp : ips)
+ {
+ if (false == isUnknown(subIp))
+ {
+ ip = subIp;
+ break;
+ }
+ }
+ }
+ return StringUtils.substring(ip, 0, 255);
+ }
+
+ /**
+ * 妫�娴嬬粰瀹氬瓧绗︿覆鏄惁涓烘湭鐭ワ紝澶氱敤浜庢娴婬TTP璇锋眰鐩稿叧
+ *
+ * @param checkString 琚娴嬬殑瀛楃涓�
+ * @return 鏄惁鏈煡
+ */
+ public static boolean isUnknown(String checkString)
+ {
+ return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
+ }
+
+ /**
+ * 鏄惁涓篒P
+ */
+ public static boolean isIP(String ip)
+ {
+ return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP);
+ }
+
+ /**
+ * 鏄惁涓篒P锛屾垨 *涓洪棿闅旂殑閫氶厤绗﹀湴鍧�
+ */
+ public static boolean isIpWildCard(String ip)
+ {
+ return StringUtils.isNotBlank(ip) && ip.matches(REGX_IP_WILDCARD);
+ }
+
+ /**
+ * 妫�娴嬪弬鏁版槸鍚﹀湪ip閫氶厤绗﹂噷
+ */
+ public static boolean ipIsInWildCardNoCheck(String ipWildCard, String ip)
+ {
+ String[] s1 = ipWildCard.split("\\.");
+ String[] s2 = ip.split("\\.");
+ boolean isMatchedSeg = true;
+ for (int i = 0; i < s1.length && !s1[i].equals("*"); i++)
+ {
+ if (!s1[i].equals(s2[i]))
+ {
+ isMatchedSeg = false;
+ break;
+ }
+ }
+ return isMatchedSeg;
+ }
+
+ /**
+ * 鏄惁涓虹壒瀹氭牸寮忓:鈥�10.10.10.1-10.10.10.99鈥濈殑ip娈靛瓧绗︿覆
+ */
+ public static boolean isIPSegment(String ipSeg)
+ {
+ return StringUtils.isNotBlank(ipSeg) && ipSeg.matches(REGX_IP_SEG);
+ }
+
+ /**
+ * 鍒ゆ柇ip鏄惁鍦ㄦ寚瀹氱綉娈典腑
+ */
+ public static boolean ipIsInNetNoCheck(String iparea, String ip)
+ {
+ int idx = iparea.indexOf('-');
+ String[] sips = iparea.substring(0, idx).split("\\.");
+ String[] sipe = iparea.substring(idx + 1).split("\\.");
+ String[] sipt = ip.split("\\.");
+ long ips = 0L, ipe = 0L, ipt = 0L;
+ for (int i = 0; i < 4; ++i)
+ {
+ ips = ips << 8 | Integer.parseInt(sips[i]);
+ ipe = ipe << 8 | Integer.parseInt(sipe[i]);
+ ipt = ipt << 8 | Integer.parseInt(sipt[i]);
+ }
+ if (ips > ipe)
+ {
+ long t = ips;
+ ips = ipe;
+ ipe = t;
+ }
+ return ips <= ipt && ipt <= ipe;
+ }
+
+ /**
+ * 鏍¢獙ip鏄惁绗﹀悎杩囨护涓茶鍒�
+ *
+ * @param filter 杩囨护IP鍒楄〃,鏀寔鍚庣紑'*'閫氶厤,鏀寔缃戞濡�:`10.10.10.1-10.10.10.99`
+ * @param ip 鏍¢獙IP鍦板潃
+ * @return boolean 缁撴灉
+ */
+ public static boolean isMatchedIp(String filter, String ip)
+ {
+ if (StringUtils.isEmpty(filter) || StringUtils.isEmpty(ip))
+ {
+ return false;
+ }
+ String[] ips = filter.split(";");
+ for (String iStr : ips)
+ {
+ if (isIP(iStr) && iStr.equals(ip))
+ {
+ return true;
+ }
+ else if (isIpWildCard(iStr) && ipIsInWildCardNoCheck(iStr, ip))
+ {
+ return true;
+ }
+ else if (isIPSegment(iStr) && ipIsInNetNoCheck(iStr, ip))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java
new file mode 100644
index 0000000..ccab288
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelHandlerAdapter.java
@@ -0,0 +1,24 @@
+package com.ruoyi.common.utils.poi;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Workbook;
+
+/**
+ * Excel鏁版嵁鏍煎紡澶勭悊閫傞厤鍣�
+ *
+ * @author ruoyi
+ */
+public interface ExcelHandlerAdapter
+{
+ /**
+ * 鏍煎紡鍖�
+ *
+ * @param value 鍗曞厓鏍兼暟鎹��
+ * @param args excel娉ㄨВargs鍙傛暟缁�
+ * @param cell 鍗曞厓鏍煎璞�
+ * @param wb 宸ヤ綔绨垮璞�
+ *
+ * @return 澶勭悊鍚庣殑鍊�
+ */
+ Object format(Object value, String[] args, Cell cell, Workbook wb);
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
new file mode 100644
index 0000000..15f5db2
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
@@ -0,0 +1,1900 @@
+package com.ruoyi.common.utils.poi;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.ParameterizedType;
+import java.math.BigDecimal;
+import java.text.DecimalFormat;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.apache.commons.lang3.RegExUtils;
+import org.apache.commons.lang3.reflect.FieldUtils;
+import org.apache.poi.hssf.usermodel.HSSFClientAnchor;
+import org.apache.poi.hssf.usermodel.HSSFPicture;
+import org.apache.poi.hssf.usermodel.HSSFPictureData;
+import org.apache.poi.hssf.usermodel.HSSFShape;
+import org.apache.poi.hssf.usermodel.HSSFSheet;
+import org.apache.poi.hssf.usermodel.HSSFWorkbook;
+import org.apache.poi.ooxml.POIXMLDocumentPart;
+import org.apache.poi.ss.usermodel.BorderStyle;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellStyle;
+import org.apache.poi.ss.usermodel.CellType;
+import org.apache.poi.ss.usermodel.ClientAnchor;
+import org.apache.poi.ss.usermodel.DataFormat;
+import org.apache.poi.ss.usermodel.DataValidation;
+import org.apache.poi.ss.usermodel.DataValidationConstraint;
+import org.apache.poi.ss.usermodel.DataValidationHelper;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.apache.poi.ss.usermodel.Drawing;
+import org.apache.poi.ss.usermodel.FillPatternType;
+import org.apache.poi.ss.usermodel.Font;
+import org.apache.poi.ss.usermodel.HorizontalAlignment;
+import org.apache.poi.ss.usermodel.IndexedColors;
+import org.apache.poi.ss.usermodel.Name;
+import org.apache.poi.ss.usermodel.PictureData;
+import org.apache.poi.ss.usermodel.Row;
+import org.apache.poi.ss.usermodel.Sheet;
+import org.apache.poi.ss.usermodel.VerticalAlignment;
+import org.apache.poi.ss.usermodel.Workbook;
+import org.apache.poi.ss.usermodel.WorkbookFactory;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellRangeAddressList;
+import org.apache.poi.util.IOUtils;
+import org.apache.poi.xssf.streaming.SXSSFWorkbook;
+import org.apache.poi.xssf.usermodel.XSSFClientAnchor;
+import org.apache.poi.xssf.usermodel.XSSFDataValidation;
+import org.apache.poi.xssf.usermodel.XSSFDrawing;
+import org.apache.poi.xssf.usermodel.XSSFPicture;
+import org.apache.poi.xssf.usermodel.XSSFShape;
+import org.apache.poi.xssf.usermodel.XSSFSheet;
+import org.apache.poi.xssf.usermodel.XSSFWorkbook;
+import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.annotation.Excel.Type;
+import com.ruoyi.common.annotation.Excels;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.UtilException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.DictUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.file.FileTypeUtils;
+import com.ruoyi.common.utils.file.FileUtils;
+import com.ruoyi.common.utils.file.ImageUtils;
+import com.ruoyi.common.utils.reflect.ReflectUtils;
+
+/**
+ * Excel鐩稿叧澶勭悊
+ *
+ * @author ruoyi
+ */
+public class ExcelUtil<T>
+{
+ private static final Logger log = LoggerFactory.getLogger(ExcelUtil.class);
+
+ public static final String FORMULA_REGEX_STR = "=|-|\\+|@";
+
+ public static final String[] FORMULA_STR = { "=", "-", "+", "@" };
+
+ /**
+ * 鐢ㄤ簬dictType灞炴�ф暟鎹瓨鍌紝閬垮厤閲嶅鏌ョ紦瀛�
+ */
+ public Map<String, String> sysDictMap = new HashMap<String, String>();
+
+ /**
+ * Excel sheet鏈�澶ц鏁帮紝榛樿65536
+ */
+ public static final int sheetSize = 65536;
+
+ /**
+ * 宸ヤ綔琛ㄥ悕绉�
+ */
+ private String sheetName;
+
+ /**
+ * 瀵煎嚭绫诲瀷锛圗XPORT:瀵煎嚭鏁版嵁锛汭MPORT锛氬鍏ユā鏉匡級
+ */
+ private Type type;
+
+ /**
+ * 宸ヤ綔钖勫璞�
+ */
+ private Workbook wb;
+
+ /**
+ * 宸ヤ綔琛ㄥ璞�
+ */
+ private Sheet sheet;
+
+ /**
+ * 鏍峰紡鍒楄〃
+ */
+ private Map<String, CellStyle> styles;
+
+ /**
+ * 瀵煎叆瀵煎嚭鏁版嵁鍒楄〃
+ */
+ private List<T> list;
+
+ /**
+ * 娉ㄨВ鍒楄〃
+ */
+ private List<Object[]> fields;
+
+ /**
+ * 褰撳墠琛屽彿
+ */
+ private int rownum;
+
+ /**
+ * 鏍囬
+ */
+ private String title;
+
+ /**
+ * 鏈�澶ч珮搴�
+ */
+ private short maxHeight;
+
+ /**
+ * 鍚堝苟鍚庢渶鍚庤鏁�
+ */
+ private int subMergedLastRowNum = 0;
+
+ /**
+ * 鍚堝苟鍚庡紑濮嬭鏁�
+ */
+ private int subMergedFirstRowNum = 1;
+
+ /**
+ * 瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+ */
+ private Method subMethod;
+
+ /**
+ * 瀵硅薄鐨勫瓙鍒楄〃灞炴��
+ */
+ private List<Field> subFields;
+
+ /**
+ * 缁熻鍒楄〃
+ */
+ private Map<Integer, Double> statistics = new HashMap<Integer, Double>();
+
+ /**
+ * 鏁板瓧鏍煎紡
+ */
+ private static final DecimalFormat DOUBLE_FORMAT = new DecimalFormat("######0.00");
+
+ /**
+ * 瀹炰綋瀵硅薄
+ */
+ public Class<T> clazz;
+
+ /**
+ * 闇�瑕佹樉绀哄垪灞炴��
+ */
+ public String[] includeFields;
+
+ /**
+ * 闇�瑕佹帓闄ゅ垪灞炴��
+ */
+ public String[] excludeFields;
+
+ public ExcelUtil(Class<T> clazz)
+ {
+ this.clazz = clazz;
+ }
+
+ /**
+ * 浠呭湪Excel涓樉绀哄垪灞炴��
+ *
+ * @param fields 鍒楀睘鎬у悕 绀轰緥[鍗曚釜"name"/澶氫釜"id","name"]
+ */
+ public void showColumn(String... fields)
+ {
+ this.includeFields = fields;
+ }
+
+ /**
+ * 闅愯棌Excel涓垪灞炴��
+ *
+ * @param fields 鍒楀睘鎬у悕 绀轰緥[鍗曚釜"name"/澶氫釜"id","name"]
+ */
+ public void hideColumn(String... fields)
+ {
+ this.excludeFields = fields;
+ }
+
+ public void init(List<T> list, String sheetName, String title, Type type)
+ {
+ if (list == null)
+ {
+ list = new ArrayList<T>();
+ }
+ this.list = list;
+ this.sheetName = sheetName;
+ this.type = type;
+ this.title = title;
+ createExcelField();
+ createWorkbook();
+ createTitle();
+ createSubHead();
+ }
+
+ /**
+ * 鍒涘缓excel绗竴琛屾爣棰�
+ */
+ public void createTitle()
+ {
+ if (StringUtils.isNotEmpty(title))
+ {
+ int titleLastCol = this.fields.size() - 1;
+ if (isSubList())
+ {
+ titleLastCol = titleLastCol + subFields.size() - 1;
+ }
+ Row titleRow = sheet.createRow(rownum == 0 ? rownum++ : 0);
+ titleRow.setHeightInPoints(30);
+ Cell titleCell = titleRow.createCell(0);
+ titleCell.setCellStyle(styles.get("title"));
+ titleCell.setCellValue(title);
+ sheet.addMergedRegion(new CellRangeAddress(titleRow.getRowNum(), titleRow.getRowNum(), 0, titleLastCol));
+ }
+ }
+
+ /**
+ * 鍒涘缓瀵硅薄鐨勫瓙鍒楄〃鍚嶇О
+ */
+ public void createSubHead()
+ {
+ if (isSubList())
+ {
+ Row subRow = sheet.createRow(rownum);
+ int column = 0;
+ int subFieldSize = subFields != null ? subFields.size() : 0;
+ for (Object[] objects : fields)
+ {
+ Field field = (Field) objects[0];
+ Excel attr = (Excel) objects[1];
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ Cell cell = subRow.createCell(column);
+ cell.setCellValue(attr.name());
+ cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+ if (subFieldSize > 1)
+ {
+ CellRangeAddress cellAddress = new CellRangeAddress(rownum, rownum, column, column + subFieldSize - 1);
+ sheet.addMergedRegion(cellAddress);
+ }
+ column += subFieldSize;
+ }
+ else
+ {
+ Cell cell = subRow.createCell(column++);
+ cell.setCellValue(attr.name());
+ cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+ }
+ }
+ rownum++;
+ }
+ }
+
+ /**
+ * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+ *
+ * @param is 杈撳叆娴�
+ * @return 杞崲鍚庨泦鍚�
+ */
+ public List<T> importExcel(InputStream is)
+ {
+ return importExcel(is, 0);
+ }
+
+ /**
+ * 瀵筫xcel琛ㄥ崟榛樿绗竴涓储寮曞悕杞崲鎴恖ist
+ *
+ * @param is 杈撳叆娴�
+ * @param titleNum 鏍囬鍗犵敤琛屾暟
+ * @return 杞崲鍚庨泦鍚�
+ */
+ public List<T> importExcel(InputStream is, int titleNum)
+ {
+ List<T> list = null;
+ try
+ {
+ list = importExcel(StringUtils.EMPTY, is, titleNum);
+ }
+ catch (Exception e)
+ {
+ log.error("瀵煎叆Excel寮傚父{}", e.getMessage());
+ throw new UtilException(e.getMessage());
+ }
+ finally
+ {
+ IOUtils.closeQuietly(is);
+ }
+ return list;
+ }
+
+ /**
+ * 瀵筫xcel琛ㄥ崟鎸囧畾琛ㄦ牸绱㈠紩鍚嶈浆鎹㈡垚list
+ *
+ * @param sheetName 琛ㄦ牸绱㈠紩鍚�
+ * @param titleNum 鏍囬鍗犵敤琛屾暟
+ * @param is 杈撳叆娴�
+ * @return 杞崲鍚庨泦鍚�
+ */
+ public List<T> importExcel(String sheetName, InputStream is, int titleNum) throws Exception
+ {
+ this.type = Type.IMPORT;
+ this.wb = WorkbookFactory.create(is);
+ List<T> list = new ArrayList<T>();
+ // 濡傛灉鎸囧畾sheet鍚�,鍒欏彇鎸囧畾sheet涓殑鍐呭 鍚﹀垯榛樿鎸囧悜绗�1涓猻heet
+ Sheet sheet = StringUtils.isNotEmpty(sheetName) ? wb.getSheet(sheetName) : wb.getSheetAt(0);
+ if (sheet == null)
+ {
+ throw new IOException("鏂囦欢sheet涓嶅瓨鍦�");
+ }
+ boolean isXSSFWorkbook = !(wb instanceof HSSFWorkbook);
+ Map<String, PictureData> pictures;
+ if (isXSSFWorkbook)
+ {
+ pictures = getSheetPictures07((XSSFSheet) sheet, (XSSFWorkbook) wb);
+ }
+ else
+ {
+ pictures = getSheetPictures03((HSSFSheet) sheet, (HSSFWorkbook) wb);
+ }
+ // 鑾峰彇鏈�鍚庝竴涓潪绌鸿鐨勮涓嬫爣锛屾瘮濡傛�昏鏁颁负n锛屽垯杩斿洖鐨勪负n-1
+ int rows = sheet.getLastRowNum();
+ if (rows > 0)
+ {
+ // 瀹氫箟涓�涓猰ap鐢ㄤ簬瀛樻斁excel鍒楃殑搴忓彿鍜宖ield.
+ Map<String, Integer> cellMap = new HashMap<String, Integer>();
+ // 鑾峰彇琛ㄥご
+ Row heard = sheet.getRow(titleNum);
+ for (int i = 0; i < heard.getPhysicalNumberOfCells(); i++)
+ {
+ Cell cell = heard.getCell(i);
+ if (StringUtils.isNotNull(cell))
+ {
+ String value = this.getCellValue(heard, i).toString();
+ cellMap.put(value, i);
+ }
+ else
+ {
+ cellMap.put(null, i);
+ }
+ }
+ // 鏈夋暟鎹椂鎵嶅鐞� 寰楀埌绫荤殑鎵�鏈塮ield.
+ List<Object[]> fields = this.getFields();
+ Map<Integer, Object[]> fieldsMap = new HashMap<Integer, Object[]>();
+ for (Object[] objects : fields)
+ {
+ Excel attr = (Excel) objects[1];
+ Integer column = cellMap.get(attr.name());
+ if (column != null)
+ {
+ fieldsMap.put(column, objects);
+ }
+ }
+ for (int i = titleNum + 1; i <= rows; i++)
+ {
+ // 浠庣2琛屽紑濮嬪彇鏁版嵁,榛樿绗竴琛屾槸琛ㄥご.
+ Row row = sheet.getRow(i);
+ // 鍒ゆ柇褰撳墠琛屾槸鍚︽槸绌鸿
+ if (isRowEmpty(row))
+ {
+ continue;
+ }
+ T entity = null;
+ for (Map.Entry<Integer, Object[]> entry : fieldsMap.entrySet())
+ {
+ Object val = this.getCellValue(row, entry.getKey());
+
+ // 濡傛灉涓嶅瓨鍦ㄥ疄渚嬪垯鏂板缓.
+ entity = (entity == null ? clazz.newInstance() : entity);
+ // 浠巑ap涓緱鍒板搴斿垪鐨刦ield.
+ Field field = (Field) entry.getValue()[0];
+ Excel attr = (Excel) entry.getValue()[1];
+ // 鍙栧緱绫诲瀷,骞舵牴鎹璞$被鍨嬭缃��.
+ Class<?> fieldType = field.getType();
+ if (String.class == fieldType)
+ {
+ String s = Convert.toStr(val);
+ if (StringUtils.endsWith(s, ".0"))
+ {
+ val = StringUtils.substringBefore(s, ".0");
+ }
+ else
+ {
+ String dateFormat = field.getAnnotation(Excel.class).dateFormat();
+ if (StringUtils.isNotEmpty(dateFormat))
+ {
+ val = parseDateToStr(dateFormat, val);
+ }
+ else
+ {
+ val = Convert.toStr(val);
+ }
+ }
+ }
+ else if ((Integer.TYPE == fieldType || Integer.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+ {
+ val = Convert.toInt(val);
+ }
+ else if ((Long.TYPE == fieldType || Long.class == fieldType) && StringUtils.isNumeric(Convert.toStr(val)))
+ {
+ val = Convert.toLong(val);
+ }
+ else if (Double.TYPE == fieldType || Double.class == fieldType)
+ {
+ val = Convert.toDouble(val);
+ }
+ else if (Float.TYPE == fieldType || Float.class == fieldType)
+ {
+ val = Convert.toFloat(val);
+ }
+ else if (BigDecimal.class == fieldType)
+ {
+ val = Convert.toBigDecimal(val);
+ }
+ else if (Date.class == fieldType)
+ {
+ if (val instanceof String)
+ {
+ val = DateUtils.parseDate(val);
+ }
+ else if (val instanceof Double)
+ {
+ val = DateUtil.getJavaDate((Double) val);
+ }
+ }
+ else if (Boolean.TYPE == fieldType || Boolean.class == fieldType)
+ {
+ val = Convert.toBool(val, false);
+ }
+ if (StringUtils.isNotNull(fieldType))
+ {
+ String propertyName = field.getName();
+ if (StringUtils.isNotEmpty(attr.targetAttr()))
+ {
+ propertyName = field.getName() + "." + attr.targetAttr();
+ }
+ if (StringUtils.isNotEmpty(attr.readConverterExp()))
+ {
+ val = reverseByExp(Convert.toStr(val), attr.readConverterExp(), attr.separator());
+ }
+ else if (StringUtils.isNotEmpty(attr.dictType()))
+ {
+ if (!sysDictMap.containsKey(attr.dictType() + val))
+ {
+ String dictValue = reverseDictByExp(Convert.toStr(val), attr.dictType(), attr.separator());
+ sysDictMap.put(attr.dictType() + val, dictValue);
+ }
+ val = sysDictMap.get(attr.dictType() + val);
+ }
+ else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+ {
+ val = dataFormatHandlerAdapter(val, attr, null);
+ }
+ else if (ColumnType.IMAGE == attr.cellType() && StringUtils.isNotEmpty(pictures))
+ {
+ PictureData image = pictures.get(row.getRowNum() + "_" + entry.getKey());
+ if (image == null)
+ {
+ val = "";
+ }
+ else
+ {
+ byte[] data = image.getData();
+ val = FileUtils.writeImportBytes(data);
+ }
+ }
+ ReflectUtils.invokeSetter(entity, propertyName, val);
+ }
+ }
+ list.add(entity);
+ }
+ }
+ return list;
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param list 瀵煎嚭鏁版嵁闆嗗悎
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @return 缁撴灉
+ */
+ public AjaxResult exportExcel(List<T> list, String sheetName)
+ {
+ return exportExcel(list, sheetName, StringUtils.EMPTY);
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param list 瀵煎嚭鏁版嵁闆嗗悎
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @param title 鏍囬
+ * @return 缁撴灉
+ */
+ public AjaxResult exportExcel(List<T> list, String sheetName, String title)
+ {
+ this.init(list, sheetName, title, Type.EXPORT);
+ return exportExcel();
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param response 杩斿洖鏁版嵁
+ * @param list 瀵煎嚭鏁版嵁闆嗗悎
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @return 缁撴灉
+ */
+ public void exportExcel(HttpServletResponse response, List<T> list, String sheetName)
+ {
+ exportExcel(response, list, sheetName, StringUtils.EMPTY);
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param response 杩斿洖鏁版嵁
+ * @param list 瀵煎嚭鏁版嵁闆嗗悎
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @param title 鏍囬
+ * @return 缁撴灉
+ */
+ public void exportExcel(HttpServletResponse response, List<T> list, String sheetName, String title)
+ {
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ response.setCharacterEncoding("utf-8");
+ this.init(list, sheetName, title, Type.EXPORT);
+ exportExcel(response);
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @return 缁撴灉
+ */
+ public AjaxResult importTemplateExcel(String sheetName)
+ {
+ return importTemplateExcel(sheetName, StringUtils.EMPTY);
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @param title 鏍囬
+ * @return 缁撴灉
+ */
+ public AjaxResult importTemplateExcel(String sheetName, String title)
+ {
+ this.init(null, sheetName, title, Type.IMPORT);
+ return exportExcel();
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @return 缁撴灉
+ */
+ public void importTemplateExcel(HttpServletResponse response, String sheetName)
+ {
+ importTemplateExcel(response, sheetName, StringUtils.EMPTY);
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @param sheetName 宸ヤ綔琛ㄧ殑鍚嶇О
+ * @param title 鏍囬
+ * @return 缁撴灉
+ */
+ public void importTemplateExcel(HttpServletResponse response, String sheetName, String title)
+ {
+ response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
+ response.setCharacterEncoding("utf-8");
+ this.init(null, sheetName, title, Type.IMPORT);
+ exportExcel(response);
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @return 缁撴灉
+ */
+ public void exportExcel(HttpServletResponse response)
+ {
+ try
+ {
+ writeSheet();
+ wb.write(response.getOutputStream());
+ }
+ catch (Exception e)
+ {
+ log.error("瀵煎嚭Excel寮傚父{}", e.getMessage());
+ }
+ finally
+ {
+ IOUtils.closeQuietly(wb);
+ }
+ }
+
+ /**
+ * 瀵筶ist鏁版嵁婧愬皢鍏堕噷闈㈢殑鏁版嵁瀵煎叆鍒癳xcel琛ㄥ崟
+ *
+ * @return 缁撴灉
+ */
+ public AjaxResult exportExcel()
+ {
+ OutputStream out = null;
+ try
+ {
+ writeSheet();
+ String filename = encodingFilename(sheetName);
+ out = new FileOutputStream(getAbsoluteFile(filename));
+ wb.write(out);
+ return AjaxResult.success(filename);
+ }
+ catch (Exception e)
+ {
+ log.error("瀵煎嚭Excel寮傚父{}", e.getMessage());
+ throw new UtilException("瀵煎嚭Excel澶辫触锛岃鑱旂郴缃戠珯绠$悊鍛橈紒");
+ }
+ finally
+ {
+ IOUtils.closeQuietly(wb);
+ IOUtils.closeQuietly(out);
+ }
+ }
+
+ /**
+ * 鍒涘缓鍐欏叆鏁版嵁鍒癝heet
+ */
+ public void writeSheet()
+ {
+ // 鍙栧嚭涓�鍏辨湁澶氬皯涓猻heet.
+ int sheetNo = Math.max(1, (int) Math.ceil(list.size() * 1.0 / sheetSize));
+ for (int index = 0; index < sheetNo; index++)
+ {
+ createSheet(sheetNo, index);
+
+ // 浜х敓涓�琛�
+ Row row = sheet.createRow(rownum);
+ int column = 0;
+ // 鍐欏叆鍚勪釜瀛楁鐨勫垪澶村悕绉�
+ for (Object[] os : fields)
+ {
+ Field field = (Field) os[0];
+ Excel excel = (Excel) os[1];
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ for (Field subField : subFields)
+ {
+ Excel subExcel = subField.getAnnotation(Excel.class);
+ this.createHeadCell(subExcel, row, column++);
+ }
+ }
+ else
+ {
+ this.createHeadCell(excel, row, column++);
+ }
+ }
+ if (Type.EXPORT.equals(type))
+ {
+ fillExcelData(index, row);
+ addStatisticsRow();
+ }
+ }
+ }
+
+ /**
+ * 濉厖excel鏁版嵁
+ *
+ * @param index 搴忓彿
+ * @param row 鍗曞厓鏍艰
+ */
+ @SuppressWarnings("unchecked")
+ public void fillExcelData(int index, Row row)
+ {
+ int startNo = index * sheetSize;
+ int endNo = Math.min(startNo + sheetSize, list.size());
+ int currentRowNum = rownum + 1; // 浠庢爣棰樿鍚庡紑濮�
+
+ for (int i = startNo; i < endNo; i++)
+ {
+ row = sheet.createRow(currentRowNum);
+ T vo = (T) list.get(i);
+ int column = 0;
+ int maxSubListSize = getCurrentMaxSubListSize(vo);
+ for (Object[] os : fields)
+ {
+ Field field = (Field) os[0];
+ Excel excel = (Excel) os[1];
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ try
+ {
+ Collection<?> subList = (Collection<?>) getTargetValue(vo, field, excel);
+ if (subList != null && !subList.isEmpty())
+ {
+ int subIndex = 0;
+ for (Object subVo : subList)
+ {
+ Row subRow = sheet.getRow(currentRowNum + subIndex);
+ if (subRow == null)
+ {
+ subRow = sheet.createRow(currentRowNum + subIndex);
+ }
+
+ int subColumn = column;
+ for (Field subField : subFields)
+ {
+ Excel subExcel = subField.getAnnotation(Excel.class);
+ addCell(subExcel, subRow, (T) subVo, subField, subColumn++);
+ }
+ subIndex++;
+ }
+ column += subFields.size();
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("濉厖闆嗗悎鏁版嵁澶辫触", e);
+ }
+ }
+ else
+ {
+ // 鍒涘缓鍗曞厓鏍煎苟璁剧疆鍊�
+ addCell(excel, row, vo, field, column);
+ if (maxSubListSize > 1 && excel.needMerge())
+ {
+ sheet.addMergedRegion(new CellRangeAddress(currentRowNum, currentRowNum + maxSubListSize - 1, column, column));
+ }
+ column++;
+ }
+ }
+ currentRowNum += maxSubListSize;
+ }
+ }
+
+ /**
+ * 鑾峰彇瀛愬垪琛ㄦ渶澶ф暟
+ */
+ private int getCurrentMaxSubListSize(T vo)
+ {
+ int maxSubListSize = 1;
+ for (Object[] os : fields)
+ {
+ Field field = (Field) os[0];
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ try
+ {
+ Collection<?> subList = (Collection<?>) getTargetValue(vo, field, (Excel) os[1]);
+ if (subList != null && !subList.isEmpty())
+ {
+ maxSubListSize = Math.max(maxSubListSize, subList.size());
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("鑾峰彇闆嗗悎澶у皬澶辫触", e);
+ }
+ }
+ }
+ return maxSubListSize;
+ }
+
+ /**
+ * 鍒涘缓琛ㄦ牸鏍峰紡
+ *
+ * @param wb 宸ヤ綔钖勫璞�
+ * @return 鏍峰紡鍒楄〃
+ */
+ private Map<String, CellStyle> createStyles(Workbook wb)
+ {
+ // 鍐欏叆鍚勬潯璁板綍,姣忔潯璁板綍瀵瑰簲excel琛ㄤ腑鐨勪竴琛�
+ Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+ CellStyle style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ Font titleFont = wb.createFont();
+ titleFont.setFontName("Arial");
+ titleFont.setFontHeightInPoints((short) 16);
+ titleFont.setBold(true);
+ style.setFont(titleFont);
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
+ styles.put("title", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.THIN);
+ style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ Font dataFont = wb.createFont();
+ dataFont.setFontName("Arial");
+ dataFont.setFontHeightInPoints((short) 10);
+ style.setFont(dataFont);
+ styles.put("data", style);
+
+ style = wb.createCellStyle();
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ Font totalFont = wb.createFont();
+ totalFont.setFontName("Arial");
+ totalFont.setFontHeightInPoints((short) 10);
+ style.setFont(totalFont);
+ styles.put("total", style);
+
+ styles.putAll(annotationHeaderStyles(wb, styles));
+
+ styles.putAll(annotationDataStyles(wb));
+
+ return styles;
+ }
+
+ /**
+ * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸澶存牱寮�
+ *
+ * @param wb 宸ヤ綔钖勫璞�
+ * @return 鑷畾涔夋牱寮忓垪琛�
+ */
+ private Map<String, CellStyle> annotationHeaderStyles(Workbook wb, Map<String, CellStyle> styles)
+ {
+ Map<String, CellStyle> headerStyles = new HashMap<String, CellStyle>();
+ for (Object[] os : fields)
+ {
+ Excel excel = (Excel) os[1];
+ String key = StringUtils.format("header_{}_{}", excel.headerColor(), excel.headerBackgroundColor());
+ if (!headerStyles.containsKey(key))
+ {
+ CellStyle style = wb.createCellStyle();
+ style.cloneStyleFrom(styles.get("data"));
+ style.setAlignment(HorizontalAlignment.CENTER);
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setFillForegroundColor(excel.headerBackgroundColor().index);
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ Font headerFont = wb.createFont();
+ headerFont.setFontName("Arial");
+ headerFont.setFontHeightInPoints((short) 10);
+ headerFont.setBold(true);
+ headerFont.setColor(excel.headerColor().index);
+ style.setFont(headerFont);
+ // 璁剧疆琛ㄦ牸澶村崟鍏冩牸鏂囨湰褰㈠紡
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
+ headerStyles.put(key, style);
+ }
+ }
+ return headerStyles;
+ }
+
+ /**
+ * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸鍒楁牱寮�
+ *
+ * @param wb 宸ヤ綔钖勫璞�
+ * @return 鑷畾涔夋牱寮忓垪琛�
+ */
+ private Map<String, CellStyle> annotationDataStyles(Workbook wb)
+ {
+ Map<String, CellStyle> styles = new HashMap<String, CellStyle>();
+ for (Object[] os : fields)
+ {
+ Field field = (Field) os[0];
+ Excel excel = (Excel) os[1];
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ ParameterizedType pt = (ParameterizedType) field.getGenericType();
+ Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+ List<Field> subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+ for (Field subField : subFields)
+ {
+ Excel subExcel = subField.getAnnotation(Excel.class);
+ annotationDataStyles(styles, subField, subExcel);
+ }
+ }
+ else
+ {
+ annotationDataStyles(styles, field, excel);
+ }
+ }
+ return styles;
+ }
+
+ /**
+ * 鏍规嵁Excel娉ㄨВ鍒涘缓琛ㄦ牸鍒楁牱寮�
+ *
+ * @param styles 鑷畾涔夋牱寮忓垪琛�
+ * @param field 灞炴�у垪淇℃伅
+ * @param excel 娉ㄨВ淇℃伅
+ */
+ public void annotationDataStyles(Map<String, CellStyle> styles, Field field, Excel excel)
+ {
+ String key = StringUtils.format("data_{}_{}_{}_{}_{}", excel.align(), excel.color(), excel.backgroundColor(), excel.cellType(), excel.wrapText());
+ if (!styles.containsKey(key))
+ {
+ CellStyle style = wb.createCellStyle();
+ style.setAlignment(excel.align());
+ style.setVerticalAlignment(VerticalAlignment.CENTER);
+ style.setBorderRight(BorderStyle.THIN);
+ style.setRightBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderLeft(BorderStyle.THIN);
+ style.setLeftBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderTop(BorderStyle.THIN);
+ style.setTopBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setBorderBottom(BorderStyle.THIN);
+ style.setBottomBorderColor(IndexedColors.GREY_50_PERCENT.getIndex());
+ style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
+ style.setFillForegroundColor(excel.backgroundColor().getIndex());
+ style.setWrapText(excel.wrapText());
+ Font dataFont = wb.createFont();
+ dataFont.setFontName("Arial");
+ dataFont.setFontHeightInPoints((short) 10);
+ dataFont.setColor(excel.color().index);
+ style.setFont(dataFont);
+ if (ColumnType.TEXT == excel.cellType())
+ {
+ DataFormat dataFormat = wb.createDataFormat();
+ style.setDataFormat(dataFormat.getFormat("@"));
+ }
+ styles.put(key, style);
+ }
+ }
+
+ /**
+ * 鍒涘缓鍗曞厓鏍�
+ */
+ public Cell createHeadCell(Excel attr, Row row, int column)
+ {
+ // 鍒涘缓鍒�
+ Cell cell = row.createCell(column);
+ // 鍐欏叆鍒椾俊鎭�
+ cell.setCellValue(attr.name());
+ setDataValidation(attr, row, column);
+ cell.setCellStyle(styles.get(StringUtils.format("header_{}_{}", attr.headerColor(), attr.headerBackgroundColor())));
+ if (isSubList())
+ {
+ // 濉厖榛樿鏍峰紡锛岄槻姝㈠悎骞跺崟鍏冩牸鏍峰紡澶辨晥
+ sheet.setDefaultColumnStyle(column, styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
+ if (attr.needMerge())
+ {
+ sheet.addMergedRegion(new CellRangeAddress(rownum - 1, rownum, column, column));
+ }
+ }
+ return cell;
+ }
+
+ /**
+ * 璁剧疆鍗曞厓鏍间俊鎭�
+ *
+ * @param value 鍗曞厓鏍煎��
+ * @param attr 娉ㄨВ鐩稿叧
+ * @param cell 鍗曞厓鏍间俊鎭�
+ */
+ public void setCellVo(Object value, Excel attr, Cell cell)
+ {
+ if (ColumnType.STRING == attr.cellType() || ColumnType.TEXT == attr.cellType())
+ {
+ String cellValue = Convert.toStr(value);
+ // 瀵逛簬浠讳綍浠ヨ〃杈惧紡瑙﹀彂瀛楃 =-+@寮�澶寸殑鍗曞厓鏍硷紝鐩存帴浣跨敤tab瀛楃浣滀负鍓嶇紑锛岄槻姝SV娉ㄥ叆銆�
+ if (StringUtils.startsWithAny(cellValue, FORMULA_STR))
+ {
+ cellValue = RegExUtils.replaceFirst(cellValue, FORMULA_REGEX_STR, "\t$0");
+ }
+ if (value instanceof Collection && StringUtils.equals("[]", cellValue))
+ {
+ cellValue = StringUtils.EMPTY;
+ }
+ cell.setCellValue(StringUtils.isNull(cellValue) ? attr.defaultValue() : cellValue + attr.suffix());
+ }
+ else if (ColumnType.NUMERIC == attr.cellType())
+ {
+ if (StringUtils.isNotNull(value))
+ {
+ cell.setCellValue(StringUtils.contains(Convert.toStr(value), ".") ? Convert.toDouble(value) : Convert.toInt(value));
+ }
+ }
+ else if (ColumnType.IMAGE == attr.cellType())
+ {
+ ClientAnchor anchor = new XSSFClientAnchor(0, 0, 0, 0, (short) cell.getColumnIndex(), cell.getRow().getRowNum(), (short) (cell.getColumnIndex() + 1), cell.getRow().getRowNum() + 1);
+ String imagePath = Convert.toStr(value);
+ if (StringUtils.isNotEmpty(imagePath))
+ {
+ byte[] data = ImageUtils.getImage(imagePath);
+ getDrawingPatriarch(cell.getSheet()).createPicture(anchor,
+ cell.getSheet().getWorkbook().addPicture(data, getImageType(data)));
+ }
+ }
+ }
+
+ /**
+ * 鑾峰彇鐢诲竷
+ */
+ public static Drawing<?> getDrawingPatriarch(Sheet sheet)
+ {
+ if (sheet.getDrawingPatriarch() == null)
+ {
+ sheet.createDrawingPatriarch();
+ }
+ return sheet.getDrawingPatriarch();
+ }
+
+ /**
+ * 鑾峰彇鍥剧墖绫诲瀷,璁剧疆鍥剧墖鎻掑叆绫诲瀷
+ */
+ public int getImageType(byte[] value)
+ {
+ String type = FileTypeUtils.getFileExtendName(value);
+ if ("JPG".equalsIgnoreCase(type))
+ {
+ return Workbook.PICTURE_TYPE_JPEG;
+ }
+ else if ("PNG".equalsIgnoreCase(type))
+ {
+ return Workbook.PICTURE_TYPE_PNG;
+ }
+ return Workbook.PICTURE_TYPE_JPEG;
+ }
+
+ /**
+ * 鍒涘缓琛ㄦ牸鏍峰紡
+ */
+ public void setDataValidation(Excel attr, Row row, int column)
+ {
+ if (attr.name().indexOf("娉細") >= 0)
+ {
+ sheet.setColumnWidth(column, 6000);
+ }
+ else
+ {
+ // 璁剧疆鍒楀
+ sheet.setColumnWidth(column, (int) ((attr.width() + 0.72) * 256));
+ }
+ if (StringUtils.isNotEmpty(attr.prompt()) || attr.combo().length > 0 || attr.comboReadDict())
+ {
+ String[] comboArray = attr.combo();
+ if (attr.comboReadDict())
+ {
+ if (!sysDictMap.containsKey("combo_" + attr.dictType()))
+ {
+ String labels = DictUtils.getDictLabels(attr.dictType());
+ sysDictMap.put("combo_" + attr.dictType(), labels);
+ }
+ String val = sysDictMap.get("combo_" + attr.dictType());
+ comboArray = StringUtils.split(val, DictUtils.SEPARATOR);
+ }
+ if (comboArray.length > 15 || StringUtils.join(comboArray).length() > 255)
+ {
+ // 濡傛灉涓嬫媺鏁板ぇ浜�15鎴栧瓧绗︿覆闀垮害澶т簬255锛屽垯浣跨敤涓�涓柊sheet瀛樺偍锛岄伩鍏嶇敓鎴愮殑妯℃澘涓嬫媺鍊艰幏鍙栦笉鍒�
+ setXSSFValidationWithHidden(sheet, comboArray, attr.prompt(), 1, 100, column, column);
+ }
+ else
+ {
+ // 鎻愮ず淇℃伅鎴栧彧鑳介�夋嫨涓嶈兘杈撳叆鐨勫垪鍐呭.
+ setPromptOrValidation(sheet, comboArray, attr.prompt(), 1, 100, column, column);
+ }
+ }
+ }
+
+ /**
+ * 娣诲姞鍗曞厓鏍�
+ */
+ public Cell addCell(Excel attr, Row row, T vo, Field field, int column)
+ {
+ Cell cell = null;
+ try
+ {
+ // 璁剧疆琛岄珮
+ row.setHeight(maxHeight);
+ // 鏍规嵁Excel涓缃儏鍐靛喅瀹氭槸鍚﹀鍑�,鏈変簺鎯呭喌闇�瑕佷繚鎸佷负绌�,甯屾湜鐢ㄦ埛濉啓杩欎竴鍒�.
+ if (attr.isExport())
+ {
+ // 鍒涘缓cell
+ cell = row.createCell(column);
+ if (isSubListValue(vo) && getListCellValue(vo).size() > 1 && attr.needMerge())
+ {
+ if (subMergedLastRowNum >= subMergedFirstRowNum)
+ {
+ sheet.addMergedRegion(new CellRangeAddress(subMergedFirstRowNum, subMergedLastRowNum, column, column));
+ }
+ }
+ cell.setCellStyle(styles.get(StringUtils.format("data_{}_{}_{}_{}_{}", attr.align(), attr.color(), attr.backgroundColor(), attr.cellType(), attr.wrapText())));
+
+ // 鐢ㄤ簬璇诲彇瀵硅薄涓殑灞炴��
+ Object value = getTargetValue(vo, field, attr);
+ String dateFormat = attr.dateFormat();
+ String readConverterExp = attr.readConverterExp();
+ String separator = attr.separator();
+ String dictType = attr.dictType();
+ if (StringUtils.isNotEmpty(dateFormat) && StringUtils.isNotNull(value))
+ {
+ cell.setCellValue(parseDateToStr(dateFormat, value));
+ }
+ else if (StringUtils.isNotEmpty(readConverterExp) && StringUtils.isNotNull(value))
+ {
+ cell.setCellValue(convertByExp(Convert.toStr(value), readConverterExp, separator));
+ }
+ else if (StringUtils.isNotEmpty(dictType) && StringUtils.isNotNull(value))
+ {
+ if (!sysDictMap.containsKey(dictType + value))
+ {
+ String lable = convertDictByExp(Convert.toStr(value), dictType, separator);
+ sysDictMap.put(dictType + value, lable);
+ }
+ cell.setCellValue(sysDictMap.get(dictType + value));
+ }
+ else if (value instanceof BigDecimal && -1 != attr.scale())
+ {
+ cell.setCellValue((((BigDecimal) value).setScale(attr.scale(), attr.roundingMode())).doubleValue());
+ }
+ else if (!attr.handler().equals(ExcelHandlerAdapter.class))
+ {
+ cell.setCellValue(dataFormatHandlerAdapter(value, attr, cell));
+ }
+ else
+ {
+ // 璁剧疆鍒楃被鍨�
+ setCellVo(value, attr, cell);
+ }
+ addStatisticsData(column, Convert.toStr(value), attr);
+ }
+ }
+ catch (Exception e)
+ {
+ log.error("瀵煎嚭Excel澶辫触{}", e);
+ }
+ return cell;
+ }
+
+ /**
+ * 璁剧疆 POI XSSFSheet 鍗曞厓鏍兼彁绀烘垨閫夋嫨妗�
+ *
+ * @param sheet 琛ㄥ崟
+ * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+ * @param promptContent 鎻愮ず鍐呭
+ * @param firstRow 寮�濮嬭
+ * @param endRow 缁撴潫琛�
+ * @param firstCol 寮�濮嬪垪
+ * @param endCol 缁撴潫鍒�
+ */
+ public void setPromptOrValidation(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow,
+ int firstCol, int endCol)
+ {
+ DataValidationHelper helper = sheet.getDataValidationHelper();
+ DataValidationConstraint constraint = textlist.length > 0 ? helper.createExplicitListConstraint(textlist) : helper.createCustomConstraint("DD1");
+ CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+ DataValidation dataValidation = helper.createValidation(constraint, regions);
+ if (StringUtils.isNotEmpty(promptContent))
+ {
+ // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+ dataValidation.createPromptBox("", promptContent);
+ dataValidation.setShowPromptBox(true);
+ }
+ // 澶勭悊Excel鍏煎鎬ч棶棰�
+ if (dataValidation instanceof XSSFDataValidation)
+ {
+ dataValidation.setSuppressDropDownArrow(true);
+ dataValidation.setShowErrorBox(true);
+ }
+ else
+ {
+ dataValidation.setSuppressDropDownArrow(false);
+ }
+ sheet.addValidationData(dataValidation);
+ }
+
+ /**
+ * 璁剧疆鏌愪簺鍒楃殑鍊煎彧鑳借緭鍏ラ鍒剁殑鏁版嵁,鏄剧ず涓嬫媺妗嗭紙鍏煎瓒呭嚭涓�瀹氭暟閲忕殑涓嬫媺妗嗭級.
+ *
+ * @param sheet 瑕佽缃殑sheet.
+ * @param textlist 涓嬫媺妗嗘樉绀虹殑鍐呭
+ * @param promptContent 鎻愮ず鍐呭
+ * @param firstRow 寮�濮嬭
+ * @param endRow 缁撴潫琛�
+ * @param firstCol 寮�濮嬪垪
+ * @param endCol 缁撴潫鍒�
+ */
+ public void setXSSFValidationWithHidden(Sheet sheet, String[] textlist, String promptContent, int firstRow, int endRow, int firstCol, int endCol)
+ {
+ String hideSheetName = "combo_" + firstCol + "_" + endCol;
+ Sheet hideSheet = wb.createSheet(hideSheetName); // 鐢ㄤ簬瀛樺偍 涓嬫媺鑿滃崟鏁版嵁
+ for (int i = 0; i < textlist.length; i++)
+ {
+ hideSheet.createRow(i).createCell(0).setCellValue(textlist[i]);
+ }
+ // 鍒涘缓鍚嶇О锛屽彲琚叾浠栧崟鍏冩牸寮曠敤
+ Name name = wb.createName();
+ name.setNameName(hideSheetName + "_data");
+ name.setRefersToFormula(hideSheetName + "!$A$1:$A$" + textlist.length);
+ DataValidationHelper helper = sheet.getDataValidationHelper();
+ // 鍔犺浇涓嬫媺鍒楄〃鍐呭
+ DataValidationConstraint constraint = helper.createFormulaListConstraint(hideSheetName + "_data");
+ // 璁剧疆鏁版嵁鏈夋晥鎬у姞杞藉湪鍝釜鍗曞厓鏍间笂,鍥涗釜鍙傛暟鍒嗗埆鏄細璧峰琛屻�佺粓姝㈣銆佽捣濮嬪垪銆佺粓姝㈠垪
+ CellRangeAddressList regions = new CellRangeAddressList(firstRow, endRow, firstCol, endCol);
+ // 鏁版嵁鏈夋晥鎬у璞�
+ DataValidation dataValidation = helper.createValidation(constraint, regions);
+ if (StringUtils.isNotEmpty(promptContent))
+ {
+ // 濡傛灉璁剧疆浜嗘彁绀轰俊鎭垯榧犳爣鏀句笂鍘绘彁绀�
+ dataValidation.createPromptBox("", promptContent);
+ dataValidation.setShowPromptBox(true);
+ }
+ // 澶勭悊Excel鍏煎鎬ч棶棰�
+ if (dataValidation instanceof XSSFDataValidation)
+ {
+ dataValidation.setSuppressDropDownArrow(true);
+ dataValidation.setShowErrorBox(true);
+ }
+ else
+ {
+ dataValidation.setSuppressDropDownArrow(false);
+ }
+
+ sheet.addValidationData(dataValidation);
+ // 璁剧疆hiddenSheet闅愯棌
+ wb.setSheetHidden(wb.getSheetIndex(hideSheet), true);
+ }
+
+ /**
+ * 瑙f瀽瀵煎嚭鍊� 0=鐢�,1=濂�,2=鏈煡
+ *
+ * @param propertyValue 鍙傛暟鍊�
+ * @param converterExp 缈昏瘧娉ㄨВ
+ * @param separator 鍒嗛殧绗�
+ * @return 瑙f瀽鍚庡��
+ */
+ public static String convertByExp(String propertyValue, String converterExp, String separator)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ String[] convertSource = converterExp.split(",");
+ for (String item : convertSource)
+ {
+ String[] itemArray = item.split("=");
+ if (StringUtils.containsAny(propertyValue, separator))
+ {
+ for (String value : propertyValue.split(separator))
+ {
+ if (itemArray[0].equals(value))
+ {
+ propertyString.append(itemArray[1] + separator);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (itemArray[0].equals(propertyValue))
+ {
+ return itemArray[1];
+ }
+ }
+ }
+ return StringUtils.stripEnd(propertyString.toString(), separator);
+ }
+
+ /**
+ * 鍙嶅悜瑙f瀽鍊� 鐢�=0,濂�=1,鏈煡=2
+ *
+ * @param propertyValue 鍙傛暟鍊�
+ * @param converterExp 缈昏瘧娉ㄨВ
+ * @param separator 鍒嗛殧绗�
+ * @return 瑙f瀽鍚庡��
+ */
+ public static String reverseByExp(String propertyValue, String converterExp, String separator)
+ {
+ StringBuilder propertyString = new StringBuilder();
+ String[] convertSource = converterExp.split(",");
+ for (String item : convertSource)
+ {
+ String[] itemArray = item.split("=");
+ if (StringUtils.containsAny(propertyValue, separator))
+ {
+ for (String value : propertyValue.split(separator))
+ {
+ if (itemArray[1].equals(value))
+ {
+ propertyString.append(itemArray[0] + separator);
+ break;
+ }
+ }
+ }
+ else
+ {
+ if (itemArray[1].equals(propertyValue))
+ {
+ return itemArray[0];
+ }
+ }
+ }
+ return StringUtils.stripEnd(propertyString.toString(), separator);
+ }
+
+ /**
+ * 瑙f瀽瀛楀吀鍊�
+ *
+ * @param dictValue 瀛楀吀鍊�
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param separator 鍒嗛殧绗�
+ * @return 瀛楀吀鏍囩
+ */
+ public static String convertDictByExp(String dictValue, String dictType, String separator)
+ {
+ return DictUtils.getDictLabel(dictType, dictValue, separator);
+ }
+
+ /**
+ * 鍙嶅悜瑙f瀽鍊煎瓧鍏稿��
+ *
+ * @param dictLabel 瀛楀吀鏍囩
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param separator 鍒嗛殧绗�
+ * @return 瀛楀吀鍊�
+ */
+ public static String reverseDictByExp(String dictLabel, String dictType, String separator)
+ {
+ return DictUtils.getDictValue(dictType, dictLabel, separator);
+ }
+
+ /**
+ * 鏁版嵁澶勭悊鍣�
+ *
+ * @param value 鏁版嵁鍊�
+ * @param excel 鏁版嵁娉ㄨВ
+ * @return
+ */
+ public String dataFormatHandlerAdapter(Object value, Excel excel, Cell cell)
+ {
+ try
+ {
+ Object instance = excel.handler().newInstance();
+ Method formatMethod = excel.handler().getMethod("format", new Class[] { Object.class, String[].class, Cell.class, Workbook.class });
+ value = formatMethod.invoke(instance, value, excel.args(), cell, this.wb);
+ }
+ catch (Exception e)
+ {
+ log.error("涓嶈兘鏍煎紡鍖栨暟鎹� " + excel.handler(), e.getMessage());
+ }
+ return Convert.toStr(value);
+ }
+
+ /**
+ * 鍚堣缁熻淇℃伅
+ */
+ private void addStatisticsData(Integer index, String text, Excel entity)
+ {
+ if (entity != null && entity.isStatistics())
+ {
+ Double temp = 0D;
+ if (!statistics.containsKey(index))
+ {
+ statistics.put(index, temp);
+ }
+ try
+ {
+ temp = Double.valueOf(text);
+ }
+ catch (NumberFormatException e)
+ {
+ }
+ statistics.put(index, statistics.get(index) + temp);
+ }
+ }
+
+ /**
+ * 鍒涘缓缁熻琛�
+ */
+ public void addStatisticsRow()
+ {
+ if (statistics.size() > 0)
+ {
+ Row row = sheet.createRow(sheet.getLastRowNum() + 1);
+ Set<Integer> keys = statistics.keySet();
+ Cell cell = row.createCell(0);
+ cell.setCellStyle(styles.get("total"));
+ cell.setCellValue("鍚堣");
+
+ for (Integer key : keys)
+ {
+ cell = row.createCell(key);
+ cell.setCellStyle(styles.get("total"));
+ cell.setCellValue(DOUBLE_FORMAT.format(statistics.get(key)));
+ }
+ statistics.clear();
+ }
+ }
+
+ /**
+ * 缂栫爜鏂囦欢鍚�
+ */
+ public String encodingFilename(String filename)
+ {
+ filename = UUID.randomUUID() + "_" + filename + ".xlsx";
+ return filename;
+ }
+
+ /**
+ * 鑾峰彇涓嬭浇璺緞
+ *
+ * @param filename 鏂囦欢鍚嶇О
+ */
+ public String getAbsoluteFile(String filename)
+ {
+ String downloadPath = RuoYiConfig.getDownloadPath() + filename;
+ File desc = new File(downloadPath);
+ if (!desc.getParentFile().exists())
+ {
+ desc.getParentFile().mkdirs();
+ }
+ return downloadPath;
+ }
+
+ /**
+ * 鑾峰彇bean涓殑灞炴�у��
+ *
+ * @param vo 瀹炰綋瀵硅薄
+ * @param field 瀛楁
+ * @param excel 娉ㄨВ
+ * @return 鏈�缁堢殑灞炴�у��
+ * @throws Exception
+ */
+ private Object getTargetValue(T vo, Field field, Excel excel) throws Exception
+ {
+ field.setAccessible(true);
+ Object o = field.get(vo);
+ if (StringUtils.isNotEmpty(excel.targetAttr()))
+ {
+ String target = excel.targetAttr();
+ if (target.contains("."))
+ {
+ String[] targets = target.split("[.]");
+ for (String name : targets)
+ {
+ o = getValue(o, name);
+ }
+ }
+ else
+ {
+ o = getValue(o, target);
+ }
+ }
+ return o;
+ }
+
+ /**
+ * 浠ョ被鐨勫睘鎬х殑get鏂规硶鏂规硶褰㈠紡鑾峰彇鍊�
+ *
+ * @param o
+ * @param name
+ * @return value
+ * @throws Exception
+ */
+ private Object getValue(Object o, String name) throws Exception
+ {
+ if (StringUtils.isNotNull(o) && StringUtils.isNotEmpty(name))
+ {
+ Class<?> clazz = o.getClass();
+ Field field = clazz.getDeclaredField(name);
+ field.setAccessible(true);
+ o = field.get(o);
+ }
+ return o;
+ }
+
+ /**
+ * 寰楀埌鎵�鏈夊畾涔夊瓧娈�
+ */
+ private void createExcelField()
+ {
+ this.fields = getFields();
+ this.fields = this.fields.stream().sorted(Comparator.comparing(objects -> ((Excel) objects[1]).sort())).collect(Collectors.toList());
+ this.maxHeight = getRowHeight();
+ }
+
+ /**
+ * 鑾峰彇瀛楁娉ㄨВ淇℃伅
+ */
+ public List<Object[]> getFields()
+ {
+ List<Object[]> fields = new ArrayList<Object[]>();
+ List<Field> tempFields = new ArrayList<>();
+ tempFields.addAll(Arrays.asList(clazz.getSuperclass().getDeclaredFields()));
+ tempFields.addAll(Arrays.asList(clazz.getDeclaredFields()));
+ if (StringUtils.isNotEmpty(includeFields))
+ {
+ for (Field field : tempFields)
+ {
+ if (ArrayUtils.contains(this.includeFields, field.getName()) || field.isAnnotationPresent(Excels.class))
+ {
+ addField(fields, field);
+ }
+ }
+ }
+ else if (StringUtils.isNotEmpty(excludeFields))
+ {
+ for (Field field : tempFields)
+ {
+ if (!ArrayUtils.contains(this.excludeFields, field.getName()))
+ {
+ addField(fields, field);
+ }
+ }
+ }
+ else
+ {
+ for (Field field : tempFields)
+ {
+ addField(fields, field);
+ }
+ }
+ return fields;
+ }
+
+ /**
+ * 娣诲姞瀛楁淇℃伅
+ */
+ public void addField(List<Object[]> fields, Field field)
+ {
+ // 鍗曟敞瑙�
+ if (field.isAnnotationPresent(Excel.class))
+ {
+ Excel attr = field.getAnnotation(Excel.class);
+ if (attr != null && (attr.type() == Type.ALL || attr.type() == type))
+ {
+ fields.add(new Object[] { field, attr });
+ }
+ if (Collection.class.isAssignableFrom(field.getType()))
+ {
+ subMethod = getSubMethod(field.getName(), clazz);
+ ParameterizedType pt = (ParameterizedType) field.getGenericType();
+ Class<?> subClass = (Class<?>) pt.getActualTypeArguments()[0];
+ this.subFields = FieldUtils.getFieldsListWithAnnotation(subClass, Excel.class);
+ }
+ }
+
+ // 澶氭敞瑙�
+ if (field.isAnnotationPresent(Excels.class))
+ {
+ Excels attrs = field.getAnnotation(Excels.class);
+ Excel[] excels = attrs.value();
+ for (Excel attr : excels)
+ {
+ if (StringUtils.isNotEmpty(includeFields))
+ {
+ if (ArrayUtils.contains(this.includeFields, field.getName() + "." + attr.targetAttr())
+ && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
+ {
+ fields.add(new Object[] { field, attr });
+ }
+ }
+ else
+ {
+ if (!ArrayUtils.contains(this.excludeFields, field.getName() + "." + attr.targetAttr())
+ && (attr != null && (attr.type() == Type.ALL || attr.type() == type)))
+ {
+ fields.add(new Object[] { field, attr });
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * 鏍规嵁娉ㄨВ鑾峰彇鏈�澶ц楂�
+ */
+ public short getRowHeight()
+ {
+ double maxHeight = 0;
+ for (Object[] os : this.fields)
+ {
+ Excel excel = (Excel) os[1];
+ maxHeight = Math.max(maxHeight, excel.height());
+ }
+ return (short) (maxHeight * 20);
+ }
+
+ /**
+ * 鍒涘缓涓�涓伐浣滅翱
+ */
+ public void createWorkbook()
+ {
+ this.wb = new SXSSFWorkbook(500);
+ this.sheet = wb.createSheet();
+ wb.setSheetName(0, sheetName);
+ this.styles = createStyles(wb);
+ }
+
+ /**
+ * 鍒涘缓宸ヤ綔琛�
+ *
+ * @param sheetNo sheet鏁伴噺
+ * @param index 搴忓彿
+ */
+ public void createSheet(int sheetNo, int index)
+ {
+ // 璁剧疆宸ヤ綔琛ㄧ殑鍚嶇О.
+ if (sheetNo > 1 && index > 0)
+ {
+ this.sheet = wb.createSheet();
+ this.createTitle();
+ wb.setSheetName(index, sheetName + index);
+ }
+ }
+
+ /**
+ * 鑾峰彇鍗曞厓鏍煎��
+ *
+ * @param row 鑾峰彇鐨勮
+ * @param column 鑾峰彇鍗曞厓鏍煎垪鍙�
+ * @return 鍗曞厓鏍煎��
+ */
+ public Object getCellValue(Row row, int column)
+ {
+ if (row == null)
+ {
+ return row;
+ }
+ Object val = "";
+ try
+ {
+ Cell cell = row.getCell(column);
+ if (StringUtils.isNotNull(cell))
+ {
+ if (cell.getCellType() == CellType.NUMERIC || cell.getCellType() == CellType.FORMULA)
+ {
+ val = cell.getNumericCellValue();
+ if (DateUtil.isCellDateFormatted(cell))
+ {
+ val = DateUtil.getJavaDate((Double) val); // POI Excel 鏃ユ湡鏍煎紡杞崲
+ }
+ else
+ {
+ if ((Double) val % 1 != 0)
+ {
+ val = new BigDecimal(val.toString());
+ }
+ else
+ {
+ val = new DecimalFormat("0").format(val);
+ }
+ }
+ }
+ else if (cell.getCellType() == CellType.STRING)
+ {
+ val = cell.getStringCellValue();
+ }
+ else if (cell.getCellType() == CellType.BOOLEAN)
+ {
+ val = cell.getBooleanCellValue();
+ }
+ else if (cell.getCellType() == CellType.ERROR)
+ {
+ val = cell.getErrorCellValue();
+ }
+
+ }
+ }
+ catch (Exception e)
+ {
+ return val;
+ }
+ return val;
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁鏄┖琛�
+ *
+ * @param row 鍒ゆ柇鐨勮
+ * @return
+ */
+ private boolean isRowEmpty(Row row)
+ {
+ if (row == null)
+ {
+ return true;
+ }
+ for (int i = row.getFirstCellNum(); i < row.getLastCellNum(); i++)
+ {
+ Cell cell = row.getCell(i);
+ if (cell != null && cell.getCellType() != CellType.BLANK)
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * 鑾峰彇Excel2003鍥剧墖
+ *
+ * @param sheet 褰撳墠sheet瀵硅薄
+ * @param workbook 宸ヤ綔绨垮璞�
+ * @return Map key:鍥剧墖鍗曞厓鏍肩储寮曪紙1_1锛塖tring锛寁alue:鍥剧墖娴丳ictureData
+ */
+ public static Map<String, PictureData> getSheetPictures03(HSSFSheet sheet, HSSFWorkbook workbook)
+ {
+ Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
+ List<HSSFPictureData> pictures = workbook.getAllPictures();
+ if (!pictures.isEmpty())
+ {
+ for (HSSFShape shape : sheet.getDrawingPatriarch().getChildren())
+ {
+ HSSFClientAnchor anchor = (HSSFClientAnchor) shape.getAnchor();
+ if (shape instanceof HSSFPicture)
+ {
+ HSSFPicture pic = (HSSFPicture) shape;
+ int pictureIndex = pic.getPictureIndex() - 1;
+ HSSFPictureData picData = pictures.get(pictureIndex);
+ String picIndex = anchor.getRow1() + "_" + anchor.getCol1();
+ sheetIndexPicMap.put(picIndex, picData);
+ }
+ }
+ return sheetIndexPicMap;
+ }
+ else
+ {
+ return sheetIndexPicMap;
+ }
+ }
+
+ /**
+ * 鑾峰彇Excel2007鍥剧墖
+ *
+ * @param sheet 褰撳墠sheet瀵硅薄
+ * @param workbook 宸ヤ綔绨垮璞�
+ * @return Map key:鍥剧墖鍗曞厓鏍肩储寮曪紙1_1锛塖tring锛寁alue:鍥剧墖娴丳ictureData
+ */
+ public static Map<String, PictureData> getSheetPictures07(XSSFSheet sheet, XSSFWorkbook workbook)
+ {
+ Map<String, PictureData> sheetIndexPicMap = new HashMap<String, PictureData>();
+ for (POIXMLDocumentPart dr : sheet.getRelations())
+ {
+ if (dr instanceof XSSFDrawing)
+ {
+ XSSFDrawing drawing = (XSSFDrawing) dr;
+ List<XSSFShape> shapes = drawing.getShapes();
+ for (XSSFShape shape : shapes)
+ {
+ if (shape instanceof XSSFPicture)
+ {
+ XSSFPicture pic = (XSSFPicture) shape;
+ XSSFClientAnchor anchor = pic.getPreferredSize();
+ CTMarker ctMarker = anchor.getFrom();
+ String picIndex = ctMarker.getRow() + "_" + ctMarker.getCol();
+ sheetIndexPicMap.put(picIndex, pic.getPictureData());
+ }
+ }
+ }
+ }
+ return sheetIndexPicMap;
+ }
+
+ /**
+ * 鏍煎紡鍖栦笉鍚岀被鍨嬬殑鏃ユ湡瀵硅薄
+ *
+ * @param dateFormat 鏃ユ湡鏍煎紡
+ * @param val 琚牸寮忓寲鐨勬棩鏈熷璞�
+ * @return 鏍煎紡鍖栧悗鐨勬棩鏈熷瓧绗�
+ */
+ public String parseDateToStr(String dateFormat, Object val)
+ {
+ if (val == null)
+ {
+ return "";
+ }
+ String str;
+ if (val instanceof Date)
+ {
+ str = DateUtils.parseDateToStr(dateFormat, (Date) val);
+ }
+ else if (val instanceof LocalDateTime)
+ {
+ str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDateTime) val));
+ }
+ else if (val instanceof LocalDate)
+ {
+ str = DateUtils.parseDateToStr(dateFormat, DateUtils.toDate((LocalDate) val));
+ }
+ else
+ {
+ str = val.toString();
+ }
+ return str;
+ }
+
+ /**
+ * 鏄惁鏈夊璞$殑瀛愬垪琛�
+ */
+ public boolean isSubList()
+ {
+ return StringUtils.isNotNull(subFields) && subFields.size() > 0;
+ }
+
+ /**
+ * 鏄惁鏈夊璞$殑瀛愬垪琛紝闆嗗悎涓嶄负绌�
+ */
+ public boolean isSubListValue(T vo)
+ {
+ return StringUtils.isNotNull(subFields) && subFields.size() > 0 && StringUtils.isNotNull(getListCellValue(vo)) && getListCellValue(vo).size() > 0;
+ }
+
+ /**
+ * 鑾峰彇闆嗗悎鐨勫��
+ */
+ public Collection<?> getListCellValue(Object obj)
+ {
+ Object value;
+ try
+ {
+ value = subMethod.invoke(obj, new Object[] {});
+ }
+ catch (Exception e)
+ {
+ return new ArrayList<Object>();
+ }
+ return (Collection<?>) value;
+ }
+
+ /**
+ * 鑾峰彇瀵硅薄鐨勫瓙鍒楄〃鏂规硶
+ *
+ * @param name 鍚嶇О
+ * @param pojoClass 绫诲璞�
+ * @return 瀛愬垪琛ㄦ柟娉�
+ */
+ public Method getSubMethod(String name, Class<?> pojoClass)
+ {
+ StringBuffer getMethodName = new StringBuffer("get");
+ getMethodName.append(name.substring(0, 1).toUpperCase());
+ getMethodName.append(name.substring(1));
+ Method method = null;
+ try
+ {
+ method = pojoClass.getMethod(getMethodName.toString(), new Class[] {});
+ }
+ catch (Exception e)
+ {
+ log.error("鑾峰彇瀵硅薄寮傚父{}", e.getMessage());
+ }
+ return method;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
new file mode 100644
index 0000000..b19953e
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/reflect/ReflectUtils.java
@@ -0,0 +1,410 @@
+package com.ruoyi.common.utils.reflect;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.Date;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.Validate;
+import org.apache.poi.ss.usermodel.DateUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.DateUtils;
+
+/**
+ * 鍙嶅皠宸ュ叿绫�. 鎻愪緵璋冪敤getter/setter鏂规硶, 璁块棶绉佹湁鍙橀噺, 璋冪敤绉佹湁鏂规硶, 鑾峰彇娉涘瀷绫诲瀷Class, 琚獳OP杩囩殑鐪熷疄绫荤瓑宸ュ叿鍑芥暟.
+ *
+ * @author ruoyi
+ */
+@SuppressWarnings("rawtypes")
+public class ReflectUtils
+{
+ private static final String SETTER_PREFIX = "set";
+
+ private static final String GETTER_PREFIX = "get";
+
+ private static final String CGLIB_CLASS_SEPARATOR = "$$";
+
+ private static Logger logger = LoggerFactory.getLogger(ReflectUtils.class);
+
+ /**
+ * 璋冪敤Getter鏂规硶.
+ * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> E invokeGetter(Object obj, String propertyName)
+ {
+ Object object = obj;
+ for (String name : StringUtils.split(propertyName, "."))
+ {
+ String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(name);
+ object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+ }
+ return (E) object;
+ }
+
+ /**
+ * 璋冪敤Setter鏂规硶, 浠呭尮閰嶆柟娉曞悕銆�
+ * 鏀寔澶氱骇锛屽锛氬璞″悕.瀵硅薄鍚�.鏂规硶
+ */
+ public static <E> void invokeSetter(Object obj, String propertyName, E value)
+ {
+ Object object = obj;
+ String[] names = StringUtils.split(propertyName, ".");
+ for (int i = 0; i < names.length; i++)
+ {
+ if (i < names.length - 1)
+ {
+ String getterMethodName = GETTER_PREFIX + StringUtils.capitalize(names[i]);
+ object = invokeMethod(object, getterMethodName, new Class[] {}, new Object[] {});
+ }
+ else
+ {
+ String setterMethodName = SETTER_PREFIX + StringUtils.capitalize(names[i]);
+ invokeMethodByName(object, setterMethodName, new Object[] { value });
+ }
+ }
+ }
+
+ /**
+ * 鐩存帴璇诲彇瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噂etter鍑芥暟.
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> E getFieldValue(final Object obj, final String fieldName)
+ {
+ Field field = getAccessibleField(obj, fieldName);
+ if (field == null)
+ {
+ logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+ return null;
+ }
+ E result = null;
+ try
+ {
+ result = (E) field.get(obj);
+ }
+ catch (IllegalAccessException e)
+ {
+ logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父{}", e.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * 鐩存帴璁剧疆瀵硅薄灞炴�у��, 鏃犺private/protected淇グ绗�, 涓嶇粡杩噑etter鍑芥暟.
+ */
+ public static <E> void setFieldValue(final Object obj, final String fieldName, final E value)
+ {
+ Field field = getAccessibleField(obj, fieldName);
+ if (field == null)
+ {
+ // throw new IllegalArgumentException("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+ logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + fieldName + "] 瀛楁 ");
+ return;
+ }
+ try
+ {
+ field.set(obj, value);
+ }
+ catch (IllegalAccessException e)
+ {
+ logger.error("涓嶅彲鑳芥姏鍑虹殑寮傚父: {}", e.getMessage());
+ }
+ }
+
+ /**
+ * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗�.
+ * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethod()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+ * 鍚屾椂鍖归厤鏂规硶鍚�+鍙傛暟绫诲瀷锛�
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> E invokeMethod(final Object obj, final String methodName, final Class<?>[] parameterTypes,
+ final Object[] args)
+ {
+ if (obj == null || methodName == null)
+ {
+ return null;
+ }
+ Method method = getAccessibleMethod(obj, methodName, parameterTypes);
+ if (method == null)
+ {
+ logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+ return null;
+ }
+ try
+ {
+ return (E) method.invoke(obj, args);
+ }
+ catch (Exception e)
+ {
+ String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+ throw convertReflectionExceptionToUnchecked(msg, e);
+ }
+ }
+
+ /**
+ * 鐩存帴璋冪敤瀵硅薄鏂规硶, 鏃犺private/protected淇グ绗︼紝
+ * 鐢ㄤ簬涓�娆℃�ц皟鐢ㄧ殑鎯呭喌锛屽惁鍒欏簲浣跨敤getAccessibleMethodByName()鍑芥暟鑾峰緱Method鍚庡弽澶嶈皟鐢�.
+ * 鍙尮閰嶅嚱鏁板悕锛屽鏋滄湁澶氫釜鍚屽悕鍑芥暟璋冪敤绗竴涓��
+ */
+ @SuppressWarnings("unchecked")
+ public static <E> E invokeMethodByName(final Object obj, final String methodName, final Object[] args)
+ {
+ Method method = getAccessibleMethodByName(obj, methodName, args.length);
+ if (method == null)
+ {
+ // 濡傛灉涓虹┖涓嶆姤閿欙紝鐩存帴杩斿洖绌恒��
+ logger.debug("鍦� [" + obj.getClass() + "] 涓紝娌℃湁鎵惧埌 [" + methodName + "] 鏂规硶 ");
+ return null;
+ }
+ try
+ {
+ // 绫诲瀷杞崲锛堝皢鍙傛暟鏁版嵁绫诲瀷杞崲涓虹洰鏍囨柟娉曞弬鏁扮被鍨嬶級
+ Class<?>[] cs = method.getParameterTypes();
+ for (int i = 0; i < cs.length; i++)
+ {
+ if (args[i] != null && !args[i].getClass().equals(cs[i]))
+ {
+ if (cs[i] == String.class)
+ {
+ args[i] = Convert.toStr(args[i]);
+ if (StringUtils.endsWith((String) args[i], ".0"))
+ {
+ args[i] = StringUtils.substringBefore((String) args[i], ".0");
+ }
+ }
+ else if (cs[i] == Integer.class)
+ {
+ args[i] = Convert.toInt(args[i]);
+ }
+ else if (cs[i] == Long.class)
+ {
+ args[i] = Convert.toLong(args[i]);
+ }
+ else if (cs[i] == Double.class)
+ {
+ args[i] = Convert.toDouble(args[i]);
+ }
+ else if (cs[i] == Float.class)
+ {
+ args[i] = Convert.toFloat(args[i]);
+ }
+ else if (cs[i] == Date.class)
+ {
+ if (args[i] instanceof String)
+ {
+ args[i] = DateUtils.parseDate(args[i]);
+ }
+ else
+ {
+ args[i] = DateUtil.getJavaDate((Double) args[i]);
+ }
+ }
+ else if (cs[i] == boolean.class || cs[i] == Boolean.class)
+ {
+ args[i] = Convert.toBool(args[i]);
+ }
+ }
+ }
+ return (E) method.invoke(obj, args);
+ }
+ catch (Exception e)
+ {
+ String msg = "method: " + method + ", obj: " + obj + ", args: " + args + "";
+ throw convertReflectionExceptionToUnchecked(msg, e);
+ }
+ }
+
+ /**
+ * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredField, 骞跺己鍒惰缃负鍙闂�.
+ * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+ */
+ public static Field getAccessibleField(final Object obj, final String fieldName)
+ {
+ // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+ if (obj == null)
+ {
+ return null;
+ }
+ Validate.notBlank(fieldName, "fieldName can't be blank");
+ for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass())
+ {
+ try
+ {
+ Field field = superClass.getDeclaredField(fieldName);
+ makeAccessible(field);
+ return field;
+ }
+ catch (NoSuchFieldException e)
+ {
+ continue;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+ * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+ * 鍖归厤鍑芥暟鍚�+鍙傛暟绫诲瀷銆�
+ * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+ */
+ public static Method getAccessibleMethod(final Object obj, final String methodName,
+ final Class<?>... parameterTypes)
+ {
+ // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+ if (obj == null)
+ {
+ return null;
+ }
+ Validate.notBlank(methodName, "methodName can't be blank");
+ for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+ {
+ try
+ {
+ Method method = searchType.getDeclaredMethod(methodName, parameterTypes);
+ makeAccessible(method);
+ return method;
+ }
+ catch (NoSuchMethodException e)
+ {
+ continue;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 寰幆鍚戜笂杞瀷, 鑾峰彇瀵硅薄鐨凞eclaredMethod,骞跺己鍒惰缃负鍙闂�.
+ * 濡傚悜涓婅浆鍨嬪埌Object浠嶆棤娉曟壘鍒�, 杩斿洖null.
+ * 鍙尮閰嶅嚱鏁板悕銆�
+ * 鐢ㄤ簬鏂规硶闇�瑕佽澶氭璋冪敤鐨勬儏鍐�. 鍏堜娇鐢ㄦ湰鍑芥暟鍏堝彇寰桵ethod,鐒跺悗璋冪敤Method.invoke(Object obj, Object... args)
+ */
+ public static Method getAccessibleMethodByName(final Object obj, final String methodName, int argsNum)
+ {
+ // 涓虹┖涓嶆姤閿欍�傜洿鎺ヨ繑鍥� null
+ if (obj == null)
+ {
+ return null;
+ }
+ Validate.notBlank(methodName, "methodName can't be blank");
+ for (Class<?> searchType = obj.getClass(); searchType != Object.class; searchType = searchType.getSuperclass())
+ {
+ Method[] methods = searchType.getDeclaredMethods();
+ for (Method method : methods)
+ {
+ if (method.getName().equals(methodName) && method.getParameterTypes().length == argsNum)
+ {
+ makeAccessible(method);
+ return method;
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 鏀瑰彉private/protected鐨勬柟娉曚负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+ */
+ public static void makeAccessible(Method method)
+ {
+ if ((!Modifier.isPublic(method.getModifiers()) || !Modifier.isPublic(method.getDeclaringClass().getModifiers()))
+ && !method.isAccessible())
+ {
+ method.setAccessible(true);
+ }
+ }
+
+ /**
+ * 鏀瑰彉private/protected鐨勬垚鍛樺彉閲忎负public锛屽敖閲忎笉璋冪敤瀹為檯鏀瑰姩鐨勮鍙ワ紝閬垮厤JDK鐨凷ecurityManager鎶辨�ㄣ��
+ */
+ public static void makeAccessible(Field field)
+ {
+ if ((!Modifier.isPublic(field.getModifiers()) || !Modifier.isPublic(field.getDeclaringClass().getModifiers())
+ || Modifier.isFinal(field.getModifiers())) && !field.isAccessible())
+ {
+ field.setAccessible(true);
+ }
+ }
+
+ /**
+ * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑娉涘瀷鍙傛暟鐨勭被鍨�, 娉ㄦ剰娉涘瀷蹇呴』瀹氫箟鍦ㄧ埗绫诲
+ * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> Class<T> getClassGenricType(final Class clazz)
+ {
+ return getClassGenricType(clazz, 0);
+ }
+
+ /**
+ * 閫氳繃鍙嶅皠, 鑾峰緱Class瀹氫箟涓0鏄庣殑鐖剁被鐨勬硾鍨嬪弬鏁扮殑绫诲瀷.
+ * 濡傛棤娉曟壘鍒�, 杩斿洖Object.class.
+ */
+ public static Class getClassGenricType(final Class clazz, final int index)
+ {
+ Type genType = clazz.getGenericSuperclass();
+
+ if (!(genType instanceof ParameterizedType))
+ {
+ logger.debug(clazz.getSimpleName() + "'s superclass not ParameterizedType");
+ return Object.class;
+ }
+
+ Type[] params = ((ParameterizedType) genType).getActualTypeArguments();
+
+ if (index >= params.length || index < 0)
+ {
+ logger.debug("Index: " + index + ", Size of " + clazz.getSimpleName() + "'s Parameterized Type: "
+ + params.length);
+ return Object.class;
+ }
+ if (!(params[index] instanceof Class))
+ {
+ logger.debug(clazz.getSimpleName() + " not set the actual class on superclass generic parameter");
+ return Object.class;
+ }
+
+ return (Class) params[index];
+ }
+
+ public static Class<?> getUserClass(Object instance)
+ {
+ if (instance == null)
+ {
+ throw new RuntimeException("Instance must not be null");
+ }
+ Class clazz = instance.getClass();
+ if (clazz != null && clazz.getName().contains(CGLIB_CLASS_SEPARATOR))
+ {
+ Class<?> superClass = clazz.getSuperclass();
+ if (superClass != null && !Object.class.equals(superClass))
+ {
+ return superClass;
+ }
+ }
+ return clazz;
+
+ }
+
+ /**
+ * 灏嗗弽灏勬椂鐨刢hecked exception杞崲涓簎nchecked exception.
+ */
+ public static RuntimeException convertReflectionExceptionToUnchecked(String msg, Exception e)
+ {
+ if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
+ || e instanceof NoSuchMethodException)
+ {
+ return new IllegalArgumentException(msg, e);
+ }
+ else if (e instanceof InvocationTargetException)
+ {
+ return new RuntimeException(msg, ((InvocationTargetException) e).getTargetException());
+ }
+ return new RuntimeException(msg, e);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java
new file mode 100644
index 0000000..ca1cd92
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Base64.java
@@ -0,0 +1,291 @@
+package com.ruoyi.common.utils.sign;
+
+/**
+ * Base64宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public final class Base64
+{
+ static private final int BASELENGTH = 128;
+ static private final int LOOKUPLENGTH = 64;
+ static private final int TWENTYFOURBITGROUP = 24;
+ static private final int EIGHTBIT = 8;
+ static private final int SIXTEENBIT = 16;
+ static private final int FOURBYTE = 4;
+ static private final int SIGN = -128;
+ static private final char PAD = '=';
+ static final private byte[] base64Alphabet = new byte[BASELENGTH];
+ static final private char[] lookUpBase64Alphabet = new char[LOOKUPLENGTH];
+
+ static
+ {
+ for (int i = 0; i < BASELENGTH; ++i)
+ {
+ base64Alphabet[i] = -1;
+ }
+ for (int i = 'Z'; i >= 'A'; i--)
+ {
+ base64Alphabet[i] = (byte) (i - 'A');
+ }
+ for (int i = 'z'; i >= 'a'; i--)
+ {
+ base64Alphabet[i] = (byte) (i - 'a' + 26);
+ }
+
+ for (int i = '9'; i >= '0'; i--)
+ {
+ base64Alphabet[i] = (byte) (i - '0' + 52);
+ }
+
+ base64Alphabet['+'] = 62;
+ base64Alphabet['/'] = 63;
+
+ for (int i = 0; i <= 25; i++)
+ {
+ lookUpBase64Alphabet[i] = (char) ('A' + i);
+ }
+
+ for (int i = 26, j = 0; i <= 51; i++, j++)
+ {
+ lookUpBase64Alphabet[i] = (char) ('a' + j);
+ }
+
+ for (int i = 52, j = 0; i <= 61; i++, j++)
+ {
+ lookUpBase64Alphabet[i] = (char) ('0' + j);
+ }
+ lookUpBase64Alphabet[62] = (char) '+';
+ lookUpBase64Alphabet[63] = (char) '/';
+ }
+
+ private static boolean isWhiteSpace(char octect)
+ {
+ return (octect == 0x20 || octect == 0xd || octect == 0xa || octect == 0x9);
+ }
+
+ private static boolean isPad(char octect)
+ {
+ return (octect == PAD);
+ }
+
+ private static boolean isData(char octect)
+ {
+ return (octect < BASELENGTH && base64Alphabet[octect] != -1);
+ }
+
+ /**
+ * Encodes hex octects into Base64
+ *
+ * @param binaryData Array containing binaryData
+ * @return Encoded Base64 array
+ */
+ public static String encode(byte[] binaryData)
+ {
+ if (binaryData == null)
+ {
+ return null;
+ }
+
+ int lengthDataBits = binaryData.length * EIGHTBIT;
+ if (lengthDataBits == 0)
+ {
+ return "";
+ }
+
+ int fewerThan24bits = lengthDataBits % TWENTYFOURBITGROUP;
+ int numberTriplets = lengthDataBits / TWENTYFOURBITGROUP;
+ int numberQuartet = fewerThan24bits != 0 ? numberTriplets + 1 : numberTriplets;
+ char encodedData[] = null;
+
+ encodedData = new char[numberQuartet * 4];
+
+ byte k = 0, l = 0, b1 = 0, b2 = 0, b3 = 0;
+
+ int encodedIndex = 0;
+ int dataIndex = 0;
+
+ for (int i = 0; i < numberTriplets; i++)
+ {
+ b1 = binaryData[dataIndex++];
+ b2 = binaryData[dataIndex++];
+ b3 = binaryData[dataIndex++];
+
+ l = (byte) (b2 & 0x0f);
+ k = (byte) (b1 & 0x03);
+
+ byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+ byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+ byte val3 = ((b3 & SIGN) == 0) ? (byte) (b3 >> 6) : (byte) ((b3) >> 6 ^ 0xfc);
+
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[(l << 2) | val3];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[b3 & 0x3f];
+ }
+
+ // form integral number of 6-bit groups
+ if (fewerThan24bits == EIGHTBIT)
+ {
+ b1 = binaryData[dataIndex];
+ k = (byte) (b1 & 0x03);
+ byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[k << 4];
+ encodedData[encodedIndex++] = PAD;
+ encodedData[encodedIndex++] = PAD;
+ }
+ else if (fewerThan24bits == SIXTEENBIT)
+ {
+ b1 = binaryData[dataIndex];
+ b2 = binaryData[dataIndex + 1];
+ l = (byte) (b2 & 0x0f);
+ k = (byte) (b1 & 0x03);
+
+ byte val1 = ((b1 & SIGN) == 0) ? (byte) (b1 >> 2) : (byte) ((b1) >> 2 ^ 0xc0);
+ byte val2 = ((b2 & SIGN) == 0) ? (byte) (b2 >> 4) : (byte) ((b2) >> 4 ^ 0xf0);
+
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[val1];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[val2 | (k << 4)];
+ encodedData[encodedIndex++] = lookUpBase64Alphabet[l << 2];
+ encodedData[encodedIndex++] = PAD;
+ }
+ return new String(encodedData);
+ }
+
+ /**
+ * Decodes Base64 data into octects
+ *
+ * @param encoded string containing Base64 data
+ * @return Array containind decoded data.
+ */
+ public static byte[] decode(String encoded)
+ {
+ if (encoded == null)
+ {
+ return null;
+ }
+
+ char[] base64Data = encoded.toCharArray();
+ // remove white spaces
+ int len = removeWhiteSpace(base64Data);
+
+ if (len % FOURBYTE != 0)
+ {
+ return null;// should be divisible by four
+ }
+
+ int numberQuadruple = (len / FOURBYTE);
+
+ if (numberQuadruple == 0)
+ {
+ return new byte[0];
+ }
+
+ byte decodedData[] = null;
+ byte b1 = 0, b2 = 0, b3 = 0, b4 = 0;
+ char d1 = 0, d2 = 0, d3 = 0, d4 = 0;
+
+ int i = 0;
+ int encodedIndex = 0;
+ int dataIndex = 0;
+ decodedData = new byte[(numberQuadruple) * 3];
+
+ for (; i < numberQuadruple - 1; i++)
+ {
+
+ if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++]))
+ || !isData((d3 = base64Data[dataIndex++])) || !isData((d4 = base64Data[dataIndex++])))
+ {
+ return null;
+ } // if found "no data" just return null
+
+ b1 = base64Alphabet[d1];
+ b2 = base64Alphabet[d2];
+ b3 = base64Alphabet[d3];
+ b4 = base64Alphabet[d4];
+
+ decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+ decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+ decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+ }
+
+ if (!isData((d1 = base64Data[dataIndex++])) || !isData((d2 = base64Data[dataIndex++])))
+ {
+ return null;// if found "no data" just return null
+ }
+
+ b1 = base64Alphabet[d1];
+ b2 = base64Alphabet[d2];
+
+ d3 = base64Data[dataIndex++];
+ d4 = base64Data[dataIndex++];
+ if (!isData((d3)) || !isData((d4)))
+ {// Check if they are PAD characters
+ if (isPad(d3) && isPad(d4))
+ {
+ if ((b2 & 0xf) != 0)// last 4 bits should be zero
+ {
+ return null;
+ }
+ byte[] tmp = new byte[i * 3 + 1];
+ System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+ tmp[encodedIndex] = (byte) (b1 << 2 | b2 >> 4);
+ return tmp;
+ }
+ else if (!isPad(d3) && isPad(d4))
+ {
+ b3 = base64Alphabet[d3];
+ if ((b3 & 0x3) != 0)// last 2 bits should be zero
+ {
+ return null;
+ }
+ byte[] tmp = new byte[i * 3 + 2];
+ System.arraycopy(decodedData, 0, tmp, 0, i * 3);
+ tmp[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+ tmp[encodedIndex] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+ return tmp;
+ }
+ else
+ {
+ return null;
+ }
+ }
+ else
+ { // No PAD e.g 3cQl
+ b3 = base64Alphabet[d3];
+ b4 = base64Alphabet[d4];
+ decodedData[encodedIndex++] = (byte) (b1 << 2 | b2 >> 4);
+ decodedData[encodedIndex++] = (byte) (((b2 & 0xf) << 4) | ((b3 >> 2) & 0xf));
+ decodedData[encodedIndex++] = (byte) (b3 << 6 | b4);
+
+ }
+ return decodedData;
+ }
+
+ /**
+ * remove WhiteSpace from MIME containing encoded Base64 data.
+ *
+ * @param data the byte array of base64 data (with WS)
+ * @return the new length
+ */
+ private static int removeWhiteSpace(char[] data)
+ {
+ if (data == null)
+ {
+ return 0;
+ }
+
+ // count characters that's not whitespace
+ int newSize = 0;
+ int len = data.length;
+ for (int i = 0; i < len; i++)
+ {
+ if (!isWhiteSpace(data[i]))
+ {
+ data[newSize++] = data[i];
+ }
+ }
+ return newSize;
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
new file mode 100644
index 0000000..c1c58db
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sign/Md5Utils.java
@@ -0,0 +1,67 @@
+package com.ruoyi.common.utils.sign;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Md5鍔犲瘑鏂规硶
+ *
+ * @author ruoyi
+ */
+public class Md5Utils
+{
+ private static final Logger log = LoggerFactory.getLogger(Md5Utils.class);
+
+ private static byte[] md5(String s)
+ {
+ MessageDigest algorithm;
+ try
+ {
+ algorithm = MessageDigest.getInstance("MD5");
+ algorithm.reset();
+ algorithm.update(s.getBytes("UTF-8"));
+ byte[] messageDigest = algorithm.digest();
+ return messageDigest;
+ }
+ catch (Exception e)
+ {
+ log.error("MD5 Error...", e);
+ }
+ return null;
+ }
+
+ private static final String toHex(byte hash[])
+ {
+ if (hash == null)
+ {
+ return null;
+ }
+ StringBuffer buf = new StringBuffer(hash.length * 2);
+ int i;
+
+ for (i = 0; i < hash.length; i++)
+ {
+ if ((hash[i] & 0xff) < 0x10)
+ {
+ buf.append("0");
+ }
+ buf.append(Long.toString(hash[i] & 0xff, 16));
+ }
+ return buf.toString();
+ }
+
+ public static String hash(String s)
+ {
+ try
+ {
+ return new String(toHex(md5(s)).getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8);
+ }
+ catch (Exception e)
+ {
+ log.error("not supported charset...{}", e);
+ return s;
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java
new file mode 100644
index 0000000..f290ec3
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/spring/SpringUtils.java
@@ -0,0 +1,158 @@
+package com.ruoyi.common.utils.spring;
+
+import org.springframework.aop.framework.AopContext;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.NoSuchBeanDefinitionException;
+import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
+import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * spring宸ュ叿绫� 鏂逛究鍦ㄩ潪spring绠$悊鐜涓幏鍙朾ean
+ *
+ * @author ruoyi
+ */
+@Component
+public final class SpringUtils implements BeanFactoryPostProcessor, ApplicationContextAware
+{
+ /** Spring搴旂敤涓婁笅鏂囩幆澧� */
+ private static ConfigurableListableBeanFactory beanFactory;
+
+ private static ApplicationContext applicationContext;
+
+ @Override
+ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException
+ {
+ SpringUtils.beanFactory = beanFactory;
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
+ {
+ SpringUtils.applicationContext = applicationContext;
+ }
+
+ /**
+ * 鑾峰彇瀵硅薄
+ *
+ * @param name
+ * @return Object 涓�涓互鎵�缁欏悕瀛楁敞鍐岀殑bean鐨勫疄渚�
+ * @throws org.springframework.beans.BeansException
+ *
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getBean(String name) throws BeansException
+ {
+ return (T) beanFactory.getBean(name);
+ }
+
+ /**
+ * 鑾峰彇绫诲瀷涓簉equiredType鐨勫璞�
+ *
+ * @param clz
+ * @return
+ * @throws org.springframework.beans.BeansException
+ *
+ */
+ public static <T> T getBean(Class<T> clz) throws BeansException
+ {
+ T result = (T) beanFactory.getBean(clz);
+ return result;
+ }
+
+ /**
+ * 濡傛灉BeanFactory鍖呭惈涓�涓笌鎵�缁欏悕绉板尮閰嶇殑bean瀹氫箟锛屽垯杩斿洖true
+ *
+ * @param name
+ * @return boolean
+ */
+ public static boolean containsBean(String name)
+ {
+ return beanFactory.containsBean(name);
+ }
+
+ /**
+ * 鍒ゆ柇浠ョ粰瀹氬悕瀛楁敞鍐岀殑bean瀹氫箟鏄竴涓猻ingleton杩樻槸涓�涓猵rototype銆� 濡傛灉涓庣粰瀹氬悕瀛楃浉搴旂殑bean瀹氫箟娌℃湁琚壘鍒帮紝灏嗕細鎶涘嚭涓�涓紓甯革紙NoSuchBeanDefinitionException锛�
+ *
+ * @param name
+ * @return boolean
+ * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+ *
+ */
+ public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException
+ {
+ return beanFactory.isSingleton(name);
+ }
+
+ /**
+ * @param name
+ * @return Class 娉ㄥ唽瀵硅薄鐨勭被鍨�
+ * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+ *
+ */
+ public static Class<?> getType(String name) throws NoSuchBeanDefinitionException
+ {
+ return beanFactory.getType(name);
+ }
+
+ /**
+ * 濡傛灉缁欏畾鐨刡ean鍚嶅瓧鍦╞ean瀹氫箟涓湁鍒悕锛屽垯杩斿洖杩欎簺鍒悕
+ *
+ * @param name
+ * @return
+ * @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
+ *
+ */
+ public static String[] getAliases(String name) throws NoSuchBeanDefinitionException
+ {
+ return beanFactory.getAliases(name);
+ }
+
+ /**
+ * 鑾峰彇aop浠g悊瀵硅薄
+ *
+ * @param invoker
+ * @return
+ */
+ @SuppressWarnings("unchecked")
+ public static <T> T getAopProxy(T invoker)
+ {
+ return (T) AopContext.currentProxy();
+ }
+
+ /**
+ * 鑾峰彇褰撳墠鐨勭幆澧冮厤缃紝鏃犻厤缃繑鍥瀗ull
+ *
+ * @return 褰撳墠鐨勭幆澧冮厤缃�
+ */
+ public static String[] getActiveProfiles()
+ {
+ return applicationContext.getEnvironment().getActiveProfiles();
+ }
+
+ /**
+ * 鑾峰彇褰撳墠鐨勭幆澧冮厤缃紝褰撴湁澶氫釜鐜閰嶇疆鏃讹紝鍙幏鍙栫涓�涓�
+ *
+ * @return 褰撳墠鐨勭幆澧冮厤缃�
+ */
+ public static String getActiveProfile()
+ {
+ final String[] activeProfiles = getActiveProfiles();
+ return StringUtils.isNotEmpty(activeProfiles) ? activeProfiles[0] : null;
+ }
+
+ /**
+ * 鑾峰彇閰嶇疆鏂囦欢涓殑鍊�
+ *
+ * @param key 閰嶇疆鏂囦欢鐨刱ey
+ * @return 褰撳墠鐨勯厤缃枃浠剁殑鍊�
+ *
+ */
+ public static String getRequiredProperty(String key)
+ {
+ return applicationContext.getEnvironment().getRequiredProperty(key);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
new file mode 100644
index 0000000..48720dc
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/sql/SqlUtil.java
@@ -0,0 +1,70 @@
+package com.ruoyi.common.utils.sql;
+
+import com.ruoyi.common.exception.UtilException;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * sql鎿嶄綔宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class SqlUtil
+{
+ /**
+ * 瀹氫箟甯哥敤鐨� sql鍏抽敭瀛�
+ */
+ public static String SQL_REGEX = "\u000B|and |extractvalue|updatexml|sleep|exec |insert |select |delete |update |drop |count |chr |mid |master |truncate |char |declare |or |union |like |+|/*|user()";
+
+ /**
+ * 浠呮敮鎸佸瓧姣嶃�佹暟瀛椼�佷笅鍒掔嚎銆佺┖鏍笺�侀�楀彿銆佸皬鏁扮偣锛堟敮鎸佸涓瓧娈垫帓搴忥級
+ */
+ public static String SQL_PATTERN = "[a-zA-Z0-9_\\ \\,\\.]+";
+
+ /**
+ * 闄愬埗orderBy鏈�澶ч暱搴�
+ */
+ private static final int ORDER_BY_MAX_LENGTH = 500;
+
+ /**
+ * 妫�鏌ュ瓧绗︼紝闃叉娉ㄥ叆缁曡繃
+ */
+ public static String escapeOrderBySql(String value)
+ {
+ if (StringUtils.isNotEmpty(value) && !isValidOrderBySql(value))
+ {
+ throw new UtilException("鍙傛暟涓嶇鍚堣鑼冿紝涓嶈兘杩涜鏌ヨ");
+ }
+ if (StringUtils.length(value) > ORDER_BY_MAX_LENGTH)
+ {
+ throw new UtilException("鍙傛暟宸茶秴杩囨渶澶ч檺鍒讹紝涓嶈兘杩涜鏌ヨ");
+ }
+ return value;
+ }
+
+ /**
+ * 楠岃瘉 order by 璇硶鏄惁绗﹀悎瑙勮寖
+ */
+ public static boolean isValidOrderBySql(String value)
+ {
+ return value.matches(SQL_PATTERN);
+ }
+
+ /**
+ * SQL鍏抽敭瀛楁鏌�
+ */
+ public static void filterKeyword(String value)
+ {
+ if (StringUtils.isEmpty(value))
+ {
+ return;
+ }
+ String[] sqlKeywords = StringUtils.split(SQL_REGEX, "\\|");
+ for (String sqlKeyword : sqlKeywords)
+ {
+ if (StringUtils.indexOfIgnoreCase(value, sqlKeyword) > -1)
+ {
+ throw new UtilException("鍙傛暟瀛樺湪SQL娉ㄥ叆椋庨櫓");
+ }
+ }
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java
new file mode 100644
index 0000000..2c84427
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/IdUtils.java
@@ -0,0 +1,49 @@
+package com.ruoyi.common.utils.uuid;
+
+/**
+ * ID鐢熸垚鍣ㄥ伐鍏风被
+ *
+ * @author ruoyi
+ */
+public class IdUtils
+{
+ /**
+ * 鑾峰彇闅忔満UUID
+ *
+ * @return 闅忔満UUID
+ */
+ public static String randomUUID()
+ {
+ return UUID.randomUUID().toString();
+ }
+
+ /**
+ * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+ *
+ * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+ */
+ public static String simpleUUID()
+ {
+ return UUID.randomUUID().toString(true);
+ }
+
+ /**
+ * 鑾峰彇闅忔満UUID锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+ *
+ * @return 闅忔満UUID
+ */
+ public static String fastUUID()
+ {
+ return UUID.fastUUID().toString();
+ }
+
+ /**
+ * 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎锛屼娇鐢ㄦ�ц兘鏇村ソ鐨凾hreadLocalRandom鐢熸垚UUID
+ *
+ * @return 绠�鍖栫殑UUID锛屽幓鎺変簡妯嚎
+ */
+ public static String fastSimpleUUID()
+ {
+ return UUID.fastUUID().toString(true);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java
new file mode 100644
index 0000000..bf99611
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/Seq.java
@@ -0,0 +1,86 @@
+package com.ruoyi.common.utils.uuid;
+
+import java.util.concurrent.atomic.AtomicInteger;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * @author ruoyi 搴忓垪鐢熸垚绫�
+ */
+public class Seq
+{
+ // 閫氱敤搴忓垪绫诲瀷
+ public static final String commSeqType = "COMMON";
+
+ // 涓婁紶搴忓垪绫诲瀷
+ public static final String uploadSeqType = "UPLOAD";
+
+ // 閫氱敤鎺ュ彛搴忓垪鏁�
+ private static AtomicInteger commSeq = new AtomicInteger(1);
+
+ // 涓婁紶鎺ュ彛搴忓垪鏁�
+ private static AtomicInteger uploadSeq = new AtomicInteger(1);
+
+ // 鏈哄櫒鏍囪瘑
+ private static final String machineCode = "A";
+
+ /**
+ * 鑾峰彇閫氱敤搴忓垪鍙�
+ *
+ * @return 搴忓垪鍊�
+ */
+ public static String getId()
+ {
+ return getId(commSeqType);
+ }
+
+ /**
+ * 榛樿16浣嶅簭鍒楀彿 yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + 3闀垮害寰幆閫掑瀛楃涓�
+ *
+ * @return 搴忓垪鍊�
+ */
+ public static String getId(String type)
+ {
+ AtomicInteger atomicInt = commSeq;
+ if (uploadSeqType.equals(type))
+ {
+ atomicInt = uploadSeq;
+ }
+ return getId(atomicInt, 3);
+ }
+
+ /**
+ * 閫氱敤鎺ュ彛搴忓垪鍙� yyMMddHHmmss + 涓�浣嶆満鍣ㄦ爣璇� + length闀垮害寰幆閫掑瀛楃涓�
+ *
+ * @param atomicInt 搴忓垪鏁�
+ * @param length 鏁板�奸暱搴�
+ * @return 搴忓垪鍊�
+ */
+ public static String getId(AtomicInteger atomicInt, int length)
+ {
+ String result = DateUtils.dateTimeNow();
+ result += machineCode;
+ result += getSeq(atomicInt, length);
+ return result;
+ }
+
+ /**
+ * 搴忓垪寰幆閫掑瀛楃涓瞇1, 10 鐨� (length)骞傛鏂�), 鐢�0宸﹁ˉ榻恖ength浣嶆暟
+ *
+ * @return 搴忓垪鍊�
+ */
+ private synchronized static String getSeq(AtomicInteger atomicInt, int length)
+ {
+ // 鍏堝彇鍊煎啀+1
+ int value = atomicInt.getAndIncrement();
+
+ // 濡傛灉鏇存柊鍚庡��>=10 鐨� (length)骞傛鏂瑰垯閲嶇疆涓�1
+ int maxSeq = (int) Math.pow(10, length);
+ if (atomicInt.get() >= maxSeq)
+ {
+ atomicInt.set(1);
+ }
+ // 杞瓧绗︿覆锛岀敤0宸﹁ˉ榻�
+ return StringUtils.padl(value, length);
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java
new file mode 100644
index 0000000..a5585d6
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/uuid/UUID.java
@@ -0,0 +1,484 @@
+package com.ruoyi.common.utils.uuid;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+import com.ruoyi.common.exception.UtilException;
+
+/**
+ * 鎻愪緵閫氱敤鍞竴璇嗗埆鐮侊紙universally unique identifier锛夛紙UUID锛夊疄鐜�
+ *
+ * @author ruoyi
+ */
+public final class UUID implements java.io.Serializable, Comparable<UUID>
+{
+ private static final long serialVersionUID = -1185015143654744140L;
+
+ /**
+ * SecureRandom 鐨勫崟渚�
+ *
+ */
+ private static class Holder
+ {
+ static final SecureRandom numberGenerator = getSecureRandom();
+ }
+
+ /** 姝UID鐨勬渶楂�64鏈夋晥浣� */
+ private final long mostSigBits;
+
+ /** 姝UID鐨勬渶浣�64鏈夋晥浣� */
+ private final long leastSigBits;
+
+ /**
+ * 绉佹湁鏋勯��
+ *
+ * @param data 鏁版嵁
+ */
+ private UUID(byte[] data)
+ {
+ long msb = 0;
+ long lsb = 0;
+ assert data.length == 16 : "data must be 16 bytes in length";
+ for (int i = 0; i < 8; i++)
+ {
+ msb = (msb << 8) | (data[i] & 0xff);
+ }
+ for (int i = 8; i < 16; i++)
+ {
+ lsb = (lsb << 8) | (data[i] & 0xff);
+ }
+ this.mostSigBits = msb;
+ this.leastSigBits = lsb;
+ }
+
+ /**
+ * 浣跨敤鎸囧畾鐨勬暟鎹瀯閫犳柊鐨� UUID銆�
+ *
+ * @param mostSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶楂樻湁鏁� 64 浣�
+ * @param leastSigBits 鐢ㄤ簬 {@code UUID} 鐨勬渶浣庢湁鏁� 64 浣�
+ */
+ public UUID(long mostSigBits, long leastSigBits)
+ {
+ this.mostSigBits = mostSigBits;
+ this.leastSigBits = leastSigBits;
+ }
+
+ /**
+ * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘��
+ *
+ * @return 闅忔満鐢熸垚鐨� {@code UUID}
+ */
+ public static UUID fastUUID()
+ {
+ return randomUUID(false);
+ }
+
+ /**
+ * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+ *
+ * @return 闅忔満鐢熸垚鐨� {@code UUID}
+ */
+ public static UUID randomUUID()
+ {
+ return randomUUID(true);
+ }
+
+ /**
+ * 鑾峰彇绫诲瀷 4锛堜吉闅忔満鐢熸垚鐨勶級UUID 鐨勯潤鎬佸伐鍘傘�� 浣跨敤鍔犲瘑鐨勫己浼殢鏈烘暟鐢熸垚鍣ㄧ敓鎴愯 UUID銆�
+ *
+ * @param isSecure 鏄惁浣跨敤{@link SecureRandom}濡傛灉鏄彲浠ヨ幏寰楁洿瀹夊叏鐨勯殢鏈虹爜锛屽惁鍒欏彲浠ュ緱鍒版洿濂界殑鎬ц兘
+ * @return 闅忔満鐢熸垚鐨� {@code UUID}
+ */
+ public static UUID randomUUID(boolean isSecure)
+ {
+ final Random ng = isSecure ? Holder.numberGenerator : getRandom();
+
+ byte[] randomBytes = new byte[16];
+ ng.nextBytes(randomBytes);
+ randomBytes[6] &= 0x0f; /* clear version */
+ randomBytes[6] |= 0x40; /* set to version 4 */
+ randomBytes[8] &= 0x3f; /* clear variant */
+ randomBytes[8] |= 0x80; /* set to IETF variant */
+ return new UUID(randomBytes);
+ }
+
+ /**
+ * 鏍规嵁鎸囧畾鐨勫瓧鑺傛暟缁勮幏鍙栫被鍨� 3锛堝熀浜庡悕绉扮殑锛塙UID 鐨勯潤鎬佸伐鍘傘��
+ *
+ * @param name 鐢ㄤ簬鏋勯�� UUID 鐨勫瓧鑺傛暟缁勩��
+ *
+ * @return 鏍规嵁鎸囧畾鏁扮粍鐢熸垚鐨� {@code UUID}
+ */
+ public static UUID nameUUIDFromBytes(byte[] name)
+ {
+ MessageDigest md;
+ try
+ {
+ md = MessageDigest.getInstance("MD5");
+ }
+ catch (NoSuchAlgorithmException nsae)
+ {
+ throw new InternalError("MD5 not supported");
+ }
+ byte[] md5Bytes = md.digest(name);
+ md5Bytes[6] &= 0x0f; /* clear version */
+ md5Bytes[6] |= 0x30; /* set to version 3 */
+ md5Bytes[8] &= 0x3f; /* clear variant */
+ md5Bytes[8] |= 0x80; /* set to IETF variant */
+ return new UUID(md5Bytes);
+ }
+
+ /**
+ * 鏍规嵁 {@link #toString()} 鏂规硶涓弿杩扮殑瀛楃涓叉爣鍑嗚〃绀哄舰寮忓垱寤簕@code UUID}銆�
+ *
+ * @param name 鎸囧畾 {@code UUID} 瀛楃涓�
+ * @return 鍏锋湁鎸囧畾鍊肩殑 {@code UUID}
+ * @throws IllegalArgumentException 濡傛灉 name 涓� {@link #toString} 涓弿杩扮殑瀛楃涓茶〃绀哄舰寮忎笉绗︽姏鍑烘寮傚父
+ *
+ */
+ public static UUID fromString(String name)
+ {
+ String[] components = name.split("-");
+ if (components.length != 5)
+ {
+ throw new IllegalArgumentException("Invalid UUID string: " + name);
+ }
+ for (int i = 0; i < 5; i++)
+ {
+ components[i] = "0x" + components[i];
+ }
+
+ long mostSigBits = Long.decode(components[0]).longValue();
+ mostSigBits <<= 16;
+ mostSigBits |= Long.decode(components[1]).longValue();
+ mostSigBits <<= 16;
+ mostSigBits |= Long.decode(components[2]).longValue();
+
+ long leastSigBits = Long.decode(components[3]).longValue();
+ leastSigBits <<= 48;
+ leastSigBits |= Long.decode(components[4]).longValue();
+
+ return new UUID(mostSigBits, leastSigBits);
+ }
+
+ /**
+ * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+ *
+ * @return 姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶浣庢湁鏁� 64 浣嶃��
+ */
+ public long getLeastSignificantBits()
+ {
+ return leastSigBits;
+ }
+
+ /**
+ * 杩斿洖姝� UUID 鐨� 128 浣嶅�间腑鐨勬渶楂樻湁鏁� 64 浣嶃��
+ *
+ * @return 姝� UUID 鐨� 128 浣嶅�间腑鏈�楂樻湁鏁� 64 浣嶃��
+ */
+ public long getMostSignificantBits()
+ {
+ return mostSigBits;
+ }
+
+ /**
+ * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鐗堟湰鍙�. 鐗堟湰鍙锋弿杩版 {@code UUID} 鏄浣曠敓鎴愮殑銆�
+ * <p>
+ * 鐗堟湰鍙峰叿鏈変互涓嬪惈鎰�:
+ * <ul>
+ * <li>1 鍩轰簬鏃堕棿鐨� UUID
+ * <li>2 DCE 瀹夊叏 UUID
+ * <li>3 鍩轰簬鍚嶇О鐨� UUID
+ * <li>4 闅忔満鐢熸垚鐨� UUID
+ * </ul>
+ *
+ * @return 姝� {@code UUID} 鐨勭増鏈彿
+ */
+ public int version()
+ {
+ // Version is bits masked by 0x000000000000F000 in MS long
+ return (int) ((mostSigBits >> 12) & 0x0f);
+ }
+
+ /**
+ * 涓庢 {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙枫�傚彉浣撳彿鎻忚堪 {@code UUID} 鐨勫竷灞�銆�
+ * <p>
+ * 鍙樹綋鍙峰叿鏈変互涓嬪惈鎰忥細
+ * <ul>
+ * <li>0 涓� NCS 鍚戝悗鍏煎淇濈暀
+ * <li>2 <a href="http://www.ietf.org/rfc/rfc4122.txt">IETF RFC 4122</a>(Leach-Salz), 鐢ㄤ簬姝ょ被
+ * <li>6 淇濈暀锛屽井杞悜鍚庡吋瀹�
+ * <li>7 淇濈暀渚涗互鍚庡畾涔変娇鐢�
+ * </ul>
+ *
+ * @return 姝� {@code UUID} 鐩稿叧鑱旂殑鍙樹綋鍙�
+ */
+ public int variant()
+ {
+ // This field is composed of a varying number of bits.
+ // 0 - - Reserved for NCS backward compatibility
+ // 1 0 - The IETF aka Leach-Salz variant (used by this class)
+ // 1 1 0 Reserved, Microsoft backward compatibility
+ // 1 1 1 Reserved for future definition.
+ return (int) ((leastSigBits >>> (64 - (leastSigBits >>> 62))) & (leastSigBits >> 63));
+ }
+
+ /**
+ * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕棿鎴冲�笺��
+ *
+ * <p>
+ * 60 浣嶇殑鏃堕棿鎴冲�兼牴鎹 {@code UUID} 鐨� time_low銆乼ime_mid 鍜� time_hi 瀛楁鏋勯�犮��<br>
+ * 鎵�寰楀埌鐨勬椂闂存埑浠� 100 姣井绉掍负鍗曚綅锛屼粠 UTC锛堥�氱敤鍗忚皟鏃堕棿锛� 1582 骞� 10 鏈� 15 鏃ラ浂鏃跺紑濮嬨��
+ *
+ * <p>
+ * 鏃堕棿鎴冲�间粎鍦ㄥ湪鍩轰簬鏃堕棿鐨� UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+ * 濡傛灉姝� {@code UUID} 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+ *
+ * @throws UnsupportedOperationException 濡傛灉姝� {@code UUID} 涓嶆槸 version 涓� 1 鐨� UUID銆�
+ */
+ public long timestamp() throws UnsupportedOperationException
+ {
+ checkTimeBase();
+ return (mostSigBits & 0x0FFFL) << 48//
+ | ((mostSigBits >> 16) & 0x0FFFFL) << 32//
+ | mostSigBits >>> 32;
+ }
+
+ /**
+ * 涓庢 UUID 鐩稿叧鑱旂殑鏃堕挓搴忓垪鍊笺��
+ *
+ * <p>
+ * 14 浣嶇殑鏃堕挓搴忓垪鍊兼牴鎹 UUID 鐨� clock_seq 瀛楁鏋勯�犮�俢lock_seq 瀛楁鐢ㄤ簬淇濊瘉鍦ㄥ熀浜庢椂闂寸殑 UUID 涓殑鏃堕棿鍞竴鎬с��
+ * <p>
+ * {@code clockSequence} 鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆� 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑�
+ * UnsupportedOperationException銆�
+ *
+ * @return 姝� {@code UUID} 鐨勬椂閽熷簭鍒�
+ *
+ * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+ */
+ public int clockSequence() throws UnsupportedOperationException
+ {
+ checkTimeBase();
+ return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
+ }
+
+ /**
+ * 涓庢 UUID 鐩稿叧鐨勮妭鐐瑰�笺��
+ *
+ * <p>
+ * 48 浣嶇殑鑺傜偣鍊兼牴鎹 UUID 鐨� node 瀛楁鏋勯�犮�傛瀛楁鏃ㄥ湪鐢ㄤ簬淇濆瓨鏈哄櫒鐨� IEEE 802 鍦板潃锛岃鍦板潃鐢ㄤ簬鐢熸垚姝� UUID 浠ヤ繚璇佺┖闂村敮涓�鎬с��
+ * <p>
+ * 鑺傜偣鍊间粎鍦ㄥ熀浜庢椂闂寸殑 UUID锛堝叾 version 绫诲瀷涓� 1锛変腑鎵嶆湁鎰忎箟銆�<br>
+ * 濡傛灉姝� UUID 涓嶆槸鍩轰簬鏃堕棿鐨� UUID锛屽垯姝ゆ柟娉曟姏鍑� UnsupportedOperationException銆�
+ *
+ * @return 姝� {@code UUID} 鐨勮妭鐐瑰��
+ *
+ * @throws UnsupportedOperationException 濡傛灉姝� UUID 鐨� version 涓嶄负 1
+ */
+ public long node() throws UnsupportedOperationException
+ {
+ checkTimeBase();
+ return leastSigBits & 0x0000FFFFFFFFFFFFL;
+ }
+
+ /**
+ * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+ *
+ * <p>
+ * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+ *
+ * <pre>
+ * {@code
+ * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+ * time_low = 4*<hexOctet>
+ * time_mid = 2*<hexOctet>
+ * time_high_and_version = 2*<hexOctet>
+ * variant_and_sequence = 2*<hexOctet>
+ * node = 6*<hexOctet>
+ * hexOctet = <hexDigit><hexDigit>
+ * hexDigit = [0-9a-fA-F]
+ * }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+ * @see #toString(boolean)
+ */
+ @Override
+ public String toString()
+ {
+ return toString(false);
+ }
+
+ /**
+ * 杩斿洖姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡銆�
+ *
+ * <p>
+ * UUID 鐨勫瓧绗︿覆琛ㄧず褰㈠紡鐢辨 BNF 鎻忚堪锛�
+ *
+ * <pre>
+ * {@code
+ * UUID = <time_low>-<time_mid>-<time_high_and_version>-<variant_and_sequence>-<node>
+ * time_low = 4*<hexOctet>
+ * time_mid = 2*<hexOctet>
+ * time_high_and_version = 2*<hexOctet>
+ * variant_and_sequence = 2*<hexOctet>
+ * node = 6*<hexOctet>
+ * hexOctet = <hexDigit><hexDigit>
+ * hexDigit = [0-9a-fA-F]
+ * }
+ * </pre>
+ *
+ * </blockquote>
+ *
+ * @param isSimple 鏄惁绠�鍗曟ā寮忥紝绠�鍗曟ā寮忎负涓嶅甫'-'鐨刄UID瀛楃涓�
+ * @return 姝@code UUID} 鐨勫瓧绗︿覆琛ㄧ幇褰㈠紡
+ */
+ public String toString(boolean isSimple)
+ {
+ final StringBuilder builder = new StringBuilder(isSimple ? 32 : 36);
+ // time_low
+ builder.append(digits(mostSigBits >> 32, 8));
+ if (!isSimple)
+ {
+ builder.append('-');
+ }
+ // time_mid
+ builder.append(digits(mostSigBits >> 16, 4));
+ if (!isSimple)
+ {
+ builder.append('-');
+ }
+ // time_high_and_version
+ builder.append(digits(mostSigBits, 4));
+ if (!isSimple)
+ {
+ builder.append('-');
+ }
+ // variant_and_sequence
+ builder.append(digits(leastSigBits >> 48, 4));
+ if (!isSimple)
+ {
+ builder.append('-');
+ }
+ // node
+ builder.append(digits(leastSigBits, 12));
+
+ return builder.toString();
+ }
+
+ /**
+ * 杩斿洖姝� UUID 鐨勫搱甯岀爜銆�
+ *
+ * @return UUID 鐨勫搱甯岀爜鍊笺��
+ */
+ @Override
+ public int hashCode()
+ {
+ long hilo = mostSigBits ^ leastSigBits;
+ return ((int) (hilo >> 32)) ^ (int) hilo;
+ }
+
+ /**
+ * 灏嗘瀵硅薄涓庢寚瀹氬璞℃瘮杈冦��
+ * <p>
+ * 褰撲笖浠呭綋鍙傛暟涓嶄负 {@code null}銆佽�屾槸涓�涓� UUID 瀵硅薄銆佸叿鏈変笌姝� UUID 鐩稿悓鐨� varriant銆佸寘鍚浉鍚岀殑鍊硷紙姣忎竴浣嶅潎鐩稿悓锛夋椂锛岀粨鏋滄墠涓� {@code true}銆�
+ *
+ * @param obj 瑕佷笌涔嬫瘮杈冪殑瀵硅薄
+ *
+ * @return 濡傛灉瀵硅薄鐩稿悓锛屽垯杩斿洖 {@code true}锛涘惁鍒欒繑鍥� {@code false}
+ */
+ @Override
+ public boolean equals(Object obj)
+ {
+ if ((null == obj) || (obj.getClass() != UUID.class))
+ {
+ return false;
+ }
+ UUID id = (UUID) obj;
+ return (mostSigBits == id.mostSigBits && leastSigBits == id.leastSigBits);
+ }
+
+ // Comparison Operations
+
+ /**
+ * 灏嗘 UUID 涓庢寚瀹氱殑 UUID 姣旇緝銆�
+ *
+ * <p>
+ * 濡傛灉涓や釜 UUID 涓嶅悓锛屼笖绗竴涓� UUID 鐨勬渶楂樻湁鏁堝瓧娈靛ぇ浜庣浜屼釜 UUID 鐨勫搴斿瓧娈碉紝鍒欑涓�涓� UUID 澶т簬绗簩涓� UUID銆�
+ *
+ * @param val 涓庢 UUID 姣旇緝鐨� UUID
+ *
+ * @return 鍦ㄦ UUID 灏忎簬銆佺瓑浜庢垨澶т簬 val 鏃讹紝鍒嗗埆杩斿洖 -1銆�0 鎴� 1銆�
+ *
+ */
+ @Override
+ public int compareTo(UUID val)
+ {
+ // The ordering is intentionally set up so that the UUIDs
+ // can simply be numerically compared as two numbers
+ return (this.mostSigBits < val.mostSigBits ? -1 : //
+ (this.mostSigBits > val.mostSigBits ? 1 : //
+ (this.leastSigBits < val.leastSigBits ? -1 : //
+ (this.leastSigBits > val.leastSigBits ? 1 : //
+ 0))));
+ }
+
+ // -------------------------------------------------------------------------------------------------------------------
+ // Private method start
+ /**
+ * 杩斿洖鎸囧畾鏁板瓧瀵瑰簲鐨刪ex鍊�
+ *
+ * @param val 鍊�
+ * @param digits 浣�
+ * @return 鍊�
+ */
+ private static String digits(long val, int digits)
+ {
+ long hi = 1L << (digits * 4);
+ return Long.toHexString(hi | (val & (hi - 1))).substring(1);
+ }
+
+ /**
+ * 妫�鏌ユ槸鍚︿负time-based鐗堟湰UUID
+ */
+ private void checkTimeBase()
+ {
+ if (version() != 1)
+ {
+ throw new UnsupportedOperationException("Not a time-based UUID");
+ }
+ }
+
+ /**
+ * 鑾峰彇{@link SecureRandom}锛岀被鎻愪緵鍔犲瘑鐨勫己闅忔満鏁扮敓鎴愬櫒 (RNG)
+ *
+ * @return {@link SecureRandom}
+ */
+ public static SecureRandom getSecureRandom()
+ {
+ try
+ {
+ return SecureRandom.getInstance("SHA1PRNG");
+ }
+ catch (NoSuchAlgorithmException e)
+ {
+ throw new UtilException(e);
+ }
+ }
+
+ /**
+ * 鑾峰彇闅忔満鏁扮敓鎴愬櫒瀵硅薄<br>
+ * ThreadLocalRandom鏄疛DK 7涔嬪悗鎻愪緵骞跺彂浜х敓闅忔満鏁帮紝鑳藉瑙e喅澶氫釜绾跨▼鍙戠敓鐨勭珵浜変簤澶恒��
+ *
+ * @return {@link ThreadLocalRandom}
+ */
+ public static ThreadLocalRandom getRandom()
+ {
+ return ThreadLocalRandom.current();
+ }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java
new file mode 100644
index 0000000..7bfdf04
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/Xss.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.xss;
+
+import javax.validation.Constraint;
+import javax.validation.Payload;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ
+ *
+ * @author ruoyi
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.METHOD, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER })
+@Constraint(validatedBy = { XssValidator.class })
+public @interface Xss
+{
+ String message()
+
+ default "涓嶅厑璁镐换浣曡剼鏈繍琛�";
+
+ Class<?>[] groups() default {};
+
+ Class<? extends Payload>[] payload() default {};
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java
new file mode 100644
index 0000000..42f425c
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/xss/XssValidator.java
@@ -0,0 +1,39 @@
+package com.ruoyi.common.xss;
+
+import com.ruoyi.common.utils.StringUtils;
+import javax.validation.ConstraintValidator;
+import javax.validation.ConstraintValidatorContext;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * 鑷畾涔墄ss鏍¢獙娉ㄨВ瀹炵幇
+ *
+ * @author ruoyi
+ */
+public class XssValidator implements ConstraintValidator<Xss, String>
+{
+ private static final String HTML_PATTERN = "<(\\S*?)[^>]*>.*?|<.*? />";
+
+ @Override
+ public boolean isValid(String value, ConstraintValidatorContext constraintValidatorContext)
+ {
+ if (StringUtils.isBlank(value))
+ {
+ return true;
+ }
+ return !containsHtml(value);
+ }
+
+ public static boolean containsHtml(String value)
+ {
+ StringBuilder sHtml = new StringBuilder();
+ Pattern pattern = Pattern.compile(HTML_PATTERN);
+ Matcher matcher = pattern.matcher(value);
+ while (matcher.find())
+ {
+ sHtml.append(matcher.group());
+ }
+ return pattern.matcher(sHtml).matches();
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/pom.xml b/ruoyi-framework/pom.xml
new file mode 100644
index 0000000..d7a4630
--- /dev/null
+++ b/ruoyi-framework/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>ruoyi-framework</artifactId>
+
+ <description>
+ framework妗嗘灦鏍稿績
+ </description>
+
+ <dependencies>
+
+ <!-- SpringBoot Web瀹瑰櫒 -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-web</artifactId>
+ </dependency>
+
+ <!-- SpringBoot 鎷︽埅鍣� -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-aop</artifactId>
+ </dependency>
+
+ <!-- 闃块噷鏁版嵁搴撹繛鎺ユ睜 -->
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ </dependency>
+
+ <!-- 楠岃瘉鐮� -->
+ <dependency>
+ <groupId>pro.fessional</groupId>
+ <artifactId>kaptcha</artifactId>
+ <exclusions>
+ <exclusion>
+ <artifactId>servlet-api</artifactId>
+ <groupId>javax.servlet</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- 鑾峰彇绯荤粺淇℃伅 -->
+ <dependency>
+ <groupId>com.github.oshi</groupId>
+ <artifactId>oshi-core</artifactId>
+ </dependency>
+
+ <!-- 绯荤粺妯″潡-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-system</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
new file mode 100644
index 0000000..b2337c9
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataScopeAspect.java
@@ -0,0 +1,184 @@
+package com.ruoyi.framework.aspectj;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.context.PermissionContextHolder;
+
+/**
+ * 鏁版嵁杩囨护澶勭悊
+ *
+ * @author ruoyi
+ */
+@Aspect
+@Component
+public class DataScopeAspect
+{
+ /**
+ * 鍏ㄩ儴鏁版嵁鏉冮檺
+ */
+ public static final String DATA_SCOPE_ALL = "1";
+
+ /**
+ * 鑷畾鏁版嵁鏉冮檺
+ */
+ public static final String DATA_SCOPE_CUSTOM = "2";
+
+ /**
+ * 閮ㄩ棬鏁版嵁鏉冮檺
+ */
+ public static final String DATA_SCOPE_DEPT = "3";
+
+ /**
+ * 閮ㄩ棬鍙婁互涓嬫暟鎹潈闄�
+ */
+ public static final String DATA_SCOPE_DEPT_AND_CHILD = "4";
+
+ /**
+ * 浠呮湰浜烘暟鎹潈闄�
+ */
+ public static final String DATA_SCOPE_SELF = "5";
+
+ /**
+ * 鏁版嵁鏉冮檺杩囨护鍏抽敭瀛�
+ */
+ public static final String DATA_SCOPE = "dataScope";
+
+ @Before("@annotation(controllerDataScope)")
+ public void doBefore(JoinPoint point, DataScope controllerDataScope) throws Throwable
+ {
+ clearDataScope(point);
+ handleDataScope(point, controllerDataScope);
+ }
+
+ protected void handleDataScope(final JoinPoint joinPoint, DataScope controllerDataScope)
+ {
+ // 鑾峰彇褰撳墠鐨勭敤鎴�
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (StringUtils.isNotNull(loginUser))
+ {
+ SysUser currentUser = loginUser.getUser();
+ // 濡傛灉鏄秴绾х鐞嗗憳锛屽垯涓嶈繃婊ゆ暟鎹�
+ if (StringUtils.isNotNull(currentUser) && !currentUser.isAdmin())
+ {
+ String permission = StringUtils.defaultIfEmpty(controllerDataScope.permission(), PermissionContextHolder.getContext());
+ dataScopeFilter(joinPoint, currentUser, controllerDataScope.deptAlias(), controllerDataScope.userAlias(), permission);
+ }
+ }
+ }
+
+ /**
+ * 鏁版嵁鑼冨洿杩囨护
+ *
+ * @param joinPoint 鍒囩偣
+ * @param user 鐢ㄦ埛
+ * @param deptAlias 閮ㄩ棬鍒悕
+ * @param userAlias 鐢ㄦ埛鍒悕
+ * @param permission 鏉冮檺瀛楃
+ */
+ public static void dataScopeFilter(JoinPoint joinPoint, SysUser user, String deptAlias, String userAlias, String permission)
+ {
+ StringBuilder sqlString = new StringBuilder();
+ List<String> conditions = new ArrayList<String>();
+ List<String> scopeCustomIds = new ArrayList<String>();
+ user.getRoles().forEach(role -> {
+ if (DATA_SCOPE_CUSTOM.equals(role.getDataScope()) && StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL) && StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
+ {
+ scopeCustomIds.add(Convert.toStr(role.getRoleId()));
+ }
+ });
+
+ for (SysRole role : user.getRoles())
+ {
+ String dataScope = role.getDataScope();
+ if (conditions.contains(dataScope) || StringUtils.equals(role.getStatus(), UserConstants.ROLE_DISABLE))
+ {
+ continue;
+ }
+ if (!StringUtils.containsAny(role.getPermissions(), Convert.toStrArray(permission)))
+ {
+ continue;
+ }
+ if (DATA_SCOPE_ALL.equals(dataScope))
+ {
+ sqlString = new StringBuilder();
+ conditions.add(dataScope);
+ break;
+ }
+ else if (DATA_SCOPE_CUSTOM.equals(dataScope))
+ {
+ if (scopeCustomIds.size() > 1)
+ {
+ // 澶氫釜鑷畾鏁版嵁鏉冮檺浣跨敤in鏌ヨ锛岄伩鍏嶅娆℃嫾鎺ャ��
+ sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id in ({}) ) ", deptAlias, String.join(",", scopeCustomIds)));
+ }
+ else
+ {
+ sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_role_dept WHERE role_id = {} ) ", deptAlias, role.getRoleId()));
+ }
+ }
+ else if (DATA_SCOPE_DEPT.equals(dataScope))
+ {
+ sqlString.append(StringUtils.format(" OR {}.dept_id = {} ", deptAlias, user.getDeptId()));
+ }
+ else if (DATA_SCOPE_DEPT_AND_CHILD.equals(dataScope))
+ {
+ sqlString.append(StringUtils.format(" OR {}.dept_id IN ( SELECT dept_id FROM sys_dept WHERE dept_id = {} or find_in_set( {} , ancestors ) )", deptAlias, user.getDeptId(), user.getDeptId()));
+ }
+ else if (DATA_SCOPE_SELF.equals(dataScope))
+ {
+ if (StringUtils.isNotBlank(userAlias))
+ {
+ sqlString.append(StringUtils.format(" OR {}.user_id = {} ", userAlias, user.getUserId()));
+ }
+ else
+ {
+ // 鏁版嵁鏉冮檺涓轰粎鏈汉涓旀病鏈塽serAlias鍒悕涓嶆煡璇换浣曟暟鎹�
+ sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
+ }
+ }
+ conditions.add(dataScope);
+ }
+
+ // 瑙掕壊閮戒笉鍖呭惈浼犻�掕繃鏉ョ殑鏉冮檺瀛楃锛岃繖涓椂鍊檚qlString涔熶細涓虹┖锛屾墍浠ヨ闄愬埗涓�涓�,涓嶆煡璇换浣曟暟鎹�
+ if (StringUtils.isEmpty(conditions))
+ {
+ sqlString.append(StringUtils.format(" OR {}.dept_id = 0 ", deptAlias));
+ }
+
+ if (StringUtils.isNotBlank(sqlString.toString()))
+ {
+ Object params = joinPoint.getArgs()[0];
+ if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
+ {
+ BaseEntity baseEntity = (BaseEntity) params;
+ baseEntity.getParams().put(DATA_SCOPE, " AND (" + sqlString.substring(4) + ")");
+ }
+ }
+ }
+
+ /**
+ * 鎷兼帴鏉冮檺sql鍓嶅厛娓呯┖params.dataScope鍙傛暟闃叉娉ㄥ叆
+ */
+ private void clearDataScope(final JoinPoint joinPoint)
+ {
+ Object params = joinPoint.getArgs()[0];
+ if (StringUtils.isNotNull(params) && params instanceof BaseEntity)
+ {
+ BaseEntity baseEntity = (BaseEntity) params;
+ baseEntity.getParams().put(DATA_SCOPE, "");
+ }
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
new file mode 100644
index 0000000..8c2c9f4
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/DataSourceAspect.java
@@ -0,0 +1,72 @@
+package com.ruoyi.framework.aspectj;
+
+import java.util.Objects;
+import org.aspectj.lang.ProceedingJoinPoint;
+import org.aspectj.lang.annotation.Around;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Pointcut;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.core.annotation.Order;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.datasource.DynamicDataSourceContextHolder;
+
+/**
+ * 澶氭暟鎹簮澶勭悊
+ *
+ * @author ruoyi
+ */
+@Aspect
+@Order(1)
+@Component
+public class DataSourceAspect
+{
+ protected Logger logger = LoggerFactory.getLogger(getClass());
+
+ @Pointcut("@annotation(com.ruoyi.common.annotation.DataSource)"
+ + "|| @within(com.ruoyi.common.annotation.DataSource)")
+ public void dsPointCut()
+ {
+
+ }
+
+ @Around("dsPointCut()")
+ public Object around(ProceedingJoinPoint point) throws Throwable
+ {
+ DataSource dataSource = getDataSource(point);
+
+ if (StringUtils.isNotNull(dataSource))
+ {
+ DynamicDataSourceContextHolder.setDataSourceType(dataSource.value().name());
+ }
+
+ try
+ {
+ return point.proceed();
+ }
+ finally
+ {
+ // 閿�姣佹暟鎹簮 鍦ㄦ墽琛屾柟娉曚箣鍚�
+ DynamicDataSourceContextHolder.clearDataSourceType();
+ }
+ }
+
+ /**
+ * 鑾峰彇闇�瑕佸垏鎹㈢殑鏁版嵁婧�
+ */
+ public DataSource getDataSource(ProceedingJoinPoint point)
+ {
+ MethodSignature signature = (MethodSignature) point.getSignature();
+ DataSource dataSource = AnnotationUtils.findAnnotation(signature.getMethod(), DataSource.class);
+ if (Objects.nonNull(dataSource))
+ {
+ return dataSource;
+ }
+
+ return AnnotationUtils.findAnnotation(signature.getDeclaringType(), DataSource.class);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
new file mode 100644
index 0000000..44b52b4
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/LogAspect.java
@@ -0,0 +1,254 @@
+package com.ruoyi.framework.aspectj;
+
+import java.util.Collection;
+import java.util.Map;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.lang3.ArrayUtils;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.AfterReturning;
+import org.aspectj.lang.annotation.AfterThrowing;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.NamedThreadLocal;
+import org.springframework.stereotype.Component;
+import org.springframework.validation.BindingResult;
+import org.springframework.web.multipart.MultipartFile;
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.enums.BusinessStatus;
+import com.ruoyi.common.enums.HttpMethod;
+import com.ruoyi.common.filter.PropertyPreExcludeFilter;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.domain.SysOperLog;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍澶勭悊
+ *
+ * @author ruoyi
+ */
+@Aspect
+@Component
+public class LogAspect
+{
+ private static final Logger log = LoggerFactory.getLogger(LogAspect.class);
+
+ /** 鎺掗櫎鏁忔劅灞炴�у瓧娈� */
+ public static final String[] EXCLUDE_PROPERTIES = { "password", "oldPassword", "newPassword", "confirmPassword" };
+
+ /** 璁$畻鎿嶄綔娑堣�楁椂闂� */
+ private static final ThreadLocal<Long> TIME_THREADLOCAL = new NamedThreadLocal<Long>("Cost Time");
+
+ /**
+ * 澶勭悊璇锋眰鍓嶆墽琛�
+ */
+ @Before(value = "@annotation(controllerLog)")
+ public void boBefore(JoinPoint joinPoint, Log controllerLog)
+ {
+ TIME_THREADLOCAL.set(System.currentTimeMillis());
+ }
+
+ /**
+ * 澶勭悊瀹岃姹傚悗鎵ц
+ *
+ * @param joinPoint 鍒囩偣
+ */
+ @AfterReturning(pointcut = "@annotation(controllerLog)", returning = "jsonResult")
+ public void doAfterReturning(JoinPoint joinPoint, Log controllerLog, Object jsonResult)
+ {
+ handleLog(joinPoint, controllerLog, null, jsonResult);
+ }
+
+ /**
+ * 鎷︽埅寮傚父鎿嶄綔
+ *
+ * @param joinPoint 鍒囩偣
+ * @param e 寮傚父
+ */
+ @AfterThrowing(value = "@annotation(controllerLog)", throwing = "e")
+ public void doAfterThrowing(JoinPoint joinPoint, Log controllerLog, Exception e)
+ {
+ handleLog(joinPoint, controllerLog, e, null);
+ }
+
+ protected void handleLog(final JoinPoint joinPoint, Log controllerLog, final Exception e, Object jsonResult)
+ {
+ try
+ {
+ // 鑾峰彇褰撳墠鐨勭敤鎴�
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+
+ // *========鏁版嵁搴撴棩蹇�=========*//
+ SysOperLog operLog = new SysOperLog();
+ operLog.setStatus(BusinessStatus.SUCCESS.ordinal());
+ // 璇锋眰鐨勫湴鍧�
+ String ip = IpUtils.getIpAddr();
+ operLog.setOperIp(ip);
+ operLog.setOperUrl(StringUtils.substring(ServletUtils.getRequest().getRequestURI(), 0, 255));
+ if (loginUser != null)
+ {
+ operLog.setOperName(loginUser.getUsername());
+ SysUser currentUser = loginUser.getUser();
+ if (StringUtils.isNotNull(currentUser) && StringUtils.isNotNull(currentUser.getDept()))
+ {
+ operLog.setDeptName(currentUser.getDept().getDeptName());
+ }
+ }
+
+ if (e != null)
+ {
+ operLog.setStatus(BusinessStatus.FAIL.ordinal());
+ operLog.setErrorMsg(StringUtils.substring(e.getMessage(), 0, 2000));
+ }
+ // 璁剧疆鏂规硶鍚嶇О
+ String className = joinPoint.getTarget().getClass().getName();
+ String methodName = joinPoint.getSignature().getName();
+ operLog.setMethod(className + "." + methodName + "()");
+ // 璁剧疆璇锋眰鏂瑰紡
+ operLog.setRequestMethod(ServletUtils.getRequest().getMethod());
+ // 澶勭悊璁剧疆娉ㄨВ涓婄殑鍙傛暟
+ getControllerMethodDescription(joinPoint, controllerLog, operLog, jsonResult);
+ // 璁剧疆娑堣�楁椂闂�
+ operLog.setCostTime(System.currentTimeMillis() - TIME_THREADLOCAL.get());
+ // 淇濆瓨鏁版嵁搴�
+ AsyncManager.me().execute(AsyncFactory.recordOper(operLog));
+ }
+ catch (Exception exp)
+ {
+ // 璁板綍鏈湴寮傚父鏃ュ織
+ log.error("寮傚父淇℃伅:{}", exp.getMessage());
+ exp.printStackTrace();
+ }
+ finally
+ {
+ TIME_THREADLOCAL.remove();
+ }
+ }
+
+ /**
+ * 鑾峰彇娉ㄨВ涓鏂规硶鐨勬弿杩颁俊鎭� 鐢ㄤ簬Controller灞傛敞瑙�
+ *
+ * @param log 鏃ュ織
+ * @param operLog 鎿嶄綔鏃ュ織
+ * @throws Exception
+ */
+ public void getControllerMethodDescription(JoinPoint joinPoint, Log log, SysOperLog operLog, Object jsonResult) throws Exception
+ {
+ // 璁剧疆action鍔ㄤ綔
+ operLog.setBusinessType(log.businessType().ordinal());
+ // 璁剧疆鏍囬
+ operLog.setTitle(log.title());
+ // 璁剧疆鎿嶄綔浜虹被鍒�
+ operLog.setOperatorType(log.operatorType().ordinal());
+ // 鏄惁闇�瑕佷繚瀛榬equest锛屽弬鏁板拰鍊�
+ if (log.isSaveRequestData())
+ {
+ // 鑾峰彇鍙傛暟鐨勪俊鎭紝浼犲叆鍒版暟鎹簱涓��
+ setRequestValue(joinPoint, operLog, log.excludeParamNames());
+ }
+ // 鏄惁闇�瑕佷繚瀛榬esponse锛屽弬鏁板拰鍊�
+ if (log.isSaveResponseData() && StringUtils.isNotNull(jsonResult))
+ {
+ operLog.setJsonResult(StringUtils.substring(JSON.toJSONString(jsonResult), 0, 2000));
+ }
+ }
+
+ /**
+ * 鑾峰彇璇锋眰鐨勫弬鏁帮紝鏀惧埌log涓�
+ *
+ * @param operLog 鎿嶄綔鏃ュ織
+ * @throws Exception 寮傚父
+ */
+ private void setRequestValue(JoinPoint joinPoint, SysOperLog operLog, String[] excludeParamNames) throws Exception
+ {
+ Map<?, ?> paramsMap = ServletUtils.getParamMap(ServletUtils.getRequest());
+ String requestMethod = operLog.getRequestMethod();
+ if (StringUtils.isEmpty(paramsMap) && StringUtils.equalsAny(requestMethod, HttpMethod.PUT.name(), HttpMethod.POST.name(), HttpMethod.DELETE.name()))
+ {
+ String params = argsArrayToString(joinPoint.getArgs(), excludeParamNames);
+ operLog.setOperParam(StringUtils.substring(params, 0, 2000));
+ }
+ else
+ {
+ operLog.setOperParam(StringUtils.substring(JSON.toJSONString(paramsMap, excludePropertyPreFilter(excludeParamNames)), 0, 2000));
+ }
+ }
+
+ /**
+ * 鍙傛暟鎷艰
+ */
+ private String argsArrayToString(Object[] paramsArray, String[] excludeParamNames)
+ {
+ String params = "";
+ if (paramsArray != null && paramsArray.length > 0)
+ {
+ for (Object o : paramsArray)
+ {
+ if (StringUtils.isNotNull(o) && !isFilterObject(o))
+ {
+ try
+ {
+ String jsonObj = JSON.toJSONString(o, excludePropertyPreFilter(excludeParamNames));
+ params += jsonObj.toString() + " ";
+ }
+ catch (Exception e)
+ {
+ }
+ }
+ }
+ }
+ return params.trim();
+ }
+
+ /**
+ * 蹇界暐鏁忔劅灞炴��
+ */
+ public PropertyPreExcludeFilter excludePropertyPreFilter(String[] excludeParamNames)
+ {
+ return new PropertyPreExcludeFilter().addExcludes(ArrayUtils.addAll(EXCLUDE_PROPERTIES, excludeParamNames));
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁闇�瑕佽繃婊ょ殑瀵硅薄銆�
+ *
+ * @param o 瀵硅薄淇℃伅銆�
+ * @return 濡傛灉鏄渶瑕佽繃婊ょ殑瀵硅薄锛屽垯杩斿洖true锛涘惁鍒欒繑鍥瀎alse銆�
+ */
+ @SuppressWarnings("rawtypes")
+ public boolean isFilterObject(final Object o)
+ {
+ Class<?> clazz = o.getClass();
+ if (clazz.isArray())
+ {
+ return clazz.getComponentType().isAssignableFrom(MultipartFile.class);
+ }
+ else if (Collection.class.isAssignableFrom(clazz))
+ {
+ Collection collection = (Collection) o;
+ for (Object value : collection)
+ {
+ return value instanceof MultipartFile;
+ }
+ }
+ else if (Map.class.isAssignableFrom(clazz))
+ {
+ Map map = (Map) o;
+ for (Object value : map.entrySet())
+ {
+ Map.Entry entry = (Map.Entry) value;
+ return entry.getValue() instanceof MultipartFile;
+ }
+ }
+ return o instanceof MultipartFile || o instanceof HttpServletRequest || o instanceof HttpServletResponse
+ || o instanceof BindingResult;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
new file mode 100644
index 0000000..b720bc1
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/aspectj/RateLimiterAspect.java
@@ -0,0 +1,89 @@
+package com.ruoyi.framework.aspectj;
+
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.List;
+import org.aspectj.lang.JoinPoint;
+import org.aspectj.lang.annotation.Aspect;
+import org.aspectj.lang.annotation.Before;
+import org.aspectj.lang.reflect.MethodSignature;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.RedisScript;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.annotation.RateLimiter;
+import com.ruoyi.common.enums.LimitType;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+
+/**
+ * 闄愭祦澶勭悊
+ *
+ * @author ruoyi
+ */
+@Aspect
+@Component
+public class RateLimiterAspect
+{
+ private static final Logger log = LoggerFactory.getLogger(RateLimiterAspect.class);
+
+ private RedisTemplate<Object, Object> redisTemplate;
+
+ private RedisScript<Long> limitScript;
+
+ @Autowired
+ public void setRedisTemplate1(RedisTemplate<Object, Object> redisTemplate)
+ {
+ this.redisTemplate = redisTemplate;
+ }
+
+ @Autowired
+ public void setLimitScript(RedisScript<Long> limitScript)
+ {
+ this.limitScript = limitScript;
+ }
+
+ @Before("@annotation(rateLimiter)")
+ public void doBefore(JoinPoint point, RateLimiter rateLimiter) throws Throwable
+ {
+ int time = rateLimiter.time();
+ int count = rateLimiter.count();
+
+ String combineKey = getCombineKey(rateLimiter, point);
+ List<Object> keys = Collections.singletonList(combineKey);
+ try
+ {
+ Long number = redisTemplate.execute(limitScript, keys, count, time);
+ if (StringUtils.isNull(number) || number.intValue() > count)
+ {
+ throw new ServiceException("璁块棶杩囦簬棰戠箒锛岃绋嶅�欏啀璇�");
+ }
+ log.info("闄愬埗璇锋眰'{}',褰撳墠璇锋眰'{}',缂撳瓨key'{}'", count, number.intValue(), combineKey);
+ }
+ catch (ServiceException e)
+ {
+ throw e;
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException("鏈嶅姟鍣ㄩ檺娴佸紓甯革紝璇风◢鍊欏啀璇�");
+ }
+ }
+
+ public String getCombineKey(RateLimiter rateLimiter, JoinPoint point)
+ {
+ StringBuffer stringBuffer = new StringBuffer(rateLimiter.key());
+ if (rateLimiter.limitType() == LimitType.IP)
+ {
+ stringBuffer.append(IpUtils.getIpAddr()).append("-");
+ }
+ MethodSignature signature = (MethodSignature) point.getSignature();
+ Method method = signature.getMethod();
+ Class<?> targetClass = method.getDeclaringClass();
+ stringBuffer.append(targetClass.getName()).append("-").append(method.getName());
+ return stringBuffer.toString();
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java
new file mode 100644
index 0000000..1d4dc1f
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ApplicationConfig.java
@@ -0,0 +1,30 @@
+package com.ruoyi.framework.config;
+
+import java.util.TimeZone;
+import org.mybatis.spring.annotation.MapperScan;
+import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.EnableAspectJAutoProxy;
+
+/**
+ * 绋嬪簭娉ㄨВ閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Configuration
+// 琛ㄧず閫氳繃aop妗嗘灦鏆撮湶璇ヤ唬鐞嗗璞�,AopContext鑳藉璁块棶
+@EnableAspectJAutoProxy(exposeProxy = true)
+// 鎸囧畾瑕佹壂鎻忕殑Mapper绫荤殑鍖呯殑璺緞
+@MapperScan("com.ruoyi.**.mapper")
+public class ApplicationConfig
+{
+ /**
+ * 鏃跺尯閰嶇疆
+ */
+ @Bean
+ public Jackson2ObjectMapperBuilderCustomizer jacksonObjectMapperCustomization()
+ {
+ return jacksonObjectMapperBuilder -> jacksonObjectMapperBuilder.timeZone(TimeZone.getDefault());
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
new file mode 100644
index 0000000..43e78ae
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/CaptchaConfig.java
@@ -0,0 +1,83 @@
+package com.ruoyi.framework.config;
+
+import java.util.Properties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.google.code.kaptcha.impl.DefaultKaptcha;
+import com.google.code.kaptcha.util.Config;
+import static com.google.code.kaptcha.Constants.*;
+
+/**
+ * 楠岃瘉鐮侀厤缃�
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class CaptchaConfig
+{
+ @Bean(name = "captchaProducer")
+ public DefaultKaptcha getKaptchaBean()
+ {
+ DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+ Properties properties = new Properties();
+ // 鏄惁鏈夎竟妗� 榛樿涓簍rue 鎴戜滑鍙互鑷繁璁剧疆yes锛宯o
+ properties.setProperty(KAPTCHA_BORDER, "yes");
+ // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹� 榛樿涓篊olor.BLACK
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "black");
+ // 楠岃瘉鐮佸浘鐗囧搴� 榛樿涓�200
+ properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+ // 楠岃瘉鐮佸浘鐗囬珮搴� 榛樿涓�50
+ properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+ // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏� 榛樿涓�40
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "38");
+ // KAPTCHA_SESSION_KEY
+ properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCode");
+ // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴� 榛樿涓�5
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "4");
+ // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮� 榛樿涓簄ew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+ // 鍥剧墖鏍峰紡 姘寸汗com.google.code.kaptcha.impl.WaterRipple 楸肩溂com.google.code.kaptcha.impl.FishEyeGimpy 闃村奖com.google.code.kaptcha.impl.ShadowGimpy
+ properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+ Config config = new Config(properties);
+ defaultKaptcha.setConfig(config);
+ return defaultKaptcha;
+ }
+
+ @Bean(name = "captchaProducerMath")
+ public DefaultKaptcha getKaptchaBeanMath()
+ {
+ DefaultKaptcha defaultKaptcha = new DefaultKaptcha();
+ Properties properties = new Properties();
+ // 鏄惁鏈夎竟妗� 榛樿涓簍rue 鎴戜滑鍙互鑷繁璁剧疆yes锛宯o
+ properties.setProperty(KAPTCHA_BORDER, "yes");
+ // 杈规棰滆壊 榛樿涓篊olor.BLACK
+ properties.setProperty(KAPTCHA_BORDER_COLOR, "105,179,90");
+ // 楠岃瘉鐮佹枃鏈瓧绗﹂鑹� 榛樿涓篊olor.BLACK
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_COLOR, "blue");
+ // 楠岃瘉鐮佸浘鐗囧搴� 榛樿涓�200
+ properties.setProperty(KAPTCHA_IMAGE_WIDTH, "160");
+ // 楠岃瘉鐮佸浘鐗囬珮搴� 榛樿涓�50
+ properties.setProperty(KAPTCHA_IMAGE_HEIGHT, "60");
+ // 楠岃瘉鐮佹枃鏈瓧绗﹀ぇ灏� 榛樿涓�40
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_SIZE, "35");
+ // KAPTCHA_SESSION_KEY
+ properties.setProperty(KAPTCHA_SESSION_CONFIG_KEY, "kaptchaCodeMath");
+ // 楠岃瘉鐮佹枃鏈敓鎴愬櫒
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_IMPL, "com.ruoyi.framework.config.KaptchaTextCreator");
+ // 楠岃瘉鐮佹枃鏈瓧绗﹂棿璺� 榛樿涓�2
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_SPACE, "3");
+ // 楠岃瘉鐮佹枃鏈瓧绗﹂暱搴� 榛樿涓�5
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_CHAR_LENGTH, "6");
+ // 楠岃瘉鐮佹枃鏈瓧浣撴牱寮� 榛樿涓簄ew Font("Arial", 1, fontSize), new Font("Courier", 1, fontSize)
+ properties.setProperty(KAPTCHA_TEXTPRODUCER_FONT_NAMES, "Arial,Courier");
+ // 楠岃瘉鐮佸櫔鐐归鑹� 榛樿涓篊olor.BLACK
+ properties.setProperty(KAPTCHA_NOISE_COLOR, "white");
+ // 骞叉壈瀹炵幇绫�
+ properties.setProperty(KAPTCHA_NOISE_IMPL, "com.google.code.kaptcha.impl.NoNoise");
+ // 鍥剧墖鏍峰紡 姘寸汗com.google.code.kaptcha.impl.WaterRipple 楸肩溂com.google.code.kaptcha.impl.FishEyeGimpy 闃村奖com.google.code.kaptcha.impl.ShadowGimpy
+ properties.setProperty(KAPTCHA_OBSCURIFICATOR_IMPL, "com.google.code.kaptcha.impl.ShadowGimpy");
+ Config config = new Config(properties);
+ defaultKaptcha.setConfig(config);
+ return defaultKaptcha;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
new file mode 100644
index 0000000..f6abac1
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/DruidConfig.java
@@ -0,0 +1,126 @@
+package com.ruoyi.framework.config;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.sql.DataSource;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Primary;
+import com.alibaba.druid.pool.DruidDataSource;
+import com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceBuilder;
+import com.alibaba.druid.spring.boot.autoconfigure.properties.DruidStatProperties;
+import com.alibaba.druid.util.Utils;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.framework.config.properties.DruidProperties;
+import com.ruoyi.framework.datasource.DynamicDataSource;
+
+/**
+ * druid 閰嶇疆澶氭暟鎹簮
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class DruidConfig
+{
+ @Bean
+ @ConfigurationProperties("spring.datasource.druid.master")
+ public DataSource masterDataSource(DruidProperties druidProperties)
+ {
+ DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+ return druidProperties.dataSource(dataSource);
+ }
+
+ @Bean
+ @ConfigurationProperties("spring.datasource.druid.slave")
+ @ConditionalOnProperty(prefix = "spring.datasource.druid.slave", name = "enabled", havingValue = "true")
+ public DataSource slaveDataSource(DruidProperties druidProperties)
+ {
+ DruidDataSource dataSource = DruidDataSourceBuilder.create().build();
+ return druidProperties.dataSource(dataSource);
+ }
+
+ @Bean(name = "dynamicDataSource")
+ @Primary
+ public DynamicDataSource dataSource(DataSource masterDataSource)
+ {
+ Map<Object, Object> targetDataSources = new HashMap<>();
+ targetDataSources.put(DataSourceType.MASTER.name(), masterDataSource);
+ setDataSource(targetDataSources, DataSourceType.SLAVE.name(), "slaveDataSource");
+ return new DynamicDataSource(masterDataSource, targetDataSources);
+ }
+
+ /**
+ * 璁剧疆鏁版嵁婧�
+ *
+ * @param targetDataSources 澶囬�夋暟鎹簮闆嗗悎
+ * @param sourceName 鏁版嵁婧愬悕绉�
+ * @param beanName bean鍚嶇О
+ */
+ public void setDataSource(Map<Object, Object> targetDataSources, String sourceName, String beanName)
+ {
+ try
+ {
+ DataSource dataSource = SpringUtils.getBean(beanName);
+ targetDataSources.put(sourceName, dataSource);
+ }
+ catch (Exception e)
+ {
+ }
+ }
+
+ /**
+ * 鍘婚櫎鐩戞帶椤甸潰搴曢儴鐨勫箍鍛�
+ */
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Bean
+ @ConditionalOnProperty(name = "spring.datasource.druid.statViewServlet.enabled", havingValue = "true")
+ public FilterRegistrationBean removeDruidFilterRegistrationBean(DruidStatProperties properties)
+ {
+ // 鑾峰彇web鐩戞帶椤甸潰鐨勫弬鏁�
+ DruidStatProperties.StatViewServlet config = properties.getStatViewServlet();
+ // 鎻愬彇common.js鐨勯厤缃矾寰�
+ String pattern = config.getUrlPattern() != null ? config.getUrlPattern() : "/druid/*";
+ String commonJsPattern = pattern.replaceAll("\\*", "js/common.js");
+ final String filePath = "support/http/resources/js/common.js";
+ // 鍒涘缓filter杩涜杩囨护
+ Filter filter = new Filter()
+ {
+ @Override
+ public void init(javax.servlet.FilterConfig filterConfig) throws ServletException
+ {
+ }
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException
+ {
+ chain.doFilter(request, response);
+ // 閲嶇疆缂撳啿鍖猴紝鍝嶅簲澶翠笉浼氳閲嶇疆
+ response.resetBuffer();
+ // 鑾峰彇common.js
+ String text = Utils.readFromResource(filePath);
+ // 姝e垯鏇挎崲banner, 闄ゅ幓搴曢儴鐨勫箍鍛婁俊鎭�
+ text = text.replaceAll("<a.*?banner\"></a><br/>", "");
+ text = text.replaceAll("powered.*?shrek.wang</a>", "");
+ response.getWriter().write(text);
+ }
+ @Override
+ public void destroy()
+ {
+ }
+ };
+ FilterRegistrationBean registrationBean = new FilterRegistrationBean();
+ registrationBean.setFilter(filter);
+ registrationBean.addUrlPatterns(commonJsPattern);
+ return registrationBean;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java
new file mode 100644
index 0000000..4adbb7f
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FastJson2JsonRedisSerializer.java
@@ -0,0 +1,52 @@
+package com.ruoyi.framework.config;
+
+import java.nio.charset.Charset;
+import org.springframework.data.redis.serializer.RedisSerializer;
+import org.springframework.data.redis.serializer.SerializationException;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONReader;
+import com.alibaba.fastjson2.JSONWriter;
+import com.alibaba.fastjson2.filter.Filter;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * Redis浣跨敤FastJson搴忓垪鍖�
+ *
+ * @author ruoyi
+ */
+public class FastJson2JsonRedisSerializer<T> implements RedisSerializer<T>
+{
+ public static final Charset DEFAULT_CHARSET = Charset.forName("UTF-8");
+
+ static final Filter AUTO_TYPE_FILTER = JSONReader.autoTypeFilter(Constants.JSON_WHITELIST_STR);
+
+ private Class<T> clazz;
+
+ public FastJson2JsonRedisSerializer(Class<T> clazz)
+ {
+ super();
+ this.clazz = clazz;
+ }
+
+ @Override
+ public byte[] serialize(T t) throws SerializationException
+ {
+ if (t == null)
+ {
+ return new byte[0];
+ }
+ return JSON.toJSONString(t, JSONWriter.Feature.WriteClassName).getBytes(DEFAULT_CHARSET);
+ }
+
+ @Override
+ public T deserialize(byte[] bytes) throws SerializationException
+ {
+ if (bytes == null || bytes.length <= 0)
+ {
+ return null;
+ }
+ String str = new String(bytes, DEFAULT_CHARSET);
+
+ return JSON.parseObject(str, clazz, AUTO_TYPE_FILTER);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java
new file mode 100644
index 0000000..bb14c04
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/FilterConfig.java
@@ -0,0 +1,58 @@
+package com.ruoyi.framework.config;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.servlet.DispatcherType;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import com.ruoyi.common.filter.RepeatableFilter;
+import com.ruoyi.common.filter.XssFilter;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * Filter閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class FilterConfig
+{
+ @Value("${xss.excludes}")
+ private String excludes;
+
+ @Value("${xss.urlPatterns}")
+ private String urlPatterns;
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Bean
+ @ConditionalOnProperty(value = "xss.enabled", havingValue = "true")
+ public FilterRegistrationBean xssFilterRegistration()
+ {
+ FilterRegistrationBean registration = new FilterRegistrationBean();
+ registration.setDispatcherTypes(DispatcherType.REQUEST);
+ registration.setFilter(new XssFilter());
+ registration.addUrlPatterns(StringUtils.split(urlPatterns, ","));
+ registration.setName("xssFilter");
+ registration.setOrder(FilterRegistrationBean.HIGHEST_PRECEDENCE);
+ Map<String, String> initParameters = new HashMap<String, String>();
+ initParameters.put("excludes", excludes);
+ registration.setInitParameters(initParameters);
+ return registration;
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Bean
+ public FilterRegistrationBean someFilterRegistration()
+ {
+ FilterRegistrationBean registration = new FilterRegistrationBean();
+ registration.setFilter(new RepeatableFilter());
+ registration.addUrlPatterns("/*");
+ registration.setName("repeatableFilter");
+ registration.setOrder(FilterRegistrationBean.LOWEST_PRECEDENCE);
+ return registration;
+ }
+
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
new file mode 100644
index 0000000..163fd01
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/I18nConfig.java
@@ -0,0 +1,43 @@
+package com.ruoyi.framework.config;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.LocaleResolver;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
+import org.springframework.web.servlet.i18n.SessionLocaleResolver;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * 璧勬簮鏂囦欢閰嶇疆鍔犺浇
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class I18nConfig implements WebMvcConfigurer
+{
+ @Bean
+ public LocaleResolver localeResolver()
+ {
+ SessionLocaleResolver slr = new SessionLocaleResolver();
+ // 榛樿璇█
+ slr.setDefaultLocale(Constants.DEFAULT_LOCALE);
+ return slr;
+ }
+
+ @Bean
+ public LocaleChangeInterceptor localeChangeInterceptor()
+ {
+ LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
+ // 鍙傛暟鍚�
+ lci.setParamName("lang");
+ return lci;
+ }
+
+ @Override
+ public void addInterceptors(InterceptorRegistry registry)
+ {
+ registry.addInterceptor(localeChangeInterceptor());
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java
new file mode 100644
index 0000000..7f8e1d5
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/KaptchaTextCreator.java
@@ -0,0 +1,68 @@
+package com.ruoyi.framework.config;
+
+import java.util.Random;
+import com.google.code.kaptcha.text.impl.DefaultTextCreator;
+
+/**
+ * 楠岃瘉鐮佹枃鏈敓鎴愬櫒
+ *
+ * @author ruoyi
+ */
+public class KaptchaTextCreator extends DefaultTextCreator
+{
+ private static final String[] CNUMBERS = "0,1,2,3,4,5,6,7,8,9,10".split(",");
+
+ @Override
+ public String getText()
+ {
+ Integer result = 0;
+ Random random = new Random();
+ int x = random.nextInt(10);
+ int y = random.nextInt(10);
+ StringBuilder suChinese = new StringBuilder();
+ int randomoperands = random.nextInt(3);
+ if (randomoperands == 0)
+ {
+ result = x * y;
+ suChinese.append(CNUMBERS[x]);
+ suChinese.append("*");
+ suChinese.append(CNUMBERS[y]);
+ }
+ else if (randomoperands == 1)
+ {
+ if ((x != 0) && y % x == 0)
+ {
+ result = y / x;
+ suChinese.append(CNUMBERS[y]);
+ suChinese.append("/");
+ suChinese.append(CNUMBERS[x]);
+ }
+ else
+ {
+ result = x + y;
+ suChinese.append(CNUMBERS[x]);
+ suChinese.append("+");
+ suChinese.append(CNUMBERS[y]);
+ }
+ }
+ else
+ {
+ if (x >= y)
+ {
+ result = x - y;
+ suChinese.append(CNUMBERS[x]);
+ suChinese.append("-");
+ suChinese.append(CNUMBERS[y]);
+ }
+ else
+ {
+ result = y - x;
+ suChinese.append(CNUMBERS[y]);
+ suChinese.append("-");
+ suChinese.append(CNUMBERS[x]);
+ }
+ }
+ suChinese.append("=?@" + result);
+ return suChinese.toString();
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
new file mode 100644
index 0000000..3f4f485
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/RedisConfig.java
@@ -0,0 +1,69 @@
+package com.ruoyi.framework.config;
+
+import org.springframework.cache.annotation.CachingConfigurerSupport;
+import org.springframework.cache.annotation.EnableCaching;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.data.redis.connection.RedisConnectionFactory;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
+import org.springframework.data.redis.serializer.StringRedisSerializer;
+
+/**
+ * redis閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Configuration
+@EnableCaching
+public class RedisConfig extends CachingConfigurerSupport
+{
+ @Bean
+ @SuppressWarnings(value = { "unchecked", "rawtypes" })
+ public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
+ {
+ RedisTemplate<Object, Object> template = new RedisTemplate<>();
+ template.setConnectionFactory(connectionFactory);
+
+ FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);
+
+ // 浣跨敤StringRedisSerializer鏉ュ簭鍒楀寲鍜屽弽搴忓垪鍖杛edis鐨刱ey鍊�
+ template.setKeySerializer(new StringRedisSerializer());
+ template.setValueSerializer(serializer);
+
+ // Hash鐨刱ey涔熼噰鐢⊿tringRedisSerializer鐨勫簭鍒楀寲鏂瑰紡
+ template.setHashKeySerializer(new StringRedisSerializer());
+ template.setHashValueSerializer(serializer);
+
+ template.afterPropertiesSet();
+ return template;
+ }
+
+ @Bean
+ public DefaultRedisScript<Long> limitScript()
+ {
+ DefaultRedisScript<Long> redisScript = new DefaultRedisScript<>();
+ redisScript.setScriptText(limitScriptText());
+ redisScript.setResultType(Long.class);
+ return redisScript;
+ }
+
+ /**
+ * 闄愭祦鑴氭湰
+ */
+ private String limitScriptText()
+ {
+ return "local key = KEYS[1]\n" +
+ "local count = tonumber(ARGV[1])\n" +
+ "local time = tonumber(ARGV[2])\n" +
+ "local current = redis.call('get', key);\n" +
+ "if current and tonumber(current) > count then\n" +
+ " return tonumber(current);\n" +
+ "end\n" +
+ "current = redis.call('incr', key)\n" +
+ "if tonumber(current) == 1 then\n" +
+ " redis.call('expire', key, time)\n" +
+ "end\n" +
+ "return tonumber(current);";
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
new file mode 100644
index 0000000..7b0300c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ResourcesConfig.java
@@ -0,0 +1,77 @@
+package com.ruoyi.framework.config;
+
+import java.util.concurrent.TimeUnit;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.CacheControl;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+import org.springframework.web.filter.CorsFilter;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 閫氱敤閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class ResourcesConfig implements WebMvcConfigurer
+{
+ @Autowired
+ private RepeatSubmitInterceptor repeatSubmitInterceptor;
+
+ @Override
+ public void addResourceHandlers(ResourceHandlerRegistry registry)
+ {
+ /** 鏈湴鏂囦欢涓婁紶璺緞 */
+ registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
+ .addResourceLocations("file:" + RuoYiConfig.getProfile() + "/");
+//
+// /** swagger閰嶇疆 */
+// registry.addResourceHandler("/swagger-ui/**")
+// .addResourceLocations("classpath:/META-INF/resources/webjars/springfox-swagger-ui/")
+// .setCacheControl(CacheControl.maxAge(5, TimeUnit.HOURS).cachePublic());
+
+ registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
+ registry.addResourceHandler("/favicon.ico").addResourceLocations("classpath:/META-INF/resources/");
+ registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
+ }
+
+ /**
+ * 鑷畾涔夋嫤鎴鍒�
+ */
+ @Override
+ public void addInterceptors(InterceptorRegistry registry)
+ {
+ registry.addInterceptor(repeatSubmitInterceptor).addPathPatterns("/**");
+ }
+
+ /**
+ * 璺ㄥ煙閰嶇疆
+ */
+ @Bean
+ public CorsFilter corsFilter()
+ {
+ CorsConfiguration config = new CorsConfiguration();
+ config.setAllowCredentials(true);
+ // 璁剧疆璁块棶婧愬湴鍧�
+ config.addAllowedOriginPattern("*");
+ // 璁剧疆璁块棶婧愯姹傚ご
+ config.addAllowedHeader("*");
+ // 璁剧疆璁块棶婧愯姹傛柟娉�
+ config.addAllowedMethod("*");
+ // 鏈夋晥鏈� 1800绉�
+ config.setMaxAge(1800L);
+ // 娣诲姞鏄犲皠璺緞锛屾嫤鎴竴鍒囪姹�
+ UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
+ source.registerCorsConfiguration("/**", config);
+ // 杩斿洖鏂扮殑CorsFilter
+ return new CorsFilter(source);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
new file mode 100644
index 0000000..511842b
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java
@@ -0,0 +1,139 @@
+package com.ruoyi.framework.config;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.ProviderManager;
+import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.http.SessionCreationPolicy;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
+import org.springframework.security.web.SecurityFilterChain;
+import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
+import org.springframework.security.web.authentication.logout.LogoutFilter;
+import org.springframework.web.filter.CorsFilter;
+import com.ruoyi.framework.config.properties.PermitAllUrlProperties;
+import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter;
+import com.ruoyi.framework.security.handle.AuthenticationEntryPointImpl;
+import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl;
+
+/**
+ * spring security閰嶇疆
+ *
+ * @author ruoyi
+ */
+@EnableMethodSecurity(prePostEnabled = true, securedEnabled = true)
+@Configuration
+public class SecurityConfig
+{
+ /**
+ * 鑷畾涔夌敤鎴疯璇侀�昏緫
+ */
+ @Autowired
+ private UserDetailsService userDetailsService;
+
+ /**
+ * 璁よ瘉澶辫触澶勭悊绫�
+ */
+ @Autowired
+ private AuthenticationEntryPointImpl unauthorizedHandler;
+
+ /**
+ * 閫�鍑哄鐞嗙被
+ */
+ @Autowired
+ private LogoutSuccessHandlerImpl logoutSuccessHandler;
+
+ /**
+ * token璁よ瘉杩囨护鍣�
+ */
+ @Autowired
+ private JwtAuthenticationTokenFilter authenticationTokenFilter;
+
+ /**
+ * 璺ㄥ煙杩囨护鍣�
+ */
+ @Autowired
+ private CorsFilter corsFilter;
+
+ /**
+ * 鍏佽鍖垮悕璁块棶鐨勫湴鍧�
+ */
+ @Autowired
+ private PermitAllUrlProperties permitAllUrl;
+
+ /**
+ * 韬唤楠岃瘉瀹炵幇
+ */
+ @Bean
+ public AuthenticationManager authenticationManager()
+ {
+ DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
+ daoAuthenticationProvider.setUserDetailsService(userDetailsService);
+ daoAuthenticationProvider.setPasswordEncoder(bCryptPasswordEncoder());
+ return new ProviderManager(daoAuthenticationProvider);
+ }
+
+ /**
+ * anyRequest | 鍖归厤鎵�鏈夎姹傝矾寰�
+ * access | SpringEl琛ㄨ揪寮忕粨鏋滀负true鏃跺彲浠ヨ闂�
+ * anonymous | 鍖垮悕鍙互璁块棶
+ * denyAll | 鐢ㄦ埛涓嶈兘璁块棶
+ * fullyAuthenticated | 鐢ㄦ埛瀹屽叏璁よ瘉鍙互璁块棶锛堥潪remember-me涓嬭嚜鍔ㄧ櫥褰曪級
+ * hasAnyAuthority | 濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず鏉冮檺锛屽垯鍏朵腑浠讳綍涓�涓潈闄愬彲浠ヨ闂�
+ * hasAnyRole | 濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず瑙掕壊锛屽垯鍏朵腑浠讳綍涓�涓鑹插彲浠ヨ闂�
+ * hasAuthority | 濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず鏉冮檺锛屽垯鍏舵潈闄愬彲浠ヨ闂�
+ * hasIpAddress | 濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧずIP鍦板潃锛屽鏋滅敤鎴稩P鍜屽弬鏁板尮閰嶏紝鍒欏彲浠ヨ闂�
+ * hasRole | 濡傛灉鏈夊弬鏁帮紝鍙傛暟琛ㄧず瑙掕壊锛屽垯鍏惰鑹插彲浠ヨ闂�
+ * permitAll | 鐢ㄦ埛鍙互浠绘剰璁块棶
+ * rememberMe | 鍏佽閫氳繃remember-me鐧诲綍鐨勭敤鎴疯闂�
+ * authenticated | 鐢ㄦ埛鐧诲綍鍚庡彲璁块棶
+ */
+ @Bean
+ protected SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception
+ {
+ return httpSecurity
+ // CSRF绂佺敤锛屽洜涓轰笉浣跨敤session
+ .csrf(csrf -> csrf.disable())
+ // 绂佺敤HTTP鍝嶅簲鏍囧ご
+ .headers((headersCustomizer) -> {
+ headersCustomizer.cacheControl(cache -> cache.disable()).frameOptions(options -> options.sameOrigin());
+ })
+ // 璁よ瘉澶辫触澶勭悊绫�
+ .exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
+ // 鍩轰簬token锛屾墍浠ヤ笉闇�瑕乻ession
+ .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
+ // 娉ㄨВ鏍囪鍏佽鍖垮悕璁块棶鐨剈rl
+ .authorizeHttpRequests((requests) -> {
+ permitAllUrl.getUrls().forEach(url -> requests.antMatchers(url).permitAll());
+ // 瀵逛簬鐧诲綍login 娉ㄥ唽register 楠岃瘉鐮乧aptchaImage 鍏佽鍖垮悕璁块棶
+ requests.antMatchers("/login", "/register", "/captchaImage").permitAll()
+ // 闈欐�佽祫婧愶紝鍙尶鍚嶈闂�
+ .antMatchers(HttpMethod.GET, "/", "/*.html", "/**/*.html", "/**/*.css", "/**/*.js", "/profile/**").permitAll()
+ .antMatchers("/swagger-ui.html", "/swagger-resources/**", "/webjars/**", "/*/api-docs", "/druid/**").permitAll()
+ // 闄や笂闈㈠鐨勬墍鏈夎姹傚叏閮ㄩ渶瑕侀壌鏉冭璇�
+ .anyRequest().authenticated();
+ })
+ // 娣诲姞Logout filter
+ .logout(logout -> logout.logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler))
+ // 娣诲姞JWT filter
+ .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class)
+ // 娣诲姞CORS filter
+ .addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class)
+ .addFilterBefore(corsFilter, LogoutFilter.class)
+ .build();
+ }
+
+ /**
+ * 寮烘暎鍒楀搱甯屽姞瀵嗗疄鐜�
+ */
+ @Bean
+ public BCryptPasswordEncoder bCryptPasswordEncoder()
+ {
+ return new BCryptPasswordEncoder();
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java
new file mode 100644
index 0000000..b5b7de3
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ServerConfig.java
@@ -0,0 +1,32 @@
+package com.ruoyi.framework.config;
+
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.ServletUtils;
+
+/**
+ * 鏈嶅姟鐩稿叧閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Component
+public class ServerConfig
+{
+ /**
+ * 鑾峰彇瀹屾暣鐨勮姹傝矾寰勶紝鍖呮嫭锛氬煙鍚嶏紝绔彛锛屼笂涓嬫枃璁块棶璺緞
+ *
+ * @return 鏈嶅姟鍦板潃
+ */
+ public String getUrl()
+ {
+ HttpServletRequest request = ServletUtils.getRequest();
+ return getDomain(request);
+ }
+
+ public static String getDomain(HttpServletRequest request)
+ {
+ StringBuffer url = request.getRequestURL();
+ String contextPath = request.getServletContext().getContextPath();
+ return url.delete(url.length() - request.getRequestURI().length(), url.length()).append(contextPath).toString();
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java
new file mode 100644
index 0000000..7840141
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ThreadPoolConfig.java
@@ -0,0 +1,63 @@
+package com.ruoyi.framework.config;
+
+import com.ruoyi.common.utils.Threads;
+import org.apache.commons.lang3.concurrent.BasicThreadFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * 绾跨▼姹犻厤缃�
+ *
+ * @author ruoyi
+ **/
+@Configuration
+public class ThreadPoolConfig
+{
+ // 鏍稿績绾跨▼姹犲ぇ灏�
+ private int corePoolSize = 50;
+
+ // 鏈�澶у彲鍒涘缓鐨勭嚎绋嬫暟
+ private int maxPoolSize = 200;
+
+ // 闃熷垪鏈�澶ч暱搴�
+ private int queueCapacity = 1000;
+
+ // 绾跨▼姹犵淮鎶ょ嚎绋嬫墍鍏佽鐨勭┖闂叉椂闂�
+ private int keepAliveSeconds = 300;
+
+ @Bean(name = "threadPoolTaskExecutor")
+ public ThreadPoolTaskExecutor threadPoolTaskExecutor()
+ {
+ ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+ executor.setMaxPoolSize(maxPoolSize);
+ executor.setCorePoolSize(corePoolSize);
+ executor.setQueueCapacity(queueCapacity);
+ executor.setKeepAliveSeconds(keepAliveSeconds);
+ // 绾跨▼姹犲鎷掔粷浠诲姟(鏃犵嚎绋嬪彲鐢�)鐨勫鐞嗙瓥鐣�
+ executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
+ return executor;
+ }
+
+ /**
+ * 鎵ц鍛ㄦ湡鎬ф垨瀹氭椂浠诲姟
+ */
+ @Bean(name = "scheduledExecutorService")
+ protected ScheduledExecutorService scheduledExecutorService()
+ {
+ return new ScheduledThreadPoolExecutor(corePoolSize,
+ new BasicThreadFactory.Builder().namingPattern("schedule-pool-%d").daemon(true).build(),
+ new ThreadPoolExecutor.CallerRunsPolicy())
+ {
+ @Override
+ protected void afterExecute(Runnable r, Throwable t)
+ {
+ super.afterExecute(r, t);
+ Threads.printException(r, t);
+ }
+ };
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java
new file mode 100644
index 0000000..c8a5c8a
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/DruidProperties.java
@@ -0,0 +1,89 @@
+package com.ruoyi.framework.config.properties;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import com.alibaba.druid.pool.DruidDataSource;
+
+/**
+ * druid 閰嶇疆灞炴��
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class DruidProperties
+{
+ @Value("${spring.datasource.druid.initialSize}")
+ private int initialSize;
+
+ @Value("${spring.datasource.druid.minIdle}")
+ private int minIdle;
+
+ @Value("${spring.datasource.druid.maxActive}")
+ private int maxActive;
+
+ @Value("${spring.datasource.druid.maxWait}")
+ private int maxWait;
+
+ @Value("${spring.datasource.druid.connectTimeout}")
+ private int connectTimeout;
+
+ @Value("${spring.datasource.druid.socketTimeout}")
+ private int socketTimeout;
+
+ @Value("${spring.datasource.druid.timeBetweenEvictionRunsMillis}")
+ private int timeBetweenEvictionRunsMillis;
+
+ @Value("${spring.datasource.druid.minEvictableIdleTimeMillis}")
+ private int minEvictableIdleTimeMillis;
+
+ @Value("${spring.datasource.druid.maxEvictableIdleTimeMillis}")
+ private int maxEvictableIdleTimeMillis;
+
+ @Value("${spring.datasource.druid.validationQuery}")
+ private String validationQuery;
+
+ @Value("${spring.datasource.druid.testWhileIdle}")
+ private boolean testWhileIdle;
+
+ @Value("${spring.datasource.druid.testOnBorrow}")
+ private boolean testOnBorrow;
+
+ @Value("${spring.datasource.druid.testOnReturn}")
+ private boolean testOnReturn;
+
+ public DruidDataSource dataSource(DruidDataSource datasource)
+ {
+ /** 閰嶇疆鍒濆鍖栧ぇ灏忋�佹渶灏忋�佹渶澶� */
+ datasource.setInitialSize(initialSize);
+ datasource.setMaxActive(maxActive);
+ datasource.setMinIdle(minIdle);
+
+ /** 閰嶇疆鑾峰彇杩炴帴绛夊緟瓒呮椂鐨勬椂闂� */
+ datasource.setMaxWait(maxWait);
+
+ /** 閰嶇疆椹卞姩杩炴帴瓒呮椂鏃堕棿锛屾娴嬫暟鎹簱寤虹珛杩炴帴鐨勮秴鏃舵椂闂达紝鍗曚綅鏄绉� */
+ datasource.setConnectTimeout(connectTimeout);
+
+ /** 閰嶇疆缃戠粶瓒呮椂鏃堕棿锛岀瓑寰呮暟鎹簱鎿嶄綔瀹屾垚鐨勭綉缁滆秴鏃舵椂闂达紝鍗曚綅鏄绉� */
+ datasource.setSocketTimeout(socketTimeout);
+
+ /** 閰嶇疆闂撮殧澶氫箙鎵嶈繘琛屼竴娆℃娴嬶紝妫�娴嬮渶瑕佸叧闂殑绌洪棽杩炴帴锛屽崟浣嶆槸姣 */
+ datasource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
+
+ /** 閰嶇疆涓�涓繛鎺ュ湪姹犱腑鏈�灏忋�佹渶澶х敓瀛樼殑鏃堕棿锛屽崟浣嶆槸姣 */
+ datasource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
+ datasource.setMaxEvictableIdleTimeMillis(maxEvictableIdleTimeMillis);
+
+ /**
+ * 鐢ㄦ潵妫�娴嬭繛鎺ユ槸鍚︽湁鏁堢殑sql锛岃姹傛槸涓�涓煡璇㈣鍙ワ紝甯哥敤select 'x'銆傚鏋渧alidationQuery涓簄ull锛宼estOnBorrow銆乼estOnReturn銆乼estWhileIdle閮戒笉浼氳捣浣滅敤銆�
+ */
+ datasource.setValidationQuery(validationQuery);
+ /** 寤鸿閰嶇疆涓簍rue锛屼笉褰卞搷鎬ц兘锛屽苟涓斾繚璇佸畨鍏ㄦ�с�傜敵璇疯繛鎺ョ殑鏃跺�欐娴嬶紝濡傛灉绌洪棽鏃堕棿澶т簬timeBetweenEvictionRunsMillis锛屾墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堛�� */
+ datasource.setTestWhileIdle(testWhileIdle);
+ /** 鐢宠杩炴帴鏃舵墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堬紝鍋氫簡杩欎釜閰嶇疆浼氶檷浣庢�ц兘銆� */
+ datasource.setTestOnBorrow(testOnBorrow);
+ /** 褰掕繕杩炴帴鏃舵墽琛寁alidationQuery妫�娴嬭繛鎺ユ槸鍚︽湁鏁堬紝鍋氫簡杩欎釜閰嶇疆浼氶檷浣庢�ц兘銆� */
+ datasource.setTestOnReturn(testOnReturn);
+ return datasource;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
new file mode 100644
index 0000000..29118fa
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/properties/PermitAllUrlProperties.java
@@ -0,0 +1,73 @@
+package com.ruoyi.framework.config.properties;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.regex.Pattern;
+import org.apache.commons.lang3.RegExUtils;
+import org.springframework.beans.BeansException;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
+import com.ruoyi.common.annotation.Anonymous;
+
+/**
+ * 璁剧疆Anonymous娉ㄨВ鍏佽鍖垮悕璁块棶鐨剈rl
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class PermitAllUrlProperties implements InitializingBean, ApplicationContextAware
+{
+ private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");
+
+ private ApplicationContext applicationContext;
+
+ private List<String> urls = new ArrayList<>();
+
+ public String ASTERISK = "*";
+
+ @Override
+ public void afterPropertiesSet()
+ {
+ RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
+ Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
+
+ map.keySet().forEach(info -> {
+ HandlerMethod handlerMethod = map.get(info);
+
+ // 鑾峰彇鏂规硶涓婅竟鐨勬敞瑙� 鏇夸唬path variable 涓� *
+ Anonymous method = AnnotationUtils.findAnnotation(handlerMethod.getMethod(), Anonymous.class);
+ Optional.ofNullable(method).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
+ .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
+
+ // 鑾峰彇绫讳笂杈圭殑娉ㄨВ, 鏇夸唬path variable 涓� *
+ Anonymous controller = AnnotationUtils.findAnnotation(handlerMethod.getBeanType(), Anonymous.class);
+ Optional.ofNullable(controller).ifPresent(anonymous -> Objects.requireNonNull(info.getPatternsCondition().getPatterns())
+ .forEach(url -> urls.add(RegExUtils.replaceAll(url, PATTERN, ASTERISK))));
+ });
+ }
+
+ @Override
+ public void setApplicationContext(ApplicationContext context) throws BeansException
+ {
+ this.applicationContext = context;
+ }
+
+ public List<String> getUrls()
+ {
+ return urls;
+ }
+
+ public void setUrls(List<String> urls)
+ {
+ this.urls = urls;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java
new file mode 100644
index 0000000..e70b8cf
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSource.java
@@ -0,0 +1,26 @@
+package com.ruoyi.framework.datasource;
+
+import java.util.Map;
+import javax.sql.DataSource;
+import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
+
+/**
+ * 鍔ㄦ�佹暟鎹簮
+ *
+ * @author ruoyi
+ */
+public class DynamicDataSource extends AbstractRoutingDataSource
+{
+ public DynamicDataSource(DataSource defaultTargetDataSource, Map<Object, Object> targetDataSources)
+ {
+ super.setDefaultTargetDataSource(defaultTargetDataSource);
+ super.setTargetDataSources(targetDataSources);
+ super.afterPropertiesSet();
+ }
+
+ @Override
+ protected Object determineCurrentLookupKey()
+ {
+ return DynamicDataSourceContextHolder.getDataSourceType();
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java
new file mode 100644
index 0000000..9770af6
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/datasource/DynamicDataSourceContextHolder.java
@@ -0,0 +1,45 @@
+package com.ruoyi.framework.datasource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 鏁版嵁婧愬垏鎹㈠鐞�
+ *
+ * @author ruoyi
+ */
+public class DynamicDataSourceContextHolder
+{
+ public static final Logger log = LoggerFactory.getLogger(DynamicDataSourceContextHolder.class);
+
+ /**
+ * 浣跨敤ThreadLocal缁存姢鍙橀噺锛孴hreadLocal涓烘瘡涓娇鐢ㄨ鍙橀噺鐨勭嚎绋嬫彁渚涚嫭绔嬬殑鍙橀噺鍓湰锛�
+ * 鎵�浠ユ瘡涓�涓嚎绋嬮兘鍙互鐙珛鍦版敼鍙樿嚜宸辩殑鍓湰锛岃�屼笉浼氬奖鍝嶅叾瀹冪嚎绋嬫墍瀵瑰簲鐨勫壇鏈��
+ */
+ private static final ThreadLocal<String> CONTEXT_HOLDER = new ThreadLocal<>();
+
+ /**
+ * 璁剧疆鏁版嵁婧愮殑鍙橀噺
+ */
+ public static void setDataSourceType(String dsType)
+ {
+ log.info("鍒囨崲鍒皗}鏁版嵁婧�", dsType);
+ CONTEXT_HOLDER.set(dsType);
+ }
+
+ /**
+ * 鑾峰緱鏁版嵁婧愮殑鍙橀噺
+ */
+ public static String getDataSourceType()
+ {
+ return CONTEXT_HOLDER.get();
+ }
+
+ /**
+ * 娓呯┖鏁版嵁婧愬彉閲�
+ */
+ public static void clearDataSourceType()
+ {
+ CONTEXT_HOLDER.remove();
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
new file mode 100644
index 0000000..c49eaf4
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/RepeatSubmitInterceptor.java
@@ -0,0 +1,56 @@
+package com.ruoyi.framework.interceptor;
+
+import java.lang.reflect.Method;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.stereotype.Component;
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.ServletUtils;
+
+/**
+ * 闃叉閲嶅鎻愪氦鎷︽埅鍣�
+ *
+ * @author ruoyi
+ */
+@Component
+public abstract class RepeatSubmitInterceptor implements HandlerInterceptor
+{
+ @Override
+ public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception
+ {
+ if (handler instanceof HandlerMethod)
+ {
+ HandlerMethod handlerMethod = (HandlerMethod) handler;
+ Method method = handlerMethod.getMethod();
+ RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class);
+ if (annotation != null)
+ {
+ if (this.isRepeatSubmit(request, annotation))
+ {
+ AjaxResult ajaxResult = AjaxResult.error(annotation.message());
+ ServletUtils.renderString(response, JSON.toJSONString(ajaxResult));
+ return false;
+ }
+ }
+ return true;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ /**
+ * 楠岃瘉鏄惁閲嶅鎻愪氦鐢卞瓙绫诲疄鐜板叿浣撶殑闃查噸澶嶆彁浜ょ殑瑙勫垯
+ *
+ * @param request 璇锋眰淇℃伅
+ * @param annotation 闃查噸澶嶆敞瑙e弬鏁�
+ * @return 缁撴灉
+ * @throws Exception
+ */
+ public abstract boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation);
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
new file mode 100644
index 0000000..9dc9511
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/interceptor/impl/SameUrlDataInterceptor.java
@@ -0,0 +1,110 @@
+package com.ruoyi.framework.interceptor.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.HttpServletRequest;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.common.annotation.RepeatSubmit;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.filter.RepeatedlyRequestWrapper;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.http.HttpHelper;
+import com.ruoyi.framework.interceptor.RepeatSubmitInterceptor;
+
+/**
+ * 鍒ゆ柇璇锋眰url鍜屾暟鎹槸鍚﹀拰涓婁竴娆$浉鍚岋紝
+ * 濡傛灉鍜屼笂娆$浉鍚岋紝鍒欐槸閲嶅鎻愪氦琛ㄥ崟銆� 鏈夋晥鏃堕棿涓�10绉掑唴銆�
+ *
+ * @author ruoyi
+ */
+@Component
+public class SameUrlDataInterceptor extends RepeatSubmitInterceptor
+{
+ public final String REPEAT_PARAMS = "repeatParams";
+
+ public final String REPEAT_TIME = "repeatTime";
+
+ // 浠ょ墝鑷畾涔夋爣璇�
+ @Value("${token.header}")
+ private String header;
+
+ @Autowired
+ private RedisCache redisCache;
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean isRepeatSubmit(HttpServletRequest request, RepeatSubmit annotation)
+ {
+ String nowParams = "";
+ if (request instanceof RepeatedlyRequestWrapper)
+ {
+ RepeatedlyRequestWrapper repeatedlyRequest = (RepeatedlyRequestWrapper) request;
+ nowParams = HttpHelper.getBodyString(repeatedlyRequest);
+ }
+
+ // body鍙傛暟涓虹┖锛岃幏鍙朠arameter鐨勬暟鎹�
+ if (StringUtils.isEmpty(nowParams))
+ {
+ nowParams = JSON.toJSONString(request.getParameterMap());
+ }
+ Map<String, Object> nowDataMap = new HashMap<String, Object>();
+ nowDataMap.put(REPEAT_PARAMS, nowParams);
+ nowDataMap.put(REPEAT_TIME, System.currentTimeMillis());
+
+ // 璇锋眰鍦板潃锛堜綔涓哄瓨鏀綾ache鐨刱ey鍊硷級
+ String url = request.getRequestURI();
+
+ // 鍞竴鍊硷紙娌℃湁娑堟伅澶村垯浣跨敤璇锋眰鍦板潃锛�
+ String submitKey = StringUtils.trimToEmpty(request.getHeader(header));
+
+ // 鍞竴鏍囪瘑锛堟寚瀹歬ey + url + 娑堟伅澶达級
+ String cacheRepeatKey = CacheConstants.REPEAT_SUBMIT_KEY + url + submitKey;
+
+ Object sessionObj = redisCache.getCacheObject(cacheRepeatKey);
+ if (sessionObj != null)
+ {
+ Map<String, Object> sessionMap = (Map<String, Object>) sessionObj;
+ if (sessionMap.containsKey(url))
+ {
+ Map<String, Object> preDataMap = (Map<String, Object>) sessionMap.get(url);
+ if (compareParams(nowDataMap, preDataMap) && compareTime(nowDataMap, preDataMap, annotation.interval()))
+ {
+ return true;
+ }
+ }
+ }
+ Map<String, Object> cacheMap = new HashMap<String, Object>();
+ cacheMap.put(url, nowDataMap);
+ redisCache.setCacheObject(cacheRepeatKey, cacheMap, annotation.interval(), TimeUnit.MILLISECONDS);
+ return false;
+ }
+
+ /**
+ * 鍒ゆ柇鍙傛暟鏄惁鐩稿悓
+ */
+ private boolean compareParams(Map<String, Object> nowMap, Map<String, Object> preMap)
+ {
+ String nowParams = (String) nowMap.get(REPEAT_PARAMS);
+ String preParams = (String) preMap.get(REPEAT_PARAMS);
+ return nowParams.equals(preParams);
+ }
+
+ /**
+ * 鍒ゆ柇涓ゆ闂撮殧鏃堕棿
+ */
+ private boolean compareTime(Map<String, Object> nowMap, Map<String, Object> preMap, int interval)
+ {
+ long time1 = (Long) nowMap.get(REPEAT_TIME);
+ long time2 = (Long) preMap.get(REPEAT_TIME);
+ if ((time1 - time2) < interval)
+ {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java
new file mode 100644
index 0000000..7387a02
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/AsyncManager.java
@@ -0,0 +1,55 @@
+package com.ruoyi.framework.manager;
+
+import java.util.TimerTask;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import com.ruoyi.common.utils.Threads;
+import com.ruoyi.common.utils.spring.SpringUtils;
+
+/**
+ * 寮傛浠诲姟绠$悊鍣�
+ *
+ * @author ruoyi
+ */
+public class AsyncManager
+{
+ /**
+ * 鎿嶄綔寤惰繜10姣
+ */
+ private final int OPERATE_DELAY_TIME = 10;
+
+ /**
+ * 寮傛鎿嶄綔浠诲姟璋冨害绾跨▼姹�
+ */
+ private ScheduledExecutorService executor = SpringUtils.getBean("scheduledExecutorService");
+
+ /**
+ * 鍗曚緥妯″紡
+ */
+ private AsyncManager(){}
+
+ private static AsyncManager me = new AsyncManager();
+
+ public static AsyncManager me()
+ {
+ return me;
+ }
+
+ /**
+ * 鎵ц浠诲姟
+ *
+ * @param task 浠诲姟
+ */
+ public void execute(TimerTask task)
+ {
+ executor.schedule(task, OPERATE_DELAY_TIME, TimeUnit.MILLISECONDS);
+ }
+
+ /**
+ * 鍋滄浠诲姟绾跨▼姹�
+ */
+ public void shutdown()
+ {
+ Threads.shutdownAndAwaitTermination(executor);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
new file mode 100644
index 0000000..e36ca3c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/ShutdownManager.java
@@ -0,0 +1,39 @@
+package com.ruoyi.framework.manager;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+import javax.annotation.PreDestroy;
+
+/**
+ * 纭繚搴旂敤閫�鍑烘椂鑳藉叧闂悗鍙扮嚎绋�
+ *
+ * @author ruoyi
+ */
+@Component
+public class ShutdownManager
+{
+ private static final Logger logger = LoggerFactory.getLogger("sys-user");
+
+ @PreDestroy
+ public void destroy()
+ {
+ shutdownAsyncManager();
+ }
+
+ /**
+ * 鍋滄寮傛鎵ц浠诲姟
+ */
+ private void shutdownAsyncManager()
+ {
+ try
+ {
+ logger.info("====鍏抽棴鍚庡彴浠诲姟浠诲姟绾跨▼姹�====");
+ AsyncManager.me().shutdown();
+ }
+ catch (Exception e)
+ {
+ logger.error(e.getMessage(), e);
+ }
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java
new file mode 100644
index 0000000..267e305
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/manager/factory/AsyncFactory.java
@@ -0,0 +1,102 @@
+package com.ruoyi.framework.manager.factory;
+
+import java.util.TimerTask;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.utils.LogUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.AddressUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.service.ISysLogininforService;
+import com.ruoyi.system.service.ISysOperLogService;
+import eu.bitwalker.useragentutils.UserAgent;
+
+/**
+ * 寮傛宸ュ巶锛堜骇鐢熶换鍔$敤锛�
+ *
+ * @author ruoyi
+ */
+public class AsyncFactory
+{
+ private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
+
+ /**
+ * 璁板綍鐧诲綍淇℃伅
+ *
+ * @param username 鐢ㄦ埛鍚�
+ * @param status 鐘舵��
+ * @param message 娑堟伅
+ * @param args 鍒楄〃
+ * @return 浠诲姟task
+ */
+ public static TimerTask recordLogininfor(final String username, final String status, final String message,
+ final Object... args)
+ {
+ final UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+ final String ip = IpUtils.getIpAddr();
+ return new TimerTask()
+ {
+ @Override
+ public void run()
+ {
+ String address = AddressUtils.getRealAddressByIP(ip);
+ StringBuilder s = new StringBuilder();
+ s.append(LogUtils.getBlock(ip));
+ s.append(address);
+ s.append(LogUtils.getBlock(username));
+ s.append(LogUtils.getBlock(status));
+ s.append(LogUtils.getBlock(message));
+ // 鎵撳嵃淇℃伅鍒版棩蹇�
+ sys_user_logger.info(s.toString(), args);
+ // 鑾峰彇瀹㈡埛绔搷浣滅郴缁�
+ String os = userAgent.getOperatingSystem().getName();
+ // 鑾峰彇瀹㈡埛绔祻瑙堝櫒
+ String browser = userAgent.getBrowser().getName();
+ // 灏佽瀵硅薄
+ SysLogininfor logininfor = new SysLogininfor();
+ logininfor.setUserName(username);
+ logininfor.setIpaddr(ip);
+ logininfor.setLoginLocation(address);
+ logininfor.setBrowser(browser);
+ logininfor.setOs(os);
+ logininfor.setMsg(message);
+ // 鏃ュ織鐘舵��
+ if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER))
+ {
+ logininfor.setStatus(Constants.SUCCESS);
+ }
+ else if (Constants.LOGIN_FAIL.equals(status))
+ {
+ logininfor.setStatus(Constants.FAIL);
+ }
+ // 鎻掑叆鏁版嵁
+ SpringUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
+ }
+ };
+ }
+
+ /**
+ * 鎿嶄綔鏃ュ織璁板綍
+ *
+ * @param operLog 鎿嶄綔鏃ュ織淇℃伅
+ * @return 浠诲姟task
+ */
+ public static TimerTask recordOper(final SysOperLog operLog)
+ {
+ return new TimerTask()
+ {
+ @Override
+ public void run()
+ {
+ // 杩滅▼鏌ヨ鎿嶄綔鍦扮偣
+ operLog.setOperLocation(AddressUtils.getRealAddressByIP(operLog.getOperIp()));
+ SpringUtils.getBean(ISysOperLogService.class).insertOperlog(operLog);
+ }
+ };
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBaseMapper.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBaseMapper.java
new file mode 100644
index 0000000..e7b6391
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBaseMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.framework.mybatis_config;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+import java.util.List;
+
+/**
+ * 鑷畾涔夋坊鍔爉ybatis-plus鎵归噺娣诲姞
+ * @param <T>
+ */
+public interface MyBaseMapper <T> extends BaseMapper<T> {
+
+ int insertBatchSomeColumn(List<T> entityList);
+}
+
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBatisPlusConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBatisPlusConfig.java
new file mode 100644
index 0000000..6876062
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MyBatisPlusConfig.java
@@ -0,0 +1,27 @@
+package com.ruoyi.framework.mybatis_config;
+
+import com.baomidou.mybatisplus.annotation.DbType;
+import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
+import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+
+@Configuration
+public class MyBatisPlusConfig {
+
+ /**
+ * 闇�瑕侀厤缃嫤鎴櫒锛屼笉鐒跺湪AddDevice涓殑total鏃犳硶鑾峰彇鍒�
+ * @return
+ */
+ @Bean
+ public MybatisPlusInterceptor mybatisPlusInterceptor(){
+ MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
+ // 涔愯閿�
+ interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
+ // 鍒嗛〉閰嶇疆
+ interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
+ return interceptor;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MySqlInjector.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MySqlInjector.java
new file mode 100644
index 0000000..e049473
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/mybatis_config/MySqlInjector.java
@@ -0,0 +1,24 @@
+package com.ruoyi.framework.mybatis_config;
+
+import com.baomidou.mybatisplus.core.injector.AbstractMethod;
+import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;
+import com.baomidou.mybatisplus.core.metadata.TableInfo;
+import com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
+import org.springframework.stereotype.Component;
+
+import java.util.List;
+
+/**
+ * 鎵归噺娣诲姞
+ */
+@Component
+public class MySqlInjector extends DefaultSqlInjector {
+
+ @Override
+ public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
+ List<AbstractMethod> methodList = super.getMethodList(mapperClass, tableInfo);
+ //澧炲姞鑷畾涔夋柟娉曪紝瀛楁娉ㄨВ涓婁笉绛変簬FieldFill.DEFAULT鐨勫瓧娈垫墠浼氭彃鍏�
+ methodList.add(new InsertBatchSomeColumn(t->!t.isLogicDelete()));
+ return methodList;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java
new file mode 100644
index 0000000..6c776ce
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/AuthenticationContextHolder.java
@@ -0,0 +1,28 @@
+package com.ruoyi.framework.security.context;
+
+import org.springframework.security.core.Authentication;
+
+/**
+ * 韬唤楠岃瘉淇℃伅
+ *
+ * @author ruoyi
+ */
+public class AuthenticationContextHolder
+{
+ private static final ThreadLocal<Authentication> contextHolder = new ThreadLocal<>();
+
+ public static Authentication getContext()
+ {
+ return contextHolder.get();
+ }
+
+ public static void setContext(Authentication context)
+ {
+ contextHolder.set(context);
+ }
+
+ public static void clearContext()
+ {
+ contextHolder.remove();
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java
new file mode 100644
index 0000000..5472f3d
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/context/PermissionContextHolder.java
@@ -0,0 +1,27 @@
+package com.ruoyi.framework.security.context;
+
+import org.springframework.web.context.request.RequestAttributes;
+import org.springframework.web.context.request.RequestContextHolder;
+import com.ruoyi.common.core.text.Convert;
+
+/**
+ * 鏉冮檺淇℃伅
+ *
+ * @author ruoyi
+ */
+public class PermissionContextHolder
+{
+ private static final String PERMISSION_CONTEXT_ATTRIBUTES = "PERMISSION_CONTEXT";
+
+ public static void setContext(String permission)
+ {
+ RequestContextHolder.currentRequestAttributes().setAttribute(PERMISSION_CONTEXT_ATTRIBUTES, permission,
+ RequestAttributes.SCOPE_REQUEST);
+ }
+
+ public static String getContext()
+ {
+ return Convert.toStr(RequestContextHolder.currentRequestAttributes().getAttribute(PERMISSION_CONTEXT_ATTRIBUTES,
+ RequestAttributes.SCOPE_REQUEST));
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
new file mode 100644
index 0000000..3eb2495
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/filter/JwtAuthenticationTokenFilter.java
@@ -0,0 +1,44 @@
+package com.ruoyi.framework.security.filter;
+
+import java.io.IOException;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
+import org.springframework.stereotype.Component;
+import org.springframework.web.filter.OncePerRequestFilter;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.web.service.TokenService;
+
+/**
+ * token杩囨护鍣� 楠岃瘉token鏈夋晥鎬�
+ *
+ * @author ruoyi
+ */
+@Component
+public class JwtAuthenticationTokenFilter extends OncePerRequestFilter
+{
+ @Autowired
+ private TokenService tokenService;
+
+ @Override
+ protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
+ throws ServletException, IOException
+ {
+ LoginUser loginUser = tokenService.getLoginUser(request);
+ if (StringUtils.isNotNull(loginUser) && StringUtils.isNull(SecurityUtils.getAuthentication()))
+ {
+ tokenService.verifyToken(loginUser);
+ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUser, null, loginUser.getAuthorities());
+ authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
+ SecurityContextHolder.getContext().setAuthentication(authenticationToken);
+ }
+ chain.doFilter(request, response);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java
new file mode 100644
index 0000000..781658c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/AuthenticationEntryPointImpl.java
@@ -0,0 +1,34 @@
+package com.ruoyi.framework.security.handle;
+
+import java.io.IOException;
+import java.io.Serializable;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.web.AuthenticationEntryPoint;
+import org.springframework.stereotype.Component;
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 璁よ瘉澶辫触澶勭悊绫� 杩斿洖鏈巿鏉�
+ *
+ * @author ruoyi
+ */
+@Component
+public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
+{
+ private static final long serialVersionUID = -8970718410437077606L;
+
+ @Override
+ public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
+ throws IOException
+ {
+ int code = HttpStatus.UNAUTHORIZED;
+ String msg = StringUtils.format("璇锋眰璁块棶锛歿}锛岃璇佸け璐ワ紝鏃犳硶璁块棶绯荤粺璧勬簮", request.getRequestURI());
+ ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java
new file mode 100644
index 0000000..ba23910
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/security/handle/LogoutSuccessHandlerImpl.java
@@ -0,0 +1,53 @@
+package com.ruoyi.framework.security.handle;
+
+import java.io.IOException;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
+import com.alibaba.fastjson2.JSON;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.framework.web.service.TokenService;
+
+/**
+ * 鑷畾涔夐��鍑哄鐞嗙被 杩斿洖鎴愬姛
+ *
+ * @author ruoyi
+ */
+@Configuration
+public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
+{
+ @Autowired
+ private TokenService tokenService;
+
+ /**
+ * 閫�鍑哄鐞�
+ *
+ * @return
+ */
+ @Override
+ public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
+ throws IOException, ServletException
+ {
+ LoginUser loginUser = tokenService.getLoginUser(request);
+ if (StringUtils.isNotNull(loginUser))
+ {
+ String userName = loginUser.getUsername();
+ // 鍒犻櫎鐢ㄦ埛缂撳瓨璁板綍
+ tokenService.delLoginUser(loginUser.getToken());
+ // 璁板綍鐢ㄦ埛閫�鍑烘棩蹇�
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(userName, Constants.LOGOUT, MessageUtils.message("user.logout.success")));
+ }
+ ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.success(MessageUtils.message("user.logout.success"))));
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java
new file mode 100644
index 0000000..63b03da
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/Server.java
@@ -0,0 +1,240 @@
+package com.ruoyi.framework.web.domain;
+
+import java.net.UnknownHostException;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import com.ruoyi.common.utils.Arith;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.framework.web.domain.server.Cpu;
+import com.ruoyi.framework.web.domain.server.Jvm;
+import com.ruoyi.framework.web.domain.server.Mem;
+import com.ruoyi.framework.web.domain.server.Sys;
+import com.ruoyi.framework.web.domain.server.SysFile;
+import oshi.SystemInfo;
+import oshi.hardware.CentralProcessor;
+import oshi.hardware.CentralProcessor.TickType;
+import oshi.hardware.GlobalMemory;
+import oshi.hardware.HardwareAbstractionLayer;
+import oshi.software.os.FileSystem;
+import oshi.software.os.OSFileStore;
+import oshi.software.os.OperatingSystem;
+import oshi.util.Util;
+
+/**
+ * 鏈嶅姟鍣ㄧ浉鍏充俊鎭�
+ *
+ * @author ruoyi
+ */
+public class Server
+{
+ private static final int OSHI_WAIT_SECOND = 1000;
+
+ /**
+ * CPU鐩稿叧淇℃伅
+ */
+ private Cpu cpu = new Cpu();
+
+ /**
+ * 鍏у瓨鐩稿叧淇℃伅
+ */
+ private Mem mem = new Mem();
+
+ /**
+ * JVM鐩稿叧淇℃伅
+ */
+ private Jvm jvm = new Jvm();
+
+ /**
+ * 鏈嶅姟鍣ㄧ浉鍏充俊鎭�
+ */
+ private Sys sys = new Sys();
+
+ /**
+ * 纾佺洏鐩稿叧淇℃伅
+ */
+ private List<SysFile> sysFiles = new LinkedList<SysFile>();
+
+ public Cpu getCpu()
+ {
+ return cpu;
+ }
+
+ public void setCpu(Cpu cpu)
+ {
+ this.cpu = cpu;
+ }
+
+ public Mem getMem()
+ {
+ return mem;
+ }
+
+ public void setMem(Mem mem)
+ {
+ this.mem = mem;
+ }
+
+ public Jvm getJvm()
+ {
+ return jvm;
+ }
+
+ public void setJvm(Jvm jvm)
+ {
+ this.jvm = jvm;
+ }
+
+ public Sys getSys()
+ {
+ return sys;
+ }
+
+ public void setSys(Sys sys)
+ {
+ this.sys = sys;
+ }
+
+ public List<SysFile> getSysFiles()
+ {
+ return sysFiles;
+ }
+
+ public void setSysFiles(List<SysFile> sysFiles)
+ {
+ this.sysFiles = sysFiles;
+ }
+
+ public void copyTo() throws Exception
+ {
+ SystemInfo si = new SystemInfo();
+ HardwareAbstractionLayer hal = si.getHardware();
+
+ setCpuInfo(hal.getProcessor());
+
+ setMemInfo(hal.getMemory());
+
+ setSysInfo();
+
+ setJvmInfo();
+
+ setSysFiles(si.getOperatingSystem());
+ }
+
+ /**
+ * 璁剧疆CPU淇℃伅
+ */
+ private void setCpuInfo(CentralProcessor processor)
+ {
+ // CPU淇℃伅
+ long[] prevTicks = processor.getSystemCpuLoadTicks();
+ Util.sleep(OSHI_WAIT_SECOND);
+ long[] ticks = processor.getSystemCpuLoadTicks();
+ long nice = ticks[TickType.NICE.getIndex()] - prevTicks[TickType.NICE.getIndex()];
+ long irq = ticks[TickType.IRQ.getIndex()] - prevTicks[TickType.IRQ.getIndex()];
+ long softirq = ticks[TickType.SOFTIRQ.getIndex()] - prevTicks[TickType.SOFTIRQ.getIndex()];
+ long steal = ticks[TickType.STEAL.getIndex()] - prevTicks[TickType.STEAL.getIndex()];
+ long cSys = ticks[TickType.SYSTEM.getIndex()] - prevTicks[TickType.SYSTEM.getIndex()];
+ long user = ticks[TickType.USER.getIndex()] - prevTicks[TickType.USER.getIndex()];
+ long iowait = ticks[TickType.IOWAIT.getIndex()] - prevTicks[TickType.IOWAIT.getIndex()];
+ long idle = ticks[TickType.IDLE.getIndex()] - prevTicks[TickType.IDLE.getIndex()];
+ long totalCpu = user + nice + cSys + idle + iowait + irq + softirq + steal;
+ cpu.setCpuNum(processor.getLogicalProcessorCount());
+ cpu.setTotal(totalCpu);
+ cpu.setSys(cSys);
+ cpu.setUsed(user);
+ cpu.setWait(iowait);
+ cpu.setFree(idle);
+ }
+
+ /**
+ * 璁剧疆鍐呭瓨淇℃伅
+ */
+ private void setMemInfo(GlobalMemory memory)
+ {
+ mem.setTotal(memory.getTotal());
+ mem.setUsed(memory.getTotal() - memory.getAvailable());
+ mem.setFree(memory.getAvailable());
+ }
+
+ /**
+ * 璁剧疆鏈嶅姟鍣ㄤ俊鎭�
+ */
+ private void setSysInfo()
+ {
+ Properties props = System.getProperties();
+ sys.setComputerName(IpUtils.getHostName());
+ sys.setComputerIp(IpUtils.getHostIp());
+ sys.setOsName(props.getProperty("os.name"));
+ sys.setOsArch(props.getProperty("os.arch"));
+ sys.setUserDir(props.getProperty("user.dir"));
+ }
+
+ /**
+ * 璁剧疆Java铏氭嫙鏈�
+ */
+ private void setJvmInfo() throws UnknownHostException
+ {
+ Properties props = System.getProperties();
+ jvm.setTotal(Runtime.getRuntime().totalMemory());
+ jvm.setMax(Runtime.getRuntime().maxMemory());
+ jvm.setFree(Runtime.getRuntime().freeMemory());
+ jvm.setVersion(props.getProperty("java.version"));
+ jvm.setHome(props.getProperty("java.home"));
+ }
+
+ /**
+ * 璁剧疆纾佺洏淇℃伅
+ */
+ private void setSysFiles(OperatingSystem os)
+ {
+ FileSystem fileSystem = os.getFileSystem();
+ List<OSFileStore> fsArray = fileSystem.getFileStores();
+ for (OSFileStore fs : fsArray)
+ {
+ long free = fs.getUsableSpace();
+ long total = fs.getTotalSpace();
+ long used = total - free;
+ SysFile sysFile = new SysFile();
+ sysFile.setDirName(fs.getMount());
+ sysFile.setSysTypeName(fs.getType());
+ sysFile.setTypeName(fs.getName());
+ sysFile.setTotal(convertFileSize(total));
+ sysFile.setFree(convertFileSize(free));
+ sysFile.setUsed(convertFileSize(used));
+ sysFile.setUsage(Arith.mul(Arith.div(used, total, 4), 100));
+ sysFiles.add(sysFile);
+ }
+ }
+
+ /**
+ * 瀛楄妭杞崲
+ *
+ * @param size 瀛楄妭澶у皬
+ * @return 杞崲鍚庡��
+ */
+ public String convertFileSize(long size)
+ {
+ long kb = 1024;
+ long mb = kb * 1024;
+ long gb = mb * 1024;
+ if (size >= gb)
+ {
+ return String.format("%.1f GB", (float) size / gb);
+ }
+ else if (size >= mb)
+ {
+ float f = (float) size / mb;
+ return String.format(f > 100 ? "%.0f MB" : "%.1f MB", f);
+ }
+ else if (size >= kb)
+ {
+ float f = (float) size / kb;
+ return String.format(f > 100 ? "%.0f KB" : "%.1f KB", f);
+ }
+ else
+ {
+ return String.format("%d B", size);
+ }
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java
new file mode 100644
index 0000000..a13a66c
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Cpu.java
@@ -0,0 +1,101 @@
+package com.ruoyi.framework.web.domain.server;
+
+import com.ruoyi.common.utils.Arith;
+
+/**
+ * CPU鐩稿叧淇℃伅
+ *
+ * @author ruoyi
+ */
+public class Cpu
+{
+ /**
+ * 鏍稿績鏁�
+ */
+ private int cpuNum;
+
+ /**
+ * CPU鎬荤殑浣跨敤鐜�
+ */
+ private double total;
+
+ /**
+ * CPU绯荤粺浣跨敤鐜�
+ */
+ private double sys;
+
+ /**
+ * CPU鐢ㄦ埛浣跨敤鐜�
+ */
+ private double used;
+
+ /**
+ * CPU褰撳墠绛夊緟鐜�
+ */
+ private double wait;
+
+ /**
+ * CPU褰撳墠绌洪棽鐜�
+ */
+ private double free;
+
+ public int getCpuNum()
+ {
+ return cpuNum;
+ }
+
+ public void setCpuNum(int cpuNum)
+ {
+ this.cpuNum = cpuNum;
+ }
+
+ public double getTotal()
+ {
+ return Arith.round(Arith.mul(total, 100), 2);
+ }
+
+ public void setTotal(double total)
+ {
+ this.total = total;
+ }
+
+ public double getSys()
+ {
+ return Arith.round(Arith.mul(sys / total, 100), 2);
+ }
+
+ public void setSys(double sys)
+ {
+ this.sys = sys;
+ }
+
+ public double getUsed()
+ {
+ return Arith.round(Arith.mul(used / total, 100), 2);
+ }
+
+ public void setUsed(double used)
+ {
+ this.used = used;
+ }
+
+ public double getWait()
+ {
+ return Arith.round(Arith.mul(wait / total, 100), 2);
+ }
+
+ public void setWait(double wait)
+ {
+ this.wait = wait;
+ }
+
+ public double getFree()
+ {
+ return Arith.round(Arith.mul(free / total, 100), 2);
+ }
+
+ public void setFree(double free)
+ {
+ this.free = free;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java
new file mode 100644
index 0000000..1fdc6ac
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Jvm.java
@@ -0,0 +1,130 @@
+package com.ruoyi.framework.web.domain.server;
+
+import java.lang.management.ManagementFactory;
+import com.ruoyi.common.utils.Arith;
+import com.ruoyi.common.utils.DateUtils;
+
+/**
+ * JVM鐩稿叧淇℃伅
+ *
+ * @author ruoyi
+ */
+public class Jvm
+{
+ /**
+ * 褰撳墠JVM鍗犵敤鐨勫唴瀛樻�绘暟(M)
+ */
+ private double total;
+
+ /**
+ * JVM鏈�澶у彲鐢ㄥ唴瀛樻�绘暟(M)
+ */
+ private double max;
+
+ /**
+ * JVM绌洪棽鍐呭瓨(M)
+ */
+ private double free;
+
+ /**
+ * JDK鐗堟湰
+ */
+ private String version;
+
+ /**
+ * JDK璺緞
+ */
+ private String home;
+
+ public double getTotal()
+ {
+ return Arith.div(total, (1024 * 1024), 2);
+ }
+
+ public void setTotal(double total)
+ {
+ this.total = total;
+ }
+
+ public double getMax()
+ {
+ return Arith.div(max, (1024 * 1024), 2);
+ }
+
+ public void setMax(double max)
+ {
+ this.max = max;
+ }
+
+ public double getFree()
+ {
+ return Arith.div(free, (1024 * 1024), 2);
+ }
+
+ public void setFree(double free)
+ {
+ this.free = free;
+ }
+
+ public double getUsed()
+ {
+ return Arith.div(total - free, (1024 * 1024), 2);
+ }
+
+ public double getUsage()
+ {
+ return Arith.mul(Arith.div(total - free, total, 4), 100);
+ }
+
+ /**
+ * 鑾峰彇JDK鍚嶇О
+ */
+ public String getName()
+ {
+ return ManagementFactory.getRuntimeMXBean().getVmName();
+ }
+
+ public String getVersion()
+ {
+ return version;
+ }
+
+ public void setVersion(String version)
+ {
+ this.version = version;
+ }
+
+ public String getHome()
+ {
+ return home;
+ }
+
+ public void setHome(String home)
+ {
+ this.home = home;
+ }
+
+ /**
+ * JDK鍚姩鏃堕棿
+ */
+ public String getStartTime()
+ {
+ return DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, DateUtils.getServerStartDate());
+ }
+
+ /**
+ * JDK杩愯鏃堕棿
+ */
+ public String getRunTime()
+ {
+ return DateUtils.timeDistance(DateUtils.getNowDate(), DateUtils.getServerStartDate());
+ }
+
+ /**
+ * 杩愯鍙傛暟
+ */
+ public String getInputArgs()
+ {
+ return ManagementFactory.getRuntimeMXBean().getInputArguments().toString();
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java
new file mode 100644
index 0000000..13eec52
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Mem.java
@@ -0,0 +1,61 @@
+package com.ruoyi.framework.web.domain.server;
+
+import com.ruoyi.common.utils.Arith;
+
+/**
+ * 鍏у瓨鐩稿叧淇℃伅
+ *
+ * @author ruoyi
+ */
+public class Mem
+{
+ /**
+ * 鍐呭瓨鎬婚噺
+ */
+ private double total;
+
+ /**
+ * 宸茬敤鍐呭瓨
+ */
+ private double used;
+
+ /**
+ * 鍓╀綑鍐呭瓨
+ */
+ private double free;
+
+ public double getTotal()
+ {
+ return Arith.div(total, (1024 * 1024 * 1024), 2);
+ }
+
+ public void setTotal(long total)
+ {
+ this.total = total;
+ }
+
+ public double getUsed()
+ {
+ return Arith.div(used, (1024 * 1024 * 1024), 2);
+ }
+
+ public void setUsed(long used)
+ {
+ this.used = used;
+ }
+
+ public double getFree()
+ {
+ return Arith.div(free, (1024 * 1024 * 1024), 2);
+ }
+
+ public void setFree(long free)
+ {
+ this.free = free;
+ }
+
+ public double getUsage()
+ {
+ return Arith.mul(Arith.div(used, total, 4), 100);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java
new file mode 100644
index 0000000..45d64d9
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/Sys.java
@@ -0,0 +1,84 @@
+package com.ruoyi.framework.web.domain.server;
+
+/**
+ * 绯荤粺鐩稿叧淇℃伅
+ *
+ * @author ruoyi
+ */
+public class Sys
+{
+ /**
+ * 鏈嶅姟鍣ㄥ悕绉�
+ */
+ private String computerName;
+
+ /**
+ * 鏈嶅姟鍣↖p
+ */
+ private String computerIp;
+
+ /**
+ * 椤圭洰璺緞
+ */
+ private String userDir;
+
+ /**
+ * 鎿嶄綔绯荤粺
+ */
+ private String osName;
+
+ /**
+ * 绯荤粺鏋舵瀯
+ */
+ private String osArch;
+
+ public String getComputerName()
+ {
+ return computerName;
+ }
+
+ public void setComputerName(String computerName)
+ {
+ this.computerName = computerName;
+ }
+
+ public String getComputerIp()
+ {
+ return computerIp;
+ }
+
+ public void setComputerIp(String computerIp)
+ {
+ this.computerIp = computerIp;
+ }
+
+ public String getUserDir()
+ {
+ return userDir;
+ }
+
+ public void setUserDir(String userDir)
+ {
+ this.userDir = userDir;
+ }
+
+ public String getOsName()
+ {
+ return osName;
+ }
+
+ public void setOsName(String osName)
+ {
+ this.osName = osName;
+ }
+
+ public String getOsArch()
+ {
+ return osArch;
+ }
+
+ public void setOsArch(String osArch)
+ {
+ this.osArch = osArch;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java
new file mode 100644
index 0000000..1320cde
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/domain/server/SysFile.java
@@ -0,0 +1,114 @@
+package com.ruoyi.framework.web.domain.server;
+
+/**
+ * 绯荤粺鏂囦欢鐩稿叧淇℃伅
+ *
+ * @author ruoyi
+ */
+public class SysFile
+{
+ /**
+ * 鐩樼璺緞
+ */
+ private String dirName;
+
+ /**
+ * 鐩樼绫诲瀷
+ */
+ private String sysTypeName;
+
+ /**
+ * 鏂囦欢绫诲瀷
+ */
+ private String typeName;
+
+ /**
+ * 鎬诲ぇ灏�
+ */
+ private String total;
+
+ /**
+ * 鍓╀綑澶у皬
+ */
+ private String free;
+
+ /**
+ * 宸茬粡浣跨敤閲�
+ */
+ private String used;
+
+ /**
+ * 璧勬簮鐨勪娇鐢ㄧ巼
+ */
+ private double usage;
+
+ public String getDirName()
+ {
+ return dirName;
+ }
+
+ public void setDirName(String dirName)
+ {
+ this.dirName = dirName;
+ }
+
+ public String getSysTypeName()
+ {
+ return sysTypeName;
+ }
+
+ public void setSysTypeName(String sysTypeName)
+ {
+ this.sysTypeName = sysTypeName;
+ }
+
+ public String getTypeName()
+ {
+ return typeName;
+ }
+
+ public void setTypeName(String typeName)
+ {
+ this.typeName = typeName;
+ }
+
+ public String getTotal()
+ {
+ return total;
+ }
+
+ public void setTotal(String total)
+ {
+ this.total = total;
+ }
+
+ public String getFree()
+ {
+ return free;
+ }
+
+ public void setFree(String free)
+ {
+ this.free = free;
+ }
+
+ public String getUsed()
+ {
+ return used;
+ }
+
+ public void setUsed(String used)
+ {
+ this.used = used;
+ }
+
+ public double getUsage()
+ {
+ return usage;
+ }
+
+ public void setUsage(double usage)
+ {
+ this.usage = usage;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
new file mode 100644
index 0000000..f5ebca7
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/exception/GlobalExceptionHandler.java
@@ -0,0 +1,146 @@
+package com.ruoyi.framework.web.exception;
+
+import javax.servlet.http.HttpServletRequest;
+
+import com.ruoyi.common.exception.DemoModeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.validation.BindException;
+import org.springframework.web.HttpRequestMethodNotSupportedException;
+import org.springframework.web.bind.MethodArgumentNotValidException;
+import org.springframework.web.bind.MissingPathVariableException;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.RestControllerAdvice;
+import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
+import com.ruoyi.common.constant.HttpStatus;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.html.EscapeUtil;
+
+/**
+ * 鍏ㄥ眬寮傚父澶勭悊鍣�
+ *
+ * @author ruoyi
+ */
+@RestControllerAdvice
+public class GlobalExceptionHandler
+{
+ private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);
+
+ /**
+ * 鏉冮檺鏍¢獙寮傚父
+ */
+ @ExceptionHandler(AccessDeniedException.class)
+ public AjaxResult handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("璇锋眰鍦板潃'{}',鏉冮檺鏍¢獙澶辫触'{}'", requestURI, e.getMessage());
+ return AjaxResult.error(HttpStatus.FORBIDDEN, "娌℃湁鏉冮檺锛岃鑱旂郴绠$悊鍛樻巿鏉�");
+ }
+
+ /**
+ * 璇锋眰鏂瑰紡涓嶆敮鎸�
+ */
+ @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
+ public AjaxResult handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
+ HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("璇锋眰鍦板潃'{}',涓嶆敮鎸�'{}'璇锋眰", requestURI, e.getMethod());
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 涓氬姟寮傚父
+ */
+ @ExceptionHandler(ServiceException.class)
+ public AjaxResult handleServiceException(ServiceException e, HttpServletRequest request)
+ {
+ log.error(e.getMessage(), e);
+ Integer code = e.getCode();
+ return StringUtils.isNotNull(code) ? AjaxResult.error(code, e.getMessage()) : AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 璇锋眰璺緞涓己灏戝繀闇�鐨勮矾寰勫彉閲�
+ */
+ @ExceptionHandler(MissingPathVariableException.class)
+ public AjaxResult handleMissingPathVariableException(MissingPathVariableException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("璇锋眰璺緞涓己灏戝繀闇�鐨勮矾寰勫彉閲�'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
+ return AjaxResult.error(String.format("璇锋眰璺緞涓己灏戝繀闇�鐨勮矾寰勫彉閲廩%s]", e.getVariableName()));
+ }
+
+ /**
+ * 璇锋眰鍙傛暟绫诲瀷涓嶅尮閰�
+ */
+ @ExceptionHandler(MethodArgumentTypeMismatchException.class)
+ public AjaxResult handleMethodArgumentTypeMismatchException(MethodArgumentTypeMismatchException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ String value = Convert.toStr(e.getValue());
+ if (StringUtils.isNotEmpty(value))
+ {
+ value = EscapeUtil.clean(value);
+ }
+ log.error("璇锋眰鍙傛暟绫诲瀷涓嶅尮閰�'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
+ return AjaxResult.error(String.format("璇锋眰鍙傛暟绫诲瀷涓嶅尮閰嶏紝鍙傛暟[%s]瑕佹眰绫诲瀷涓猴細'%s'锛屼絾杈撳叆鍊间负锛�'%s'", e.getName(), e.getRequiredType().getName(), value));
+ }
+
+ /**
+ * 鎷︽埅鏈煡鐨勮繍琛屾椂寮傚父
+ */
+ @ExceptionHandler(RuntimeException.class)
+ public AjaxResult handleRuntimeException(RuntimeException e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("璇锋眰鍦板潃'{}',鍙戠敓鏈煡寮傚父.", requestURI, e);
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 绯荤粺寮傚父
+ */
+ @ExceptionHandler(Exception.class)
+ public AjaxResult handleException(Exception e, HttpServletRequest request)
+ {
+ String requestURI = request.getRequestURI();
+ log.error("璇锋眰鍦板潃'{}',鍙戠敓绯荤粺寮傚父.", requestURI, e);
+ return AjaxResult.error(e.getMessage());
+ }
+
+ /**
+ * 鑷畾涔夐獙璇佸紓甯�
+ */
+ @ExceptionHandler(BindException.class)
+ public AjaxResult handleBindException(BindException e)
+ {
+ log.error(e.getMessage(), e);
+ String message = e.getAllErrors().get(0).getDefaultMessage();
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 鑷畾涔夐獙璇佸紓甯�
+ */
+ @ExceptionHandler(MethodArgumentNotValidException.class)
+ public Object handleMethodArgumentNotValidException(MethodArgumentNotValidException e)
+ {
+ log.error(e.getMessage(), e);
+ String message = e.getBindingResult().getFieldError().getDefaultMessage();
+ return AjaxResult.error(message);
+ }
+
+ /**
+ * 婕旂ず妯″紡寮傚父
+ */
+ @ExceptionHandler(DemoModeException.class)
+ public AjaxResult handleDemoModeException(DemoModeException e)
+ {
+ return AjaxResult.error("婕旂ず妯″紡锛屼笉鍏佽鎿嶄綔");
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
new file mode 100644
index 0000000..07d259a
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/PermissionService.java
@@ -0,0 +1,159 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.Set;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.security.context.PermissionContextHolder;
+
+/**
+ * RuoYi棣栧垱 鑷畾涔夋潈闄愬疄鐜帮紝ss鍙栬嚜SpringSecurity棣栧瓧姣�
+ *
+ * @author ruoyi
+ */
+@Service("ss")
+public class PermissionService
+{
+ /**
+ * 楠岃瘉鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+ *
+ * @param permission 鏉冮檺瀛楃涓�
+ * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+ */
+ public boolean hasPermi(String permission)
+ {
+ if (StringUtils.isEmpty(permission))
+ {
+ return false;
+ }
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
+ {
+ return false;
+ }
+ PermissionContextHolder.setContext(permission);
+ return hasPermissions(loginUser.getPermissions(), permission);
+ }
+
+ /**
+ * 楠岃瘉鐢ㄦ埛鏄惁涓嶅叿澶囨煇鏉冮檺锛屼笌 hasPermi閫昏緫鐩稿弽
+ *
+ * @param permission 鏉冮檺瀛楃涓�
+ * @return 鐢ㄦ埛鏄惁涓嶅叿澶囨煇鏉冮檺
+ */
+ public boolean lacksPermi(String permission)
+ {
+ return hasPermi(permission) != true;
+ }
+
+ /**
+ * 楠岃瘉鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓潈闄�
+ *
+ * @param permissions 浠� PERMISSION_DELIMETER 涓哄垎闅旂鐨勬潈闄愬垪琛�
+ * @return 鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓潈闄�
+ */
+ public boolean hasAnyPermi(String permissions)
+ {
+ if (StringUtils.isEmpty(permissions))
+ {
+ return false;
+ }
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
+ {
+ return false;
+ }
+ PermissionContextHolder.setContext(permissions);
+ Set<String> authorities = loginUser.getPermissions();
+ for (String permission : permissions.split(Constants.PERMISSION_DELIMETER))
+ {
+ if (permission != null && hasPermissions(authorities, permission))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鍒ゆ柇鐢ㄦ埛鏄惁鎷ユ湁鏌愪釜瑙掕壊
+ *
+ * @param role 瑙掕壊瀛楃涓�
+ * @return 鐢ㄦ埛鏄惁鍏峰鏌愯鑹�
+ */
+ public boolean hasRole(String role)
+ {
+ if (StringUtils.isEmpty(role))
+ {
+ return false;
+ }
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
+ {
+ return false;
+ }
+ for (SysRole sysRole : loginUser.getUser().getRoles())
+ {
+ String roleKey = sysRole.getRoleKey();
+ if (Constants.SUPER_ADMIN.equals(roleKey) || roleKey.equals(StringUtils.trim(role)))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 楠岃瘉鐢ㄦ埛鏄惁涓嶅叿澶囨煇瑙掕壊锛屼笌 isRole閫昏緫鐩稿弽銆�
+ *
+ * @param role 瑙掕壊鍚嶇О
+ * @return 鐢ㄦ埛鏄惁涓嶅叿澶囨煇瑙掕壊
+ */
+ public boolean lacksRole(String role)
+ {
+ return hasRole(role) != true;
+ }
+
+ /**
+ * 楠岃瘉鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓鑹�
+ *
+ * @param roles 浠� ROLE_NAMES_DELIMETER 涓哄垎闅旂鐨勮鑹插垪琛�
+ * @return 鐢ㄦ埛鏄惁鍏锋湁浠ヤ笅浠绘剰涓�涓鑹�
+ */
+ public boolean hasAnyRoles(String roles)
+ {
+ if (StringUtils.isEmpty(roles))
+ {
+ return false;
+ }
+ LoginUser loginUser = SecurityUtils.getLoginUser();
+ if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
+ {
+ return false;
+ }
+ for (String role : roles.split(Constants.ROLE_DELIMETER))
+ {
+ if (hasRole(role))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁鍖呭惈鏉冮檺
+ *
+ * @param permissions 鏉冮檺鍒楄〃
+ * @param permission 鏉冮檺瀛楃涓�
+ * @return 鐢ㄦ埛鏄惁鍏峰鏌愭潈闄�
+ */
+ private boolean hasPermissions(Set<String> permissions, String permission)
+ {
+ return permissions.contains(Constants.ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
new file mode 100644
index 0000000..fe16427
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java
@@ -0,0 +1,181 @@
+package com.ruoyi.framework.web.service;
+
+import javax.annotation.Resource;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.exception.user.BlackListException;
+import com.ruoyi.common.exception.user.CaptchaException;
+import com.ruoyi.common.exception.user.CaptchaExpireException;
+import com.ruoyi.common.exception.user.UserNotExistsException;
+import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.framework.security.context.AuthenticationContextHolder;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 鐧诲綍鏍¢獙鏂规硶
+ *
+ * @author ruoyi
+ */
+@Component
+public class SysLoginService
+{
+ @Autowired
+ private TokenService tokenService;
+
+ @Resource
+ private AuthenticationManager authenticationManager;
+
+ @Autowired
+ private RedisCache redisCache;
+
+ @Autowired
+ private ISysUserService userService;
+
+ @Autowired
+ private ISysConfigService configService;
+
+ /**
+ * 鐧诲綍楠岃瘉
+ *
+ * @param username 鐢ㄦ埛鍚�
+ * @param password 瀵嗙爜
+ * @param code 楠岃瘉鐮�
+ * @param uuid 鍞竴鏍囪瘑
+ * @return 缁撴灉
+ */
+ public String login(String username, String password, String code, String uuid)
+ {
+ // 楠岃瘉鐮佹牎楠�
+ validateCaptcha(username, code, uuid);
+ // 鐧诲綍鍓嶇疆鏍¢獙
+ loginPreCheck(username, password);
+ // 鐢ㄦ埛楠岃瘉
+ Authentication authentication = null;
+ try
+ {
+ UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
+ AuthenticationContextHolder.setContext(authenticationToken);
+ // 璇ユ柟娉曚細鍘昏皟鐢║serDetailsServiceImpl.loadUserByUsername
+ authentication = authenticationManager.authenticate(authenticationToken);
+ }
+ catch (Exception e)
+ {
+ if (e instanceof BadCredentialsException)
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+ throw new UserPasswordNotMatchException();
+ }
+ else
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
+ throw new ServiceException(e.getMessage());
+ }
+ }
+ finally
+ {
+ AuthenticationContextHolder.clearContext();
+ }
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
+ LoginUser loginUser = (LoginUser) authentication.getPrincipal();
+ recordLoginInfo(loginUser.getUserId());
+ // 鐢熸垚token
+ return tokenService.createToken(loginUser);
+ }
+
+ /**
+ * 鏍¢獙楠岃瘉鐮�
+ *
+ * @param username 鐢ㄦ埛鍚�
+ * @param code 楠岃瘉鐮�
+ * @param uuid 鍞竴鏍囪瘑
+ * @return 缁撴灉
+ */
+ public void validateCaptcha(String username, String code, String uuid)
+ {
+ boolean captchaEnabled = configService.selectCaptchaEnabled();
+ if (captchaEnabled)
+ {
+ String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
+ String captcha = redisCache.getCacheObject(verifyKey);
+ if (captcha == null)
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.expire")));
+ throw new CaptchaExpireException();
+ }
+ redisCache.deleteObject(verifyKey);
+ if (!code.equalsIgnoreCase(captcha))
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.jcaptcha.error")));
+ throw new CaptchaException();
+ }
+ }
+ }
+
+ /**
+ * 鐧诲綍鍓嶇疆鏍¢獙
+ * @param username 鐢ㄦ埛鍚�
+ * @param password 鐢ㄦ埛瀵嗙爜
+ */
+ public void loginPreCheck(String username, String password)
+ {
+ // 鐢ㄦ埛鍚嶆垨瀵嗙爜涓虹┖ 閿欒
+ if (StringUtils.isEmpty(username) || StringUtils.isEmpty(password))
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("not.null")));
+ throw new UserNotExistsException();
+ }
+ // 瀵嗙爜濡傛灉涓嶅湪鎸囧畾鑼冨洿鍐� 閿欒
+ if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+ || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+ throw new UserPasswordNotMatchException();
+ }
+ // 鐢ㄦ埛鍚嶄笉鍦ㄦ寚瀹氳寖鍥村唴 閿欒
+ if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+ || username.length() > UserConstants.USERNAME_MAX_LENGTH)
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
+ throw new UserPasswordNotMatchException();
+ }
+ // IP榛戝悕鍗曟牎楠�
+ String blackStr = configService.selectConfigByKey("sys.login.blackIPList");
+ if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr()))
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("login.blocked")));
+ throw new BlackListException();
+ }
+ }
+
+ /**
+ * 璁板綍鐧诲綍淇℃伅
+ *
+ * @param userId 鐢ㄦ埛ID
+ */
+ public void recordLoginInfo(Long userId)
+ {
+ SysUser sysUser = new SysUser();
+ sysUser.setUserId(userId);
+ sysUser.setLoginIp(IpUtils.getIpAddr());
+ sysUser.setLoginDate(DateUtils.getNowDate());
+ userService.updateUserProfile(sysUser);
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java
new file mode 100644
index 0000000..6728c7b
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPasswordService.java
@@ -0,0 +1,86 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.concurrent.TimeUnit;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.exception.user.UserPasswordNotMatchException;
+import com.ruoyi.common.exception.user.UserPasswordRetryLimitExceedException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.framework.security.context.AuthenticationContextHolder;
+
+/**
+ * 鐧诲綍瀵嗙爜鏂规硶
+ *
+ * @author ruoyi
+ */
+@Component
+public class SysPasswordService
+{
+ @Autowired
+ private RedisCache redisCache;
+
+ @Value(value = "${user.password.maxRetryCount}")
+ private int maxRetryCount;
+
+ @Value(value = "${user.password.lockTime}")
+ private int lockTime;
+
+ /**
+ * 鐧诲綍璐︽埛瀵嗙爜閿欒娆℃暟缂撳瓨閿悕
+ *
+ * @param username 鐢ㄦ埛鍚�
+ * @return 缂撳瓨閿甼ey
+ */
+ private String getCacheKey(String username)
+ {
+ return CacheConstants.PWD_ERR_CNT_KEY + username;
+ }
+
+ public void validate(SysUser user)
+ {
+ Authentication usernamePasswordAuthenticationToken = AuthenticationContextHolder.getContext();
+ String username = usernamePasswordAuthenticationToken.getName();
+ String password = usernamePasswordAuthenticationToken.getCredentials().toString();
+
+ Integer retryCount = redisCache.getCacheObject(getCacheKey(username));
+
+ if (retryCount == null)
+ {
+ retryCount = 0;
+ }
+
+ if (retryCount >= Integer.valueOf(maxRetryCount).intValue())
+ {
+ throw new UserPasswordRetryLimitExceedException(maxRetryCount, lockTime);
+ }
+
+ if (!matches(user, password))
+ {
+ retryCount = retryCount + 1;
+ redisCache.setCacheObject(getCacheKey(username), retryCount, lockTime, TimeUnit.MINUTES);
+ throw new UserPasswordNotMatchException();
+ }
+ else
+ {
+ clearLoginRecordCache(username);
+ }
+ }
+
+ public boolean matches(SysUser user, String rawPassword)
+ {
+ return SecurityUtils.matchesPassword(rawPassword, user.getPassword());
+ }
+
+ public void clearLoginRecordCache(String loginName)
+ {
+ if (redisCache.hasKey(getCacheKey(loginName)))
+ {
+ redisCache.deleteObject(getCacheKey(loginName));
+ }
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java
new file mode 100644
index 0000000..51c4dd9
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysPermissionService.java
@@ -0,0 +1,88 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysMenuService;
+import com.ruoyi.system.service.ISysRoleService;
+
+/**
+ * 鐢ㄦ埛鏉冮檺澶勭悊
+ *
+ * @author ruoyi
+ */
+@Component
+public class SysPermissionService
+{
+ @Autowired
+ private ISysRoleService roleService;
+
+ @Autowired
+ private ISysMenuService menuService;
+
+ /**
+ * 鑾峰彇瑙掕壊鏁版嵁鏉冮檺
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 瑙掕壊鏉冮檺淇℃伅
+ */
+ public Set<String> getRolePermission(SysUser user)
+ {
+ Set<String> roles = new HashSet<String>();
+ // 绠$悊鍛樻嫢鏈夋墍鏈夋潈闄�
+ if (user.isAdmin())
+ {
+ roles.add("admin");
+ }
+ else
+ {
+ roles.addAll(roleService.selectRolePermissionByUserId(user.getUserId()));
+ }
+ return roles;
+ }
+
+ /**
+ * 鑾峰彇鑿滃崟鏁版嵁鏉冮檺
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鑿滃崟鏉冮檺淇℃伅
+ */
+ public Set<String> getMenuPermission(SysUser user)
+ {
+ Set<String> perms = new HashSet<String>();
+ // 绠$悊鍛樻嫢鏈夋墍鏈夋潈闄�
+ if (user.isAdmin())
+ {
+ perms.add("*:*:*");
+ }
+ else
+ {
+ List<SysRole> roles = user.getRoles();
+ if (!CollectionUtils.isEmpty(roles))
+ {
+ // 澶氳鑹茶缃畃ermissions灞炴�э紝浠ヤ究鏁版嵁鏉冮檺鍖归厤鏉冮檺
+ for (SysRole role : roles)
+ {
+ if (StringUtils.equals(role.getStatus(), UserConstants.ROLE_NORMAL))
+ {
+ Set<String> rolePerms = menuService.selectMenuPermsByRoleId(role.getRoleId());
+ role.setPermissions(rolePerms);
+ perms.addAll(rolePerms);
+ }
+ }
+ }
+ else
+ {
+ perms.addAll(menuService.selectMenuPermsByUserId(user.getUserId()));
+ }
+ }
+ return perms;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java
new file mode 100644
index 0000000..f2afe31
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/SysRegisterService.java
@@ -0,0 +1,115 @@
+package com.ruoyi.framework.web.service;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.RegisterBody;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.exception.user.CaptchaException;
+import com.ruoyi.common.exception.user.CaptchaExpireException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.framework.manager.AsyncManager;
+import com.ruoyi.framework.manager.factory.AsyncFactory;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 娉ㄥ唽鏍¢獙鏂规硶
+ *
+ * @author ruoyi
+ */
+@Component
+public class SysRegisterService
+{
+ @Autowired
+ private ISysUserService userService;
+
+ @Autowired
+ private ISysConfigService configService;
+
+ @Autowired
+ private RedisCache redisCache;
+
+ /**
+ * 娉ㄥ唽
+ */
+ public String register(RegisterBody registerBody)
+ {
+ String msg = "", username = registerBody.getUsername(), password = registerBody.getPassword();
+ SysUser sysUser = new SysUser();
+ sysUser.setUserName(username);
+
+ // 楠岃瘉鐮佸紑鍏�
+ boolean captchaEnabled = configService.selectCaptchaEnabled();
+ if (captchaEnabled)
+ {
+ validateCaptcha(username, registerBody.getCode(), registerBody.getUuid());
+ }
+
+ if (StringUtils.isEmpty(username))
+ {
+ msg = "鐢ㄦ埛鍚嶄笉鑳戒负绌�";
+ }
+ else if (StringUtils.isEmpty(password))
+ {
+ msg = "鐢ㄦ埛瀵嗙爜涓嶈兘涓虹┖";
+ }
+ else if (username.length() < UserConstants.USERNAME_MIN_LENGTH
+ || username.length() > UserConstants.USERNAME_MAX_LENGTH)
+ {
+ msg = "璐︽埛闀垮害蹇呴』鍦�2鍒�20涓瓧绗︿箣闂�";
+ }
+ else if (password.length() < UserConstants.PASSWORD_MIN_LENGTH
+ || password.length() > UserConstants.PASSWORD_MAX_LENGTH)
+ {
+ msg = "瀵嗙爜闀垮害蹇呴』鍦�5鍒�20涓瓧绗︿箣闂�";
+ }
+ else if (!userService.checkUserNameUnique(sysUser))
+ {
+ msg = "淇濆瓨鐢ㄦ埛'" + username + "'澶辫触锛屾敞鍐岃处鍙峰凡瀛樺湪";
+ }
+ else
+ {
+ sysUser.setNickName(username);
+ sysUser.setPassword(SecurityUtils.encryptPassword(password));
+ boolean regFlag = userService.registerUser(sysUser);
+ if (!regFlag)
+ {
+ msg = "娉ㄥ唽澶辫触,璇疯仈绯荤郴缁熺鐞嗕汉鍛�";
+ }
+ else
+ {
+ AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.REGISTER, MessageUtils.message("user.register.success")));
+ }
+ }
+ return msg;
+ }
+
+ /**
+ * 鏍¢獙楠岃瘉鐮�
+ *
+ * @param username 鐢ㄦ埛鍚�
+ * @param code 楠岃瘉鐮�
+ * @param uuid 鍞竴鏍囪瘑
+ * @return 缁撴灉
+ */
+ public void validateCaptcha(String username, String code, String uuid)
+ {
+ String verifyKey = CacheConstants.CAPTCHA_CODE_KEY + StringUtils.nvl(uuid, "");
+ String captcha = redisCache.getCacheObject(verifyKey);
+ redisCache.deleteObject(verifyKey);
+ if (captcha == null)
+ {
+ throw new CaptchaExpireException();
+ }
+ if (!code.equalsIgnoreCase(captcha))
+ {
+ throw new CaptchaException();
+ }
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
new file mode 100644
index 0000000..aa112da
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java
@@ -0,0 +1,231 @@
+package com.ruoyi.framework.web.service;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import javax.servlet.http.HttpServletRequest;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.ServletUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.ip.AddressUtils;
+import com.ruoyi.common.utils.ip.IpUtils;
+import com.ruoyi.common.utils.uuid.IdUtils;
+import eu.bitwalker.useragentutils.UserAgent;
+import io.jsonwebtoken.Claims;
+import io.jsonwebtoken.Jwts;
+import io.jsonwebtoken.SignatureAlgorithm;
+
+/**
+ * token楠岃瘉澶勭悊
+ *
+ * @author ruoyi
+ */
+@Component
+public class TokenService
+{
+ private static final Logger log = LoggerFactory.getLogger(TokenService.class);
+
+ // 浠ょ墝鑷畾涔夋爣璇�
+ @Value("${token.header}")
+ private String header;
+
+ // 浠ょ墝绉橀挜
+ @Value("${token.secret}")
+ private String secret;
+
+ // 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+ @Value("${token.expireTime}")
+ private int expireTime;
+
+ protected static final long MILLIS_SECOND = 1000;
+
+ protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND;
+
+ private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L;
+
+ @Autowired
+ private RedisCache redisCache;
+
+ /**
+ * 鑾峰彇鐢ㄦ埛韬唤淇℃伅
+ *
+ * @return 鐢ㄦ埛淇℃伅
+ */
+ public LoginUser getLoginUser(HttpServletRequest request)
+ {
+ // 鑾峰彇璇锋眰鎼哄甫鐨勪护鐗�
+ String token = getToken(request);
+ if (StringUtils.isNotEmpty(token))
+ {
+ try
+ {
+ Claims claims = parseToken(token);
+ // 瑙f瀽瀵瑰簲鐨勬潈闄愪互鍙婄敤鎴蜂俊鎭�
+ String uuid = (String) claims.get(Constants.LOGIN_USER_KEY);
+ String userKey = getTokenKey(uuid);
+ LoginUser user = redisCache.getCacheObject(userKey);
+ return user;
+ }
+ catch (Exception e)
+ {
+ log.error("鑾峰彇鐢ㄦ埛淇℃伅寮傚父'{}'", e.getMessage());
+ }
+ }
+ return null;
+ }
+
+ /**
+ * 璁剧疆鐢ㄦ埛韬唤淇℃伅
+ */
+ public void setLoginUser(LoginUser loginUser)
+ {
+ if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
+ {
+ refreshToken(loginUser);
+ }
+ }
+
+ /**
+ * 鍒犻櫎鐢ㄦ埛韬唤淇℃伅
+ */
+ public void delLoginUser(String token)
+ {
+ if (StringUtils.isNotEmpty(token))
+ {
+ String userKey = getTokenKey(token);
+ redisCache.deleteObject(userKey);
+ }
+ }
+
+ /**
+ * 鍒涘缓浠ょ墝
+ *
+ * @param loginUser 鐢ㄦ埛淇℃伅
+ * @return 浠ょ墝
+ */
+ public String createToken(LoginUser loginUser)
+ {
+ String token = IdUtils.fastUUID();
+ loginUser.setToken(token);
+ setUserAgent(loginUser);
+ refreshToken(loginUser);
+
+ Map<String, Object> claims = new HashMap<>();
+ claims.put(Constants.LOGIN_USER_KEY, token);
+ return createToken(claims);
+ }
+
+ /**
+ * 楠岃瘉浠ょ墝鏈夋晥鏈燂紝鐩稿樊涓嶈冻20鍒嗛挓锛岃嚜鍔ㄥ埛鏂扮紦瀛�
+ *
+ * @param loginUser
+ * @return 浠ょ墝
+ */
+ public void verifyToken(LoginUser loginUser)
+ {
+ long expireTime = loginUser.getExpireTime();
+ long currentTime = System.currentTimeMillis();
+ if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
+ {
+ refreshToken(loginUser);
+ }
+ }
+
+ /**
+ * 鍒锋柊浠ょ墝鏈夋晥鏈�
+ *
+ * @param loginUser 鐧诲綍淇℃伅
+ */
+ public void refreshToken(LoginUser loginUser)
+ {
+ loginUser.setLoginTime(System.currentTimeMillis());
+ loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
+ // 鏍规嵁uuid灏唋oginUser缂撳瓨
+ String userKey = getTokenKey(loginUser.getToken());
+ redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
+ }
+
+ /**
+ * 璁剧疆鐢ㄦ埛浠g悊淇℃伅
+ *
+ * @param loginUser 鐧诲綍淇℃伅
+ */
+ public void setUserAgent(LoginUser loginUser)
+ {
+ UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent"));
+ String ip = IpUtils.getIpAddr();
+ loginUser.setIpaddr(ip);
+ loginUser.setLoginLocation(AddressUtils.getRealAddressByIP(ip));
+ loginUser.setBrowser(userAgent.getBrowser().getName());
+ loginUser.setOs(userAgent.getOperatingSystem().getName());
+ }
+
+ /**
+ * 浠庢暟鎹0鏄庣敓鎴愪护鐗�
+ *
+ * @param claims 鏁版嵁澹版槑
+ * @return 浠ょ墝
+ */
+ private String createToken(Map<String, Object> claims)
+ {
+ String token = Jwts.builder()
+ .setClaims(claims)
+ .signWith(SignatureAlgorithm.HS512, secret).compact();
+ return token;
+ }
+
+ /**
+ * 浠庝护鐗屼腑鑾峰彇鏁版嵁澹版槑
+ *
+ * @param token 浠ょ墝
+ * @return 鏁版嵁澹版槑
+ */
+ private Claims parseToken(String token)
+ {
+ return Jwts.parser()
+ .setSigningKey(secret)
+ .parseClaimsJws(token)
+ .getBody();
+ }
+
+ /**
+ * 浠庝护鐗屼腑鑾峰彇鐢ㄦ埛鍚�
+ *
+ * @param token 浠ょ墝
+ * @return 鐢ㄦ埛鍚�
+ */
+ public String getUsernameFromToken(String token)
+ {
+ Claims claims = parseToken(token);
+ return claims.getSubject();
+ }
+
+ /**
+ * 鑾峰彇璇锋眰token
+ *
+ * @param request
+ * @return token
+ */
+ private String getToken(HttpServletRequest request)
+ {
+ String token = request.getHeader(header);
+ if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX))
+ {
+ token = token.replace(Constants.TOKEN_PREFIX, "");
+ }
+ return token;
+ }
+
+ private String getTokenKey(String uuid)
+ {
+ return CacheConstants.LOGIN_TOKEN_KEY + uuid;
+ }
+}
diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java
new file mode 100644
index 0000000..5dcdf90
--- /dev/null
+++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/web/service/UserDetailsServiceImpl.java
@@ -0,0 +1,66 @@
+package com.ruoyi.framework.web.service;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.enums.UserStatus;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.MessageUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 鐢ㄦ埛楠岃瘉澶勭悊
+ *
+ * @author ruoyi
+ */
+@Service
+public class UserDetailsServiceImpl implements UserDetailsService
+{
+ private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
+
+ @Autowired
+ private ISysUserService userService;
+
+ @Autowired
+ private SysPasswordService passwordService;
+
+ @Autowired
+ private SysPermissionService permissionService;
+
+ @Override
+ public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
+ {
+ SysUser user = userService.selectUserByUserName(username);
+ if (StringUtils.isNull(user))
+ {
+ log.info("鐧诲綍鐢ㄦ埛锛歿} 涓嶅瓨鍦�.", username);
+ throw new ServiceException(MessageUtils.message("user.not.exists"));
+ }
+ else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
+ {
+ log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍒犻櫎.", username);
+ throw new ServiceException(MessageUtils.message("user.password.delete"));
+ }
+ else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
+ {
+ log.info("鐧诲綍鐢ㄦ埛锛歿} 宸茶鍋滅敤.", username);
+ throw new ServiceException(MessageUtils.message("user.blocked"));
+ }
+
+ passwordService.validate(user);
+
+ return createLoginUser(user);
+ }
+
+ public UserDetails createLoginUser(SysUser user)
+ {
+ return new LoginUser(user.getUserId(), user.getDeptId(), user, permissionService.getMenuPermission(user));
+ }
+}
diff --git a/ruoyi-generator/pom.xml b/ruoyi-generator/pom.xml
new file mode 100644
index 0000000..188cd90
--- /dev/null
+++ b/ruoyi-generator/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>ruoyi-generator</artifactId>
+
+ <description>
+ generator浠g爜鐢熸垚
+ </description>
+
+ <dependencies>
+
+ <!-- velocity浠g爜鐢熸垚浣跨敤妯℃澘 -->
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity-engine-core</artifactId>
+ </dependency>
+
+ <!-- 閫氱敤宸ュ叿-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ </dependency>
+
+ <!-- 闃块噷鏁版嵁搴撹繛鎺ユ睜 -->
+ <dependency>
+ <groupId>com.alibaba</groupId>
+ <artifactId>druid-spring-boot-starter</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java
new file mode 100644
index 0000000..c01857c
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/config/GenConfig.java
@@ -0,0 +1,87 @@
+package com.ruoyi.generator.config;
+
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.PropertySource;
+import org.springframework.stereotype.Component;
+
+/**
+ * 璇诲彇浠g爜鐢熸垚鐩稿叧閰嶇疆
+ *
+ * @author ruoyi
+ */
+@Component
+@ConfigurationProperties(prefix = "gen")
+@PropertySource(value = { "classpath:generator.yml" })
+public class GenConfig
+{
+ /** 浣滆�� */
+ public static String author;
+
+ /** 鐢熸垚鍖呰矾寰� */
+ public static String packageName;
+
+ /** 鑷姩鍘婚櫎琛ㄥ墠缂� */
+ public static boolean autoRemovePre;
+
+ /** 琛ㄥ墠缂� */
+ public static String tablePrefix;
+
+ /** 鏄惁鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦帮紙鑷畾涔夎矾寰勶級 */
+ public static boolean allowOverwrite;
+
+ public static String getAuthor()
+ {
+ return author;
+ }
+
+ @Value("${author}")
+ public void setAuthor(String author)
+ {
+ GenConfig.author = author;
+ }
+
+ public static String getPackageName()
+ {
+ return packageName;
+ }
+
+ @Value("${packageName}")
+ public void setPackageName(String packageName)
+ {
+ GenConfig.packageName = packageName;
+ }
+
+ public static boolean getAutoRemovePre()
+ {
+ return autoRemovePre;
+ }
+
+ @Value("${autoRemovePre}")
+ public void setAutoRemovePre(boolean autoRemovePre)
+ {
+ GenConfig.autoRemovePre = autoRemovePre;
+ }
+
+ public static String getTablePrefix()
+ {
+ return tablePrefix;
+ }
+
+ @Value("${tablePrefix}")
+ public void setTablePrefix(String tablePrefix)
+ {
+ GenConfig.tablePrefix = tablePrefix;
+ }
+
+ public static boolean isAllowOverwrite()
+ {
+ return allowOverwrite;
+ }
+
+ @Value("${allowOverwrite}")
+ public void setAllowOverwrite(boolean allowOverwrite)
+ {
+ GenConfig.allowOverwrite = allowOverwrite;
+ }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
new file mode 100644
index 0000000..ac040ed
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/controller/GenController.java
@@ -0,0 +1,263 @@
+package com.ruoyi.generator.controller;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.servlet.http.HttpServletResponse;
+import org.apache.commons.io.IOUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.alibaba.druid.DbType;
+import com.alibaba.druid.sql.SQLUtils;
+import com.alibaba.druid.sql.ast.SQLStatement;
+import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCreateTableStatement;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.sql.SqlUtil;
+import com.ruoyi.generator.config.GenConfig;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.service.IGenTableColumnService;
+import com.ruoyi.generator.service.IGenTableService;
+
+/**
+ * 浠g爜鐢熸垚 鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/tool/gen")
+public class GenController extends BaseController
+{
+ @Autowired
+ private IGenTableService genTableService;
+
+ @Autowired
+ private IGenTableColumnService genTableColumnService;
+
+ /**
+ * 鏌ヨ浠g爜鐢熸垚鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+ @GetMapping("/list")
+ public TableDataInfo genList(GenTable genTable)
+ {
+ startPage();
+ List<GenTable> list = genTableService.selectGenTableList(genTable);
+ return getDataTable(list);
+ }
+
+ /**
+ * 淇敼浠g爜鐢熸垚涓氬姟
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:query')")
+ @GetMapping(value = "/{tableId}")
+ public AjaxResult getInfo(@PathVariable Long tableId)
+ {
+ GenTable table = genTableService.selectGenTableById(tableId);
+ List<GenTable> tables = genTableService.selectGenTableAll();
+ List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
+ Map<String, Object> map = new HashMap<String, Object>();
+ map.put("info", table);
+ map.put("rows", list);
+ map.put("tables", tables);
+ return success(map);
+ }
+
+ /**
+ * 鏌ヨ鏁版嵁搴撳垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+ @GetMapping("/db/list")
+ public TableDataInfo dataList(GenTable genTable)
+ {
+ startPage();
+ List<GenTable> list = genTableService.selectDbTableList(genTable);
+ return getDataTable(list);
+ }
+
+ /**
+ * 鏌ヨ鏁版嵁琛ㄥ瓧娈靛垪琛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:list')")
+ @GetMapping(value = "/column/{tableId}")
+ public TableDataInfo columnList(Long tableId)
+ {
+ TableDataInfo dataInfo = new TableDataInfo();
+ List<GenTableColumn> list = genTableColumnService.selectGenTableColumnListByTableId(tableId);
+ dataInfo.setRows(list);
+ dataInfo.setTotal(list.size());
+ return dataInfo;
+ }
+
+ /**
+ * 瀵煎叆琛ㄧ粨鏋勶紙淇濆瓨锛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:import')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.IMPORT)
+ @PostMapping("/importTable")
+ public AjaxResult importTableSave(String tables)
+ {
+ String[] tableNames = Convert.toStrArray(tables);
+ // 鏌ヨ琛ㄤ俊鎭�
+ List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames);
+ genTableService.importGenTable(tableList, SecurityUtils.getUsername());
+ return success();
+ }
+
+ /**
+ * 鍒涘缓琛ㄧ粨鏋勶紙淇濆瓨锛�
+ */
+ @PreAuthorize("@ss.hasRole('admin')")
+ @Log(title = "鍒涘缓琛�", businessType = BusinessType.OTHER)
+ @PostMapping("/createTable")
+ public AjaxResult createTableSave(String sql)
+ {
+ try
+ {
+ SqlUtil.filterKeyword(sql);
+ List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);
+ List<String> tableNames = new ArrayList<>();
+ for (SQLStatement sqlStatement : sqlStatements)
+ {
+ if (sqlStatement instanceof MySqlCreateTableStatement)
+ {
+ MySqlCreateTableStatement createTableStatement = (MySqlCreateTableStatement) sqlStatement;
+ if (genTableService.createTable(createTableStatement.toString()))
+ {
+ String tableName = createTableStatement.getTableName().replaceAll("`", "");
+ tableNames.add(tableName);
+ }
+ }
+ }
+ List<GenTable> tableList = genTableService.selectDbTableListByNames(tableNames.toArray(new String[tableNames.size()]));
+ String operName = SecurityUtils.getUsername();
+ genTableService.importGenTable(tableList, operName);
+ return AjaxResult.success();
+ }
+ catch (Exception e)
+ {
+ logger.error(e.getMessage(), e);
+ return AjaxResult.error("鍒涘缓琛ㄧ粨鏋勫紓甯�");
+ }
+ }
+
+ /**
+ * 淇敼淇濆瓨浠g爜鐢熸垚涓氬姟
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult editSave(@Validated @RequestBody GenTable genTable)
+ {
+ genTableService.validateEdit(genTable);
+ genTableService.updateGenTable(genTable);
+ return success();
+ }
+
+ /**
+ * 鍒犻櫎浠g爜鐢熸垚
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:remove')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{tableIds}")
+ public AjaxResult remove(@PathVariable Long[] tableIds)
+ {
+ genTableService.deleteGenTableByIds(tableIds);
+ return success();
+ }
+
+ /**
+ * 棰勮浠g爜
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:preview')")
+ @GetMapping("/preview/{tableId}")
+ public AjaxResult preview(@PathVariable("tableId") Long tableId) throws IOException
+ {
+ Map<String, String> dataMap = genTableService.previewCode(tableId);
+ return success(dataMap);
+ }
+
+ /**
+ * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+ @GetMapping("/download/{tableName}")
+ public void download(HttpServletResponse response, @PathVariable("tableName") String tableName) throws IOException
+ {
+ byte[] data = genTableService.downloadCode(tableName);
+ genCode(response, data);
+ }
+
+ /**
+ * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+ @GetMapping("/genCode/{tableName}")
+ public AjaxResult genCode(@PathVariable("tableName") String tableName)
+ {
+ if (!GenConfig.isAllowOverwrite())
+ {
+ return AjaxResult.error("銆愮郴缁熼璁俱�戜笉鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦�");
+ }
+ genTableService.generatorCode(tableName);
+ return success();
+ }
+
+ /**
+ * 鍚屾鏁版嵁搴�
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:edit')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.UPDATE)
+ @GetMapping("/synchDb/{tableName}")
+ public AjaxResult synchDb(@PathVariable("tableName") String tableName)
+ {
+ genTableService.synchDb(tableName);
+ return success();
+ }
+
+ /**
+ * 鎵归噺鐢熸垚浠g爜
+ */
+ @PreAuthorize("@ss.hasPermi('tool:gen:code')")
+ @Log(title = "浠g爜鐢熸垚", businessType = BusinessType.GENCODE)
+ @GetMapping("/batchGenCode")
+ public void batchGenCode(HttpServletResponse response, String tables) throws IOException
+ {
+ String[] tableNames = Convert.toStrArray(tables);
+ byte[] data = genTableService.downloadCode(tableNames);
+ genCode(response, data);
+ }
+
+ /**
+ * 鐢熸垚zip鏂囦欢
+ */
+ private void genCode(HttpServletResponse response, byte[] data) throws IOException
+ {
+ response.reset();
+ response.addHeader("Access-Control-Allow-Origin", "*");
+ response.addHeader("Access-Control-Expose-Headers", "Content-Disposition");
+ response.setHeader("Content-Disposition", "attachment; filename=\"ruoyi.zip\"");
+ response.addHeader("Content-Length", "" + data.length);
+ response.setContentType("application/octet-stream; charset=UTF-8");
+ IOUtils.write(data, response.getOutputStream());
+ }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
new file mode 100644
index 0000000..022a54d
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTable.java
@@ -0,0 +1,385 @@
+package com.ruoyi.generator.domain;
+
+import java.util.List;
+import javax.validation.Valid;
+import javax.validation.constraints.NotBlank;
+import org.apache.commons.lang3.ArrayUtils;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 涓氬姟琛� gen_table
+ *
+ * @author ruoyi
+ */
+public class GenTable extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 缂栧彿 */
+ private Long tableId;
+
+ /** 琛ㄥ悕绉� */
+ @NotBlank(message = "琛ㄥ悕绉颁笉鑳戒负绌�")
+ private String tableName;
+
+ /** 琛ㄦ弿杩� */
+ @NotBlank(message = "琛ㄦ弿杩颁笉鑳戒负绌�")
+ private String tableComment;
+
+ /** 鍏宠仈鐖惰〃鐨勮〃鍚� */
+ private String subTableName;
+
+ /** 鏈〃鍏宠仈鐖惰〃鐨勫閿悕 */
+ private String subTableFkName;
+
+ /** 瀹炰綋绫诲悕绉�(棣栧瓧姣嶅ぇ鍐�) */
+ @NotBlank(message = "瀹炰綋绫诲悕绉颁笉鑳戒负绌�")
+ private String className;
+
+ /** 浣跨敤鐨勬ā鏉匡紙crud鍗曡〃鎿嶄綔 tree鏍戣〃鎿嶄綔 sub涓诲瓙琛ㄦ搷浣滐級 */
+ private String tplCategory;
+
+ /** 鍓嶇绫诲瀷锛坋lement-ui妯$増 element-plus妯$増锛� */
+ private String tplWebType;
+
+ /** 鐢熸垚鍖呰矾寰� */
+ @NotBlank(message = "鐢熸垚鍖呰矾寰勪笉鑳戒负绌�")
+ private String packageName;
+
+ /** 鐢熸垚妯″潡鍚� */
+ @NotBlank(message = "鐢熸垚妯″潡鍚嶄笉鑳戒负绌�")
+ private String moduleName;
+
+ /** 鐢熸垚涓氬姟鍚� */
+ @NotBlank(message = "鐢熸垚涓氬姟鍚嶄笉鑳戒负绌�")
+ private String businessName;
+
+ /** 鐢熸垚鍔熻兘鍚� */
+ @NotBlank(message = "鐢熸垚鍔熻兘鍚嶄笉鑳戒负绌�")
+ private String functionName;
+
+ /** 鐢熸垚浣滆�� */
+ @NotBlank(message = "浣滆�呬笉鑳戒负绌�")
+ private String functionAuthor;
+
+ /** 鐢熸垚浠g爜鏂瑰紡锛�0zip鍘嬬缉鍖� 1鑷畾涔夎矾寰勶級 */
+ private String genType;
+
+ /** 鐢熸垚璺緞锛堜笉濉粯璁ら」鐩矾寰勶級 */
+ private String genPath;
+
+ /** 涓婚敭淇℃伅 */
+ private GenTableColumn pkColumn;
+
+ /** 瀛愯〃淇℃伅 */
+ private GenTable subTable;
+
+ /** 琛ㄥ垪淇℃伅 */
+ @Valid
+ private List<GenTableColumn> columns;
+
+ /** 鍏跺畠鐢熸垚閫夐」 */
+ private String options;
+
+ /** 鏍戠紪鐮佸瓧娈� */
+ private String treeCode;
+
+ /** 鏍戠埗缂栫爜瀛楁 */
+ private String treeParentCode;
+
+ /** 鏍戝悕绉板瓧娈� */
+ private String treeName;
+
+ /** 涓婄骇鑿滃崟ID瀛楁 */
+ private Long parentMenuId;
+
+ /** 涓婄骇鑿滃崟鍚嶇О瀛楁 */
+ private String parentMenuName;
+
+ public Long getTableId()
+ {
+ return tableId;
+ }
+
+ public void setTableId(Long tableId)
+ {
+ this.tableId = tableId;
+ }
+
+ public String getTableName()
+ {
+ return tableName;
+ }
+
+ public void setTableName(String tableName)
+ {
+ this.tableName = tableName;
+ }
+
+ public String getTableComment()
+ {
+ return tableComment;
+ }
+
+ public void setTableComment(String tableComment)
+ {
+ this.tableComment = tableComment;
+ }
+
+ public String getSubTableName()
+ {
+ return subTableName;
+ }
+
+ public void setSubTableName(String subTableName)
+ {
+ this.subTableName = subTableName;
+ }
+
+ public String getSubTableFkName()
+ {
+ return subTableFkName;
+ }
+
+ public void setSubTableFkName(String subTableFkName)
+ {
+ this.subTableFkName = subTableFkName;
+ }
+
+ public String getClassName()
+ {
+ return className;
+ }
+
+ public void setClassName(String className)
+ {
+ this.className = className;
+ }
+
+ public String getTplCategory()
+ {
+ return tplCategory;
+ }
+
+ public void setTplCategory(String tplCategory)
+ {
+ this.tplCategory = tplCategory;
+ }
+
+ public String getTplWebType()
+ {
+ return tplWebType;
+ }
+
+ public void setTplWebType(String tplWebType)
+ {
+ this.tplWebType = tplWebType;
+ }
+
+ public String getPackageName()
+ {
+ return packageName;
+ }
+
+ public void setPackageName(String packageName)
+ {
+ this.packageName = packageName;
+ }
+
+ public String getModuleName()
+ {
+ return moduleName;
+ }
+
+ public void setModuleName(String moduleName)
+ {
+ this.moduleName = moduleName;
+ }
+
+ public String getBusinessName()
+ {
+ return businessName;
+ }
+
+ public void setBusinessName(String businessName)
+ {
+ this.businessName = businessName;
+ }
+
+ public String getFunctionName()
+ {
+ return functionName;
+ }
+
+ public void setFunctionName(String functionName)
+ {
+ this.functionName = functionName;
+ }
+
+ public String getFunctionAuthor()
+ {
+ return functionAuthor;
+ }
+
+ public void setFunctionAuthor(String functionAuthor)
+ {
+ this.functionAuthor = functionAuthor;
+ }
+
+ public String getGenType()
+ {
+ return genType;
+ }
+
+ public void setGenType(String genType)
+ {
+ this.genType = genType;
+ }
+
+ public String getGenPath()
+ {
+ return genPath;
+ }
+
+ public void setGenPath(String genPath)
+ {
+ this.genPath = genPath;
+ }
+
+ public GenTableColumn getPkColumn()
+ {
+ return pkColumn;
+ }
+
+ public void setPkColumn(GenTableColumn pkColumn)
+ {
+ this.pkColumn = pkColumn;
+ }
+
+ public GenTable getSubTable()
+ {
+ return subTable;
+ }
+
+ public void setSubTable(GenTable subTable)
+ {
+ this.subTable = subTable;
+ }
+
+ public List<GenTableColumn> getColumns()
+ {
+ return columns;
+ }
+
+ public void setColumns(List<GenTableColumn> columns)
+ {
+ this.columns = columns;
+ }
+
+ public String getOptions()
+ {
+ return options;
+ }
+
+ public void setOptions(String options)
+ {
+ this.options = options;
+ }
+
+ public String getTreeCode()
+ {
+ return treeCode;
+ }
+
+ public void setTreeCode(String treeCode)
+ {
+ this.treeCode = treeCode;
+ }
+
+ public String getTreeParentCode()
+ {
+ return treeParentCode;
+ }
+
+ public void setTreeParentCode(String treeParentCode)
+ {
+ this.treeParentCode = treeParentCode;
+ }
+
+ public String getTreeName()
+ {
+ return treeName;
+ }
+
+ public void setTreeName(String treeName)
+ {
+ this.treeName = treeName;
+ }
+
+ public Long getParentMenuId()
+ {
+ return parentMenuId;
+ }
+
+ public void setParentMenuId(Long parentMenuId)
+ {
+ this.parentMenuId = parentMenuId;
+ }
+
+ public String getParentMenuName()
+ {
+ return parentMenuName;
+ }
+
+ public void setParentMenuName(String parentMenuName)
+ {
+ this.parentMenuName = parentMenuName;
+ }
+
+ public boolean isSub()
+ {
+ return isSub(this.tplCategory);
+ }
+
+ public static boolean isSub(String tplCategory)
+ {
+ return tplCategory != null && StringUtils.equals(GenConstants.TPL_SUB, tplCategory);
+ }
+
+ public boolean isTree()
+ {
+ return isTree(this.tplCategory);
+ }
+
+ public static boolean isTree(String tplCategory)
+ {
+ return tplCategory != null && StringUtils.equals(GenConstants.TPL_TREE, tplCategory);
+ }
+
+ public boolean isCrud()
+ {
+ return isCrud(this.tplCategory);
+ }
+
+ public static boolean isCrud(String tplCategory)
+ {
+ return tplCategory != null && StringUtils.equals(GenConstants.TPL_CRUD, tplCategory);
+ }
+
+ public boolean isSuperColumn(String javaField)
+ {
+ return isSuperColumn(this.tplCategory, javaField);
+ }
+
+ public static boolean isSuperColumn(String tplCategory, String javaField)
+ {
+ if (isTree(tplCategory))
+ {
+ return StringUtils.equalsAnyIgnoreCase(javaField,
+ ArrayUtils.addAll(GenConstants.TREE_ENTITY, GenConstants.BASE_ENTITY));
+ }
+ return StringUtils.equalsAnyIgnoreCase(javaField, GenConstants.BASE_ENTITY);
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
new file mode 100644
index 0000000..d1733b6
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/domain/GenTableColumn.java
@@ -0,0 +1,373 @@
+package com.ruoyi.generator.domain;
+
+import javax.validation.constraints.NotBlank;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 浠g爜鐢熸垚涓氬姟瀛楁琛� gen_table_column
+ *
+ * @author ruoyi
+ */
+public class GenTableColumn extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 缂栧彿 */
+ private Long columnId;
+
+ /** 褰掑睘琛ㄧ紪鍙� */
+ private Long tableId;
+
+ /** 鍒楀悕绉� */
+ private String columnName;
+
+ /** 鍒楁弿杩� */
+ private String columnComment;
+
+ /** 鍒楃被鍨� */
+ private String columnType;
+
+ /** JAVA绫诲瀷 */
+ private String javaType;
+
+ /** JAVA瀛楁鍚� */
+ @NotBlank(message = "Java灞炴�т笉鑳戒负绌�")
+ private String javaField;
+
+ /** 鏄惁涓婚敭锛�1鏄級 */
+ private String isPk;
+
+ /** 鏄惁鑷锛�1鏄級 */
+ private String isIncrement;
+
+ /** 鏄惁蹇呭~锛�1鏄級 */
+ private String isRequired;
+
+ /** 鏄惁涓烘彃鍏ュ瓧娈碉紙1鏄級 */
+ private String isInsert;
+
+ /** 鏄惁缂栬緫瀛楁锛�1鏄級 */
+ private String isEdit;
+
+ /** 鏄惁鍒楄〃瀛楁锛�1鏄級 */
+ private String isList;
+
+ /** 鏄惁鏌ヨ瀛楁锛�1鏄級 */
+ private String isQuery;
+
+ /** 鏌ヨ鏂瑰紡锛圗Q绛変簬銆丯E涓嶇瓑浜庛�丟T澶т簬銆丩T灏忎簬銆丩IKE妯$硦銆丅ETWEEN鑼冨洿锛� */
+ private String queryType;
+
+ /** 鏄剧ず绫诲瀷锛坕nput鏂囨湰妗嗐�乼extarea鏂囨湰鍩熴�乻elect涓嬫媺妗嗐�乧heckbox澶嶉�夋銆乺adio鍗曢�夋銆乨atetime鏃ユ湡鎺т欢銆乮mage鍥剧墖涓婁紶鎺т欢銆乽pload鏂囦欢涓婁紶鎺т欢銆乪ditor瀵屾枃鏈帶浠讹級 */
+ private String htmlType;
+
+ /** 瀛楀吀绫诲瀷 */
+ private String dictType;
+
+ /** 鎺掑簭 */
+ private Integer sort;
+
+ public void setColumnId(Long columnId)
+ {
+ this.columnId = columnId;
+ }
+
+ public Long getColumnId()
+ {
+ return columnId;
+ }
+
+ public void setTableId(Long tableId)
+ {
+ this.tableId = tableId;
+ }
+
+ public Long getTableId()
+ {
+ return tableId;
+ }
+
+ public void setColumnName(String columnName)
+ {
+ this.columnName = columnName;
+ }
+
+ public String getColumnName()
+ {
+ return columnName;
+ }
+
+ public void setColumnComment(String columnComment)
+ {
+ this.columnComment = columnComment;
+ }
+
+ public String getColumnComment()
+ {
+ return columnComment;
+ }
+
+ public void setColumnType(String columnType)
+ {
+ this.columnType = columnType;
+ }
+
+ public String getColumnType()
+ {
+ return columnType;
+ }
+
+ public void setJavaType(String javaType)
+ {
+ this.javaType = javaType;
+ }
+
+ public String getJavaType()
+ {
+ return javaType;
+ }
+
+ public void setJavaField(String javaField)
+ {
+ this.javaField = javaField;
+ }
+
+ public String getJavaField()
+ {
+ return javaField;
+ }
+
+ public String getCapJavaField()
+ {
+ return StringUtils.capitalize(javaField);
+ }
+
+ public void setIsPk(String isPk)
+ {
+ this.isPk = isPk;
+ }
+
+ public String getIsPk()
+ {
+ return isPk;
+ }
+
+ public boolean isPk()
+ {
+ return isPk(this.isPk);
+ }
+
+ public boolean isPk(String isPk)
+ {
+ return isPk != null && StringUtils.equals("1", isPk);
+ }
+
+ public String getIsIncrement()
+ {
+ return isIncrement;
+ }
+
+ public void setIsIncrement(String isIncrement)
+ {
+ this.isIncrement = isIncrement;
+ }
+
+ public boolean isIncrement()
+ {
+ return isIncrement(this.isIncrement);
+ }
+
+ public boolean isIncrement(String isIncrement)
+ {
+ return isIncrement != null && StringUtils.equals("1", isIncrement);
+ }
+
+ public void setIsRequired(String isRequired)
+ {
+ this.isRequired = isRequired;
+ }
+
+ public String getIsRequired()
+ {
+ return isRequired;
+ }
+
+ public boolean isRequired()
+ {
+ return isRequired(this.isRequired);
+ }
+
+ public boolean isRequired(String isRequired)
+ {
+ return isRequired != null && StringUtils.equals("1", isRequired);
+ }
+
+ public void setIsInsert(String isInsert)
+ {
+ this.isInsert = isInsert;
+ }
+
+ public String getIsInsert()
+ {
+ return isInsert;
+ }
+
+ public boolean isInsert()
+ {
+ return isInsert(this.isInsert);
+ }
+
+ public boolean isInsert(String isInsert)
+ {
+ return isInsert != null && StringUtils.equals("1", isInsert);
+ }
+
+ public void setIsEdit(String isEdit)
+ {
+ this.isEdit = isEdit;
+ }
+
+ public String getIsEdit()
+ {
+ return isEdit;
+ }
+
+ public boolean isEdit()
+ {
+ return isInsert(this.isEdit);
+ }
+
+ public boolean isEdit(String isEdit)
+ {
+ return isEdit != null && StringUtils.equals("1", isEdit);
+ }
+
+ public void setIsList(String isList)
+ {
+ this.isList = isList;
+ }
+
+ public String getIsList()
+ {
+ return isList;
+ }
+
+ public boolean isList()
+ {
+ return isList(this.isList);
+ }
+
+ public boolean isList(String isList)
+ {
+ return isList != null && StringUtils.equals("1", isList);
+ }
+
+ public void setIsQuery(String isQuery)
+ {
+ this.isQuery = isQuery;
+ }
+
+ public String getIsQuery()
+ {
+ return isQuery;
+ }
+
+ public boolean isQuery()
+ {
+ return isQuery(this.isQuery);
+ }
+
+ public boolean isQuery(String isQuery)
+ {
+ return isQuery != null && StringUtils.equals("1", isQuery);
+ }
+
+ public void setQueryType(String queryType)
+ {
+ this.queryType = queryType;
+ }
+
+ public String getQueryType()
+ {
+ return queryType;
+ }
+
+ public String getHtmlType()
+ {
+ return htmlType;
+ }
+
+ public void setHtmlType(String htmlType)
+ {
+ this.htmlType = htmlType;
+ }
+
+ public void setDictType(String dictType)
+ {
+ this.dictType = dictType;
+ }
+
+ public String getDictType()
+ {
+ return dictType;
+ }
+
+ public void setSort(Integer sort)
+ {
+ this.sort = sort;
+ }
+
+ public Integer getSort()
+ {
+ return sort;
+ }
+
+ public boolean isSuperColumn()
+ {
+ return isSuperColumn(this.javaField);
+ }
+
+ public static boolean isSuperColumn(String javaField)
+ {
+ return StringUtils.equalsAnyIgnoreCase(javaField,
+ // BaseEntity
+ "createBy", "createTime", "updateBy", "updateTime", "remark",
+ // TreeEntity
+ "parentName", "parentId", "orderNum", "ancestors");
+ }
+
+ public boolean isUsableColumn()
+ {
+ return isUsableColumn(javaField);
+ }
+
+ public static boolean isUsableColumn(String javaField)
+ {
+ // isSuperColumn()涓殑鍚嶅崟鐢ㄤ簬閬垮厤鐢熸垚澶氫綑Domain灞炴�э紝鑻ユ煇浜涘睘鎬у湪鐢熸垚椤甸潰鏃堕渶瑕佺敤鍒颁笉鑳藉拷鐣ワ紝鍒欐斁鍦ㄦ澶勭櫧鍚嶅崟
+ return StringUtils.equalsAnyIgnoreCase(javaField, "parentId", "orderNum", "remark");
+ }
+
+ public String readConverterExp()
+ {
+ String remarks = StringUtils.substringBetween(this.columnComment, "锛�", "锛�");
+ StringBuffer sb = new StringBuffer();
+ if (StringUtils.isNotEmpty(remarks))
+ {
+ for (String value : remarks.split(" "))
+ {
+ if (StringUtils.isNotEmpty(value))
+ {
+ Object startStr = value.subSequence(0, 1);
+ String endStr = value.substring(1);
+ sb.append("").append(startStr).append("=").append(endStr).append(",");
+ }
+ }
+ return sb.deleteCharAt(sb.length() - 1).toString();
+ }
+ else
+ {
+ return this.columnComment;
+ }
+ }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
new file mode 100644
index 0000000..951e166
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableColumnMapper.java
@@ -0,0 +1,60 @@
+package com.ruoyi.generator.mapper;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 涓氬姟瀛楁 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface GenTableColumnMapper
+{
+ /**
+ * 鏍规嵁琛ㄥ悕绉版煡璇㈠垪淇℃伅
+ *
+ * @param tableName 琛ㄥ悕绉�
+ * @return 鍒椾俊鎭�
+ */
+ public List<GenTableColumn> selectDbTableColumnsByName(String tableName);
+
+ /**
+ * 鏌ヨ涓氬姟瀛楁鍒楄〃
+ *
+ * @param tableId 涓氬姟瀛楁缂栧彿
+ * @return 涓氬姟瀛楁闆嗗悎
+ */
+ public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
+
+ /**
+ * 鏂板涓氬姟瀛楁
+ *
+ * @param genTableColumn 涓氬姟瀛楁淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertGenTableColumn(GenTableColumn genTableColumn);
+
+ /**
+ * 淇敼涓氬姟瀛楁
+ *
+ * @param genTableColumn 涓氬姟瀛楁淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateGenTableColumn(GenTableColumn genTableColumn);
+
+ /**
+ * 鍒犻櫎涓氬姟瀛楁
+ *
+ * @param genTableColumns 鍒楁暟鎹�
+ * @return 缁撴灉
+ */
+ public int deleteGenTableColumns(List<GenTableColumn> genTableColumns);
+
+ /**
+ * 鎵归噺鍒犻櫎涓氬姟瀛楁
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteGenTableColumnByIds(Long[] ids);
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
new file mode 100644
index 0000000..937656d
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/mapper/GenTableMapper.java
@@ -0,0 +1,91 @@
+package com.ruoyi.generator.mapper;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTable;
+
+/**
+ * 涓氬姟 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface GenTableMapper
+{
+ /**
+ * 鏌ヨ涓氬姟鍒楄〃
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 涓氬姟闆嗗悎
+ */
+ public List<GenTable> selectGenTableList(GenTable genTable);
+
+ /**
+ * 鏌ヨ鎹簱鍒楄〃
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 鏁版嵁搴撹〃闆嗗悎
+ */
+ public List<GenTable> selectDbTableList(GenTable genTable);
+
+ /**
+ * 鏌ヨ鎹簱鍒楄〃
+ *
+ * @param tableNames 琛ㄥ悕绉扮粍
+ * @return 鏁版嵁搴撹〃闆嗗悎
+ */
+ public List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+ /**
+ * 鏌ヨ鎵�鏈夎〃淇℃伅
+ *
+ * @return 琛ㄤ俊鎭泦鍚�
+ */
+ public List<GenTable> selectGenTableAll();
+
+ /**
+ * 鏌ヨ琛↖D涓氬姟淇℃伅
+ *
+ * @param id 涓氬姟ID
+ * @return 涓氬姟淇℃伅
+ */
+ public GenTable selectGenTableById(Long id);
+
+ /**
+ * 鏌ヨ琛ㄥ悕绉颁笟鍔′俊鎭�
+ *
+ * @param tableName 琛ㄥ悕绉�
+ * @return 涓氬姟淇℃伅
+ */
+ public GenTable selectGenTableByName(String tableName);
+
+ /**
+ * 鏂板涓氬姟
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertGenTable(GenTable genTable);
+
+ /**
+ * 淇敼涓氬姟
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateGenTable(GenTable genTable);
+
+ /**
+ * 鎵归噺鍒犻櫎涓氬姟
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteGenTableByIds(Long[] ids);
+
+ /**
+ * 鍒涘缓琛�
+ *
+ * @param sql 琛ㄧ粨鏋�
+ * @return 缁撴灉
+ */
+ public int createTable(String sql);
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java
new file mode 100644
index 0000000..0679689
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableColumnServiceImpl.java
@@ -0,0 +1,68 @@
+package com.ruoyi.generator.service;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.mapper.GenTableColumnMapper;
+
+/**
+ * 涓氬姟瀛楁 鏈嶅姟灞傚疄鐜�
+ *
+ * @author ruoyi
+ */
+@Service
+public class GenTableColumnServiceImpl implements IGenTableColumnService
+{
+ @Autowired
+ private GenTableColumnMapper genTableColumnMapper;
+
+ /**
+ * 鏌ヨ涓氬姟瀛楁鍒楄〃
+ *
+ * @param tableId 涓氬姟瀛楁缂栧彿
+ * @return 涓氬姟瀛楁闆嗗悎
+ */
+ @Override
+ public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId)
+ {
+ return genTableColumnMapper.selectGenTableColumnListByTableId(tableId);
+ }
+
+ /**
+ * 鏂板涓氬姟瀛楁
+ *
+ * @param genTableColumn 涓氬姟瀛楁淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertGenTableColumn(GenTableColumn genTableColumn)
+ {
+ return genTableColumnMapper.insertGenTableColumn(genTableColumn);
+ }
+
+ /**
+ * 淇敼涓氬姟瀛楁
+ *
+ * @param genTableColumn 涓氬姟瀛楁淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateGenTableColumn(GenTableColumn genTableColumn)
+ {
+ return genTableColumnMapper.updateGenTableColumn(genTableColumn);
+ }
+
+ /**
+ * 鍒犻櫎涓氬姟瀛楁瀵硅薄
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteGenTableColumnByIds(String ids)
+ {
+ return genTableColumnMapper.deleteGenTableColumnByIds(Convert.toLongArray(ids));
+ }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
new file mode 100644
index 0000000..fc19233
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/GenTableServiceImpl.java
@@ -0,0 +1,531 @@
+package com.ruoyi.generator.service;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.Velocity;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.core.text.CharsetKit;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+import com.ruoyi.generator.mapper.GenTableColumnMapper;
+import com.ruoyi.generator.mapper.GenTableMapper;
+import com.ruoyi.generator.util.GenUtils;
+import com.ruoyi.generator.util.VelocityInitializer;
+import com.ruoyi.generator.util.VelocityUtils;
+
+/**
+ * 涓氬姟 鏈嶅姟灞傚疄鐜�
+ *
+ * @author ruoyi
+ */
+@Service
+public class GenTableServiceImpl implements IGenTableService
+{
+ private static final Logger log = LoggerFactory.getLogger(GenTableServiceImpl.class);
+
+ @Autowired
+ private GenTableMapper genTableMapper;
+
+ @Autowired
+ private GenTableColumnMapper genTableColumnMapper;
+
+ /**
+ * 鏌ヨ涓氬姟淇℃伅
+ *
+ * @param id 涓氬姟ID
+ * @return 涓氬姟淇℃伅
+ */
+ @Override
+ public GenTable selectGenTableById(Long id)
+ {
+ GenTable genTable = genTableMapper.selectGenTableById(id);
+ setTableFromOptions(genTable);
+ return genTable;
+ }
+
+ /**
+ * 鏌ヨ涓氬姟鍒楄〃
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 涓氬姟闆嗗悎
+ */
+ @Override
+ public List<GenTable> selectGenTableList(GenTable genTable)
+ {
+ return genTableMapper.selectGenTableList(genTable);
+ }
+
+ /**
+ * 鏌ヨ鎹簱鍒楄〃
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 鏁版嵁搴撹〃闆嗗悎
+ */
+ @Override
+ public List<GenTable> selectDbTableList(GenTable genTable)
+ {
+ return genTableMapper.selectDbTableList(genTable);
+ }
+
+ /**
+ * 鏌ヨ鎹簱鍒楄〃
+ *
+ * @param tableNames 琛ㄥ悕绉扮粍
+ * @return 鏁版嵁搴撹〃闆嗗悎
+ */
+ @Override
+ public List<GenTable> selectDbTableListByNames(String[] tableNames)
+ {
+ return genTableMapper.selectDbTableListByNames(tableNames);
+ }
+
+ /**
+ * 鏌ヨ鎵�鏈夎〃淇℃伅
+ *
+ * @return 琛ㄤ俊鎭泦鍚�
+ */
+ @Override
+ public List<GenTable> selectGenTableAll()
+ {
+ return genTableMapper.selectGenTableAll();
+ }
+
+ /**
+ * 淇敼涓氬姟
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public void updateGenTable(GenTable genTable)
+ {
+ String options = JSON.toJSONString(genTable.getParams());
+ genTable.setOptions(options);
+ int row = genTableMapper.updateGenTable(genTable);
+ if (row > 0)
+ {
+ for (GenTableColumn cenTableColumn : genTable.getColumns())
+ {
+ genTableColumnMapper.updateGenTableColumn(cenTableColumn);
+ }
+ }
+ }
+
+ /**
+ * 鍒犻櫎涓氬姟瀵硅薄
+ *
+ * @param tableIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public void deleteGenTableByIds(Long[] tableIds)
+ {
+ genTableMapper.deleteGenTableByIds(tableIds);
+ genTableColumnMapper.deleteGenTableColumnByIds(tableIds);
+ }
+
+ /**
+ * 鍒涘缓琛�
+ *
+ * @param sql 鍒涘缓琛ㄨ鍙�
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean createTable(String sql)
+ {
+ return genTableMapper.createTable(sql) == 0;
+ }
+
+ /**
+ * 瀵煎叆琛ㄧ粨鏋�
+ *
+ * @param tableList 瀵煎叆琛ㄥ垪琛�
+ */
+ @Override
+ @Transactional
+ public void importGenTable(List<GenTable> tableList, String operName)
+ {
+ try
+ {
+ for (GenTable table : tableList)
+ {
+ String tableName = table.getTableName();
+ GenUtils.initTable(table, operName);
+ int row = genTableMapper.insertGenTable(table);
+ if (row > 0)
+ {
+ // 淇濆瓨鍒椾俊鎭�
+ List<GenTableColumn> genTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+ for (GenTableColumn column : genTableColumns)
+ {
+ GenUtils.initColumnField(column, table);
+ genTableColumnMapper.insertGenTableColumn(column);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ throw new ServiceException("瀵煎叆澶辫触锛�" + e.getMessage());
+ }
+ }
+
+ /**
+ * 棰勮浠g爜
+ *
+ * @param tableId 琛ㄧ紪鍙�
+ * @return 棰勮鏁版嵁鍒楄〃
+ */
+ @Override
+ public Map<String, String> previewCode(Long tableId)
+ {
+ Map<String, String> dataMap = new LinkedHashMap<>();
+ // 鏌ヨ琛ㄤ俊鎭�
+ GenTable table = genTableMapper.selectGenTableById(tableId);
+ // 璁剧疆涓诲瓙琛ㄤ俊鎭�
+ setSubTable(table);
+ // 璁剧疆涓婚敭鍒椾俊鎭�
+ setPkColumn(table);
+ VelocityInitializer.initVelocity();
+
+ VelocityContext context = VelocityUtils.prepareContext(table);
+
+ // 鑾峰彇妯℃澘鍒楄〃
+ List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+ for (String template : templates)
+ {
+ // 娓叉煋妯℃澘
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+ tpl.merge(context, sw);
+ dataMap.put(template, sw.toString());
+ }
+ return dataMap;
+ }
+
+ /**
+ * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+ *
+ * @param tableName 琛ㄥ悕绉�
+ * @return 鏁版嵁
+ */
+ @Override
+ public byte[] downloadCode(String tableName)
+ {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ZipOutputStream zip = new ZipOutputStream(outputStream);
+ generatorCode(tableName, zip);
+ IOUtils.closeQuietly(zip);
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+ *
+ * @param tableName 琛ㄥ悕绉�
+ */
+ @Override
+ public void generatorCode(String tableName)
+ {
+ // 鏌ヨ琛ㄤ俊鎭�
+ GenTable table = genTableMapper.selectGenTableByName(tableName);
+ // 璁剧疆涓诲瓙琛ㄤ俊鎭�
+ setSubTable(table);
+ // 璁剧疆涓婚敭鍒椾俊鎭�
+ setPkColumn(table);
+
+ VelocityInitializer.initVelocity();
+
+ VelocityContext context = VelocityUtils.prepareContext(table);
+
+ // 鑾峰彇妯℃澘鍒楄〃
+ List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+ for (String template : templates)
+ {
+ if (!StringUtils.containsAny(template, "sql.vm", "api.js.vm", "index.vue.vm", "index-tree.vue.vm"))
+ {
+ // 娓叉煋妯℃澘
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+ tpl.merge(context, sw);
+ try
+ {
+ String path = getGenPath(table, template);
+ FileUtils.writeStringToFile(new File(path), sw.toString(), CharsetKit.UTF_8);
+ }
+ catch (IOException e)
+ {
+ throw new ServiceException("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName());
+ }
+ }
+ }
+ }
+
+ /**
+ * 鍚屾鏁版嵁搴�
+ *
+ * @param tableName 琛ㄥ悕绉�
+ */
+ @Override
+ @Transactional
+ public void synchDb(String tableName)
+ {
+ GenTable table = genTableMapper.selectGenTableByName(tableName);
+ List<GenTableColumn> tableColumns = table.getColumns();
+ Map<String, GenTableColumn> tableColumnMap = tableColumns.stream().collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity()));
+
+ List<GenTableColumn> dbTableColumns = genTableColumnMapper.selectDbTableColumnsByName(tableName);
+ if (StringUtils.isEmpty(dbTableColumns))
+ {
+ throw new ServiceException("鍚屾鏁版嵁澶辫触锛屽師琛ㄧ粨鏋勪笉瀛樺湪");
+ }
+ List<String> dbTableColumnNames = dbTableColumns.stream().map(GenTableColumn::getColumnName).collect(Collectors.toList());
+
+ dbTableColumns.forEach(column -> {
+ GenUtils.initColumnField(column, table);
+ if (tableColumnMap.containsKey(column.getColumnName()))
+ {
+ GenTableColumn prevColumn = tableColumnMap.get(column.getColumnName());
+ column.setColumnId(prevColumn.getColumnId());
+ if (column.isList())
+ {
+ // 濡傛灉鏄垪琛紝缁х画淇濈暀鏌ヨ鏂瑰紡/瀛楀吀绫诲瀷閫夐」
+ column.setDictType(prevColumn.getDictType());
+ column.setQueryType(prevColumn.getQueryType());
+ }
+ if (StringUtils.isNotEmpty(prevColumn.getIsRequired()) && !column.isPk()
+ && (column.isInsert() || column.isEdit())
+ && ((column.isUsableColumn()) || (!column.isSuperColumn())))
+ {
+ // 濡傛灉鏄�(鏂板/淇敼&闈炰富閿�/闈炲拷鐣ュ強鐖跺睘鎬�)锛岀户缁繚鐣欏繀濉�/鏄剧ず绫诲瀷閫夐」
+ column.setIsRequired(prevColumn.getIsRequired());
+ column.setHtmlType(prevColumn.getHtmlType());
+ }
+ genTableColumnMapper.updateGenTableColumn(column);
+ }
+ else
+ {
+ genTableColumnMapper.insertGenTableColumn(column);
+ }
+ });
+
+ List<GenTableColumn> delColumns = tableColumns.stream().filter(column -> !dbTableColumnNames.contains(column.getColumnName())).collect(Collectors.toList());
+ if (StringUtils.isNotEmpty(delColumns))
+ {
+ genTableColumnMapper.deleteGenTableColumns(delColumns);
+ }
+ }
+
+ /**
+ * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+ *
+ * @param tableNames 琛ㄦ暟缁�
+ * @return 鏁版嵁
+ */
+ @Override
+ public byte[] downloadCode(String[] tableNames)
+ {
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+ ZipOutputStream zip = new ZipOutputStream(outputStream);
+ for (String tableName : tableNames)
+ {
+ generatorCode(tableName, zip);
+ }
+ IOUtils.closeQuietly(zip);
+ return outputStream.toByteArray();
+ }
+
+ /**
+ * 鏌ヨ琛ㄤ俊鎭苟鐢熸垚浠g爜
+ */
+ private void generatorCode(String tableName, ZipOutputStream zip)
+ {
+ // 鏌ヨ琛ㄤ俊鎭�
+ GenTable table = genTableMapper.selectGenTableByName(tableName);
+ // 璁剧疆涓诲瓙琛ㄤ俊鎭�
+ setSubTable(table);
+ // 璁剧疆涓婚敭鍒椾俊鎭�
+ setPkColumn(table);
+
+ VelocityInitializer.initVelocity();
+
+ VelocityContext context = VelocityUtils.prepareContext(table);
+
+ // 鑾峰彇妯℃澘鍒楄〃
+ List<String> templates = VelocityUtils.getTemplateList(table.getTplCategory(), table.getTplWebType());
+ for (String template : templates)
+ {
+ // 娓叉煋妯℃澘
+ StringWriter sw = new StringWriter();
+ Template tpl = Velocity.getTemplate(template, Constants.UTF8);
+ tpl.merge(context, sw);
+ try
+ {
+ // 娣诲姞鍒皕ip
+ zip.putNextEntry(new ZipEntry(VelocityUtils.getFileName(template, table)));
+ IOUtils.write(sw.toString(), zip, Constants.UTF8);
+ IOUtils.closeQuietly(sw);
+ zip.flush();
+ zip.closeEntry();
+ }
+ catch (IOException e)
+ {
+ log.error("娓叉煋妯℃澘澶辫触锛岃〃鍚嶏細" + table.getTableName(), e);
+ }
+ }
+ }
+
+ /**
+ * 淇敼淇濆瓨鍙傛暟鏍¢獙
+ *
+ * @param genTable 涓氬姟淇℃伅
+ */
+ @Override
+ public void validateEdit(GenTable genTable)
+ {
+ if (GenConstants.TPL_TREE.equals(genTable.getTplCategory()))
+ {
+ String options = JSON.toJSONString(genTable.getParams());
+ JSONObject paramsObj = JSON.parseObject(options);
+ if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_CODE)))
+ {
+ throw new ServiceException("鏍戠紪鐮佸瓧娈典笉鑳戒负绌�");
+ }
+ else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_PARENT_CODE)))
+ {
+ throw new ServiceException("鏍戠埗缂栫爜瀛楁涓嶈兘涓虹┖");
+ }
+ else if (StringUtils.isEmpty(paramsObj.getString(GenConstants.TREE_NAME)))
+ {
+ throw new ServiceException("鏍戝悕绉板瓧娈典笉鑳戒负绌�");
+ }
+ else if (GenConstants.TPL_SUB.equals(genTable.getTplCategory()))
+ {
+ if (StringUtils.isEmpty(genTable.getSubTableName()))
+ {
+ throw new ServiceException("鍏宠仈瀛愯〃鐨勮〃鍚嶄笉鑳戒负绌�");
+ }
+ else if (StringUtils.isEmpty(genTable.getSubTableFkName()))
+ {
+ throw new ServiceException("瀛愯〃鍏宠仈鐨勫閿悕涓嶈兘涓虹┖");
+ }
+ }
+ }
+ }
+
+ /**
+ * 璁剧疆涓婚敭鍒椾俊鎭�
+ *
+ * @param table 涓氬姟琛ㄤ俊鎭�
+ */
+ public void setPkColumn(GenTable table)
+ {
+ for (GenTableColumn column : table.getColumns())
+ {
+ if (column.isPk())
+ {
+ table.setPkColumn(column);
+ break;
+ }
+ }
+ if (StringUtils.isNull(table.getPkColumn()))
+ {
+ table.setPkColumn(table.getColumns().get(0));
+ }
+ if (GenConstants.TPL_SUB.equals(table.getTplCategory()))
+ {
+ for (GenTableColumn column : table.getSubTable().getColumns())
+ {
+ if (column.isPk())
+ {
+ table.getSubTable().setPkColumn(column);
+ break;
+ }
+ }
+ if (StringUtils.isNull(table.getSubTable().getPkColumn()))
+ {
+ table.getSubTable().setPkColumn(table.getSubTable().getColumns().get(0));
+ }
+ }
+ }
+
+ /**
+ * 璁剧疆涓诲瓙琛ㄤ俊鎭�
+ *
+ * @param table 涓氬姟琛ㄤ俊鎭�
+ */
+ public void setSubTable(GenTable table)
+ {
+ String subTableName = table.getSubTableName();
+ if (StringUtils.isNotEmpty(subTableName))
+ {
+ table.setSubTable(genTableMapper.selectGenTableByName(subTableName));
+ }
+ }
+
+ /**
+ * 璁剧疆浠g爜鐢熸垚鍏朵粬閫夐」鍊�
+ *
+ * @param genTable 璁剧疆鍚庣殑鐢熸垚瀵硅薄
+ */
+ public void setTableFromOptions(GenTable genTable)
+ {
+ JSONObject paramsObj = JSON.parseObject(genTable.getOptions());
+ if (StringUtils.isNotNull(paramsObj))
+ {
+ String treeCode = paramsObj.getString(GenConstants.TREE_CODE);
+ String treeParentCode = paramsObj.getString(GenConstants.TREE_PARENT_CODE);
+ String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+ Long parentMenuId = paramsObj.getLongValue(GenConstants.PARENT_MENU_ID);
+ String parentMenuName = paramsObj.getString(GenConstants.PARENT_MENU_NAME);
+
+ genTable.setTreeCode(treeCode);
+ genTable.setTreeParentCode(treeParentCode);
+ genTable.setTreeName(treeName);
+ genTable.setParentMenuId(parentMenuId);
+ genTable.setParentMenuName(parentMenuName);
+ }
+ }
+
+ /**
+ * 鑾峰彇浠g爜鐢熸垚鍦板潃
+ *
+ * @param table 涓氬姟琛ㄤ俊鎭�
+ * @param template 妯℃澘鏂囦欢璺緞
+ * @return 鐢熸垚鍦板潃
+ */
+ public static String getGenPath(GenTable table, String template)
+ {
+ String genPath = table.getGenPath();
+ if (StringUtils.equals(genPath, "/"))
+ {
+ return System.getProperty("user.dir") + File.separator + "src" + File.separator + VelocityUtils.getFileName(template, table);
+ }
+ return genPath + File.separator + VelocityUtils.getFileName(template, table);
+ }
+}
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java
new file mode 100644
index 0000000..3037f70
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableColumnService.java
@@ -0,0 +1,44 @@
+package com.ruoyi.generator.service;
+
+import java.util.List;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 涓氬姟瀛楁 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface IGenTableColumnService
+{
+ /**
+ * 鏌ヨ涓氬姟瀛楁鍒楄〃
+ *
+ * @param tableId 涓氬姟瀛楁缂栧彿
+ * @return 涓氬姟瀛楁闆嗗悎
+ */
+ public List<GenTableColumn> selectGenTableColumnListByTableId(Long tableId);
+
+ /**
+ * 鏂板涓氬姟瀛楁
+ *
+ * @param genTableColumn 涓氬姟瀛楁淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertGenTableColumn(GenTableColumn genTableColumn);
+
+ /**
+ * 淇敼涓氬姟瀛楁
+ *
+ * @param genTableColumn 涓氬姟瀛楁淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateGenTableColumn(GenTableColumn genTableColumn);
+
+ /**
+ * 鍒犻櫎涓氬姟瀛楁淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteGenTableColumnByIds(String ids);
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
new file mode 100644
index 0000000..695426e
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/service/IGenTableService.java
@@ -0,0 +1,130 @@
+package com.ruoyi.generator.service;
+
+import java.util.List;
+import java.util.Map;
+import com.ruoyi.generator.domain.GenTable;
+
+/**
+ * 涓氬姟 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface IGenTableService
+{
+ /**
+ * 鏌ヨ涓氬姟鍒楄〃
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 涓氬姟闆嗗悎
+ */
+ public List<GenTable> selectGenTableList(GenTable genTable);
+
+ /**
+ * 鏌ヨ鎹簱鍒楄〃
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 鏁版嵁搴撹〃闆嗗悎
+ */
+ public List<GenTable> selectDbTableList(GenTable genTable);
+
+ /**
+ * 鏌ヨ鎹簱鍒楄〃
+ *
+ * @param tableNames 琛ㄥ悕绉扮粍
+ * @return 鏁版嵁搴撹〃闆嗗悎
+ */
+ public List<GenTable> selectDbTableListByNames(String[] tableNames);
+
+ /**
+ * 鏌ヨ鎵�鏈夎〃淇℃伅
+ *
+ * @return 琛ㄤ俊鎭泦鍚�
+ */
+ public List<GenTable> selectGenTableAll();
+
+ /**
+ * 鏌ヨ涓氬姟淇℃伅
+ *
+ * @param id 涓氬姟ID
+ * @return 涓氬姟淇℃伅
+ */
+ public GenTable selectGenTableById(Long id);
+
+ /**
+ * 淇敼涓氬姟
+ *
+ * @param genTable 涓氬姟淇℃伅
+ * @return 缁撴灉
+ */
+ public void updateGenTable(GenTable genTable);
+
+ /**
+ * 鍒犻櫎涓氬姟淇℃伅
+ *
+ * @param tableIds 闇�瑕佸垹闄ょ殑琛ㄦ暟鎹甀D
+ * @return 缁撴灉
+ */
+ public void deleteGenTableByIds(Long[] tableIds);
+
+ /**
+ * 鍒涘缓琛�
+ *
+ * @param sql 鍒涘缓琛ㄨ鍙�
+ * @return 缁撴灉
+ */
+ public boolean createTable(String sql);
+
+ /**
+ * 瀵煎叆琛ㄧ粨鏋�
+ *
+ * @param tableList 瀵煎叆琛ㄥ垪琛�
+ * @param operName 鎿嶄綔浜哄憳
+ */
+ public void importGenTable(List<GenTable> tableList, String operName);
+
+ /**
+ * 棰勮浠g爜
+ *
+ * @param tableId 琛ㄧ紪鍙�
+ * @return 棰勮鏁版嵁鍒楄〃
+ */
+ public Map<String, String> previewCode(Long tableId);
+
+ /**
+ * 鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+ *
+ * @param tableName 琛ㄥ悕绉�
+ * @return 鏁版嵁
+ */
+ public byte[] downloadCode(String tableName);
+
+ /**
+ * 鐢熸垚浠g爜锛堣嚜瀹氫箟璺緞锛�
+ *
+ * @param tableName 琛ㄥ悕绉�
+ * @return 鏁版嵁
+ */
+ public void generatorCode(String tableName);
+
+ /**
+ * 鍚屾鏁版嵁搴�
+ *
+ * @param tableName 琛ㄥ悕绉�
+ */
+ public void synchDb(String tableName);
+
+ /**
+ * 鎵归噺鐢熸垚浠g爜锛堜笅杞芥柟寮忥級
+ *
+ * @param tableNames 琛ㄦ暟缁�
+ * @return 鏁版嵁
+ */
+ public byte[] downloadCode(String[] tableNames);
+
+ /**
+ * 淇敼淇濆瓨鍙傛暟鏍¢獙
+ *
+ * @param genTable 涓氬姟淇℃伅
+ */
+ public void validateEdit(GenTable genTable);
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
new file mode 100644
index 0000000..e7ebc20
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/GenUtils.java
@@ -0,0 +1,257 @@
+package com.ruoyi.generator.util;
+
+import java.util.Arrays;
+import org.apache.commons.lang3.RegExUtils;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.config.GenConfig;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 浠g爜鐢熸垚鍣� 宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class GenUtils
+{
+ /**
+ * 鍒濆鍖栬〃淇℃伅
+ */
+ public static void initTable(GenTable genTable, String operName)
+ {
+ genTable.setClassName(convertClassName(genTable.getTableName()));
+ genTable.setPackageName(GenConfig.getPackageName());
+ genTable.setModuleName(getModuleName(GenConfig.getPackageName()));
+ genTable.setBusinessName(getBusinessName(genTable.getTableName()));
+ genTable.setFunctionName(replaceText(genTable.getTableComment()));
+ genTable.setFunctionAuthor(GenConfig.getAuthor());
+ genTable.setCreateBy(operName);
+ }
+
+ /**
+ * 鍒濆鍖栧垪灞炴�у瓧娈�
+ */
+ public static void initColumnField(GenTableColumn column, GenTable table)
+ {
+ String dataType = getDbType(column.getColumnType());
+ String columnName = column.getColumnName();
+ column.setTableId(table.getTableId());
+ column.setCreateBy(table.getCreateBy());
+ // 璁剧疆java瀛楁鍚�
+ column.setJavaField(StringUtils.toCamelCase(columnName));
+ // 璁剧疆榛樿绫诲瀷
+ column.setJavaType(GenConstants.TYPE_STRING);
+ column.setQueryType(GenConstants.QUERY_EQ);
+
+ if (arraysContains(GenConstants.COLUMNTYPE_STR, dataType) || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType))
+ {
+ // 瀛楃涓查暱搴﹁秴杩�500璁剧疆涓烘枃鏈煙
+ Integer columnLength = getColumnLength(column.getColumnType());
+ String htmlType = columnLength >= 500 || arraysContains(GenConstants.COLUMNTYPE_TEXT, dataType) ? GenConstants.HTML_TEXTAREA : GenConstants.HTML_INPUT;
+ column.setHtmlType(htmlType);
+ }
+ else if (arraysContains(GenConstants.COLUMNTYPE_TIME, dataType))
+ {
+ column.setJavaType(GenConstants.TYPE_DATE);
+ column.setHtmlType(GenConstants.HTML_DATETIME);
+ }
+ else if (arraysContains(GenConstants.COLUMNTYPE_NUMBER, dataType))
+ {
+ column.setHtmlType(GenConstants.HTML_INPUT);
+
+ // 濡傛灉鏄诞鐐瑰瀷 缁熶竴鐢˙igDecimal
+ String[] str = StringUtils.split(StringUtils.substringBetween(column.getColumnType(), "(", ")"), ",");
+ if (str != null && str.length == 2 && Integer.parseInt(str[1]) > 0)
+ {
+ column.setJavaType(GenConstants.TYPE_BIGDECIMAL);
+ }
+ // 濡傛灉鏄暣褰�
+ else if (str != null && str.length == 1 && Integer.parseInt(str[0]) <= 10)
+ {
+ column.setJavaType(GenConstants.TYPE_INTEGER);
+ }
+ // 闀挎暣褰�
+ else
+ {
+ column.setJavaType(GenConstants.TYPE_LONG);
+ }
+ }
+
+ // 鎻掑叆瀛楁锛堥粯璁ゆ墍鏈夊瓧娈甸兘闇�瑕佹彃鍏ワ級
+ column.setIsInsert(GenConstants.REQUIRE);
+
+ // 缂栬緫瀛楁
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_EDIT, columnName) && !column.isPk())
+ {
+ column.setIsEdit(GenConstants.REQUIRE);
+ }
+ // 鍒楄〃瀛楁
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_LIST, columnName) && !column.isPk())
+ {
+ column.setIsList(GenConstants.REQUIRE);
+ }
+ // 鏌ヨ瀛楁
+ if (!arraysContains(GenConstants.COLUMNNAME_NOT_QUERY, columnName) && !column.isPk())
+ {
+ column.setIsQuery(GenConstants.REQUIRE);
+ }
+
+ // 鏌ヨ瀛楁绫诲瀷
+ if (StringUtils.endsWithIgnoreCase(columnName, "name"))
+ {
+ column.setQueryType(GenConstants.QUERY_LIKE);
+ }
+ // 鐘舵�佸瓧娈佃缃崟閫夋
+ if (StringUtils.endsWithIgnoreCase(columnName, "status"))
+ {
+ column.setHtmlType(GenConstants.HTML_RADIO);
+ }
+ // 绫诲瀷&鎬у埆瀛楁璁剧疆涓嬫媺妗�
+ else if (StringUtils.endsWithIgnoreCase(columnName, "type")
+ || StringUtils.endsWithIgnoreCase(columnName, "sex"))
+ {
+ column.setHtmlType(GenConstants.HTML_SELECT);
+ }
+ // 鍥剧墖瀛楁璁剧疆鍥剧墖涓婁紶鎺т欢
+ else if (StringUtils.endsWithIgnoreCase(columnName, "image"))
+ {
+ column.setHtmlType(GenConstants.HTML_IMAGE_UPLOAD);
+ }
+ // 鏂囦欢瀛楁璁剧疆鏂囦欢涓婁紶鎺т欢
+ else if (StringUtils.endsWithIgnoreCase(columnName, "file"))
+ {
+ column.setHtmlType(GenConstants.HTML_FILE_UPLOAD);
+ }
+ // 鍐呭瀛楁璁剧疆瀵屾枃鏈帶浠�
+ else if (StringUtils.endsWithIgnoreCase(columnName, "content"))
+ {
+ column.setHtmlType(GenConstants.HTML_EDITOR);
+ }
+ }
+
+ /**
+ * 鏍¢獙鏁扮粍鏄惁鍖呭惈鎸囧畾鍊�
+ *
+ * @param arr 鏁扮粍
+ * @param targetValue 鍊�
+ * @return 鏄惁鍖呭惈
+ */
+ public static boolean arraysContains(String[] arr, String targetValue)
+ {
+ return Arrays.asList(arr).contains(targetValue);
+ }
+
+ /**
+ * 鑾峰彇妯″潡鍚�
+ *
+ * @param packageName 鍖呭悕
+ * @return 妯″潡鍚�
+ */
+ public static String getModuleName(String packageName)
+ {
+ int lastIndex = packageName.lastIndexOf(".");
+ int nameLength = packageName.length();
+ return StringUtils.substring(packageName, lastIndex + 1, nameLength);
+ }
+
+ /**
+ * 鑾峰彇涓氬姟鍚�
+ *
+ * @param tableName 琛ㄥ悕
+ * @return 涓氬姟鍚�
+ */
+ public static String getBusinessName(String tableName)
+ {
+ int lastIndex = tableName.lastIndexOf("_");
+ int nameLength = tableName.length();
+ return StringUtils.substring(tableName, lastIndex + 1, nameLength);
+ }
+
+ /**
+ * 琛ㄥ悕杞崲鎴怞ava绫诲悕
+ *
+ * @param tableName 琛ㄥ悕绉�
+ * @return 绫诲悕
+ */
+ public static String convertClassName(String tableName)
+ {
+ boolean autoRemovePre = GenConfig.getAutoRemovePre();
+ String tablePrefix = GenConfig.getTablePrefix();
+ if (autoRemovePre && StringUtils.isNotEmpty(tablePrefix))
+ {
+ String[] searchList = StringUtils.split(tablePrefix, ",");
+ tableName = replaceFirst(tableName, searchList);
+ }
+ return StringUtils.convertToCamelCase(tableName);
+ }
+
+ /**
+ * 鎵归噺鏇挎崲鍓嶇紑
+ *
+ * @param replacementm 鏇挎崲鍊�
+ * @param searchList 鏇挎崲鍒楄〃
+ * @return
+ */
+ public static String replaceFirst(String replacementm, String[] searchList)
+ {
+ String text = replacementm;
+ for (String searchString : searchList)
+ {
+ if (replacementm.startsWith(searchString))
+ {
+ text = replacementm.replaceFirst(searchString, "");
+ break;
+ }
+ }
+ return text;
+ }
+
+ /**
+ * 鍏抽敭瀛楁浛鎹�
+ *
+ * @param text 闇�瑕佽鏇挎崲鐨勫悕瀛�
+ * @return 鏇挎崲鍚庣殑鍚嶅瓧
+ */
+ public static String replaceText(String text)
+ {
+ return RegExUtils.replaceAll(text, "(?:琛▅鑻ヤ緷)", "");
+ }
+
+ /**
+ * 鑾峰彇鏁版嵁搴撶被鍨嬪瓧娈�
+ *
+ * @param columnType 鍒楃被鍨�
+ * @return 鎴彇鍚庣殑鍒楃被鍨�
+ */
+ public static String getDbType(String columnType)
+ {
+ if (StringUtils.indexOf(columnType, "(") > 0)
+ {
+ return StringUtils.substringBefore(columnType, "(");
+ }
+ else
+ {
+ return columnType;
+ }
+ }
+
+ /**
+ * 鑾峰彇瀛楁闀垮害
+ *
+ * @param columnType 鍒楃被鍨�
+ * @return 鎴彇鍚庣殑鍒楃被鍨�
+ */
+ public static Integer getColumnLength(String columnType)
+ {
+ if (StringUtils.indexOf(columnType, "(") > 0)
+ {
+ String length = StringUtils.substringBetween(columnType, "(", ")");
+ return Integer.valueOf(length);
+ }
+ else
+ {
+ return 0;
+ }
+ }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
new file mode 100644
index 0000000..9f69403
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityInitializer.java
@@ -0,0 +1,34 @@
+package com.ruoyi.generator.util;
+
+import java.util.Properties;
+import org.apache.velocity.app.Velocity;
+import com.ruoyi.common.constant.Constants;
+
+/**
+ * VelocityEngine宸ュ巶
+ *
+ * @author ruoyi
+ */
+public class VelocityInitializer
+{
+ /**
+ * 鍒濆鍖杤m鏂规硶
+ */
+ public static void initVelocity()
+ {
+ Properties p = new Properties();
+ try
+ {
+ // 鍔犺浇classpath鐩綍涓嬬殑vm鏂囦欢
+ p.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader");
+ // 瀹氫箟瀛楃闆�
+ p.setProperty(Velocity.INPUT_ENCODING, Constants.UTF8);
+ // 鍒濆鍖朧elocity寮曟搸锛屾寚瀹氶厤缃甈roperties
+ Velocity.init(p);
+ }
+ catch (Exception e)
+ {
+ throw new RuntimeException(e);
+ }
+ }
+}
diff --git a/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
new file mode 100644
index 0000000..1a14681
--- /dev/null
+++ b/ruoyi-generator/src/main/java/com/ruoyi/generator/util/VelocityUtils.java
@@ -0,0 +1,408 @@
+package com.ruoyi.generator.util;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.velocity.VelocityContext;
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.constant.GenConstants;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.generator.domain.GenTable;
+import com.ruoyi.generator.domain.GenTableColumn;
+
+/**
+ * 妯℃澘澶勭悊宸ュ叿绫�
+ *
+ * @author ruoyi
+ */
+public class VelocityUtils
+{
+ /** 椤圭洰绌洪棿璺緞 */
+ private static final String PROJECT_PATH = "main/java";
+
+ /** mybatis绌洪棿璺緞 */
+ private static final String MYBATIS_PATH = "main/resources/mapper";
+
+ /** 榛樿涓婄骇鑿滃崟锛岀郴缁熷伐鍏� */
+ private static final String DEFAULT_PARENT_MENU_ID = "3";
+
+ /**
+ * 璁剧疆妯℃澘鍙橀噺淇℃伅
+ *
+ * @return 妯℃澘鍒楄〃
+ */
+ public static VelocityContext prepareContext(GenTable genTable)
+ {
+ String moduleName = genTable.getModuleName();
+ String businessName = genTable.getBusinessName();
+ String packageName = genTable.getPackageName();
+ String tplCategory = genTable.getTplCategory();
+ String functionName = genTable.getFunctionName();
+
+ VelocityContext velocityContext = new VelocityContext();
+ velocityContext.put("tplCategory", genTable.getTplCategory());
+ velocityContext.put("tableName", genTable.getTableName());
+ velocityContext.put("functionName", StringUtils.isNotEmpty(functionName) ? functionName : "銆愯濉啓鍔熻兘鍚嶇О銆�");
+ velocityContext.put("ClassName", genTable.getClassName());
+ velocityContext.put("className", StringUtils.uncapitalize(genTable.getClassName()));
+ velocityContext.put("moduleName", genTable.getModuleName());
+ velocityContext.put("BusinessName", StringUtils.capitalize(genTable.getBusinessName()));
+ velocityContext.put("businessName", genTable.getBusinessName());
+ velocityContext.put("basePackage", getPackagePrefix(packageName));
+ velocityContext.put("packageName", packageName);
+ velocityContext.put("author", genTable.getFunctionAuthor());
+ velocityContext.put("datetime", DateUtils.getDate());
+ velocityContext.put("pkColumn", genTable.getPkColumn());
+ velocityContext.put("importList", getImportList(genTable));
+ velocityContext.put("permissionPrefix", getPermissionPrefix(moduleName, businessName));
+ velocityContext.put("columns", genTable.getColumns());
+ velocityContext.put("table", genTable);
+ velocityContext.put("dicts", getDicts(genTable));
+ setMenuVelocityContext(velocityContext, genTable);
+ if (GenConstants.TPL_TREE.equals(tplCategory))
+ {
+ setTreeVelocityContext(velocityContext, genTable);
+ }
+ if (GenConstants.TPL_SUB.equals(tplCategory))
+ {
+ setSubVelocityContext(velocityContext, genTable);
+ }
+ return velocityContext;
+ }
+
+ public static void setMenuVelocityContext(VelocityContext context, GenTable genTable)
+ {
+ String options = genTable.getOptions();
+ JSONObject paramsObj = JSON.parseObject(options);
+ String parentMenuId = getParentMenuId(paramsObj);
+ context.put("parentMenuId", parentMenuId);
+ }
+
+ public static void setTreeVelocityContext(VelocityContext context, GenTable genTable)
+ {
+ String options = genTable.getOptions();
+ JSONObject paramsObj = JSON.parseObject(options);
+ String treeCode = getTreecode(paramsObj);
+ String treeParentCode = getTreeParentCode(paramsObj);
+ String treeName = getTreeName(paramsObj);
+
+ context.put("treeCode", treeCode);
+ context.put("treeParentCode", treeParentCode);
+ context.put("treeName", treeName);
+ context.put("expandColumn", getExpandColumn(genTable));
+ if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
+ {
+ context.put("tree_parent_code", paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+ }
+ if (paramsObj.containsKey(GenConstants.TREE_NAME))
+ {
+ context.put("tree_name", paramsObj.getString(GenConstants.TREE_NAME));
+ }
+ }
+
+ public static void setSubVelocityContext(VelocityContext context, GenTable genTable)
+ {
+ GenTable subTable = genTable.getSubTable();
+ String subTableName = genTable.getSubTableName();
+ String subTableFkName = genTable.getSubTableFkName();
+ String subClassName = genTable.getSubTable().getClassName();
+ String subTableFkClassName = StringUtils.convertToCamelCase(subTableFkName);
+
+ context.put("subTable", subTable);
+ context.put("subTableName", subTableName);
+ context.put("subTableFkName", subTableFkName);
+ context.put("subTableFkClassName", subTableFkClassName);
+ context.put("subTableFkclassName", StringUtils.uncapitalize(subTableFkClassName));
+ context.put("subClassName", subClassName);
+ context.put("subclassName", StringUtils.uncapitalize(subClassName));
+ context.put("subImportList", getImportList(genTable.getSubTable()));
+ }
+
+ /**
+ * 鑾峰彇妯℃澘淇℃伅
+ * @param tplCategory 鐢熸垚鐨勬ā鏉�
+ * @param tplWebType 鍓嶇绫诲瀷
+ * @return 妯℃澘鍒楄〃
+ */
+ public static List<String> getTemplateList(String tplCategory, String tplWebType)
+ {
+ String useWebType = "vm/vue";
+ if ("element-plus".equals(tplWebType))
+ {
+ useWebType = "vm/vue/v3";
+ }
+ List<String> templates = new ArrayList<String>();
+ templates.add("vm/java/domain.java.vm");
+ templates.add("vm/java/mapper.java.vm");
+ templates.add("vm/java/service.java.vm");
+ templates.add("vm/java/serviceImpl.java.vm");
+ templates.add("vm/java/controller.java.vm");
+ templates.add("vm/xml/mapper.xml.vm");
+ templates.add("vm/sql/sql.vm");
+ templates.add("vm/js/api.js.vm");
+ if (GenConstants.TPL_CRUD.equals(tplCategory))
+ {
+ templates.add(useWebType + "/index.vue.vm");
+ }
+ else if (GenConstants.TPL_TREE.equals(tplCategory))
+ {
+ templates.add(useWebType + "/index-tree.vue.vm");
+ }
+ else if (GenConstants.TPL_SUB.equals(tplCategory))
+ {
+ templates.add(useWebType + "/index.vue.vm");
+ templates.add("vm/java/sub-domain.java.vm");
+ }
+ return templates;
+ }
+
+ /**
+ * 鑾峰彇鏂囦欢鍚�
+ */
+ public static String getFileName(String template, GenTable genTable)
+ {
+ // 鏂囦欢鍚嶇О
+ String fileName = "";
+ // 鍖呰矾寰�
+ String packageName = genTable.getPackageName();
+ // 妯″潡鍚�
+ String moduleName = genTable.getModuleName();
+ // 澶у啓绫诲悕
+ String className = genTable.getClassName();
+ // 涓氬姟鍚嶇О
+ String businessName = genTable.getBusinessName();
+
+ String javaPath = PROJECT_PATH + "/" + StringUtils.replace(packageName, ".", "/");
+ String mybatisPath = MYBATIS_PATH + "/" + moduleName;
+ String vuePath = "vue";
+
+ if (template.contains("domain.java.vm"))
+ {
+ fileName = StringUtils.format("{}/domain/{}.java", javaPath, className);
+ }
+ if (template.contains("sub-domain.java.vm") && StringUtils.equals(GenConstants.TPL_SUB, genTable.getTplCategory()))
+ {
+ fileName = StringUtils.format("{}/domain/{}.java", javaPath, genTable.getSubTable().getClassName());
+ }
+ else if (template.contains("mapper.java.vm"))
+ {
+ fileName = StringUtils.format("{}/mapper/{}Mapper.java", javaPath, className);
+ }
+ else if (template.contains("service.java.vm"))
+ {
+ fileName = StringUtils.format("{}/service/I{}Service.java", javaPath, className);
+ }
+ else if (template.contains("serviceImpl.java.vm"))
+ {
+ fileName = StringUtils.format("{}/service/impl/{}ServiceImpl.java", javaPath, className);
+ }
+ else if (template.contains("controller.java.vm"))
+ {
+ fileName = StringUtils.format("{}/controller/{}Controller.java", javaPath, className);
+ }
+ else if (template.contains("mapper.xml.vm"))
+ {
+ fileName = StringUtils.format("{}/{}Mapper.xml", mybatisPath, className);
+ }
+ else if (template.contains("sql.vm"))
+ {
+ fileName = businessName + "Menu.sql";
+ }
+ else if (template.contains("api.js.vm"))
+ {
+ fileName = StringUtils.format("{}/api/{}/{}.js", vuePath, moduleName, businessName);
+ }
+ else if (template.contains("index.vue.vm"))
+ {
+ fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+ }
+ else if (template.contains("index-tree.vue.vm"))
+ {
+ fileName = StringUtils.format("{}/views/{}/{}/index.vue", vuePath, moduleName, businessName);
+ }
+ return fileName;
+ }
+
+ /**
+ * 鑾峰彇鍖呭墠缂�
+ *
+ * @param packageName 鍖呭悕绉�
+ * @return 鍖呭墠缂�鍚嶇О
+ */
+ public static String getPackagePrefix(String packageName)
+ {
+ int lastIndex = packageName.lastIndexOf(".");
+ return StringUtils.substring(packageName, 0, lastIndex);
+ }
+
+ /**
+ * 鏍规嵁鍒楃被鍨嬭幏鍙栧鍏ュ寘
+ *
+ * @param genTable 涓氬姟琛ㄥ璞�
+ * @return 杩斿洖闇�瑕佸鍏ョ殑鍖呭垪琛�
+ */
+ public static HashSet<String> getImportList(GenTable genTable)
+ {
+ List<GenTableColumn> columns = genTable.getColumns();
+ GenTable subGenTable = genTable.getSubTable();
+ HashSet<String> importList = new HashSet<String>();
+ if (StringUtils.isNotNull(subGenTable))
+ {
+ importList.add("java.util.List");
+ }
+ for (GenTableColumn column : columns)
+ {
+ if (!column.isSuperColumn() && GenConstants.TYPE_DATE.equals(column.getJavaType()))
+ {
+ importList.add("java.util.Date");
+ importList.add("com.fasterxml.jackson.annotation.JsonFormat");
+ }
+ else if (!column.isSuperColumn() && GenConstants.TYPE_BIGDECIMAL.equals(column.getJavaType()))
+ {
+ importList.add("java.math.BigDecimal");
+ }
+ }
+ return importList;
+ }
+
+ /**
+ * 鏍规嵁鍒楃被鍨嬭幏鍙栧瓧鍏哥粍
+ *
+ * @param genTable 涓氬姟琛ㄥ璞�
+ * @return 杩斿洖瀛楀吀缁�
+ */
+ public static String getDicts(GenTable genTable)
+ {
+ List<GenTableColumn> columns = genTable.getColumns();
+ Set<String> dicts = new HashSet<String>();
+ addDicts(dicts, columns);
+ if (StringUtils.isNotNull(genTable.getSubTable()))
+ {
+ List<GenTableColumn> subColumns = genTable.getSubTable().getColumns();
+ addDicts(dicts, subColumns);
+ }
+ return StringUtils.join(dicts, ", ");
+ }
+
+ /**
+ * 娣诲姞瀛楀吀鍒楄〃
+ *
+ * @param dicts 瀛楀吀鍒楄〃
+ * @param columns 鍒楅泦鍚�
+ */
+ public static void addDicts(Set<String> dicts, List<GenTableColumn> columns)
+ {
+ for (GenTableColumn column : columns)
+ {
+ if (!column.isSuperColumn() && StringUtils.isNotEmpty(column.getDictType()) && StringUtils.equalsAny(
+ column.getHtmlType(),
+ new String[] { GenConstants.HTML_SELECT, GenConstants.HTML_RADIO, GenConstants.HTML_CHECKBOX }))
+ {
+ dicts.add("'" + column.getDictType() + "'");
+ }
+ }
+ }
+
+ /**
+ * 鑾峰彇鏉冮檺鍓嶇紑
+ *
+ * @param moduleName 妯″潡鍚嶇О
+ * @param businessName 涓氬姟鍚嶇О
+ * @return 杩斿洖鏉冮檺鍓嶇紑
+ */
+ public static String getPermissionPrefix(String moduleName, String businessName)
+ {
+ return StringUtils.format("{}:{}", moduleName, businessName);
+ }
+
+ /**
+ * 鑾峰彇涓婄骇鑿滃崟ID瀛楁
+ *
+ * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+ * @return 涓婄骇鑿滃崟ID瀛楁
+ */
+ public static String getParentMenuId(JSONObject paramsObj)
+ {
+ if (StringUtils.isNotEmpty(paramsObj) && paramsObj.containsKey(GenConstants.PARENT_MENU_ID)
+ && StringUtils.isNotEmpty(paramsObj.getString(GenConstants.PARENT_MENU_ID)))
+ {
+ return paramsObj.getString(GenConstants.PARENT_MENU_ID);
+ }
+ return DEFAULT_PARENT_MENU_ID;
+ }
+
+ /**
+ * 鑾峰彇鏍戠紪鐮�
+ *
+ * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+ * @return 鏍戠紪鐮�
+ */
+ public static String getTreecode(JSONObject paramsObj)
+ {
+ if (paramsObj.containsKey(GenConstants.TREE_CODE))
+ {
+ return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_CODE));
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * 鑾峰彇鏍戠埗缂栫爜
+ *
+ * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+ * @return 鏍戠埗缂栫爜
+ */
+ public static String getTreeParentCode(JSONObject paramsObj)
+ {
+ if (paramsObj.containsKey(GenConstants.TREE_PARENT_CODE))
+ {
+ return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_PARENT_CODE));
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * 鑾峰彇鏍戝悕绉�
+ *
+ * @param paramsObj 鐢熸垚鍏朵粬閫夐」
+ * @return 鏍戝悕绉�
+ */
+ public static String getTreeName(JSONObject paramsObj)
+ {
+ if (paramsObj.containsKey(GenConstants.TREE_NAME))
+ {
+ return StringUtils.toCamelCase(paramsObj.getString(GenConstants.TREE_NAME));
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * 鑾峰彇闇�瑕佸湪鍝竴鍒椾笂闈㈡樉绀哄睍寮�鎸夐挳
+ *
+ * @param genTable 涓氬姟琛ㄥ璞�
+ * @return 灞曞紑鎸夐挳鍒楀簭鍙�
+ */
+ public static int getExpandColumn(GenTable genTable)
+ {
+ String options = genTable.getOptions();
+ JSONObject paramsObj = JSON.parseObject(options);
+ String treeName = paramsObj.getString(GenConstants.TREE_NAME);
+ int num = 0;
+ for (GenTableColumn column : genTable.getColumns())
+ {
+ if (column.isList())
+ {
+ num++;
+ String columnName = column.getColumnName();
+ if (columnName.equals(treeName))
+ {
+ break;
+ }
+ }
+ }
+ return num;
+ }
+}
diff --git a/ruoyi-generator/src/main/resources/generator.yml b/ruoyi-generator/src/main/resources/generator.yml
new file mode 100644
index 0000000..d1cbf48
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/generator.yml
@@ -0,0 +1,12 @@
+# 浠g爜鐢熸垚
+gen:
+ # 浣滆��
+ author: ruoyi
+ # 榛樿鐢熸垚鍖呰矾寰� system 闇�鏀规垚鑷繁鐨勬ā鍧楀悕绉� 濡� system monitor tool
+ packageName: com.ruoyi.system
+ # 鑷姩鍘婚櫎琛ㄥ墠缂�锛岄粯璁ゆ槸false
+ autoRemovePre: false
+ # 琛ㄥ墠缂�锛堢敓鎴愮被鍚嶄笉浼氬寘鍚〃鍓嶇紑锛屽涓敤閫楀彿鍒嗛殧锛�
+ tablePrefix: sys_
+ # 鏄惁鍏佽鐢熸垚鏂囦欢瑕嗙洊鍒版湰鍦帮紙鑷畾涔夎矾寰勶級锛岄粯璁や笉鍏佽
+ allowOverwrite: false
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
new file mode 100644
index 0000000..52857e8
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableColumnMapper.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.generator.mapper.GenTableColumnMapper">
+
+ <resultMap type="GenTableColumn" id="GenTableColumnResult">
+ <id property="columnId" column="column_id" />
+ <result property="tableId" column="table_id" />
+ <result property="columnName" column="column_name" />
+ <result property="columnComment" column="column_comment" />
+ <result property="columnType" column="column_type" />
+ <result property="javaType" column="java_type" />
+ <result property="javaField" column="java_field" />
+ <result property="isPk" column="is_pk" />
+ <result property="isIncrement" column="is_increment" />
+ <result property="isRequired" column="is_required" />
+ <result property="isInsert" column="is_insert" />
+ <result property="isEdit" column="is_edit" />
+ <result property="isList" column="is_list" />
+ <result property="isQuery" column="is_query" />
+ <result property="queryType" column="query_type" />
+ <result property="htmlType" column="html_type" />
+ <result property="dictType" column="dict_type" />
+ <result property="sort" column="sort" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectGenTableColumnVo">
+ select column_id, table_id, column_name, column_comment, column_type, java_type, java_field, is_pk, is_increment, is_required, is_insert, is_edit, is_list, is_query, query_type, html_type, dict_type, sort, create_by, create_time, update_by, update_time from gen_table_column
+ </sql>
+
+ <select id="selectGenTableColumnListByTableId" parameterType="Long" resultMap="GenTableColumnResult">
+ <include refid="selectGenTableColumnVo"/>
+ where table_id = #{tableId}
+ order by sort
+ </select>
+
+ <select id="selectDbTableColumnsByName" parameterType="String" resultMap="GenTableColumnResult">
+ select column_name, (case when (is_nullable = 'no' <![CDATA[ && ]]> column_key != 'PRI') then '1' else '0' end) as is_required, (case when column_key = 'PRI' then '1' else '0' end) as is_pk, ordinal_position as sort, column_comment, (case when extra = 'auto_increment' then '1' else '0' end) as is_increment, column_type
+ from information_schema.columns where table_schema = (select database()) and table_name = (#{tableName})
+ order by ordinal_position
+ </select>
+
+ <insert id="insertGenTableColumn" parameterType="GenTableColumn" useGeneratedKeys="true" keyProperty="columnId">
+ insert into gen_table_column (
+ <if test="tableId != null and tableId != ''">table_id,</if>
+ <if test="columnName != null and columnName != ''">column_name,</if>
+ <if test="columnComment != null and columnComment != ''">column_comment,</if>
+ <if test="columnType != null and columnType != ''">column_type,</if>
+ <if test="javaType != null and javaType != ''">java_type,</if>
+ <if test="javaField != null and javaField != ''">java_field,</if>
+ <if test="isPk != null and isPk != ''">is_pk,</if>
+ <if test="isIncrement != null and isIncrement != ''">is_increment,</if>
+ <if test="isRequired != null and isRequired != ''">is_required,</if>
+ <if test="isInsert != null and isInsert != ''">is_insert,</if>
+ <if test="isEdit != null and isEdit != ''">is_edit,</if>
+ <if test="isList != null and isList != ''">is_list,</if>
+ <if test="isQuery != null and isQuery != ''">is_query,</if>
+ <if test="queryType != null and queryType != ''">query_type,</if>
+ <if test="htmlType != null and htmlType != ''">html_type,</if>
+ <if test="dictType != null and dictType != ''">dict_type,</if>
+ <if test="sort != null">sort,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="tableId != null and tableId != ''">#{tableId},</if>
+ <if test="columnName != null and columnName != ''">#{columnName},</if>
+ <if test="columnComment != null and columnComment != ''">#{columnComment},</if>
+ <if test="columnType != null and columnType != ''">#{columnType},</if>
+ <if test="javaType != null and javaType != ''">#{javaType},</if>
+ <if test="javaField != null and javaField != ''">#{javaField},</if>
+ <if test="isPk != null and isPk != ''">#{isPk},</if>
+ <if test="isIncrement != null and isIncrement != ''">#{isIncrement},</if>
+ <if test="isRequired != null and isRequired != ''">#{isRequired},</if>
+ <if test="isInsert != null and isInsert != ''">#{isInsert},</if>
+ <if test="isEdit != null and isEdit != ''">#{isEdit},</if>
+ <if test="isList != null and isList != ''">#{isList},</if>
+ <if test="isQuery != null and isQuery != ''">#{isQuery},</if>
+ <if test="queryType != null and queryType != ''">#{queryType},</if>
+ <if test="htmlType != null and htmlType != ''">#{htmlType},</if>
+ <if test="dictType != null and dictType != ''">#{dictType},</if>
+ <if test="sort != null">#{sort},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="updateGenTableColumn" parameterType="GenTableColumn">
+ update gen_table_column
+ <set>
+ <if test="columnComment != null">column_comment = #{columnComment},</if>
+ <if test="javaType != null">java_type = #{javaType},</if>
+ <if test="javaField != null">java_field = #{javaField},</if>
+ <if test="isInsert != null">is_insert = #{isInsert},</if>
+ <if test="isEdit != null">is_edit = #{isEdit},</if>
+ <if test="isList != null">is_list = #{isList},</if>
+ <if test="isQuery != null">is_query = #{isQuery},</if>
+ <if test="isRequired != null">is_required = #{isRequired},</if>
+ <if test="queryType != null">query_type = #{queryType},</if>
+ <if test="htmlType != null">html_type = #{htmlType},</if>
+ <if test="dictType != null">dict_type = #{dictType},</if>
+ <if test="sort != null">sort = #{sort},</if>
+ <if test="updateBy != null">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where column_id = #{columnId}
+ </update>
+
+ <delete id="deleteGenTableColumnByIds" parameterType="Long">
+ delete from gen_table_column where table_id in
+ <foreach collection="array" item="tableId" open="(" separator="," close=")">
+ #{tableId}
+ </foreach>
+ </delete>
+
+ <delete id="deleteGenTableColumns">
+ delete from gen_table_column where column_id in
+ <foreach collection="list" item="item" open="(" separator="," close=")">
+ #{item.columnId}
+ </foreach>
+ </delete>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
new file mode 100644
index 0000000..d1110f7
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/mapper/generator/GenTableMapper.xml
@@ -0,0 +1,210 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.generator.mapper.GenTableMapper">
+
+ <resultMap type="GenTable" id="GenTableResult">
+ <id property="tableId" column="table_id" />
+ <result property="tableName" column="table_name" />
+ <result property="tableComment" column="table_comment" />
+ <result property="subTableName" column="sub_table_name" />
+ <result property="subTableFkName" column="sub_table_fk_name" />
+ <result property="className" column="class_name" />
+ <result property="tplCategory" column="tpl_category" />
+ <result property="tplWebType" column="tpl_web_type" />
+ <result property="packageName" column="package_name" />
+ <result property="moduleName" column="module_name" />
+ <result property="businessName" column="business_name" />
+ <result property="functionName" column="function_name" />
+ <result property="functionAuthor" column="function_author" />
+ <result property="genType" column="gen_type" />
+ <result property="genPath" column="gen_path" />
+ <result property="options" column="options" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="remark" column="remark" />
+ <collection property="columns" javaType="java.util.List" resultMap="GenTableColumnResult" />
+ </resultMap>
+
+ <resultMap type="GenTableColumn" id="GenTableColumnResult">
+ <id property="columnId" column="column_id" />
+ <result property="tableId" column="table_id" />
+ <result property="columnName" column="column_name" />
+ <result property="columnComment" column="column_comment" />
+ <result property="columnType" column="column_type" />
+ <result property="javaType" column="java_type" />
+ <result property="javaField" column="java_field" />
+ <result property="isPk" column="is_pk" />
+ <result property="isIncrement" column="is_increment" />
+ <result property="isRequired" column="is_required" />
+ <result property="isInsert" column="is_insert" />
+ <result property="isEdit" column="is_edit" />
+ <result property="isList" column="is_list" />
+ <result property="isQuery" column="is_query" />
+ <result property="queryType" column="query_type" />
+ <result property="htmlType" column="html_type" />
+ <result property="dictType" column="dict_type" />
+ <result property="sort" column="sort" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectGenTableVo">
+ select table_id, table_name, table_comment, sub_table_name, sub_table_fk_name, class_name, tpl_category, tpl_web_type, package_name, module_name, business_name, function_name, function_author, gen_type, gen_path, options, create_by, create_time, update_by, update_time, remark from gen_table
+ </sql>
+
+ <select id="selectGenTableList" parameterType="GenTable" resultMap="GenTableResult">
+ <include refid="selectGenTableVo"/>
+ <where>
+ <if test="tableName != null and tableName != ''">
+ AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
+ </if>
+ <if test="tableComment != null and tableComment != ''">
+ AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ AND date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ AND date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ </if>
+ </where>
+ </select>
+
+ <select id="selectDbTableList" parameterType="GenTable" resultMap="GenTableResult">
+ select table_name, table_comment, create_time, update_time from information_schema.tables
+ where table_schema = (select database())
+ AND table_name NOT LIKE 'qrtz\_%' AND table_name NOT LIKE 'gen\_%'
+ AND table_name NOT IN (select table_name from gen_table)
+ <if test="tableName != null and tableName != ''">
+ AND lower(table_name) like lower(concat('%', #{tableName}, '%'))
+ </if>
+ <if test="tableComment != null and tableComment != ''">
+ AND lower(table_comment) like lower(concat('%', #{tableComment}, '%'))
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ AND date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ AND date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ </if>
+ order by create_time desc
+ </select>
+
+ <select id="selectDbTableListByNames" resultMap="GenTableResult">
+ select table_name, table_comment, create_time, update_time from information_schema.tables
+ where table_name NOT LIKE 'qrtz\_%' and table_name NOT LIKE 'gen\_%' and table_schema = (select database())
+ and table_name in
+ <foreach collection="array" item="name" open="(" separator="," close=")">
+ #{name}
+ </foreach>
+ </select>
+
+ <select id="selectTableByName" parameterType="String" resultMap="GenTableResult">
+ select table_name, table_comment, create_time, update_time from information_schema.tables
+ where table_comment <![CDATA[ <> ]]> '' and table_schema = (select database())
+ and table_name = #{tableName}
+ </select>
+
+ <select id="selectGenTableById" parameterType="Long" resultMap="GenTableResult">
+ SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
+ c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+ FROM gen_table t
+ LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+ where t.table_id = #{tableId} order by c.sort
+ </select>
+
+ <select id="selectGenTableByName" parameterType="String" resultMap="GenTableResult">
+ SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.gen_type, t.gen_path, t.options, t.remark,
+ c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+ FROM gen_table t
+ LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+ where t.table_name = #{tableName} order by c.sort
+ </select>
+
+ <select id="selectGenTableAll" parameterType="String" resultMap="GenTableResult">
+ SELECT t.table_id, t.table_name, t.table_comment, t.sub_table_name, t.sub_table_fk_name, t.class_name, t.tpl_category, t.tpl_web_type, t.package_name, t.module_name, t.business_name, t.function_name, t.function_author, t.options, t.remark,
+ c.column_id, c.column_name, c.column_comment, c.column_type, c.java_type, c.java_field, c.is_pk, c.is_increment, c.is_required, c.is_insert, c.is_edit, c.is_list, c.is_query, c.query_type, c.html_type, c.dict_type, c.sort
+ FROM gen_table t
+ LEFT JOIN gen_table_column c ON t.table_id = c.table_id
+ order by c.sort
+ </select>
+
+ <insert id="insertGenTable" parameterType="GenTable" useGeneratedKeys="true" keyProperty="tableId">
+ insert into gen_table (
+ <if test="tableName != null">table_name,</if>
+ <if test="tableComment != null and tableComment != ''">table_comment,</if>
+ <if test="className != null and className != ''">class_name,</if>
+ <if test="tplCategory != null and tplCategory != ''">tpl_category,</if>
+ <if test="tplWebType != null and tplWebType != ''">tpl_web_type,</if>
+ <if test="packageName != null and packageName != ''">package_name,</if>
+ <if test="moduleName != null and moduleName != ''">module_name,</if>
+ <if test="businessName != null and businessName != ''">business_name,</if>
+ <if test="functionName != null and functionName != ''">function_name,</if>
+ <if test="functionAuthor != null and functionAuthor != ''">function_author,</if>
+ <if test="genType != null and genType != ''">gen_type,</if>
+ <if test="genPath != null and genPath != ''">gen_path,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="tableName != null">#{tableName},</if>
+ <if test="tableComment != null and tableComment != ''">#{tableComment},</if>
+ <if test="className != null and className != ''">#{className},</if>
+ <if test="tplCategory != null and tplCategory != ''">#{tplCategory},</if>
+ <if test="tplWebType != null and tplWebType != ''">#{tplWebType},</if>
+ <if test="packageName != null and packageName != ''">#{packageName},</if>
+ <if test="moduleName != null and moduleName != ''">#{moduleName},</if>
+ <if test="businessName != null and businessName != ''">#{businessName},</if>
+ <if test="functionName != null and functionName != ''">#{functionName},</if>
+ <if test="functionAuthor != null and functionAuthor != ''">#{functionAuthor},</if>
+ <if test="genType != null and genType != ''">#{genType},</if>
+ <if test="genPath != null and genPath != ''">#{genPath},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="createTable">
+ ${sql}
+ </update>
+
+ <update id="updateGenTable" parameterType="GenTable">
+ update gen_table
+ <set>
+ <if test="tableName != null">table_name = #{tableName},</if>
+ <if test="tableComment != null and tableComment != ''">table_comment = #{tableComment},</if>
+ <if test="subTableName != null">sub_table_name = #{subTableName},</if>
+ <if test="subTableFkName != null">sub_table_fk_name = #{subTableFkName},</if>
+ <if test="className != null and className != ''">class_name = #{className},</if>
+ <if test="functionAuthor != null and functionAuthor != ''">function_author = #{functionAuthor},</if>
+ <if test="genType != null and genType != ''">gen_type = #{genType},</if>
+ <if test="genPath != null and genPath != ''">gen_path = #{genPath},</if>
+ <if test="tplCategory != null and tplCategory != ''">tpl_category = #{tplCategory},</if>
+ <if test="tplWebType != null and tplWebType != ''">tpl_web_type = #{tplWebType},</if>
+ <if test="packageName != null and packageName != ''">package_name = #{packageName},</if>
+ <if test="moduleName != null and moduleName != ''">module_name = #{moduleName},</if>
+ <if test="businessName != null and businessName != ''">business_name = #{businessName},</if>
+ <if test="functionName != null and functionName != ''">function_name = #{functionName},</if>
+ <if test="options != null and options != ''">options = #{options},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ update_time = sysdate()
+ </set>
+ where table_id = #{tableId}
+ </update>
+
+ <delete id="deleteGenTableByIds" parameterType="Long">
+ delete from gen_table where table_id in
+ <foreach collection="array" item="tableId" open="(" separator="," close=")">
+ #{tableId}
+ </foreach>
+ </delete>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/java/controller.java.vm b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
new file mode 100644
index 0000000..0eab21c
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/controller.java.vm
@@ -0,0 +1,115 @@
+package ${packageName}.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.enums.BusinessType;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.I${ClassName}Service;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+#if($table.crud || $table.sub)
+import com.ruoyi.common.core.page.TableDataInfo;
+#elseif($table.tree)
+#end
+
+/**
+ * ${functionName}Controller
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@RestController
+@RequestMapping("/${moduleName}/${businessName}")
+public class ${ClassName}Controller extends BaseController
+{
+ @Autowired
+ private I${ClassName}Service ${className}Service;
+
+ /**
+ * 鏌ヨ${functionName}鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('${permissionPrefix}:list')")
+ @GetMapping("/list")
+#if($table.crud || $table.sub)
+ public TableDataInfo list(${ClassName} ${className})
+ {
+ startPage();
+ List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+ return getDataTable(list);
+ }
+#elseif($table.tree)
+ public AjaxResult list(${ClassName} ${className})
+ {
+ List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+ return success(list);
+ }
+#end
+
+ /**
+ * 瀵煎嚭${functionName}鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('${permissionPrefix}:export')")
+ @Log(title = "${functionName}", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, ${ClassName} ${className})
+ {
+ List<${ClassName}> list = ${className}Service.select${ClassName}List(${className});
+ ExcelUtil<${ClassName}> util = new ExcelUtil<${ClassName}>(${ClassName}.class);
+ util.exportExcel(response, list, "${functionName}鏁版嵁");
+ }
+
+ /**
+ * 鑾峰彇${functionName}璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('${permissionPrefix}:query')")
+ @GetMapping(value = "/{${pkColumn.javaField}}")
+ public AjaxResult getInfo(@PathVariable("${pkColumn.javaField}") ${pkColumn.javaType} ${pkColumn.javaField})
+ {
+ return success(${className}Service.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField}));
+ }
+
+ /**
+ * 鏂板${functionName}
+ */
+ @PreAuthorize("@ss.hasPermi('${permissionPrefix}:add')")
+ @Log(title = "${functionName}", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody ${ClassName} ${className})
+ {
+ return toAjax(${className}Service.insert${ClassName}(${className}));
+ }
+
+ /**
+ * 淇敼${functionName}
+ */
+ @PreAuthorize("@ss.hasPermi('${permissionPrefix}:edit')")
+ @Log(title = "${functionName}", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody ${ClassName} ${className})
+ {
+ return toAjax(${className}Service.update${ClassName}(${className}));
+ }
+
+ /**
+ * 鍒犻櫎${functionName}
+ */
+ @PreAuthorize("@ss.hasPermi('${permissionPrefix}:remove')")
+ @Log(title = "${functionName}", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{${pkColumn.javaField}s}")
+ public AjaxResult remove(@PathVariable ${pkColumn.javaType}[] ${pkColumn.javaField}s)
+ {
+ return toAjax(${className}Service.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s));
+ }
+}
diff --git a/ruoyi-generator/src/main/resources/vm/java/domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
new file mode 100644
index 0000000..bd51c17
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/domain.java.vm
@@ -0,0 +1,105 @@
+package ${packageName}.domain;
+
+#foreach ($import in $importList)
+import ${import};
+#end
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+#if($table.crud || $table.sub)
+import com.ruoyi.common.core.domain.BaseEntity;
+#elseif($table.tree)
+import com.ruoyi.common.core.domain.TreeEntity;
+#end
+
+/**
+ * ${functionName}瀵硅薄 ${tableName}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+#if($table.crud || $table.sub)
+#set($Entity="BaseEntity")
+#elseif($table.tree)
+#set($Entity="TreeEntity")
+#end
+public class ${ClassName} extends ${Entity}
+{
+ private static final long serialVersionUID = 1L;
+
+#foreach ($column in $columns)
+#if(!$table.isSuperColumn($column.javaField))
+ /** $column.columnComment */
+#if($column.list)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($parentheseIndex != -1)
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+#elseif($column.javaType == 'Date')
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
+#else
+ @Excel(name = "${comment}")
+#end
+#end
+ private $column.javaType $column.javaField;
+
+#end
+#end
+#if($table.sub)
+ /** $table.subTable.functionName淇℃伅 */
+ private List<${subClassName}> ${subclassName}List;
+
+#end
+#foreach ($column in $columns)
+#if(!$table.isSuperColumn($column.javaField))
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+ public void set${AttrName}($column.javaType $column.javaField)
+ {
+ this.$column.javaField = $column.javaField;
+ }
+
+ public $column.javaType get${AttrName}()
+ {
+ return $column.javaField;
+ }
+#end
+#end
+
+#if($table.sub)
+ public List<${subClassName}> get${subClassName}List()
+ {
+ return ${subclassName}List;
+ }
+
+ public void set${subClassName}List(List<${subClassName}> ${subclassName}List)
+ {
+ this.${subclassName}List = ${subclassName}List;
+ }
+
+#end
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+#foreach ($column in $columns)
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+ .append("${column.javaField}", get${AttrName}())
+#end
+#if($table.sub)
+ .append("${subclassName}List", get${subClassName}List())
+#end
+ .toString();
+ }
+}
diff --git a/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
new file mode 100644
index 0000000..7e7d7c2
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/mapper.java.vm
@@ -0,0 +1,91 @@
+package ${packageName}.mapper;
+
+import java.util.List;
+import ${packageName}.domain.${ClassName};
+#if($table.sub)
+import ${packageName}.domain.${subClassName};
+#end
+
+/**
+ * ${functionName}Mapper鎺ュ彛
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+public interface ${ClassName}Mapper
+{
+ /**
+ * 鏌ヨ${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}涓婚敭
+ * @return ${functionName}
+ */
+ public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+ /**
+ * 鏌ヨ${functionName}鍒楄〃
+ *
+ * @param ${className} ${functionName}
+ * @return ${functionName}闆嗗悎
+ */
+ public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+ /**
+ * 鏂板${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 缁撴灉
+ */
+ public int insert${ClassName}(${ClassName} ${className});
+
+ /**
+ * 淇敼${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 缁撴灉
+ */
+ public int update${ClassName}(${ClassName} ${className});
+
+ /**
+ * 鍒犻櫎${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}涓婚敭
+ * @return 缁撴灉
+ */
+ public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+ /**
+ * 鎵归噺鍒犻櫎${functionName}
+ *
+ * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+#if($table.sub)
+
+ /**
+ * 鎵归噺鍒犻櫎${subTable.functionName}
+ *
+ * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+
+ /**
+ * 鎵归噺鏂板${subTable.functionName}
+ *
+ * @param ${subclassName}List ${subTable.functionName}鍒楄〃
+ * @return 缁撴灉
+ */
+ public int batch${subClassName}(List<${subClassName}> ${subclassName}List);
+
+
+ /**
+ * 閫氳繃${functionName}涓婚敭鍒犻櫎${subTable.functionName}淇℃伅
+ *
+ * @param ${pkColumn.javaField} ${functionName}ID
+ * @return 缁撴灉
+ */
+ public int delete${subClassName}By${subTableFkClassName}(${pkColumn.javaType} ${pkColumn.javaField});
+#end
+}
diff --git a/ruoyi-generator/src/main/resources/vm/java/service.java.vm b/ruoyi-generator/src/main/resources/vm/java/service.java.vm
new file mode 100644
index 0000000..264882b
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/service.java.vm
@@ -0,0 +1,61 @@
+package ${packageName}.service;
+
+import java.util.List;
+import ${packageName}.domain.${ClassName};
+
+/**
+ * ${functionName}Service鎺ュ彛
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+public interface I${ClassName}Service
+{
+ /**
+ * 鏌ヨ${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}涓婚敭
+ * @return ${functionName}
+ */
+ public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+
+ /**
+ * 鏌ヨ${functionName}鍒楄〃
+ *
+ * @param ${className} ${functionName}
+ * @return ${functionName}闆嗗悎
+ */
+ public List<${ClassName}> select${ClassName}List(${ClassName} ${className});
+
+ /**
+ * 鏂板${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 缁撴灉
+ */
+ public int insert${ClassName}(${ClassName} ${className});
+
+ /**
+ * 淇敼${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 缁撴灉
+ */
+ public int update${ClassName}(${ClassName} ${className});
+
+ /**
+ * 鎵归噺鍒犻櫎${functionName}
+ *
+ * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑${functionName}涓婚敭闆嗗悎
+ * @return 缁撴灉
+ */
+ public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s);
+
+ /**
+ * 鍒犻櫎${functionName}淇℃伅
+ *
+ * @param ${pkColumn.javaField} ${functionName}涓婚敭
+ * @return 缁撴灉
+ */
+ public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField});
+}
diff --git a/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
new file mode 100644
index 0000000..14746e1
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/serviceImpl.java.vm
@@ -0,0 +1,169 @@
+package ${packageName}.service.impl;
+
+import java.util.List;
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime' || $column.javaField == 'updateTime')
+import com.ruoyi.common.utils.DateUtils;
+#break
+#end
+#end
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+#if($table.sub)
+import java.util.ArrayList;
+import com.ruoyi.common.utils.StringUtils;
+import org.springframework.transaction.annotation.Transactional;
+import ${packageName}.domain.${subClassName};
+#end
+import ${packageName}.mapper.${ClassName}Mapper;
+import ${packageName}.domain.${ClassName};
+import ${packageName}.service.I${ClassName}Service;
+
+/**
+ * ${functionName}Service涓氬姟灞傚鐞�
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+@Service
+public class ${ClassName}ServiceImpl implements I${ClassName}Service
+{
+ @Autowired
+ private ${ClassName}Mapper ${className}Mapper;
+
+ /**
+ * 鏌ヨ${functionName}
+ *
+ * @param ${pkColumn.javaField} ${functionName}涓婚敭
+ * @return ${functionName}
+ */
+ @Override
+ public ${ClassName} select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
+ {
+ return ${className}Mapper.select${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
+ }
+
+ /**
+ * 鏌ヨ${functionName}鍒楄〃
+ *
+ * @param ${className} ${functionName}
+ * @return ${functionName}
+ */
+ @Override
+ public List<${ClassName}> select${ClassName}List(${ClassName} ${className})
+ {
+ return ${className}Mapper.select${ClassName}List(${className});
+ }
+
+ /**
+ * 鏂板${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 缁撴灉
+ */
+#if($table.sub)
+ @Transactional
+#end
+ @Override
+ public int insert${ClassName}(${ClassName} ${className})
+ {
+#foreach ($column in $columns)
+#if($column.javaField == 'createTime')
+ ${className}.setCreateTime(DateUtils.getNowDate());
+#end
+#end
+#if($table.sub)
+ int rows = ${className}Mapper.insert${ClassName}(${className});
+ insert${subClassName}(${className});
+ return rows;
+#else
+ return ${className}Mapper.insert${ClassName}(${className});
+#end
+ }
+
+ /**
+ * 淇敼${functionName}
+ *
+ * @param ${className} ${functionName}
+ * @return 缁撴灉
+ */
+#if($table.sub)
+ @Transactional
+#end
+ @Override
+ public int update${ClassName}(${ClassName} ${className})
+ {
+#foreach ($column in $columns)
+#if($column.javaField == 'updateTime')
+ ${className}.setUpdateTime(DateUtils.getNowDate());
+#end
+#end
+#if($table.sub)
+ ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${className}.get${pkColumn.capJavaField}());
+ insert${subClassName}(${className});
+#end
+ return ${className}Mapper.update${ClassName}(${className});
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎${functionName}
+ *
+ * @param ${pkColumn.javaField}s 闇�瑕佸垹闄ょ殑${functionName}涓婚敭
+ * @return 缁撴灉
+ */
+#if($table.sub)
+ @Transactional
+#end
+ @Override
+ public int delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaType}[] ${pkColumn.javaField}s)
+ {
+#if($table.sub)
+ ${className}Mapper.delete${subClassName}By${subTableFkClassName}s(${pkColumn.javaField}s);
+#end
+ return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}s(${pkColumn.javaField}s);
+ }
+
+ /**
+ * 鍒犻櫎${functionName}淇℃伅
+ *
+ * @param ${pkColumn.javaField} ${functionName}涓婚敭
+ * @return 缁撴灉
+ */
+#if($table.sub)
+ @Transactional
+#end
+ @Override
+ public int delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaType} ${pkColumn.javaField})
+ {
+#if($table.sub)
+ ${className}Mapper.delete${subClassName}By${subTableFkClassName}(${pkColumn.javaField});
+#end
+ return ${className}Mapper.delete${ClassName}By${pkColumn.capJavaField}(${pkColumn.javaField});
+ }
+#if($table.sub)
+
+ /**
+ * 鏂板${subTable.functionName}淇℃伅
+ *
+ * @param ${className} ${functionName}瀵硅薄
+ */
+ public void insert${subClassName}(${ClassName} ${className})
+ {
+ List<${subClassName}> ${subclassName}List = ${className}.get${subClassName}List();
+ ${pkColumn.javaType} ${pkColumn.javaField} = ${className}.get${pkColumn.capJavaField}();
+ if (StringUtils.isNotNull(${subclassName}List))
+ {
+ List<${subClassName}> list = new ArrayList<${subClassName}>();
+ for (${subClassName} ${subclassName} : ${subclassName}List)
+ {
+ ${subclassName}.set${subTableFkClassName}(${pkColumn.javaField});
+ list.add(${subclassName});
+ }
+ if (list.size() > 0)
+ {
+ ${className}Mapper.batch${subClassName}(list);
+ }
+ }
+ }
+#end
+}
diff --git a/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm b/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm
new file mode 100644
index 0000000..a3f53eb
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/java/sub-domain.java.vm
@@ -0,0 +1,76 @@
+package ${packageName}.domain;
+
+#foreach ($import in $subImportList)
+import ${import};
+#end
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * ${subTable.functionName}瀵硅薄 ${subTableName}
+ *
+ * @author ${author}
+ * @date ${datetime}
+ */
+public class ${subClassName} extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+#foreach ($column in $subTable.columns)
+#if(!$table.isSuperColumn($column.javaField))
+ /** $column.columnComment */
+#if($column.list)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($parentheseIndex != -1)
+ @Excel(name = "${comment}", readConverterExp = "$column.readConverterExp()")
+#elseif($column.javaType == 'Date')
+ @JsonFormat(pattern = "yyyy-MM-dd")
+ @Excel(name = "${comment}", width = 30, dateFormat = "yyyy-MM-dd")
+#else
+ @Excel(name = "${comment}")
+#end
+#end
+ private $column.javaType $column.javaField;
+
+#end
+#end
+#foreach ($column in $subTable.columns)
+#if(!$table.isSuperColumn($column.javaField))
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+ public void set${AttrName}($column.javaType $column.javaField)
+ {
+ this.$column.javaField = $column.javaField;
+ }
+
+ public $column.javaType get${AttrName}()
+ {
+ return $column.javaField;
+ }
+#end
+#end
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+#foreach ($column in $subTable.columns)
+#if($column.javaField.length() > 2 && $column.javaField.substring(1,2).matches("[A-Z]"))
+#set($AttrName=$column.javaField)
+#else
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#end
+ .append("${column.javaField}", get${AttrName}())
+#end
+ .toString();
+ }
+}
diff --git a/ruoyi-generator/src/main/resources/vm/js/api.js.vm b/ruoyi-generator/src/main/resources/vm/js/api.js.vm
new file mode 100644
index 0000000..9295524
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/js/api.js.vm
@@ -0,0 +1,44 @@
+import request from '@/utils/request'
+
+// 鏌ヨ${functionName}鍒楄〃
+export function list${BusinessName}(query) {
+ return request({
+ url: '/${moduleName}/${businessName}/list',
+ method: 'get',
+ params: query
+ })
+}
+
+// 鏌ヨ${functionName}璇︾粏
+export function get${BusinessName}(${pkColumn.javaField}) {
+ return request({
+ url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
+ method: 'get'
+ })
+}
+
+// 鏂板${functionName}
+export function add${BusinessName}(data) {
+ return request({
+ url: '/${moduleName}/${businessName}',
+ method: 'post',
+ data: data
+ })
+}
+
+// 淇敼${functionName}
+export function update${BusinessName}(data) {
+ return request({
+ url: '/${moduleName}/${businessName}',
+ method: 'put',
+ data: data
+ })
+}
+
+// 鍒犻櫎${functionName}
+export function del${BusinessName}(${pkColumn.javaField}) {
+ return request({
+ url: '/${moduleName}/${businessName}/' + ${pkColumn.javaField},
+ method: 'delete'
+ })
+}
diff --git a/ruoyi-generator/src/main/resources/vm/sql/sql.vm b/ruoyi-generator/src/main/resources/vm/sql/sql.vm
new file mode 100644
index 0000000..0575583
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/sql/sql.vm
@@ -0,0 +1,22 @@
+-- 鑿滃崟 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}', '${parentMenuId}', '1', '${businessName}', '${moduleName}/${businessName}/index', 1, 0, 'C', '0', '0', '${permissionPrefix}:list', '#', 'admin', sysdate(), '', null, '${functionName}鑿滃崟');
+
+-- 鎸夐挳鐖惰彍鍗旾D
+SELECT @parentId := LAST_INSERT_ID();
+
+-- 鎸夐挳 SQL
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}鏌ヨ', @parentId, '1', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:query', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}鏂板', @parentId, '2', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:add', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}淇敼', @parentId, '3', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:edit', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}鍒犻櫎', @parentId, '4', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:remove', '#', 'admin', sysdate(), '', null, '');
+
+insert into sys_menu (menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values('${functionName}瀵煎嚭', @parentId, '5', '#', '', 1, 0, 'F', '0', '0', '${permissionPrefix}:export', '#', 'admin', sysdate(), '', null, '');
\ No newline at end of file
diff --git a/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
new file mode 100644
index 0000000..4819c2a
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/vue/index-tree.vue.vm
@@ -0,0 +1,505 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-input
+ v-model="queryParams.${column.javaField}"
+ placeholder="璇疯緭鍏�${comment}"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-date-picker clearable
+ v-model="queryParams.${column.javaField}"
+ type="date"
+ value-format="yyyy-MM-dd"
+ placeholder="閫夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ <el-form-item label="${comment}">
+ <el-date-picker
+ v-model="daterange${AttrName}"
+ style="width: 240px"
+ value-format="yyyy-MM-dd"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ </el-form-item>
+#end
+#end
+#end
+ <el-form-item>
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="el-icon-plus"
+ size="mini"
+ @click="handleAdd"
+ v-hasPermi="['${moduleName}:${businessName}:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="info"
+ plain
+ icon="el-icon-sort"
+ size="mini"
+ @click="toggleExpandAll"
+ >灞曞紑/鎶樺彔</el-button>
+ </el-col>
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table
+ v-if="refreshTable"
+ v-loading="loading"
+ :data="${businessName}List"
+ row-key="${treeCode}"
+ :default-expand-all="isExpandAll"
+ :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+ >
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list && $column.htmlType == "datetime")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+#elseif($column.list && $column.htmlType == "imageUpload")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+ <template slot-scope="scope">
+ <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $column.dictType)
+ <el-table-column label="${comment}" align="center" prop="${javaField}">
+ <template slot-scope="scope">
+#if($column.htmlType == "checkbox")
+ <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+ <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $javaField)
+#if(${foreach.index} == 1)
+ <el-table-column label="${comment}" prop="${javaField}" />
+#else
+ <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+#end
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-edit"
+ @click="handleUpdate(scope.row)"
+ v-hasPermi="['${moduleName}:${businessName}:edit']"
+ >淇敼</el-button>
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-plus"
+ @click="handleAdd(scope.row)"
+ v-hasPermi="['${moduleName}:${businessName}:add']"
+ >鏂板</el-button>
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-delete"
+ @click="handleDelete(scope.row)"
+ v-hasPermi="['${moduleName}:${businessName}:remove']"
+ >鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+ <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+ <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+ <el-form-item label="${comment}" prop="${treeParentCode}">
+ <treeselect v-model="form.${treeParentCode}" :options="${businessName}Options" :normalizer="normalizer" placeholder="璇烽�夋嫨${comment}" />
+ </el-form-item>
+#elseif($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+ </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <image-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <file-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "editor")
+ <el-form-item label="${comment}">
+ <editor v-model="form.${field}" :min-height="192"/>
+ </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :value="parseInt(dict.value)"
+#else
+ :value="dict.value"
+#end
+ ></el-option>
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+ :label="dict.value">
+ {{dict.label}}
+ </el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :label="parseInt(dict.value)"
+#else
+ :label="dict.value"
+#end
+ >{{dict.label}}</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "datetime")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-date-picker clearable
+ v-model="form.${field}"
+ type="date"
+ value-format="yyyy-MM-dd"
+ placeholder="閫夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "textarea")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+ </el-form-item>
+#end
+#end
+#end
+#end
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+ <el-button @click="cancel">鍙� 娑�</el-button>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+import Treeselect from "@riophae/vue-treeselect";
+import "@riophae/vue-treeselect/dist/vue-treeselect.css";
+
+export default {
+ name: "${BusinessName}",
+#if(${dicts} != '')
+ dicts: [${dicts}],
+#end
+ components: {
+ Treeselect
+ },
+ data() {
+ return {
+ // 閬僵灞�
+ loading: true,
+ // 鏄剧ず鎼滅储鏉′欢
+ showSearch: true,
+ // ${functionName}琛ㄦ牸鏁版嵁
+ ${businessName}List: [],
+ // ${functionName}鏍戦�夐」
+ ${businessName}Options: [],
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+ // 鏄惁灞曞紑锛岄粯璁ゅ叏閮ㄥ睍寮�
+ isExpandAll: true,
+ // 閲嶆柊娓叉煋琛ㄦ牸鐘舵��
+ refreshTable: true,
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ // $comment鏃堕棿鑼冨洿
+ daterange${AttrName}: [],
+#end
+#end
+ // 鏌ヨ鍙傛暟
+ queryParams: {
+#foreach ($column in $columns)
+#if($column.query)
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ },
+ // 琛ㄥ崟鍙傛暟
+ form: {},
+ // 琛ㄥ崟鏍¢獙
+ rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+ $column.javaField: [
+ { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+ ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+ }
+ };
+ },
+ created() {
+ this.getList();
+ },
+ methods: {
+ /** 鏌ヨ${functionName}鍒楄〃 */
+ getList() {
+ this.loading = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ this.queryParams.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
+ this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
+ this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
+ }
+#end
+#end
+ list${BusinessName}(this.queryParams).then(response => {
+ this.${businessName}List = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+ this.loading = false;
+ });
+ },
+ /** 杞崲${functionName}鏁版嵁缁撴瀯 */
+ normalizer(node) {
+ if (node.children && !node.children.length) {
+ delete node.children;
+ }
+ return {
+ id: node.${treeCode},
+ label: node.${treeName},
+ children: node.children
+ };
+ },
+ /** 鏌ヨ${functionName}涓嬫媺鏍戠粨鏋� */
+ getTreeselect() {
+ list${BusinessName}().then(response => {
+ this.${businessName}Options = [];
+ const data = { ${treeCode}: 0, ${treeName}: '椤剁骇鑺傜偣', children: [] };
+ data.children = this.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+ this.${businessName}Options.push(data);
+ });
+ },
+ // 鍙栨秷鎸夐挳
+ cancel() {
+ this.open = false;
+ this.reset();
+ },
+ // 琛ㄥ崟閲嶇疆
+ reset() {
+ this.form = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ };
+ this.resetForm("form");
+ },
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ handleQuery() {
+ this.getList();
+ },
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ this.daterange${AttrName} = [];
+#end
+#end
+ this.resetForm("queryForm");
+ this.handleQuery();
+ },
+ /** 鏂板鎸夐挳鎿嶄綔 */
+ handleAdd(row) {
+ this.reset();
+ this.getTreeselect();
+ if (row != null && row.${treeCode}) {
+ this.form.${treeParentCode} = row.${treeCode};
+ } else {
+ this.form.${treeParentCode} = 0;
+ }
+ this.open = true;
+ this.title = "娣诲姞${functionName}";
+ },
+ /** 灞曞紑/鎶樺彔鎿嶄綔 */
+ toggleExpandAll() {
+ this.refreshTable = false;
+ this.isExpandAll = !this.isExpandAll;
+ this.$nextTick(() => {
+ this.refreshTable = true;
+ });
+ },
+ /** 淇敼鎸夐挳鎿嶄綔 */
+ handleUpdate(row) {
+ this.reset();
+ this.getTreeselect();
+ if (row != null) {
+ this.form.${treeParentCode} = row.${treeParentCode};
+ }
+ get${BusinessName}(row.${pkColumn.javaField}).then(response => {
+ this.form = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ this.form.$column.javaField = this.form.${column.javaField}.split(",");
+#end
+#end
+ this.open = true;
+ this.title = "淇敼${functionName}";
+ });
+ },
+ /** 鎻愪氦鎸夐挳 */
+ submitForm() {
+ this.#[[$]]#refs["form"].validate(valid => {
+ if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ this.form.$column.javaField = this.form.${column.javaField}.join(",");
+#end
+#end
+ if (this.form.${pkColumn.javaField} != null) {
+ update${BusinessName}(this.form).then(response => {
+ this.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ } else {
+ add${BusinessName}(this.form).then(response => {
+ this.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ }
+ }
+ });
+ },
+ /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+ handleDelete(row) {
+ this.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + row.${pkColumn.javaField} + '"鐨勬暟鎹」锛�').then(function() {
+ return del${BusinessName}(row.${pkColumn.javaField});
+ }).then(() => {
+ this.getList();
+ this.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+ }).catch(() => {});
+ }
+ }
+};
+</script>
diff --git a/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
new file mode 100644
index 0000000..6296014
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/vue/index.vue.vm
@@ -0,0 +1,602 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryForm" size="small" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-input
+ v-model="queryParams.${column.javaField}"
+ placeholder="璇疯緭鍏�${comment}"
+ clearable
+ @keyup.enter.native="handleQuery"
+ />
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-date-picker clearable
+ v-model="queryParams.${column.javaField}"
+ type="date"
+ value-format="yyyy-MM-dd"
+ placeholder="璇烽�夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ <el-form-item label="${comment}">
+ <el-date-picker
+ v-model="daterange${AttrName}"
+ style="width: 240px"
+ value-format="yyyy-MM-dd"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ </el-form-item>
+#end
+#end
+#end
+ <el-form-item>
+ <el-button type="primary" icon="el-icon-search" size="mini" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="el-icon-plus"
+ size="mini"
+ @click="handleAdd"
+ v-hasPermi="['${moduleName}:${businessName}:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="success"
+ plain
+ icon="el-icon-edit"
+ size="mini"
+ :disabled="single"
+ @click="handleUpdate"
+ v-hasPermi="['${moduleName}:${businessName}:edit']"
+ >淇敼</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="danger"
+ plain
+ icon="el-icon-delete"
+ size="mini"
+ :disabled="multiple"
+ @click="handleDelete"
+ v-hasPermi="['${moduleName}:${businessName}:remove']"
+ >鍒犻櫎</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="warning"
+ plain
+ icon="el-icon-download"
+ size="mini"
+ @click="handleExport"
+ v-hasPermi="['${moduleName}:${businessName}:export']"
+ >瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+ <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#elseif($column.list && $column.htmlType == "datetime")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+ <template slot-scope="scope">
+ <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+#elseif($column.list && $column.htmlType == "imageUpload")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+ <template slot-scope="scope">
+ <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $column.dictType)
+ <el-table-column label="${comment}" align="center" prop="${javaField}">
+ <template slot-scope="scope">
+#if($column.htmlType == "checkbox")
+ <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+ <dict-tag :options="dict.type.${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $javaField)
+ <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template slot-scope="scope">
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-edit"
+ @click="handleUpdate(scope.row)"
+ v-hasPermi="['${moduleName}:${businessName}:edit']"
+ >淇敼</el-button>
+ <el-button
+ size="mini"
+ type="text"
+ icon="el-icon-delete"
+ @click="handleDelete(scope.row)"
+ v-hasPermi="['${moduleName}:${businessName}:remove']"
+ >鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ :page.sync="queryParams.pageNum"
+ :limit.sync="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+ <el-dialog :title="title" :visible.sync="open" width="500px" append-to-body>
+ <el-form ref="form" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+ </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <image-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <file-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "editor")
+ <el-form-item label="${comment}">
+ <editor v-model="form.${field}" :min-height="192"/>
+ </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :value="parseInt(dict.value)"
+#else
+ :value="dict.value"
+#end
+ ></el-option>
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+ :label="dict.value">
+ {{dict.label}}
+ </el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio
+ v-for="dict in dict.type.${dictType}"
+ :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :label="parseInt(dict.value)"
+#else
+ :label="dict.value"
+#end
+ >{{dict.label}}</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "datetime")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-date-picker clearable
+ v-model="form.${field}"
+ type="date"
+ value-format="yyyy-MM-dd"
+ placeholder="璇烽�夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "textarea")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+ </el-form-item>
+#end
+#end
+#end
+#end
+#if($table.sub)
+ <el-divider content-position="center">${subTable.functionName}淇℃伅</el-divider>
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd${subClassName}">娣诲姞</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button type="danger" icon="el-icon-delete" size="mini" @click="handleDelete${subClassName}">鍒犻櫎</el-button>
+ </el-col>
+ </el-row>
+ <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
+ <el-table-column type="selection" width="50" align="center" />
+ <el-table-column label="搴忓彿" align="center" prop="index" width="50"/>
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk || $javaField == ${subTableFkclassName})
+#elseif($column.list && $column.htmlType == "input")
+ <el-table-column label="$comment" prop="${javaField}" width="150">
+ <template slot-scope="scope">
+ <el-input v-model="scope.row.$javaField" placeholder="璇疯緭鍏�$comment" />
+ </template>
+ </el-table-column>
+#elseif($column.list && $column.htmlType == "datetime")
+ <el-table-column label="$comment" prop="${javaField}" width="240">
+ <template slot-scope="scope">
+ <el-date-picker clearable v-model="scope.row.$javaField" type="date" value-format="yyyy-MM-dd" placeholder="璇烽�夋嫨$comment" />
+ </template>
+ </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
+ <el-table-column label="$comment" prop="${javaField}" width="150">
+ <template slot-scope="scope">
+ <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+ <el-option
+ v-for="dict in dict.type.$column.dictType"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ ></el-option>
+ </el-select>
+ </template>
+ </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
+ <el-table-column label="$comment" prop="${javaField}" width="150">
+ <template slot-scope="scope">
+ <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </template>
+ </el-table-column>
+#end
+#end
+ </el-table>
+#end
+ </el-form>
+ <div slot="footer" class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+ <el-button @click="cancel">鍙� 娑�</el-button>
+ </div>
+ </el-dialog>
+ </div>
+</template>
+
+<script>
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+export default {
+ name: "${BusinessName}",
+#if(${dicts} != '')
+ dicts: [${dicts}],
+#end
+ data() {
+ return {
+ // 閬僵灞�
+ loading: true,
+ // 閫変腑鏁扮粍
+ ids: [],
+#if($table.sub)
+ // 瀛愯〃閫変腑鏁版嵁
+ checked${subClassName}: [],
+#end
+ // 闈炲崟涓鐢�
+ single: true,
+ // 闈炲涓鐢�
+ multiple: true,
+ // 鏄剧ず鎼滅储鏉′欢
+ showSearch: true,
+ // 鎬绘潯鏁�
+ total: 0,
+ // ${functionName}琛ㄦ牸鏁版嵁
+ ${businessName}List: [],
+#if($table.sub)
+ // ${subTable.functionName}琛ㄦ牸鏁版嵁
+ ${subclassName}List: [],
+#end
+ // 寮瑰嚭灞傛爣棰�
+ title: "",
+ // 鏄惁鏄剧ず寮瑰嚭灞�
+ open: false,
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ // $comment鏃堕棿鑼冨洿
+ daterange${AttrName}: [],
+#end
+#end
+ // 鏌ヨ鍙傛暟
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+#foreach ($column in $columns)
+#if($column.query)
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ },
+ // 琛ㄥ崟鍙傛暟
+ form: {},
+ // 琛ㄥ崟鏍¢獙
+ rules: {
+#foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+ $column.javaField: [
+ { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+ ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+ }
+ };
+ },
+ created() {
+ this.getList();
+ },
+ methods: {
+ /** 鏌ヨ${functionName}鍒楄〃 */
+ getList() {
+ this.loading = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ this.queryParams.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ if (null != this.daterange${AttrName} && '' != this.daterange${AttrName}) {
+ this.queryParams.params["begin${AttrName}"] = this.daterange${AttrName}[0];
+ this.queryParams.params["end${AttrName}"] = this.daterange${AttrName}[1];
+ }
+#end
+#end
+ list${BusinessName}(this.queryParams).then(response => {
+ this.${businessName}List = response.rows;
+ this.total = response.total;
+ this.loading = false;
+ });
+ },
+ // 鍙栨秷鎸夐挳
+ cancel() {
+ this.open = false;
+ this.reset();
+ },
+ // 琛ㄥ崟閲嶇疆
+ reset() {
+ this.form = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ };
+#if($table.sub)
+ this.${subclassName}List = [];
+#end
+ this.resetForm("form");
+ },
+ /** 鎼滅储鎸夐挳鎿嶄綔 */
+ handleQuery() {
+ this.queryParams.pageNum = 1;
+ this.getList();
+ },
+ /** 閲嶇疆鎸夐挳鎿嶄綔 */
+ resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ this.daterange${AttrName} = [];
+#end
+#end
+ this.resetForm("queryForm");
+ this.handleQuery();
+ },
+ // 澶氶�夋閫変腑鏁版嵁
+ handleSelectionChange(selection) {
+ this.ids = selection.map(item => item.${pkColumn.javaField})
+ this.single = selection.length!==1
+ this.multiple = !selection.length
+ },
+ /** 鏂板鎸夐挳鎿嶄綔 */
+ handleAdd() {
+ this.reset();
+ this.open = true;
+ this.title = "娣诲姞${functionName}";
+ },
+ /** 淇敼鎸夐挳鎿嶄綔 */
+ handleUpdate(row) {
+ this.reset();
+ const ${pkColumn.javaField} = row.${pkColumn.javaField} || this.ids
+ get${BusinessName}(${pkColumn.javaField}).then(response => {
+ this.form = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ this.form.$column.javaField = this.form.${column.javaField}.split(",");
+#end
+#end
+#if($table.sub)
+ this.${subclassName}List = response.data.${subclassName}List;
+#end
+ this.open = true;
+ this.title = "淇敼${functionName}";
+ });
+ },
+ /** 鎻愪氦鎸夐挳 */
+ submitForm() {
+ this.#[[$]]#refs["form"].validate(valid => {
+ if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ this.form.$column.javaField = this.form.${column.javaField}.join(",");
+#end
+#end
+#if($table.sub)
+ this.form.${subclassName}List = this.${subclassName}List;
+#end
+ if (this.form.${pkColumn.javaField} != null) {
+ update${BusinessName}(this.form).then(response => {
+ this.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ } else {
+ add${BusinessName}(this.form).then(response => {
+ this.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+ this.open = false;
+ this.getList();
+ });
+ }
+ }
+ });
+ },
+ /** 鍒犻櫎鎸夐挳鎿嶄綔 */
+ handleDelete(row) {
+ const ${pkColumn.javaField}s = row.${pkColumn.javaField} || this.ids;
+ this.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + ${pkColumn.javaField}s + '"鐨勬暟鎹」锛�').then(function() {
+ return del${BusinessName}(${pkColumn.javaField}s);
+ }).then(() => {
+ this.getList();
+ this.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+ }).catch(() => {});
+ },
+#if($table.sub)
+ /** ${subTable.functionName}搴忓彿 */
+ row${subClassName}Index({ row, rowIndex }) {
+ row.index = rowIndex + 1;
+ },
+ /** ${subTable.functionName}娣诲姞鎸夐挳鎿嶄綔 */
+ handleAdd${subClassName}() {
+ let obj = {};
+#foreach($column in $subTable.columns)
+#if($column.pk || $column.javaField == ${subTableFkclassName})
+#elseif($column.list && "" != $javaField)
+ obj.$column.javaField = "";
+#end
+#end
+ this.${subclassName}List.push(obj);
+ },
+ /** ${subTable.functionName}鍒犻櫎鎸夐挳鎿嶄綔 */
+ handleDelete${subClassName}() {
+ if (this.checked${subClassName}.length == 0) {
+ this.#[[$modal]]#.msgError("璇峰厛閫夋嫨瑕佸垹闄ょ殑${subTable.functionName}鏁版嵁");
+ } else {
+ const ${subclassName}List = this.${subclassName}List;
+ const checked${subClassName} = this.checked${subClassName};
+ this.${subclassName}List = ${subclassName}List.filter(function(item) {
+ return checked${subClassName}.indexOf(item.index) == -1
+ });
+ }
+ },
+ /** 澶嶉�夋閫変腑鏁版嵁 */
+ handle${subClassName}SelectionChange(selection) {
+ this.checked${subClassName} = selection.map(item => item.index)
+ },
+#end
+ /** 瀵煎嚭鎸夐挳鎿嶄綔 */
+ handleExport() {
+ this.download('${moduleName}/${businessName}/export', {
+ ...this.queryParams
+ }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
+ }
+ }
+};
+</script>
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
new file mode 100644
index 0000000..c54d62b
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index-tree.vue.vm
@@ -0,0 +1,474 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-input
+ v-model="queryParams.${column.javaField}"
+ placeholder="璇疯緭鍏�${comment}"
+ clearable
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-date-picker clearable
+ v-model="queryParams.${column.javaField}"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ <el-form-item label="${comment}" style="width: 308px">
+ <el-date-picker
+ v-model="daterange${AttrName}"
+ value-format="YYYY-MM-DD"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ </el-form-item>
+#end
+#end
+#end
+ <el-form-item>
+ <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="handleAdd"
+ v-hasPermi="['${moduleName}:${businessName}:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="info"
+ plain
+ icon="Sort"
+ @click="toggleExpandAll"
+ >灞曞紑/鎶樺彔</el-button>
+ </el-col>
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table
+ v-if="refreshTable"
+ v-loading="loading"
+ :data="${businessName}List"
+ row-key="${treeCode}"
+ :default-expand-all="isExpandAll"
+ :tree-props="{children: 'children', hasChildren: 'hasChildren'}"
+ >
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+#elseif($column.list && $column.htmlType == "datetime")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+#elseif($column.list && $column.htmlType == "imageUpload")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+ <template #default="scope">
+ <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $column.dictType)
+ <el-table-column label="${comment}" align="center" prop="${javaField}">
+ <template #default="scope">
+#if($column.htmlType == "checkbox")
+ <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+ <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $javaField)
+#if(${foreach.index} == 1)
+ <el-table-column label="${comment}" prop="${javaField}" />
+#else
+ <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+#end
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template #default="scope">
+ <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">淇敼</el-button>
+ <el-button link type="primary" icon="Plus" @click="handleAdd(scope.row)" v-hasPermi="['${moduleName}:${businessName}:add']">鏂板</el-button>
+ <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+ <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+ <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if("" != $treeParentCode && $column.javaField == $treeParentCode)
+ <el-form-item label="${comment}" prop="${treeParentCode}">
+ <el-tree-select
+ v-model="form.${treeParentCode}"
+ :data="${businessName}Options"
+ :props="{ value: '${treeCode}', label: '${treeName}', children: 'children' }"
+ value-key="${treeCode}"
+ placeholder="璇烽�夋嫨${comment}"
+ check-strictly
+ />
+ </el-form-item>
+#elseif($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+ </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <image-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <file-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "editor")
+ <el-form-item label="${comment}">
+ <editor v-model="form.${field}" :min-height="192"/>
+ </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :value="parseInt(dict.value)"
+#else
+ :value="dict.value"
+#end
+ ></el-option>
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+ :label="dict.value">
+ {{dict.label}}
+ </el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :label="parseInt(dict.value)"
+#else
+ :label="dict.value"
+#end
+ >{{dict.label}}</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "datetime")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-date-picker clearable
+ v-model="form.${field}"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="閫夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "textarea")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+ </el-form-item>
+#end
+#end
+#end
+#end
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+ <el-button @click="cancel">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup name="${BusinessName}">
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+const { proxy } = getCurrentInstance();
+#if(${dicts} != '')
+#set($dictsNoSymbol=$dicts.replace("'", ""))
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
+#end
+
+const ${businessName}List = ref([]);
+const ${businessName}Options = ref([]);
+const open = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const title = ref("");
+const isExpandAll = ref(true);
+const refreshTable = ref(true);
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+const daterange${AttrName} = ref([]);
+#end
+#end
+
+const data = reactive({
+ form: {},
+ queryParams: {
+ #foreach ($column in $columns)
+#if($column.query)
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ },
+ rules: {
+ #foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+ $column.javaField: [
+ { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+ ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+ }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 鏌ヨ${functionName}鍒楄〃 */
+function getList() {
+ loading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ queryParams.value.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ if (null != daterange${AttrName} && '' != daterange${AttrName}) {
+ queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
+ queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
+ }
+#end
+#end
+ list${BusinessName}(queryParams.value).then(response => {
+ ${businessName}List.value = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+ loading.value = false;
+ });
+}
+
+/** 鏌ヨ${functionName}涓嬫媺鏍戠粨鏋� */
+function getTreeselect() {
+ list${BusinessName}().then(response => {
+ ${businessName}Options.value = [];
+ const data = { ${treeCode}: 0, ${treeName}: '椤剁骇鑺傜偣', children: [] };
+ data.children = proxy.handleTree(response.data, "${treeCode}", "${treeParentCode}");
+ ${businessName}Options.value.push(data);
+ });
+}
+
+// 鍙栨秷鎸夐挳
+function cancel() {
+ open.value = false;
+ reset();
+}
+
+// 琛ㄥ崟閲嶇疆
+function reset() {
+ form.value = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ };
+ proxy.resetForm("${businessName}Ref");
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+ getList();
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ daterange${AttrName}.value = [];
+#end
+#end
+ proxy.resetForm("queryRef");
+ handleQuery();
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd(row) {
+ reset();
+ getTreeselect();
+ if (row != null && row.${treeCode}) {
+ form.value.${treeParentCode} = row.${treeCode};
+ } else {
+ form.value.${treeParentCode} = 0;
+ }
+ open.value = true;
+ title.value = "娣诲姞${functionName}";
+}
+
+/** 灞曞紑/鎶樺彔鎿嶄綔 */
+function toggleExpandAll() {
+ refreshTable.value = false;
+ isExpandAll.value = !isExpandAll.value;
+ nextTick(() => {
+ refreshTable.value = true;
+ });
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+async function handleUpdate(row) {
+ reset();
+ await getTreeselect();
+ if (row != null) {
+ form.value.${treeParentCode} = row.${treeParentCode};
+ }
+ get${BusinessName}(row.${pkColumn.javaField}).then(response => {
+ form.value = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ form.value.$column.javaField = form.value.${column.javaField}.split(",");
+#end
+#end
+ open.value = true;
+ title.value = "淇敼${functionName}";
+ });
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+ proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
+ if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ form.value.$column.javaField = form.value.${column.javaField}.join(",");
+#end
+#end
+ if (form.value.${pkColumn.javaField} != null) {
+ update${BusinessName}(form.value).then(response => {
+ proxy.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+ open.value = false;
+ getList();
+ });
+ } else {
+ add${BusinessName}(form.value).then(response => {
+ proxy.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+ open.value = false;
+ getList();
+ });
+ }
+ }
+ });
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+ proxy.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + row.${pkColumn.javaField} + '"鐨勬暟鎹」锛�').then(function() {
+ return del${BusinessName}(row.${pkColumn.javaField});
+ }).then(() => {
+ getList();
+ proxy.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+ }).catch(() => {});
+}
+
+getList();
+</script>
diff --git a/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
new file mode 100644
index 0000000..8b25665
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/vue/v3/index.vue.vm
@@ -0,0 +1,590 @@
+<template>
+ <div class="app-container">
+ <el-form :model="queryParams" ref="queryRef" :inline="true" v-show="showSearch" label-width="68px">
+#foreach($column in $columns)
+#if($column.query)
+#set($dictType=$column.dictType)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-input
+ v-model="queryParams.${column.javaField}"
+ placeholder="璇疯緭鍏�${comment}"
+ clearable
+ @keyup.enter="handleQuery"
+ />
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && "" != $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ />
+ </el-select>
+ </el-form-item>
+#elseif(($column.htmlType == "select" || $column.htmlType == "radio") && $dictType)
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-select v-model="queryParams.${column.javaField}" placeholder="璇烽�夋嫨${comment}" clearable>
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType != "BETWEEN")
+ <el-form-item label="${comment}" prop="${column.javaField}">
+ <el-date-picker clearable
+ v-model="queryParams.${column.javaField}"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ <el-form-item label="${comment}" style="width: 308px">
+ <el-date-picker
+ v-model="daterange${AttrName}"
+ value-format="YYYY-MM-DD"
+ type="daterange"
+ range-separator="-"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ ></el-date-picker>
+ </el-form-item>
+#end
+#end
+#end
+ <el-form-item>
+ <el-button type="primary" icon="Search" @click="handleQuery">鎼滅储</el-button>
+ <el-button icon="Refresh" @click="resetQuery">閲嶇疆</el-button>
+ </el-form-item>
+ </el-form>
+
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button
+ type="primary"
+ plain
+ icon="Plus"
+ @click="handleAdd"
+ v-hasPermi="['${moduleName}:${businessName}:add']"
+ >鏂板</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="success"
+ plain
+ icon="Edit"
+ :disabled="single"
+ @click="handleUpdate"
+ v-hasPermi="['${moduleName}:${businessName}:edit']"
+ >淇敼</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="danger"
+ plain
+ icon="Delete"
+ :disabled="multiple"
+ @click="handleDelete"
+ v-hasPermi="['${moduleName}:${businessName}:remove']"
+ >鍒犻櫎</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button
+ type="warning"
+ plain
+ icon="Download"
+ @click="handleExport"
+ v-hasPermi="['${moduleName}:${businessName}:export']"
+ >瀵煎嚭</el-button>
+ </el-col>
+ <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
+ </el-row>
+
+ <el-table v-loading="loading" :data="${businessName}List" @selection-change="handleSelectionChange">
+ <el-table-column type="selection" width="55" align="center" />
+#foreach($column in $columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk)
+ <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#elseif($column.list && $column.htmlType == "datetime")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="180">
+ <template #default="scope">
+ <span>{{ parseTime(scope.row.${javaField}, '{y}-{m}-{d}') }}</span>
+ </template>
+ </el-table-column>
+#elseif($column.list && $column.htmlType == "imageUpload")
+ <el-table-column label="${comment}" align="center" prop="${javaField}" width="100">
+ <template #default="scope">
+ <image-preview :src="scope.row.${javaField}" :width="50" :height="50"/>
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $column.dictType)
+ <el-table-column label="${comment}" align="center" prop="${javaField}">
+ <template #default="scope">
+#if($column.htmlType == "checkbox")
+ <dict-tag :options="${column.dictType}" :value="scope.row.${javaField} ? scope.row.${javaField}.split(',') : []"/>
+#else
+ <dict-tag :options="${column.dictType}" :value="scope.row.${javaField}"/>
+#end
+ </template>
+ </el-table-column>
+#elseif($column.list && "" != $javaField)
+ <el-table-column label="${comment}" align="center" prop="${javaField}" />
+#end
+#end
+ <el-table-column label="鎿嶄綔" align="center" class-name="small-padding fixed-width">
+ <template #default="scope">
+ <el-button link type="primary" icon="Edit" @click="handleUpdate(scope.row)" v-hasPermi="['${moduleName}:${businessName}:edit']">淇敼</el-button>
+ <el-button link type="primary" icon="Delete" @click="handleDelete(scope.row)" v-hasPermi="['${moduleName}:${businessName}:remove']">鍒犻櫎</el-button>
+ </template>
+ </el-table-column>
+ </el-table>
+
+ <pagination
+ v-show="total>0"
+ :total="total"
+ v-model:page="queryParams.pageNum"
+ v-model:limit="queryParams.pageSize"
+ @pagination="getList"
+ />
+
+ <!-- 娣诲姞鎴栦慨鏀�${functionName}瀵硅瘽妗� -->
+ <el-dialog :title="title" v-model="open" width="500px" append-to-body>
+ <el-form ref="${businessName}Ref" :model="form" :rules="rules" label-width="80px">
+#foreach($column in $columns)
+#set($field=$column.javaField)
+#if($column.insert && !$column.pk)
+#if(($column.usableColumn) || (!$column.superColumn))
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#set($dictType=$column.dictType)
+#if($column.htmlType == "input")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" placeholder="璇疯緭鍏�${comment}" />
+ </el-form-item>
+#elseif($column.htmlType == "imageUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <image-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "fileUpload")
+ <el-form-item label="${comment}" prop="${field}">
+ <file-upload v-model="form.${field}"/>
+ </el-form-item>
+#elseif($column.htmlType == "editor")
+ <el-form-item label="${comment}">
+ <editor v-model="form.${field}" :min-height="192"/>
+ </el-form-item>
+#elseif($column.htmlType == "select" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+ :label="dict.label"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :value="parseInt(dict.value)"
+#else
+ :value="dict.value"
+#end
+ ></el-option>
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "select" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-select v-model="form.${field}" placeholder="璇烽�夋嫨${comment}">
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+ :label="dict.value">
+ {{dict.label}}
+ </el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "checkbox" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-checkbox-group v-model="form.${field}">
+ <el-checkbox>璇烽�夋嫨瀛楀吀鐢熸垚</el-checkbox>
+ </el-checkbox-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && "" != $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio
+ v-for="dict in ${dictType}"
+ :key="dict.value"
+#if($column.javaType == "Integer" || $column.javaType == "Long")
+ :label="parseInt(dict.value)"
+#else
+ :label="dict.value"
+#end
+ >{{dict.label}}</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "radio" && $dictType)
+ <el-form-item label="${comment}" prop="${field}">
+ <el-radio-group v-model="form.${field}">
+ <el-radio label="1">璇烽�夋嫨瀛楀吀鐢熸垚</el-radio>
+ </el-radio-group>
+ </el-form-item>
+#elseif($column.htmlType == "datetime")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-date-picker clearable
+ v-model="form.${field}"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨${comment}">
+ </el-date-picker>
+ </el-form-item>
+#elseif($column.htmlType == "textarea")
+ <el-form-item label="${comment}" prop="${field}">
+ <el-input v-model="form.${field}" type="textarea" placeholder="璇疯緭鍏ュ唴瀹�" />
+ </el-form-item>
+#end
+#end
+#end
+#end
+#if($table.sub)
+ <el-divider content-position="center">${subTable.functionName}淇℃伅</el-divider>
+ <el-row :gutter="10" class="mb8">
+ <el-col :span="1.5">
+ <el-button type="primary" icon="Plus" @click="handleAdd${subClassName}">娣诲姞</el-button>
+ </el-col>
+ <el-col :span="1.5">
+ <el-button type="danger" icon="Delete" @click="handleDelete${subClassName}">鍒犻櫎</el-button>
+ </el-col>
+ </el-row>
+ <el-table :data="${subclassName}List" :row-class-name="row${subClassName}Index" @selection-change="handle${subClassName}SelectionChange" ref="${subclassName}">
+ <el-table-column type="selection" width="50" align="center" />
+ <el-table-column label="搴忓彿" align="center" prop="index" width="50"/>
+#foreach($column in $subTable.columns)
+#set($javaField=$column.javaField)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+#if($column.pk || $javaField == ${subTableFkclassName})
+#elseif($column.list && $column.htmlType == "input")
+ <el-table-column label="$comment" prop="${javaField}" width="150">
+ <template #default="scope">
+ <el-input v-model="scope.row.$javaField" placeholder="璇疯緭鍏�$comment" />
+ </template>
+ </el-table-column>
+#elseif($column.list && $column.htmlType == "datetime")
+ <el-table-column label="$comment" prop="${javaField}" width="240">
+ <template #default="scope">
+ <el-date-picker clearable
+ v-model="scope.row.$javaField"
+ type="date"
+ value-format="YYYY-MM-DD"
+ placeholder="璇烽�夋嫨$comment">
+ </el-date-picker>
+ </template>
+ </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" != $column.dictType)
+ <el-table-column label="$comment" prop="${javaField}" width="150">
+ <template #default="scope">
+ <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+ <el-option
+ v-for="dict in $column.dictType"
+ :key="dict.value"
+ :label="dict.label"
+ :value="dict.value"
+ ></el-option>
+ </el-select>
+ </template>
+ </el-table-column>
+#elseif($column.list && ($column.htmlType == "select" || $column.htmlType == "radio") && "" == $column.dictType)
+ <el-table-column label="$comment" prop="${javaField}" width="150">
+ <template #default="scope">
+ <el-select v-model="scope.row.$javaField" placeholder="璇烽�夋嫨$comment">
+ <el-option label="璇烽�夋嫨瀛楀吀鐢熸垚" value="" />
+ </el-select>
+ </template>
+ </el-table-column>
+#end
+#end
+ </el-table>
+#end
+ </el-form>
+ <template #footer>
+ <div class="dialog-footer">
+ <el-button type="primary" @click="submitForm">纭� 瀹�</el-button>
+ <el-button @click="cancel">鍙� 娑�</el-button>
+ </div>
+ </template>
+ </el-dialog>
+ </div>
+</template>
+
+<script setup name="${BusinessName}">
+import { list${BusinessName}, get${BusinessName}, del${BusinessName}, add${BusinessName}, update${BusinessName} } from "@/api/${moduleName}/${businessName}";
+
+const { proxy } = getCurrentInstance();
+#if(${dicts} != '')
+#set($dictsNoSymbol=$dicts.replace("'", ""))
+const { ${dictsNoSymbol} } = proxy.useDict(${dicts});
+#end
+
+const ${businessName}List = ref([]);
+#if($table.sub)
+const ${subclassName}List = ref([]);
+#end
+const open = ref(false);
+const loading = ref(true);
+const showSearch = ref(true);
+const ids = ref([]);
+#if($table.sub)
+const checked${subClassName} = ref([]);
+#end
+const single = ref(true);
+const multiple = ref(true);
+const total = ref(0);
+const title = ref("");
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+const daterange${AttrName} = ref([]);
+#end
+#end
+
+const data = reactive({
+ form: {},
+ queryParams: {
+ pageNum: 1,
+ pageSize: 10,
+ #foreach ($column in $columns)
+#if($column.query)
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ },
+ rules: {
+ #foreach ($column in $columns)
+#if($column.required)
+#set($parentheseIndex=$column.columnComment.indexOf("锛�"))
+#if($parentheseIndex != -1)
+#set($comment=$column.columnComment.substring(0, $parentheseIndex))
+#else
+#set($comment=$column.columnComment)
+#end
+ $column.javaField: [
+ { required: true, message: "$comment涓嶈兘涓虹┖", trigger: #if($column.htmlType == "select" || $column.htmlType == "radio")"change"#else"blur"#end }
+ ]#if($foreach.count != $columns.size()),#end
+#end
+#end
+ }
+});
+
+const { queryParams, form, rules } = toRefs(data);
+
+/** 鏌ヨ${functionName}鍒楄〃 */
+function getList() {
+ loading.value = true;
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+ queryParams.value.params = {};
+#break
+#end
+#end
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ if (null != daterange${AttrName} && '' != daterange${AttrName}) {
+ queryParams.value.params["begin${AttrName}"] = daterange${AttrName}.value[0];
+ queryParams.value.params["end${AttrName}"] = daterange${AttrName}.value[1];
+ }
+#end
+#end
+ list${BusinessName}(queryParams.value).then(response => {
+ ${businessName}List.value = response.rows;
+ total.value = response.total;
+ loading.value = false;
+ });
+}
+
+// 鍙栨秷鎸夐挳
+function cancel() {
+ open.value = false;
+ reset();
+}
+
+// 琛ㄥ崟閲嶇疆
+function reset() {
+ form.value = {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ $column.javaField: []#if($foreach.count != $columns.size()),#end
+#else
+ $column.javaField: null#if($foreach.count != $columns.size()),#end
+#end
+#end
+ };
+#if($table.sub)
+ ${subclassName}List.value = [];
+#end
+ proxy.resetForm("${businessName}Ref");
+}
+
+/** 鎼滅储鎸夐挳鎿嶄綔 */
+function handleQuery() {
+ queryParams.value.pageNum = 1;
+ getList();
+}
+
+/** 閲嶇疆鎸夐挳鎿嶄綔 */
+function resetQuery() {
+#foreach ($column in $columns)
+#if($column.htmlType == "datetime" && $column.queryType == "BETWEEN")
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+ daterange${AttrName}.value = [];
+#end
+#end
+ proxy.resetForm("queryRef");
+ handleQuery();
+}
+
+// 澶氶�夋閫変腑鏁版嵁
+function handleSelectionChange(selection) {
+ ids.value = selection.map(item => item.${pkColumn.javaField});
+ single.value = selection.length != 1;
+ multiple.value = !selection.length;
+}
+
+/** 鏂板鎸夐挳鎿嶄綔 */
+function handleAdd() {
+ reset();
+ open.value = true;
+ title.value = "娣诲姞${functionName}";
+}
+
+/** 淇敼鎸夐挳鎿嶄綔 */
+function handleUpdate(row) {
+ reset();
+ const _${pkColumn.javaField} = row.${pkColumn.javaField} || ids.value
+ get${BusinessName}(_${pkColumn.javaField}).then(response => {
+ form.value = response.data;
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ form.value.$column.javaField = form.value.${column.javaField}.split(",");
+#end
+#end
+#if($table.sub)
+ ${subclassName}List.value = response.data.${subclassName}List;
+#end
+ open.value = true;
+ title.value = "淇敼${functionName}";
+ });
+}
+
+/** 鎻愪氦鎸夐挳 */
+function submitForm() {
+ proxy.#[[$]]#refs["${businessName}Ref"].validate(valid => {
+ if (valid) {
+#foreach ($column in $columns)
+#if($column.htmlType == "checkbox")
+ form.value.$column.javaField = form.value.${column.javaField}.join(",");
+#end
+#end
+#if($table.sub)
+ form.value.${subclassName}List = ${subclassName}List.value;
+#end
+ if (form.value.${pkColumn.javaField} != null) {
+ update${BusinessName}(form.value).then(response => {
+ proxy.#[[$modal]]#.msgSuccess("淇敼鎴愬姛");
+ open.value = false;
+ getList();
+ });
+ } else {
+ add${BusinessName}(form.value).then(response => {
+ proxy.#[[$modal]]#.msgSuccess("鏂板鎴愬姛");
+ open.value = false;
+ getList();
+ });
+ }
+ }
+ });
+}
+
+/** 鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete(row) {
+ const _${pkColumn.javaField}s = row.${pkColumn.javaField} || ids.value;
+ proxy.#[[$modal]]#.confirm('鏄惁纭鍒犻櫎${functionName}缂栧彿涓�"' + _${pkColumn.javaField}s + '"鐨勬暟鎹」锛�').then(function() {
+ return del${BusinessName}(_${pkColumn.javaField}s);
+ }).then(() => {
+ getList();
+ proxy.#[[$modal]]#.msgSuccess("鍒犻櫎鎴愬姛");
+ }).catch(() => {});
+}
+
+#if($table.sub)
+/** ${subTable.functionName}搴忓彿 */
+function row${subClassName}Index({ row, rowIndex }) {
+ row.index = rowIndex + 1;
+}
+
+/** ${subTable.functionName}娣诲姞鎸夐挳鎿嶄綔 */
+function handleAdd${subClassName}() {
+ let obj = {};
+#foreach($column in $subTable.columns)
+#if($column.pk || $column.javaField == ${subTableFkclassName})
+#elseif($column.list && "" != $javaField)
+ obj.$column.javaField = "";
+#end
+#end
+ ${subclassName}List.value.push(obj);
+}
+
+/** ${subTable.functionName}鍒犻櫎鎸夐挳鎿嶄綔 */
+function handleDelete${subClassName}() {
+ if (checked${subClassName}.value.length == 0) {
+ proxy.#[[$modal]]#.msgError("璇峰厛閫夋嫨瑕佸垹闄ょ殑${subTable.functionName}鏁版嵁");
+ } else {
+ const ${subclassName}s = ${subclassName}List.value;
+ const checked${subClassName}s = checked${subClassName}.value;
+ ${subclassName}List.value = ${subclassName}s.filter(function(item) {
+ return checked${subClassName}s.indexOf(item.index) == -1
+ });
+ }
+}
+
+/** 澶嶉�夋閫変腑鏁版嵁 */
+function handle${subClassName}SelectionChange(selection) {
+ checked${subClassName}.value = selection.map(item => item.index)
+}
+
+#end
+/** 瀵煎嚭鎸夐挳鎿嶄綔 */
+function handleExport() {
+ proxy.download('${moduleName}/${businessName}/export', {
+ ...queryParams.value
+ }, `${businessName}_#[[${new Date().getTime()}]]#.xlsx`)
+}
+
+getList();
+</script>
diff --git a/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
new file mode 100644
index 0000000..456755b
--- /dev/null
+++ b/ruoyi-generator/src/main/resources/vm/xml/mapper.xml.vm
@@ -0,0 +1,140 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="${packageName}.mapper.${ClassName}Mapper">
+
+ <resultMap type="${ClassName}" id="${ClassName}Result">
+#foreach ($column in $columns)
+ <result property="${column.javaField}" column="${column.columnName}" />
+#end
+ </resultMap>
+#if($table.sub)
+
+ <resultMap id="${ClassName}${subClassName}Result" type="${ClassName}" extends="${ClassName}Result">
+ <collection property="${subclassName}List" ofType="${subClassName}" column="${pkColumn.columnName}" select="select${subClassName}List" />
+ </resultMap>
+
+ <resultMap type="${subClassName}" id="${subClassName}Result">
+#foreach ($column in $subTable.columns)
+ <result property="${column.javaField}" column="${column.columnName}" />
+#end
+ </resultMap>
+#end
+
+ <sql id="select${ClassName}Vo">
+ select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end from ${tableName}
+ </sql>
+
+ <select id="select${ClassName}List" parameterType="${ClassName}" resultMap="${ClassName}Result">
+ <include refid="select${ClassName}Vo"/>
+ <where>
+#foreach($column in $columns)
+#set($queryType=$column.queryType)
+#set($javaField=$column.javaField)
+#set($javaType=$column.javaType)
+#set($columnName=$column.columnName)
+#set($AttrName=$column.javaField.substring(0,1).toUpperCase() + ${column.javaField.substring(1)})
+#if($column.query)
+#if($column.queryType == "EQ")
+ <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName = #{$javaField}</if>
+#elseif($queryType == "NE")
+ <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName != #{$javaField}</if>
+#elseif($queryType == "GT")
+ <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName > #{$javaField}</if>
+#elseif($queryType == "GTE")
+ <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName >= #{$javaField}</if>
+#elseif($queryType == "LT")
+ <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName < #{$javaField}</if>
+#elseif($queryType == "LTE")
+ <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName <= #{$javaField}</if>
+#elseif($queryType == "LIKE")
+ <if test="$javaField != null #if($javaType == 'String' ) and $javaField.trim() != ''#end"> and $columnName like concat('%', #{$javaField}, '%')</if>
+#elseif($queryType == "BETWEEN")
+ <if test="params.begin$AttrName != null and params.begin$AttrName != '' and params.end$AttrName != null and params.end$AttrName != ''"> and $columnName between #{params.begin$AttrName} and #{params.end$AttrName}</if>
+#end
+#end
+#end
+ </where>
+ </select>
+
+ <select id="select${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}" resultMap="#if($table.sub)${ClassName}${subClassName}Result#else${ClassName}Result#end">
+#if($table.crud || $table.tree)
+ <include refid="select${ClassName}Vo"/>
+ where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+#elseif($table.sub)
+ select#foreach($column in $columns) $column.columnName#if($foreach.count != $columns.size()),#end#end
+ from ${tableName}
+ where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+#end
+ </select>
+#if($table.sub)
+
+ <select id="select${subClassName}List" resultMap="${subClassName}Result">
+ select#foreach ($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end
+ from ${subTableName}
+ where ${subTableFkName} = #{${subTableFkName}}
+ </select>
+#end
+
+ <insert id="insert${ClassName}" parameterType="${ClassName}"#if($pkColumn.increment) useGeneratedKeys="true" keyProperty="$pkColumn.javaField"#end>
+ insert into ${tableName}
+ <trim prefix="(" suffix=")" suffixOverrides=",">
+#foreach($column in $columns)
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+ <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName,</if>
+#end
+#end
+ </trim>
+ <trim prefix="values (" suffix=")" suffixOverrides=",">
+#foreach($column in $columns)
+#if($column.columnName != $pkColumn.columnName || !$pkColumn.increment)
+ <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">#{$column.javaField},</if>
+#end
+#end
+ </trim>
+ </insert>
+
+ <update id="update${ClassName}" parameterType="${ClassName}">
+ update ${tableName}
+ <trim prefix="SET" suffixOverrides=",">
+#foreach($column in $columns)
+#if($column.columnName != $pkColumn.columnName)
+ <if test="$column.javaField != null#if($column.javaType == 'String' && $column.required) and $column.javaField != ''#end">$column.columnName = #{$column.javaField},</if>
+#end
+#end
+ </trim>
+ where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+ </update>
+
+ <delete id="delete${ClassName}By${pkColumn.capJavaField}" parameterType="${pkColumn.javaType}">
+ delete from ${tableName} where ${pkColumn.columnName} = #{${pkColumn.javaField}}
+ </delete>
+
+ <delete id="delete${ClassName}By${pkColumn.capJavaField}s" parameterType="String">
+ delete from ${tableName} where ${pkColumn.columnName} in
+ <foreach item="${pkColumn.javaField}" collection="array" open="(" separator="," close=")">
+ #{${pkColumn.javaField}}
+ </foreach>
+ </delete>
+#if($table.sub)
+
+ <delete id="delete${subClassName}By${subTableFkClassName}s" parameterType="String">
+ delete from ${subTableName} where ${subTableFkName} in
+ <foreach item="${subTableFkclassName}" collection="array" open="(" separator="," close=")">
+ #{${subTableFkclassName}}
+ </foreach>
+ </delete>
+
+ <delete id="delete${subClassName}By${subTableFkClassName}" parameterType="${pkColumn.javaType}">
+ delete from ${subTableName} where ${subTableFkName} = #{${subTableFkclassName}}
+ </delete>
+
+ <insert id="batch${subClassName}">
+ insert into ${subTableName}(#foreach($column in $subTable.columns) $column.columnName#if($foreach.count != $subTable.columns.size()),#end#end) values
+ <foreach item="item" index="index" collection="list" separator=",">
+ (#foreach($column in $subTable.columns) #{item.$column.javaField}#if($foreach.count != $subTable.columns.size()),#end#end)
+ </foreach>
+ </insert>
+#end
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-quartz/pom.xml b/ruoyi-quartz/pom.xml
new file mode 100644
index 0000000..0421087
--- /dev/null
+++ b/ruoyi-quartz/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>ruoyi-quartz</artifactId>
+
+ <description>
+ quartz瀹氭椂浠诲姟
+ </description>
+
+ <dependencies>
+
+ <!-- 瀹氭椂浠诲姟 -->
+ <dependency>
+ <groupId>org.quartz-scheduler</groupId>
+ <artifactId>quartz</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>com.mchange</groupId>
+ <artifactId>c3p0</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <!-- 閫氱敤宸ュ叿-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java
new file mode 100644
index 0000000..d4e065a
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/config/ScheduleConfig.java
@@ -0,0 +1,57 @@
+//package com.ruoyi.quartz.config;
+//
+//import org.springframework.context.annotation.Bean;
+//import org.springframework.context.annotation.Configuration;
+//import org.springframework.scheduling.quartz.SchedulerFactoryBean;
+//import javax.sql.DataSource;
+//import java.util.Properties;
+//
+///**
+// * 瀹氭椂浠诲姟閰嶇疆锛堝崟鏈洪儴缃插缓璁垹闄ゆ绫诲拰qrtz鏁版嵁搴撹〃锛岄粯璁よ蛋鍐呭瓨浼氭渶楂樻晥锛�
+// *
+// * @author ruoyi
+// */
+//@Configuration
+//public class ScheduleConfig
+//{
+// @Bean
+// public SchedulerFactoryBean schedulerFactoryBean(DataSource dataSource)
+// {
+// SchedulerFactoryBean factory = new SchedulerFactoryBean();
+// factory.setDataSource(dataSource);
+//
+// // quartz鍙傛暟
+// Properties prop = new Properties();
+// prop.put("org.quartz.scheduler.instanceName", "RuoyiScheduler");
+// prop.put("org.quartz.scheduler.instanceId", "AUTO");
+// // 绾跨▼姹犻厤缃�
+// prop.put("org.quartz.threadPool.class", "org.quartz.simpl.SimpleThreadPool");
+// prop.put("org.quartz.threadPool.threadCount", "20");
+// prop.put("org.quartz.threadPool.threadPriority", "5");
+// // JobStore閰嶇疆
+// prop.put("org.quartz.jobStore.class", "org.springframework.scheduling.quartz.LocalDataSourceJobStore");
+// // 闆嗙兢閰嶇疆
+// prop.put("org.quartz.jobStore.isClustered", "true");
+// prop.put("org.quartz.jobStore.clusterCheckinInterval", "15000");
+// prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "10");
+// prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
+//
+// // sqlserver 鍚敤
+// // prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS UPDLOCK WHERE LOCK_NAME = ?");
+// prop.put("org.quartz.jobStore.misfireThreshold", "12000");
+// prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
+// factory.setQuartzProperties(prop);
+//
+// factory.setSchedulerName("RuoyiScheduler");
+// // 寤舵椂鍚姩
+// factory.setStartupDelay(1);
+// factory.setApplicationContextSchedulerContextKey("applicationContextKey");
+// // 鍙�夛紝QuartzScheduler
+// // 鍚姩鏃舵洿鏂板繁瀛樺湪鐨凧ob锛岃繖鏍峰氨涓嶇敤姣忔淇敼targetObject鍚庡垹闄rtz_job_details琛ㄥ搴旇褰曚簡
+// factory.setOverwriteExistingJobs(true);
+// // 璁剧疆鑷姩鍚姩锛岄粯璁や负true
+// factory.setAutoStartup(true);
+//
+// return factory;
+// }
+//}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
new file mode 100644
index 0000000..4fd7aab
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobController.java
@@ -0,0 +1,185 @@
+package com.ruoyi.quartz.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.quartz.domain.SysJob;
+import com.ruoyi.quartz.service.ISysJobService;
+import com.ruoyi.quartz.util.CronUtils;
+import com.ruoyi.quartz.util.ScheduleUtils;
+
+/**
+ * 璋冨害浠诲姟淇℃伅鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/job")
+public class SysJobController extends BaseController
+{
+ @Autowired
+ private ISysJobService jobService;
+
+ /**
+ * 鏌ヨ瀹氭椂浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJob sysJob)
+ {
+ startPage();
+ List<SysJob> list = jobService.selectJobList(sysJob);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭瀹氭椂浠诲姟鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJob sysJob)
+ {
+ List<SysJob> list = jobService.selectJobList(sysJob);
+ ExcelUtil<SysJob> util = new ExcelUtil<SysJob>(SysJob.class);
+ util.exportExcel(response, list, "瀹氭椂浠诲姟");
+ }
+
+ /**
+ * 鑾峰彇瀹氭椂浠诲姟璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+ @GetMapping(value = "/{jobId}")
+ public AjaxResult getInfo(@PathVariable("jobId") Long jobId)
+ {
+ return success(jobService.selectJobById(jobId));
+ }
+
+ /**
+ * 鏂板瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:add')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("鏂板浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+ }
+ job.setCreateBy(getUsername());
+ return toAjax(jobService.insertJob(job));
+ }
+
+ /**
+ * 淇敼瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:edit')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody SysJob job) throws SchedulerException, TaskException
+ {
+ if (!CronUtils.isValid(job.getCronExpression()))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛孋ron琛ㄨ揪寮忎笉姝g‘");
+ }
+ else if (StringUtils.containsIgnoreCase(job.getInvokeTarget(), Constants.LOOKUP_RMI))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'rmi'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.LOOKUP_LDAP, Constants.LOOKUP_LDAPS }))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'ldap(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), new String[] { Constants.HTTP, Constants.HTTPS }))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅厑璁�'http(s)'璋冪敤");
+ }
+ else if (StringUtils.containsAnyIgnoreCase(job.getInvokeTarget(), Constants.JOB_ERROR_STR))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆瀛樺湪杩濊");
+ }
+ else if (!ScheduleUtils.whiteList(job.getInvokeTarget()))
+ {
+ return error("淇敼浠诲姟'" + job.getJobName() + "'澶辫触锛岀洰鏍囧瓧绗︿覆涓嶅湪鐧藉悕鍗曞唴");
+ }
+ job.setUpdateBy(getUsername());
+ return toAjax(jobService.updateJob(job));
+ }
+
+ /**
+ * 瀹氭椂浠诲姟鐘舵�佷慨鏀�
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping("/changeStatus")
+ public AjaxResult changeStatus(@RequestBody SysJob job) throws SchedulerException
+ {
+ SysJob newJob = jobService.selectJobById(job.getJobId());
+ newJob.setStatus(job.getStatus());
+ return toAjax(jobService.changeStatus(newJob));
+ }
+
+ /**
+ * 瀹氭椂浠诲姟绔嬪嵆鎵ц涓�娆�
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:changeStatus')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.UPDATE)
+ @PutMapping("/run")
+ public AjaxResult run(@RequestBody SysJob job) throws SchedulerException
+ {
+ boolean result = jobService.run(job);
+ return result ? success() : error("浠诲姟涓嶅瓨鍦ㄦ垨宸茶繃鏈燂紒");
+ }
+
+ /**
+ * 鍒犻櫎瀹氭椂浠诲姟
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "瀹氭椂浠诲姟", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobIds}")
+ public AjaxResult remove(@PathVariable Long[] jobIds) throws SchedulerException, TaskException
+ {
+ jobService.deleteJobByIds(jobIds);
+ return success();
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java
new file mode 100644
index 0000000..4f6bb63
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/controller/SysJobLogController.java
@@ -0,0 +1,92 @@
+package com.ruoyi.quartz.controller;
+
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.ruoyi.quartz.domain.SysJobLog;
+import com.ruoyi.quartz.service.ISysJobLogService;
+
+/**
+ * 璋冨害鏃ュ織鎿嶄綔澶勭悊
+ *
+ * @author ruoyi
+ */
+@RestController
+@RequestMapping("/monitor/jobLog")
+public class SysJobLogController extends BaseController
+{
+ @Autowired
+ private ISysJobLogService jobLogService;
+
+ /**
+ * 鏌ヨ瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(SysJobLog sysJobLog)
+ {
+ startPage();
+ List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+ return getDataTable(list);
+ }
+
+ /**
+ * 瀵煎嚭瀹氭椂浠诲姟璋冨害鏃ュ織鍒楄〃
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:export')")
+ @Log(title = "浠诲姟璋冨害鏃ュ織", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, SysJobLog sysJobLog)
+ {
+ List<SysJobLog> list = jobLogService.selectJobLogList(sysJobLog);
+ ExcelUtil<SysJobLog> util = new ExcelUtil<SysJobLog>(SysJobLog.class);
+ util.exportExcel(response, list, "璋冨害鏃ュ織");
+ }
+
+ /**
+ * 鏍规嵁璋冨害缂栧彿鑾峰彇璇︾粏淇℃伅
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:query')")
+ @GetMapping(value = "/{jobLogId}")
+ public AjaxResult getInfo(@PathVariable Long jobLogId)
+ {
+ return success(jobLogService.selectJobLogById(jobLogId));
+ }
+
+
+ /**
+ * 鍒犻櫎瀹氭椂浠诲姟璋冨害鏃ュ織
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "瀹氭椂浠诲姟璋冨害鏃ュ織", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{jobLogIds}")
+ public AjaxResult remove(@PathVariable Long[] jobLogIds)
+ {
+ return toAjax(jobLogService.deleteJobLogByIds(jobLogIds));
+ }
+
+ /**
+ * 娓呯┖瀹氭椂浠诲姟璋冨害鏃ュ織
+ */
+ @PreAuthorize("@ss.hasPermi('monitor:job:remove')")
+ @Log(title = "璋冨害鏃ュ織", businessType = BusinessType.CLEAN)
+ @DeleteMapping("/clean")
+ public AjaxResult clean()
+ {
+ jobLogService.cleanJobLog();
+ return success();
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java
new file mode 100644
index 0000000..1f49695
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJob.java
@@ -0,0 +1,171 @@
+package com.ruoyi.quartz.domain;
+
+import java.util.Date;
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.quartz.util.CronUtils;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害琛� sys_job
+ *
+ * @author ruoyi
+ */
+public class SysJob extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 浠诲姟ID */
+ @Excel(name = "浠诲姟搴忓彿", cellType = ColumnType.NUMERIC)
+ private Long jobId;
+
+ /** 浠诲姟鍚嶇О */
+ @Excel(name = "浠诲姟鍚嶇О")
+ private String jobName;
+
+ /** 浠诲姟缁勫悕 */
+ @Excel(name = "浠诲姟缁勫悕")
+ private String jobGroup;
+
+ /** 璋冪敤鐩爣瀛楃涓� */
+ @Excel(name = "璋冪敤鐩爣瀛楃涓�")
+ private String invokeTarget;
+
+ /** cron鎵ц琛ㄨ揪寮� */
+ @Excel(name = "鎵ц琛ㄨ揪寮� ")
+ private String cronExpression;
+
+ /** cron璁″垝绛栫暐 */
+ @Excel(name = "璁″垝绛栫暐 ", readConverterExp = "0=榛樿,1=绔嬪嵆瑙﹀彂鎵ц,2=瑙﹀彂涓�娆℃墽琛�,3=涓嶈Е鍙戠珛鍗虫墽琛�")
+ private String misfirePolicy = ScheduleConstants.MISFIRE_DEFAULT;
+
+ /** 鏄惁骞跺彂鎵ц锛�0鍏佽 1绂佹锛� */
+ @Excel(name = "骞跺彂鎵ц", readConverterExp = "0=鍏佽,1=绂佹")
+ private String concurrent;
+
+ /** 浠诲姟鐘舵�侊紙0姝e父 1鏆傚仠锛� */
+ @Excel(name = "浠诲姟鐘舵��", readConverterExp = "0=姝e父,1=鏆傚仠")
+ private String status;
+
+ public Long getJobId()
+ {
+ return jobId;
+ }
+
+ public void setJobId(Long jobId)
+ {
+ this.jobId = jobId;
+ }
+
+ @NotBlank(message = "浠诲姟鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 64, message = "浠诲姟鍚嶇О涓嶈兘瓒呰繃64涓瓧绗�")
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ @NotBlank(message = "璋冪敤鐩爣瀛楃涓蹭笉鑳戒负绌�")
+ @Size(min = 0, max = 500, message = "璋冪敤鐩爣瀛楃涓查暱搴︿笉鑳借秴杩�500涓瓧绗�")
+ public String getInvokeTarget()
+ {
+ return invokeTarget;
+ }
+
+ public void setInvokeTarget(String invokeTarget)
+ {
+ this.invokeTarget = invokeTarget;
+ }
+
+ @NotBlank(message = "Cron鎵ц琛ㄨ揪寮忎笉鑳戒负绌�")
+ @Size(min = 0, max = 255, message = "Cron鎵ц琛ㄨ揪寮忎笉鑳借秴杩�255涓瓧绗�")
+ public String getCronExpression()
+ {
+ return cronExpression;
+ }
+
+ public void setCronExpression(String cronExpression)
+ {
+ this.cronExpression = cronExpression;
+ }
+
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ public Date getNextValidTime()
+ {
+ if (StringUtils.isNotEmpty(cronExpression))
+ {
+ return CronUtils.getNextExecution(cronExpression);
+ }
+ return null;
+ }
+
+ public String getMisfirePolicy()
+ {
+ return misfirePolicy;
+ }
+
+ public void setMisfirePolicy(String misfirePolicy)
+ {
+ this.misfirePolicy = misfirePolicy;
+ }
+
+ public String getConcurrent()
+ {
+ return concurrent;
+ }
+
+ public void setConcurrent(String concurrent)
+ {
+ this.concurrent = concurrent;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("jobId", getJobId())
+ .append("jobName", getJobName())
+ .append("jobGroup", getJobGroup())
+ .append("cronExpression", getCronExpression())
+ .append("nextValidTime", getNextValidTime())
+ .append("misfirePolicy", getMisfirePolicy())
+ .append("concurrent", getConcurrent())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java
new file mode 100644
index 0000000..121c035
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/domain/SysJobLog.java
@@ -0,0 +1,155 @@
+package com.ruoyi.quartz.domain;
+
+import java.util.Date;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織琛� sys_job_log
+ *
+ * @author ruoyi
+ */
+public class SysJobLog extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** ID */
+ @Excel(name = "鏃ュ織搴忓彿")
+ private Long jobLogId;
+
+ /** 浠诲姟鍚嶇О */
+ @Excel(name = "浠诲姟鍚嶇О")
+ private String jobName;
+
+ /** 浠诲姟缁勫悕 */
+ @Excel(name = "浠诲姟缁勫悕")
+ private String jobGroup;
+
+ /** 璋冪敤鐩爣瀛楃涓� */
+ @Excel(name = "璋冪敤鐩爣瀛楃涓�")
+ private String invokeTarget;
+
+ /** 鏃ュ織淇℃伅 */
+ @Excel(name = "鏃ュ織淇℃伅")
+ private String jobMessage;
+
+ /** 鎵ц鐘舵�侊紙0姝e父 1澶辫触锛� */
+ @Excel(name = "鎵ц鐘舵��", readConverterExp = "0=姝e父,1=澶辫触")
+ private String status;
+
+ /** 寮傚父淇℃伅 */
+ @Excel(name = "寮傚父淇℃伅")
+ private String exceptionInfo;
+
+ /** 寮�濮嬫椂闂� */
+ private Date startTime;
+
+ /** 鍋滄鏃堕棿 */
+ private Date stopTime;
+
+ public Long getJobLogId()
+ {
+ return jobLogId;
+ }
+
+ public void setJobLogId(Long jobLogId)
+ {
+ this.jobLogId = jobLogId;
+ }
+
+ public String getJobName()
+ {
+ return jobName;
+ }
+
+ public void setJobName(String jobName)
+ {
+ this.jobName = jobName;
+ }
+
+ public String getJobGroup()
+ {
+ return jobGroup;
+ }
+
+ public void setJobGroup(String jobGroup)
+ {
+ this.jobGroup = jobGroup;
+ }
+
+ public String getInvokeTarget()
+ {
+ return invokeTarget;
+ }
+
+ public void setInvokeTarget(String invokeTarget)
+ {
+ this.invokeTarget = invokeTarget;
+ }
+
+ public String getJobMessage()
+ {
+ return jobMessage;
+ }
+
+ public void setJobMessage(String jobMessage)
+ {
+ this.jobMessage = jobMessage;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getExceptionInfo()
+ {
+ return exceptionInfo;
+ }
+
+ public void setExceptionInfo(String exceptionInfo)
+ {
+ this.exceptionInfo = exceptionInfo;
+ }
+
+ public Date getStartTime()
+ {
+ return startTime;
+ }
+
+ public void setStartTime(Date startTime)
+ {
+ this.startTime = startTime;
+ }
+
+ public Date getStopTime()
+ {
+ return stopTime;
+ }
+
+ public void setStopTime(Date stopTime)
+ {
+ this.stopTime = stopTime;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("jobLogId", getJobLogId())
+ .append("jobName", getJobName())
+ .append("jobGroup", getJobGroup())
+ .append("jobMessage", getJobMessage())
+ .append("status", getStatus())
+ .append("exceptionInfo", getExceptionInfo())
+ .append("startTime", getStartTime())
+ .append("stopTime", getStopTime())
+ .toString();
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java
new file mode 100644
index 0000000..727d916
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobLogMapper.java
@@ -0,0 +1,64 @@
+package com.ruoyi.quartz.mapper;
+
+import java.util.List;
+import com.ruoyi.quartz.domain.SysJobLog;
+
+/**
+ * 璋冨害浠诲姟鏃ュ織淇℃伅 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysJobLogMapper
+{
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+ */
+ public List<SysJobLog> selectJobLogList(SysJobLog jobLog);
+
+ /**
+ * 鏌ヨ鎵�鏈夎皟搴︿换鍔℃棩蹇�
+ *
+ * @return 璋冨害浠诲姟鏃ュ織鍒楄〃
+ */
+ public List<SysJobLog> selectJobLogAll();
+
+ /**
+ * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+ * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+ */
+ public SysJobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 鏂板浠诲姟鏃ュ織
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertJobLog(SysJobLog jobLog);
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+ *
+ * @param logIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogByIds(Long[] logIds);
+
+ /**
+ * 鍒犻櫎浠诲姟鏃ュ織
+ *
+ * @param jobId 璋冨害鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogById(Long jobId);
+
+ /**
+ * 娓呯┖浠诲姟鏃ュ織
+ */
+ public void cleanJobLog();
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java
new file mode 100644
index 0000000..20f45db
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/mapper/SysJobMapper.java
@@ -0,0 +1,67 @@
+package com.ruoyi.quartz.mapper;
+
+import java.util.List;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 璋冨害浠诲姟淇℃伅 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysJobMapper
+{
+ /**
+ * 鏌ヨ璋冨害浠诲姟鏃ュ織闆嗗悎
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 鎿嶄綔鏃ュ織闆嗗悎
+ */
+ public List<SysJob> selectJobList(SysJob job);
+
+ /**
+ * 鏌ヨ鎵�鏈夎皟搴︿换鍔�
+ *
+ * @return 璋冨害浠诲姟鍒楄〃
+ */
+ public List<SysJob> selectJobAll();
+
+ /**
+ * 閫氳繃璋冨害ID鏌ヨ璋冨害浠诲姟淇℃伅
+ *
+ * @param jobId 璋冨害ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ public SysJob selectJobById(Long jobId);
+
+ /**
+ * 閫氳繃璋冨害ID鍒犻櫎璋冨害浠诲姟淇℃伅
+ *
+ * @param jobId 璋冨害ID
+ * @return 缁撴灉
+ */
+ public int deleteJobById(Long jobId);
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害浠诲姟淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteJobByIds(Long[] ids);
+
+ /**
+ * 淇敼璋冨害浠诲姟淇℃伅
+ *
+ * @param job 璋冨害浠诲姟淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateJob(SysJob job);
+
+ /**
+ * 鏂板璋冨害浠诲姟淇℃伅
+ *
+ * @param job 璋冨害浠诲姟淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertJob(SysJob job);
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java
new file mode 100644
index 0000000..8546792
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobLogService.java
@@ -0,0 +1,56 @@
+package com.ruoyi.quartz.service;
+
+import java.util.List;
+import com.ruoyi.quartz.domain.SysJobLog;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織淇℃伅淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysJobLogService
+{
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+ */
+ public List<SysJobLog> selectJobLogList(SysJobLog jobLog);
+
+ /**
+ * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+ * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+ */
+ public SysJobLog selectJobLogById(Long jobLogId);
+
+ /**
+ * 鏂板浠诲姟鏃ュ織
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ */
+ public void addJobLog(SysJobLog jobLog);
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+ *
+ * @param logIds 闇�瑕佸垹闄ょ殑鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogByIds(Long[] logIds);
+
+ /**
+ * 鍒犻櫎浠诲姟鏃ュ織
+ *
+ * @param jobId 璋冨害鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteJobLogById(Long jobId);
+
+ /**
+ * 娓呯┖浠诲姟鏃ュ織
+ */
+ public void cleanJobLog();
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java
new file mode 100644
index 0000000..437ade8
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/ISysJobService.java
@@ -0,0 +1,102 @@
+package com.ruoyi.quartz.service;
+
+import java.util.List;
+import org.quartz.SchedulerException;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害淇℃伅淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysJobService
+{
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄧ殑璁″垝浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 璋冨害浠诲姟闆嗗悎
+ */
+ public List<SysJob> selectJobList(SysJob job);
+
+ /**
+ * 閫氳繃璋冨害浠诲姟ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobId 璋冨害浠诲姟ID
+ * @return 璋冨害浠诲姟瀵硅薄淇℃伅
+ */
+ public SysJob selectJobById(Long jobId);
+
+ /**
+ * 鏆傚仠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int pauseJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 鎭㈠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int resumeJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 鍒犻櫎浠诲姟鍚庯紝鎵�瀵瑰簲鐨則rigger涔熷皢琚垹闄�
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int deleteJob(SysJob job) throws SchedulerException;
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害淇℃伅
+ *
+ * @param jobIds 闇�瑕佸垹闄ょ殑浠诲姟ID
+ * @return 缁撴灉
+ */
+ public void deleteJobByIds(Long[] jobIds) throws SchedulerException;
+
+ /**
+ * 浠诲姟璋冨害鐘舵�佷慨鏀�
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int changeStatus(SysJob job) throws SchedulerException;
+
+ /**
+ * 绔嬪嵆杩愯浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean run(SysJob job) throws SchedulerException;
+
+ /**
+ * 鏂板浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertJob(SysJob job) throws SchedulerException, TaskException;
+
+ /**
+ * 鏇存柊浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateJob(SysJob job) throws SchedulerException, TaskException;
+
+ /**
+ * 鏍¢獙cron琛ㄨ揪寮忔槸鍚︽湁鏁�
+ *
+ * @param cronExpression 琛ㄨ揪寮�
+ * @return 缁撴灉
+ */
+ public boolean checkCronExpressionIsValid(String cronExpression);
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java
new file mode 100644
index 0000000..812eed7
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobLogServiceImpl.java
@@ -0,0 +1,87 @@
+package com.ruoyi.quartz.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.quartz.domain.SysJobLog;
+import com.ruoyi.quartz.mapper.SysJobLogMapper;
+import com.ruoyi.quartz.service.ISysJobLogService;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害鏃ュ織淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysJobLogServiceImpl implements ISysJobLogService
+{
+ @Autowired
+ private SysJobLogMapper jobLogMapper;
+
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄦ棩蹇楃殑璁″垝浠诲姟
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ * @return 璋冨害浠诲姟鏃ュ織闆嗗悎
+ */
+ @Override
+ public List<SysJobLog> selectJobLogList(SysJobLog jobLog)
+ {
+ return jobLogMapper.selectJobLogList(jobLog);
+ }
+
+ /**
+ * 閫氳繃璋冨害浠诲姟鏃ュ織ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobLogId 璋冨害浠诲姟鏃ュ織ID
+ * @return 璋冨害浠诲姟鏃ュ織瀵硅薄淇℃伅
+ */
+ @Override
+ public SysJobLog selectJobLogById(Long jobLogId)
+ {
+ return jobLogMapper.selectJobLogById(jobLogId);
+ }
+
+ /**
+ * 鏂板浠诲姟鏃ュ織
+ *
+ * @param jobLog 璋冨害鏃ュ織淇℃伅
+ */
+ @Override
+ public void addJobLog(SysJobLog jobLog)
+ {
+ jobLogMapper.insertJobLog(jobLog);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害鏃ュ織淇℃伅
+ *
+ * @param logIds 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteJobLogByIds(Long[] logIds)
+ {
+ return jobLogMapper.deleteJobLogByIds(logIds);
+ }
+
+ /**
+ * 鍒犻櫎浠诲姟鏃ュ織
+ *
+ * @param jobId 璋冨害鏃ュ織ID
+ */
+ @Override
+ public int deleteJobLogById(Long jobId)
+ {
+ return jobLogMapper.deleteJobLogById(jobId);
+ }
+
+ /**
+ * 娓呯┖浠诲姟鏃ュ織
+ */
+ @Override
+ public void cleanJobLog()
+ {
+ jobLogMapper.cleanJobLog();
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java
new file mode 100644
index 0000000..77fdbb5
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/service/impl/SysJobServiceImpl.java
@@ -0,0 +1,261 @@
+package com.ruoyi.quartz.service.impl;
+
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.quartz.JobDataMap;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.quartz.domain.SysJob;
+import com.ruoyi.quartz.mapper.SysJobMapper;
+import com.ruoyi.quartz.service.ISysJobService;
+import com.ruoyi.quartz.util.CronUtils;
+import com.ruoyi.quartz.util.ScheduleUtils;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysJobServiceImpl implements ISysJobService
+{
+ @Autowired
+ private Scheduler scheduler;
+
+ @Autowired
+ private SysJobMapper jobMapper;
+
+ /**
+ * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧畾鏃跺櫒 涓昏鏄槻姝㈡墜鍔ㄤ慨鏀规暟鎹簱瀵艰嚧鏈悓姝ュ埌瀹氭椂浠诲姟澶勭悊锛堟敞锛氫笉鑳芥墜鍔ㄤ慨鏀规暟鎹簱ID鍜屼换鍔$粍鍚嶏紝鍚﹀垯浼氬鑷磋剰鏁版嵁锛�
+ */
+ @PostConstruct
+ public void init() throws SchedulerException, TaskException
+ {
+ scheduler.clear();
+ List<SysJob> jobList = jobMapper.selectJobAll();
+ for (SysJob job : jobList)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ }
+
+ /**
+ * 鑾峰彇quartz璋冨害鍣ㄧ殑璁″垝浠诲姟鍒楄〃
+ *
+ * @param job 璋冨害淇℃伅
+ * @return
+ */
+ @Override
+ public List<SysJob> selectJobList(SysJob job)
+ {
+ return jobMapper.selectJobList(job);
+ }
+
+ /**
+ * 閫氳繃璋冨害浠诲姟ID鏌ヨ璋冨害淇℃伅
+ *
+ * @param jobId 璋冨害浠诲姟ID
+ * @return 璋冨害浠诲姟瀵硅薄淇℃伅
+ */
+ @Override
+ public SysJob selectJobById(Long jobId)
+ {
+ return jobMapper.selectJobById(jobId);
+ }
+
+ /**
+ * 鏆傚仠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int pauseJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 鎭㈠浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int resumeJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ scheduler.resumeJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 鍒犻櫎浠诲姟鍚庯紝鎵�瀵瑰簲鐨則rigger涔熷皢琚垹闄�
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int deleteJob(SysJob job) throws SchedulerException
+ {
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ int rows = jobMapper.deleteJobById(jobId);
+ if (rows > 0)
+ {
+ scheduler.deleteJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ return rows;
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎璋冨害淇℃伅
+ *
+ * @param jobIds 闇�瑕佸垹闄ょ殑浠诲姟ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void deleteJobByIds(Long[] jobIds) throws SchedulerException
+ {
+ for (Long jobId : jobIds)
+ {
+ SysJob job = jobMapper.selectJobById(jobId);
+ deleteJob(job);
+ }
+ }
+
+ /**
+ * 浠诲姟璋冨害鐘舵�佷慨鏀�
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int changeStatus(SysJob job) throws SchedulerException
+ {
+ int rows = 0;
+ String status = job.getStatus();
+ if (ScheduleConstants.Status.NORMAL.getValue().equals(status))
+ {
+ rows = resumeJob(job);
+ }
+ else if (ScheduleConstants.Status.PAUSE.getValue().equals(status))
+ {
+ rows = pauseJob(job);
+ }
+ return rows;
+ }
+
+ /**
+ * 绔嬪嵆杩愯浠诲姟
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public boolean run(SysJob job) throws SchedulerException
+ {
+ boolean result = false;
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ SysJob properties = selectJobById(job.getJobId());
+ // 鍙傛暟
+ JobDataMap dataMap = new JobDataMap();
+ dataMap.put(ScheduleConstants.TASK_PROPERTIES, properties);
+ JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+ if (scheduler.checkExists(jobKey))
+ {
+ result = true;
+ scheduler.triggerJob(jobKey, dataMap);
+ }
+ return result;
+ }
+
+ /**
+ * 鏂板浠诲姟
+ *
+ * @param job 璋冨害淇℃伅 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int insertJob(SysJob job) throws SchedulerException, TaskException
+ {
+ job.setStatus(ScheduleConstants.Status.PAUSE.getValue());
+ int rows = jobMapper.insertJob(job);
+ if (rows > 0)
+ {
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+ return rows;
+ }
+
+ /**
+ * 鏇存柊浠诲姟鐨勬椂闂磋〃杈惧紡
+ *
+ * @param job 璋冨害淇℃伅
+ */
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public int updateJob(SysJob job) throws SchedulerException, TaskException
+ {
+ SysJob properties = selectJobById(job.getJobId());
+ int rows = jobMapper.updateJob(job);
+ if (rows > 0)
+ {
+ updateSchedulerJob(job, properties.getJobGroup());
+ }
+ return rows;
+ }
+
+ /**
+ * 鏇存柊浠诲姟
+ *
+ * @param job 浠诲姟瀵硅薄
+ * @param jobGroup 浠诲姟缁勫悕
+ */
+ public void updateSchedulerJob(SysJob job, String jobGroup) throws SchedulerException, TaskException
+ {
+ Long jobId = job.getJobId();
+ // 鍒ゆ柇鏄惁瀛樺湪
+ JobKey jobKey = ScheduleUtils.getJobKey(jobId, jobGroup);
+ if (scheduler.checkExists(jobKey))
+ {
+ // 闃叉鍒涘缓鏃跺瓨鍦ㄦ暟鎹棶棰� 鍏堢Щ闄わ紝鐒跺悗鍦ㄦ墽琛屽垱寤烘搷浣�
+ scheduler.deleteJob(jobKey);
+ }
+ ScheduleUtils.createScheduleJob(scheduler, job);
+ }
+
+ /**
+ * 鏍¢獙cron琛ㄨ揪寮忔槸鍚︽湁鏁�
+ *
+ * @param cronExpression 琛ㄨ揪寮�
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkCronExpressionIsValid(String cronExpression)
+ {
+ return CronUtils.isValid(cronExpression);
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
new file mode 100644
index 0000000..853243b
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/task/RyTask.java
@@ -0,0 +1,28 @@
+package com.ruoyi.quartz.task;
+
+import org.springframework.stereotype.Component;
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 瀹氭椂浠诲姟璋冨害娴嬭瘯
+ *
+ * @author ruoyi
+ */
+@Component("ryTask")
+public class RyTask
+{
+ public void ryMultipleParams(String s, Boolean b, Long l, Double d, Integer i)
+ {
+ System.out.println(StringUtils.format("鎵ц澶氬弬鏂规硶锛� 瀛楃涓茬被鍨媨}锛屽竷灏旂被鍨媨}锛岄暱鏁村瀷{}锛屾诞鐐瑰瀷{}锛屾暣褰}", s, b, l, d, i));
+ }
+
+ public void ryParams(String params)
+ {
+ System.out.println("鎵ц鏈夊弬鏂规硶锛�" + params);
+ }
+
+ public void ryNoParams()
+ {
+ System.out.println("鎵ц鏃犲弬鏂规硶");
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java
new file mode 100644
index 0000000..731a5eb
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/AbstractQuartzJob.java
@@ -0,0 +1,107 @@
+package com.ruoyi.quartz.util;
+
+import java.util.Date;
+import org.quartz.Job;
+import org.quartz.JobExecutionContext;
+import org.quartz.JobExecutionException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.utils.ExceptionUtil;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.quartz.domain.SysJob;
+import com.ruoyi.quartz.domain.SysJobLog;
+import com.ruoyi.quartz.service.ISysJobLogService;
+
+/**
+ * 鎶借薄quartz璋冪敤
+ *
+ * @author ruoyi
+ */
+public abstract class AbstractQuartzJob implements Job
+{
+ private static final Logger log = LoggerFactory.getLogger(AbstractQuartzJob.class);
+
+ /**
+ * 绾跨▼鏈湴鍙橀噺
+ */
+ private static ThreadLocal<Date> threadLocal = new ThreadLocal<>();
+
+ @Override
+ public void execute(JobExecutionContext context) throws JobExecutionException
+ {
+ SysJob sysJob = new SysJob();
+ BeanUtils.copyBeanProp(sysJob, context.getMergedJobDataMap().get(ScheduleConstants.TASK_PROPERTIES));
+ try
+ {
+ before(context, sysJob);
+ if (sysJob != null)
+ {
+ doExecute(context, sysJob);
+ }
+ after(context, sysJob, null);
+ }
+ catch (Exception e)
+ {
+ log.error("浠诲姟鎵ц寮傚父 - 锛�", e);
+ after(context, sysJob, e);
+ }
+ }
+
+ /**
+ * 鎵ц鍓�
+ *
+ * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+ * @param sysJob 绯荤粺璁″垝浠诲姟
+ */
+ protected void before(JobExecutionContext context, SysJob sysJob)
+ {
+ threadLocal.set(new Date());
+ }
+
+ /**
+ * 鎵ц鍚�
+ *
+ * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+ * @param sysJob 绯荤粺璁″垝浠诲姟
+ */
+ protected void after(JobExecutionContext context, SysJob sysJob, Exception e)
+ {
+ Date startTime = threadLocal.get();
+ threadLocal.remove();
+
+ final SysJobLog sysJobLog = new SysJobLog();
+ sysJobLog.setJobName(sysJob.getJobName());
+ sysJobLog.setJobGroup(sysJob.getJobGroup());
+ sysJobLog.setInvokeTarget(sysJob.getInvokeTarget());
+ sysJobLog.setStartTime(startTime);
+ sysJobLog.setStopTime(new Date());
+ long runMs = sysJobLog.getStopTime().getTime() - sysJobLog.getStartTime().getTime();
+ sysJobLog.setJobMessage(sysJobLog.getJobName() + " 鎬诲叡鑰楁椂锛�" + runMs + "姣");
+ if (e != null)
+ {
+ sysJobLog.setStatus(Constants.FAIL);
+ String errorMsg = StringUtils.substring(ExceptionUtil.getExceptionMessage(e), 0, 2000);
+ sysJobLog.setExceptionInfo(errorMsg);
+ }
+ else
+ {
+ sysJobLog.setStatus(Constants.SUCCESS);
+ }
+
+ // 鍐欏叆鏁版嵁搴撳綋涓�
+ SpringUtils.getBean(ISysJobLogService.class).addJobLog(sysJobLog);
+ }
+
+ /**
+ * 鎵ц鏂规硶锛岀敱瀛愮被閲嶈浇
+ *
+ * @param context 宸ヤ綔鎵ц涓婁笅鏂囧璞�
+ * @param sysJob 绯荤粺璁″垝浠诲姟
+ * @throws Exception 鎵ц杩囩▼涓殑寮傚父
+ */
+ protected abstract void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception;
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java
new file mode 100644
index 0000000..dd53839
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/CronUtils.java
@@ -0,0 +1,63 @@
+package com.ruoyi.quartz.util;
+
+import java.text.ParseException;
+import java.util.Date;
+import org.quartz.CronExpression;
+
+/**
+ * cron琛ㄨ揪寮忓伐鍏风被
+ *
+ * @author ruoyi
+ *
+ */
+public class CronUtils
+{
+ /**
+ * 杩斿洖涓�涓竷灏斿�间唬琛ㄤ竴涓粰瀹氱殑Cron琛ㄨ揪寮忕殑鏈夋晥鎬�
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return boolean 琛ㄨ揪寮忔槸鍚︽湁鏁�
+ */
+ public static boolean isValid(String cronExpression)
+ {
+ return CronExpression.isValidExpression(cronExpression);
+ }
+
+ /**
+ * 杩斿洖涓�涓瓧绗︿覆鍊�,琛ㄧず璇ユ秷鎭棤鏁圕ron琛ㄨ揪寮忕粰鍑烘湁鏁堟��
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return String 鏃犳晥鏃惰繑鍥炶〃杈惧紡閿欒鎻忚堪,濡傛灉鏈夋晥杩斿洖null
+ */
+ public static String getInvalidMessage(String cronExpression)
+ {
+ try
+ {
+ new CronExpression(cronExpression);
+ return null;
+ }
+ catch (ParseException pe)
+ {
+ return pe.getMessage();
+ }
+ }
+
+ /**
+ * 杩斿洖涓嬩竴涓墽琛屾椂闂存牴鎹粰瀹氱殑Cron琛ㄨ揪寮�
+ *
+ * @param cronExpression Cron琛ㄨ揪寮�
+ * @return Date 涓嬫Cron琛ㄨ揪寮忔墽琛屾椂闂�
+ */
+ public static Date getNextExecution(String cronExpression)
+ {
+ try
+ {
+ CronExpression cron = new CronExpression(cronExpression);
+ return cron.getNextValidTimeAfter(new Date(System.currentTimeMillis()));
+ }
+ catch (ParseException e)
+ {
+ throw new IllegalArgumentException(e.getMessage());
+ }
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java
new file mode 100644
index 0000000..e3dc62c
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/JobInvokeUtil.java
@@ -0,0 +1,182 @@
+package com.ruoyi.quartz.util;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.LinkedList;
+import java.util.List;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 浠诲姟鎵ц宸ュ叿
+ *
+ * @author ruoyi
+ */
+public class JobInvokeUtil
+{
+ /**
+ * 鎵ц鏂规硶
+ *
+ * @param sysJob 绯荤粺浠诲姟
+ */
+ public static void invokeMethod(SysJob sysJob) throws Exception
+ {
+ String invokeTarget = sysJob.getInvokeTarget();
+ String beanName = getBeanName(invokeTarget);
+ String methodName = getMethodName(invokeTarget);
+ List<Object[]> methodParams = getMethodParams(invokeTarget);
+
+ if (!isValidClassName(beanName))
+ {
+ Object bean = SpringUtils.getBean(beanName);
+ invokeMethod(bean, methodName, methodParams);
+ }
+ else
+ {
+ Object bean = Class.forName(beanName).getDeclaredConstructor().newInstance();
+ invokeMethod(bean, methodName, methodParams);
+ }
+ }
+
+ /**
+ * 璋冪敤浠诲姟鏂规硶
+ *
+ * @param bean 鐩爣瀵硅薄
+ * @param methodName 鏂规硶鍚嶇О
+ * @param methodParams 鏂规硶鍙傛暟
+ */
+ private static void invokeMethod(Object bean, String methodName, List<Object[]> methodParams)
+ throws NoSuchMethodException, SecurityException, IllegalAccessException, IllegalArgumentException,
+ InvocationTargetException
+ {
+ if (StringUtils.isNotNull(methodParams) && methodParams.size() > 0)
+ {
+ Method method = bean.getClass().getMethod(methodName, getMethodParamsType(methodParams));
+ method.invoke(bean, getMethodParamsValue(methodParams));
+ }
+ else
+ {
+ Method method = bean.getClass().getMethod(methodName);
+ method.invoke(bean);
+ }
+ }
+
+ /**
+ * 鏍¢獙鏄惁涓轰负class鍖呭悕
+ *
+ * @param invokeTarget 鍚嶇О
+ * @return true鏄� false鍚�
+ */
+ public static boolean isValidClassName(String invokeTarget)
+ {
+ return StringUtils.countMatches(invokeTarget, ".") > 1;
+ }
+
+ /**
+ * 鑾峰彇bean鍚嶇О
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return bean鍚嶇О
+ */
+ public static String getBeanName(String invokeTarget)
+ {
+ String beanName = StringUtils.substringBefore(invokeTarget, "(");
+ return StringUtils.substringBeforeLast(beanName, ".");
+ }
+
+ /**
+ * 鑾峰彇bean鏂规硶
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return method鏂规硶
+ */
+ public static String getMethodName(String invokeTarget)
+ {
+ String methodName = StringUtils.substringBefore(invokeTarget, "(");
+ return StringUtils.substringAfterLast(methodName, ".");
+ }
+
+ /**
+ * 鑾峰彇method鏂规硶鍙傛暟鐩稿叧鍒楄〃
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return method鏂规硶鐩稿叧鍙傛暟鍒楄〃
+ */
+ public static List<Object[]> getMethodParams(String invokeTarget)
+ {
+ String methodStr = StringUtils.substringBetween(invokeTarget, "(", ")");
+ if (StringUtils.isEmpty(methodStr))
+ {
+ return null;
+ }
+ String[] methodParams = methodStr.split(",(?=([^\"']*[\"'][^\"']*[\"'])*[^\"']*$)");
+ List<Object[]> classs = new LinkedList<>();
+ for (int i = 0; i < methodParams.length; i++)
+ {
+ String str = StringUtils.trimToEmpty(methodParams[i]);
+ // String瀛楃涓茬被鍨嬶紝浠�'鎴�"寮�澶�
+ if (StringUtils.startsWithAny(str, "'", "\""))
+ {
+ classs.add(new Object[] { StringUtils.substring(str, 1, str.length() - 1), String.class });
+ }
+ // boolean甯冨皵绫诲瀷锛岀瓑浜巘rue鎴栬�協alse
+ else if ("true".equalsIgnoreCase(str) || "false".equalsIgnoreCase(str))
+ {
+ classs.add(new Object[] { Boolean.valueOf(str), Boolean.class });
+ }
+ // long闀挎暣褰紝浠缁撳熬
+ else if (StringUtils.endsWith(str, "L"))
+ {
+ classs.add(new Object[] { Long.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Long.class });
+ }
+ // double娴偣绫诲瀷锛屼互D缁撳熬
+ else if (StringUtils.endsWith(str, "D"))
+ {
+ classs.add(new Object[] { Double.valueOf(StringUtils.substring(str, 0, str.length() - 1)), Double.class });
+ }
+ // 鍏朵粬绫诲瀷褰掔被涓烘暣褰�
+ else
+ {
+ classs.add(new Object[] { Integer.valueOf(str), Integer.class });
+ }
+ }
+ return classs;
+ }
+
+ /**
+ * 鑾峰彇鍙傛暟绫诲瀷
+ *
+ * @param methodParams 鍙傛暟鐩稿叧鍒楄〃
+ * @return 鍙傛暟绫诲瀷鍒楄〃
+ */
+ public static Class<?>[] getMethodParamsType(List<Object[]> methodParams)
+ {
+ Class<?>[] classs = new Class<?>[methodParams.size()];
+ int index = 0;
+ for (Object[] os : methodParams)
+ {
+ classs[index] = (Class<?>) os[1];
+ index++;
+ }
+ return classs;
+ }
+
+ /**
+ * 鑾峰彇鍙傛暟鍊�
+ *
+ * @param methodParams 鍙傛暟鐩稿叧鍒楄〃
+ * @return 鍙傛暟鍊煎垪琛�
+ */
+ public static Object[] getMethodParamsValue(List<Object[]> methodParams)
+ {
+ Object[] classs = new Object[methodParams.size()];
+ int index = 0;
+ for (Object[] os : methodParams)
+ {
+ classs[index] = (Object) os[0];
+ index++;
+ }
+ return classs;
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java
new file mode 100644
index 0000000..5e13558
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzDisallowConcurrentExecution.java
@@ -0,0 +1,21 @@
+package com.ruoyi.quartz.util;
+
+import org.quartz.DisallowConcurrentExecution;
+import org.quartz.JobExecutionContext;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟澶勭悊锛堢姝㈠苟鍙戞墽琛岋級
+ *
+ * @author ruoyi
+ *
+ */
+@DisallowConcurrentExecution
+public class QuartzDisallowConcurrentExecution extends AbstractQuartzJob
+{
+ @Override
+ protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+ {
+ JobInvokeUtil.invokeMethod(sysJob);
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java
new file mode 100644
index 0000000..e975326
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/QuartzJobExecution.java
@@ -0,0 +1,19 @@
+package com.ruoyi.quartz.util;
+
+import org.quartz.JobExecutionContext;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟澶勭悊锛堝厑璁稿苟鍙戞墽琛岋級
+ *
+ * @author ruoyi
+ *
+ */
+public class QuartzJobExecution extends AbstractQuartzJob
+{
+ @Override
+ protected void doExecute(JobExecutionContext context, SysJob sysJob) throws Exception
+ {
+ JobInvokeUtil.invokeMethod(sysJob);
+ }
+}
diff --git a/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java
new file mode 100644
index 0000000..21fedae
--- /dev/null
+++ b/ruoyi-quartz/src/main/java/com/ruoyi/quartz/util/ScheduleUtils.java
@@ -0,0 +1,141 @@
+package com.ruoyi.quartz.util;
+
+import org.quartz.CronScheduleBuilder;
+import org.quartz.CronTrigger;
+import org.quartz.Job;
+import org.quartz.JobBuilder;
+import org.quartz.JobDetail;
+import org.quartz.JobKey;
+import org.quartz.Scheduler;
+import org.quartz.SchedulerException;
+import org.quartz.TriggerBuilder;
+import org.quartz.TriggerKey;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.ScheduleConstants;
+import com.ruoyi.common.exception.job.TaskException;
+import com.ruoyi.common.exception.job.TaskException.Code;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.quartz.domain.SysJob;
+
+/**
+ * 瀹氭椂浠诲姟宸ュ叿绫�
+ *
+ * @author ruoyi
+ *
+ */
+public class ScheduleUtils
+{
+ /**
+ * 寰楀埌quartz浠诲姟绫�
+ *
+ * @param sysJob 鎵ц璁″垝
+ * @return 鍏蜂綋鎵ц浠诲姟绫�
+ */
+ private static Class<? extends Job> getQuartzJobClass(SysJob sysJob)
+ {
+ boolean isConcurrent = "0".equals(sysJob.getConcurrent());
+ return isConcurrent ? QuartzJobExecution.class : QuartzDisallowConcurrentExecution.class;
+ }
+
+ /**
+ * 鏋勫缓浠诲姟瑙﹀彂瀵硅薄
+ */
+ public static TriggerKey getTriggerKey(Long jobId, String jobGroup)
+ {
+ return TriggerKey.triggerKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
+ }
+
+ /**
+ * 鏋勫缓浠诲姟閿璞�
+ */
+ public static JobKey getJobKey(Long jobId, String jobGroup)
+ {
+ return JobKey.jobKey(ScheduleConstants.TASK_CLASS_NAME + jobId, jobGroup);
+ }
+
+ /**
+ * 鍒涘缓瀹氭椂浠诲姟
+ */
+ public static void createScheduleJob(Scheduler scheduler, SysJob job) throws SchedulerException, TaskException
+ {
+ Class<? extends Job> jobClass = getQuartzJobClass(job);
+ // 鏋勫缓job淇℃伅
+ Long jobId = job.getJobId();
+ String jobGroup = job.getJobGroup();
+ JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(getJobKey(jobId, jobGroup)).build();
+
+ // 琛ㄨ揪寮忚皟搴︽瀯寤哄櫒
+ CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(job.getCronExpression());
+ cronScheduleBuilder = handleCronScheduleMisfirePolicy(job, cronScheduleBuilder);
+
+ // 鎸夋柊鐨刢ronExpression琛ㄨ揪寮忔瀯寤轰竴涓柊鐨則rigger
+ CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(getTriggerKey(jobId, jobGroup))
+ .withSchedule(cronScheduleBuilder).build();
+
+ // 鏀惧叆鍙傛暟锛岃繍琛屾椂鐨勬柟娉曞彲浠ヨ幏鍙�
+ jobDetail.getJobDataMap().put(ScheduleConstants.TASK_PROPERTIES, job);
+
+ // 鍒ゆ柇鏄惁瀛樺湪
+ if (scheduler.checkExists(getJobKey(jobId, jobGroup)))
+ {
+ // 闃叉鍒涘缓鏃跺瓨鍦ㄦ暟鎹棶棰� 鍏堢Щ闄わ紝鐒跺悗鍦ㄦ墽琛屽垱寤烘搷浣�
+ scheduler.deleteJob(getJobKey(jobId, jobGroup));
+ }
+
+ // 鍒ゆ柇浠诲姟鏄惁杩囨湡
+ if (StringUtils.isNotNull(CronUtils.getNextExecution(job.getCronExpression())))
+ {
+ // 鎵ц璋冨害浠诲姟
+ scheduler.scheduleJob(jobDetail, trigger);
+ }
+
+ // 鏆傚仠浠诲姟
+ if (job.getStatus().equals(ScheduleConstants.Status.PAUSE.getValue()))
+ {
+ scheduler.pauseJob(ScheduleUtils.getJobKey(jobId, jobGroup));
+ }
+ }
+
+ /**
+ * 璁剧疆瀹氭椂浠诲姟绛栫暐
+ */
+ public static CronScheduleBuilder handleCronScheduleMisfirePolicy(SysJob job, CronScheduleBuilder cb)
+ throws TaskException
+ {
+ switch (job.getMisfirePolicy())
+ {
+ case ScheduleConstants.MISFIRE_DEFAULT:
+ return cb;
+ case ScheduleConstants.MISFIRE_IGNORE_MISFIRES:
+ return cb.withMisfireHandlingInstructionIgnoreMisfires();
+ case ScheduleConstants.MISFIRE_FIRE_AND_PROCEED:
+ return cb.withMisfireHandlingInstructionFireAndProceed();
+ case ScheduleConstants.MISFIRE_DO_NOTHING:
+ return cb.withMisfireHandlingInstructionDoNothing();
+ default:
+ throw new TaskException("The task misfire policy '" + job.getMisfirePolicy()
+ + "' cannot be used in cron schedule tasks", Code.CONFIG_ERROR);
+ }
+ }
+
+ /**
+ * 妫�鏌ュ寘鍚嶆槸鍚︿负鐧藉悕鍗曢厤缃�
+ *
+ * @param invokeTarget 鐩爣瀛楃涓�
+ * @return 缁撴灉
+ */
+ public static boolean whiteList(String invokeTarget)
+ {
+ String packageName = StringUtils.substringBefore(invokeTarget, "(");
+ int count = StringUtils.countMatches(packageName, ".");
+ if (count > 1)
+ {
+ return StringUtils.containsAnyIgnoreCase(invokeTarget, Constants.JOB_WHITELIST_STR);
+ }
+ Object obj = SpringUtils.getBean(StringUtils.split(invokeTarget, ".")[0]);
+ String beanPackageName = obj.getClass().getPackage().getName();
+ return StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_WHITELIST_STR)
+ && !StringUtils.containsAnyIgnoreCase(beanPackageName, Constants.JOB_ERROR_STR);
+ }
+}
diff --git a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
new file mode 100644
index 0000000..ba1b683
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobLogMapper.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.quartz.mapper.SysJobLogMapper">
+
+ <resultMap type="SysJobLog" id="SysJobLogResult">
+ <id property="jobLogId" column="job_log_id" />
+ <result property="jobName" column="job_name" />
+ <result property="jobGroup" column="job_group" />
+ <result property="invokeTarget" column="invoke_target" />
+ <result property="jobMessage" column="job_message" />
+ <result property="status" column="status" />
+ <result property="exceptionInfo" column="exception_info" />
+ <result property="createTime" column="create_time" />
+ </resultMap>
+
+ <sql id="selectJobLogVo">
+ select job_log_id, job_name, job_group, invoke_target, job_message, status, exception_info, create_time
+ from sys_job_log
+ </sql>
+
+ <select id="selectJobLogList" parameterType="SysJobLog" resultMap="SysJobLogResult">
+ <include refid="selectJobLogVo"/>
+ <where>
+ <if test="jobName != null and jobName != ''">
+ AND job_name like concat('%', #{jobName}, '%')
+ </if>
+ <if test="jobGroup != null and jobGroup != ''">
+ AND job_group = #{jobGroup}
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="invokeTarget != null and invokeTarget != ''">
+ AND invoke_target like concat('%', #{invokeTarget}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ and date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ and date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ </if>
+ </where>
+ order by create_time desc
+ </select>
+
+ <select id="selectJobLogAll" resultMap="SysJobLogResult">
+ <include refid="selectJobLogVo"/>
+ </select>
+
+ <select id="selectJobLogById" parameterType="Long" resultMap="SysJobLogResult">
+ <include refid="selectJobLogVo"/>
+ where job_log_id = #{jobLogId}
+ </select>
+
+ <delete id="deleteJobLogById" parameterType="Long">
+ delete from sys_job_log where job_log_id = #{jobLogId}
+ </delete>
+
+ <delete id="deleteJobLogByIds" parameterType="Long">
+ delete from sys_job_log where job_log_id in
+ <foreach collection="array" item="jobLogId" open="(" separator="," close=")">
+ #{jobLogId}
+ </foreach>
+ </delete>
+
+ <update id="cleanJobLog">
+ truncate table sys_job_log
+ </update>
+
+ <insert id="insertJobLog" parameterType="SysJobLog">
+ insert into sys_job_log(
+ <if test="jobLogId != null and jobLogId != 0">job_log_id,</if>
+ <if test="jobName != null and jobName != ''">job_name,</if>
+ <if test="jobGroup != null and jobGroup != ''">job_group,</if>
+ <if test="invokeTarget != null and invokeTarget != ''">invoke_target,</if>
+ <if test="jobMessage != null and jobMessage != ''">job_message,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="exceptionInfo != null and exceptionInfo != ''">exception_info,</if>
+ create_time
+ )values(
+ <if test="jobLogId != null and jobLogId != 0">#{jobLogId},</if>
+ <if test="jobName != null and jobName != ''">#{jobName},</if>
+ <if test="jobGroup != null and jobGroup != ''">#{jobGroup},</if>
+ <if test="invokeTarget != null and invokeTarget != ''">#{invokeTarget},</if>
+ <if test="jobMessage != null and jobMessage != ''">#{jobMessage},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="exceptionInfo != null and exceptionInfo != ''">#{exceptionInfo},</if>
+ sysdate()
+ )
+ </insert>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml
new file mode 100644
index 0000000..5605c44
--- /dev/null
+++ b/ruoyi-quartz/src/main/resources/mapper/quartz/SysJobMapper.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.quartz.mapper.SysJobMapper">
+
+ <resultMap type="SysJob" id="SysJobResult">
+ <id property="jobId" column="job_id" />
+ <result property="jobName" column="job_name" />
+ <result property="jobGroup" column="job_group" />
+ <result property="invokeTarget" column="invoke_target" />
+ <result property="cronExpression" column="cron_expression" />
+ <result property="misfirePolicy" column="misfire_policy" />
+ <result property="concurrent" column="concurrent" />
+ <result property="status" column="status" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="remark" column="remark" />
+ </resultMap>
+
+ <sql id="selectJobVo">
+ select job_id, job_name, job_group, invoke_target, cron_expression, misfire_policy, concurrent, status, create_by, create_time, remark
+ from sys_job
+ </sql>
+
+ <select id="selectJobList" parameterType="SysJob" resultMap="SysJobResult">
+ <include refid="selectJobVo"/>
+ <where>
+ <if test="jobName != null and jobName != ''">
+ AND job_name like concat('%', #{jobName}, '%')
+ </if>
+ <if test="jobGroup != null and jobGroup != ''">
+ AND job_group = #{jobGroup}
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="invokeTarget != null and invokeTarget != ''">
+ AND invoke_target like concat('%', #{invokeTarget}, '%')
+ </if>
+ </where>
+ </select>
+
+ <select id="selectJobAll" resultMap="SysJobResult">
+ <include refid="selectJobVo"/>
+ </select>
+
+ <select id="selectJobById" parameterType="Long" resultMap="SysJobResult">
+ <include refid="selectJobVo"/>
+ where job_id = #{jobId}
+ </select>
+
+ <delete id="deleteJobById" parameterType="Long">
+ delete from sys_job where job_id = #{jobId}
+ </delete>
+
+ <delete id="deleteJobByIds" parameterType="Long">
+ delete from sys_job where job_id in
+ <foreach collection="array" item="jobId" open="(" separator="," close=")">
+ #{jobId}
+ </foreach>
+ </delete>
+
+ <update id="updateJob" parameterType="SysJob">
+ update sys_job
+ <set>
+ <if test="jobName != null and jobName != ''">job_name = #{jobName},</if>
+ <if test="jobGroup != null and jobGroup != ''">job_group = #{jobGroup},</if>
+ <if test="invokeTarget != null and invokeTarget != ''">invoke_target = #{invokeTarget},</if>
+ <if test="cronExpression != null and cronExpression != ''">cron_expression = #{cronExpression},</if>
+ <if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy = #{misfirePolicy},</if>
+ <if test="concurrent != null and concurrent != ''">concurrent = #{concurrent},</if>
+ <if test="status !=null">status = #{status},</if>
+ <if test="remark != null and remark != ''">remark = #{remark},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where job_id = #{jobId}
+ </update>
+
+ <insert id="insertJob" parameterType="SysJob" useGeneratedKeys="true" keyProperty="jobId">
+ insert into sys_job(
+ <if test="jobId != null and jobId != 0">job_id,</if>
+ <if test="jobName != null and jobName != ''">job_name,</if>
+ <if test="jobGroup != null and jobGroup != ''">job_group,</if>
+ <if test="invokeTarget != null and invokeTarget != ''">invoke_target,</if>
+ <if test="cronExpression != null and cronExpression != ''">cron_expression,</if>
+ <if test="misfirePolicy != null and misfirePolicy != ''">misfire_policy,</if>
+ <if test="concurrent != null and concurrent != ''">concurrent,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="jobId != null and jobId != 0">#{jobId},</if>
+ <if test="jobName != null and jobName != ''">#{jobName},</if>
+ <if test="jobGroup != null and jobGroup != ''">#{jobGroup},</if>
+ <if test="invokeTarget != null and invokeTarget != ''">#{invokeTarget},</if>
+ <if test="cronExpression != null and cronExpression != ''">#{cronExpression},</if>
+ <if test="misfirePolicy != null and misfirePolicy != ''">#{misfirePolicy},</if>
+ <if test="concurrent != null and concurrent != ''">#{concurrent},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/pom.xml b/ruoyi-system/pom.xml
new file mode 100644
index 0000000..6248a2c
--- /dev/null
+++ b/ruoyi-system/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>ruoyi</artifactId>
+ <groupId>com.ruoyi</groupId>
+ <version>3.8.9</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>ruoyi-system</artifactId>
+
+ <description>
+ system绯荤粺妯″潡
+ </description>
+
+ <dependencies>
+
+ <!-- 閫氱敤宸ュ叿-->
+ <dependency>
+ <groupId>com.ruoyi</groupId>
+ <artifactId>ruoyi-common</artifactId>
+ </dependency>
+
+ </dependencies>
+
+</project>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java
new file mode 100644
index 0000000..83f0703
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysCache.java
@@ -0,0 +1,81 @@
+package com.ruoyi.system.domain;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 缂撳瓨淇℃伅
+ *
+ * @author ruoyi
+ */
+public class SysCache
+{
+ /** 缂撳瓨鍚嶇О */
+ private String cacheName = "";
+
+ /** 缂撳瓨閿悕 */
+ private String cacheKey = "";
+
+ /** 缂撳瓨鍐呭 */
+ private String cacheValue = "";
+
+ /** 澶囨敞 */
+ private String remark = "";
+
+ public SysCache()
+ {
+
+ }
+
+ public SysCache(String cacheName, String remark)
+ {
+ this.cacheName = cacheName;
+ this.remark = remark;
+ }
+
+ public SysCache(String cacheName, String cacheKey, String cacheValue)
+ {
+ this.cacheName = StringUtils.replace(cacheName, ":", "");
+ this.cacheKey = StringUtils.replace(cacheKey, cacheName, "");
+ this.cacheValue = cacheValue;
+ }
+
+ public String getCacheName()
+ {
+ return cacheName;
+ }
+
+ public void setCacheName(String cacheName)
+ {
+ this.cacheName = cacheName;
+ }
+
+ public String getCacheKey()
+ {
+ return cacheKey;
+ }
+
+ public void setCacheKey(String cacheKey)
+ {
+ this.cacheKey = cacheKey;
+ }
+
+ public String getCacheValue()
+ {
+ return cacheValue;
+ }
+
+ public void setCacheValue(String cacheValue)
+ {
+ this.cacheValue = cacheValue;
+ }
+
+ public String getRemark()
+ {
+ return remark;
+ }
+
+ public void setRemark(String remark)
+ {
+ this.remark = remark;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
new file mode 100644
index 0000000..c54678c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysConfig.java
@@ -0,0 +1,111 @@
+package com.ruoyi.system.domain;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 鍙傛暟閰嶇疆琛� sys_config
+ *
+ * @author ruoyi
+ */
+public class SysConfig extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鍙傛暟涓婚敭 */
+ @Excel(name = "鍙傛暟涓婚敭", cellType = ColumnType.NUMERIC)
+ private Long configId;
+
+ /** 鍙傛暟鍚嶇О */
+ @Excel(name = "鍙傛暟鍚嶇О")
+ private String configName;
+
+ /** 鍙傛暟閿悕 */
+ @Excel(name = "鍙傛暟閿悕")
+ private String configKey;
+
+ /** 鍙傛暟閿�� */
+ @Excel(name = "鍙傛暟閿��")
+ private String configValue;
+
+ /** 绯荤粺鍐呯疆锛圷鏄� N鍚︼級 */
+ @Excel(name = "绯荤粺鍐呯疆", readConverterExp = "Y=鏄�,N=鍚�")
+ private String configType;
+
+ public Long getConfigId()
+ {
+ return configId;
+ }
+
+ public void setConfigId(Long configId)
+ {
+ this.configId = configId;
+ }
+
+ @NotBlank(message = "鍙傛暟鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 100, message = "鍙傛暟鍚嶇О涓嶈兘瓒呰繃100涓瓧绗�")
+ public String getConfigName()
+ {
+ return configName;
+ }
+
+ public void setConfigName(String configName)
+ {
+ this.configName = configName;
+ }
+
+ @NotBlank(message = "鍙傛暟閿悕闀垮害涓嶈兘涓虹┖")
+ @Size(min = 0, max = 100, message = "鍙傛暟閿悕闀垮害涓嶈兘瓒呰繃100涓瓧绗�")
+ public String getConfigKey()
+ {
+ return configKey;
+ }
+
+ public void setConfigKey(String configKey)
+ {
+ this.configKey = configKey;
+ }
+
+ @NotBlank(message = "鍙傛暟閿�间笉鑳戒负绌�")
+ @Size(min = 0, max = 500, message = "鍙傛暟閿�奸暱搴︿笉鑳借秴杩�500涓瓧绗�")
+ public String getConfigValue()
+ {
+ return configValue;
+ }
+
+ public void setConfigValue(String configValue)
+ {
+ this.configValue = configValue;
+ }
+
+ public String getConfigType()
+ {
+ return configType;
+ }
+
+ public void setConfigType(String configType)
+ {
+ this.configType = configType;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("configId", getConfigId())
+ .append("configName", getConfigName())
+ .append("configKey", getConfigKey())
+ .append("configValue", getConfigValue())
+ .append("configType", getConfigType())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
new file mode 100644
index 0000000..7fdea30
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysLogininfor.java
@@ -0,0 +1,144 @@
+package com.ruoyi.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 绯荤粺璁块棶璁板綍琛� sys_logininfor
+ *
+ * @author ruoyi
+ */
+public class SysLogininfor extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** ID */
+ @Excel(name = "搴忓彿", cellType = ColumnType.NUMERIC)
+ private Long infoId;
+
+ /** 鐢ㄦ埛璐﹀彿 */
+ @Excel(name = "鐢ㄦ埛璐﹀彿")
+ private String userName;
+
+ /** 鐧诲綍鐘舵�� 0鎴愬姛 1澶辫触 */
+ @Excel(name = "鐧诲綍鐘舵��", readConverterExp = "0=鎴愬姛,1=澶辫触")
+ private String status;
+
+ /** 鐧诲綍IP鍦板潃 */
+ @Excel(name = "鐧诲綍鍦板潃")
+ private String ipaddr;
+
+ /** 鐧诲綍鍦扮偣 */
+ @Excel(name = "鐧诲綍鍦扮偣")
+ private String loginLocation;
+
+ /** 娴忚鍣ㄧ被鍨� */
+ @Excel(name = "娴忚鍣�")
+ private String browser;
+
+ /** 鎿嶄綔绯荤粺 */
+ @Excel(name = "鎿嶄綔绯荤粺")
+ private String os;
+
+ /** 鎻愮ず娑堟伅 */
+ @Excel(name = "鎻愮ず娑堟伅")
+ private String msg;
+
+ /** 璁块棶鏃堕棿 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "璁块棶鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date loginTime;
+
+ public Long getInfoId()
+ {
+ return infoId;
+ }
+
+ public void setInfoId(Long infoId)
+ {
+ this.infoId = infoId;
+ }
+
+ public String getUserName()
+ {
+ return userName;
+ }
+
+ public void setUserName(String userName)
+ {
+ this.userName = userName;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getIpaddr()
+ {
+ return ipaddr;
+ }
+
+ public void setIpaddr(String ipaddr)
+ {
+ this.ipaddr = ipaddr;
+ }
+
+ public String getLoginLocation()
+ {
+ return loginLocation;
+ }
+
+ public void setLoginLocation(String loginLocation)
+ {
+ this.loginLocation = loginLocation;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public String getMsg()
+ {
+ return msg;
+ }
+
+ public void setMsg(String msg)
+ {
+ this.msg = msg;
+ }
+
+ public Date getLoginTime()
+ {
+ return loginTime;
+ }
+
+ public void setLoginTime(Date loginTime)
+ {
+ this.loginTime = loginTime;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
new file mode 100644
index 0000000..8c07a54
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysNotice.java
@@ -0,0 +1,102 @@
+package com.ruoyi.system.domain;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.core.domain.BaseEntity;
+import com.ruoyi.common.xss.Xss;
+
+/**
+ * 閫氱煡鍏憡琛� sys_notice
+ *
+ * @author ruoyi
+ */
+public class SysNotice extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鍏憡ID */
+ private Long noticeId;
+
+ /** 鍏憡鏍囬 */
+ private String noticeTitle;
+
+ /** 鍏憡绫诲瀷锛�1閫氱煡 2鍏憡锛� */
+ private String noticeType;
+
+ /** 鍏憡鍐呭 */
+ private String noticeContent;
+
+ /** 鍏憡鐘舵�侊紙0姝e父 1鍏抽棴锛� */
+ private String status;
+
+ public Long getNoticeId()
+ {
+ return noticeId;
+ }
+
+ public void setNoticeId(Long noticeId)
+ {
+ this.noticeId = noticeId;
+ }
+
+ public void setNoticeTitle(String noticeTitle)
+ {
+ this.noticeTitle = noticeTitle;
+ }
+
+ @Xss(message = "鍏憡鏍囬涓嶈兘鍖呭惈鑴氭湰瀛楃")
+ @NotBlank(message = "鍏憡鏍囬涓嶈兘涓虹┖")
+ @Size(min = 0, max = 50, message = "鍏憡鏍囬涓嶈兘瓒呰繃50涓瓧绗�")
+ public String getNoticeTitle()
+ {
+ return noticeTitle;
+ }
+
+ public void setNoticeType(String noticeType)
+ {
+ this.noticeType = noticeType;
+ }
+
+ public String getNoticeType()
+ {
+ return noticeType;
+ }
+
+ public void setNoticeContent(String noticeContent)
+ {
+ this.noticeContent = noticeContent;
+ }
+
+ public String getNoticeContent()
+ {
+ return noticeContent;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("noticeId", getNoticeId())
+ .append("noticeTitle", getNoticeTitle())
+ .append("noticeType", getNoticeType())
+ .append("noticeContent", getNoticeContent())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
new file mode 100644
index 0000000..f6761df
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysOperLog.java
@@ -0,0 +1,269 @@
+package com.ruoyi.system.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 鎿嶄綔鏃ュ織璁板綍琛� oper_log
+ *
+ * @author ruoyi
+ */
+public class SysOperLog extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 鏃ュ織涓婚敭 */
+ @Excel(name = "鎿嶄綔搴忓彿", cellType = ColumnType.NUMERIC)
+ private Long operId;
+
+ /** 鎿嶄綔妯″潡 */
+ @Excel(name = "鎿嶄綔妯″潡")
+ private String title;
+
+ /** 涓氬姟绫诲瀷锛�0鍏跺畠 1鏂板 2淇敼 3鍒犻櫎锛� */
+ @Excel(name = "涓氬姟绫诲瀷", readConverterExp = "0=鍏跺畠,1=鏂板,2=淇敼,3=鍒犻櫎,4=鎺堟潈,5=瀵煎嚭,6=瀵煎叆,7=寮洪��,8=鐢熸垚浠g爜,9=娓呯┖鏁版嵁")
+ private Integer businessType;
+
+ /** 涓氬姟绫诲瀷鏁扮粍 */
+ private Integer[] businessTypes;
+
+ /** 璇锋眰鏂规硶 */
+ @Excel(name = "璇锋眰鏂规硶")
+ private String method;
+
+ /** 璇锋眰鏂瑰紡 */
+ @Excel(name = "璇锋眰鏂瑰紡")
+ private String requestMethod;
+
+ /** 鎿嶄綔绫诲埆锛�0鍏跺畠 1鍚庡彴鐢ㄦ埛 2鎵嬫満绔敤鎴凤級 */
+ @Excel(name = "鎿嶄綔绫诲埆", readConverterExp = "0=鍏跺畠,1=鍚庡彴鐢ㄦ埛,2=鎵嬫満绔敤鎴�")
+ private Integer operatorType;
+
+ /** 鎿嶄綔浜哄憳 */
+ @Excel(name = "鎿嶄綔浜哄憳")
+ private String operName;
+
+ /** 閮ㄩ棬鍚嶇О */
+ @Excel(name = "閮ㄩ棬鍚嶇О")
+ private String deptName;
+
+ /** 璇锋眰url */
+ @Excel(name = "璇锋眰鍦板潃")
+ private String operUrl;
+
+ /** 鎿嶄綔鍦板潃 */
+ @Excel(name = "鎿嶄綔鍦板潃")
+ private String operIp;
+
+ /** 鎿嶄綔鍦扮偣 */
+ @Excel(name = "鎿嶄綔鍦扮偣")
+ private String operLocation;
+
+ /** 璇锋眰鍙傛暟 */
+ @Excel(name = "璇锋眰鍙傛暟")
+ private String operParam;
+
+ /** 杩斿洖鍙傛暟 */
+ @Excel(name = "杩斿洖鍙傛暟")
+ private String jsonResult;
+
+ /** 鎿嶄綔鐘舵�侊紙0姝e父 1寮傚父锛� */
+ @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=寮傚父")
+ private Integer status;
+
+ /** 閿欒娑堟伅 */
+ @Excel(name = "閿欒娑堟伅")
+ private String errorMsg;
+
+ /** 鎿嶄綔鏃堕棿 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "鎿嶄綔鏃堕棿", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date operTime;
+
+ /** 娑堣�楁椂闂� */
+ @Excel(name = "娑堣�楁椂闂�", suffix = "姣")
+ private Long costTime;
+
+ public Long getOperId()
+ {
+ return operId;
+ }
+
+ public void setOperId(Long operId)
+ {
+ this.operId = operId;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ public Integer getBusinessType()
+ {
+ return businessType;
+ }
+
+ public void setBusinessType(Integer businessType)
+ {
+ this.businessType = businessType;
+ }
+
+ public Integer[] getBusinessTypes()
+ {
+ return businessTypes;
+ }
+
+ public void setBusinessTypes(Integer[] businessTypes)
+ {
+ this.businessTypes = businessTypes;
+ }
+
+ public String getMethod()
+ {
+ return method;
+ }
+
+ public void setMethod(String method)
+ {
+ this.method = method;
+ }
+
+ public String getRequestMethod()
+ {
+ return requestMethod;
+ }
+
+ public void setRequestMethod(String requestMethod)
+ {
+ this.requestMethod = requestMethod;
+ }
+
+ public Integer getOperatorType()
+ {
+ return operatorType;
+ }
+
+ public void setOperatorType(Integer operatorType)
+ {
+ this.operatorType = operatorType;
+ }
+
+ public String getOperName()
+ {
+ return operName;
+ }
+
+ public void setOperName(String operName)
+ {
+ this.operName = operName;
+ }
+
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ public String getOperUrl()
+ {
+ return operUrl;
+ }
+
+ public void setOperUrl(String operUrl)
+ {
+ this.operUrl = operUrl;
+ }
+
+ public String getOperIp()
+ {
+ return operIp;
+ }
+
+ public void setOperIp(String operIp)
+ {
+ this.operIp = operIp;
+ }
+
+ public String getOperLocation()
+ {
+ return operLocation;
+ }
+
+ public void setOperLocation(String operLocation)
+ {
+ this.operLocation = operLocation;
+ }
+
+ public String getOperParam()
+ {
+ return operParam;
+ }
+
+ public void setOperParam(String operParam)
+ {
+ this.operParam = operParam;
+ }
+
+ public String getJsonResult()
+ {
+ return jsonResult;
+ }
+
+ public void setJsonResult(String jsonResult)
+ {
+ this.jsonResult = jsonResult;
+ }
+
+ public Integer getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(Integer status)
+ {
+ this.status = status;
+ }
+
+ public String getErrorMsg()
+ {
+ return errorMsg;
+ }
+
+ public void setErrorMsg(String errorMsg)
+ {
+ this.errorMsg = errorMsg;
+ }
+
+ public Date getOperTime()
+ {
+ return operTime;
+ }
+
+ public void setOperTime(Date operTime)
+ {
+ this.operTime = operTime;
+ }
+
+ public Long getCostTime()
+ {
+ return costTime;
+ }
+
+ public void setCostTime(Long costTime)
+ {
+ this.costTime = costTime;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
new file mode 100644
index 0000000..820a13b
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysPost.java
@@ -0,0 +1,124 @@
+package com.ruoyi.system.domain;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import javax.validation.constraints.Size;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.annotation.Excel.ColumnType;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 宀椾綅琛� sys_post
+ *
+ * @author ruoyi
+ */
+public class SysPost extends BaseEntity
+{
+ private static final long serialVersionUID = 1L;
+
+ /** 宀椾綅搴忓彿 */
+ @Excel(name = "宀椾綅搴忓彿", cellType = ColumnType.NUMERIC)
+ private Long postId;
+
+ /** 宀椾綅缂栫爜 */
+ @Excel(name = "宀椾綅缂栫爜")
+ private String postCode;
+
+ /** 宀椾綅鍚嶇О */
+ @Excel(name = "宀椾綅鍚嶇О")
+ private String postName;
+
+ /** 宀椾綅鎺掑簭 */
+ @Excel(name = "宀椾綅鎺掑簭")
+ private Integer postSort;
+
+ /** 鐘舵�侊紙0姝e父 1鍋滅敤锛� */
+ @Excel(name = "鐘舵��", readConverterExp = "0=姝e父,1=鍋滅敤")
+ private String status;
+
+ /** 鐢ㄦ埛鏄惁瀛樺湪姝ゅ矖浣嶆爣璇� 榛樿涓嶅瓨鍦� */
+ private boolean flag = false;
+
+ public Long getPostId()
+ {
+ return postId;
+ }
+
+ public void setPostId(Long postId)
+ {
+ this.postId = postId;
+ }
+
+ @NotBlank(message = "宀椾綅缂栫爜涓嶈兘涓虹┖")
+ @Size(min = 0, max = 64, message = "宀椾綅缂栫爜闀垮害涓嶈兘瓒呰繃64涓瓧绗�")
+ public String getPostCode()
+ {
+ return postCode;
+ }
+
+ public void setPostCode(String postCode)
+ {
+ this.postCode = postCode;
+ }
+
+ @NotBlank(message = "宀椾綅鍚嶇О涓嶈兘涓虹┖")
+ @Size(min = 0, max = 50, message = "宀椾綅鍚嶇О闀垮害涓嶈兘瓒呰繃50涓瓧绗�")
+ public String getPostName()
+ {
+ return postName;
+ }
+
+ public void setPostName(String postName)
+ {
+ this.postName = postName;
+ }
+
+ @NotNull(message = "鏄剧ず椤哄簭涓嶈兘涓虹┖")
+ public Integer getPostSort()
+ {
+ return postSort;
+ }
+
+ public void setPostSort(Integer postSort)
+ {
+ this.postSort = postSort;
+ }
+
+ public String getStatus()
+ {
+ return status;
+ }
+
+ public void setStatus(String status)
+ {
+ this.status = status;
+ }
+
+ public boolean isFlag()
+ {
+ return flag;
+ }
+
+ public void setFlag(boolean flag)
+ {
+ this.flag = flag;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("postId", getPostId())
+ .append("postCode", getPostCode())
+ .append("postName", getPostName())
+ .append("postSort", getPostSort())
+ .append("status", getStatus())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("remark", getRemark())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java
new file mode 100644
index 0000000..47b21bf
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleDept.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 瑙掕壊鍜岄儴闂ㄥ叧鑱� sys_role_dept
+ *
+ * @author ruoyi
+ */
+public class SysRoleDept
+{
+ /** 瑙掕壊ID */
+ private Long roleId;
+
+ /** 閮ㄩ棬ID */
+ private Long deptId;
+
+ public Long getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public Long getDeptId()
+ {
+ return deptId;
+ }
+
+ public void setDeptId(Long deptId)
+ {
+ this.deptId = deptId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("roleId", getRoleId())
+ .append("deptId", getDeptId())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java
new file mode 100644
index 0000000..de10a74
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysRoleMenu.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 瑙掕壊鍜岃彍鍗曞叧鑱� sys_role_menu
+ *
+ * @author ruoyi
+ */
+public class SysRoleMenu
+{
+ /** 瑙掕壊ID */
+ private Long roleId;
+
+ /** 鑿滃崟ID */
+ private Long menuId;
+
+ public Long getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ public Long getMenuId()
+ {
+ return menuId;
+ }
+
+ public void setMenuId(Long menuId)
+ {
+ this.menuId = menuId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("roleId", getRoleId())
+ .append("menuId", getMenuId())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java
new file mode 100644
index 0000000..2bbd318
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserOnline.java
@@ -0,0 +1,113 @@
+package com.ruoyi.system.domain;
+
+/**
+ * 褰撳墠鍦ㄧ嚎浼氳瘽
+ *
+ * @author ruoyi
+ */
+public class SysUserOnline
+{
+ /** 浼氳瘽缂栧彿 */
+ private String tokenId;
+
+ /** 閮ㄩ棬鍚嶇О */
+ private String deptName;
+
+ /** 鐢ㄦ埛鍚嶇О */
+ private String userName;
+
+ /** 鐧诲綍IP鍦板潃 */
+ private String ipaddr;
+
+ /** 鐧诲綍鍦板潃 */
+ private String loginLocation;
+
+ /** 娴忚鍣ㄧ被鍨� */
+ private String browser;
+
+ /** 鎿嶄綔绯荤粺 */
+ private String os;
+
+ /** 鐧诲綍鏃堕棿 */
+ private Long loginTime;
+
+ public String getTokenId()
+ {
+ return tokenId;
+ }
+
+ public void setTokenId(String tokenId)
+ {
+ this.tokenId = tokenId;
+ }
+
+ public String getDeptName()
+ {
+ return deptName;
+ }
+
+ public void setDeptName(String deptName)
+ {
+ this.deptName = deptName;
+ }
+
+ public String getUserName()
+ {
+ return userName;
+ }
+
+ public void setUserName(String userName)
+ {
+ this.userName = userName;
+ }
+
+ public String getIpaddr()
+ {
+ return ipaddr;
+ }
+
+ public void setIpaddr(String ipaddr)
+ {
+ this.ipaddr = ipaddr;
+ }
+
+ public String getLoginLocation()
+ {
+ return loginLocation;
+ }
+
+ public void setLoginLocation(String loginLocation)
+ {
+ this.loginLocation = loginLocation;
+ }
+
+ public String getBrowser()
+ {
+ return browser;
+ }
+
+ public void setBrowser(String browser)
+ {
+ this.browser = browser;
+ }
+
+ public String getOs()
+ {
+ return os;
+ }
+
+ public void setOs(String os)
+ {
+ this.os = os;
+ }
+
+ public Long getLoginTime()
+ {
+ return loginTime;
+ }
+
+ public void setLoginTime(Long loginTime)
+ {
+ this.loginTime = loginTime;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java
new file mode 100644
index 0000000..6e8c416
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserPost.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 鐢ㄦ埛鍜屽矖浣嶅叧鑱� sys_user_post
+ *
+ * @author ruoyi
+ */
+public class SysUserPost
+{
+ /** 鐢ㄦ埛ID */
+ private Long userId;
+
+ /** 宀椾綅ID */
+ private Long postId;
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public Long getPostId()
+ {
+ return postId;
+ }
+
+ public void setPostId(Long postId)
+ {
+ this.postId = postId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("userId", getUserId())
+ .append("postId", getPostId())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java
new file mode 100644
index 0000000..4d15810
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/SysUserRole.java
@@ -0,0 +1,46 @@
+package com.ruoyi.system.domain;
+
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+/**
+ * 鐢ㄦ埛鍜岃鑹插叧鑱� sys_user_role
+ *
+ * @author ruoyi
+ */
+public class SysUserRole
+{
+ /** 鐢ㄦ埛ID */
+ private Long userId;
+
+ /** 瑙掕壊ID */
+ private Long roleId;
+
+ public Long getUserId()
+ {
+ return userId;
+ }
+
+ public void setUserId(Long userId)
+ {
+ this.userId = userId;
+ }
+
+ public Long getRoleId()
+ {
+ return roleId;
+ }
+
+ public void setRoleId(Long roleId)
+ {
+ this.roleId = roleId;
+ }
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+ .append("userId", getUserId())
+ .append("roleId", getRoleId())
+ .toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java
new file mode 100644
index 0000000..a5d5fdc
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/MetaVo.java
@@ -0,0 +1,106 @@
+package com.ruoyi.system.domain.vo;
+
+import com.ruoyi.common.utils.StringUtils;
+
+/**
+ * 璺敱鏄剧ず淇℃伅
+ *
+ * @author ruoyi
+ */
+public class MetaVo
+{
+ /**
+ * 璁剧疆璇ヨ矾鐢卞湪渚ц竟鏍忓拰闈㈠寘灞戜腑灞曠ず鐨勫悕瀛�
+ */
+ private String title;
+
+ /**
+ * 璁剧疆璇ヨ矾鐢辩殑鍥炬爣锛屽搴旇矾寰剆rc/assets/icons/svg
+ */
+ private String icon;
+
+ /**
+ * 璁剧疆涓簍rue锛屽垯涓嶄細琚� <keep-alive>缂撳瓨
+ */
+ private boolean noCache;
+
+ /**
+ * 鍐呴摼鍦板潃锛坔ttp(s)://寮�澶达級
+ */
+ private String link;
+
+ public MetaVo()
+ {
+ }
+
+ public MetaVo(String title, String icon)
+ {
+ this.title = title;
+ this.icon = icon;
+ }
+
+ public MetaVo(String title, String icon, boolean noCache)
+ {
+ this.title = title;
+ this.icon = icon;
+ this.noCache = noCache;
+ }
+
+ public MetaVo(String title, String icon, String link)
+ {
+ this.title = title;
+ this.icon = icon;
+ this.link = link;
+ }
+
+ public MetaVo(String title, String icon, boolean noCache, String link)
+ {
+ this.title = title;
+ this.icon = icon;
+ this.noCache = noCache;
+ if (StringUtils.ishttp(link))
+ {
+ this.link = link;
+ }
+ }
+
+ public boolean isNoCache()
+ {
+ return noCache;
+ }
+
+ public void setNoCache(boolean noCache)
+ {
+ this.noCache = noCache;
+ }
+
+ public String getTitle()
+ {
+ return title;
+ }
+
+ public void setTitle(String title)
+ {
+ this.title = title;
+ }
+
+ public String getIcon()
+ {
+ return icon;
+ }
+
+ public void setIcon(String icon)
+ {
+ this.icon = icon;
+ }
+
+ public String getLink()
+ {
+ return link;
+ }
+
+ public void setLink(String link)
+ {
+ this.link = link;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java
new file mode 100644
index 0000000..afff8c9
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/vo/RouterVo.java
@@ -0,0 +1,148 @@
+package com.ruoyi.system.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonInclude;
+import java.util.List;
+
+/**
+ * 璺敱閰嶇疆淇℃伅
+ *
+ * @author ruoyi
+ */
+@JsonInclude(JsonInclude.Include.NON_EMPTY)
+public class RouterVo
+{
+ /**
+ * 璺敱鍚嶅瓧
+ */
+ private String name;
+
+ /**
+ * 璺敱鍦板潃
+ */
+ private String path;
+
+ /**
+ * 鏄惁闅愯棌璺敱锛屽綋璁剧疆 true 鐨勬椂鍊欒璺敱涓嶄細鍐嶄晶杈规爮鍑虹幇
+ */
+ private boolean hidden;
+
+ /**
+ * 閲嶅畾鍚戝湴鍧�锛屽綋璁剧疆 noRedirect 鐨勬椂鍊欒璺敱鍦ㄩ潰鍖呭睉瀵艰埅涓笉鍙鐐瑰嚮
+ */
+ private String redirect;
+
+ /**
+ * 缁勪欢鍦板潃
+ */
+ private String component;
+
+ /**
+ * 璺敱鍙傛暟锛氬 {"id": 1, "name": "ry"}
+ */
+ private String query;
+
+ /**
+ * 褰撲綘涓�涓矾鐢变笅闈㈢殑 children 澹版槑鐨勮矾鐢卞ぇ浜�1涓椂锛岃嚜鍔ㄤ細鍙樻垚宓屽鐨勬ā寮�--濡傜粍浠堕〉闈�
+ */
+ private Boolean alwaysShow;
+
+ /**
+ * 鍏朵粬鍏冪礌
+ */
+ private MetaVo meta;
+
+ /**
+ * 瀛愯矾鐢�
+ */
+ private List<RouterVo> children;
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public String getPath()
+ {
+ return path;
+ }
+
+ public void setPath(String path)
+ {
+ this.path = path;
+ }
+
+ public boolean getHidden()
+ {
+ return hidden;
+ }
+
+ public void setHidden(boolean hidden)
+ {
+ this.hidden = hidden;
+ }
+
+ public String getRedirect()
+ {
+ return redirect;
+ }
+
+ public void setRedirect(String redirect)
+ {
+ this.redirect = redirect;
+ }
+
+ public String getComponent()
+ {
+ return component;
+ }
+
+ public void setComponent(String component)
+ {
+ this.component = component;
+ }
+
+ public String getQuery()
+ {
+ return query;
+ }
+
+ public void setQuery(String query)
+ {
+ this.query = query;
+ }
+
+ public Boolean getAlwaysShow()
+ {
+ return alwaysShow;
+ }
+
+ public void setAlwaysShow(Boolean alwaysShow)
+ {
+ this.alwaysShow = alwaysShow;
+ }
+
+ public MetaVo getMeta()
+ {
+ return meta;
+ }
+
+ public void setMeta(MetaVo meta)
+ {
+ this.meta = meta;
+ }
+
+ public List<RouterVo> getChildren()
+ {
+ return children;
+ }
+
+ public void setChildren(List<RouterVo> children)
+ {
+ this.children = children;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomMapper.java
new file mode 100644
index 0000000..71798e8
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/CustomMapper.java
@@ -0,0 +1,18 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.ruoyi.common.core.domain.entity.Custom;
+import org.apache.ibatis.annotations.Mapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.stereotype.Repository;
+
+@Mapper
+public interface CustomMapper extends BaseMapper<Custom> {
+
+ IPage<Custom> selectCustomPageList(IPage<Custom> page, @Param("ew") QueryWrapper<Custom> ew);
+
+ int delCustomById(Integer id);
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
new file mode 100644
index 0000000..13d49d6
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysConfigMapper.java
@@ -0,0 +1,76 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysConfig;
+
+/**
+ * 鍙傛暟閰嶇疆 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysConfigMapper
+{
+ /**
+ * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 鍙傛暟閰嶇疆淇℃伅
+ */
+ public SysConfig selectConfig(SysConfig config);
+
+ /**
+ * 閫氳繃ID鏌ヨ閰嶇疆
+ *
+ * @param configId 鍙傛暟ID
+ * @return 鍙傛暟閰嶇疆淇℃伅
+ */
+ public SysConfig selectConfigById(Long configId);
+
+ /**
+ * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 鍙傛暟閰嶇疆闆嗗悎
+ */
+ public List<SysConfig> selectConfigList(SysConfig config);
+
+ /**
+ * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+ *
+ * @param configKey 鍙傛暟閿悕
+ * @return 鍙傛暟閰嶇疆淇℃伅
+ */
+ public SysConfig checkConfigKeyUnique(String configKey);
+
+ /**
+ * 鏂板鍙傛暟閰嶇疆
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertConfig(SysConfig config);
+
+ /**
+ * 淇敼鍙傛暟閰嶇疆
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateConfig(SysConfig config);
+
+ /**
+ * 鍒犻櫎鍙傛暟閰嶇疆
+ *
+ * @param configId 鍙傛暟ID
+ * @return 缁撴灉
+ */
+ public int deleteConfigById(Long configId);
+
+ /**
+ * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+ *
+ * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+ * @return 缁撴灉
+ */
+ public int deleteConfigByIds(Long[] configIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
new file mode 100644
index 0000000..384a9b6
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -0,0 +1,118 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.common.core.domain.entity.SysDept;
+
+/**
+ * 閮ㄩ棬绠$悊 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysDeptMapper
+{
+ /**
+ * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 閮ㄩ棬淇℃伅闆嗗悎
+ */
+ public List<SysDept> selectDeptList(SysDept dept);
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+ *
+ * @param roleId 瑙掕壊ID
+ * @param deptCheckStrictly 閮ㄩ棬鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
+ * @return 閫変腑閮ㄩ棬鍒楄〃
+ */
+ public List<Long> selectDeptListByRoleId(@Param("roleId") Long roleId, @Param("deptCheckStrictly") boolean deptCheckStrictly);
+
+ /**
+ * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 閮ㄩ棬淇℃伅
+ */
+ public SysDept selectDeptById(Long deptId);
+
+ /**
+ * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 閮ㄩ棬鍒楄〃
+ */
+ public List<SysDept> selectChildrenDeptById(Long deptId);
+
+ /**
+ * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 瀛愰儴闂ㄦ暟
+ */
+ public int selectNormalChildrenDeptById(Long deptId);
+
+ /**
+ * 鏄惁瀛樺湪瀛愯妭鐐�
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int hasChildByDeptId(Long deptId);
+
+ /**
+ * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int checkDeptExistUser(Long deptId);
+
+ /**
+ * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+ *
+ * @param deptName 閮ㄩ棬鍚嶇О
+ * @param parentId 鐖堕儴闂↖D
+ * @return 缁撴灉
+ */
+ public SysDept checkDeptNameUnique(@Param("deptName") String deptName, @Param("parentId") Long parentId);
+
+ /**
+ * 鏂板閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertDept(SysDept dept);
+
+ /**
+ * 淇敼閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateDept(SysDept dept);
+
+ /**
+ * 淇敼鎵�鍦ㄩ儴闂ㄦ甯哥姸鎬�
+ *
+ * @param deptIds 閮ㄩ棬ID缁�
+ */
+ public void updateDeptStatusNormal(Long[] deptIds);
+
+ /**
+ * 淇敼瀛愬厓绱犲叧绯�
+ *
+ * @param depts 瀛愬厓绱�
+ * @return 缁撴灉
+ */
+ public int updateDeptChildren(@Param("depts") List<SysDept> depts);
+
+ /**
+ * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int deleteDeptById(Long deptId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
new file mode 100644
index 0000000..a341f1e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictDataMapper.java
@@ -0,0 +1,95 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+
+/**
+ * 瀛楀吀琛� 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysDictDataMapper
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictData 瀛楀吀鏁版嵁淇℃伅
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ public List<SysDictData> selectDictDataList(SysDictData dictData);
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ public List<SysDictData> selectDictDataByType(String dictType);
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param dictValue 瀛楀吀閿��
+ * @return 瀛楀吀鏍囩
+ */
+ public String selectDictLabel(@Param("dictType") String dictType, @Param("dictValue") String dictValue);
+
+ /**
+ * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+ *
+ * @param dictCode 瀛楀吀鏁版嵁ID
+ * @return 瀛楀吀鏁版嵁
+ */
+ public SysDictData selectDictDataById(Long dictCode);
+
+ /**
+ * 鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀鏁版嵁
+ */
+ public int countDictDataByType(String dictType);
+
+ /**
+ * 閫氳繃瀛楀吀ID鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictCode 瀛楀吀鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteDictDataById(Long dictCode);
+
+ /**
+ * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteDictDataByIds(Long[] dictCodes);
+
+ /**
+ * 鏂板瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictData 瀛楀吀鏁版嵁淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertDictData(SysDictData dictData);
+
+ /**
+ * 淇敼瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictData 瀛楀吀鏁版嵁淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateDictData(SysDictData dictData);
+
+ /**
+ * 鍚屾淇敼瀛楀吀绫诲瀷
+ *
+ * @param oldDictType 鏃у瓧鍏哥被鍨�
+ * @param newDictType 鏂版棫瀛楀吀绫诲瀷
+ * @return 缁撴灉
+ */
+ public int updateDictDataType(@Param("oldDictType") String oldDictType, @Param("newDictType") String newDictType);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
new file mode 100644
index 0000000..3e5cfb2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDictTypeMapper.java
@@ -0,0 +1,88 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+
+/**
+ * 瀛楀吀琛� 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysDictTypeMapper
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+ *
+ * @param dictType 瀛楀吀绫诲瀷淇℃伅
+ * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+ */
+ public List<SysDictType> selectDictTypeList(SysDictType dictType);
+
+ /**
+ * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+ *
+ * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+ */
+ public List<SysDictType> selectDictTypeAll();
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+ *
+ * @param dictId 瀛楀吀绫诲瀷ID
+ * @return 瀛楀吀绫诲瀷
+ */
+ public SysDictType selectDictTypeById(Long dictId);
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀绫诲瀷
+ */
+ public SysDictType selectDictTypeByType(String dictType);
+
+ /**
+ * 閫氳繃瀛楀吀ID鍒犻櫎瀛楀吀淇℃伅
+ *
+ * @param dictId 瀛楀吀ID
+ * @return 缁撴灉
+ */
+ public int deleteDictTypeById(Long dictId);
+
+ /**
+ * 鎵归噺鍒犻櫎瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+ * @return 缁撴灉
+ */
+ public int deleteDictTypeByIds(Long[] dictIds);
+
+ /**
+ * 鏂板瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dictType 瀛楀吀绫诲瀷淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertDictType(SysDictType dictType);
+
+ /**
+ * 淇敼瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dictType 瀛楀吀绫诲瀷淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateDictType(SysDictType dictType);
+
+ /**
+ * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 缁撴灉
+ */
+ public SysDictType checkDictTypeUnique(String dictType);
+
+ List<SysDictType> selectList(String dictName);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
new file mode 100644
index 0000000..629866f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysLogininforMapper.java
@@ -0,0 +1,42 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysLogininfor;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysLogininforMapper
+{
+ /**
+ * 鏂板绯荤粺鐧诲綍鏃ュ織
+ *
+ * @param logininfor 璁块棶鏃ュ織瀵硅薄
+ */
+ public void insertLogininfor(SysLogininfor logininfor);
+
+ /**
+ * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+ *
+ * @param logininfor 璁块棶鏃ュ織瀵硅薄
+ * @return 鐧诲綍璁板綍闆嗗悎
+ */
+ public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+ /**
+ * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+ *
+ * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteLogininforByIds(Long[] infoIds);
+
+ /**
+ * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+ *
+ * @return 缁撴灉
+ */
+ public int cleanLogininfor();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
new file mode 100644
index 0000000..99c0c50
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysMenuMapper.java
@@ -0,0 +1,125 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+
+/**
+ * 鑿滃崟琛� 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysMenuMapper
+{
+ /**
+ * 鏌ヨ绯荤粺鑿滃崟鍒楄〃
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 鑿滃崟鍒楄〃
+ */
+ public List<SysMenu> selectMenuList(SysMenu menu);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛鎵�鏈夋潈闄�
+ *
+ * @return 鏉冮檺鍒楄〃
+ */
+ public List<String> selectMenuPerms();
+
+ /**
+ * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 鑿滃崟鍒楄〃
+ */
+ public List<SysMenu> selectMenuListByUserId(SysMenu menu);
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ public List<String> selectMenuPermsByRoleId(Long roleId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ public List<String> selectMenuPermsByUserId(Long userId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+ *
+ * @return 鑿滃崟鍒楄〃
+ */
+ public List<SysMenu> selectMenuTreeAll();
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鑿滃崟鍒楄〃
+ */
+ public List<SysMenu> selectMenuTreeByUserId(Long userId);
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+ *
+ * @param roleId 瑙掕壊ID
+ * @param menuCheckStrictly 鑿滃崟鏍戦�夋嫨椤规槸鍚﹀叧鑱旀樉绀�
+ * @return 閫変腑鑿滃崟鍒楄〃
+ */
+ public List<Long> selectMenuListByRoleId(@Param("roleId") Long roleId, @Param("menuCheckStrictly") boolean menuCheckStrictly);
+
+ /**
+ * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 鑿滃崟淇℃伅
+ */
+ public SysMenu selectMenuById(Long menuId);
+
+ /**
+ * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉
+ */
+ public int hasChildByMenuId(Long menuId);
+
+ /**
+ * 鏂板鑿滃崟淇℃伅
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertMenu(SysMenu menu);
+
+ /**
+ * 淇敼鑿滃崟淇℃伅
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateMenu(SysMenu menu);
+
+ /**
+ * 鍒犻櫎鑿滃崟绠$悊淇℃伅
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉
+ */
+ public int deleteMenuById(Long menuId);
+
+ /**
+ * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
+ *
+ * @param menuName 鑿滃崟鍚嶇О
+ * @param parentId 鐖惰彍鍗旾D
+ * @return 缁撴灉
+ */
+ public SysMenu checkMenuNameUnique(@Param("menuName") String menuName, @Param("parentId") Long parentId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
new file mode 100644
index 0000000..c34f0a2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysNoticeMapper.java
@@ -0,0 +1,60 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysNotice;
+
+/**
+ * 閫氱煡鍏憡琛� 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysNoticeMapper
+{
+ /**
+ * 鏌ヨ鍏憡淇℃伅
+ *
+ * @param noticeId 鍏憡ID
+ * @return 鍏憡淇℃伅
+ */
+ public SysNotice selectNoticeById(Long noticeId);
+
+ /**
+ * 鏌ヨ鍏憡鍒楄〃
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 鍏憡闆嗗悎
+ */
+ public List<SysNotice> selectNoticeList(SysNotice notice);
+
+ /**
+ * 鏂板鍏憡
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertNotice(SysNotice notice);
+
+ /**
+ * 淇敼鍏憡
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateNotice(SysNotice notice);
+
+ /**
+ * 鎵归噺鍒犻櫎鍏憡
+ *
+ * @param noticeId 鍏憡ID
+ * @return 缁撴灉
+ */
+ public int deleteNoticeById(Long noticeId);
+
+ /**
+ * 鎵归噺鍒犻櫎鍏憡淇℃伅
+ *
+ * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+ * @return 缁撴灉
+ */
+ public int deleteNoticeByIds(Long[] noticeIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
new file mode 100644
index 0000000..2ae6457
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysOperLogMapper.java
@@ -0,0 +1,48 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysOperLog;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysOperLogMapper
+{
+ /**
+ * 鏂板鎿嶄綔鏃ュ織
+ *
+ * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+ */
+ public void insertOperlog(SysOperLog operLog);
+
+ /**
+ * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+ *
+ * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+ * @return 鎿嶄綔鏃ュ織闆嗗悎
+ */
+ public List<SysOperLog> selectOperLogList(SysOperLog operLog);
+
+ /**
+ * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+ *
+ * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteOperLogByIds(Long[] operIds);
+
+ /**
+ * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+ *
+ * @param operId 鎿嶄綔ID
+ * @return 鎿嶄綔鏃ュ織瀵硅薄
+ */
+ public SysOperLog selectOperLogById(Long operId);
+
+ /**
+ * 娓呯┖鎿嶄綔鏃ュ織
+ */
+ public void cleanOperLog();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
new file mode 100644
index 0000000..19be227
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysPostMapper.java
@@ -0,0 +1,99 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysPost;
+
+/**
+ * 宀椾綅淇℃伅 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysPostMapper
+{
+ /**
+ * 鏌ヨ宀椾綅鏁版嵁闆嗗悎
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 宀椾綅鏁版嵁闆嗗悎
+ */
+ public List<SysPost> selectPostList(SysPost post);
+
+ /**
+ * 鏌ヨ鎵�鏈夊矖浣�
+ *
+ * @return 宀椾綅鍒楄〃
+ */
+ public List<SysPost> selectPostAll();
+
+ /**
+ * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+ *
+ * @param postId 宀椾綅ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ public SysPost selectPostById(Long postId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 閫変腑宀椾綅ID鍒楄〃
+ */
+ public List<Long> selectPostListByUserId(Long userId);
+
+ /**
+ * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 缁撴灉
+ */
+ public List<SysPost> selectPostsByUserName(String userName);
+
+ /**
+ * 鍒犻櫎宀椾綅淇℃伅
+ *
+ * @param postId 宀椾綅ID
+ * @return 缁撴灉
+ */
+ public int deletePostById(Long postId);
+
+ /**
+ * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+ *
+ * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+ * @return 缁撴灉
+ */
+ public int deletePostByIds(Long[] postIds);
+
+ /**
+ * 淇敼宀椾綅淇℃伅
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ public int updatePost(SysPost post);
+
+ /**
+ * 鏂板宀椾綅淇℃伅
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertPost(SysPost post);
+
+ /**
+ * 鏍¢獙宀椾綅鍚嶇О
+ *
+ * @param postName 宀椾綅鍚嶇О
+ * @return 缁撴灉
+ */
+ public SysPost checkPostNameUnique(String postName);
+
+ /**
+ * 鏍¢獙宀椾綅缂栫爜
+ *
+ * @param postCode 宀椾綅缂栫爜
+ * @return 缁撴灉
+ */
+ public SysPost checkPostCodeUnique(String postCode);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
new file mode 100644
index 0000000..f9d3a2f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleDeptMapper.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysRoleDept;
+
+/**
+ * 瑙掕壊涓庨儴闂ㄥ叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysRoleDeptMapper
+{
+ /**
+ * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊鍜岄儴闂ㄥ叧鑱�
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleDeptByRoleId(Long roleId);
+
+ /**
+ * 鎵归噺鍒犻櫎瑙掕壊閮ㄩ棬鍏宠仈淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleDept(Long[] ids);
+
+ /**
+ * 鏌ヨ閮ㄩ棬浣跨敤鏁伴噺
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int selectCountRoleDeptByDeptId(Long deptId);
+
+ /**
+ * 鎵归噺鏂板瑙掕壊閮ㄩ棬淇℃伅
+ *
+ * @param roleDeptList 瑙掕壊閮ㄩ棬鍒楄〃
+ * @return 缁撴灉
+ */
+ public int batchRoleDept(List<SysRoleDept> roleDeptList);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
new file mode 100644
index 0000000..cf2bd8c
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMapper.java
@@ -0,0 +1,107 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysRole;
+
+/**
+ * 瑙掕壊琛� 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysRoleMapper
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+ */
+ public List<SysRole> selectRoleList(SysRole role);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 瑙掕壊鍒楄〃
+ */
+ public List<SysRole> selectRolePermissionByUserId(Long userId);
+
+ /**
+ * 鏌ヨ鎵�鏈夎鑹�
+ *
+ * @return 瑙掕壊鍒楄〃
+ */
+ public List<SysRole> selectRoleAll();
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 閫変腑瑙掕壊ID鍒楄〃
+ */
+ public List<Long> selectRoleListByUserId(Long userId);
+
+ /**
+ * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ public SysRole selectRoleById(Long roleId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 瑙掕壊鍒楄〃
+ */
+ public List<SysRole> selectRolesByUserName(String userName);
+
+ /**
+ * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+ *
+ * @param roleName 瑙掕壊鍚嶇О
+ * @return 瑙掕壊淇℃伅
+ */
+ public SysRole checkRoleNameUnique(String roleName);
+
+ /**
+ * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+ *
+ * @param roleKey 瑙掕壊鏉冮檺
+ * @return 瑙掕壊淇℃伅
+ */
+ public SysRole checkRoleKeyUnique(String roleKey);
+
+ /**
+ * 淇敼瑙掕壊淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateRole(SysRole role);
+
+ /**
+ * 鏂板瑙掕壊淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertRole(SysRole role);
+
+ /**
+ * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleById(Long roleId);
+
+ /**
+ * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+ *
+ * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleByIds(Long[] roleIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
new file mode 100644
index 0000000..6602bee
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysRoleMenuMapper.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysRoleMenu;
+
+/**
+ * 瑙掕壊涓庤彍鍗曞叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysRoleMenuMapper
+{
+ /**
+ * 鏌ヨ鑿滃崟浣跨敤鏁伴噺
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉
+ */
+ public int checkMenuExistRole(Long menuId);
+
+ /**
+ * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊鍜岃彍鍗曞叧鑱�
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleMenuByRoleId(Long roleId);
+
+ /**
+ * 鎵归噺鍒犻櫎瑙掕壊鑿滃崟鍏宠仈淇℃伅
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleMenu(Long[] ids);
+
+ /**
+ * 鎵归噺鏂板瑙掕壊鑿滃崟淇℃伅
+ *
+ * @param roleMenuList 瑙掕壊鑿滃崟鍒楄〃
+ * @return 缁撴灉
+ */
+ public int batchRoleMenu(List<SysRoleMenu> roleMenuList);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
new file mode 100644
index 0000000..76e1c79
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -0,0 +1,127 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.common.core.domain.entity.SysUser;
+
+/**
+ * 鐢ㄦ埛琛� 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysUserMapper
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+ *
+ * @param sysUser 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectUserList(SysUser sysUser);
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸查厤鐢ㄦ埛瑙掕壊鍒楄〃
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectAllocatedList(SysUser user);
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectUnallocatedList(SysUser user);
+
+ /**
+ * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ public SysUser selectUserByUserName(String userName);
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ public SysUser selectUserById(Long userId);
+
+ /**
+ * 鏂板鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertUser(SysUser user);
+
+ /**
+ * 淇敼鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateUser(SysUser user);
+
+ /**
+ * 淇敼鐢ㄦ埛澶村儚
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param avatar 澶村儚鍦板潃
+ * @return 缁撴灉
+ */
+ public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar);
+
+ /**
+ * 閲嶇疆鐢ㄦ埛瀵嗙爜
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param password 瀵嗙爜
+ * @return 缁撴灉
+ */
+ public int resetUserPwd(@Param("userName") String userName, @Param("password") String password);
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserById(Long userId);
+
+ /**
+ * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+ *
+ * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserByIds(Long[] userIds);
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+ *
+ * @param userName 鐢ㄦ埛鍚嶇О
+ * @return 缁撴灉
+ */
+ public SysUser checkUserNameUnique(String userName);
+
+ /**
+ * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+ *
+ * @param phonenumber 鎵嬫満鍙风爜
+ * @return 缁撴灉
+ */
+ public SysUser checkPhoneUnique(String phonenumber);
+
+ /**
+ * 鏍¢獙email鏄惁鍞竴
+ *
+ * @param email 鐢ㄦ埛閭
+ * @return 缁撴灉
+ */
+ public SysUser checkEmailUnique(String email);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
new file mode 100644
index 0000000..2a6a720
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserPostMapper.java
@@ -0,0 +1,44 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysUserPost;
+
+/**
+ * 鐢ㄦ埛涓庡矖浣嶅叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysUserPostMapper
+{
+ /**
+ * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛鍜屽矖浣嶅叧鑱�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserPostByUserId(Long userId);
+
+ /**
+ * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+ *
+ * @param postId 宀椾綅ID
+ * @return 缁撴灉
+ */
+ public int countUserPostById(Long postId);
+
+ /**
+ * 鎵归噺鍒犻櫎鐢ㄦ埛鍜屽矖浣嶅叧鑱�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteUserPost(Long[] ids);
+
+ /**
+ * 鎵归噺鏂板鐢ㄦ埛宀椾綅淇℃伅
+ *
+ * @param userPostList 鐢ㄦ埛宀椾綅鍒楄〃
+ * @return 缁撴灉
+ */
+ public int batchUserPost(List<SysUserPost> userPostList);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
new file mode 100644
index 0000000..3143ec8
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserRoleMapper.java
@@ -0,0 +1,62 @@
+package com.ruoyi.system.mapper;
+
+import java.util.List;
+import org.apache.ibatis.annotations.Param;
+import com.ruoyi.system.domain.SysUserRole;
+
+/**
+ * 鐢ㄦ埛涓庤鑹插叧鑱旇〃 鏁版嵁灞�
+ *
+ * @author ruoyi
+ */
+public interface SysUserRoleMapper
+{
+ /**
+ * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserRoleByUserId(Long userId);
+
+ /**
+ * 鎵归噺鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱�
+ *
+ * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteUserRole(Long[] ids);
+
+ /**
+ * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int countUserRoleByRoleId(Long roleId);
+
+ /**
+ * 鎵归噺鏂板鐢ㄦ埛瑙掕壊淇℃伅
+ *
+ * @param userRoleList 鐢ㄦ埛瑙掕壊鍒楄〃
+ * @return 缁撴灉
+ */
+ public int batchUserRole(List<SysUserRole> userRoleList);
+
+ /**
+ * 鍒犻櫎鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+ *
+ * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+ * @return 缁撴灉
+ */
+ public int deleteUserRoleInfo(SysUserRole userRole);
+
+ /**
+ * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteUserRoleInfos(@Param("roleId") Long roleId, @Param("userIds") Long[] userIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserMapper.java
new file mode 100644
index 0000000..0f3eafd
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/UserMapper.java
@@ -0,0 +1,15 @@
+package com.ruoyi.system.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.ruoyi.common.core.domain.entity.User;
+
+/**
+ * 鐢ㄦ埛淇℃伅琛�
+ *
+ * @author zhuo
+ * @since 2025-02-13
+ */
+public interface UserMapper extends BaseMapper<User> {
+
+}
+
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/CustomService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/CustomService.java
new file mode 100644
index 0000000..6ee01f2
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/CustomService.java
@@ -0,0 +1,28 @@
+package com.ruoyi.system.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.entity.Custom;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恥ser(鐢ㄦ埛id)銆戠殑鏁版嵁搴撴搷浣淪ervice
+* @createDate 2024骞�3鏈�7鏃�09:21:59
+*/
+public interface CustomService extends IService<Custom> {
+
+ IPage<Custom> selectCustomPageList(IPage<Custom> page, Custom custom);
+
+ int delCustomById(Long id);
+
+ int addCustom(Custom custom);
+
+ int upCustom(Custom custom);
+
+ List<Custom> selectCustomEnum();
+
+ Custom getCustomId(String company);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
new file mode 100644
index 0000000..b307776
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysConfigService.java
@@ -0,0 +1,89 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysConfig;
+
+/**
+ * 鍙傛暟閰嶇疆 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysConfigService
+{
+ /**
+ * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+ *
+ * @param configId 鍙傛暟閰嶇疆ID
+ * @return 鍙傛暟閰嶇疆淇℃伅
+ */
+ public SysConfig selectConfigById(Long configId);
+
+ /**
+ * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+ *
+ * @param configKey 鍙傛暟閿悕
+ * @return 鍙傛暟閿��
+ */
+ public String selectConfigByKey(String configKey);
+
+ /**
+ * 鑾峰彇楠岃瘉鐮佸紑鍏�
+ *
+ * @return true寮�鍚紝false鍏抽棴
+ */
+ public boolean selectCaptchaEnabled();
+
+ /**
+ * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 鍙傛暟閰嶇疆闆嗗悎
+ */
+ public List<SysConfig> selectConfigList(SysConfig config);
+
+ /**
+ * 鏂板鍙傛暟閰嶇疆
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertConfig(SysConfig config);
+
+ /**
+ * 淇敼鍙傛暟閰嶇疆
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateConfig(SysConfig config);
+
+ /**
+ * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+ *
+ * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+ */
+ public void deleteConfigByIds(Long[] configIds);
+
+ /**
+ * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
+ */
+ public void loadingConfigCache();
+
+ /**
+ * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
+ */
+ public void clearConfigCache();
+
+ /**
+ * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
+ */
+ public void resetConfigCache();
+
+ /**
+ * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
+ *
+ * @param config 鍙傛暟淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkConfigKeyUnique(SysConfig config);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
new file mode 100644
index 0000000..f228208
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDeptService.java
@@ -0,0 +1,124 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.TreeSelect;
+import com.ruoyi.common.core.domain.entity.SysDept;
+
+/**
+ * 閮ㄩ棬绠$悊 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysDeptService
+{
+ /**
+ * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 閮ㄩ棬淇℃伅闆嗗悎
+ */
+ public List<SysDept> selectDeptList(SysDept dept);
+
+ /**
+ * 鏌ヨ閮ㄩ棬鏍戠粨鏋勪俊鎭�
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 閮ㄩ棬鏍戜俊鎭泦鍚�
+ */
+ public List<TreeSelect> selectDeptTreeList(SysDept dept);
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+ *
+ * @param depts 閮ㄩ棬鍒楄〃
+ * @return 鏍戠粨鏋勫垪琛�
+ */
+ public List<SysDept> buildDeptTree(List<SysDept> depts);
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+ *
+ * @param depts 閮ㄩ棬鍒楄〃
+ * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+ */
+ public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts);
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 閫変腑閮ㄩ棬鍒楄〃
+ */
+ public List<Long> selectDeptListByRoleId(Long roleId);
+
+ /**
+ * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 閮ㄩ棬淇℃伅
+ */
+ public SysDept selectDeptById(Long deptId);
+
+ /**
+ * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 瀛愰儴闂ㄦ暟
+ */
+ public int selectNormalChildrenDeptById(Long deptId);
+
+ /**
+ * 鏄惁瀛樺湪閮ㄩ棬瀛愯妭鐐�
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public boolean hasChildByDeptId(Long deptId);
+
+ /**
+ * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+ */
+ public boolean checkDeptExistUser(Long deptId);
+
+ /**
+ * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkDeptNameUnique(SysDept dept);
+
+ /**
+ * 鏍¢獙閮ㄩ棬鏄惁鏈夋暟鎹潈闄�
+ *
+ * @param deptId 閮ㄩ棬id
+ */
+ public void checkDeptDataScope(Long deptId);
+
+ /**
+ * 鏂板淇濆瓨閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertDept(SysDept dept);
+
+ /**
+ * 淇敼淇濆瓨閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateDept(SysDept dept);
+
+ /**
+ * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ public int deleteDeptById(Long deptId);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
new file mode 100644
index 0000000..9bc4f13
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictDataService.java
@@ -0,0 +1,60 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+
+/**
+ * 瀛楀吀 涓氬姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysDictDataService
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictData 瀛楀吀鏁版嵁淇℃伅
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ public List<SysDictData> selectDictDataList(SysDictData dictData);
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param dictValue 瀛楀吀閿��
+ * @return 瀛楀吀鏍囩
+ */
+ public String selectDictLabel(String dictType, String dictValue);
+
+ /**
+ * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+ *
+ * @param dictCode 瀛楀吀鏁版嵁ID
+ * @return 瀛楀吀鏁版嵁
+ */
+ public SysDictData selectDictDataById(Long dictCode);
+
+ /**
+ * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+ */
+ public void deleteDictDataByIds(Long[] dictCodes);
+
+ /**
+ * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictData 瀛楀吀鏁版嵁淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertDictData(SysDictData dictData);
+
+ /**
+ * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictData 瀛楀吀鏁版嵁淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateDictData(SysDictData dictData);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
new file mode 100644
index 0000000..10e27a8
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysDictTypeService.java
@@ -0,0 +1,106 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+
+/**
+ * 瀛楀吀 涓氬姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysDictTypeService
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+ *
+ * @param dictType 瀛楀吀绫诲瀷淇℃伅
+ * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+ */
+ public List<SysDictType> selectDictTypeList(SysDictType dictType);
+
+ /**
+ * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+ *
+ * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+ */
+ public List<SysDictType> selectDictTypeAll();
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ public List<SysDictData> selectDictDataByType(String dictType);
+
+ /**
+ * 鏍规嵁瀛楀吀鍚嶇О鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictName 瀛楀吀鍚嶇О
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ public List<SysDictData> selectDictDataByName(String dictName);
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+ *
+ * @param dictId 瀛楀吀绫诲瀷ID
+ * @return 瀛楀吀绫诲瀷
+ */
+ public SysDictType selectDictTypeById(Long dictId);
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀绫诲瀷
+ */
+ public SysDictType selectDictTypeByType(String dictType);
+
+ /**
+ * 鎵归噺鍒犻櫎瀛楀吀淇℃伅
+ *
+ * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+ */
+ public void deleteDictTypeByIds(Long[] dictIds);
+
+ /**
+ * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
+ */
+ public void loadingDictCache();
+
+ /**
+ * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
+ */
+ public void clearDictCache();
+
+ /**
+ * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
+ */
+ public void resetDictCache();
+
+ /**
+ * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dictType 瀛楀吀绫诲瀷淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertDictType(SysDictType dictType);
+
+ /**
+ * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dictType 瀛楀吀绫诲瀷淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateDictType(SysDictType dictType);
+
+ /**
+ * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 缁撴灉
+ */
+ public boolean checkDictTypeUnique(SysDictType dictType);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
new file mode 100644
index 0000000..ce3151d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysLogininforService.java
@@ -0,0 +1,40 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysLogininfor;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysLogininforService
+{
+ /**
+ * 鏂板绯荤粺鐧诲綍鏃ュ織
+ *
+ * @param logininfor 璁块棶鏃ュ織瀵硅薄
+ */
+ public void insertLogininfor(SysLogininfor logininfor);
+
+ /**
+ * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+ *
+ * @param logininfor 璁块棶鏃ュ織瀵硅薄
+ * @return 鐧诲綍璁板綍闆嗗悎
+ */
+ public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor);
+
+ /**
+ * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+ *
+ * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteLogininforByIds(Long[] infoIds);
+
+ /**
+ * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+ */
+ public void cleanLogininfor();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
new file mode 100644
index 0000000..7d60696
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysMenuService.java
@@ -0,0 +1,144 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import java.util.Set;
+import com.ruoyi.common.core.domain.TreeSelect;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.system.domain.vo.RouterVo;
+
+/**
+ * 鑿滃崟 涓氬姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysMenuService
+{
+ /**
+ * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鑿滃崟鍒楄〃
+ */
+ public List<SysMenu> selectMenuList(Long userId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @param userId 鐢ㄦ埛ID
+ * @return 鑿滃崟鍒楄〃
+ */
+ public List<SysMenu> selectMenuList(SysMenu menu, Long userId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ public Set<String> selectMenuPermsByUserId(Long userId);
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ public Set<String> selectMenuPermsByRoleId(Long roleId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟鏍戜俊鎭�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鑿滃崟鍒楄〃
+ */
+ public List<SysMenu> selectMenuTreeByUserId(Long userId);
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 閫変腑鑿滃崟鍒楄〃
+ */
+ public List<Long> selectMenuListByRoleId(Long roleId);
+
+ /**
+ * 鏋勫缓鍓嶇璺敱鎵�闇�瑕佺殑鑿滃崟
+ *
+ * @param menus 鑿滃崟鍒楄〃
+ * @return 璺敱鍒楄〃
+ */
+ public List<RouterVo> buildMenus(List<SysMenu> menus);
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+ *
+ * @param menus 鑿滃崟鍒楄〃
+ * @return 鏍戠粨鏋勫垪琛�
+ */
+ public List<SysMenu> buildMenuTree(List<SysMenu> menus);
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+ *
+ * @param menus 鑿滃崟鍒楄〃
+ * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+ */
+ public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus);
+
+ /**
+ * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 鑿滃崟淇℃伅
+ */
+ public SysMenu selectMenuById(Long menuId);
+
+ /**
+ * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+ */
+ public boolean hasChildByMenuId(Long menuId);
+
+ /**
+ * 鏌ヨ鑿滃崟鏄惁瀛樺湪瑙掕壊
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+ */
+ public boolean checkMenuExistRole(Long menuId);
+
+ /**
+ * 鏂板淇濆瓨鑿滃崟淇℃伅
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertMenu(SysMenu menu);
+
+ /**
+ * 淇敼淇濆瓨鑿滃崟淇℃伅
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateMenu(SysMenu menu);
+
+ /**
+ * 鍒犻櫎鑿滃崟绠$悊淇℃伅
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉
+ */
+ public int deleteMenuById(Long menuId);
+
+ /**
+ * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkMenuNameUnique(SysMenu menu);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
new file mode 100644
index 0000000..47ce1b7
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysNoticeService.java
@@ -0,0 +1,60 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysNotice;
+
+/**
+ * 鍏憡 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysNoticeService
+{
+ /**
+ * 鏌ヨ鍏憡淇℃伅
+ *
+ * @param noticeId 鍏憡ID
+ * @return 鍏憡淇℃伅
+ */
+ public SysNotice selectNoticeById(Long noticeId);
+
+ /**
+ * 鏌ヨ鍏憡鍒楄〃
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 鍏憡闆嗗悎
+ */
+ public List<SysNotice> selectNoticeList(SysNotice notice);
+
+ /**
+ * 鏂板鍏憡
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertNotice(SysNotice notice);
+
+ /**
+ * 淇敼鍏憡
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateNotice(SysNotice notice);
+
+ /**
+ * 鍒犻櫎鍏憡淇℃伅
+ *
+ * @param noticeId 鍏憡ID
+ * @return 缁撴灉
+ */
+ public int deleteNoticeById(Long noticeId);
+
+ /**
+ * 鎵归噺鍒犻櫎鍏憡淇℃伅
+ *
+ * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+ * @return 缁撴灉
+ */
+ public int deleteNoticeByIds(Long[] noticeIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
new file mode 100644
index 0000000..4fd8e5a
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysOperLogService.java
@@ -0,0 +1,48 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysOperLog;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysOperLogService
+{
+ /**
+ * 鏂板鎿嶄綔鏃ュ織
+ *
+ * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+ */
+ public void insertOperlog(SysOperLog operLog);
+
+ /**
+ * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+ *
+ * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+ * @return 鎿嶄綔鏃ュ織闆嗗悎
+ */
+ public List<SysOperLog> selectOperLogList(SysOperLog operLog);
+
+ /**
+ * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+ *
+ * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+ * @return 缁撴灉
+ */
+ public int deleteOperLogByIds(Long[] operIds);
+
+ /**
+ * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+ *
+ * @param operId 鎿嶄綔ID
+ * @return 鎿嶄綔鏃ュ織瀵硅薄
+ */
+ public SysOperLog selectOperLogById(Long operId);
+
+ /**
+ * 娓呯┖鎿嶄綔鏃ュ織
+ */
+ public void cleanOperLog();
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
new file mode 100644
index 0000000..84779bf
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysPostService.java
@@ -0,0 +1,99 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.system.domain.SysPost;
+
+/**
+ * 宀椾綅淇℃伅 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysPostService
+{
+ /**
+ * 鏌ヨ宀椾綅淇℃伅闆嗗悎
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 宀椾綅鍒楄〃
+ */
+ public List<SysPost> selectPostList(SysPost post);
+
+ /**
+ * 鏌ヨ鎵�鏈夊矖浣�
+ *
+ * @return 宀椾綅鍒楄〃
+ */
+ public List<SysPost> selectPostAll();
+
+ /**
+ * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+ *
+ * @param postId 宀椾綅ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ public SysPost selectPostById(Long postId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 閫変腑宀椾綅ID鍒楄〃
+ */
+ public List<Long> selectPostListByUserId(Long userId);
+
+ /**
+ * 鏍¢獙宀椾綅鍚嶇О
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkPostNameUnique(SysPost post);
+
+ /**
+ * 鏍¢獙宀椾綅缂栫爜
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkPostCodeUnique(SysPost post);
+
+ /**
+ * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+ *
+ * @param postId 宀椾綅ID
+ * @return 缁撴灉
+ */
+ public int countUserPostById(Long postId);
+
+ /**
+ * 鍒犻櫎宀椾綅淇℃伅
+ *
+ * @param postId 宀椾綅ID
+ * @return 缁撴灉
+ */
+ public int deletePostById(Long postId);
+
+ /**
+ * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+ *
+ * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+ * @return 缁撴灉
+ */
+ public int deletePostByIds(Long[] postIds);
+
+ /**
+ * 鏂板淇濆瓨宀椾綅淇℃伅
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertPost(SysPost post);
+
+ /**
+ * 淇敼淇濆瓨宀椾綅淇℃伅
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ public int updatePost(SysPost post);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
new file mode 100644
index 0000000..9185cce
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysRoleService.java
@@ -0,0 +1,173 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import java.util.Set;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.system.domain.SysUserRole;
+
+/**
+ * 瑙掕壊涓氬姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysRoleService
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+ */
+ public List<SysRole> selectRoleList(SysRole role);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鍒楄〃
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 瑙掕壊鍒楄〃
+ */
+ public List<SysRole> selectRolesByUserId(Long userId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊鏉冮檺
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ public Set<String> selectRolePermissionByUserId(Long userId);
+
+ /**
+ * 鏌ヨ鎵�鏈夎鑹�
+ *
+ * @return 瑙掕壊鍒楄〃
+ */
+ public List<SysRole> selectRoleAll();
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 閫変腑瑙掕壊ID鍒楄〃
+ */
+ public List<Long> selectRoleListByUserId(Long userId);
+
+ /**
+ * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ public SysRole selectRoleById(Long roleId);
+
+ /**
+ * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkRoleNameUnique(SysRole role);
+
+ /**
+ * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkRoleKeyUnique(SysRole role);
+
+ /**
+ * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
+ *
+ * @param role 瑙掕壊淇℃伅
+ */
+ public void checkRoleAllowed(SysRole role);
+
+ /**
+ * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
+ *
+ * @param roleIds 瑙掕壊id
+ */
+ public void checkRoleDataScope(Long... roleIds);
+
+ /**
+ * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int countUserRoleByRoleId(Long roleId);
+
+ /**
+ * 鏂板淇濆瓨瑙掕壊淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertRole(SysRole role);
+
+ /**
+ * 淇敼淇濆瓨瑙掕壊淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateRole(SysRole role);
+
+ /**
+ * 淇敼瑙掕壊鐘舵��
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateRoleStatus(SysRole role);
+
+ /**
+ * 淇敼鏁版嵁鏉冮檺淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ public int authDataScope(SysRole role);
+
+ /**
+ * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleById(Long roleId);
+
+ /**
+ * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+ *
+ * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+ * @return 缁撴灉
+ */
+ public int deleteRoleByIds(Long[] roleIds);
+
+ /**
+ * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+ * @return 缁撴灉
+ */
+ public int deleteAuthUser(SysUserRole userRole);
+
+ /**
+ * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int deleteAuthUsers(Long roleId, Long[] userIds);
+
+ /**
+ * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛鏁版嵁ID
+ * @return 缁撴灉
+ */
+ public int insertAuthUsers(Long roleId, Long[] userIds);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java
new file mode 100644
index 0000000..8eb5448
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserOnlineService.java
@@ -0,0 +1,48 @@
+package com.ruoyi.system.service;
+
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.system.domain.SysUserOnline;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛 鏈嶅姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysUserOnlineService
+{
+ /**
+ * 閫氳繃鐧诲綍鍦板潃鏌ヨ淇℃伅
+ *
+ * @param ipaddr 鐧诲綍鍦板潃
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ */
+ public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user);
+
+ /**
+ * 閫氳繃鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+ *
+ * @param userName 鐢ㄦ埛鍚嶇О
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ */
+ public SysUserOnline selectOnlineByUserName(String userName, LoginUser user);
+
+ /**
+ * 閫氳繃鐧诲綍鍦板潃/鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+ *
+ * @param ipaddr 鐧诲綍鍦板潃
+ * @param userName 鐢ㄦ埛鍚嶇О
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ */
+ public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user);
+
+ /**
+ * 璁剧疆鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛
+ */
+ public SysUserOnline loginUserToUserOnline(LoginUser user);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
new file mode 100644
index 0000000..10bc2ab
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -0,0 +1,206 @@
+package com.ruoyi.system.service;
+
+import java.util.List;
+import com.ruoyi.common.core.domain.entity.SysUser;
+
+/**
+ * 鐢ㄦ埛 涓氬姟灞�
+ *
+ * @author ruoyi
+ */
+public interface ISysUserService
+{
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectUserList(SysUser user);
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectAllocatedList(SysUser user);
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ public List<SysUser> selectUnallocatedList(SysUser user);
+
+ /**
+ * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ public SysUser selectUserByUserName(String userName);
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ public SysUser selectUserById(Long userId);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 缁撴灉
+ */
+ public String selectUserRoleGroup(String userName);
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 缁撴灉
+ */
+ public String selectUserPostGroup(String userName);
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkUserNameUnique(SysUser user);
+
+ /**
+ * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkPhoneUnique(SysUser user);
+
+ /**
+ * 鏍¢獙email鏄惁鍞竴
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean checkEmailUnique(SysUser user);
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ */
+ public void checkUserAllowed(SysUser user);
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
+ *
+ * @param userId 鐢ㄦ埛id
+ */
+ public void checkUserDataScope(Long userId);
+
+ /**
+ * 鏂板鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int insertUser(SysUser user);
+
+ /**
+ * 娉ㄥ唽鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean registerUser(SysUser user);
+
+ /**
+ * 淇敼鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateUser(SysUser user);
+
+ /**
+ * 鐢ㄦ埛鎺堟潈瑙掕壊
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @param roleIds 瑙掕壊缁�
+ */
+ public void insertUserAuth(Long userId, Long[] roleIds);
+
+ /**
+ * 淇敼鐢ㄦ埛鐘舵��
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateUserStatus(SysUser user);
+
+ /**
+ * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int updateUserProfile(SysUser user);
+
+ /**
+ * 淇敼鐢ㄦ埛澶村儚
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param avatar 澶村儚鍦板潃
+ * @return 缁撴灉
+ */
+ public boolean updateUserAvatar(String userName, String avatar);
+
+ /**
+ * 閲嶇疆鐢ㄦ埛瀵嗙爜
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ public int resetPwd(SysUser user);
+
+ /**
+ * 閲嶇疆鐢ㄦ埛瀵嗙爜
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param password 瀵嗙爜
+ * @return 缁撴灉
+ */
+ public int resetUserPwd(String userName, String password);
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserById(Long userId);
+
+ /**
+ * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+ *
+ * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ public int deleteUserByIds(Long[] userIds);
+
+ /**
+ * 瀵煎叆鐢ㄦ埛鏁版嵁
+ *
+ * @param userList 鐢ㄦ埛鏁版嵁鍒楄〃
+ * @param isUpdateSupport 鏄惁鏇存柊鏀寔锛屽鏋滃凡瀛樺湪锛屽垯杩涜鏇存柊鏁版嵁
+ * @param operName 鎿嶄綔鐢ㄦ埛
+ * @return 缁撴灉
+ */
+ public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName);
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/UserService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/UserService.java
new file mode 100644
index 0000000..b073d56
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/UserService.java
@@ -0,0 +1,15 @@
+package com.ruoyi.system.service;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.common.core.domain.entity.User;
+
+/**
+ * 鐢ㄦ埛淇℃伅琛�
+ *
+ * @author zhuo
+ * @since 2025-02-13
+ */
+public interface UserService extends IService<User> {
+
+}
+
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomServiceImpl.java
new file mode 100644
index 0000000..44ee431
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CustomServiceImpl.java
@@ -0,0 +1,62 @@
+package com.ruoyi.system.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.Custom;
+import com.ruoyi.common.utils.QueryWrappers;
+import com.ruoyi.system.mapper.CustomMapper;
+import com.ruoyi.system.service.CustomService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+* @author Administrator
+* @description 閽堝琛ㄣ�恜ower(鐢ㄦ埛id)銆戠殑鏁版嵁搴撴搷浣淪ervice瀹炵幇
+* @createDate 2023-12-27 02:37:38
+*/
+@Service
+@AllArgsConstructor
+public class CustomServiceImpl extends ServiceImpl<CustomMapper, Custom>
+ implements CustomService {
+
+ private CustomMapper customMapper;
+
+ @Override
+ public IPage<Custom> selectCustomPageList(IPage<Custom> page, Custom custom) {
+ return customMapper.selectCustomPageList(page, QueryWrappers.queryWrappers(custom));
+ }
+
+ @Override
+ public int delCustomById(Long id) {
+ return customMapper.deleteById(id);
+ }
+
+ @Override
+ public int addCustom(Custom custom) {
+ return customMapper.insert(custom);
+ }
+
+ @Override
+ public int upCustom(Custom custom) {
+ return customMapper.updateById(custom);
+ }
+
+ @Override
+ public List<Custom> selectCustomEnum() {
+ return customMapper.selectList(Wrappers.<Custom>lambdaQuery().select(Custom::getId,Custom::getCompany));
+ }
+
+ @Override
+ public Custom getCustomId(String company) {
+ return customMapper.selectOne(Wrappers.<Custom>lambdaQuery().eq(Custom::getCompany, company).last("limit 1"));
+ }
+}
+
+
+
+
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
new file mode 100644
index 0000000..4d29b22
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysConfigServiceImpl.java
@@ -0,0 +1,232 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.Collection;
+import java.util.List;
+import javax.annotation.PostConstruct;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.annotation.DataSource;
+import com.ruoyi.common.constant.CacheConstants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.enums.DataSourceType;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysConfig;
+import com.ruoyi.system.mapper.SysConfigMapper;
+import com.ruoyi.system.service.ISysConfigService;
+
+/**
+ * 鍙傛暟閰嶇疆 鏈嶅姟灞傚疄鐜�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysConfigServiceImpl implements ISysConfigService
+{
+ @Autowired
+ private SysConfigMapper configMapper;
+
+ @Autowired
+ private RedisCache redisCache;
+
+ /**
+ * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧弬鏁板埌缂撳瓨
+ */
+ @PostConstruct
+ public void init()
+ {
+ loadingConfigCache();
+ }
+
+ /**
+ * 鏌ヨ鍙傛暟閰嶇疆淇℃伅
+ *
+ * @param configId 鍙傛暟閰嶇疆ID
+ * @return 鍙傛暟閰嶇疆淇℃伅
+ */
+ @Override
+ @DataSource(DataSourceType.MASTER)
+ public SysConfig selectConfigById(Long configId)
+ {
+ SysConfig config = new SysConfig();
+ config.setConfigId(configId);
+ return configMapper.selectConfig(config);
+ }
+
+ /**
+ * 鏍规嵁閿悕鏌ヨ鍙傛暟閰嶇疆淇℃伅
+ *
+ * @param configKey 鍙傛暟key
+ * @return 鍙傛暟閿��
+ */
+ @Override
+ public String selectConfigByKey(String configKey)
+ {
+ String configValue = Convert.toStr(redisCache.getCacheObject(getCacheKey(configKey)));
+ if (StringUtils.isNotEmpty(configValue))
+ {
+ return configValue;
+ }
+ SysConfig config = new SysConfig();
+ config.setConfigKey(configKey);
+ SysConfig retConfig = configMapper.selectConfig(config);
+ if (StringUtils.isNotNull(retConfig))
+ {
+ redisCache.setCacheObject(getCacheKey(configKey), retConfig.getConfigValue());
+ return retConfig.getConfigValue();
+ }
+ return StringUtils.EMPTY;
+ }
+
+ /**
+ * 鑾峰彇楠岃瘉鐮佸紑鍏�
+ *
+ * @return true寮�鍚紝false鍏抽棴
+ */
+ @Override
+ public boolean selectCaptchaEnabled()
+ {
+ String captchaEnabled = selectConfigByKey("sys.account.captchaEnabled");
+ if (StringUtils.isEmpty(captchaEnabled))
+ {
+ return true;
+ }
+ return Convert.toBool(captchaEnabled);
+ }
+
+ /**
+ * 鏌ヨ鍙傛暟閰嶇疆鍒楄〃
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 鍙傛暟閰嶇疆闆嗗悎
+ */
+ @Override
+ public List<SysConfig> selectConfigList(SysConfig config)
+ {
+ return configMapper.selectConfigList(config);
+ }
+
+ /**
+ * 鏂板鍙傛暟閰嶇疆
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertConfig(SysConfig config)
+ {
+ int row = configMapper.insertConfig(config);
+ if (row > 0)
+ {
+ redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+ }
+ return row;
+ }
+
+ /**
+ * 淇敼鍙傛暟閰嶇疆
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateConfig(SysConfig config)
+ {
+ SysConfig temp = configMapper.selectConfigById(config.getConfigId());
+ if (!StringUtils.equals(temp.getConfigKey(), config.getConfigKey()))
+ {
+ redisCache.deleteObject(getCacheKey(temp.getConfigKey()));
+ }
+
+ int row = configMapper.updateConfig(config);
+ if (row > 0)
+ {
+ redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+ }
+ return row;
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鍙傛暟淇℃伅
+ *
+ * @param configIds 闇�瑕佸垹闄ょ殑鍙傛暟ID
+ */
+ @Override
+ public void deleteConfigByIds(Long[] configIds)
+ {
+ for (Long configId : configIds)
+ {
+ SysConfig config = selectConfigById(configId);
+ if (StringUtils.equals(UserConstants.YES, config.getConfigType()))
+ {
+ throw new ServiceException(String.format("鍐呯疆鍙傛暟銆�%1$s銆戜笉鑳藉垹闄� ", config.getConfigKey()));
+ }
+ configMapper.deleteConfigById(configId);
+ redisCache.deleteObject(getCacheKey(config.getConfigKey()));
+ }
+ }
+
+ /**
+ * 鍔犺浇鍙傛暟缂撳瓨鏁版嵁
+ */
+ @Override
+ public void loadingConfigCache()
+ {
+ List<SysConfig> configsList = configMapper.selectConfigList(new SysConfig());
+ for (SysConfig config : configsList)
+ {
+ redisCache.setCacheObject(getCacheKey(config.getConfigKey()), config.getConfigValue());
+ }
+ }
+
+ /**
+ * 娓呯┖鍙傛暟缂撳瓨鏁版嵁
+ */
+ @Override
+ public void clearConfigCache()
+ {
+ Collection<String> keys = redisCache.keys(CacheConstants.SYS_CONFIG_KEY + "*");
+ redisCache.deleteObject(keys);
+ }
+
+ /**
+ * 閲嶇疆鍙傛暟缂撳瓨鏁版嵁
+ */
+ @Override
+ public void resetConfigCache()
+ {
+ clearConfigCache();
+ loadingConfigCache();
+ }
+
+ /**
+ * 鏍¢獙鍙傛暟閿悕鏄惁鍞竴
+ *
+ * @param config 鍙傛暟閰嶇疆淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkConfigKeyUnique(SysConfig config)
+ {
+ Long configId = StringUtils.isNull(config.getConfigId()) ? -1L : config.getConfigId();
+ SysConfig info = configMapper.checkConfigKeyUnique(config.getConfigKey());
+ if (StringUtils.isNotNull(info) && info.getConfigId().longValue() != configId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 璁剧疆cache key
+ *
+ * @param configKey 鍙傛暟閿�
+ * @return 缂撳瓨閿甼ey
+ */
+ private String getCacheKey(String configKey)
+ {
+ return CacheConstants.SYS_CONFIG_KEY + configKey;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
new file mode 100644
index 0000000..54b605d
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDeptServiceImpl.java
@@ -0,0 +1,338 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.stream.Collectors;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.TreeSelect;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.core.text.Convert;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.service.ISysDeptService;
+
+/**
+ * 閮ㄩ棬绠$悊 鏈嶅姟瀹炵幇
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysDeptServiceImpl implements ISysDeptService
+{
+ @Autowired
+ private SysDeptMapper deptMapper;
+
+ @Autowired
+ private SysRoleMapper roleMapper;
+
+ /**
+ * 鏌ヨ閮ㄩ棬绠$悊鏁版嵁
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 閮ㄩ棬淇℃伅闆嗗悎
+ */
+ @Override
+ @DataScope(deptAlias = "d")
+ public List<SysDept> selectDeptList(SysDept dept)
+ {
+ return deptMapper.selectDeptList(dept);
+ }
+
+ /**
+ * 鏌ヨ閮ㄩ棬鏍戠粨鏋勪俊鎭�
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 閮ㄩ棬鏍戜俊鎭泦鍚�
+ */
+ @Override
+ public List<TreeSelect> selectDeptTreeList(SysDept dept)
+ {
+ List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
+ return buildDeptTreeSelect(depts);
+ }
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+ *
+ * @param depts 閮ㄩ棬鍒楄〃
+ * @return 鏍戠粨鏋勫垪琛�
+ */
+ @Override
+ public List<SysDept> buildDeptTree(List<SysDept> depts)
+ {
+ List<SysDept> returnList = new ArrayList<SysDept>();
+ List<Long> tempList = depts.stream().map(SysDept::getDeptId).collect(Collectors.toList());
+ for (SysDept dept : depts)
+ {
+ // 濡傛灉鏄《绾ц妭鐐�, 閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
+ if (!tempList.contains(dept.getParentId()))
+ {
+ recursionFn(depts, dept);
+ returnList.add(dept);
+ }
+ }
+ if (returnList.isEmpty())
+ {
+ returnList = depts;
+ }
+ return returnList;
+ }
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+ *
+ * @param depts 閮ㄩ棬鍒楄〃
+ * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+ */
+ @Override
+ public List<TreeSelect> buildDeptTreeSelect(List<SysDept> depts)
+ {
+ List<SysDept> deptTrees = buildDeptTree(depts);
+ return deptTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ閮ㄩ棬鏍戜俊鎭�
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 閫変腑閮ㄩ棬鍒楄〃
+ */
+ @Override
+ public List<Long> selectDeptListByRoleId(Long roleId)
+ {
+ SysRole role = roleMapper.selectRoleById(roleId);
+ return deptMapper.selectDeptListByRoleId(roleId, role.isDeptCheckStrictly());
+ }
+
+ /**
+ * 鏍规嵁閮ㄩ棬ID鏌ヨ淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 閮ㄩ棬淇℃伅
+ */
+ @Override
+ public SysDept selectDeptById(Long deptId)
+ {
+ return deptMapper.selectDeptById(deptId);
+ }
+
+ /**
+ * 鏍规嵁ID鏌ヨ鎵�鏈夊瓙閮ㄩ棬锛堟甯哥姸鎬侊級
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 瀛愰儴闂ㄦ暟
+ */
+ @Override
+ public int selectNormalChildrenDeptById(Long deptId)
+ {
+ return deptMapper.selectNormalChildrenDeptById(deptId);
+ }
+
+ /**
+ * 鏄惁瀛樺湪瀛愯妭鐐�
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean hasChildByDeptId(Long deptId)
+ {
+ int result = deptMapper.hasChildByDeptId(deptId);
+ return result > 0;
+ }
+
+ /**
+ * 鏌ヨ閮ㄩ棬鏄惁瀛樺湪鐢ㄦ埛
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉 true 瀛樺湪 false 涓嶅瓨鍦�
+ */
+ @Override
+ public boolean checkDeptExistUser(Long deptId)
+ {
+ int result = deptMapper.checkDeptExistUser(deptId);
+ return result > 0;
+ }
+
+ /**
+ * 鏍¢獙閮ㄩ棬鍚嶇О鏄惁鍞竴
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkDeptNameUnique(SysDept dept)
+ {
+ Long deptId = StringUtils.isNull(dept.getDeptId()) ? -1L : dept.getDeptId();
+ SysDept info = deptMapper.checkDeptNameUnique(dept.getDeptName(), dept.getParentId());
+ if (StringUtils.isNotNull(info) && info.getDeptId().longValue() != deptId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鏍¢獙閮ㄩ棬鏄惁鏈夋暟鎹潈闄�
+ *
+ * @param deptId 閮ㄩ棬id
+ */
+ @Override
+ public void checkDeptDataScope(Long deptId)
+ {
+ if (!SysUser.isAdmin(SecurityUtils.getUserId()) && StringUtils.isNotNull(deptId))
+ {
+ SysDept dept = new SysDept();
+ dept.setDeptId(deptId);
+ List<SysDept> depts = SpringUtils.getAopProxy(this).selectDeptList(dept);
+ if (StringUtils.isEmpty(depts))
+ {
+ throw new ServiceException("娌℃湁鏉冮檺璁块棶閮ㄩ棬鏁版嵁锛�");
+ }
+ }
+ }
+
+ /**
+ * 鏂板淇濆瓨閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertDept(SysDept dept)
+ {
+ SysDept info = deptMapper.selectDeptById(dept.getParentId());
+ // 濡傛灉鐖惰妭鐐逛笉涓烘甯哥姸鎬�,鍒欎笉鍏佽鏂板瀛愯妭鐐�
+ if (!UserConstants.DEPT_NORMAL.equals(info.getStatus()))
+ {
+ throw new ServiceException("閮ㄩ棬鍋滅敤锛屼笉鍏佽鏂板");
+ }
+ dept.setAncestors(info.getAncestors() + "," + dept.getParentId());
+ return deptMapper.insertDept(dept);
+ }
+
+ /**
+ * 淇敼淇濆瓨閮ㄩ棬淇℃伅
+ *
+ * @param dept 閮ㄩ棬淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateDept(SysDept dept)
+ {
+ SysDept newParentDept = deptMapper.selectDeptById(dept.getParentId());
+ SysDept oldDept = deptMapper.selectDeptById(dept.getDeptId());
+ if (StringUtils.isNotNull(newParentDept) && StringUtils.isNotNull(oldDept))
+ {
+ String newAncestors = newParentDept.getAncestors() + "," + newParentDept.getDeptId();
+ String oldAncestors = oldDept.getAncestors();
+ dept.setAncestors(newAncestors);
+ updateDeptChildren(dept.getDeptId(), newAncestors, oldAncestors);
+ }
+ int result = deptMapper.updateDept(dept);
+ if (UserConstants.DEPT_NORMAL.equals(dept.getStatus()) && StringUtils.isNotEmpty(dept.getAncestors())
+ && !StringUtils.equals("0", dept.getAncestors()))
+ {
+ // 濡傛灉璇ラ儴闂ㄦ槸鍚敤鐘舵�侊紝鍒欏惎鐢ㄨ閮ㄩ棬鐨勬墍鏈変笂绾ч儴闂�
+ updateParentDeptStatusNormal(dept);
+ }
+ return result;
+ }
+
+ /**
+ * 淇敼璇ラ儴闂ㄧ殑鐖剁骇閮ㄩ棬鐘舵��
+ *
+ * @param dept 褰撳墠閮ㄩ棬
+ */
+ private void updateParentDeptStatusNormal(SysDept dept)
+ {
+ String ancestors = dept.getAncestors();
+ Long[] deptIds = Convert.toLongArray(ancestors);
+ deptMapper.updateDeptStatusNormal(deptIds);
+ }
+
+ /**
+ * 淇敼瀛愬厓绱犲叧绯�
+ *
+ * @param deptId 琚慨鏀圭殑閮ㄩ棬ID
+ * @param newAncestors 鏂扮殑鐖禝D闆嗗悎
+ * @param oldAncestors 鏃х殑鐖禝D闆嗗悎
+ */
+ public void updateDeptChildren(Long deptId, String newAncestors, String oldAncestors)
+ {
+ List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
+ for (SysDept child : children)
+ {
+ child.setAncestors(child.getAncestors().replaceFirst(oldAncestors, newAncestors));
+ }
+ if (children.size() > 0)
+ {
+ deptMapper.updateDeptChildren(children);
+ }
+ }
+
+ /**
+ * 鍒犻櫎閮ㄩ棬绠$悊淇℃伅
+ *
+ * @param deptId 閮ㄩ棬ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteDeptById(Long deptId)
+ {
+ return deptMapper.deleteDeptById(deptId);
+ }
+
+ /**
+ * 閫掑綊鍒楄〃
+ */
+ private void recursionFn(List<SysDept> list, SysDept t)
+ {
+ // 寰楀埌瀛愯妭鐐瑰垪琛�
+ List<SysDept> childList = getChildList(list, t);
+ t.setChildren(childList);
+ for (SysDept tChild : childList)
+ {
+ if (hasChild(list, tChild))
+ {
+ recursionFn(list, tChild);
+ }
+ }
+ }
+
+ /**
+ * 寰楀埌瀛愯妭鐐瑰垪琛�
+ */
+ private List<SysDept> getChildList(List<SysDept> list, SysDept t)
+ {
+ List<SysDept> tlist = new ArrayList<SysDept>();
+ Iterator<SysDept> it = list.iterator();
+ while (it.hasNext())
+ {
+ SysDept n = (SysDept) it.next();
+ if (StringUtils.isNotNull(n.getParentId()) && n.getParentId().longValue() == t.getDeptId().longValue())
+ {
+ tlist.add(n);
+ }
+ }
+ return tlist;
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁鏈夊瓙鑺傜偣
+ */
+ private boolean hasChild(List<SysDept> list, SysDept t)
+ {
+ return getChildList(list, t).size() > 0;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
new file mode 100644
index 0000000..fced569
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictDataServiceImpl.java
@@ -0,0 +1,111 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.utils.DictUtils;
+import com.ruoyi.system.mapper.SysDictDataMapper;
+import com.ruoyi.system.service.ISysDictDataService;
+
+/**
+ * 瀛楀吀 涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysDictDataServiceImpl implements ISysDictDataService
+{
+ @Autowired
+ private SysDictDataMapper dictDataMapper;
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictData 瀛楀吀鏁版嵁淇℃伅
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ @Override
+ public List<SysDictData> selectDictDataList(SysDictData dictData)
+ {
+ return dictDataMapper.selectDictDataList(dictData);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鍜屽瓧鍏搁敭鍊兼煡璇㈠瓧鍏告暟鎹俊鎭�
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @param dictValue 瀛楀吀閿��
+ * @return 瀛楀吀鏍囩
+ */
+ @Override
+ public String selectDictLabel(String dictType, String dictValue)
+ {
+ return dictDataMapper.selectDictLabel(dictType, dictValue);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀鏁版嵁ID鏌ヨ淇℃伅
+ *
+ * @param dictCode 瀛楀吀鏁版嵁ID
+ * @return 瀛楀吀鏁版嵁
+ */
+ @Override
+ public SysDictData selectDictDataById(Long dictCode)
+ {
+ return dictDataMapper.selectDictDataById(dictCode);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param dictCodes 闇�瑕佸垹闄ょ殑瀛楀吀鏁版嵁ID
+ */
+ @Override
+ public void deleteDictDataByIds(Long[] dictCodes)
+ {
+ for (Long dictCode : dictCodes)
+ {
+ SysDictData data = selectDictDataById(dictCode);
+ dictDataMapper.deleteDictDataById(dictCode);
+ List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
+ DictUtils.setDictCache(data.getDictType(), dictDatas);
+ }
+ }
+
+ /**
+ * 鏂板淇濆瓨瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param data 瀛楀吀鏁版嵁淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertDictData(SysDictData data)
+ {
+ int row = dictDataMapper.insertDictData(data);
+ if (row > 0)
+ {
+ List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
+ DictUtils.setDictCache(data.getDictType(), dictDatas);
+ }
+ return row;
+ }
+
+ /**
+ * 淇敼淇濆瓨瀛楀吀鏁版嵁淇℃伅
+ *
+ * @param data 瀛楀吀鏁版嵁淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateDictData(SysDictData data)
+ {
+ int row = dictDataMapper.updateDictData(data);
+ if (row > 0)
+ {
+ List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(data.getDictType());
+ DictUtils.setDictCache(data.getDictType(), dictDatas);
+ }
+ return row;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
new file mode 100644
index 0000000..05c999f
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysDictTypeServiceImpl.java
@@ -0,0 +1,238 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.Comparator;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.annotation.PostConstruct;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.domain.entity.SysDictType;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.DictUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.mapper.SysDictDataMapper;
+import com.ruoyi.system.mapper.SysDictTypeMapper;
+import com.ruoyi.system.service.ISysDictTypeService;
+
+/**
+ * 瀛楀吀 涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysDictTypeServiceImpl implements ISysDictTypeService
+{
+ @Autowired
+ private SysDictTypeMapper dictTypeMapper;
+
+ @Autowired
+ private SysDictDataMapper dictDataMapper;
+
+ /**
+ * 椤圭洰鍚姩鏃讹紝鍒濆鍖栧瓧鍏稿埌缂撳瓨
+ */
+ @PostConstruct
+ public void init()
+ {
+ loadingDictCache();
+ }
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瀛楀吀绫诲瀷
+ *
+ * @param dictType 瀛楀吀绫诲瀷淇℃伅
+ * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+ */
+ @Override
+ public List<SysDictType> selectDictTypeList(SysDictType dictType)
+ {
+ return dictTypeMapper.selectDictTypeList(dictType);
+ }
+
+ /**
+ * 鏍规嵁鎵�鏈夊瓧鍏哥被鍨�
+ *
+ * @return 瀛楀吀绫诲瀷闆嗗悎淇℃伅
+ */
+ @Override
+ public List<SysDictType> selectDictTypeAll()
+ {
+ return dictTypeMapper.selectDictTypeAll();
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ @Override
+ public List<SysDictData> selectDictDataByType(String dictType)
+ {
+ List<SysDictData> dictDatas = DictUtils.getDictCache(dictType);
+ if (StringUtils.isNotEmpty(dictDatas))
+ {
+ return dictDatas;
+ }
+ dictDatas = dictDataMapper.selectDictDataByType(dictType);
+ if (StringUtils.isNotEmpty(dictDatas))
+ {
+ DictUtils.setDictCache(dictType, dictDatas);
+ return dictDatas;
+ }
+ return null;
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀鍚嶇О鏌ヨ瀛楀吀鏁版嵁
+ *
+ * @param dictName 瀛楀吀鍚嶇О
+ * @return 瀛楀吀鏁版嵁闆嗗悎淇℃伅
+ */
+ @Override
+ public List<SysDictData> selectDictDataByName(String dictName)
+ {
+ List<SysDictType> sysDictTypes = dictTypeMapper.selectList(dictName);
+ return selectDictDataByType(sysDictTypes.get(0).getDictType());
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷ID鏌ヨ淇℃伅
+ *
+ * @param dictId 瀛楀吀绫诲瀷ID
+ * @return 瀛楀吀绫诲瀷
+ */
+ @Override
+ public SysDictType selectDictTypeById(Long dictId)
+ {
+ return dictTypeMapper.selectDictTypeById(dictId);
+ }
+
+ /**
+ * 鏍规嵁瀛楀吀绫诲瀷鏌ヨ淇℃伅
+ *
+ * @param dictType 瀛楀吀绫诲瀷
+ * @return 瀛楀吀绫诲瀷
+ */
+ @Override
+ public SysDictType selectDictTypeByType(String dictType)
+ {
+ return dictTypeMapper.selectDictTypeByType(dictType);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dictIds 闇�瑕佸垹闄ょ殑瀛楀吀ID
+ */
+ @Override
+ public void deleteDictTypeByIds(Long[] dictIds)
+ {
+ for (Long dictId : dictIds)
+ {
+ SysDictType dictType = selectDictTypeById(dictId);
+ if (dictDataMapper.countDictDataByType(dictType.getDictType()) > 0)
+ {
+ throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", dictType.getDictName()));
+ }
+ dictTypeMapper.deleteDictTypeById(dictId);
+ DictUtils.removeDictCache(dictType.getDictType());
+ }
+ }
+
+ /**
+ * 鍔犺浇瀛楀吀缂撳瓨鏁版嵁
+ */
+ @Override
+ public void loadingDictCache()
+ {
+ SysDictData dictData = new SysDictData();
+ dictData.setStatus("0");
+ Map<String, List<SysDictData>> dictDataMap = dictDataMapper.selectDictDataList(dictData).stream().collect(Collectors.groupingBy(SysDictData::getDictType));
+ for (Map.Entry<String, List<SysDictData>> entry : dictDataMap.entrySet())
+ {
+ DictUtils.setDictCache(entry.getKey(), entry.getValue().stream().sorted(Comparator.comparing(SysDictData::getDictSort)).collect(Collectors.toList()));
+ }
+ }
+
+ /**
+ * 娓呯┖瀛楀吀缂撳瓨鏁版嵁
+ */
+ @Override
+ public void clearDictCache()
+ {
+ DictUtils.clearDictCache();
+ }
+
+ /**
+ * 閲嶇疆瀛楀吀缂撳瓨鏁版嵁
+ */
+ @Override
+ public void resetDictCache()
+ {
+ clearDictCache();
+ loadingDictCache();
+ }
+
+ /**
+ * 鏂板淇濆瓨瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dict 瀛楀吀绫诲瀷淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertDictType(SysDictType dict)
+ {
+ int row = dictTypeMapper.insertDictType(dict);
+ if (row > 0)
+ {
+ DictUtils.setDictCache(dict.getDictType(), null);
+ }
+ return row;
+ }
+
+ /**
+ * 淇敼淇濆瓨瀛楀吀绫诲瀷淇℃伅
+ *
+ * @param dict 瀛楀吀绫诲瀷淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int updateDictType(SysDictType dict)
+ {
+ SysDictType oldDict = dictTypeMapper.selectDictTypeById(dict.getDictId());
+ dictDataMapper.updateDictDataType(oldDict.getDictType(), dict.getDictType());
+ int row = dictTypeMapper.updateDictType(dict);
+ if (row > 0)
+ {
+ List<SysDictData> dictDatas = dictDataMapper.selectDictDataByType(dict.getDictType());
+ DictUtils.setDictCache(dict.getDictType(), dictDatas);
+ }
+ return row;
+ }
+
+ /**
+ * 鏍¢獙瀛楀吀绫诲瀷绉版槸鍚﹀敮涓�
+ *
+ * @param dict 瀛楀吀绫诲瀷
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkDictTypeUnique(SysDictType dict)
+ {
+ Long dictId = StringUtils.isNull(dict.getDictId()) ? -1L : dict.getDictId();
+ SysDictType dictType = dictTypeMapper.checkDictTypeUnique(dict.getDictType());
+ if (StringUtils.isNotNull(dictType) && dictType.getDictId().longValue() != dictId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
new file mode 100644
index 0000000..216aecb
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysLogininforServiceImpl.java
@@ -0,0 +1,65 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.system.domain.SysLogininfor;
+import com.ruoyi.system.mapper.SysLogininforMapper;
+import com.ruoyi.system.service.ISysLogininforService;
+
+/**
+ * 绯荤粺璁块棶鏃ュ織鎯呭喌淇℃伅 鏈嶅姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysLogininforServiceImpl implements ISysLogininforService
+{
+
+ @Autowired
+ private SysLogininforMapper logininforMapper;
+
+ /**
+ * 鏂板绯荤粺鐧诲綍鏃ュ織
+ *
+ * @param logininfor 璁块棶鏃ュ織瀵硅薄
+ */
+ @Override
+ public void insertLogininfor(SysLogininfor logininfor)
+ {
+ logininforMapper.insertLogininfor(logininfor);
+ }
+
+ /**
+ * 鏌ヨ绯荤粺鐧诲綍鏃ュ織闆嗗悎
+ *
+ * @param logininfor 璁块棶鏃ュ織瀵硅薄
+ * @return 鐧诲綍璁板綍闆嗗悎
+ */
+ @Override
+ public List<SysLogininfor> selectLogininforList(SysLogininfor logininfor)
+ {
+ return logininforMapper.selectLogininforList(logininfor);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎绯荤粺鐧诲綍鏃ュ織
+ *
+ * @param infoIds 闇�瑕佸垹闄ょ殑鐧诲綍鏃ュ織ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteLogininforByIds(Long[] infoIds)
+ {
+ return logininforMapper.deleteLogininforByIds(infoIds);
+ }
+
+ /**
+ * 娓呯┖绯荤粺鐧诲綍鏃ュ織
+ */
+ @Override
+ public void cleanLogininfor()
+ {
+ logininforMapper.cleanLogininfor();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
new file mode 100644
index 0000000..78a7830
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysMenuServiceImpl.java
@@ -0,0 +1,543 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.Constants;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.TreeSelect;
+import com.ruoyi.common.core.domain.entity.SysMenu;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.vo.MetaVo;
+import com.ruoyi.system.domain.vo.RouterVo;
+import com.ruoyi.system.mapper.SysMenuMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysRoleMenuMapper;
+import com.ruoyi.system.service.ISysMenuService;
+
+/**
+ * 鑿滃崟 涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysMenuServiceImpl implements ISysMenuService
+{
+ public static final String PREMISSION_STRING = "perms[\"{0}\"]";
+
+ @Autowired
+ private SysMenuMapper menuMapper;
+
+ @Autowired
+ private SysRoleMapper roleMapper;
+
+ @Autowired
+ private SysRoleMenuMapper roleMenuMapper;
+
+ /**
+ * 鏍规嵁鐢ㄦ埛鏌ヨ绯荤粺鑿滃崟鍒楄〃
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鑿滃崟鍒楄〃
+ */
+ @Override
+ public List<SysMenu> selectMenuList(Long userId)
+ {
+ return selectMenuList(new SysMenu(), userId);
+ }
+
+ /**
+ * 鏌ヨ绯荤粺鑿滃崟鍒楄〃
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 鑿滃崟鍒楄〃
+ */
+ @Override
+ public List<SysMenu> selectMenuList(SysMenu menu, Long userId)
+ {
+ List<SysMenu> menuList = null;
+ // 绠$悊鍛樻樉绀烘墍鏈夎彍鍗曚俊鎭�
+ if (SysUser.isAdmin(userId))
+ {
+ menuList = menuMapper.selectMenuList(menu);
+ }
+ else
+ {
+ menu.getParams().put("userId", userId);
+ menuList = menuMapper.selectMenuListByUserId(menu);
+ }
+ return menuList;
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ @Override
+ public Set<String> selectMenuPermsByUserId(Long userId)
+ {
+ List<String> perms = menuMapper.selectMenuPermsByUserId(userId);
+ Set<String> permsSet = new HashSet<>();
+ for (String perm : perms)
+ {
+ if (StringUtils.isNotEmpty(perm))
+ {
+ permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+ }
+ }
+ return permsSet;
+ }
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ鏉冮檺
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ @Override
+ public Set<String> selectMenuPermsByRoleId(Long roleId)
+ {
+ List<String> perms = menuMapper.selectMenuPermsByRoleId(roleId);
+ Set<String> permsSet = new HashSet<>();
+ for (String perm : perms)
+ {
+ if (StringUtils.isNotEmpty(perm))
+ {
+ permsSet.addAll(Arrays.asList(perm.trim().split(",")));
+ }
+ }
+ return permsSet;
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鑿滃崟
+ *
+ * @param userId 鐢ㄦ埛鍚嶇О
+ * @return 鑿滃崟鍒楄〃
+ */
+ @Override
+ public List<SysMenu> selectMenuTreeByUserId(Long userId)
+ {
+ List<SysMenu> menus = null;
+ if (SecurityUtils.isAdmin(userId))
+ {
+ menus = menuMapper.selectMenuTreeAll();
+ }
+ else
+ {
+ menus = menuMapper.selectMenuTreeByUserId(userId);
+ }
+ return getChildPerms(menus, 0);
+ }
+
+ /**
+ * 鏍规嵁瑙掕壊ID鏌ヨ鑿滃崟鏍戜俊鎭�
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 閫変腑鑿滃崟鍒楄〃
+ */
+ @Override
+ public List<Long> selectMenuListByRoleId(Long roleId)
+ {
+ SysRole role = roleMapper.selectRoleById(roleId);
+ return menuMapper.selectMenuListByRoleId(roleId, role.isMenuCheckStrictly());
+ }
+
+ /**
+ * 鏋勫缓鍓嶇璺敱鎵�闇�瑕佺殑鑿滃崟
+ *
+ * @param menus 鑿滃崟鍒楄〃
+ * @return 璺敱鍒楄〃
+ */
+ @Override
+ public List<RouterVo> buildMenus(List<SysMenu> menus)
+ {
+ List<RouterVo> routers = new LinkedList<RouterVo>();
+ for (SysMenu menu : menus)
+ {
+ RouterVo router = new RouterVo();
+ router.setHidden("1".equals(menu.getVisible()));
+ router.setName(getRouteName(menu));
+ router.setPath(getRouterPath(menu));
+ router.setComponent(getComponent(menu));
+ router.setQuery(menu.getQuery());
+ router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+ List<SysMenu> cMenus = menu.getChildren();
+ if (StringUtils.isNotEmpty(cMenus) && UserConstants.TYPE_DIR.equals(menu.getMenuType()))
+ {
+ router.setAlwaysShow(true);
+ router.setRedirect("noRedirect");
+ router.setChildren(buildMenus(cMenus));
+ }
+ else if (isMenuFrame(menu))
+ {
+ router.setMeta(null);
+ List<RouterVo> childrenList = new ArrayList<RouterVo>();
+ RouterVo children = new RouterVo();
+ children.setPath(menu.getPath());
+ children.setComponent(menu.getComponent());
+ children.setName(getRouteName(menu.getRouteName(), menu.getPath()));
+ children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), StringUtils.equals("1", menu.getIsCache()), menu.getPath()));
+ children.setQuery(menu.getQuery());
+ childrenList.add(children);
+ router.setChildren(childrenList);
+ }
+ else if (menu.getParentId().intValue() == 0 && isInnerLink(menu))
+ {
+ router.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon()));
+ router.setPath("/");
+ List<RouterVo> childrenList = new ArrayList<RouterVo>();
+ RouterVo children = new RouterVo();
+ String routerPath = innerLinkReplaceEach(menu.getPath());
+ children.setPath(routerPath);
+ children.setComponent(UserConstants.INNER_LINK);
+ children.setName(getRouteName(menu.getRouteName(), routerPath));
+ children.setMeta(new MetaVo(menu.getMenuName(), menu.getIcon(), menu.getPath()));
+ childrenList.add(children);
+ router.setChildren(childrenList);
+ }
+ routers.add(router);
+ }
+ return routers;
+ }
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佹爲缁撴瀯
+ *
+ * @param menus 鑿滃崟鍒楄〃
+ * @return 鏍戠粨鏋勫垪琛�
+ */
+ @Override
+ public List<SysMenu> buildMenuTree(List<SysMenu> menus)
+ {
+ List<SysMenu> returnList = new ArrayList<SysMenu>();
+ List<Long> tempList = menus.stream().map(SysMenu::getMenuId).collect(Collectors.toList());
+ for (Iterator<SysMenu> iterator = menus.iterator(); iterator.hasNext();)
+ {
+ SysMenu menu = (SysMenu) iterator.next();
+ // 濡傛灉鏄《绾ц妭鐐�, 閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
+ if (!tempList.contains(menu.getParentId()))
+ {
+ recursionFn(menus, menu);
+ returnList.add(menu);
+ }
+ }
+ if (returnList.isEmpty())
+ {
+ returnList = menus;
+ }
+ return returnList;
+ }
+
+ /**
+ * 鏋勫缓鍓嶇鎵�闇�瑕佷笅鎷夋爲缁撴瀯
+ *
+ * @param menus 鑿滃崟鍒楄〃
+ * @return 涓嬫媺鏍戠粨鏋勫垪琛�
+ */
+ @Override
+ public List<TreeSelect> buildMenuTreeSelect(List<SysMenu> menus)
+ {
+ List<SysMenu> menuTrees = buildMenuTree(menus);
+ return menuTrees.stream().map(TreeSelect::new).collect(Collectors.toList());
+ }
+
+ /**
+ * 鏍规嵁鑿滃崟ID鏌ヨ淇℃伅
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 鑿滃崟淇℃伅
+ */
+ @Override
+ public SysMenu selectMenuById(Long menuId)
+ {
+ return menuMapper.selectMenuById(menuId);
+ }
+
+ /**
+ * 鏄惁瀛樺湪鑿滃崟瀛愯妭鐐�
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean hasChildByMenuId(Long menuId)
+ {
+ int result = menuMapper.hasChildByMenuId(menuId);
+ return result > 0;
+ }
+
+ /**
+ * 鏌ヨ鑿滃崟浣跨敤鏁伴噺
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkMenuExistRole(Long menuId)
+ {
+ int result = roleMenuMapper.checkMenuExistRole(menuId);
+ return result > 0;
+ }
+
+ /**
+ * 鏂板淇濆瓨鑿滃崟淇℃伅
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertMenu(SysMenu menu)
+ {
+ return menuMapper.insertMenu(menu);
+ }
+
+ /**
+ * 淇敼淇濆瓨鑿滃崟淇℃伅
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateMenu(SysMenu menu)
+ {
+ return menuMapper.updateMenu(menu);
+ }
+
+ /**
+ * 鍒犻櫎鑿滃崟绠$悊淇℃伅
+ *
+ * @param menuId 鑿滃崟ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteMenuById(Long menuId)
+ {
+ return menuMapper.deleteMenuById(menuId);
+ }
+
+ /**
+ * 鏍¢獙鑿滃崟鍚嶇О鏄惁鍞竴
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkMenuNameUnique(SysMenu menu)
+ {
+ Long menuId = StringUtils.isNull(menu.getMenuId()) ? -1L : menu.getMenuId();
+ SysMenu info = menuMapper.checkMenuNameUnique(menu.getMenuName(), menu.getParentId());
+ if (StringUtils.isNotNull(info) && info.getMenuId().longValue() != menuId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鑾峰彇璺敱鍚嶇О
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 璺敱鍚嶇О
+ */
+ public String getRouteName(SysMenu menu)
+ {
+ // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
+ if (isMenuFrame(menu))
+ {
+ return StringUtils.EMPTY;
+ }
+ return getRouteName(menu.getRouteName(), menu.getPath());
+ }
+
+ /**
+ * 鑾峰彇璺敱鍚嶇О锛屽娌℃湁閰嶇疆璺敱鍚嶇О鍒欏彇璺敱鍦板潃
+ *
+ * @param routerName 璺敱鍚嶇О
+ * @param path 璺敱鍦板潃
+ * @return 璺敱鍚嶇О锛堥┘宄版牸寮忥級
+ */
+ public String getRouteName(String name, String path)
+ {
+ String routerName = StringUtils.isNotEmpty(name) ? name : path;
+ return StringUtils.capitalize(routerName);
+ }
+
+ /**
+ * 鑾峰彇璺敱鍦板潃
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 璺敱鍦板潃
+ */
+ public String getRouterPath(SysMenu menu)
+ {
+ String routerPath = menu.getPath();
+ // 鍐呴摼鎵撳紑澶栫綉鏂瑰紡
+ if (menu.getParentId().intValue() != 0 && isInnerLink(menu))
+ {
+ routerPath = innerLinkReplaceEach(routerPath);
+ }
+ // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓虹洰褰曪級
+ if (0 == menu.getParentId().intValue() && UserConstants.TYPE_DIR.equals(menu.getMenuType())
+ && UserConstants.NO_FRAME.equals(menu.getIsFrame()))
+ {
+ routerPath = "/" + menu.getPath();
+ }
+ // 闈炲閾惧苟涓旀槸涓�绾х洰褰曪紙绫诲瀷涓鸿彍鍗曪級
+ else if (isMenuFrame(menu))
+ {
+ routerPath = "/";
+ }
+ return routerPath;
+ }
+
+ /**
+ * 鑾峰彇缁勪欢淇℃伅
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁勪欢淇℃伅
+ */
+ public String getComponent(SysMenu menu)
+ {
+ String component = UserConstants.LAYOUT;
+ if (StringUtils.isNotEmpty(menu.getComponent()) && !isMenuFrame(menu))
+ {
+ component = menu.getComponent();
+ }
+ else if (StringUtils.isEmpty(menu.getComponent()) && menu.getParentId().intValue() != 0 && isInnerLink(menu))
+ {
+ component = UserConstants.INNER_LINK;
+ }
+ else if (StringUtils.isEmpty(menu.getComponent()) && isParentView(menu))
+ {
+ component = UserConstants.PARENT_VIEW;
+ }
+ return component;
+ }
+
+ /**
+ * 鏄惁涓鸿彍鍗曞唴閮ㄨ烦杞�
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean isMenuFrame(SysMenu menu)
+ {
+ return menu.getParentId().intValue() == 0 && UserConstants.TYPE_MENU.equals(menu.getMenuType())
+ && menu.getIsFrame().equals(UserConstants.NO_FRAME);
+ }
+
+ /**
+ * 鏄惁涓哄唴閾剧粍浠�
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean isInnerLink(SysMenu menu)
+ {
+ return menu.getIsFrame().equals(UserConstants.NO_FRAME) && StringUtils.ishttp(menu.getPath());
+ }
+
+ /**
+ * 鏄惁涓簆arent_view缁勪欢
+ *
+ * @param menu 鑿滃崟淇℃伅
+ * @return 缁撴灉
+ */
+ public boolean isParentView(SysMenu menu)
+ {
+ return menu.getParentId().intValue() != 0 && UserConstants.TYPE_DIR.equals(menu.getMenuType());
+ }
+
+ /**
+ * 鏍规嵁鐖惰妭鐐圭殑ID鑾峰彇鎵�鏈夊瓙鑺傜偣
+ *
+ * @param list 鍒嗙被琛�
+ * @param parentId 浼犲叆鐨勭埗鑺傜偣ID
+ * @return String
+ */
+ public List<SysMenu> getChildPerms(List<SysMenu> list, int parentId)
+ {
+ List<SysMenu> returnList = new ArrayList<SysMenu>();
+ for (Iterator<SysMenu> iterator = list.iterator(); iterator.hasNext();)
+ {
+ SysMenu t = (SysMenu) iterator.next();
+ // 涓�銆佹牴鎹紶鍏ョ殑鏌愪釜鐖惰妭鐐笽D,閬嶅巻璇ョ埗鑺傜偣鐨勬墍鏈夊瓙鑺傜偣
+ if (t.getParentId() == parentId)
+ {
+ recursionFn(list, t);
+ returnList.add(t);
+ }
+ }
+ return returnList;
+ }
+
+ /**
+ * 閫掑綊鍒楄〃
+ *
+ * @param list 鍒嗙被琛�
+ * @param t 瀛愯妭鐐�
+ */
+ private void recursionFn(List<SysMenu> list, SysMenu t)
+ {
+ // 寰楀埌瀛愯妭鐐瑰垪琛�
+ List<SysMenu> childList = getChildList(list, t);
+ t.setChildren(childList);
+ for (SysMenu tChild : childList)
+ {
+ if (hasChild(list, tChild))
+ {
+ recursionFn(list, tChild);
+ }
+ }
+ }
+
+ /**
+ * 寰楀埌瀛愯妭鐐瑰垪琛�
+ */
+ private List<SysMenu> getChildList(List<SysMenu> list, SysMenu t)
+ {
+ List<SysMenu> tlist = new ArrayList<SysMenu>();
+ Iterator<SysMenu> it = list.iterator();
+ while (it.hasNext())
+ {
+ SysMenu n = (SysMenu) it.next();
+ if (n.getParentId().longValue() == t.getMenuId().longValue())
+ {
+ tlist.add(n);
+ }
+ }
+ return tlist;
+ }
+
+ /**
+ * 鍒ゆ柇鏄惁鏈夊瓙鑺傜偣
+ */
+ private boolean hasChild(List<SysMenu> list, SysMenu t)
+ {
+ return getChildList(list, t).size() > 0;
+ }
+
+ /**
+ * 鍐呴摼鍩熷悕鐗规畩瀛楃鏇挎崲
+ *
+ * @return 鏇挎崲鍚庣殑鍐呴摼鍩熷悕
+ */
+ public String innerLinkReplaceEach(String path)
+ {
+ return StringUtils.replaceEach(path, new String[] { Constants.HTTP, Constants.HTTPS, Constants.WWW, ".", ":" },
+ new String[] { "", "", "", "/", "/" });
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
new file mode 100644
index 0000000..765438b
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysNoticeServiceImpl.java
@@ -0,0 +1,92 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.system.domain.SysNotice;
+import com.ruoyi.system.mapper.SysNoticeMapper;
+import com.ruoyi.system.service.ISysNoticeService;
+
+/**
+ * 鍏憡 鏈嶅姟灞傚疄鐜�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysNoticeServiceImpl implements ISysNoticeService
+{
+ @Autowired
+ private SysNoticeMapper noticeMapper;
+
+ /**
+ * 鏌ヨ鍏憡淇℃伅
+ *
+ * @param noticeId 鍏憡ID
+ * @return 鍏憡淇℃伅
+ */
+ @Override
+ public SysNotice selectNoticeById(Long noticeId)
+ {
+ return noticeMapper.selectNoticeById(noticeId);
+ }
+
+ /**
+ * 鏌ヨ鍏憡鍒楄〃
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 鍏憡闆嗗悎
+ */
+ @Override
+ public List<SysNotice> selectNoticeList(SysNotice notice)
+ {
+ return noticeMapper.selectNoticeList(notice);
+ }
+
+ /**
+ * 鏂板鍏憡
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertNotice(SysNotice notice)
+ {
+ return noticeMapper.insertNotice(notice);
+ }
+
+ /**
+ * 淇敼鍏憡
+ *
+ * @param notice 鍏憡淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateNotice(SysNotice notice)
+ {
+ return noticeMapper.updateNotice(notice);
+ }
+
+ /**
+ * 鍒犻櫎鍏憡瀵硅薄
+ *
+ * @param noticeId 鍏憡ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteNoticeById(Long noticeId)
+ {
+ return noticeMapper.deleteNoticeById(noticeId);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鍏憡淇℃伅
+ *
+ * @param noticeIds 闇�瑕佸垹闄ょ殑鍏憡ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteNoticeByIds(Long[] noticeIds)
+ {
+ return noticeMapper.deleteNoticeByIds(noticeIds);
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
new file mode 100644
index 0000000..5489815
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysOperLogServiceImpl.java
@@ -0,0 +1,76 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.system.domain.SysOperLog;
+import com.ruoyi.system.mapper.SysOperLogMapper;
+import com.ruoyi.system.service.ISysOperLogService;
+
+/**
+ * 鎿嶄綔鏃ュ織 鏈嶅姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysOperLogServiceImpl implements ISysOperLogService
+{
+ @Autowired
+ private SysOperLogMapper operLogMapper;
+
+ /**
+ * 鏂板鎿嶄綔鏃ュ織
+ *
+ * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+ */
+ @Override
+ public void insertOperlog(SysOperLog operLog)
+ {
+ operLogMapper.insertOperlog(operLog);
+ }
+
+ /**
+ * 鏌ヨ绯荤粺鎿嶄綔鏃ュ織闆嗗悎
+ *
+ * @param operLog 鎿嶄綔鏃ュ織瀵硅薄
+ * @return 鎿嶄綔鏃ュ織闆嗗悎
+ */
+ @Override
+ public List<SysOperLog> selectOperLogList(SysOperLog operLog)
+ {
+ return operLogMapper.selectOperLogList(operLog);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎绯荤粺鎿嶄綔鏃ュ織
+ *
+ * @param operIds 闇�瑕佸垹闄ょ殑鎿嶄綔鏃ュ織ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteOperLogByIds(Long[] operIds)
+ {
+ return operLogMapper.deleteOperLogByIds(operIds);
+ }
+
+ /**
+ * 鏌ヨ鎿嶄綔鏃ュ織璇︾粏
+ *
+ * @param operId 鎿嶄綔ID
+ * @return 鎿嶄綔鏃ュ織瀵硅薄
+ */
+ @Override
+ public SysOperLog selectOperLogById(Long operId)
+ {
+ return operLogMapper.selectOperLogById(operId);
+ }
+
+ /**
+ * 娓呯┖鎿嶄綔鏃ュ織
+ */
+ @Override
+ public void cleanOperLog()
+ {
+ operLogMapper.cleanOperLog();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
new file mode 100644
index 0000000..5e5fe06
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysPostServiceImpl.java
@@ -0,0 +1,178 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.List;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.mapper.SysPostMapper;
+import com.ruoyi.system.mapper.SysUserPostMapper;
+import com.ruoyi.system.service.ISysPostService;
+
+/**
+ * 宀椾綅淇℃伅 鏈嶅姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysPostServiceImpl implements ISysPostService
+{
+ @Autowired
+ private SysPostMapper postMapper;
+
+ @Autowired
+ private SysUserPostMapper userPostMapper;
+
+ /**
+ * 鏌ヨ宀椾綅淇℃伅闆嗗悎
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 宀椾綅淇℃伅闆嗗悎
+ */
+ @Override
+ public List<SysPost> selectPostList(SysPost post)
+ {
+ return postMapper.selectPostList(post);
+ }
+
+ /**
+ * 鏌ヨ鎵�鏈夊矖浣�
+ *
+ * @return 宀椾綅鍒楄〃
+ */
+ @Override
+ public List<SysPost> selectPostAll()
+ {
+ return postMapper.selectPostAll();
+ }
+
+ /**
+ * 閫氳繃宀椾綅ID鏌ヨ宀椾綅淇℃伅
+ *
+ * @param postId 宀椾綅ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ @Override
+ public SysPost selectPostById(Long postId)
+ {
+ return postMapper.selectPostById(postId);
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鑾峰彇宀椾綅閫夋嫨妗嗗垪琛�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 閫変腑宀椾綅ID鍒楄〃
+ */
+ @Override
+ public List<Long> selectPostListByUserId(Long userId)
+ {
+ return postMapper.selectPostListByUserId(userId);
+ }
+
+ /**
+ * 鏍¢獙宀椾綅鍚嶇О鏄惁鍞竴
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkPostNameUnique(SysPost post)
+ {
+ Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
+ SysPost info = postMapper.checkPostNameUnique(post.getPostName());
+ if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鏍¢獙宀椾綅缂栫爜鏄惁鍞竴
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkPostCodeUnique(SysPost post)
+ {
+ Long postId = StringUtils.isNull(post.getPostId()) ? -1L : post.getPostId();
+ SysPost info = postMapper.checkPostCodeUnique(post.getPostCode());
+ if (StringUtils.isNotNull(info) && info.getPostId().longValue() != postId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 閫氳繃宀椾綅ID鏌ヨ宀椾綅浣跨敤鏁伴噺
+ *
+ * @param postId 宀椾綅ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int countUserPostById(Long postId)
+ {
+ return userPostMapper.countUserPostById(postId);
+ }
+
+ /**
+ * 鍒犻櫎宀椾綅淇℃伅
+ *
+ * @param postId 宀椾綅ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deletePostById(Long postId)
+ {
+ return postMapper.deletePostById(postId);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎宀椾綅淇℃伅
+ *
+ * @param postIds 闇�瑕佸垹闄ょ殑宀椾綅ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deletePostByIds(Long[] postIds)
+ {
+ for (Long postId : postIds)
+ {
+ SysPost post = selectPostById(postId);
+ if (countUserPostById(postId) > 0)
+ {
+ throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", post.getPostName()));
+ }
+ }
+ return postMapper.deletePostByIds(postIds);
+ }
+
+ /**
+ * 鏂板淇濆瓨宀椾綅淇℃伅
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertPost(SysPost post)
+ {
+ return postMapper.insertPost(post);
+ }
+
+ /**
+ * 淇敼淇濆瓨宀椾綅淇℃伅
+ *
+ * @param post 宀椾綅淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updatePost(SysPost post)
+ {
+ return postMapper.updatePost(post);
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
new file mode 100644
index 0000000..e432bb1
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysRoleServiceImpl.java
@@ -0,0 +1,427 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.system.domain.SysRoleDept;
+import com.ruoyi.system.domain.SysRoleMenu;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.mapper.SysRoleDeptMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysRoleMenuMapper;
+import com.ruoyi.system.mapper.SysUserRoleMapper;
+import com.ruoyi.system.service.ISysRoleService;
+
+/**
+ * 瑙掕壊 涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysRoleServiceImpl implements ISysRoleService
+{
+ @Autowired
+ private SysRoleMapper roleMapper;
+
+ @Autowired
+ private SysRoleMenuMapper roleMenuMapper;
+
+ @Autowired
+ private SysUserRoleMapper userRoleMapper;
+
+ @Autowired
+ private SysRoleDeptMapper roleDeptMapper;
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ瑙掕壊鏁版嵁
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 瑙掕壊鏁版嵁闆嗗悎淇℃伅
+ */
+ @Override
+ @DataScope(deptAlias = "d")
+ public List<SysRole> selectRoleList(SysRole role)
+ {
+ return roleMapper.selectRoleList(role);
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ瑙掕壊
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 瑙掕壊鍒楄〃
+ */
+ @Override
+ public List<SysRole> selectRolesByUserId(Long userId)
+ {
+ List<SysRole> userRoles = roleMapper.selectRolePermissionByUserId(userId);
+ List<SysRole> roles = selectRoleAll();
+ for (SysRole role : roles)
+ {
+ for (SysRole userRole : userRoles)
+ {
+ if (role.getRoleId().longValue() == userRole.getRoleId().longValue())
+ {
+ role.setFlag(true);
+ break;
+ }
+ }
+ }
+ return roles;
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鏌ヨ鏉冮檺
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鏉冮檺鍒楄〃
+ */
+ @Override
+ public Set<String> selectRolePermissionByUserId(Long userId)
+ {
+ List<SysRole> perms = roleMapper.selectRolePermissionByUserId(userId);
+ Set<String> permsSet = new HashSet<>();
+ for (SysRole perm : perms)
+ {
+ if (StringUtils.isNotNull(perm))
+ {
+ permsSet.addAll(Arrays.asList(perm.getRoleKey().trim().split(",")));
+ }
+ }
+ return permsSet;
+ }
+
+ /**
+ * 鏌ヨ鎵�鏈夎鑹�
+ *
+ * @return 瑙掕壊鍒楄〃
+ */
+ @Override
+ public List<SysRole> selectRoleAll()
+ {
+ return SpringUtils.getAopProxy(this).selectRoleList(new SysRole());
+ }
+
+ /**
+ * 鏍规嵁鐢ㄦ埛ID鑾峰彇瑙掕壊閫夋嫨妗嗗垪琛�
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 閫変腑瑙掕壊ID鍒楄〃
+ */
+ @Override
+ public List<Long> selectRoleListByUserId(Long userId)
+ {
+ return roleMapper.selectRoleListByUserId(userId);
+ }
+
+ /**
+ * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 瑙掕壊瀵硅薄淇℃伅
+ */
+ @Override
+ public SysRole selectRoleById(Long roleId)
+ {
+ return roleMapper.selectRoleById(roleId);
+ }
+
+ /**
+ * 鏍¢獙瑙掕壊鍚嶇О鏄惁鍞竴
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkRoleNameUnique(SysRole role)
+ {
+ Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+ SysRole info = roleMapper.checkRoleNameUnique(role.getRoleName());
+ if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鏍¢獙瑙掕壊鏉冮檺鏄惁鍞竴
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkRoleKeyUnique(SysRole role)
+ {
+ Long roleId = StringUtils.isNull(role.getRoleId()) ? -1L : role.getRoleId();
+ SysRole info = roleMapper.checkRoleKeyUnique(role.getRoleKey());
+ if (StringUtils.isNotNull(info) && info.getRoleId().longValue() != roleId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鏍¢獙瑙掕壊鏄惁鍏佽鎿嶄綔
+ *
+ * @param role 瑙掕壊淇℃伅
+ */
+ @Override
+ public void checkRoleAllowed(SysRole role)
+ {
+ if (StringUtils.isNotNull(role.getRoleId()) && role.isAdmin())
+ {
+ throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳瑙掕壊");
+ }
+ }
+
+ /**
+ * 鏍¢獙瑙掕壊鏄惁鏈夋暟鎹潈闄�
+ *
+ * @param roleIds 瑙掕壊id
+ */
+ @Override
+ public void checkRoleDataScope(Long... roleIds)
+ {
+ if (!SysUser.isAdmin(SecurityUtils.getUserId()))
+ {
+ for (Long roleId : roleIds)
+ {
+ SysRole role = new SysRole();
+ role.setRoleId(roleId);
+ List<SysRole> roles = SpringUtils.getAopProxy(this).selectRoleList(role);
+ if (StringUtils.isEmpty(roles))
+ {
+ throw new ServiceException("娌℃湁鏉冮檺璁块棶瑙掕壊鏁版嵁锛�");
+ }
+ }
+ }
+ }
+
+ /**
+ * 閫氳繃瑙掕壊ID鏌ヨ瑙掕壊浣跨敤鏁伴噺
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int countUserRoleByRoleId(Long roleId)
+ {
+ return userRoleMapper.countUserRoleByRoleId(roleId);
+ }
+
+ /**
+ * 鏂板淇濆瓨瑙掕壊淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int insertRole(SysRole role)
+ {
+ // 鏂板瑙掕壊淇℃伅
+ roleMapper.insertRole(role);
+ return insertRoleMenu(role);
+ }
+
+ /**
+ * 淇敼淇濆瓨瑙掕壊淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int updateRole(SysRole role)
+ {
+ // 淇敼瑙掕壊淇℃伅
+ roleMapper.updateRole(role);
+ // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+ roleMenuMapper.deleteRoleMenuByRoleId(role.getRoleId());
+ return insertRoleMenu(role);
+ }
+
+ /**
+ * 淇敼瑙掕壊鐘舵��
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateRoleStatus(SysRole role)
+ {
+ return roleMapper.updateRole(role);
+ }
+
+ /**
+ * 淇敼鏁版嵁鏉冮檺淇℃伅
+ *
+ * @param role 瑙掕壊淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int authDataScope(SysRole role)
+ {
+ // 淇敼瑙掕壊淇℃伅
+ roleMapper.updateRole(role);
+ // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+ roleDeptMapper.deleteRoleDeptByRoleId(role.getRoleId());
+ // 鏂板瑙掕壊鍜岄儴闂ㄤ俊鎭紙鏁版嵁鏉冮檺锛�
+ return insertRoleDept(role);
+ }
+
+ /**
+ * 鏂板瑙掕壊鑿滃崟淇℃伅
+ *
+ * @param role 瑙掕壊瀵硅薄
+ */
+ public int insertRoleMenu(SysRole role)
+ {
+ int rows = 1;
+ // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+ List<SysRoleMenu> list = new ArrayList<SysRoleMenu>();
+ for (Long menuId : role.getMenuIds())
+ {
+ SysRoleMenu rm = new SysRoleMenu();
+ rm.setRoleId(role.getRoleId());
+ rm.setMenuId(menuId);
+ list.add(rm);
+ }
+ if (list.size() > 0)
+ {
+ rows = roleMenuMapper.batchRoleMenu(list);
+ }
+ return rows;
+ }
+
+ /**
+ * 鏂板瑙掕壊閮ㄩ棬淇℃伅(鏁版嵁鏉冮檺)
+ *
+ * @param role 瑙掕壊瀵硅薄
+ */
+ public int insertRoleDept(SysRole role)
+ {
+ int rows = 1;
+ // 鏂板瑙掕壊涓庨儴闂紙鏁版嵁鏉冮檺锛夌鐞�
+ List<SysRoleDept> list = new ArrayList<SysRoleDept>();
+ for (Long deptId : role.getDeptIds())
+ {
+ SysRoleDept rd = new SysRoleDept();
+ rd.setRoleId(role.getRoleId());
+ rd.setDeptId(deptId);
+ list.add(rd);
+ }
+ if (list.size() > 0)
+ {
+ rows = roleDeptMapper.batchRoleDept(list);
+ }
+ return rows;
+ }
+
+ /**
+ * 閫氳繃瑙掕壊ID鍒犻櫎瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteRoleById(Long roleId)
+ {
+ // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+ roleMenuMapper.deleteRoleMenuByRoleId(roleId);
+ // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+ roleDeptMapper.deleteRoleDeptByRoleId(roleId);
+ return roleMapper.deleteRoleById(roleId);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎瑙掕壊淇℃伅
+ *
+ * @param roleIds 闇�瑕佸垹闄ょ殑瑙掕壊ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteRoleByIds(Long[] roleIds)
+ {
+ for (Long roleId : roleIds)
+ {
+ checkRoleAllowed(new SysRole(roleId));
+ checkRoleDataScope(roleId);
+ SysRole role = selectRoleById(roleId);
+ if (countUserRoleByRoleId(roleId) > 0)
+ {
+ throw new ServiceException(String.format("%1$s宸插垎閰�,涓嶈兘鍒犻櫎", role.getRoleName()));
+ }
+ }
+ // 鍒犻櫎瑙掕壊涓庤彍鍗曞叧鑱�
+ roleMenuMapper.deleteRoleMenu(roleIds);
+ // 鍒犻櫎瑙掕壊涓庨儴闂ㄥ叧鑱�
+ roleDeptMapper.deleteRoleDept(roleIds);
+ return roleMapper.deleteRoleByIds(roleIds);
+ }
+
+ /**
+ * 鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param userRole 鐢ㄦ埛鍜岃鑹插叧鑱斾俊鎭�
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteAuthUser(SysUserRole userRole)
+ {
+ return userRoleMapper.deleteUserRoleInfo(userRole);
+ }
+
+ /**
+ * 鎵归噺鍙栨秷鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @param userIds 闇�瑕佸彇娑堟巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int deleteAuthUsers(Long roleId, Long[] userIds)
+ {
+ return userRoleMapper.deleteUserRoleInfos(roleId, userIds);
+ }
+
+ /**
+ * 鎵归噺閫夋嫨鎺堟潈鐢ㄦ埛瑙掕壊
+ *
+ * @param roleId 瑙掕壊ID
+ * @param userIds 闇�瑕佹巿鏉冪殑鐢ㄦ埛鏁版嵁ID
+ * @return 缁撴灉
+ */
+ @Override
+ public int insertAuthUsers(Long roleId, Long[] userIds)
+ {
+ // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+ List<SysUserRole> list = new ArrayList<SysUserRole>();
+ for (Long userId : userIds)
+ {
+ SysUserRole ur = new SysUserRole();
+ ur.setUserId(userId);
+ ur.setRoleId(roleId);
+ list.add(ur);
+ }
+ return userRoleMapper.batchUserRole(list);
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java
new file mode 100644
index 0000000..f80a877
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserOnlineServiceImpl.java
@@ -0,0 +1,96 @@
+package com.ruoyi.system.service.impl;
+
+import org.springframework.stereotype.Service;
+import com.ruoyi.common.core.domain.model.LoginUser;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.SysUserOnline;
+import com.ruoyi.system.service.ISysUserOnlineService;
+
+/**
+ * 鍦ㄧ嚎鐢ㄦ埛 鏈嶅姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysUserOnlineServiceImpl implements ISysUserOnlineService
+{
+ /**
+ * 閫氳繃鐧诲綍鍦板潃鏌ヨ淇℃伅
+ *
+ * @param ipaddr 鐧诲綍鍦板潃
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ */
+ @Override
+ public SysUserOnline selectOnlineByIpaddr(String ipaddr, LoginUser user)
+ {
+ if (StringUtils.equals(ipaddr, user.getIpaddr()))
+ {
+ return loginUserToUserOnline(user);
+ }
+ return null;
+ }
+
+ /**
+ * 閫氳繃鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+ *
+ * @param userName 鐢ㄦ埛鍚嶇О
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ */
+ @Override
+ public SysUserOnline selectOnlineByUserName(String userName, LoginUser user)
+ {
+ if (StringUtils.equals(userName, user.getUsername()))
+ {
+ return loginUserToUserOnline(user);
+ }
+ return null;
+ }
+
+ /**
+ * 閫氳繃鐧诲綍鍦板潃/鐢ㄦ埛鍚嶇О鏌ヨ淇℃伅
+ *
+ * @param ipaddr 鐧诲綍鍦板潃
+ * @param userName 鐢ㄦ埛鍚嶇О
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ */
+ @Override
+ public SysUserOnline selectOnlineByInfo(String ipaddr, String userName, LoginUser user)
+ {
+ if (StringUtils.equals(ipaddr, user.getIpaddr()) && StringUtils.equals(userName, user.getUsername()))
+ {
+ return loginUserToUserOnline(user);
+ }
+ return null;
+ }
+
+ /**
+ * 璁剧疆鍦ㄧ嚎鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鍦ㄧ嚎鐢ㄦ埛
+ */
+ @Override
+ public SysUserOnline loginUserToUserOnline(LoginUser user)
+ {
+ if (StringUtils.isNull(user) || StringUtils.isNull(user.getUser()))
+ {
+ return null;
+ }
+ SysUserOnline sysUserOnline = new SysUserOnline();
+ sysUserOnline.setTokenId(user.getToken());
+ sysUserOnline.setUserName(user.getUsername());
+ sysUserOnline.setIpaddr(user.getIpaddr());
+ sysUserOnline.setLoginLocation(user.getLoginLocation());
+ sysUserOnline.setBrowser(user.getBrowser());
+ sysUserOnline.setOs(user.getOs());
+ sysUserOnline.setLoginTime(user.getLoginTime());
+ if (StringUtils.isNotNull(user.getUser().getDept()))
+ {
+ sysUserOnline.setDeptName(user.getUser().getDept().getDeptName());
+ }
+ return sysUserOnline;
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
new file mode 100644
index 0000000..0aa82fb
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -0,0 +1,550 @@
+package com.ruoyi.system.service.impl;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+import javax.validation.Validator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.util.CollectionUtils;
+import com.ruoyi.common.annotation.DataScope;
+import com.ruoyi.common.constant.UserConstants;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.common.utils.bean.BeanValidators;
+import com.ruoyi.common.utils.spring.SpringUtils;
+import com.ruoyi.system.domain.SysPost;
+import com.ruoyi.system.domain.SysUserPost;
+import com.ruoyi.system.domain.SysUserRole;
+import com.ruoyi.system.mapper.SysPostMapper;
+import com.ruoyi.system.mapper.SysRoleMapper;
+import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.mapper.SysUserPostMapper;
+import com.ruoyi.system.mapper.SysUserRoleMapper;
+import com.ruoyi.system.service.ISysConfigService;
+import com.ruoyi.system.service.ISysDeptService;
+import com.ruoyi.system.service.ISysUserService;
+
+/**
+ * 鐢ㄦ埛 涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ */
+@Service
+public class SysUserServiceImpl implements ISysUserService
+{
+ private static final Logger log = LoggerFactory.getLogger(SysUserServiceImpl.class);
+
+ @Autowired
+ private SysUserMapper userMapper;
+
+ @Autowired
+ private SysRoleMapper roleMapper;
+
+ @Autowired
+ private SysPostMapper postMapper;
+
+ @Autowired
+ private SysUserRoleMapper userRoleMapper;
+
+ @Autowired
+ private SysUserPostMapper userPostMapper;
+
+ @Autowired
+ private ISysConfigService configService;
+
+ @Autowired
+ private ISysDeptService deptService;
+
+ @Autowired
+ protected Validator validator;
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鐢ㄦ埛鍒楄〃
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ @Override
+ @DataScope(deptAlias = "d", userAlias = "u")
+ public List<SysUser> selectUserList(SysUser user)
+ {
+ return userMapper.selectUserList(user);
+ }
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ宸插垎閰嶇敤鎴疯鑹插垪琛�
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ @Override
+ @DataScope(deptAlias = "d", userAlias = "u")
+ public List<SysUser> selectAllocatedList(SysUser user)
+ {
+ return userMapper.selectAllocatedList(user);
+ }
+
+ /**
+ * 鏍规嵁鏉′欢鍒嗛〉鏌ヨ鏈垎閰嶇敤鎴疯鑹插垪琛�
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 鐢ㄦ埛淇℃伅闆嗗悎淇℃伅
+ */
+ @Override
+ @DataScope(deptAlias = "d", userAlias = "u")
+ public List<SysUser> selectUnallocatedList(SysUser user)
+ {
+ return userMapper.selectUnallocatedList(user);
+ }
+
+ /**
+ * 閫氳繃鐢ㄦ埛鍚嶆煡璇㈢敤鎴�
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ @Override
+ public SysUser selectUserByUserName(String userName)
+ {
+ return userMapper.selectUserByUserName(userName);
+ }
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鏌ヨ鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 鐢ㄦ埛瀵硅薄淇℃伅
+ */
+ @Override
+ public SysUser selectUserById(Long userId)
+ {
+ return userMapper.selectUserById(userId);
+ }
+
+ /**
+ * 鏌ヨ鐢ㄦ埛鎵�灞炶鑹茬粍
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 缁撴灉
+ */
+ @Override
+ public String selectUserRoleGroup(String userName)
+ {
+ List<SysRole> list = roleMapper.selectRolesByUserName(userName);
+ if (CollectionUtils.isEmpty(list))
+ {
+ return StringUtils.EMPTY;
+ }
+ return list.stream().map(SysRole::getRoleName).collect(Collectors.joining(","));
+ }
+
+ /**
+ * 鏌ヨ鐢ㄦ埛鎵�灞炲矖浣嶇粍
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @return 缁撴灉
+ */
+ @Override
+ public String selectUserPostGroup(String userName)
+ {
+ List<SysPost> list = postMapper.selectPostsByUserName(userName);
+ if (CollectionUtils.isEmpty(list))
+ {
+ return StringUtils.EMPTY;
+ }
+ return list.stream().map(SysPost::getPostName).collect(Collectors.joining(","));
+ }
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鍚嶇О鏄惁鍞竴
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean checkUserNameUnique(SysUser user)
+ {
+ Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
+ SysUser info = userMapper.checkUserNameUnique(user.getUserName());
+ if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鏍¢獙鎵嬫満鍙风爜鏄惁鍞竴
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return
+ */
+ @Override
+ public boolean checkPhoneUnique(SysUser user)
+ {
+ Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
+ SysUser info = userMapper.checkPhoneUnique(user.getPhonenumber());
+ if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鏍¢獙email鏄惁鍞竴
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return
+ */
+ @Override
+ public boolean checkEmailUnique(SysUser user)
+ {
+ Long userId = StringUtils.isNull(user.getUserId()) ? -1L : user.getUserId();
+ SysUser info = userMapper.checkEmailUnique(user.getEmail());
+ if (StringUtils.isNotNull(info) && info.getUserId().longValue() != userId.longValue())
+ {
+ return UserConstants.NOT_UNIQUE;
+ }
+ return UserConstants.UNIQUE;
+ }
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鏄惁鍏佽鎿嶄綔
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ */
+ @Override
+ public void checkUserAllowed(SysUser user)
+ {
+ if (StringUtils.isNotNull(user.getUserId()) && user.isAdmin())
+ {
+ throw new ServiceException("涓嶅厑璁告搷浣滆秴绾х鐞嗗憳鐢ㄦ埛");
+ }
+ }
+
+ /**
+ * 鏍¢獙鐢ㄦ埛鏄惁鏈夋暟鎹潈闄�
+ *
+ * @param userId 鐢ㄦ埛id
+ */
+ @Override
+ public void checkUserDataScope(Long userId)
+ {
+ if (!SysUser.isAdmin(SecurityUtils.getUserId()))
+ {
+ SysUser user = new SysUser();
+ user.setUserId(userId);
+ List<SysUser> users = SpringUtils.getAopProxy(this).selectUserList(user);
+ if (StringUtils.isEmpty(users))
+ {
+ throw new ServiceException("娌℃湁鏉冮檺璁块棶鐢ㄦ埛鏁版嵁锛�");
+ }
+ }
+ }
+
+ /**
+ * 鏂板淇濆瓨鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int insertUser(SysUser user)
+ {
+ // 鏂板鐢ㄦ埛淇℃伅
+ int rows = userMapper.insertUser(user);
+ // 鏂板鐢ㄦ埛宀椾綅鍏宠仈
+ insertUserPost(user);
+ // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+ insertUserRole(user);
+ return rows;
+ }
+
+ /**
+ * 娉ㄥ唽鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean registerUser(SysUser user)
+ {
+ return userMapper.insertUser(user) > 0;
+ }
+
+ /**
+ * 淇敼淇濆瓨鐢ㄦ埛淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int updateUser(SysUser user)
+ {
+ Long userId = user.getUserId();
+ // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+ userRoleMapper.deleteUserRoleByUserId(userId);
+ // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+ insertUserRole(user);
+ // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶅叧鑱�
+ userPostMapper.deleteUserPostByUserId(userId);
+ // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
+ insertUserPost(user);
+ return userMapper.updateUser(user);
+ }
+
+ /**
+ * 鐢ㄦ埛鎺堟潈瑙掕壊
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @param roleIds 瑙掕壊缁�
+ */
+ @Override
+ @Transactional
+ public void insertUserAuth(Long userId, Long[] roleIds)
+ {
+ userRoleMapper.deleteUserRoleByUserId(userId);
+ insertUserRole(userId, roleIds);
+ }
+
+ /**
+ * 淇敼鐢ㄦ埛鐘舵��
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateUserStatus(SysUser user)
+ {
+ return userMapper.updateUser(user);
+ }
+
+ /**
+ * 淇敼鐢ㄦ埛鍩烘湰淇℃伅
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int updateUserProfile(SysUser user)
+ {
+ return userMapper.updateUser(user);
+ }
+
+ /**
+ * 淇敼鐢ㄦ埛澶村儚
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param avatar 澶村儚鍦板潃
+ * @return 缁撴灉
+ */
+ @Override
+ public boolean updateUserAvatar(String userName, String avatar)
+ {
+ return userMapper.updateUserAvatar(userName, avatar) > 0;
+ }
+
+ /**
+ * 閲嶇疆鐢ㄦ埛瀵嗙爜
+ *
+ * @param user 鐢ㄦ埛淇℃伅
+ * @return 缁撴灉
+ */
+ @Override
+ public int resetPwd(SysUser user)
+ {
+ return userMapper.updateUser(user);
+ }
+
+ /**
+ * 閲嶇疆鐢ㄦ埛瀵嗙爜
+ *
+ * @param userName 鐢ㄦ埛鍚�
+ * @param password 瀵嗙爜
+ * @return 缁撴灉
+ */
+ @Override
+ public int resetUserPwd(String userName, String password)
+ {
+ return userMapper.resetUserPwd(userName, password);
+ }
+
+ /**
+ * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
+ *
+ * @param user 鐢ㄦ埛瀵硅薄
+ */
+ public void insertUserRole(SysUser user)
+ {
+ this.insertUserRole(user.getUserId(), user.getRoleIds());
+ }
+
+ /**
+ * 鏂板鐢ㄦ埛宀椾綅淇℃伅
+ *
+ * @param user 鐢ㄦ埛瀵硅薄
+ */
+ public void insertUserPost(SysUser user)
+ {
+ Long[] posts = user.getPostIds();
+ if (StringUtils.isNotEmpty(posts))
+ {
+ // 鏂板鐢ㄦ埛涓庡矖浣嶇鐞�
+ List<SysUserPost> list = new ArrayList<SysUserPost>(posts.length);
+ for (Long postId : posts)
+ {
+ SysUserPost up = new SysUserPost();
+ up.setUserId(user.getUserId());
+ up.setPostId(postId);
+ list.add(up);
+ }
+ userPostMapper.batchUserPost(list);
+ }
+ }
+
+ /**
+ * 鏂板鐢ㄦ埛瑙掕壊淇℃伅
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @param roleIds 瑙掕壊缁�
+ */
+ public void insertUserRole(Long userId, Long[] roleIds)
+ {
+ if (StringUtils.isNotEmpty(roleIds))
+ {
+ // 鏂板鐢ㄦ埛涓庤鑹茬鐞�
+ List<SysUserRole> list = new ArrayList<SysUserRole>(roleIds.length);
+ for (Long roleId : roleIds)
+ {
+ SysUserRole ur = new SysUserRole();
+ ur.setUserId(userId);
+ ur.setRoleId(roleId);
+ list.add(ur);
+ }
+ userRoleMapper.batchUserRole(list);
+ }
+ }
+
+ /**
+ * 閫氳繃鐢ㄦ埛ID鍒犻櫎鐢ㄦ埛
+ *
+ * @param userId 鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteUserById(Long userId)
+ {
+ // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+ userRoleMapper.deleteUserRoleByUserId(userId);
+ // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶈〃
+ userPostMapper.deleteUserPostByUserId(userId);
+ return userMapper.deleteUserById(userId);
+ }
+
+ /**
+ * 鎵归噺鍒犻櫎鐢ㄦ埛淇℃伅
+ *
+ * @param userIds 闇�瑕佸垹闄ょ殑鐢ㄦ埛ID
+ * @return 缁撴灉
+ */
+ @Override
+ @Transactional
+ public int deleteUserByIds(Long[] userIds)
+ {
+ for (Long userId : userIds)
+ {
+ checkUserAllowed(new SysUser(userId));
+ checkUserDataScope(userId);
+ }
+ // 鍒犻櫎鐢ㄦ埛涓庤鑹插叧鑱�
+ userRoleMapper.deleteUserRole(userIds);
+ // 鍒犻櫎鐢ㄦ埛涓庡矖浣嶅叧鑱�
+ userPostMapper.deleteUserPost(userIds);
+ return userMapper.deleteUserByIds(userIds);
+ }
+
+ /**
+ * 瀵煎叆鐢ㄦ埛鏁版嵁
+ *
+ * @param userList 鐢ㄦ埛鏁版嵁鍒楄〃
+ * @param isUpdateSupport 鏄惁鏇存柊鏀寔锛屽鏋滃凡瀛樺湪锛屽垯杩涜鏇存柊鏁版嵁
+ * @param operName 鎿嶄綔鐢ㄦ埛
+ * @return 缁撴灉
+ */
+ @Override
+ public String importUser(List<SysUser> userList, Boolean isUpdateSupport, String operName)
+ {
+ if (StringUtils.isNull(userList) || userList.size() == 0)
+ {
+ throw new ServiceException("瀵煎叆鐢ㄦ埛鏁版嵁涓嶈兘涓虹┖锛�");
+ }
+ int successNum = 0;
+ int failureNum = 0;
+ StringBuilder successMsg = new StringBuilder();
+ StringBuilder failureMsg = new StringBuilder();
+ for (SysUser user : userList)
+ {
+ try
+ {
+ // 楠岃瘉鏄惁瀛樺湪杩欎釜鐢ㄦ埛
+ SysUser u = userMapper.selectUserByUserName(user.getUserName());
+ if (StringUtils.isNull(u))
+ {
+ BeanValidators.validateWithException(validator, user);
+ deptService.checkDeptDataScope(user.getDeptId());
+ String password = configService.selectConfigByKey("sys.user.initPassword");
+ user.setPassword(SecurityUtils.encryptPassword(password));
+ user.setCreateBy(operName);
+ userMapper.insertUser(user);
+ successNum++;
+ successMsg.append("<br/>" + successNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆鎴愬姛");
+ }
+ else if (isUpdateSupport)
+ {
+ BeanValidators.validateWithException(validator, user);
+ checkUserAllowed(u);
+ checkUserDataScope(u.getUserId());
+ deptService.checkDeptDataScope(user.getDeptId());
+ user.setUserId(u.getUserId());
+ user.setUpdateBy(operName);
+ userMapper.updateUser(user);
+ successNum++;
+ successMsg.append("<br/>" + successNum + "銆佽处鍙� " + user.getUserName() + " 鏇存柊鎴愬姛");
+ }
+ else
+ {
+ failureNum++;
+ failureMsg.append("<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 宸插瓨鍦�");
+ }
+ }
+ catch (Exception e)
+ {
+ failureNum++;
+ String msg = "<br/>" + failureNum + "銆佽处鍙� " + user.getUserName() + " 瀵煎叆澶辫触锛�";
+ failureMsg.append(msg + e.getMessage());
+ log.error(msg, e);
+ }
+ }
+ if (failureNum > 0)
+ {
+ failureMsg.insert(0, "寰堟姳姝夛紝瀵煎叆澶辫触锛佸叡 " + failureNum + " 鏉℃暟鎹牸寮忎笉姝g‘锛岄敊璇涓嬶細");
+ throw new ServiceException(failureMsg.toString());
+ }
+ else
+ {
+ successMsg.insert(0, "鎭枩鎮紝鏁版嵁宸插叏閮ㄥ鍏ユ垚鍔燂紒鍏� " + successNum + " 鏉★紝鏁版嵁濡備笅锛�");
+ }
+ return successMsg.toString();
+ }
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserServiceImpl.java
new file mode 100644
index 0000000..acc052e
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/UserServiceImpl.java
@@ -0,0 +1,19 @@
+package com.ruoyi.system.service.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.User;
+import com.ruoyi.system.mapper.UserMapper;
+import com.ruoyi.system.service.UserService;
+import org.springframework.stereotype.Service;
+
+/**
+ * 鐢ㄦ埛淇℃伅琛�
+ *
+ * @author zhuo
+ * @since 2025-02-13
+ */
+@Service
+public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
+
+}
+
diff --git a/ruoyi-system/src/main/resources/mapper/system/CustomMapper.xml b/ruoyi-system/src/main/resources/mapper/system/CustomMapper.xml
new file mode 100644
index 0000000..b4f43ed
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/CustomMapper.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
+<mapper namespace="com.ruoyi.system.mapper.CustomMapper">
+ <update id="delCustomById">
+ update user set is_custom = 0
+ where id = #{id}
+ </update>
+ <select id="selectCustomPageList" resultType="com.ruoyi.common.core.domain.entity.Custom">
+ select * from custom
+ <if test="ew.customSqlSegment != null and ew.customSqlSegment != ''">
+ ${ew.customSqlSegment}
+ </if>
+ </select>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml
new file mode 100644
index 0000000..a5ff114
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysConfigMapper.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysConfigMapper">
+
+ <resultMap type="SysConfig" id="SysConfigResult">
+ <id property="configId" column="config_id" />
+ <result property="configName" column="config_name" />
+ <result property="configKey" column="config_key" />
+ <result property="configValue" column="config_value" />
+ <result property="configType" column="config_type" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectConfigVo">
+ select config_id, config_name, config_key, config_value, config_type, create_by, create_time, update_by, update_time, remark
+ from sys_config
+ </sql>
+
+ <!-- 鏌ヨ鏉′欢 -->
+ <sql id="sqlwhereSearch">
+ <where>
+ <if test="configId !=null">
+ and config_id = #{configId}
+ </if>
+ <if test="configKey !=null and configKey != ''">
+ and config_key = #{configKey}
+ </if>
+ </where>
+ </sql>
+
+ <select id="selectConfig" parameterType="SysConfig" resultMap="SysConfigResult">
+ <include refid="selectConfigVo"/>
+ <include refid="sqlwhereSearch"/>
+ </select>
+
+ <select id="selectConfigList" parameterType="SysConfig" resultMap="SysConfigResult">
+ <include refid="selectConfigVo"/>
+ <where>
+ <if test="configName != null and configName != ''">
+ AND config_name like concat('%', #{configName}, '%')
+ </if>
+ <if test="configType != null and configType != ''">
+ AND config_type = #{configType}
+ </if>
+ <if test="configKey != null and configKey != ''">
+ AND config_key like concat('%', #{configKey}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ and date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ and date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ </if>
+ </where>
+ </select>
+
+ <select id="selectConfigById" parameterType="Long" resultMap="SysConfigResult">
+ <include refid="selectConfigVo"/>
+ where config_id = #{configId}
+ </select>
+
+ <select id="checkConfigKeyUnique" parameterType="String" resultMap="SysConfigResult">
+ <include refid="selectConfigVo"/>
+ where config_key = #{configKey} limit 1
+ </select>
+
+ <insert id="insertConfig" parameterType="SysConfig">
+ insert into sys_config (
+ <if test="configName != null and configName != '' ">config_name,</if>
+ <if test="configKey != null and configKey != '' ">config_key,</if>
+ <if test="configValue != null and configValue != '' ">config_value,</if>
+ <if test="configType != null and configType != '' ">config_type,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ create_time
+ )values(
+ <if test="configName != null and configName != ''">#{configName},</if>
+ <if test="configKey != null and configKey != ''">#{configKey},</if>
+ <if test="configValue != null and configValue != ''">#{configValue},</if>
+ <if test="configType != null and configType != ''">#{configType},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="updateConfig" parameterType="SysConfig">
+ update sys_config
+ <set>
+ <if test="configName != null and configName != ''">config_name = #{configName},</if>
+ <if test="configKey != null and configKey != ''">config_key = #{configKey},</if>
+ <if test="configValue != null and configValue != ''">config_value = #{configValue},</if>
+ <if test="configType != null and configType != ''">config_type = #{configType},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ update_time = sysdate()
+ </set>
+ where config_id = #{configId}
+ </update>
+
+ <delete id="deleteConfigById" parameterType="Long">
+ delete from sys_config where config_id = #{configId}
+ </delete>
+
+ <delete id="deleteConfigByIds" parameterType="Long">
+ delete from sys_config where config_id in
+ <foreach item="configId" collection="array" open="(" separator="," close=")">
+ #{configId}
+ </foreach>
+ </delete>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
new file mode 100644
index 0000000..a77ee54
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysDeptMapper">
+
+ <resultMap type="SysDept" id="SysDeptResult">
+ <id property="deptId" column="dept_id" />
+ <result property="parentId" column="parent_id" />
+ <result property="ancestors" column="ancestors" />
+ <result property="deptName" column="dept_name" />
+ <result property="orderNum" column="order_num" />
+ <result property="leader" column="leader" />
+ <result property="phone" column="phone" />
+ <result property="email" column="email" />
+ <result property="status" column="status" />
+ <result property="delFlag" column="del_flag" />
+ <result property="parentName" column="parent_name" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectDeptVo">
+ select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status, d.del_flag, d.create_by, d.create_time
+ from sys_dept d
+ </sql>
+
+ <select id="selectDeptList" parameterType="SysDept" resultMap="SysDeptResult">
+ <include refid="selectDeptVo"/>
+ where d.del_flag = '0'
+ <if test="deptId != null and deptId != 0">
+ AND dept_id = #{deptId}
+ </if>
+ <if test="parentId != null and parentId != 0">
+ AND parent_id = #{parentId}
+ </if>
+ <if test="deptName != null and deptName != ''">
+ AND dept_name like concat('%', #{deptName}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ order by d.parent_id, d.order_num
+ </select>
+
+ <select id="selectDeptListByRoleId" resultType="Long">
+ select d.dept_id
+ from sys_dept d
+ left join sys_role_dept rd on d.dept_id = rd.dept_id
+ where rd.role_id = #{roleId}
+ <if test="deptCheckStrictly">
+ and d.dept_id not in (select d.parent_id from sys_dept d inner join sys_role_dept rd on d.dept_id = rd.dept_id and rd.role_id = #{roleId})
+ </if>
+ order by d.parent_id, d.order_num
+ </select>
+
+ <select id="selectDeptById" parameterType="Long" resultMap="SysDeptResult">
+ select d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.phone, d.email, d.status,
+ (select dept_name from sys_dept where dept_id = d.parent_id) parent_name
+ from sys_dept d
+ where d.dept_id = #{deptId}
+ </select>
+
+ <select id="checkDeptExistUser" parameterType="Long" resultType="int">
+ select count(1) from user where dept_id = #{deptId} and del_flag = '0'
+ </select>
+
+ <select id="hasChildByDeptId" parameterType="Long" resultType="int">
+ select count(1) from sys_dept
+ where del_flag = '0' and parent_id = #{deptId} limit 1
+ </select>
+
+ <select id="selectChildrenDeptById" parameterType="Long" resultMap="SysDeptResult">
+ select * from sys_dept where find_in_set(#{deptId}, ancestors)
+ </select>
+
+ <select id="selectNormalChildrenDeptById" parameterType="Long" resultType="int">
+ select count(*) from sys_dept where status = 0 and del_flag = '0' and find_in_set(#{deptId}, ancestors)
+ </select>
+
+ <select id="checkDeptNameUnique" resultMap="SysDeptResult">
+ <include refid="selectDeptVo"/>
+ where dept_name=#{deptName} and parent_id = #{parentId} and del_flag = '0' limit 1
+ </select>
+
+ <insert id="insertDept" parameterType="SysDept">
+ insert into sys_dept(
+ <if test="deptId != null and deptId != 0">dept_id,</if>
+ <if test="parentId != null and parentId != 0">parent_id,</if>
+ <if test="deptName != null and deptName != ''">dept_name,</if>
+ <if test="ancestors != null and ancestors != ''">ancestors,</if>
+ <if test="orderNum != null">order_num,</if>
+ <if test="leader != null and leader != ''">leader,</if>
+ <if test="phone != null and phone != ''">phone,</if>
+ <if test="email != null and email != ''">email,</if>
+ <if test="status != null">status,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="deptId != null and deptId != 0">#{deptId},</if>
+ <if test="parentId != null and parentId != 0">#{parentId},</if>
+ <if test="deptName != null and deptName != ''">#{deptName},</if>
+ <if test="ancestors != null and ancestors != ''">#{ancestors},</if>
+ <if test="orderNum != null">#{orderNum},</if>
+ <if test="leader != null and leader != ''">#{leader},</if>
+ <if test="phone != null and phone != ''">#{phone},</if>
+ <if test="email != null and email != ''">#{email},</if>
+ <if test="status != null">#{status},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="updateDept" parameterType="SysDept">
+ update sys_dept
+ <set>
+ <if test="parentId != null and parentId != 0">parent_id = #{parentId},</if>
+ <if test="deptName != null and deptName != ''">dept_name = #{deptName},</if>
+ <if test="ancestors != null and ancestors != ''">ancestors = #{ancestors},</if>
+ <if test="orderNum != null">order_num = #{orderNum},</if>
+ <if test="leader != null">leader = #{leader},</if>
+ <if test="phone != null">phone = #{phone},</if>
+ <if test="email != null">email = #{email},</if>
+ <if test="status != null and status != ''">status = #{status},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where dept_id = #{deptId}
+ </update>
+
+ <update id="updateDeptChildren" parameterType="java.util.List">
+ update sys_dept set ancestors =
+ <foreach collection="depts" item="item" index="index"
+ separator=" " open="case dept_id" close="end">
+ when #{item.deptId} then #{item.ancestors}
+ </foreach>
+ where dept_id in
+ <foreach collection="depts" item="item" index="index"
+ separator="," open="(" close=")">
+ #{item.deptId}
+ </foreach>
+ </update>
+
+ <update id="updateDeptStatusNormal" parameterType="Long">
+ update sys_dept set status = '0' where dept_id in
+ <foreach collection="array" item="deptId" open="(" separator="," close=")">
+ #{deptId}
+ </foreach>
+ </update>
+
+ <delete id="deleteDeptById" parameterType="Long">
+ update sys_dept set del_flag = '2' where dept_id = #{deptId}
+ </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
new file mode 100644
index 0000000..3b94b7f
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDictDataMapper.xml
@@ -0,0 +1,124 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysDictDataMapper">
+
+ <resultMap type="SysDictData" id="SysDictDataResult">
+ <id property="dictCode" column="dict_code" />
+ <result property="dictSort" column="dict_sort" />
+ <result property="dictLabel" column="dict_label" />
+ <result property="dictValue" column="dict_value" />
+ <result property="dictType" column="dict_type" />
+ <result property="cssClass" column="css_class" />
+ <result property="listClass" column="list_class" />
+ <result property="isDefault" column="is_default" />
+ <result property="status" column="status" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ </resultMap>
+
+ <sql id="selectDictDataVo">
+ select dict_code, dict_sort, dict_label, dict_value, dict_type, css_class, list_class, is_default, status, create_by, create_time, remark
+ from sys_dict_data
+ </sql>
+
+ <select id="selectDictDataList" parameterType="SysDictData" resultMap="SysDictDataResult">
+ <include refid="selectDictDataVo"/>
+ <where>
+ <if test="dictType != null and dictType != ''">
+ AND dict_type = #{dictType}
+ </if>
+ <if test="dictLabel != null and dictLabel != ''">
+ AND dict_label like concat('%', #{dictLabel}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ </where>
+ order by dict_sort asc
+ </select>
+
+ <select id="selectDictDataByType" parameterType="String" resultMap="SysDictDataResult">
+ <include refid="selectDictDataVo"/>
+ where status = '0' and dict_type = #{dictType} order by dict_sort asc
+ </select>
+
+ <select id="selectDictLabel" resultType="String">
+ select dict_label from sys_dict_data
+ where dict_type = #{dictType} and dict_value = #{dictValue}
+ </select>
+
+ <select id="selectDictDataById" parameterType="Long" resultMap="SysDictDataResult">
+ <include refid="selectDictDataVo"/>
+ where dict_code = #{dictCode}
+ </select>
+
+ <select id="countDictDataByType" resultType="Integer">
+ select count(1) from sys_dict_data where dict_type=#{dictType}
+ </select>
+
+ <delete id="deleteDictDataById" parameterType="Long">
+ delete from sys_dict_data where dict_code = #{dictCode}
+ </delete>
+
+ <delete id="deleteDictDataByIds" parameterType="Long">
+ delete from sys_dict_data where dict_code in
+ <foreach collection="array" item="dictCode" open="(" separator="," close=")">
+ #{dictCode}
+ </foreach>
+ </delete>
+
+ <update id="updateDictData" parameterType="SysDictData">
+ update sys_dict_data
+ <set>
+ <if test="dictSort != null">dict_sort = #{dictSort},</if>
+ <if test="dictLabel != null and dictLabel != ''">dict_label = #{dictLabel},</if>
+ <if test="dictValue != null and dictValue != ''">dict_value = #{dictValue},</if>
+ <if test="dictType != null and dictType != ''">dict_type = #{dictType},</if>
+ <if test="cssClass != null">css_class = #{cssClass},</if>
+ <if test="listClass != null">list_class = #{listClass},</if>
+ <if test="isDefault != null and isDefault != ''">is_default = #{isDefault},</if>
+ <if test="status != null">status = #{status},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where dict_code = #{dictCode}
+ </update>
+
+ <update id="updateDictDataType" parameterType="String">
+ update sys_dict_data set dict_type = #{newDictType} where dict_type = #{oldDictType}
+ </update>
+
+ <insert id="insertDictData" parameterType="SysDictData">
+ insert into sys_dict_data(
+ <if test="dictSort != null">dict_sort,</if>
+ <if test="dictLabel != null and dictLabel != ''">dict_label,</if>
+ <if test="dictValue != null and dictValue != ''">dict_value,</if>
+ <if test="dictType != null and dictType != ''">dict_type,</if>
+ <if test="cssClass != null and cssClass != ''">css_class,</if>
+ <if test="listClass != null and listClass != ''">list_class,</if>
+ <if test="isDefault != null and isDefault != ''">is_default,</if>
+ <if test="status != null">status,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="dictSort != null">#{dictSort},</if>
+ <if test="dictLabel != null and dictLabel != ''">#{dictLabel},</if>
+ <if test="dictValue != null and dictValue != ''">#{dictValue},</if>
+ <if test="dictType != null and dictType != ''">#{dictType},</if>
+ <if test="cssClass != null and cssClass != ''">#{cssClass},</if>
+ <if test="listClass != null and listClass != ''">#{listClass},</if>
+ <if test="isDefault != null and isDefault != ''">#{isDefault},</if>
+ <if test="status != null">#{status},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
new file mode 100644
index 0000000..5288fa9
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDictTypeMapper.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysDictTypeMapper">
+ <resultMap type="SysDictType" id="SysDictTypeResult">
+ <id property="dictId" column="dict_id"/>
+ <result property="dictName" column="dict_name"/>
+ <result property="dictType" column="dict_type"/>
+ <result property="status" column="status"/>
+ <result property="createBy" column="create_by"/>
+ <result property="createTime" column="create_time"/>
+ <result property="updateBy" column="update_by"/>
+ <result property="updateTime" column="update_time"/>
+ </resultMap>
+
+ <sql id="selectDictTypeVo">
+ select dict_id, dict_name, dict_type, status, create_by, create_time, remark
+ from sys_dict_type
+ </sql>
+
+ <select id="selectDictTypeList" parameterType="SysDictType" resultMap="SysDictTypeResult">
+ <include refid="selectDictTypeVo"/>
+ <where>
+ <if test="dictName != null and dictName != ''">
+ AND dict_name like concat('%', #{dictName}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="dictType != null and dictType != ''">
+ AND dict_type like concat('%', #{dictType}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''">
+ <!-- 寮�濮嬫椂闂存绱� -->
+ and date_format(create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''">
+ <!-- 缁撴潫鏃堕棿妫�绱� -->
+ and date_format(create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ </if>
+ </where>
+ </select>
+
+ <select id="selectDictTypeAll" resultMap="SysDictTypeResult">
+ <include refid="selectDictTypeVo"/>
+ </select>
+
+ <select id="selectDictTypeById" parameterType="Long" resultMap="SysDictTypeResult">
+ <include refid="selectDictTypeVo"/>
+ where dict_id = #{dictId}
+ </select>
+
+ <select id="selectDictTypeByType" parameterType="String" resultMap="SysDictTypeResult">
+ <include refid="selectDictTypeVo"/>
+ where dict_type = #{dictType}
+ </select>
+
+ <select id="checkDictTypeUnique" parameterType="String" resultMap="SysDictTypeResult">
+ <include refid="selectDictTypeVo"/>
+ where dict_type = #{dictType} limit 1
+ </select>
+
+ <delete id="deleteDictTypeById" parameterType="Long">
+ delete
+ from sys_dict_type
+ where dict_id = #{dictId}
+ </delete>
+
+ <delete id="deleteDictTypeByIds" parameterType="Long">
+ delete from sys_dict_type where dict_id in
+ <foreach collection="array" item="dictId" open="(" separator="," close=")">
+ #{dictId}
+ </foreach>
+ </delete>
+
+ <update id="updateDictType" parameterType="SysDictType">
+ update sys_dict_type
+ <set>
+ <if test="dictName != null and dictName != ''">
+ dict_name = #{dictName},
+ </if>
+ <if test="dictType != null and dictType != ''">
+ dict_type = #{dictType},
+ </if>
+ <if test="status != null">
+ status = #{status},
+ </if>
+ <if test="remark != null">
+ remark = #{remark},
+ </if>
+ <if test="updateBy != null and updateBy != ''">
+ update_by = #{updateBy},
+ </if>
+ update_time = sysdate()
+ </set>
+ where dict_id = #{dictId}
+ </update>
+
+ <insert id="insertDictType" parameterType="SysDictType">
+ insert into sys_dict_type(
+ <if test="dictName != null and dictName != ''">
+ dict_name,
+ </if>
+ <if test="dictType != null and dictType != ''">
+ dict_type,
+ </if>
+ <if test="status != null">
+ status,
+ </if>
+ <if test="remark != null and remark != ''">
+ remark,
+ </if>
+ <if test="createBy != null and createBy != ''">
+ create_by,
+ </if>
+ create_time
+ )values(
+ <if test="dictName != null and dictName != ''">
+ #{dictName},
+ </if>
+ <if test="dictType != null and dictType != ''">
+ #{dictType},
+ </if>
+ <if test="status != null">
+ #{status},
+ </if>
+ <if test="remark != null and remark != ''">
+ #{remark},
+ </if>
+ <if test="createBy != null and createBy != ''">
+ #{createBy},
+ </if>
+ sysdate()
+ )
+ </insert>
+
+ <select id="selectList" resultType="com.ruoyi.common.core.domain.entity.SysDictType">
+ select *
+ from sys_dict_type
+ where dict_name = #{dictName}
+ </select>
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
new file mode 100644
index 0000000..e62f8d3
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysLogininforMapper.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysLogininforMapper">
+
+ <resultMap type="SysLogininfor" id="SysLogininforResult">
+ <id property="infoId" column="info_id" />
+ <result property="userName" column="user_name" />
+ <result property="status" column="status" />
+ <result property="ipaddr" column="ipaddr" />
+ <result property="loginLocation" column="login_location" />
+ <result property="browser" column="browser" />
+ <result property="os" column="os" />
+ <result property="msg" column="msg" />
+ <result property="loginTime" column="login_time" />
+ </resultMap>
+
+ <insert id="insertLogininfor" parameterType="SysLogininfor">
+ insert into sys_logininfor (user_name, status, ipaddr, login_location, browser, os, msg, login_time)
+ values (#{userName}, #{status}, #{ipaddr}, #{loginLocation}, #{browser}, #{os}, #{msg}, sysdate())
+ </insert>
+
+ <select id="selectLogininforList" parameterType="SysLogininfor" resultMap="SysLogininforResult">
+ select info_id, user_name, ipaddr, login_location, browser, os, status, msg, login_time from sys_logininfor
+ <where>
+ <if test="ipaddr != null and ipaddr != ''">
+ AND ipaddr like concat('%', #{ipaddr}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="userName != null and userName != ''">
+ AND user_name like concat('%', #{userName}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ AND login_time >= #{params.beginTime}
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ AND login_time <= #{params.endTime}
+ </if>
+ </where>
+ order by info_id desc
+ </select>
+
+ <delete id="deleteLogininforByIds" parameterType="Long">
+ delete from sys_logininfor where info_id in
+ <foreach collection="array" item="infoId" open="(" separator="," close=")">
+ #{infoId}
+ </foreach>
+ </delete>
+
+ <update id="cleanLogininfor">
+ truncate table sys_logininfor
+ </update>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
new file mode 100644
index 0000000..9284614
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysMenuMapper.xml
@@ -0,0 +1,206 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+ "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysMenuMapper">
+
+ <resultMap type="SysMenu" id="SysMenuResult">
+ <id property="menuId" column="menu_id" />
+ <result property="menuName" column="menu_name" />
+ <result property="parentName" column="parent_name" />
+ <result property="parentId" column="parent_id" />
+ <result property="orderNum" column="order_num" />
+ <result property="path" column="path" />
+ <result property="component" column="component" />
+ <result property="query" column="query" />
+ <result property="routeName" column="route_name" />
+ <result property="isFrame" column="is_frame" />
+ <result property="isCache" column="is_cache" />
+ <result property="menuType" column="menu_type" />
+ <result property="visible" column="visible" />
+ <result property="status" column="status" />
+ <result property="perms" column="perms" />
+ <result property="icon" column="icon" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateTime" column="update_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="remark" column="remark" />
+ </resultMap>
+
+ <sql id="selectMenuVo">
+ select menu_id, menu_name, parent_id, order_num, path, component, `query`, route_name, is_frame, is_cache, menu_type, visible, status, ifnull(perms,'') as perms, icon, create_time
+ from sys_menu
+ </sql>
+
+ <select id="selectMenuList" parameterType="SysMenu" resultMap="SysMenuResult">
+ <include refid="selectMenuVo"/>
+ <where>
+ <if test="menuName != null and menuName != ''">
+ AND menu_name like concat('%', #{menuName}, '%')
+ </if>
+ <if test="visible != null and visible != ''">
+ AND visible = #{visible}
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ </where>
+ order by parent_id, order_num
+ </select>
+
+ <select id="selectMenuTreeAll" resultMap="SysMenuResult">
+ select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+ from sys_menu m where m.menu_type in ('M', 'C') and m.status = 0
+ order by m.parent_id, m.order_num
+ </select>
+
+ <select id="selectMenuListByUserId" parameterType="SysMenu" resultMap="SysMenuResult">
+ select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+ from sys_menu m
+ left join sys_role_menu rm on m.menu_id = rm.menu_id
+ left join sys_user_role ur on rm.role_id = ur.role_id
+ left join sys_role ro on ur.role_id = ro.role_id
+ where ur.user_id = #{params.userId}
+ <if test="menuName != null and menuName != ''">
+ AND m.menu_name like concat('%', #{menuName}, '%')
+ </if>
+ <if test="visible != null and visible != ''">
+ AND m.visible = #{visible}
+ </if>
+ <if test="status != null and status != ''">
+ AND m.status = #{status}
+ </if>
+ order by m.parent_id, m.order_num
+ </select>
+
+ <select id="selectMenuTreeByUserId" parameterType="Long" resultMap="SysMenuResult">
+ select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.route_name, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
+ from sys_menu m
+ left join sys_role_menu rm on m.menu_id = rm.menu_id
+ left join sys_user_role ur on rm.role_id = ur.role_id
+ left join sys_role ro on ur.role_id = ro.role_id
+ left join user u on ur.user_id = u.id
+ where u.id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0 AND ro.status = 0
+ order by m.parent_id, m.order_num
+ </select>
+
+ <select id="selectMenuListByRoleId" resultType="Long">
+ select m.menu_id
+ from sys_menu m
+ left join sys_role_menu rm on m.menu_id = rm.menu_id
+ where rm.role_id = #{roleId}
+ <if test="menuCheckStrictly">
+ and m.menu_id not in (select m.parent_id from sys_menu m inner join sys_role_menu rm on m.menu_id = rm.menu_id and rm.role_id = #{roleId})
+ </if>
+ order by m.parent_id, m.order_num
+ </select>
+
+ <select id="selectMenuPerms" resultType="String">
+ select distinct m.perms
+ from sys_menu m
+ left join sys_role_menu rm on m.menu_id = rm.menu_id
+ left join sys_user_role ur on rm.role_id = ur.role_id
+ </select>
+
+ <select id="selectMenuPermsByUserId" parameterType="Long" resultType="String">
+ select distinct m.perms
+ from sys_menu m
+ left join sys_role_menu rm on m.menu_id = rm.menu_id
+ left join sys_user_role ur on rm.role_id = ur.role_id
+ left join sys_role r on r.role_id = ur.role_id
+ where m.status = '0' and r.status = '0' and ur.user_id = #{userId}
+ </select>
+
+ <select id="selectMenuPermsByRoleId" parameterType="Long" resultType="String">
+ select distinct m.perms
+ from sys_menu m
+ left join sys_role_menu rm on m.menu_id = rm.menu_id
+ where m.status = '0' and rm.role_id = #{roleId}
+ </select>
+
+ <select id="selectMenuById" parameterType="Long" resultMap="SysMenuResult">
+ <include refid="selectMenuVo"/>
+ where menu_id = #{menuId}
+ </select>
+
+ <select id="hasChildByMenuId" resultType="Integer">
+ select count(1) from sys_menu where parent_id = #{menuId}
+ </select>
+
+ <select id="checkMenuNameUnique" parameterType="SysMenu" resultMap="SysMenuResult">
+ <include refid="selectMenuVo"/>
+ where menu_name=#{menuName} and parent_id = #{parentId} limit 1
+ </select>
+
+ <update id="updateMenu" parameterType="SysMenu">
+ update sys_menu
+ <set>
+ <if test="menuName != null and menuName != ''">menu_name = #{menuName},</if>
+ <if test="parentId != null">parent_id = #{parentId},</if>
+ <if test="orderNum != null">order_num = #{orderNum},</if>
+ <if test="path != null and path != ''">path = #{path},</if>
+ <if test="component != null">component = #{component},</if>
+ <if test="query != null">`query` = #{query},</if>
+ <if test="routeName != null">route_name = #{routeName},</if>
+ <if test="isFrame != null and isFrame != ''">is_frame = #{isFrame},</if>
+ <if test="isCache != null and isCache != ''">is_cache = #{isCache},</if>
+ <if test="menuType != null and menuType != ''">menu_type = #{menuType},</if>
+ <if test="visible != null">visible = #{visible},</if>
+ <if test="status != null">status = #{status},</if>
+ <if test="perms !=null">perms = #{perms},</if>
+ <if test="icon !=null and icon != ''">icon = #{icon},</if>
+ <if test="remark != null and remark != ''">remark = #{remark},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where menu_id = #{menuId}
+ </update>
+
+ <insert id="insertMenu" parameterType="SysMenu">
+ insert into sys_menu(
+ <if test="menuId != null and menuId != 0">menu_id,</if>
+ <if test="parentId != null and parentId != 0">parent_id,</if>
+ <if test="menuName != null and menuName != ''">menu_name,</if>
+ <if test="orderNum != null">order_num,</if>
+ <if test="path != null and path != ''">path,</if>
+ <if test="component != null and component != ''">component,</if>
+ <if test="query != null and query != ''">`query`,</if>
+ <if test="routeName != null">route_name,</if>
+ <if test="isFrame != null and isFrame != ''">is_frame,</if>
+ <if test="isCache != null and isCache != ''">is_cache,</if>
+ <if test="menuType != null and menuType != ''">menu_type,</if>
+ <if test="visible != null">visible,</if>
+ <if test="status != null">status,</if>
+ <if test="perms !=null and perms != ''">perms,</if>
+ <if test="icon != null and icon != ''">icon,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="menuId != null and menuId != 0">#{menuId},</if>
+ <if test="parentId != null and parentId != 0">#{parentId},</if>
+ <if test="menuName != null and menuName != ''">#{menuName},</if>
+ <if test="orderNum != null">#{orderNum},</if>
+ <if test="path != null and path != ''">#{path},</if>
+ <if test="component != null and component != ''">#{component},</if>
+ <if test="query != null and query != ''">#{query},</if>
+ <if test="routeName != null">#{routeName},</if>
+ <if test="isFrame != null and isFrame != ''">#{isFrame},</if>
+ <if test="isCache != null and isCache != ''">#{isCache},</if>
+ <if test="menuType != null and menuType != ''">#{menuType},</if>
+ <if test="visible != null">#{visible},</if>
+ <if test="status != null">#{status},</if>
+ <if test="perms !=null and perms != ''">#{perms},</if>
+ <if test="icon != null and icon != ''">#{icon},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+ <delete id="deleteMenuById" parameterType="Long">
+ delete from sys_menu where menu_id = #{menuId}
+ </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
new file mode 100644
index 0000000..65d3079
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysNoticeMapper.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysNoticeMapper">
+
+ <resultMap type="SysNotice" id="SysNoticeResult">
+ <result property="noticeId" column="notice_id" />
+ <result property="noticeTitle" column="notice_title" />
+ <result property="noticeType" column="notice_type" />
+ <result property="noticeContent" column="notice_content" />
+ <result property="status" column="status" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="remark" column="remark" />
+ </resultMap>
+
+ <sql id="selectNoticeVo">
+ select notice_id, notice_title, notice_type, cast(notice_content as char) as notice_content, status, create_by, create_time, update_by, update_time, remark
+ from sys_notice
+ </sql>
+
+ <select id="selectNoticeById" parameterType="Long" resultMap="SysNoticeResult">
+ <include refid="selectNoticeVo"/>
+ where notice_id = #{noticeId}
+ </select>
+
+ <select id="selectNoticeList" parameterType="SysNotice" resultMap="SysNoticeResult">
+ <include refid="selectNoticeVo"/>
+ <where>
+ <if test="noticeTitle != null and noticeTitle != ''">
+ AND notice_title like concat('%', #{noticeTitle}, '%')
+ </if>
+ <if test="noticeType != null and noticeType != ''">
+ AND notice_type = #{noticeType}
+ </if>
+ <if test="createBy != null and createBy != ''">
+ AND create_by like concat('%', #{createBy}, '%')
+ </if>
+ </where>
+ </select>
+
+ <insert id="insertNotice" parameterType="SysNotice">
+ insert into sys_notice (
+ <if test="noticeTitle != null and noticeTitle != '' ">notice_title, </if>
+ <if test="noticeType != null and noticeType != '' ">notice_type, </if>
+ <if test="noticeContent != null and noticeContent != '' ">notice_content, </if>
+ <if test="status != null and status != '' ">status, </if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="noticeTitle != null and noticeTitle != ''">#{noticeTitle}, </if>
+ <if test="noticeType != null and noticeType != ''">#{noticeType}, </if>
+ <if test="noticeContent != null and noticeContent != ''">#{noticeContent}, </if>
+ <if test="status != null and status != ''">#{status}, </if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="updateNotice" parameterType="SysNotice">
+ update sys_notice
+ <set>
+ <if test="noticeTitle != null and noticeTitle != ''">notice_title = #{noticeTitle}, </if>
+ <if test="noticeType != null and noticeType != ''">notice_type = #{noticeType}, </if>
+ <if test="noticeContent != null">notice_content = #{noticeContent}, </if>
+ <if test="status != null and status != ''">status = #{status}, </if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where notice_id = #{noticeId}
+ </update>
+
+ <delete id="deleteNoticeById" parameterType="Long">
+ delete from sys_notice where notice_id = #{noticeId}
+ </delete>
+
+ <delete id="deleteNoticeByIds" parameterType="Long">
+ delete from sys_notice where notice_id in
+ <foreach item="noticeId" collection="array" open="(" separator="," close=")">
+ #{noticeId}
+ </foreach>
+ </delete>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
new file mode 100644
index 0000000..201db07
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysOperLogMapper.xml
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysOperLogMapper">
+
+ <resultMap type="SysOperLog" id="SysOperLogResult">
+ <id property="operId" column="oper_id" />
+ <result property="title" column="title" />
+ <result property="businessType" column="business_type" />
+ <result property="method" column="method" />
+ <result property="requestMethod" column="request_method" />
+ <result property="operatorType" column="operator_type" />
+ <result property="operName" column="oper_name" />
+ <result property="deptName" column="dept_name" />
+ <result property="operUrl" column="oper_url" />
+ <result property="operIp" column="oper_ip" />
+ <result property="operLocation" column="oper_location" />
+ <result property="operParam" column="oper_param" />
+ <result property="jsonResult" column="json_result" />
+ <result property="status" column="status" />
+ <result property="errorMsg" column="error_msg" />
+ <result property="operTime" column="oper_time" />
+ <result property="costTime" column="cost_time" />
+ </resultMap>
+
+ <sql id="selectOperLogVo">
+ select oper_id, title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, oper_time, cost_time
+ from sys_oper_log
+ </sql>
+
+ <insert id="insertOperlog" parameterType="SysOperLog">
+ insert into sys_oper_log(title, business_type, method, request_method, operator_type, oper_name, dept_name, oper_url, oper_ip, oper_location, oper_param, json_result, status, error_msg, cost_time, oper_time)
+ values (#{title}, #{businessType}, #{method}, #{requestMethod}, #{operatorType}, #{operName}, #{deptName}, #{operUrl}, #{operIp}, #{operLocation}, #{operParam}, #{jsonResult}, #{status}, #{errorMsg}, #{costTime}, sysdate())
+ </insert>
+
+ <select id="selectOperLogList" parameterType="SysOperLog" resultMap="SysOperLogResult">
+ <include refid="selectOperLogVo"/>
+ <where>
+ <if test="operIp != null and operIp != ''">
+ AND oper_ip like concat('%', #{operIp}, '%')
+ </if>
+ <if test="title != null and title != ''">
+ AND title like concat('%', #{title}, '%')
+ </if>
+ <if test="businessType != null">
+ AND business_type = #{businessType}
+ </if>
+ <if test="businessTypes != null and businessTypes.length > 0">
+ AND business_type in
+ <foreach collection="businessTypes" item="businessType" open="(" separator="," close=")">
+ #{businessType}
+ </foreach>
+ </if>
+ <if test="status != null">
+ AND status = #{status}
+ </if>
+ <if test="operName != null and operName != ''">
+ AND oper_name like concat('%', #{operName}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ AND oper_time >= #{params.beginTime}
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ AND oper_time <= #{params.endTime}
+ </if>
+ </where>
+ order by oper_id desc
+ </select>
+
+ <delete id="deleteOperLogByIds" parameterType="Long">
+ delete from sys_oper_log where oper_id in
+ <foreach collection="array" item="operId" open="(" separator="," close=")">
+ #{operId}
+ </foreach>
+ </delete>
+
+ <select id="selectOperLogById" parameterType="Long" resultMap="SysOperLogResult">
+ <include refid="selectOperLogVo"/>
+ where oper_id = #{operId}
+ </select>
+
+ <update id="cleanOperLog">
+ truncate table sys_oper_log
+ </update>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
new file mode 100644
index 0000000..085827b
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysPostMapper.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysPostMapper">
+
+ <resultMap type="SysPost" id="SysPostResult">
+ <id property="postId" column="post_id" />
+ <result property="postCode" column="post_code" />
+ <result property="postName" column="post_name" />
+ <result property="postSort" column="post_sort" />
+ <result property="status" column="status" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="remark" column="remark" />
+ </resultMap>
+
+ <sql id="selectPostVo">
+ select post_id, post_code, post_name, post_sort, status, create_by, create_time, remark
+ from sys_post
+ </sql>
+
+ <select id="selectPostList" parameterType="SysPost" resultMap="SysPostResult">
+ <include refid="selectPostVo"/>
+ <where>
+ <if test="postCode != null and postCode != ''">
+ AND post_code like concat('%', #{postCode}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND status = #{status}
+ </if>
+ <if test="postName != null and postName != ''">
+ AND post_name like concat('%', #{postName}, '%')
+ </if>
+ </where>
+ </select>
+
+ <select id="selectPostAll" resultMap="SysPostResult">
+ <include refid="selectPostVo"/>
+ </select>
+
+ <select id="selectPostById" parameterType="Long" resultMap="SysPostResult">
+ <include refid="selectPostVo"/>
+ where post_id = #{postId}
+ </select>
+
+ <select id="selectPostListByUserId" parameterType="Long" resultType="Long">
+ select p.post_id
+ from sys_post p
+ left join sys_user_post up on up.post_id = p.post_id
+ left join user u on u.id = up.user_id
+ where u.id = #{userId}
+ </select>
+
+ <select id="selectPostsByUserName" parameterType="String" resultMap="SysPostResult">
+ select p.post_id, p.post_name, p.post_code
+ from sys_post p
+ left join sys_user_post up on up.post_id = p.post_id
+ left join user u on u.id = up.user_id
+ where u.account = #{userName}
+ </select>
+
+ <select id="checkPostNameUnique" parameterType="String" resultMap="SysPostResult">
+ <include refid="selectPostVo"/>
+ where post_name=#{postName} limit 1
+ </select>
+
+ <select id="checkPostCodeUnique" parameterType="String" resultMap="SysPostResult">
+ <include refid="selectPostVo"/>
+ where post_code=#{postCode} limit 1
+ </select>
+
+ <update id="updatePost" parameterType="SysPost">
+ update sys_post
+ <set>
+ <if test="postCode != null and postCode != ''">post_code = #{postCode},</if>
+ <if test="postName != null and postName != ''">post_name = #{postName},</if>
+ <if test="postSort != null">post_sort = #{postSort},</if>
+ <if test="status != null and status != ''">status = #{status},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where post_id = #{postId}
+ </update>
+
+ <insert id="insertPost" parameterType="SysPost" useGeneratedKeys="true" keyProperty="postId">
+ insert into sys_post(
+ <if test="postId != null and postId != 0">post_id,</if>
+ <if test="postCode != null and postCode != ''">post_code,</if>
+ <if test="postName != null and postName != ''">post_name,</if>
+ <if test="postSort != null">post_sort,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="postId != null and postId != 0">#{postId},</if>
+ <if test="postCode != null and postCode != ''">#{postCode},</if>
+ <if test="postName != null and postName != ''">#{postName},</if>
+ <if test="postSort != null">#{postSort},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+ <delete id="deletePostById" parameterType="Long">
+ delete from sys_post where post_id = #{postId}
+ </delete>
+
+ <delete id="deletePostByIds" parameterType="Long">
+ delete from sys_post where post_id in
+ <foreach collection="array" item="postId" open="(" separator="," close=")">
+ #{postId}
+ </foreach>
+ </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
new file mode 100644
index 0000000..7c4139b
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleDeptMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysRoleDeptMapper">
+
+ <resultMap type="SysRoleDept" id="SysRoleDeptResult">
+ <result property="roleId" column="role_id" />
+ <result property="deptId" column="dept_id" />
+ </resultMap>
+
+ <delete id="deleteRoleDeptByRoleId" parameterType="Long">
+ delete from sys_role_dept where role_id=#{roleId}
+ </delete>
+
+ <select id="selectCountRoleDeptByDeptId" resultType="Integer">
+ select count(1) from sys_role_dept where dept_id=#{deptId}
+ </select>
+
+ <delete id="deleteRoleDept" parameterType="Long">
+ delete from sys_role_dept where role_id in
+ <foreach collection="array" item="roleId" open="(" separator="," close=")">
+ #{roleId}
+ </foreach>
+ </delete>
+
+ <insert id="batchRoleDept">
+ insert into sys_role_dept(role_id, dept_id) values
+ <foreach item="item" index="index" collection="list" separator=",">
+ (#{item.roleId},#{item.deptId})
+ </foreach>
+ </insert>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
new file mode 100644
index 0000000..a2e9bc6
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMapper.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysRoleMapper">
+
+ <resultMap type="SysRole" id="SysRoleResult">
+ <id property="roleId" column="role_id" />
+ <result property="roleName" column="role_name" />
+ <result property="roleKey" column="role_key" />
+ <result property="roleSort" column="role_sort" />
+ <result property="dataScope" column="data_scope" />
+ <result property="menuCheckStrictly" column="menu_check_strictly" />
+ <result property="deptCheckStrictly" column="dept_check_strictly" />
+ <result property="status" column="status" />
+ <result property="delFlag" column="del_flag" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="remark" column="remark" />
+ </resultMap>
+
+ <sql id="selectRoleVo">
+ select distinct r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.menu_check_strictly, r.dept_check_strictly,
+ r.status, r.del_flag, r.create_time, r.remark
+ from sys_role r
+ left join sys_user_role ur on ur.role_id = r.role_id
+ left join user u on u.id = ur.user_id
+ left join sys_dept d on u.dept_id = d.dept_id
+ </sql>
+
+ <select id="selectRoleList" parameterType="SysRole" resultMap="SysRoleResult">
+ <include refid="selectRoleVo"/>
+ where r.del_flag = '0'
+ <if test="roleId != null and roleId != 0">
+ AND r.role_id = #{roleId}
+ </if>
+ <if test="roleName != null and roleName != ''">
+ AND r.role_name like concat('%', #{roleName}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND r.status = #{status}
+ </if>
+ <if test="roleKey != null and roleKey != ''">
+ AND r.role_key like concat('%', #{roleKey}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ and date_format(r.create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ and date_format(r.create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ order by r.role_sort
+ </select>
+
+ <select id="selectRolePermissionByUserId" parameterType="Long" resultMap="SysRoleResult">
+ <include refid="selectRoleVo"/>
+ WHERE r.del_flag = '0' and ur.user_id = #{userId}
+ </select>
+
+ <select id="selectRoleAll" resultMap="SysRoleResult">
+ <include refid="selectRoleVo"/>
+ </select>
+
+ <select id="selectRoleListByUserId" parameterType="Long" resultType="Long">
+ select r.role_id
+ from sys_role r
+ left join sys_user_role ur on ur.role_id = r.role_id
+ left join user u on u.id = ur.user_id
+ where u.id = #{userId}
+ </select>
+
+ <select id="selectRoleById" parameterType="Long" resultMap="SysRoleResult">
+ <include refid="selectRoleVo"/>
+ where r.role_id = #{roleId}
+ </select>
+
+ <select id="selectRolesByUserName" parameterType="String" resultMap="SysRoleResult">
+ <include refid="selectRoleVo"/>
+ WHERE r.del_flag = '0' and u.account = #{userName}
+ </select>
+
+ <select id="checkRoleNameUnique" parameterType="String" resultMap="SysRoleResult">
+ <include refid="selectRoleVo"/>
+ where r.role_name=#{roleName} and r.del_flag = '0' limit 1
+ </select>
+
+ <select id="checkRoleKeyUnique" parameterType="String" resultMap="SysRoleResult">
+ <include refid="selectRoleVo"/>
+ where r.role_key=#{roleKey} and r.del_flag = '0' limit 1
+ </select>
+
+ <insert id="insertRole" parameterType="SysRole" useGeneratedKeys="true" keyProperty="roleId">
+ insert into sys_role(
+ <if test="roleId != null and roleId != 0">role_id,</if>
+ <if test="roleName != null and roleName != ''">role_name,</if>
+ <if test="roleKey != null and roleKey != ''">role_key,</if>
+ <if test="roleSort != null">role_sort,</if>
+ <if test="dataScope != null and dataScope != ''">data_scope,</if>
+ <if test="menuCheckStrictly != null">menu_check_strictly,</if>
+ <if test="deptCheckStrictly != null">dept_check_strictly,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ create_time
+ )values(
+ <if test="roleId != null and roleId != 0">#{roleId},</if>
+ <if test="roleName != null and roleName != ''">#{roleName},</if>
+ <if test="roleKey != null and roleKey != ''">#{roleKey},</if>
+ <if test="roleSort != null">#{roleSort},</if>
+ <if test="dataScope != null and dataScope != ''">#{dataScope},</if>
+ <if test="menuCheckStrictly != null">#{menuCheckStrictly},</if>
+ <if test="deptCheckStrictly != null">#{deptCheckStrictly},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="updateRole" parameterType="SysRole">
+ update sys_role
+ <set>
+ <if test="roleName != null and roleName != ''">role_name = #{roleName},</if>
+ <if test="roleKey != null and roleKey != ''">role_key = #{roleKey},</if>
+ <if test="roleSort != null">role_sort = #{roleSort},</if>
+ <if test="dataScope != null and dataScope != ''">data_scope = #{dataScope},</if>
+ <if test="menuCheckStrictly != null">menu_check_strictly = #{menuCheckStrictly},</if>
+ <if test="deptCheckStrictly != null">dept_check_strictly = #{deptCheckStrictly},</if>
+ <if test="status != null and status != ''">status = #{status},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ update_time = sysdate()
+ </set>
+ where role_id = #{roleId}
+ </update>
+
+ <delete id="deleteRoleById" parameterType="Long">
+ update sys_role set del_flag = '2' where role_id = #{roleId}
+ </delete>
+
+ <delete id="deleteRoleByIds" parameterType="Long">
+ update sys_role set del_flag = '2' where role_id in
+ <foreach collection="array" item="roleId" open="(" separator="," close=")">
+ #{roleId}
+ </foreach>
+ </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
new file mode 100644
index 0000000..cb60a85
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysRoleMenuMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysRoleMenuMapper">
+
+ <resultMap type="SysRoleMenu" id="SysRoleMenuResult">
+ <result property="roleId" column="role_id" />
+ <result property="menuId" column="menu_id" />
+ </resultMap>
+
+ <select id="checkMenuExistRole" resultType="Integer">
+ select count(1) from sys_role_menu where menu_id = #{menuId}
+ </select>
+
+ <delete id="deleteRoleMenuByRoleId" parameterType="Long">
+ delete from sys_role_menu where role_id=#{roleId}
+ </delete>
+
+ <delete id="deleteRoleMenu" parameterType="Long">
+ delete from sys_role_menu where role_id in
+ <foreach collection="array" item="roleId" open="(" separator="," close=")">
+ #{roleId}
+ </foreach>
+ </delete>
+
+ <insert id="batchRoleMenu">
+ insert into sys_role_menu(role_id, menu_id) values
+ <foreach item="item" index="index" collection="list" separator=",">
+ (#{item.roleId},#{item.menuId})
+ </foreach>
+ </insert>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
new file mode 100644
index 0000000..8757304
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -0,0 +1,233 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysUserMapper">
+
+ <resultMap type="SysUser" id="SysUserResult">
+ <id property="userId" column="id" />
+ <result property="deptId" column="dept_id" />
+ <result property="userName" column="account" />
+ <result property="nickName" column="name" />
+ <result property="email" column="email" />
+ <result property="phonenumber" column="phone" />
+ <result property="sex" column="sex" />
+ <result property="avatar" column="avatar" />
+ <result property="password" column="password" />
+ <result property="status" column="status" />
+ <result property="delFlag" column="del_flag" />
+ <result property="loginIp" column="login_ip" />
+ <result property="loginDate" column="login_date" />
+ <result property="createBy" column="create_by" />
+ <result property="createTime" column="create_time" />
+ <result property="updateBy" column="update_by" />
+ <result property="updateTime" column="update_time" />
+ <result property="remark" column="remark" />
+ <result property="nameEn" column="name_en" />
+ <result property="signatureUrl" column="signature_url" />
+ <result property="company" column="company" />
+ <association property="dept" javaType="SysDept" resultMap="deptResult" />
+ <collection property="roles" javaType="java.util.List" resultMap="RoleResult" />
+ </resultMap>
+
+ <resultMap id="deptResult" type="SysDept">
+ <id property="deptId" column="dept_id" />
+ <result property="parentId" column="parent_id" />
+ <result property="deptName" column="dept_name" />
+ <result property="ancestors" column="ancestors" />
+ <result property="orderNum" column="order_num" />
+ <result property="leader" column="leader" />
+ <result property="status" column="dept_status" />
+ </resultMap>
+
+ <resultMap id="RoleResult" type="SysRole">
+ <id property="roleId" column="role_id" />
+ <result property="roleName" column="role_name" />
+ <result property="roleKey" column="role_key" />
+ <result property="roleSort" column="role_sort" />
+ <result property="dataScope" column="data_scope" />
+ <result property="status" column="role_status" />
+ </resultMap>
+
+ <sql id="selectUserVo">
+ select u.id, u.dept_id, u.account, u.name, u.email, u.picture_url, u.phone, u.password, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, u.name_en, u.signature_url, u.company,
+ d.dept_id, d.parent_id, d.ancestors, d.dept_name, d.order_num, d.leader, d.status as dept_status,
+ r.role_id, r.role_name, r.role_key, r.role_sort, r.data_scope, r.status as role_status
+ from user u
+ left join sys_dept d on u.dept_id = d.dept_id
+ left join sys_user_role ur on u.id = ur.user_id
+ left join sys_role r on r.role_id = ur.role_id
+ </sql>
+
+ <select id="selectUserList" parameterType="SysUser" resultMap="SysUserResult">
+ select u.id, u.dept_id, u.name, u.account, u.email, u.picture_url, u.phone, u.sex, u.status, u.del_flag, u.login_ip, u.login_date, u.create_by, u.create_time, u.remark, d.dept_name, d.leader from user u
+ left join sys_dept d on u.dept_id = d.dept_id
+ where u.del_flag = '0'
+ <if test="userId != null and userId != 0">
+ AND u.id = #{userId}
+ </if>
+ <if test="userName != null and userName != ''">
+ AND u.account like concat('%', #{userName}, '%')
+ </if>
+ <if test="status != null and status != ''">
+ AND u.status = #{status}
+ </if>
+ <if test="phonenumber != null and phonenumber != ''">
+ AND u.phone like concat('%', #{phonenumber}, '%')
+ </if>
+ <if test="params.beginTime != null and params.beginTime != ''"><!-- 寮�濮嬫椂闂存绱� -->
+ AND date_format(u.create_time,'%Y%m%d') >= date_format(#{params.beginTime},'%Y%m%d')
+ </if>
+ <if test="params.endTime != null and params.endTime != ''"><!-- 缁撴潫鏃堕棿妫�绱� -->
+ AND date_format(u.create_time,'%Y%m%d') <= date_format(#{params.endTime},'%Y%m%d')
+ </if>
+ <if test="deptId != null and deptId != 0">
+ AND (u.dept_id = #{deptId} OR u.dept_id IN ( SELECT t.dept_id FROM sys_dept t WHERE find_in_set(#{deptId}, ancestors) ))
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ </select>
+
+ <select id="selectAllocatedList" parameterType="SysUser" resultMap="SysUserResult">
+ select distinct u.id, u.dept_id, u.account, u.name, u.email, u.phone, u.status, u.create_time
+ from user u
+ left join sys_dept d on u.dept_id = d.dept_id
+ left join sys_user_role ur on u.id = ur.user_id
+ left join sys_role r on r.role_id = ur.role_id
+ where u.del_flag = '0' and r.role_id = #{roleId}
+ <if test="userName != null and userName != ''">
+ AND u.account like concat('%', #{userName}, '%')
+ </if>
+ <if test="phonenumber != null and phonenumber != ''">
+ AND u.phone like concat('%', #{phonenumber}, '%')
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ </select>
+
+ <select id="selectUnallocatedList" parameterType="SysUser" resultMap="SysUserResult">
+ select distinct u.id, u.dept_id, u.account, u.name, u.email, u.phone, u.status, u.create_time
+ from user u
+ left join sys_dept d on u.dept_id = d.dept_id
+ left join sys_user_role ur on u.id = ur.user_id
+ left join sys_role r on r.role_id = ur.role_id
+ where u.del_flag = '0' and (r.role_id != #{roleId} or r.role_id IS NULL)
+ and u.id not in (select u.id from user u inner join sys_user_role ur on u.id = ur.user_id and ur.role_id = #{roleId})
+ <if test="userName != null and userName != ''">
+ AND u.account like concat('%', #{userName}, '%')
+ </if>
+ <if test="phonenumber != null and phonenumber != ''">
+ AND u.phone like concat('%', #{phonenumber}, '%')
+ </if>
+ <!-- 鏁版嵁鑼冨洿杩囨护 -->
+ ${params.dataScope}
+ </select>
+
+ <select id="selectUserByUserName" parameterType="String" resultMap="SysUserResult">
+ <include refid="selectUserVo"/>
+ where u.account = #{userName} and u.del_flag = '0'
+ </select>
+
+ <select id="selectUserById" parameterType="Long" resultMap="SysUserResult">
+ <include refid="selectUserVo"/>
+ where u.id = #{userId}
+ </select>
+
+ <select id="checkUserNameUnique" parameterType="String" resultMap="SysUserResult">
+ select id, account from user where account = #{userName} and del_flag = '0' limit 1
+ </select>
+
+ <select id="checkPhoneUnique" parameterType="String" resultMap="SysUserResult">
+ select id, phone from user where phone = #{phonenumber} and del_flag = '0' limit 1
+ </select>
+
+ <select id="checkEmailUnique" parameterType="String" resultMap="SysUserResult">
+ select id, email from user where email = #{email} and del_flag = '0' limit 1
+ </select>
+
+ <insert id="insertUser" parameterType="SysUser" useGeneratedKeys="true" keyProperty="userId">
+ insert into user(
+ <if test="userId != null and userId != 0">id,</if>
+ <if test="deptId != null and deptId != 0">dept_id,</if>
+ <if test="userName != null and userName != ''">account,</if>
+ <if test="nickName != null and nickName != ''">`name`,</if>
+ <if test="email != null and email != ''">email,</if>
+ <if test="avatar != null and avatar != ''">avatar,</if>
+ <if test="phonenumber != null and phonenumber != ''">phone,</if>
+ <if test="sex != null and sex != ''">sex,</if>
+ <if test="password != null and password != ''">password,</if>
+ <if test="status != null and status != ''">status,</if>
+ <if test="createBy != null and createBy != ''">create_by,</if>
+ <if test="remark != null and remark != ''">remark,</if>
+ <if test="nameEn != null and nameEn != ''">name_en,</if>
+ <if test="signatureUrl != null and signatureUrl != ''">signature_url,</if>
+ <if test="company != null and company != ''">company,</if>
+ create_time
+ )values(
+ <if test="userId != null and userId != ''">#{userId},</if>
+ <if test="deptId != null and deptId != ''">#{deptId},</if>
+ <if test="userName != null and userName != ''">#{userName},</if>
+ <if test="nickName != null and nickName != ''">#{nickName},</if>
+ <if test="email != null and email != ''">#{email},</if>
+ <if test="avatar != null and avatar != ''">#{avatar},</if>
+ <if test="phonenumber != null and phonenumber != ''">#{phonenumber},</if>
+ <if test="sex != null and sex != ''">#{sex},</if>
+ <if test="password != null and password != ''">#{password},</if>
+ <if test="status != null and status != ''">#{status},</if>
+ <if test="createBy != null and createBy != ''">#{createBy},</if>
+ <if test="remark != null and remark != ''">#{remark},</if>
+ <if test="nameEn != null and nameEn != ''">#{nameEn},</if>
+ <if test="signatureUrl != null and signatureUrl != ''">#{signatureUrl},</if>
+ <if test="company != null and company != ''">#{company},</if>
+ sysdate()
+ )
+ </insert>
+
+ <update id="updateUser" parameterType="SysUser">
+ update user
+ <set>
+ <if test="deptId != null and deptId != 0">dept_id = #{deptId},</if>
+ <if test="userName != null and userName != ''">account = #{userName},</if>
+ <if test="nickName != null and nickName != ''">`name` = #{nickName},</if>
+ <if test="email != null ">email = #{email},</if>
+ <if test="phonenumber != null ">phone = #{phonenumber},</if>
+ <if test="sex != null and sex != ''">sex = #{sex},</if>
+ <if test="avatar != null and avatar != ''">avatar = #{avatar},</if>
+ <if test="password != null and password != ''">password = #{password},</if>
+ <if test="status != null and status != ''">status = #{status},</if>
+ <if test="loginIp != null and loginIp != ''">login_ip = #{loginIp},</if>
+ <if test="loginDate != null">login_date = #{loginDate},</if>
+ <if test="updateBy != null and updateBy != ''">update_by = #{updateBy},</if>
+ <if test="remark != null">remark = #{remark},</if>
+ <if test="nameEn != null and nameEn != ''">name_en = #{nameEn},</if>
+ <if test="signatureUrl != null and signatureUrl != ''">signature_url = #{signatureUrl},</if>
+ <if test="company != null and company != ''">company = #{company},</if>
+ update_time = sysdate()
+ </set>
+ where id = #{userId}
+ </update>
+
+ <update id="updateUserStatus" parameterType="SysUser">
+ update user set status = #{status} where id = #{userId}
+ </update>
+
+ <update id="updateUserAvatar" parameterType="SysUser">
+ update user set avatar = #{avatar} where account = #{userName}
+ </update>
+
+ <update id="resetUserPwd" parameterType="SysUser">
+ update user set password = #{password} where account = #{userName}
+ </update>
+
+ <delete id="deleteUserById" parameterType="Long">
+ update user set del_flag = '2' where id = #{userId}
+ </delete>
+
+ <delete id="deleteUserByIds" parameterType="Long">
+ update user set del_flag = '2' where id in
+ <foreach collection="array" item="userId" open="(" separator="," close=")">
+ #{userId}
+ </foreach>
+ </delete>
+
+</mapper>
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
new file mode 100644
index 0000000..2b90bc4
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserPostMapper.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysUserPostMapper">
+
+ <resultMap type="SysUserPost" id="SysUserPostResult">
+ <result property="userId" column="user_id" />
+ <result property="postId" column="post_id" />
+ </resultMap>
+
+ <delete id="deleteUserPostByUserId" parameterType="Long">
+ delete from sys_user_post where user_id=#{userId}
+ </delete>
+
+ <select id="countUserPostById" resultType="Integer">
+ select count(1) from sys_user_post where post_id=#{postId}
+ </select>
+
+ <delete id="deleteUserPost" parameterType="Long">
+ delete from sys_user_post where user_id in
+ <foreach collection="array" item="userId" open="(" separator="," close=")">
+ #{userId}
+ </foreach>
+ </delete>
+
+ <insert id="batchUserPost">
+ insert into sys_user_post(user_id, post_id) values
+ <foreach item="item" index="index" collection="list" separator=",">
+ (#{item.userId},#{item.postId})
+ </foreach>
+ </insert>
+
+</mapper>
\ No newline at end of file
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
new file mode 100644
index 0000000..dd72689
--- /dev/null
+++ b/ruoyi-system/src/main/resources/mapper/system/SysUserRoleMapper.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.system.mapper.SysUserRoleMapper">
+
+ <resultMap type="SysUserRole" id="SysUserRoleResult">
+ <result property="userId" column="user_id" />
+ <result property="roleId" column="role_id" />
+ </resultMap>
+
+ <delete id="deleteUserRoleByUserId" parameterType="Long">
+ delete from sys_user_role where user_id=#{userId}
+ </delete>
+
+ <select id="countUserRoleByRoleId" resultType="Integer">
+ select count(1) from sys_user_role where role_id=#{roleId}
+ </select>
+
+ <delete id="deleteUserRole" parameterType="Long">
+ delete from sys_user_role where user_id in
+ <foreach collection="array" item="userId" open="(" separator="," close=")">
+ #{userId}
+ </foreach>
+ </delete>
+
+ <insert id="batchUserRole">
+ insert into sys_user_role(user_id, role_id) values
+ <foreach item="item" index="index" collection="list" separator=",">
+ (#{item.userId},#{item.roleId})
+ </foreach>
+ </insert>
+
+ <delete id="deleteUserRoleInfo" parameterType="SysUserRole">
+ delete from sys_user_role where user_id=#{userId} and role_id=#{roleId}
+ </delete>
+
+ <delete id="deleteUserRoleInfos">
+ delete from sys_user_role where role_id=#{roleId} and user_id in
+ <foreach collection="userIds" item="userId" open="(" separator="," close=")">
+ #{userId}
+ </foreach>
+ </delete>
+</mapper>
\ No newline at end of file
diff --git a/ry.bat b/ry.bat
new file mode 100644
index 0000000..ac1e437
--- /dev/null
+++ b/ry.bat
@@ -0,0 +1,67 @@
+@echo off
+
+rem jar平级目录
+set AppName=ruoyi-admin.jar
+
+rem JVM参数
+set JVM_OPTS="-Dname=%AppName% -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
+
+
+ECHO.
+ ECHO. [1] 启动%AppName%
+ ECHO. [2] 关闭%AppName%
+ ECHO. [3] 重启%AppName%
+ ECHO. [4] 启动状态 %AppName%
+ ECHO. [5] 退 出
+ECHO.
+
+ECHO.请输入选择项目的序号:
+set /p ID=
+ IF "%id%"=="1" GOTO start
+ IF "%id%"=="2" GOTO stop
+ IF "%id%"=="3" GOTO restart
+ IF "%id%"=="4" GOTO status
+ IF "%id%"=="5" EXIT
+PAUSE
+:start
+ for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
+ set pid=%%a
+ set image_name=%%b
+ )
+ if defined pid (
+ echo %%is running
+ PAUSE
+ )
+
+start javaw %JVM_OPTS% -jar %AppName%
+
+echo starting……
+echo Start %AppName% success...
+goto:eof
+
+rem 函数stop通过jps命令查找pid并结束进程
+:stop
+ for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
+ set pid=%%a
+ set image_name=%%b
+ )
+ if not defined pid (echo process %AppName% does not exists) else (
+ echo prepare to kill %image_name%
+ echo start kill %pid% ...
+ rem 根据进程ID,kill进程
+ taskkill /f /pid %pid%
+ )
+goto:eof
+:restart
+ call :stop
+ call :start
+goto:eof
+:status
+ for /f "usebackq tokens=1-2" %%a in (`jps -l ^| findstr %AppName%`) do (
+ set pid=%%a
+ set image_name=%%b
+ )
+ if not defined pid (echo process %AppName% is dead ) else (
+ echo %image_name% is running
+ )
+goto:eof
diff --git a/ry.sh b/ry.sh
new file mode 100644
index 0000000..d6a9cf3
--- /dev/null
+++ b/ry.sh
@@ -0,0 +1,86 @@
+#!/bin/sh
+# ./ry.sh start 鍚姩 stop 鍋滄 restart 閲嶅惎 status 鐘舵��
+AppName=ruoyi-admin.jar
+
+# JVM鍙傛暟
+JVM_OPTS="-Dname=$AppName -Duser.timezone=Asia/Shanghai -Xms512m -Xmx1024m -XX:MetaspaceSize=128m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemoryError -XX:+PrintGCDateStamps -XX:+PrintGCDetails -XX:NewRatio=1 -XX:SurvivorRatio=30 -XX:+UseParallelGC -XX:+UseParallelOldGC"
+APP_HOME=`pwd`
+LOG_PATH=$APP_HOME/logs/$AppName.log
+
+if [ "$1" = "" ];
+then
+ echo -e "\033[0;31m 鏈緭鍏ユ搷浣滃悕 \033[0m \033[0;34m {start|stop|restart|status} \033[0m"
+ exit 1
+fi
+
+if [ "$AppName" = "" ];
+then
+ echo -e "\033[0;31m 鏈緭鍏ュ簲鐢ㄥ悕 \033[0m"
+ exit 1
+fi
+
+function start()
+{
+ PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
+
+ if [ x"$PID" != x"" ]; then
+ echo "$AppName is running..."
+ else
+ nohup java $JVM_OPTS -jar $AppName > /dev/null 2>&1 &
+ echo "Start $AppName success..."
+ fi
+}
+
+function stop()
+{
+ echo "Stop $AppName"
+
+ PID=""
+ query(){
+ PID=`ps -ef |grep java|grep $AppName|grep -v grep|awk '{print $2}'`
+ }
+
+ query
+ if [ x"$PID" != x"" ]; then
+ kill -TERM $PID
+ echo "$AppName (pid:$PID) exiting..."
+ while [ x"$PID" != x"" ]
+ do
+ sleep 1
+ query
+ done
+ echo "$AppName exited."
+ else
+ echo "$AppName already stopped."
+ fi
+}
+
+function restart()
+{
+ stop
+ sleep 2
+ start
+}
+
+function status()
+{
+ PID=`ps -ef |grep java|grep $AppName|grep -v grep|wc -l`
+ if [ $PID != 0 ];then
+ echo "$AppName is running..."
+ else
+ echo "$AppName is not running..."
+ fi
+}
+
+case $1 in
+ start)
+ start;;
+ stop)
+ stop;;
+ restart)
+ restart;;
+ status)
+ status;;
+ *)
+
+esac
--
Gitblit v1.9.3