commit c2b222ec52b72e05c3511f2f3eb6534a80177b7a Author: wang Date: Wed Jun 3 15:09:23 2026 +0800 first commit diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..1440f0b Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3084414 --- /dev/null +++ b/.gitignore @@ -0,0 +1,37 @@ +HELP.md +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/** +!**/src/test/** + +### STS ### +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### IntelliJ IDEA ### +# 保留 .idea 与模块 *.iml 以便克隆后可直接打开工程;仅忽略本机/会话文件 +.idea/workspace.xml +.idea/tasks.xml +.idea/dataSources/ +.idea/dataSources.local.xml +.idea/shelf/ +.idea/httpRequests/ +.idea/usage.statistics.xml +.idea/statistics.xml +.idea/dictionaries/ +.idea/libraries/ +.idea/aws.xml +*.iws +*.ipr +.idea/* +### front ### +**/dist +**/node_modules +**/.vscode +**/.env +**/.log + diff --git a/.superpowers/brainstorm/62699-1778123142/content/operate-log-page-layout.html b/.superpowers/brainstorm/62699-1778123142/content/operate-log-page-layout.html new file mode 100644 index 0000000..778de55 --- /dev/null +++ b/.superpowers/brainstorm/62699-1778123142/content/operate-log-page-layout.html @@ -0,0 +1,51 @@ +

操作日志管理页(拟)

+

这是基于你现有风格的一版布局草图:筛选区 + 表格分页 + 详情弹窗(不在此页展示)。看完告诉我是否需要调整筛选项/列。

+ +
+
+
筛选区
+
+
+
用户名/账号(模糊)
+
操作模块(下拉)
+
操作类型(下拉)
+
时间范围(起止)
+
请求关键字(URL/内容)
+ + +
+

自动脱敏:password/token/authorization;超长参数截断;异常请求也记录。

+
+
+
+ +
+
+
表格列(可配置)
+
+
+ 列建议:时间|账号(loginName)|姓名(actualName)|角色|模块|类型|URL|方法|IP|地区|结果|操作(详情) +
+
+
分页:pageNum / pageSize / total
+
+
+
+
+ +
+
+
A
+
+

就按这个布局做

+

如果你更偏向现有 `support/operate-log` 的样式,我也可以完全复用那一套组件结构。

+
+
+
+
B
+
+

需要调整筛选项/列

+

你告诉我必须要的筛选与列,我按你的习惯改到位。

+
+
+
diff --git a/.superpowers/brainstorm/62699-1778123142/state/server-stopped b/.superpowers/brainstorm/62699-1778123142/state/server-stopped new file mode 100644 index 0000000..e0aa50f --- /dev/null +++ b/.superpowers/brainstorm/62699-1778123142/state/server-stopped @@ -0,0 +1 @@ +{"reason":"idle timeout","timestamp":1778125002586} diff --git a/.superpowers/brainstorm/62699-1778123142/state/server.log b/.superpowers/brainstorm/62699-1778123142/state/server.log new file mode 100644 index 0000000..35b846b --- /dev/null +++ b/.superpowers/brainstorm/62699-1778123142/state/server.log @@ -0,0 +1,3 @@ +{"type":"server-started","port":56120,"host":"127.0.0.1","url_host":"localhost","url":"http://localhost:56120","screen_dir":"/Users/wang/sanduoyun/developspace/smart-flow-master/.superpowers/brainstorm/62699-1778123142/content","state_dir":"/Users/wang/sanduoyun/developspace/smart-flow-master/.superpowers/brainstorm/62699-1778123142/state"} +{"type":"screen-added","file":"/Users/wang/sanduoyun/developspace/smart-flow-master/.superpowers/brainstorm/62699-1778123142/content/operate-log-page-layout.html"} +{"type":"server-stopped","reason":"idle timeout"} diff --git a/.superpowers/brainstorm/62699-1778123142/state/server.pid b/.superpowers/brainstorm/62699-1778123142/state/server.pid new file mode 100644 index 0000000..716dc43 --- /dev/null +++ b/.superpowers/brainstorm/62699-1778123142/state/server.pid @@ -0,0 +1 @@ +62708 diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..477a1b2 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 1024-lab + +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. diff --git a/docs/.DS_Store b/docs/.DS_Store new file mode 100644 index 0000000..d314c95 Binary files /dev/null and b/docs/.DS_Store differ diff --git a/logs/sa-admin/dev/debug/debug.log b/logs/sa-admin/dev/debug/debug.log new file mode 100644 index 0000000..d4918c7 --- /dev/null +++ b/logs/sa-admin/dev/debug/debug.log @@ -0,0 +1,8825 @@ +[2026-06-02 18:54:57,768][DEBUG][main] Found key 'AnsiColor.BRIGHT_GREEN' in PropertySource 'ansi' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:57,774][DEBUG][background-preinit] Logging Provider: org.jboss.logging.Log4j2LoggerProvider (LoggerProviders.java:162) +[2026-06-02 18:54:57,776][DEBUG][main] Found key 'AnsiColor.DEFAULT' in PropertySource 'ansi' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:57,782][DEBUG][background-preinit] Trying to load META-INF/validation.xml for XML based Validator configuration. (ValidationXmlParser.java:122) +[2026-06-02 18:54:57,782][DEBUG][background-preinit] Trying to load META-INF/validation.xml via TCCL (ResourceLoaderHelper.java:61) +[2026-06-02 18:54:57,783][DEBUG][background-preinit] Trying to load META-INF/validation.xml via Hibernate Validator's class loader (ResourceLoaderHelper.java:67) +[2026-06-02 18:54:57,783][DEBUG][background-preinit] No META-INF/validation.xml found. Using annotation based configuration only. (ValidationXmlParser.java:129) +[2026-06-02 18:54:57,786][DEBUG][background-preinit] Cannot find jakarta.persistence.Persistence on classpath. Assuming non JPA 2 environment. All properties will per default be traversable. (TraversableResolvers.java:61) +[2026-06-02 18:54:57,805][DEBUG][background-preinit] Loaded expression factory via original TCCL (ResourceBundleMessageInterpolator.java:175) +[2026-06-02 18:54:57,852][DEBUG][main] Running with Spring Boot v3.3.1, Spring v6.1.10 (StartupInfoLogger.java:51) +[2026-06-02 18:54:57,853][DEBUG][main] Loading source class net.lab1024.sa.admin.AdminApplication (SpringApplication.java:687) +[2026-06-02 18:54:57,869][DEBUG][background-preinit] HV000252: Using org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider as property node name provider. (ValidatorFactoryConfigurationHelper.java:355) +[2026-06-02 18:54:57,875][DEBUG][background-preinit] HV000234: Using org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator as ValidatorFactory-scoped message interpolator. (ValidatorFactoryConfigurationHelper.java:447) +[2026-06-02 18:54:57,875][DEBUG][background-preinit] HV000234: Using org.hibernate.validator.internal.engine.resolver.TraverseAllTraversableResolver as ValidatorFactory-scoped traversable resolver. (ValidatorFactoryConfigurationHelper.java:448) +[2026-06-02 18:54:57,875][DEBUG][background-preinit] HV000234: Using org.hibernate.validator.internal.util.ExecutableParameterNameProvider as ValidatorFactory-scoped parameter name provider. (ValidatorFactoryConfigurationHelper.java:449) +[2026-06-02 18:54:57,875][DEBUG][background-preinit] HV000234: Using org.hibernate.validator.internal.engine.DefaultClockProvider as ValidatorFactory-scoped clock provider. (ValidatorFactoryConfigurationHelper.java:450) +[2026-06-02 18:54:57,875][DEBUG][background-preinit] HV000234: Using org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory as ValidatorFactory-scoped script evaluator factory. (ValidatorFactoryConfigurationHelper.java:451) +[2026-06-02 18:54:57,899][DEBUG][main] Refreshing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244 (AbstractApplicationContext.java:671) +[2026-06-02 18:54:57,918][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.context.annotation.internalConfigurationAnnotationProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:57,933][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.internalCachingMetadataReaderFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:57,986][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/config/MvcConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:57,986][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/config/OperateLogAspectConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:57,989][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/interceptor/AdminInterceptor.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,013][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/category/controller/CategoryController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,020][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/category/manager/CategoryCacheManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,020][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/category/service/CategoryQueryService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,020][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/category/service/CategoryService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,022][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,026][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/goods/service/GoodsService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,027][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/bank/BankController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,028][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/bank/BankService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,031][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,031][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,031][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,035][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,036][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,038][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/leave/controller/LeaveController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,039][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/leave/manager/LeaveManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,039][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/leave/service/LeaveService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,040][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/notice/controller/NoticeController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,045][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/notice/manager/NoticeManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,045][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeEmployeeService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,046][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,046][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeTypeService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,046][DEBUG][main] Ignored because not a concrete top-level class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/adapter/AbstractWarmFlowAdapter.class] (ClassPathScanningCandidateComponentProvider.java:482) +[2026-06-02 18:54:58,047][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/adapter/AddSignatureAdapter.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,047][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/adapter/DeputeAdapter.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,047][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/adapter/ReductionSignatureAdapter.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,048][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/adapter/TransferAdapter.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,052][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/controller/DefController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,053][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/controller/ExecuteController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,053][DEBUG][main] Ignored because not a concrete top-level class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/dao/FlowDefinitionDao.class] (ClassPathScanningCandidateComponentProvider.java:482) +[2026-06-02 18:54:58,063][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/handler/FlowProcessEventHandler.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,064][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/handler/WorkflowPermissionHandler.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,065][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/listener/WorkflowGlobalListener.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,065][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/service/FlowDefinitionService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,066][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/service/impl/FlowInstanceServiceImpl.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,067][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/service/impl/FlowTaskServiceImpl.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,067][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/service/impl/HandlerSelectServiceImpl.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,067][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/service/impl/HhDefServiceImpl.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,068][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/service/impl/NodeExtServiceImpl.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,068][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/datascope/DataScopeController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,069][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/datascope/MyBatisPlugin.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,072][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,072][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/datascope/service/DataScopeSqlConfigService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,072][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/datascope/service/DataScopeViewService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,073][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/department/controller/DepartmentController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,074][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,074][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/department/service/DepartmentService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,075][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/employee/controller/EmployeeController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,077][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/employee/manager/EmployeeManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,077][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/employee/service/EmployeeService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,078][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/login/controller/LoginController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,079][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/login/service/LoginService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,079][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/menu/controller/MenuController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,080][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/menu/service/MenuService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,081][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/message/AdminMessageController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,081][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/position/controller/PositionController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,082][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/position/manager/PositionManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,082][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/position/service/PositionService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,082][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/controller/RoleController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,082][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/controller/RoleDataScopeController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,083][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/controller/RoleEmployeeController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,083][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/controller/RoleMenuController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,085][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/manager/RoleDataScopeManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,085][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/manager/RoleEmployeeManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,085][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/manager/RoleMenuManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,086][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/service/RoleDataScopeService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,086][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/service/RoleEmployeeService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,086][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/service/RoleMenuService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,086][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/service/RoleService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,087][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminApiEncryptController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,087][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminCacheController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,087][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminChangeLogController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,088][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminConfigController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,088][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminDataMaskingDemoController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,089][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminDictController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,089][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminFileController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,089][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminHeartBeatController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,089][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminHelpDocController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,089][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminLoginLogController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,090][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminOperateLogController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,090][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminProtectController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,090][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminReloadController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,090][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminSerialNumberController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,093][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/support/AdminSmartJobController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,103][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/common/swagger/SchemaEnumPropertyCustomizer.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,106][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/common/util/SmartTableMetadataUtil.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,106][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/common/util/SpringUtils.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,107][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/AsyncConfig$AsyncExceptionConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,107][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/AsyncConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,107][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/CacheConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,110][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/CorsFilterConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,111][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/DataSourceConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,111][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/FileConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,111][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/HeartBeatConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,112][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/JsonConfig$StringToLocalDate.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,112][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/JsonConfig$StringToLocalDateTime.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,112][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/JsonConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,112][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/MybatisDatabaseIdProviderConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,113][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/MybatisPlusConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,113][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/RedisConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,113][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/RepeatSubmitConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,114][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/RestTemplateConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,115][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/ScheduleConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,115][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/SwaggerConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,116][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/SystemEnvironmentConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,117][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/TokenConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,117][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/UrlConfig.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,117][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/config/YamlProcessor.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,119][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/handler/GlobalExceptionHandler.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,119][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/handler/MybatisPlusFillHandler.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,120][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/listener/WebServerListener.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,120][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/apiencrypt/advice/DecryptRequestAdvice.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,120][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/apiencrypt/advice/EncryptResponseAdvice.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,121][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptServiceSmImpl.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,121][DEBUG][main] Ignored because not a concrete top-level class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/cache/CacheService.class] (ClassPathScanningCandidateComponentProvider.java:482) +[2026-06-02 18:54:58,122][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/captcha/CaptchaController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,122][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/captcha/CaptchaService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,122][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/changelog/controller/ChangeLogController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,123][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/changelog/service/ChangeLogService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,124][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/codegenerator/controller/CodeGeneratorController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,125][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,126][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorTemplateService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,128][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/config/ConfigController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,130][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/config/ConfigService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,133][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/datatracer/controller/DataTracerController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,134][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/datatracer/manager/DataTracerManger.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,135][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/datatracer/service/DataTracerChangeContentService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,135][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/datatracer/service/DataTracerService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,135][DEBUG][main] Ignored because not a concrete top-level class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/dict/dao/DictDao.class] (ClassPathScanningCandidateComponentProvider.java:482) +[2026-06-02 18:54:58,135][DEBUG][main] Ignored because not a concrete top-level class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/dict/dao/DictDataDao.class] (ClassPathScanningCandidateComponentProvider.java:482) +[2026-06-02 18:54:58,137][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/dict/manager/DictManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,137][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/dict/service/DictService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,137][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/feedback/controller/FeedbackController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,138][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/feedback/service/FeedbackService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,138][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/file/controller/FileController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,139][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/file/service/FileService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,140][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordHandler.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,140][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/heartbeat/HeartBeatService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,142][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/helpdoc/controller/HelpDocController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,144][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/helpdoc/manager/HelpDocManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,144][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocCatalogService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,145][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,145][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocUserService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,145][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/api/SmartJobClientManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,146][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/api/SmartJobService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,148][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/config/SmartJobAutoConfiguration.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,150][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/repository/SmartJobRepository.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,151][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/sample/SmartJobSample1.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,152][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/sample/SmartJobSample2.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,152][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/loginlog/LoginLogService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,153][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/mail/MailService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,153][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/message/controller/MessageController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,154][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/message/service/MessageManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,154][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/message/service/MessageService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,155][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/operatelog/OperateLogService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,157][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/redis/RedisService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,157][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/redis/RedissonPasswordConfigurationCustomizer.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,158][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/redis/RedissonService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,158][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/reload/ReloadCommand.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,158][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/reload/ReloadService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,158][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/reload/core/SmartReloadManager.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,162][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/securityprotect/service/Level3ProtectConfigService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,162][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,162][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/securityprotect/service/SecurityLoginService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,162][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/securityprotect/service/SecurityPasswordService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,166][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberRecordService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,167][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberInternService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,167][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/table/TableColumnController.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:58,167][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/table/TableColumnService.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,087][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.AutoConfigurationPackages' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,097][DEBUG][main] @EnableAutoConfiguration was declared on a class in the package 'net.lab1024.sa.admin'. Automatic @Repository and @Entity scanning is enabled. (AutoConfigurationPackages.java:213) +[2026-06-02 18:54:59,097][DEBUG][main] Scanning for Redis repositories in packages net.lab1024.sa.admin. (RepositoryConfigurationDelegate.java:153) +[2026-06-02 18:54:59,152][DEBUG][main] Creating shared instance of singleton bean 'net.lab1024.sa.admin.AdminApplication#MapperScannerRegistrar#0' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,154][DEBUG][main] Creating shared instance of singleton bean 'org.dromara.warm.flow.spring.boot.config.FlowAutoConfig#MapperScannerRegistrar#0' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,154][DEBUG][main] Creating shared instance of singleton bean 'propertySourcesPlaceholderConfigurer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,158][DEBUG][main] Logging initialized using 'class org.apache.ibatis.logging.slf4j.Slf4jImpl' adapter. (LogFactory.java:112) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/bank/BankDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/leave/dao/LeaveDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/dao/FlowDefinitionDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/flow/mapper/WarmFlowMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,170][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,171][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,171][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/menu/dao/MenuDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,171][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/position/dao/PositionDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,171][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/dao/RoleDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,171][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/dao/RoleDataScopeDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,171][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/dao/RoleEmployeeDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,171][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/net/lab1024/sa/admin/module/system/role/dao/RoleMenuDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,172][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/changelog/dao/ChangeLogDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,172][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorConfigDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,172][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,172][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/config/ConfigDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,172][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/datatracer/dao/DataTracerDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,172][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/dict/dao/DictDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/dict/dao/DictDataDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/feedback/dao/FeedbackDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/file/dao/FileDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocCatalogDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/repository/SmartJobDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/job/repository/SmartJobLogDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/loginlog/LoginLogDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/mail/MailTemplateDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/message/dao/MessageDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/operatelog/OperateLogDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/reload/dao/ReloadItemDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/reload/dao/ReloadResultDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/securityprotect/dao/LoginFailDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/securityprotect/dao/PasswordLogDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,173][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,174][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberRecordDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,174][DEBUG][main] Identified candidate component class: file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/net/lab1024/sa/base/module/support/table/TableColumnDao.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,174][DEBUG][main] Creating MapperFactoryBean with name 'categoryDao' and 'net.lab1024.sa.admin.module.business.category.dao.CategoryDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,176][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'categoryDao'. (Logger.java:49) +[2026-06-02 18:54:59,176][DEBUG][main] Creating MapperFactoryBean with name 'goodsDao' and 'net.lab1024.sa.admin.module.business.goods.dao.GoodsDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,177][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'goodsDao'. (Logger.java:49) +[2026-06-02 18:54:59,177][DEBUG][main] Creating MapperFactoryBean with name 'bankDao' and 'net.lab1024.sa.admin.module.business.oa.bank.BankDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,177][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'bankDao'. (Logger.java:49) +[2026-06-02 18:54:59,177][DEBUG][main] Creating MapperFactoryBean with name 'enterpriseDao' and 'net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,177][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'enterpriseDao'. (Logger.java:49) +[2026-06-02 18:54:59,177][DEBUG][main] Creating MapperFactoryBean with name 'enterpriseEmployeeDao' and 'net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'enterpriseEmployeeDao'. (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Creating MapperFactoryBean with name 'invoiceDao' and 'net.lab1024.sa.admin.module.business.oa.invoice.InvoiceDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'invoiceDao'. (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Creating MapperFactoryBean with name 'leaveDao' and 'net.lab1024.sa.admin.module.business.oa.leave.dao.LeaveDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'leaveDao'. (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Creating MapperFactoryBean with name 'noticeDao' and 'net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'noticeDao'. (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Creating MapperFactoryBean with name 'noticeTypeDao' and 'net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeTypeDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'noticeTypeDao'. (Logger.java:49) +[2026-06-02 18:54:59,178][DEBUG][main] Creating MapperFactoryBean with name 'flowDefinitionDao' and 'net.lab1024.sa.admin.module.flow.dao.FlowDefinitionDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowDefinitionDao'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'warmFlowMapper' and 'net.lab1024.sa.admin.module.flow.mapper.WarmFlowMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'warmFlowMapper'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'departmentDao' and 'net.lab1024.sa.admin.module.system.department.dao.DepartmentDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'departmentDao'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'employeeDao' and 'net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'employeeDao'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'menuDao' and 'net.lab1024.sa.admin.module.system.menu.dao.MenuDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'menuDao'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'positionDao' and 'net.lab1024.sa.admin.module.system.position.dao.PositionDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'positionDao'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'roleDao' and 'net.lab1024.sa.admin.module.system.role.dao.RoleDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'roleDao'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'roleDataScopeDao' and 'net.lab1024.sa.admin.module.system.role.dao.RoleDataScopeDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'roleDataScopeDao'. (Logger.java:49) +[2026-06-02 18:54:59,179][DEBUG][main] Creating MapperFactoryBean with name 'roleEmployeeDao' and 'net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'roleEmployeeDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'roleMenuDao' and 'net.lab1024.sa.admin.module.system.role.dao.RoleMenuDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'roleMenuDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'changeLogDao' and 'net.lab1024.sa.base.module.support.changelog.dao.ChangeLogDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'changeLogDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'codeGeneratorConfigDao' and 'net.lab1024.sa.base.module.support.codegenerator.dao.CodeGeneratorConfigDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'codeGeneratorConfigDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'codeGeneratorDao' and 'net.lab1024.sa.base.module.support.codegenerator.dao.CodeGeneratorDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'codeGeneratorDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'configDao' and 'net.lab1024.sa.base.module.support.config.ConfigDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'configDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'dataTracerDao' and 'net.lab1024.sa.base.module.support.datatracer.dao.DataTracerDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'dataTracerDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'dictDao' and 'net.lab1024.sa.base.module.support.dict.dao.DictDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'dictDao'. (Logger.java:49) +[2026-06-02 18:54:59,180][DEBUG][main] Creating MapperFactoryBean with name 'dictDataDao' and 'net.lab1024.sa.base.module.support.dict.dao.DictDataDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'dictDataDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'feedbackDao' and 'net.lab1024.sa.base.module.support.feedback.dao.FeedbackDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'feedbackDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'fileDao' and 'net.lab1024.sa.base.module.support.file.dao.FileDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'fileDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'heartBeatRecordDao' and 'net.lab1024.sa.base.module.support.heartbeat.HeartBeatRecordDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'heartBeatRecordDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'helpDocCatalogDao' and 'net.lab1024.sa.base.module.support.helpdoc.dao.HelpDocCatalogDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'helpDocCatalogDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'helpDocDao' and 'net.lab1024.sa.base.module.support.helpdoc.dao.HelpDocDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'helpDocDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'smartJobDao' and 'net.lab1024.sa.base.module.support.job.repository.SmartJobDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'smartJobDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'smartJobLogDao' and 'net.lab1024.sa.base.module.support.job.repository.SmartJobLogDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'smartJobLogDao'. (Logger.java:49) +[2026-06-02 18:54:59,181][DEBUG][main] Creating MapperFactoryBean with name 'loginLogDao' and 'net.lab1024.sa.base.module.support.loginlog.LoginLogDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'loginLogDao'. (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Creating MapperFactoryBean with name 'mailTemplateDao' and 'net.lab1024.sa.base.module.support.mail.MailTemplateDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'mailTemplateDao'. (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Creating MapperFactoryBean with name 'messageDao' and 'net.lab1024.sa.base.module.support.message.dao.MessageDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'messageDao'. (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Creating MapperFactoryBean with name 'operateLogDao' and 'net.lab1024.sa.base.module.support.operatelog.OperateLogDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'operateLogDao'. (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Creating MapperFactoryBean with name 'reloadItemDao' and 'net.lab1024.sa.base.module.support.reload.dao.ReloadItemDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'reloadItemDao'. (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Creating MapperFactoryBean with name 'reloadResultDao' and 'net.lab1024.sa.base.module.support.reload.dao.ReloadResultDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'reloadResultDao'. (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Creating MapperFactoryBean with name 'loginFailDao' and 'net.lab1024.sa.base.module.support.securityprotect.dao.LoginFailDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'loginFailDao'. (Logger.java:49) +[2026-06-02 18:54:59,182][DEBUG][main] Creating MapperFactoryBean with name 'passwordLogDao' and 'net.lab1024.sa.base.module.support.securityprotect.dao.PasswordLogDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,183][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'passwordLogDao'. (Logger.java:49) +[2026-06-02 18:54:59,183][DEBUG][main] Creating MapperFactoryBean with name 'serialNumberDao' and 'net.lab1024.sa.base.module.support.serialnumber.dao.SerialNumberDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,183][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'serialNumberDao'. (Logger.java:49) +[2026-06-02 18:54:59,183][DEBUG][main] Creating MapperFactoryBean with name 'serialNumberRecordDao' and 'net.lab1024.sa.base.module.support.serialnumber.dao.SerialNumberRecordDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,183][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'serialNumberRecordDao'. (Logger.java:49) +[2026-06-02 18:54:59,183][DEBUG][main] Creating MapperFactoryBean with name 'tableColumnDao' and 'net.lab1024.sa.base.module.support.table.TableColumnDao' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,183][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'tableColumnDao'. (Logger.java:49) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowDefinitionMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowFormMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowHisTaskMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowInstanceMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowNodeMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowSkipMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowTaskMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/FlowUserMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Identified candidate component class: URL [jar:file:/Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/dromara/warm/warm-flow-mybatis-plus-core/1.7.3/warm-flow-mybatis-plus-core-1.7.3.jar!/org/dromara/warm/flow/orm/mapper/WarmMapper.class] (ClassPathScanningCandidateComponentProvider.java:476) +[2026-06-02 18:54:59,185][DEBUG][main] Creating MapperFactoryBean with name 'flowDefinitionMapper' and 'org.dromara.warm.flow.orm.mapper.FlowDefinitionMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowDefinitionMapper'. (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Creating MapperFactoryBean with name 'flowFormMapper' and 'org.dromara.warm.flow.orm.mapper.FlowFormMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowFormMapper'. (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Creating MapperFactoryBean with name 'flowHisTaskMapper' and 'org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowHisTaskMapper'. (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Creating MapperFactoryBean with name 'flowInstanceMapper' and 'org.dromara.warm.flow.orm.mapper.FlowInstanceMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowInstanceMapper'. (Logger.java:49) +[2026-06-02 18:54:59,186][DEBUG][main] Creating MapperFactoryBean with name 'flowNodeMapper' and 'org.dromara.warm.flow.orm.mapper.FlowNodeMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowNodeMapper'. (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Creating MapperFactoryBean with name 'flowSkipMapper' and 'org.dromara.warm.flow.orm.mapper.FlowSkipMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowSkipMapper'. (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Creating MapperFactoryBean with name 'flowTaskMapper' and 'org.dromara.warm.flow.orm.mapper.FlowTaskMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowTaskMapper'. (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Creating MapperFactoryBean with name 'flowUserMapper' and 'org.dromara.warm.flow.orm.mapper.FlowUserMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'flowUserMapper'. (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Creating MapperFactoryBean with name 'warmMapper' and 'org.dromara.warm.flow.orm.mapper.WarmMapper' mapperInterface (Logger.java:49) +[2026-06-02 18:54:59,187][DEBUG][main] Enabling autowire by type for MapperFactoryBean with name 'warmMapper'. (Logger.java:49) +[2026-06-02 18:54:59,267][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.sql.init.dependency.DatabaseInitializationDependencyConfigurer$DependsOnDatabaseInitializationPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,290][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,292][DEBUG][main] Creating shared instance of singleton bean 'springUtils' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,292][DEBUG][main] Creating shared instance of singleton bean 'preserveErrorControllerTargetClassPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,292][DEBUG][main] Creating shared instance of singleton bean 'cn.hutool.extra.spring.SpringUtil' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,292][DEBUG][main] Creating shared instance of singleton bean 'springdocBeanFactoryPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,295][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.context.event.internalEventListenerFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,295][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionalEventListenerFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,302][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.context.annotation.internalAutowiredAnnotationProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,303][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.context.annotation.internalCommonAnnotationProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,305][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.context.properties.ConfigurationPropertiesBindingPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,305][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.context.internalConfigurationPropertiesBinder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,306][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.aop.config.internalAutoProxyCreator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,313][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.context.annotation.internalScheduledAnnotationProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,313][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.scheduling.annotation.SchedulingConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,315][DEBUG][main] Creating shared instance of singleton bean 'methodValidationPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,317][DEBUG][main] Autowiring by type from bean name 'methodValidationPostProcessor' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,318][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.context.properties.EnableConfigurationPropertiesRegistrar.methodValidationExcludeFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,325][DEBUG][main] Creating shared instance of singleton bean 'persistenceExceptionTranslationPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,325][DEBUG][main] Autowiring by type from bean name 'persistenceExceptionTranslationPostProcessor' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,326][DEBUG][main] Creating shared instance of singleton bean 'smartReloadManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'defaultPointcutAdvisor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'dataSourceConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.transaction.config.internalTransactionAdvisor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.cache.config.internalCacheAdvisor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.cache.annotation.ProxyCachingConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.cache.config.internalJCacheAdvisor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,327][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.cache.jcache.config.ProxyJCacheConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,331][DEBUG][main] Found AspectJ method: public java.lang.Object net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.aroundController(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable (ReflectiveAspectJAdvisorFactory.java:269) +[2026-06-02 18:54:59,332][DEBUG][main] Found AspectJ method: public java.lang.Object net.lab1024.sa.base.module.support.repeatsubmit.RepeatSubmitAspect.around(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable (ReflectiveAspectJAdvisorFactory.java:269) +[2026-06-02 18:54:59,335][DEBUG][main] Found AspectJ method: public java.lang.Object io.micrometer.observation.aop.ObservedAspect.observeClass(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable (ReflectiveAspectJAdvisorFactory.java:269) +[2026-06-02 18:54:59,335][DEBUG][main] Found AspectJ method: public java.lang.Object io.micrometer.observation.aop.ObservedAspect.observeMethod(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable (ReflectiveAspectJAdvisorFactory.java:269) +[2026-06-02 18:54:59,392][DEBUG][main] Creating shared instance of singleton bean 'jCacheOperationSource' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,404][DEBUG][main] Creating shared instance of singleton bean 'jCacheInterceptor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,404][DEBUG][main] Autowiring by type from bean name 'jCacheInterceptor' via factory method to bean named 'jCacheOperationSource' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,407][DEBUG][main] Autowiring by type from bean name 'org.springframework.cache.config.internalJCacheAdvisor' via factory method to bean named 'jCacheOperationSource' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,407][DEBUG][main] Autowiring by type from bean name 'org.springframework.cache.config.internalJCacheAdvisor' via factory method to bean named 'jCacheInterceptor' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,410][DEBUG][main] Creating shared instance of singleton bean 'cacheOperationSource' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,415][DEBUG][main] Creating shared instance of singleton bean 'cacheInterceptor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,415][DEBUG][main] Autowiring by type from bean name 'cacheInterceptor' via factory method to bean named 'cacheOperationSource' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,528][DEBUG][main] Autowiring by type from bean name 'org.springframework.cache.config.internalCacheAdvisor' via factory method to bean named 'cacheOperationSource' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,528][DEBUG][main] Autowiring by type from bean name 'org.springframework.cache.config.internalCacheAdvisor' via factory method to bean named 'cacheInterceptor' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,537][DEBUG][main] Creating shared instance of singleton bean 'transactionAttributeSource' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,544][DEBUG][main] Creating shared instance of singleton bean 'transactionInterceptor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,545][DEBUG][main] Autowiring by type from bean name 'transactionInterceptor' via factory method to bean named 'transactionAttributeSource' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,547][DEBUG][main] Autowiring by type from bean name 'org.springframework.transaction.config.internalTransactionAdvisor' via factory method to bean named 'transactionAttributeSource' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,547][DEBUG][main] Autowiring by type from bean name 'org.springframework.transaction.config.internalTransactionAdvisor' via factory method to bean named 'transactionInterceptor' (ConstructorResolver.java:945) +[2026-06-02 18:54:59,549][DEBUG][main] Creating shared instance of singleton bean 'paginationInterceptor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,549][DEBUG][main] Creating shared instance of singleton bean 'mybatisPlusConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,558][DEBUG][main] Creating shared instance of singleton bean 'myBatisPlugin' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,561][DEBUG][main] Found key 'spring.datasource.driver-class-name' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,561][DEBUG][main] Found key 'spring.datasource.url' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,561][DEBUG][main] Found key 'spring.datasource.username' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,561][DEBUG][main] Found key 'spring.datasource.password' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,561][DEBUG][main] Found key 'spring.datasource.initial-size' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,562][DEBUG][main] Found key 'spring.datasource.min-idle' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,562][DEBUG][main] Found key 'spring.datasource.max-active' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,562][DEBUG][main] Found key 'spring.datasource.max-wait' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,562][DEBUG][main] Found key 'spring.datasource.time-between-eviction-runs-millis' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,562][DEBUG][main] Found key 'spring.datasource.min-evictable-idle-time-millis' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,562][DEBUG][main] Found key 'spring.datasource.filters' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,563][DEBUG][main] Found key 'spring.datasource.druid.username' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,563][DEBUG][main] Found key 'spring.datasource.druid.password' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,563][DEBUG][main] Found key 'spring.datasource.druid.login.enabled' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,563][DEBUG][main] Found key 'spring.datasource.druid.method.pointcut' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:54:59,564][DEBUG][main] Creating shared instance of singleton bean 'jdkRegexpMethodPointcut' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,568][DEBUG][main] Creating shared instance of singleton bean 'reloadCommand' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,568][DEBUG][main] Creating shared instance of singleton bean 'reloadItemDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,570][DEBUG][main] Creating shared instance of singleton bean 'sqlSessionFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:54:59,572][DEBUG][main] Creating shared instance of singleton bean 'druidDataSource' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,620][DEBUG][main] Property 'configuration' or 'configLocation' not specified, using default MyBatis Configuration (Logger.java:49) +[2026-06-02 18:55:00,639][DEBUG][main] Registered plugin: 'com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor@1d3546f9' (Logger.java:49) +[2026-06-02 18:55:00,639][DEBUG][main] Registered plugin: 'net.lab1024.sa.admin.module.system.datascope.MyBatisPlugin@229514ff' (Logger.java:49) +[2026-06-02 18:55:00,715][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/category/CategoryMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,726][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/goods/GoodsMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,736][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/oa/bank/BankMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,744][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/oa/enterprise/EnterpriseEmployeeMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,754][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/oa/enterprise/EnterpriseMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,761][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/oa/invoice/InvoiceMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,768][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/oa/leave/LeaveMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,783][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/business/oa/notice/NoticeMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,792][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/flow/WarmFLowMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,799][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/PositionMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,806][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/department/DepartmentMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,814][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/employee/EmployeeMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,821][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/menu/MenuMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,826][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/role/RoleDataScopeMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,832][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/role/RoleEmployeeMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,837][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/role/RoleMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,842][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes/mapper/system/role/RoleMenuMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,850][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/ChangeLogMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,852][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/CodeGeneratorMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,856][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/ConfigMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,861][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/DataTracerMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,866][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/DictDataMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,870][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/DictMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,875][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/FeedbackMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,881][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/FileMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,885][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/HeartBeatRecordMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,891][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/HelpDocDao.xml]' (Logger.java:49) +[2026-06-02 18:55:00,897][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/LoginFailMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,903][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/LoginLogMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,908][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/MessageMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,913][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/OperateLogMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,918][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/PasswordLogMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,923][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/ReloadItemMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,927][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/ReloadResultMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,931][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/SerialNumberMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,934][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/SerialNumberRecordMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,939][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/SmartJobLogMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,944][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/SmartJobMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,949][DEBUG][main] Parsed mapper file: 'file [/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-base/target/classes/mapper/support/TableColumnMapper.xml]' (Logger.java:49) +[2026-06-02 18:55:00,953][DEBUG][main] Get /172.20.10.11 network interface (Sequence.java:155) +[2026-06-02 18:55:00,954][DEBUG][main] Get network interface info: name:en0 (en0) (Sequence.java:159) +[2026-06-02 18:55:00,954][DEBUG][main] Initialization Sequence datacenterId:23 workerId:20 (Sequence.java:103) +[2026-06-02 18:55:00,958][DEBUG][main] Creating shared instance of singleton bean 'dataSourceScriptDatabaseInitializer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,958][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,960][DEBUG][main] Creating shared instance of singleton bean 'spring.sql.init-org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,960][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.context.properties.BoundConfigurationProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,965][DEBUG][main] Autowiring by type from bean name 'dataSourceScriptDatabaseInitializer' via factory method to bean named 'druidDataSource' (ConstructorResolver.java:945) +[2026-06-02 18:55:00,966][DEBUG][main] Autowiring by type from bean name 'dataSourceScriptDatabaseInitializer' via factory method to bean named 'spring.sql.init-org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:00,969][DEBUG][main] Creating shared instance of singleton bean 'sqlSessionTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,969][DEBUG][main] Creating shared instance of singleton bean 'com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,970][DEBUG][main] Creating shared instance of singleton bean 'mybatis-plus-com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,973][DEBUG][main] Autowiring by type from bean name 'com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration' via constructor to bean named 'mybatis-plus-com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:00,973][DEBUG][main] Autowiring by type from bean name 'com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration' via constructor to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:00,975][DEBUG][main] Creating shared instance of singleton bean 'databaseIdProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,975][DEBUG][main] Creating shared instance of singleton bean 'mybatisDatabaseIdProviderConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:00,980][DEBUG][main] Autowiring by type from bean name 'sqlSessionTemplate' via factory method to bean named 'sqlSessionFactory' (ConstructorResolver.java:945) +[2026-06-02 18:55:00,997][DEBUG][main] Creating shared instance of singleton bean 'reloadResultDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,009][DEBUG][main] Found key 'reload.interval-seconds' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:01,011][DEBUG][main] Creating shared instance of singleton bean 'webServerFactoryCustomizerBeanPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,011][DEBUG][main] Creating shared instance of singleton bean 'errorPageRegistrarBeanPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,011][DEBUG][main] Creating shared instance of singleton bean 'meterRegistryPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,011][DEBUG][main] Autowiring by type from bean name 'meterRegistryPostProcessor' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,013][DEBUG][main] Creating shared instance of singleton bean 'healthEndpointGroupsBeanPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,014][DEBUG][main] Creating shared instance of singleton bean 'metricsRepositoryMethodInvocationListenerBeanPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,015][DEBUG][main] Creating shared instance of singleton bean 'observationRegistryPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,016][DEBUG][main] Creating shared instance of singleton bean 'projectingArgumentResolverBeanPostProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,025][DEBUG][main] Unable to locate ThemeSource with name 'themeSource': using default [org.springframework.ui.context.support.ResourceBundleThemeSource@a20898c] (UiApplicationContextUtils.java:86) +[2026-06-02 18:55:01,026][DEBUG][main] Creating shared instance of singleton bean 'tomcatServletWebServerFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,026][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryConfiguration$EmbeddedTomcat' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,045][DEBUG][main] Creating shared instance of singleton bean 'websocketServletWebServerCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,045][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration$TomcatWebSocketConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,047][DEBUG][main] Creating shared instance of singleton bean 'servletWebServerFactoryCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,047][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,048][DEBUG][main] Creating shared instance of singleton bean 'server-org.springframework.boot.autoconfigure.web.ServerProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,056][DEBUG][main] Autowiring by type from bean name 'servletWebServerFactoryCustomizer' via factory method to bean named 'server-org.springframework.boot.autoconfigure.web.ServerProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,058][DEBUG][main] Creating shared instance of singleton bean 'sslBundleRegistry' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,058][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,058][DEBUG][main] Creating shared instance of singleton bean 'spring.ssl-org.springframework.boot.autoconfigure.ssl.SslProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,060][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration' via constructor to bean named 'spring.ssl-org.springframework.boot.autoconfigure.ssl.SslProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,061][DEBUG][main] Creating shared instance of singleton bean 'sslPropertiesSslBundleRegistrar' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,061][DEBUG][main] Creating shared instance of singleton bean 'fileWatcher' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,062][DEBUG][main] Autowiring by type from bean name 'sslPropertiesSslBundleRegistrar' via factory method to bean named 'fileWatcher' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,066][DEBUG][main] Creating shared instance of singleton bean 'tomcatServletWebServerFactoryCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,066][DEBUG][main] Autowiring by type from bean name 'tomcatServletWebServerFactoryCustomizer' via factory method to bean named 'server-org.springframework.boot.autoconfigure.web.ServerProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,067][DEBUG][main] Creating shared instance of singleton bean 'tomcatWebServerFactoryCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,067][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration$TomcatWebServerFactoryCustomizerConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,068][DEBUG][main] Autowiring by type from bean name 'tomcatWebServerFactoryCustomizer' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,068][DEBUG][main] Autowiring by type from bean name 'tomcatWebServerFactoryCustomizer' via factory method to bean named 'server-org.springframework.boot.autoconfigure.web.ServerProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,071][DEBUG][main] Creating shared instance of singleton bean 'localeCharsetMappingsCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,071][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,071][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.HttpEncodingAutoConfiguration' via constructor to bean named 'server-org.springframework.boot.autoconfigure.web.ServerProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,086][DEBUG][main] Creating shared instance of singleton bean 'errorPageCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,086][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,087][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration' via constructor to bean named 'server-org.springframework.boot.autoconfigure.web.ServerProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,088][DEBUG][main] Creating shared instance of singleton bean 'dispatcherServletRegistration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,088][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletRegistrationConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,089][DEBUG][main] Creating shared instance of singleton bean 'dispatcherServlet' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,089][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration$DispatcherServletConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,089][DEBUG][main] Creating shared instance of singleton bean 'spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,092][DEBUG][main] Autowiring by type from bean name 'dispatcherServlet' via factory method to bean named 'spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,105][DEBUG][main] Autowiring by type from bean name 'dispatcherServletRegistration' via factory method to bean named 'dispatcherServlet' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,106][DEBUG][main] Autowiring by type from bean name 'dispatcherServletRegistration' via factory method to bean named 'spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,106][DEBUG][main] Creating shared instance of singleton bean 'multipartConfigElement' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,106][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,107][DEBUG][main] Creating shared instance of singleton bean 'spring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,109][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.MultipartAutoConfiguration' via constructor to bean named 'spring.servlet.multipart-org.springframework.boot.autoconfigure.web.servlet.MultipartProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,114][DEBUG][main] Autowiring by type from bean name 'errorPageCustomizer' via factory method to bean named 'dispatcherServletRegistration' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,167][DEBUG][main] Code archive: /Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/springframework/boot/spring-boot/3.3.1/spring-boot-3.3.1.jar (DocumentRoot.java:81) +[2026-06-02 18:55:01,167][DEBUG][main] Code archive: /Users/wang/wang/javasoft/apache-maven-3.9.12/repo/org/springframework/boot/spring-boot/3.3.1/spring-boot-3.3.1.jar (DocumentRoot.java:125) +[2026-06-02 18:55:01,167][DEBUG][main] None of the document roots [src/main/webapp, public, static] point to a directory and will be ignored. (DocumentRoot.java:149) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [Connector["http-nio-1024"]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [StandardService[Tomcat]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [StandardServer[-1]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [StandardServer[-1]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [StandardServer[-1]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@3da55998] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@3da55998] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@3da55998] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [StandardService[Tomcat]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [StandardService[Tomcat]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][DEBUG][main] Setting state for [StandardEngine[Tomcat]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [SimpleRealm[StandardEngine[Tomcat]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [SimpleRealm[StandardEngine[Tomcat]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [SimpleRealm[StandardEngine[Tomcat]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [SimpleRealm[StandardEngine[Tomcat]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [SimpleRealm[StandardEngine[Tomcat]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,190][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,191][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,191][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,191][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,197][DEBUG][main] Setting state for [org.apache.catalina.webresources.StandardRoot@52667676] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,197][DEBUG][main] Setting state for [org.apache.catalina.webresources.StandardRoot@52667676] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,197][DEBUG][main] Setting state for [org.apache.catalina.webresources.StandardRoot@52667676] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [org.apache.catalina.webresources.DirResourceSet@1f370472] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [org.apache.catalina.webresources.DirResourceSet@1f370472] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [org.apache.catalina.webresources.DirResourceSet@1f370472] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [org.apache.catalina.webresources.DirResourceSet@1f370472] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [org.apache.catalina.webresources.DirResourceSet@1f370472] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [org.apache.catalina.webresources.StandardRoot@52667676] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [org.apache.catalina.webresources.StandardRoot@52667676] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [WebappLoader[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [WebappLoader[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Setting state for [WebappLoader[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,198][DEBUG][main] Starting this Loader (DirectJDKLog.java:173) +[2026-06-02 18:55:01,202][DEBUG][main] Setting state for [WebappLoader[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,202][DEBUG][main] Setting state for [WebappLoader[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@278cbf5a] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@278cbf5a] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@278cbf5a] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@278cbf5a] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@278cbf5a] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@7ca0b05e] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@7ca0b05e] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@7ca0b05e] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@7ca0b05e] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@7ca0b05e] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@237bdbcb] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,218][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@237bdbcb] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@237bdbcb] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@237bdbcb] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [org.apache.catalina.webresources.JarResourceSet@237bdbcb] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [NonLoginAuthenticator[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [NonLoginAuthenticator[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,219][DEBUG][main] Setting state for [NonLoginAuthenticator[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [NonLoginAuthenticator[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [NonLoginAuthenticator[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [StandardContextValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [StandardContextValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [StandardContextValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [StandardContextValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [StandardContextValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,220][DEBUG][main] No manager found. Checking if cluster manager should be used. Cluster configured: [false], Application distributable: [false] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,223][DEBUG][main] Configured a manager of class [org.apache.catalina.session.StandardManager] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,224][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@543196f9] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,224][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@543196f9] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,224][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@543196f9] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,224][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@543196f9] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,224][DEBUG][main] Setting state for [org.apache.catalina.deploy.NamingResourcesImpl@543196f9] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,226][DEBUG][main] Published root WebApplicationContext as ServletContext attribute with name [org.springframework.web.context.WebApplicationContext.ROOT] (ServletWebServerApplicationContext.java:290) +[2026-06-02 18:55:01,228][DEBUG][main] Creating shared instance of singleton bean 'druidServlet' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,230][DEBUG][main] Creating shared instance of singleton bean 'filterRegistrationBean' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,233][DEBUG][main] Creating shared instance of singleton bean 'webMvcObservationFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,233][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,233][DEBUG][main] Creating shared instance of singleton bean 'observationRegistry' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,233][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,236][DEBUG][main] Creating shared instance of singleton bean 'propertiesObservationFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,236][DEBUG][main] Creating shared instance of singleton bean 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,238][DEBUG][main] Autowiring by type from bean name 'propertiesObservationFilter' via factory method to bean named 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,240][DEBUG][main] Creating shared instance of singleton bean 'metricsObservationHandlerGrouping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,240][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$OnlyMetricsConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,241][DEBUG][main] Creating shared instance of singleton bean 'defaultMeterObservationHandler' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,241][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$MeterObservationHandlerConfiguration$OnlyMetricsMeterObservationHandlerConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,242][DEBUG][main] Creating shared instance of singleton bean 'simpleMeterRegistry' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,242][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,243][DEBUG][main] Creating shared instance of singleton bean 'simpleConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,243][DEBUG][main] Creating shared instance of singleton bean 'management.simple.metrics.export-org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,244][DEBUG][main] Autowiring by type from bean name 'simpleConfig' via factory method to bean named 'management.simple.metrics.export-org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,246][DEBUG][main] Creating shared instance of singleton bean 'micrometerClock' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,246][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,247][DEBUG][main] Autowiring by type from bean name 'simpleMeterRegistry' via factory method to bean named 'simpleConfig' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,247][DEBUG][main] Autowiring by type from bean name 'simpleMeterRegistry' via factory method to bean named 'micrometerClock' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,260][DEBUG][main] Creating shared instance of singleton bean 'propertiesMeterFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,260][DEBUG][main] Creating shared instance of singleton bean 'management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,262][DEBUG][main] Autowiring by type from bean name 'propertiesMeterFilter' via factory method to bean named 'management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,264][DEBUG][main] Creating shared instance of singleton bean 'metricsHttpClientUriTagFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,264][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration$MeterFilterConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,265][DEBUG][main] Autowiring by type from bean name 'metricsHttpClientUriTagFilter' via factory method to bean named 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,265][DEBUG][main] Autowiring by type from bean name 'metricsHttpClientUriTagFilter' via factory method to bean named 'management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,266][DEBUG][main] Creating shared instance of singleton bean 'metricsHttpServerUriTagFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,266][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.web.servlet.WebMvcObservationAutoConfiguration$MeterFilterConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,267][DEBUG][main] Autowiring by type from bean name 'metricsHttpServerUriTagFilter' via factory method to bean named 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,267][DEBUG][main] Autowiring by type from bean name 'metricsHttpServerUriTagFilter' via factory method to bean named 'management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,269][DEBUG][main] Autowiring by type from bean name 'defaultMeterObservationHandler' via factory method to bean named 'simpleMeterRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,269][DEBUG][main] Autowiring by type from bean name 'defaultMeterObservationHandler' via factory method to bean named 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,272][DEBUG][main] Autowiring by type from bean name 'webMvcObservationFilter' via factory method to bean named 'observationRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,272][DEBUG][main] Autowiring by type from bean name 'webMvcObservationFilter' via factory method to bean named 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,275][DEBUG][main] Creating shared instance of singleton bean 'servletEndpointRegistrar' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,275][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration$WebMvcServletEndpointManagementContextConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,275][DEBUG][main] Creating shared instance of singleton bean 'management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,277][DEBUG][main] Creating shared instance of singleton bean 'servletEndpointDiscoverer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,277][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration$WebEndpointServletConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,277][DEBUG][main] Autowiring by type from bean name 'servletEndpointDiscoverer' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,278][DEBUG][main] Creating shared instance of singleton bean 'webEndpointPathMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,278][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,279][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration' via constructor to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,279][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration' via constructor to bean named 'management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,281][DEBUG][main] Creating shared instance of singleton bean 'servletExposeExcludePropertyEndpointFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,281][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.web.ServletEndpointManagementContextConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,282][DEBUG][main] Autowiring by type from bean name 'servletExposeExcludePropertyEndpointFilter' via factory method to bean named 'management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,287][DEBUG][main] Autowiring by type from bean name 'servletEndpointRegistrar' via factory method to bean named 'management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,287][DEBUG][main] Autowiring by type from bean name 'servletEndpointRegistrar' via factory method to bean named 'servletEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,287][DEBUG][main] Autowiring by type from bean name 'servletEndpointRegistrar' via factory method to bean named 'dispatcherServletRegistration' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,294][DEBUG][main] Creating shared instance of singleton bean 'corsFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,294][DEBUG][main] Creating shared instance of singleton bean 'corsFilterConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,294][DEBUG][main] Found key 'access-control-allow-origin' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:01,301][DEBUG][main] Creating shared instance of singleton bean 'requestContextFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,303][DEBUG][main] Creating shared instance of singleton bean 'formContentFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,303][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,305][DEBUG][main] Creating shared instance of singleton bean 'saFirewallCheckFilterForJakartaServlet' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,305][DEBUG][main] Creating shared instance of singleton bean 'cn.dev33.satoken.spring.SaTokenContextRegister' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,306][DEBUG][main] Creating shared instance of singleton bean 'characterEncodingFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,312][DEBUG][main] Mapping filters: webMvcObservationFilter urls=[/*] order=-2147483647, filterRegistrationBean urls=[/*] order=2147483647, characterEncodingFilter urls=[/*] order=-2147483648, formContentFilter urls=[/*] order=-9900, saFirewallCheckFilterForJakartaServlet urls=[/*] order=-1000, requestContextFilter urls=[/*] order=-105, corsFilter urls=[/*] order=2147483647 (ServletContextInitializerBeans.java:235) +[2026-06-02 18:55:01,312][DEBUG][main] Mapping servlets: druidServlet urls=[/druid/*], dispatcherServlet urls=[/] (ServletContextInitializerBeans.java:235) +[2026-06-02 18:55:01,315][DEBUG][main] Add container child [StandardWrapper[druidServlet]] to container [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,315][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,315][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,315][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,315][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,315][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[druidServlet]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Add container child [StandardWrapper[dispatcherServlet]] to container [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,316][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardWrapperValve[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,317][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[].StandardWrapper[dispatcherServlet]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,325][DEBUG][main] Setting state for [StandardManager[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,325][DEBUG][main] Setting state for [StandardManager[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,325][DEBUG][main] Setting state for [StandardManager[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,325][DEBUG][main] Setting state for [org.springframework.boot.web.embedded.tomcat.LazySessionIdGenerator@2530baf6] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,326][DEBUG][main] Setting state for [org.springframework.boot.web.embedded.tomcat.LazySessionIdGenerator@2530baf6] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,326][DEBUG][main] Setting state for [org.springframework.boot.web.embedded.tomcat.LazySessionIdGenerator@2530baf6] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,326][DEBUG][main] Setting state for [org.springframework.boot.web.embedded.tomcat.LazySessionIdGenerator@2530baf6] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,326][DEBUG][main] Setting state for [org.springframework.boot.web.embedded.tomcat.LazySessionIdGenerator@2530baf6] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,330][DEBUG][main] Setting state for [StandardManager[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,330][DEBUG][main] Setting state for [StandardManager[StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,332][DEBUG][main] Filter 'requestContextFilter' configured for use (GenericFilterBean.java:240) +[2026-06-02 18:55:01,333][DEBUG][main] Filter 'webMvcObservationFilter' configured for use (GenericFilterBean.java:240) +[2026-06-02 18:55:01,335][DEBUG][main] Filter 'corsFilter' configured for use (GenericFilterBean.java:240) +[2026-06-02 18:55:01,335][DEBUG][main] Filter 'characterEncodingFilter' configured for use (GenericFilterBean.java:240) +[2026-06-02 18:55:01,335][DEBUG][main] Filter 'formContentFilter' configured for use (GenericFilterBean.java:240) +[2026-06-02 18:55:01,335][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,335][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost].TomcatEmbeddedContext[]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [ErrorReportValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [ErrorReportValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [ErrorReportValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [ErrorReportValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [ErrorReportValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [StandardHostValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,336][DEBUG][main] Setting state for [StandardHostValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardHostValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardHostValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardHostValve[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat].StandardHost[localhost]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardEngine[Tomcat].StandardHost[localhost]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [AccessLogValve[StandardEngine[Tomcat]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [AccessLogValve[StandardEngine[Tomcat]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,337][DEBUG][main] Setting state for [AccessLogValve[StandardEngine[Tomcat]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [AccessLogValve[StandardEngine[Tomcat]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [AccessLogValve[StandardEngine[Tomcat]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardEngineValve[StandardEngine[Tomcat]]] to [INITIALIZING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardEngineValve[StandardEngine[Tomcat]]] to [INITIALIZED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardEngineValve[StandardEngine[Tomcat]]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardEngineValve[StandardEngine[Tomcat]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardEngineValve[StandardEngine[Tomcat]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat]]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardPipeline[StandardEngine[Tomcat]]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,338][DEBUG][main] Setting state for [StandardEngine[Tomcat]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,339][DEBUG][main] Setting state for [StandardEngine[Tomcat]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,339][DEBUG][main] Setting state for [org.apache.catalina.mapper.MapperListener@425a5c2e] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,339][DEBUG][main] Setting state for [org.apache.catalina.mapper.MapperListener@425a5c2e] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,340][DEBUG][main] Registered host [localhost] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,340][DEBUG][main] Register Wrapper [druidServlet] in Context [] for service [StandardService[Tomcat]] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,340][DEBUG][main] Register Wrapper [dispatcherServlet] in Context [] for service [StandardService[Tomcat]] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,340][DEBUG][main] Register Context [] for service [StandardService[Tomcat]] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,340][DEBUG][main] Register host [localhost] at domain [null] for service [StandardService[Tomcat]] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,340][DEBUG][main] Setting state for [org.apache.catalina.mapper.MapperListener@425a5c2e] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,340][DEBUG][main] Setting state for [StandardService[Tomcat]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,342][DEBUG][main] Setting state for [StandardServer[-1]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,347][DEBUG][main] Creating shared instance of singleton bean 'adminApplication' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,348][DEBUG][main] Creating shared instance of singleton bean 'mvcConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,348][DEBUG][main] Creating shared instance of singleton bean 'adminInterceptor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,349][DEBUG][main] Creating shared instance of singleton bean 'loginService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,356][DEBUG][main] Creating shared instance of singleton bean 'employeeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,357][DEBUG][main] Creating shared instance of singleton bean 'employeeDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,369][DEBUG][main] Creating shared instance of singleton bean 'departmentDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,377][DEBUG][main] Creating shared instance of singleton bean 'employeeManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,382][DEBUG][main] Creating shared instance of singleton bean 'roleEmployeeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,382][DEBUG][main] Creating shared instance of singleton bean 'roleEmployeeDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,389][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:01,389][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,391][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,391][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,391][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,392][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,392][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,392][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,392][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,393][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:01,393][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,394][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,394][DEBUG][main] Creating shared instance of singleton bean 'roleDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,394][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:01,394][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 7, name=org.springframework.boot:type=Admin,name=SpringApplication, attribute=Ready (LoggingProviderImpl.java:230) +[2026-06-02 18:55:01,395][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: [127.0.0.1] exception: (Log.java:236) +javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1073) ~[?:?] + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:632) ~[?:?] + at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:679) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1449) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1310) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1405) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:639) ~[?:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) ~[?:?] + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:01,401][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,401][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@58e412ce: connectionId=rmi://127.0.0.1 7] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:01,402][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@58e412ce: connectionId=rmi://127.0.0.1 7] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:01,409][DEBUG][main] Creating shared instance of singleton bean 'roleEmployeeManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,443][DEBUG][main] Creating shared instance of singleton bean 'departmentService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,443][DEBUG][main] Creating shared instance of singleton bean 'departmentCacheManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,450][DEBUG][main] Creating shared instance of singleton bean 'securityPasswordService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,451][DEBUG][main] Creating shared instance of singleton bean 'passwordLogDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,462][DEBUG][main] Creating shared instance of singleton bean 'level3ProtectConfigService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,462][DEBUG][main] Creating shared instance of singleton bean 'configService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,463][DEBUG][main] Creating shared instance of singleton bean 'configDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,477][DEBUG][main] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:01,480][DEBUG][main] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62eb918] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:01,491][DEBUG][main] Creating shared instance of singleton bean 'dataScopeSqlConfigService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,491][DEBUG][main] Creating shared instance of singleton bean 'dataScopeViewService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,492][DEBUG][main] Creating shared instance of singleton bean 'roleDataScopeDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,577][DEBUG][main] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:01,578][DEBUG][main] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:01,580][DEBUG][main] ==> Preparing: SELECT config_id,config_key,config_value,config_name,remark,update_time,create_time FROM t_config (BaseJdbcLogger.java:135) +[2026-06-02 18:55:01,652][DEBUG][main] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:01,731][DEBUG][main] <== Total: 2 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:01,733][DEBUG][main] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62eb918] (Logger.java:49) +[2026-06-02 18:55:01,739][DEBUG][main] Trying to load META-INF/validation.xml for XML based Validator configuration. (ValidationXmlParser.java:122) +[2026-06-02 18:55:01,739][DEBUG][main] Trying to load META-INF/validation.xml via TCCL (ResourceLoaderHelper.java:61) +[2026-06-02 18:55:01,739][DEBUG][main] Trying to load META-INF/validation.xml via Hibernate Validator's class loader (ResourceLoaderHelper.java:67) +[2026-06-02 18:55:01,739][DEBUG][main] No META-INF/validation.xml found. Using annotation based configuration only. (ValidationXmlParser.java:129) +[2026-06-02 18:55:01,739][DEBUG][main] Cannot find jakarta.persistence.Persistence on classpath. Assuming non JPA 2 environment. All properties will per default be traversable. (TraversableResolvers.java:61) +[2026-06-02 18:55:01,739][DEBUG][main] Loaded expression factory via original TCCL (ResourceBundleMessageInterpolator.java:175) +[2026-06-02 18:55:01,740][DEBUG][main] HV000252: Using org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider as property node name provider. (ValidatorFactoryConfigurationHelper.java:355) +[2026-06-02 18:55:01,740][DEBUG][main] HV000234: Using org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator as ValidatorFactory-scoped message interpolator. (ValidatorFactoryConfigurationHelper.java:447) +[2026-06-02 18:55:01,740][DEBUG][main] HV000234: Using org.hibernate.validator.internal.engine.resolver.TraverseAllTraversableResolver as ValidatorFactory-scoped traversable resolver. (ValidatorFactoryConfigurationHelper.java:448) +[2026-06-02 18:55:01,740][DEBUG][main] HV000234: Using org.hibernate.validator.internal.util.ExecutableParameterNameProvider as ValidatorFactory-scoped parameter name provider. (ValidatorFactoryConfigurationHelper.java:449) +[2026-06-02 18:55:01,740][DEBUG][main] HV000234: Using org.hibernate.validator.internal.engine.DefaultClockProvider as ValidatorFactory-scoped clock provider. (ValidatorFactoryConfigurationHelper.java:450) +[2026-06-02 18:55:01,740][DEBUG][main] HV000234: Using org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory as ValidatorFactory-scoped script evaluator factory. (ValidatorFactoryConfigurationHelper.java:451) +[2026-06-02 18:55:01,821][DEBUG][main] Creating shared instance of singleton bean 'positionDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,831][DEBUG][main] Creating shared instance of singleton bean 'captchaService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,831][DEBUG][main] Creating shared instance of singleton bean 'systemEnvironment' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,831][DEBUG][main] Creating shared instance of singleton bean 'systemEnvironmentConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,832][DEBUG][main] Found key 'spring.profiles.active' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:01,832][DEBUG][main] Found key 'project.name' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:01,833][DEBUG][main] Creating shared instance of singleton bean 'redisService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,833][DEBUG][main] Creating shared instance of singleton bean 'stringRedisTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,834][DEBUG][main] Creating shared instance of singleton bean 'org.redisson.spring.starter.RedissonAutoConfigurationV2' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,834][DEBUG][main] Creating shared instance of singleton bean 'redissonPasswordConfigurationCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,836][DEBUG][main] Creating shared instance of singleton bean 'spring.redis.redisson-org.redisson.spring.starter.RedissonProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,837][DEBUG][main] Creating shared instance of singleton bean 'spring.data.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,845][DEBUG][main] Creating shared instance of singleton bean 'redissonConnectionFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,845][DEBUG][main] Creating shared instance of singleton bean 'redisson' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,845][DEBUG][main] Creating shared instance of singleton bean 'redisConnectionDetails' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,845][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:01,846][DEBUG][main] Autowiring by type from bean name 'redisConnectionDetails' via factory method to bean named 'spring.data.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:01,891][DEBUG][main] Using SLF4J as the default logging framework (InternalLoggerFactory.java:63) +[2026-06-02 18:55:01,892][DEBUG][main] -Dio.netty.globalEventExecutor.quietPeriodSeconds: 1 (GlobalEventExecutor.java:53) +[2026-06-02 18:55:01,896][DEBUG][main] -Dio.netty.threadLocalMap.stringBuilder.initialSize: 1024 (InternalThreadLocalMap.java:100) +[2026-06-02 18:55:01,896][DEBUG][main] -Dio.netty.threadLocalMap.stringBuilder.maxSize: 4096 (InternalThreadLocalMap.java:101) +[2026-06-02 18:55:01,907][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,908][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 8, name=org.springframework.boot:type=Admin,name=SpringApplication, attribute=Ready (LoggingProviderImpl.java:230) +[2026-06-02 18:55:01,909][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: [127.0.0.1] exception: (Log.java:236) +javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1073) ~[?:?] + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:632) ~[?:?] + at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:679) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1449) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1310) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1405) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:639) ~[?:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) ~[?:?] + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:01,910][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:01,910][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:01,910][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@299d682c: connectionId=rmi://127.0.0.1 8] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:01,910][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@299d682c: connectionId=rmi://127.0.0.1 8] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:01,921][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:3c:9e:b1:fc:89:f7:33:d3, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:RSA, Length:2048, Cert Id:3044386973, Valid from:2016/7/7 07:48, Valid until:2030/12/31 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,922][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:87:4f:23:f4:bb:f6:3b:d8:06:a7:ae:b0:a1:2c:f4:67:2b:ba:2a, Subject:CN=Legion of the Bouncy Castle Inc., OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:DSA, Length:2048, Cert Id:2266411741, Valid from:2022/1/25 08:58, Valid until:2027/1/25 08:58 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,926][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0b:ae:66:bc:5a:ba:7f:95:87:c6:f9:e9:04:e3:33:04, Subject:CN=DigiCert Timestamp 2024, O=DigiCert, C=US, Issuer:CN=DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA, O="DigiCert, Inc.", C=US, Key type:RSA, Length:4096, Cert Id:3934399196, Valid from:2024/9/26 08:00, Valid until:2035/11/26 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,926][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:07:36:37:b7:24:54:7c:d8:47:ac:fd:28:66:2a:5e:5b, Subject:CN=DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:4096, Cert Id:3207540671, Valid from:2022/3/23 08:00, Valid until:2037/3/23 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,926][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:0e:9b:18:8e:f9:d0:2d:e7:ef:db:50:e2:08:40:18:5a, Subject:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:4096, Cert Id:845088433, Valid from:2022/8/1 08:00, Valid until:2031/11/10 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,954][DEBUG][main] X509Certificate: Alg:SHA1withDSA, Serial:10, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Key type:DSA, Length:1024, Cert Id:1776909028, Valid from:2001/4/25 15:00, Valid until:2020/4/25 15:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,954][DEBUG][main] X509Certificate: Alg:SHA1withDSA, Serial:04:7f, Subject:CN=Legion of the Bouncy Castle Inc., OU=Java Software Code Signing, O=Sun Microsystems Inc, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Key type:DSA, Length:1024, Cert Id:2271114451, Valid from:2017/3/11 09:15, Valid until:2020/4/25 15:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,955][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:03:01:9a:02:3a:ff:58:b1:6b:d6:d5:ea:e6:17:f0:66, Subject:CN=DigiCert Timestamp Responder, O=DigiCert, C=US, Issuer:CN=DigiCert Assured ID CA-1, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3795447098, Valid from:2014/10/22 08:00, Valid until:2024/10/22 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,955][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:06:fd:f9:03:96:03:ad:ea:00:0a:eb:3f:27:bb:ba:1b, Subject:CN=DigiCert Assured ID CA-1, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3183604018, Valid from:2006/11/10 08:00, Valid until:2021/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,958][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:3c:9e:b1:fc:89:f7:33:d3, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:RSA, Length:2048, Cert Id:3044386973, Valid from:2016/7/7 07:48, Valid until:2030/12/31 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,958][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:4e:fb:7b:c6:2e:2b:04:9e, Subject:CN=Legion of the Bouncy Castle Inc., OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:DSA, Length:2048, Cert Id:3640944114, Valid from:2017/3/11 09:07, Valid until:2022/3/11 09:07 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,959][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,959][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,975][DEBUG][main] X509Certificate: Alg:SHA1withDSA, Serial:10, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Key type:DSA, Length:1024, Cert Id:1776909028, Valid from:2001/4/25 15:00, Valid until:2020/4/25 15:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,975][DEBUG][main] X509Certificate: Alg:SHA1withDSA, Serial:04:7f, Subject:CN=Legion of the Bouncy Castle Inc., OU=Java Software Code Signing, O=Sun Microsystems Inc, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Key type:DSA, Length:1024, Cert Id:2271114451, Valid from:2017/3/11 09:15, Valid until:2020/4/25 15:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,977][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:03:01:9a:02:3a:ff:58:b1:6b:d6:d5:ea:e6:17:f0:66, Subject:CN=DigiCert Timestamp Responder, O=DigiCert, C=US, Issuer:CN=DigiCert Assured ID CA-1, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3795447098, Valid from:2014/10/22 08:00, Valid until:2024/10/22 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,977][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:06:fd:f9:03:96:03:ad:ea:00:0a:eb:3f:27:bb:ba:1b, Subject:CN=DigiCert Assured ID CA-1, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3183604018, Valid from:2006/11/10 08:00, Valid until:2021/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,982][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:3c:9e:b1:fc:89:f7:33:d3, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:RSA, Length:2048, Cert Id:3044386973, Valid from:2016/7/7 07:48, Valid until:2030/12/31 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,982][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:4e:fb:7b:c6:2e:2b:04:9e, Subject:CN=Legion of the Bouncy Castle Inc., OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:DSA, Length:2048, Cert Id:3640944114, Valid from:2017/3/11 09:07, Valid until:2022/3/11 09:07 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,984][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:01,985][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,006][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,007][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:20:a8:44:47:ee:c4:58:6d:a2:6b:97:b3:5c:f2:6f, Subject:CN=Open Preservation Foundation, O=Open Preservation Foundation, L=London, C=GB, Issuer:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3262224480, Valid from:2019/7/5 08:00, Valid until:2020/5/20 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,007][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08, Subject:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3406727098, Valid from:2013/10/22 20:00, Valid until:2028/10/22 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,007][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,007][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,010][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,010][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:20:a8:44:47:ee:c4:58:6d:a2:6b:97:b3:5c:f2:6f, Subject:CN=Open Preservation Foundation, O=Open Preservation Foundation, L=London, C=GB, Issuer:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3262224480, Valid from:2019/7/5 08:00, Valid until:2020/5/20 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,010][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08, Subject:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3406727098, Valid from:2013/10/22 20:00, Valid until:2028/10/22 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,010][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,010][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,012][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,012][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:20:a8:44:47:ee:c4:58:6d:a2:6b:97:b3:5c:f2:6f, Subject:CN=Open Preservation Foundation, O=Open Preservation Foundation, L=London, C=GB, Issuer:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3262224480, Valid from:2019/7/5 08:00, Valid until:2020/5/20 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,012][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08, Subject:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3406727098, Valid from:2013/10/22 20:00, Valid until:2028/10/22 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,012][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,012][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,014][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,014][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:20:a8:44:47:ee:c4:58:6d:a2:6b:97:b3:5c:f2:6f, Subject:CN=Open Preservation Foundation, O=Open Preservation Foundation, L=London, C=GB, Issuer:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3262224480, Valid from:2019/7/5 08:00, Valid until:2020/5/20 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,015][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08, Subject:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3406727098, Valid from:2013/10/22 20:00, Valid until:2028/10/22 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,015][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,015][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,016][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,016][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:20:a8:44:47:ee:c4:58:6d:a2:6b:97:b3:5c:f2:6f, Subject:CN=Open Preservation Foundation, O=Open Preservation Foundation, L=London, C=GB, Issuer:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3262224480, Valid from:2019/7/5 08:00, Valid until:2020/5/20 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,016][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08, Subject:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3406727098, Valid from:2013/10/22 20:00, Valid until:2028/10/22 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,017][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,017][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,018][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,018][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:20:a8:44:47:ee:c4:58:6d:a2:6b:97:b3:5c:f2:6f, Subject:CN=Open Preservation Foundation, O=Open Preservation Foundation, L=London, C=GB, Issuer:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3262224480, Valid from:2019/7/5 08:00, Valid until:2020/5/20 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,018][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08, Subject:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3406727098, Valid from:2013/10/22 20:00, Valid until:2028/10/22 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,018][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,018][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,019][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,019][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:20:a8:44:47:ee:c4:58:6d:a2:6b:97:b3:5c:f2:6f, Subject:CN=Open Preservation Foundation, O=Open Preservation Foundation, L=London, C=GB, Issuer:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3262224480, Valid from:2019/7/5 08:00, Valid until:2020/5/20 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,019][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:09:18:1b:5f:d5:bb:66:75:53:43:b5:6f:95:50:08, Subject:CN=DigiCert SHA2 Assured ID Code Signing CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3406727098, Valid from:2013/10/22 20:00, Valid until:2028/10/22 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,019][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:cd:3f:85:68:ae:76:c6:1b:b0:fe:71:60:cc:a7:6d, Subject:CN=TIMESTAMP-SHA256-2019-10-15, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:380147180, Valid from:2019/10/1 08:00, Valid until:2030/10/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,019][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:a1:25:d6:d6:32:1b:7e:41:e4:05:da:36:97:c2:15, Subject:CN=DigiCert SHA2 Assured ID Timestamping CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2614494003, Valid from:2016/1/7 20:00, Valid until:2031/1/7 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,022][DEBUG][main] -Dio.netty.eventLoopThreads: 20 (MultithreadEventLoopGroup.java:44) +[2026-06-02 18:55:02,033][DEBUG][main] -Dio.netty.noUnsafe: false (PlatformDependent0.java:550) +[2026-06-02 18:55:02,033][DEBUG][main] Java version: 21 (PlatformDependent0.java:1068) +[2026-06-02 18:55:02,034][DEBUG][main] sun.misc.Unsafe.theUnsafe: available (PlatformDependent0.java:140) +[2026-06-02 18:55:02,034][DEBUG][main] sun.misc.Unsafe base methods: all available (PlatformDependent0.java:199) +[2026-06-02 18:55:02,034][DEBUG][main] sun.misc.Unsafe.storeFence: available (PlatformDependent0.java:231) +[2026-06-02 18:55:02,034][DEBUG][main] java.nio.Buffer.address: available (PlatformDependent0.java:274) +[2026-06-02 18:55:02,034][DEBUG][main] direct buffer constructor: unavailable: Reflective setAccessible(true) disabled (PlatformDependent0.java:360) +[2026-06-02 18:55:02,034][DEBUG][main] java.nio.Bits.unaligned: available, true (PlatformDependent0.java:438) +[2026-06-02 18:55:02,035][DEBUG][main] jdk.internal.misc.Unsafe.allocateUninitializedArray(int): unavailable: class io.netty.util.internal.PlatformDependent0$7 cannot access class jdk.internal.misc.Unsafe (in module java.base) because module java.base does not export jdk.internal.misc to unnamed module @30c7da1e (PlatformDependent0.java:506) +[2026-06-02 18:55:02,035][DEBUG][main] java.nio.DirectByteBuffer.(long, {int,long}): unavailable (PlatformDependent0.java:536) +[2026-06-02 18:55:02,035][DEBUG][main] sun.misc.Unsafe: available (PlatformDependent.java:1186) +[2026-06-02 18:55:02,035][DEBUG][main] -Dio.netty.tmpdir: /var/folders/kn/4p33snzd7v14kyzt43vz7t5r0000gn/T (java.io.tmpdir) (PlatformDependent.java:1332) +[2026-06-02 18:55:02,036][DEBUG][main] -Dio.netty.bitMode: 64 (sun.arch.data.model) (PlatformDependent.java:1411) +[2026-06-02 18:55:02,036][DEBUG][main] Platform: MacOS (PlatformDependent.java:1154) +[2026-06-02 18:55:02,036][DEBUG][main] -Dio.netty.maxDirectMemory: -1 bytes (PlatformDependent.java:178) +[2026-06-02 18:55:02,036][DEBUG][main] -Dio.netty.uninitializedArrayAllocationThreshold: -1 (PlatformDependent.java:185) +[2026-06-02 18:55:02,036][DEBUG][main] java.nio.ByteBuffer.cleaner(): available (CleanerJava9.java:71) +[2026-06-02 18:55:02,036][DEBUG][main] -Dio.netty.noPreferDirect: false (PlatformDependent.java:205) +[2026-06-02 18:55:02,036][DEBUG][main] -Dio.netty.noKeySetOptimization: false (NioEventLoop.java:110) +[2026-06-02 18:55:02,036][DEBUG][main] -Dio.netty.selectorAutoRebuildThreshold: 512 (NioEventLoop.java:111) +[2026-06-02 18:55:02,038][DEBUG][main] org.jctools-core.MpscChunkedArrayQueue: available (PlatformDependent.java:1029) +[2026-06-02 18:55:02,047][DEBUG][main] -Djava.net.preferIPv4Stack: false (NetUtil.java:148) +[2026-06-02 18:55:02,047][DEBUG][main] -Djava.net.preferIPv6Addresses: false (NetUtil.java:149) +[2026-06-02 18:55:02,048][DEBUG][main] Loopback interface: lo0 (lo0, 0:0:0:0:0:0:0:1%lo0) (NetUtilInitializations.java:145) +[2026-06-02 18:55:02,048][DEBUG][main] Failed to get SOMAXCONN from sysctl and file /proc/sys/net/core/somaxconn. Default: 128 (NetUtil.java:206) +[2026-06-02 18:55:02,055][DEBUG][main] Default ResolvedAddressTypes: IPV4_PREFERRED (DnsNameResolver.java:147) +[2026-06-02 18:55:02,055][DEBUG][main] Localhost address: localhost/127.0.0.1 (DnsNameResolver.java:148) +[2026-06-02 18:55:02,055][DEBUG][main] Windows hostname: null (DnsNameResolver.java:157) +[2026-06-02 18:55:02,055][DEBUG][main] Default search domains: [] (DnsNameResolver.java:170) +[2026-06-02 18:55:02,056][DEBUG][main] Default UnixResolverOptions{ndots=1, timeout=5, attempts=16} (DnsNameResolver.java:179) +[2026-06-02 18:55:02,060][DEBUG][main] -Dio.netty.hostsFileRefreshInterval: 0 (DefaultHostsFileEntriesResolver.java:53) +[2026-06-02 18:55:02,068][DEBUG][main] -Dio.netty.leakDetection.level: simple (ResourceLeakDetector.java:129) +[2026-06-02 18:55:02,068][DEBUG][main] -Dio.netty.leakDetection.targetRecords: 4 (ResourceLeakDetector.java:130) +[2026-06-02 18:55:02,068][DEBUG][main] Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@123fd460 (ResourceLeakDetectorFactory.java:196) +[2026-06-02 18:55:02,085][DEBUG][main] -Dio.netty.processId: 66984 (auto-detected) (DefaultChannelId.java:84) +[2026-06-02 18:55:02,085][DEBUG][main] -Dio.netty.machineId: 22:e2:2d:ff:fe:b7:d6:75 (auto-detected) (DefaultChannelId.java:106) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.numHeapArenas: 20 (PooledByteBufAllocator.java:157) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.numDirectArenas: 20 (PooledByteBufAllocator.java:158) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.pageSize: 8192 (PooledByteBufAllocator.java:160) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.maxOrder: 9 (PooledByteBufAllocator.java:165) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.chunkSize: 4194304 (PooledByteBufAllocator.java:169) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.smallCacheSize: 256 (PooledByteBufAllocator.java:170) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.normalCacheSize: 64 (PooledByteBufAllocator.java:171) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.maxCachedBufferCapacity: 32768 (PooledByteBufAllocator.java:172) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.cacheTrimInterval: 8192 (PooledByteBufAllocator.java:173) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.cacheTrimIntervalMillis: 0 (PooledByteBufAllocator.java:174) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.useCacheForAllThreads: false (PooledByteBufAllocator.java:175) +[2026-06-02 18:55:02,097][DEBUG][main] -Dio.netty.allocator.maxCachedByteBuffersPerChunk: 1023 (PooledByteBufAllocator.java:176) +[2026-06-02 18:55:02,100][DEBUG][main] -Dio.netty.allocator.type: pooled (ByteBufUtil.java:89) +[2026-06-02 18:55:02,100][DEBUG][main] -Dio.netty.threadLocalDirectBufferSize: 0 (ByteBufUtil.java:101) +[2026-06-02 18:55:02,100][DEBUG][main] -Dio.netty.maxThreadLocalCharBufferSize: 16384 (ByteBufUtil.java:104) +[2026-06-02 18:55:02,102][DEBUG][main] -Dio.netty.bootstrap.extensions: null (ChannelInitializerExtensions.java:54) +[2026-06-02 18:55:02,123][DEBUG][redisson-netty-2-2] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,125][DEBUG][redisson-netty-2-3] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,127][DEBUG][redisson-netty-2-3] -Dio.netty.recycler.maxCapacityPerThread: 4096 (Recycler.java:96) +[2026-06-02 18:55:02,127][DEBUG][redisson-netty-2-3] -Dio.netty.recycler.ratio: 8 (Recycler.java:97) +[2026-06-02 18:55:02,127][DEBUG][redisson-netty-2-3] -Dio.netty.recycler.chunkSize: 32 (Recycler.java:98) +[2026-06-02 18:55:02,127][DEBUG][redisson-netty-2-3] -Dio.netty.recycler.blocking: false (Recycler.java:99) +[2026-06-02 18:55:02,127][DEBUG][redisson-netty-2-3] -Dio.netty.recycler.batchFastThreadLocalOnly: true (Recycler.java:100) +[2026-06-02 18:55:02,130][DEBUG][redisson-netty-2-3] -Dio.netty.buffer.checkAccessible: true (AbstractByteBuf.java:63) +[2026-06-02 18:55:02,130][DEBUG][redisson-netty-2-3] -Dio.netty.buffer.checkBounds: true (AbstractByteBuf.java:64) +[2026-06-02 18:55:02,130][DEBUG][redisson-netty-2-3] Loaded default ResourceLeakDetector: io.netty.util.ResourceLeakDetector@5955622a (ResourceLeakDetectorFactory.java:196) +[2026-06-02 18:55:02,141][DEBUG][redisson-netty-2-4] new connection created: RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,141][DEBUG][redisson-netty-2-5] new pubsub connection created: RedisPubSubConnection@1061906526 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc91961a1, L:/127.0.0.1:57551 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=0] (ClientConnectionsEntry.java:203) +[2026-06-02 18:55:02,144][DEBUG][redisson-netty-2-6] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,146][DEBUG][redisson-netty-2-7] new connection created: RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@59861e6c[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,146][DEBUG][redisson-netty-2-8] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,148][DEBUG][redisson-netty-2-9] new connection created: RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@120b3215[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,148][DEBUG][redisson-netty-2-10] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,150][DEBUG][redisson-netty-2-11] new connection created: RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@22f24416[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,151][DEBUG][redisson-netty-2-12] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,153][DEBUG][redisson-netty-2-13] new connection created: RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@11cd9461[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,153][DEBUG][redisson-netty-2-14] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,155][DEBUG][redisson-netty-2-15] new connection created: RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@657389f8[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,155][DEBUG][redisson-netty-2-16] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,156][DEBUG][redisson-netty-2-17] new connection created: RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@24d40cc6[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,157][DEBUG][redisson-netty-2-18] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,160][DEBUG][redisson-netty-2-19] new connection created: RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@159a689c[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,160][DEBUG][redisson-netty-2-20] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,162][DEBUG][redisson-netty-2-21] new connection created: RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6d40c24e[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,162][DEBUG][redisson-netty-2-22] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,163][DEBUG][redisson-netty-2-23] new connection created: RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1cf39af7[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,164][DEBUG][redisson-netty-2-24] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,165][DEBUG][redisson-netty-2-25] new connection created: RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1eec868f[Completed normally], command=(PING), params=[], codec=null], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,166][DEBUG][redisson-netty-2-26] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,168][DEBUG][redisson-netty-2-27] new connection created: RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6c240415[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,168][DEBUG][redisson-netty-2-28] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,171][DEBUG][redisson-netty-2-29] new connection created: RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1473c371[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,171][DEBUG][redisson-netty-2-30] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,172][DEBUG][redisson-netty-2-31] new connection created: RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@44f328e4[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,173][DEBUG][redisson-netty-2-1] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,175][DEBUG][redisson-netty-2-32] new connection created: RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@60bb1fbd[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,175][DEBUG][redisson-netty-2-2] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,176][DEBUG][redisson-netty-2-3] new connection created: RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@70fd2629[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,177][DEBUG][redisson-netty-2-4] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,178][DEBUG][redisson-netty-2-5] new connection created: RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@35b3032e[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,178][DEBUG][redisson-netty-2-6] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,180][DEBUG][redisson-netty-2-7] new connection created: RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7cdaf725[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,180][DEBUG][redisson-netty-2-8] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,181][DEBUG][redisson-netty-2-9] new connection created: RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6342bcef[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,181][DEBUG][redisson-netty-2-10] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,182][DEBUG][redisson-netty-2-11] new connection created: RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@441b627a[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,182][DEBUG][redisson-netty-2-12] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,183][DEBUG][redisson-netty-2-13] new connection created: RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@65311c93[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,183][DEBUG][redisson-netty-2-14] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,184][DEBUG][redisson-netty-2-15] new connection created: RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@332eeb0[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,184][DEBUG][redisson-netty-2-16] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,184][DEBUG][redisson-netty-2-17] new connection created: RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@56eaef00[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,184][DEBUG][redisson-netty-2-18] Connection created [addr=redis://127.0.0.1:6379] (RedisConnection.java:76) +[2026-06-02 18:55:02,185][DEBUG][redisson-netty-2-19] new connection created: RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1e23f68c[Not completed, 1 dependents], command=(PING), params=[], codec=org.redisson.client.codec.StringCodec], usage=0] (ClientConnectionsEntry.java:190) +[2026-06-02 18:55:02,212][DEBUG][main] Autowiring by type from bean name 'redissonConnectionFactory' via factory method to bean named 'redisson' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,217][DEBUG][main] Autowiring by type from bean name 'stringRedisTemplate' via factory method to bean named 'redissonConnectionFactory' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,228][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,229][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,230][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,237][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,238][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,239][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,242][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,243][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:02,261][DEBUG][main] Creating shared instance of singleton bean 'redisTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,262][DEBUG][main] Creating shared instance of singleton bean 'redisConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,270][DEBUG][main] Creating shared instance of singleton bean 'valueOperations' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,271][DEBUG][main] Autowiring by type from bean name 'valueOperations' via factory method to bean named 'stringRedisTemplate' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,278][DEBUG][main] Creating shared instance of singleton bean 'hashOperations' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,278][DEBUG][main] Autowiring by type from bean name 'hashOperations' via factory method to bean named 'redisTemplate' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,283][DEBUG][main] Creating shared instance of singleton bean 'listOperations' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,283][DEBUG][main] Autowiring by type from bean name 'listOperations' via factory method to bean named 'redisTemplate' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,288][DEBUG][main] Creating shared instance of singleton bean 'setOperations' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,288][DEBUG][main] Autowiring by type from bean name 'setOperations' via factory method to bean named 'redisTemplate' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,296][DEBUG][main] Creating shared instance of singleton bean 'loginLogService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,296][DEBUG][main] Creating shared instance of singleton bean 'loginLogDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,313][DEBUG][main] Creating shared instance of singleton bean 'roleMenuService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,313][DEBUG][main] Creating shared instance of singleton bean 'roleMenuDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,325][DEBUG][main] Creating shared instance of singleton bean 'roleMenuManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,335][DEBUG][main] Creating shared instance of singleton bean 'menuDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,348][DEBUG][main] Creating shared instance of singleton bean 'securityLoginService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,348][DEBUG][main] Creating shared instance of singleton bean 'loginFailDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,361][DEBUG][main] Creating shared instance of singleton bean 'initLocalFileService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,361][DEBUG][main] Creating shared instance of singleton bean 'fileConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,361][DEBUG][main] Found key 'file.storage.cloud.region' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.cloud.endpoint' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.cloud.bucket-name' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.cloud.access-key' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.cloud.secret-key' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.cloud.private-url-expire-seconds' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.cloud.url-prefix' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.local.upload-path' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,362][DEBUG][main] Found key 'file.storage.mode' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,368][DEBUG][main] Found key 'file.storage.local.upload-path' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,368][DEBUG][main] Found key 'file.storage.local.url-prefix' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,368][DEBUG][main] Found key 'server.servlet.context-path' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,368][DEBUG][main] Found key 'server.port' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,375][DEBUG][main] Creating shared instance of singleton bean 'apiEncryptServiceSmImpl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,383][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:3c:9e:b1:fc:89:f7:33:d3, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:RSA, Length:2048, Cert Id:3044386973, Valid from:2016/7/7 07:48, Valid until:2030/12/31 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,383][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:08:87:4f:23:f4:bb:f6:3b:d8:06:a7:ae:b0:a1:2c:f4:67:2b:ba:2a, Subject:CN=Legion of the Bouncy Castle Inc., OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:DSA, Length:2048, Cert Id:2266411741, Valid from:2022/1/25 08:58, Valid until:2027/1/25 08:58 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,385][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0b:ae:66:bc:5a:ba:7f:95:87:c6:f9:e9:04:e3:33:04, Subject:CN=DigiCert Timestamp 2024, O=DigiCert, C=US, Issuer:CN=DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA, O="DigiCert, Inc.", C=US, Key type:RSA, Length:4096, Cert Id:3934399196, Valid from:2024/9/26 08:00, Valid until:2035/11/26 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,385][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:07:36:37:b7:24:54:7c:d8:47:ac:fd:28:66:2a:5e:5b, Subject:CN=DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:4096, Cert Id:3207540671, Valid from:2022/3/23 08:00, Valid until:2037/3/23 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,385][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:0e:9b:18:8e:f9:d0:2d:e7:ef:db:50:e2:08:40:18:5a, Subject:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:4096, Cert Id:845088433, Valid from:2022/8/1 08:00, Valid until:2031/11/10 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:02,416][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,416][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,416][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,417][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 9, name=org.springframework.boot:type=Admin,name=SpringApplication, attribute=Ready (LoggingProviderImpl.java:230) +[2026-06-02 18:55:02,418][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: [127.0.0.1] exception: (Log.java:236) +javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1073) ~[?:?] + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:632) ~[?:?] + at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:679) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1449) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1310) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1405) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:639) ~[?:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) ~[?:?] + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:02,419][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,419][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,419][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@1fe50420: connectionId=rmi://127.0.0.1 9] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:02,419][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@1fe50420: connectionId=rmi://127.0.0.1 9] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:02,469][DEBUG][main] Creating shared instance of singleton bean 'mailService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,470][DEBUG][main] Creating shared instance of singleton bean 'mailTemplateDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,483][DEBUG][main] Creating shared instance of singleton bean 'mailSender' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,483][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.mail.MailSenderPropertiesConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,484][DEBUG][main] Creating shared instance of singleton bean 'spring.mail-org.springframework.boot.autoconfigure.mail.MailProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,488][DEBUG][main] Autowiring by type from bean name 'mailSender' via factory method to bean named 'spring.mail-org.springframework.boot.autoconfigure.mail.MailProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,491][DEBUG][main] MimetypesFileTypeMap: load HOME (LogSupport.java:43) +[2026-06-02 18:55:02,492][DEBUG][main] Checking system property jakarta.activation.spi.MimeTypeRegistryProvider (FactoryFinder.java:105) +[2026-06-02 18:55:02,492][DEBUG][main] not found (FactoryFinder.java:120) +[2026-06-02 18:55:02,492][DEBUG][main] Using java.util.ServiceLoader to find jakarta.activation.spi.MimeTypeRegistryProvider (ServiceLoaderUtil.java:30) +[2026-06-02 18:55:02,493][DEBUG][main] ServiceProvider loading Facility used; returning object [org.eclipse.angus.activation.MimeTypeRegistryProviderImpl] (ServiceLoaderUtil.java:36) +[2026-06-02 18:55:02,493][DEBUG][main] MimeTypeRegistry: can't load from file - /Users/wang/.mime.types (LogSupport.java:49) +java.io.FileNotFoundException: /Users/wang/.mime.types (No such file or directory) + at java.base/java.io.FileInputStream.open0(Native Method) ~[?:?] + at java.base/java.io.FileInputStream.open(FileInputStream.java:213) ~[?:?] + at java.base/java.io.FileInputStream.(FileInputStream.java:152) ~[?:?] + at java.base/java.io.FileReader.(FileReader.java:75) ~[?:?] + at org.eclipse.angus.activation.MimeTypeFile.(MimeTypeFile.java:47) ~[angus-activation-2.0.2.jar:?] + at org.eclipse.angus.activation.MimeTypeRegistryProviderImpl.getByFileName(MimeTypeRegistryProviderImpl.java:28) ~[angus-activation-2.0.2.jar:?] + at jakarta.activation.MimetypesFileTypeMap.loadFile(MimetypesFileTypeMap.java:263) ~[jakarta.activation-api-2.1.3.jar:?] + at jakarta.activation.MimetypesFileTypeMap.(MimetypesFileTypeMap.java:107) ~[jakarta.activation-api-2.1.3.jar:?] + at jakarta.activation.MimetypesFileTypeMap.(MimetypesFileTypeMap.java:305) ~[jakarta.activation-api-2.1.3.jar:?] + at org.springframework.mail.javamail.ConfigurableMimeFileTypeMap.createFileTypeMap(ConfigurableMimeFileTypeMap.java:150) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.mail.javamail.ConfigurableMimeFileTypeMap.getFileTypeMap(ConfigurableMimeFileTypeMap.java:123) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.mail.javamail.ConfigurableMimeFileTypeMap.afterPropertiesSet(ConfigurableMimeFileTypeMap.java:110) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.mail.javamail.JavaMailSenderImpl.(JavaMailSenderImpl.java:114) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.boot.autoconfigure.mail.MailSenderPropertiesConfiguration.mailSender(MailSenderPropertiesConfiguration.java:44) ~[spring-boot-autoconfigure-3.3.1.jar:3.3.1] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1167) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:784) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:767) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:461) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:605) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:576) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:738) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:270) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:368) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:461) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:605) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:576) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:738) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:270) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:368) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:461) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:605) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:576) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:738) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:270) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:368) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) [spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) [spring-context-6.1.10.jar:6.1.10] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) [spring-boot-3.3.1.jar:3.3.1] + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-3.3.1.jar:3.3.1] + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) [spring-boot-3.3.1.jar:3.3.1] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) [spring-boot-3.3.1.jar:3.3.1] + at net.lab1024.sa.admin.AdminApplication.main(AdminApplication.java:35) [classes/:?] +[2026-06-02 18:55:02,493][DEBUG][main] MimetypesFileTypeMap: load SYS (LogSupport.java:43) +[2026-06-02 18:55:02,493][DEBUG][main] Checking system property jakarta.activation.spi.MimeTypeRegistryProvider (FactoryFinder.java:105) +[2026-06-02 18:55:02,493][DEBUG][main] not found (FactoryFinder.java:120) +[2026-06-02 18:55:02,493][DEBUG][main] Using java.util.ServiceLoader to find jakarta.activation.spi.MimeTypeRegistryProvider (ServiceLoaderUtil.java:30) +[2026-06-02 18:55:02,493][DEBUG][main] ServiceProvider loading Facility used; returning object [org.eclipse.angus.activation.MimeTypeRegistryProviderImpl] (ServiceLoaderUtil.java:36) +[2026-06-02 18:55:02,494][DEBUG][main] MimeTypeRegistry: can't load from file - /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home/conf/mime.types (LogSupport.java:49) +java.io.FileNotFoundException: /Library/Java/JavaVirtualMachines/jdk-21.jdk/Contents/Home/conf/mime.types (No such file or directory) + at java.base/java.io.FileInputStream.open0(Native Method) ~[?:?] + at java.base/java.io.FileInputStream.open(FileInputStream.java:213) ~[?:?] + at java.base/java.io.FileInputStream.(FileInputStream.java:152) ~[?:?] + at java.base/java.io.FileReader.(FileReader.java:75) ~[?:?] + at org.eclipse.angus.activation.MimeTypeFile.(MimeTypeFile.java:47) ~[angus-activation-2.0.2.jar:?] + at org.eclipse.angus.activation.MimeTypeRegistryProviderImpl.getByFileName(MimeTypeRegistryProviderImpl.java:28) ~[angus-activation-2.0.2.jar:?] + at jakarta.activation.MimetypesFileTypeMap.loadFile(MimetypesFileTypeMap.java:263) ~[jakarta.activation-api-2.1.3.jar:?] + at jakarta.activation.MimetypesFileTypeMap.(MimetypesFileTypeMap.java:120) ~[jakarta.activation-api-2.1.3.jar:?] + at jakarta.activation.MimetypesFileTypeMap.(MimetypesFileTypeMap.java:305) ~[jakarta.activation-api-2.1.3.jar:?] + at org.springframework.mail.javamail.ConfigurableMimeFileTypeMap.createFileTypeMap(ConfigurableMimeFileTypeMap.java:150) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.mail.javamail.ConfigurableMimeFileTypeMap.getFileTypeMap(ConfigurableMimeFileTypeMap.java:123) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.mail.javamail.ConfigurableMimeFileTypeMap.afterPropertiesSet(ConfigurableMimeFileTypeMap.java:110) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.mail.javamail.JavaMailSenderImpl.(JavaMailSenderImpl.java:114) ~[spring-context-support-6.1.10.jar:6.1.10] + at org.springframework.boot.autoconfigure.mail.MailSenderPropertiesConfiguration.mailSender(MailSenderPropertiesConfiguration.java:44) ~[spring-boot-autoconfigure-3.3.1.jar:3.3.1] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:644) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:636) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1167) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:562) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:254) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1443) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1353) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.resolveFieldValue(AutowiredAnnotationBeanPostProcessor.java:784) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:767) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessProperties(AutowiredAnnotationBeanPostProcessor.java:508) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:461) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:605) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:576) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:738) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:270) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:368) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:461) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:605) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:576) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:738) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:270) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:368) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:205) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.resolveBeanByName(AbstractAutowireCapableBeanFactory.java:461) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.autowireResource(CommonAnnotationBeanPostProcessor.java:605) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:576) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:738) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:270) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:145) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessProperties(CommonAnnotationBeanPostProcessor.java:368) ~[spring-context-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1421) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:599) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:522) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:337) ~[spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:234) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:335) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:200) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:975) [spring-beans-6.1.10.jar:6.1.10] + at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:962) [spring-context-6.1.10.jar:6.1.10] + at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:624) [spring-context-6.1.10.jar:6.1.10] + at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:146) [spring-boot-3.3.1.jar:3.3.1] + at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:754) [spring-boot-3.3.1.jar:3.3.1] + at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:456) [spring-boot-3.3.1.jar:3.3.1] + at org.springframework.boot.SpringApplication.run(SpringApplication.java:335) [spring-boot-3.3.1.jar:3.3.1] + at net.lab1024.sa.admin.AdminApplication.main(AdminApplication.java:35) [classes/:?] +[2026-06-02 18:55:02,494][DEBUG][main] MimetypesFileTypeMap: load JAR (LogSupport.java:43) +[2026-06-02 18:55:02,494][DEBUG][main] MimetypesFileTypeMap: !anyLoaded (LogSupport.java:43) +[2026-06-02 18:55:02,494][DEBUG][main] MimetypesFileTypeMap: not loading mime types file: /META-INF/mime.types (LogSupport.java:43) +[2026-06-02 18:55:02,494][DEBUG][main] MimetypesFileTypeMap: load DEF (LogSupport.java:43) +[2026-06-02 18:55:02,494][DEBUG][main] Checking system property jakarta.activation.spi.MimeTypeRegistryProvider (FactoryFinder.java:105) +[2026-06-02 18:55:02,494][DEBUG][main] not found (FactoryFinder.java:120) +[2026-06-02 18:55:02,494][DEBUG][main] Using java.util.ServiceLoader to find jakarta.activation.spi.MimeTypeRegistryProvider (ServiceLoaderUtil.java:30) +[2026-06-02 18:55:02,494][DEBUG][main] ServiceProvider loading Facility used; returning object [org.eclipse.angus.activation.MimeTypeRegistryProviderImpl] (ServiceLoaderUtil.java:36) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/html, html (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/html, htm (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/html, HTML (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/html, HTM (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/plain, txt (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/plain, text (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/plain, TXT (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: text/plain, TEXT (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/gif, gif (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/gif, GIF (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/ief, ief (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/jpeg, jpeg (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/jpeg, jpg (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/jpeg, jpe (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/jpeg, JPG (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/tiff, tiff (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/tiff, tif (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/png, png (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/png, PNG (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: image/x-xwindowdump, xwd (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/postscript, ai (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/postscript, eps (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/postscript, ps (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/rtf, rtf (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/x-tex, tex (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/x-texinfo, texinfo (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/x-texinfo, texi (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/x-troff, t (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/x-troff, tr (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: application/x-troff, roff (LogSupport.java:46) +[2026-06-02 18:55:02,495][DEBUG][main] Added: MIMETypeEntry: audio/basic, au (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/midi, midi (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/midi, mid (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/x-aifc, aifc (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/x-aiff, aif (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/x-aiff, aiff (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg, mpeg (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg, mpg (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: audio/x-wav, wav (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpeg (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpg (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpe (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: video/quicktime, qt (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: video/quicktime, mov (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: video/x-msvideo, avi (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] MimetypesFileTypeMap: successfully loaded mime types file: /META-INF/mimetypes.default (LogSupport.java:43) +[2026-06-02 18:55:02,496][DEBUG][main] Checking system property jakarta.activation.spi.MimeTypeRegistryProvider (FactoryFinder.java:105) +[2026-06-02 18:55:02,496][DEBUG][main] not found (FactoryFinder.java:120) +[2026-06-02 18:55:02,496][DEBUG][main] Using java.util.ServiceLoader to find jakarta.activation.spi.MimeTypeRegistryProvider (ServiceLoaderUtil.java:30) +[2026-06-02 18:55:02,496][DEBUG][main] ServiceProvider loading Facility used; returning object [org.eclipse.angus.activation.MimeTypeRegistryProviderImpl] (ServiceLoaderUtil.java:36) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/html, html (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/html, htm (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/html, HTML (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/html, HTM (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, txt (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, text (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, TXT (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, TEXT (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, java (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, c (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, c++ (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, cpp (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, pl (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, cc (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: text/plain, h (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: image/gif, gif (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: image/gif, GIF (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: image/ief, ief (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: image/jpeg, jpeg (LogSupport.java:46) +[2026-06-02 18:55:02,496][DEBUG][main] Added: MIMETypeEntry: image/jpeg, jpg (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/jpeg, jpe (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/jpeg, JPG (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/tiff, tiff (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/tiff, tif (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-xwindowdump, xwd (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/postscript, ai (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/postscript, eps (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/postscript, ps (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/rtf, rtf (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/x-tex, tex (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/x-texinfo, texinfo (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/x-texinfo, texi (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/x-troff, t (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/x-troff, tr (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: application/x-troff, roff (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/basic, au (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/midi, midi (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/midi, mid (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/x-aifc, aifc (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/x-aiff, aif (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/x-aiff, aiff (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg, mpeg (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg, mpg (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/x-wav, wav (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpeg (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpg (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpe (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: video/quicktime, qt (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: video/quicktime, mov (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: video/x-msvideo, avi (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: text/x-speech, talk (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: text/css, css (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: text/csv, csv (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-xbitmap, xbm (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-xpixmap, xpm (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/png, png (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/svg+xml, svg (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/ief, ief (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/rgb, rgb (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/g3fax, g3f (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-xwindowdump, xwd (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-pict, pict (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-portable-pixmap, ppm (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-portable-graymap, pgm (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-portable-bitmap, pbm (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-portable-anymap, pnm (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-ms-bmp, bmp (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-cmu-raster, ras (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-photo-cd, pcd (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/cgm, cgm (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-cals, mil (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-cals, cal (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/fif, fif (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-mgx-dsf, dsf (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/x-cmx, cmx (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/wavelet, wi (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/vnd.dwg, dwg (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/vnd.dxf, dxf (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: image/vnd.svf, svf (LogSupport.java:46) +[2026-06-02 18:55:02,497][DEBUG][main] Added: MIMETypeEntry: audio/basic, au (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/basic, snd (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-aiff, aif (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-aiff, aiff (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-aiff, aifc (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-wav, wav (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg, mpa (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg, abs (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg, mpega (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg-2, mp2a (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/x-mpeg-2, mpa2 (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/echospeech, es (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: audio/voxware, vox (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/fastman, lcc (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-pn-realaudio, ra (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-pn-realaudio, ram (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: x-music/x-midi, mmid (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/vnd.koan, skp (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: text/x-speech, talk (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpeg (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpg (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/mpeg, mpe (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/mpeg-2, mpv2 (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/mpeg-2, mp2v (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/quicktime, qt (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/quicktime, mov (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/x-msvideo, avi (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/x-sgi-movie, movie (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/vdo, vdo (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: video/vnd.vivo, viv (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-ns-proxy-autoconfig, pac (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: x-conference/x-cooltalk, ice (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/postscript, ai (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/postscript, eps (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/postscript, ps (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/rtf, rtf (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/pdf, pdf (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/vnd.mif, mif (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-troff, t (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-troff, tr (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-troff, roff (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-troff-man, man (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-troff-me, me (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-troff-ms, ms (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-latex, latex (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-tex, tex (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-texinfo, texinfo (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-texinfo, texi (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-dvi, dvi (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/msword, doc (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/msword, DOC (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/oda, oda (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/envoy, evy (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-gtar, gtar (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-tar, tar (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-ustar, ustar (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-bcpio, bcpio (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-cpio, cpio (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/x-shar, shar (LogSupport.java:46) +[2026-06-02 18:55:02,498][DEBUG][main] Added: MIMETypeEntry: application/zip, zip (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/mac-binhex40, hqx (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-stuffit, sit (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-stuffit, sea (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/fractals, fif (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/octet-stream, bin (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/octet-stream, uu (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/octet-stream, exe (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-wais-source, src (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-wais-source, wsrc (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/hdf, hdf (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: text/javascript, js (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: text/javascript, ls (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: text/javascript, mocha (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-sh, sh (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-csh, csh (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-perl, pl (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-tcl, tcl (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/futuresplash, spl (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/mbedlet, mbd (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-rad-powermedia, rad (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/mspowerpoint, ppz (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-asap, asp (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/astound, asn (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-olescript, axs (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-oleobject, ods (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-form/x-openscape, opp (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-webbasic, wba (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-alpha-form, frm (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-script/x-wfxclient, wfx (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/octet-stream, exe (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/octet-stream, com (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-pcn, pcn (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/vnd.ms-excel, xls (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/vnd.ms-powerpoint, ppt (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/vnd.ms-project, mpp (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/vnd.svd, svd (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-net-install, ins (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/ccv, ccv (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: workbook/formulaone, vts (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-world/x-vrml, wrl (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-world/x-vrml, vrml (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-world/x-vream, vrw (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/x-p3d, p3d (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-world/x-svr, svr (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-world/x-wvr, wvr (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-world/x-3dmf, 3dmf (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/mathematica, ma (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: x-model/x-mesh, msh (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/vis5d, v5d (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: application/iges, igs (LogSupport.java:46) +[2026-06-02 18:55:02,499][DEBUG][main] Added: MIMETypeEntry: drawing/x-dwf, dwf (LogSupport.java:46) +[2026-06-02 18:55:02,503][DEBUG][main] Found key 'spring.mail.username' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:02,508][DEBUG][main] Creating shared instance of singleton bean 'operateLogAspectConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,509][DEBUG][main] Initializing ExecutorService (ExecutorConfigurationSupport.java:264) +[2026-06-02 18:55:02,510][DEBUG][main] Creating shared instance of singleton bean 'categoryController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,511][DEBUG][main] Creating shared instance of singleton bean 'categoryService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,511][DEBUG][main] Creating shared instance of singleton bean 'categoryDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,522][DEBUG][main] Creating shared instance of singleton bean 'categoryQueryService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,522][DEBUG][main] Creating shared instance of singleton bean 'categoryCacheManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,529][DEBUG][main] Creating shared instance of singleton bean 'goodsController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,530][DEBUG][main] Creating shared instance of singleton bean 'goodsService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,530][DEBUG][main] Creating shared instance of singleton bean 'goodsDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,541][DEBUG][main] Creating shared instance of singleton bean 'dataTracerService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,542][DEBUG][main] Creating shared instance of singleton bean 'dataTracerDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,553][DEBUG][main] Creating shared instance of singleton bean 'dataTracerManger' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,559][DEBUG][main] Creating shared instance of singleton bean 'dataTracerChangeContentService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,559][DEBUG][main] Creating shared instance of singleton bean 'dictService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,559][DEBUG][main] Creating shared instance of singleton bean 'dictDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,571][DEBUG][main] Creating shared instance of singleton bean 'dictDataDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,584][DEBUG][main] Creating shared instance of singleton bean 'cacheManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,584][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,586][DEBUG][main] Creating shared instance of singleton bean 'spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,588][DEBUG][main] Creating shared instance of singleton bean 'cacheManagerCustomizers' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,588][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.cache.CacheAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,589][DEBUG][main] Autowiring by type from bean name 'cacheManager' via factory method to bean named 'spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,589][DEBUG][main] Autowiring by type from bean name 'cacheManager' via factory method to bean named 'cacheManagerCustomizers' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,597][DEBUG][main] Creating shared instance of singleton bean 'dictManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,609][DEBUG][main] Creating shared instance of singleton bean 'bankController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,610][DEBUG][main] Creating shared instance of singleton bean 'bankService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,610][DEBUG][main] Creating shared instance of singleton bean 'bankDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,622][DEBUG][main] Creating shared instance of singleton bean 'enterpriseDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,634][DEBUG][main] Creating shared instance of singleton bean 'enterpriseController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,635][DEBUG][main] Creating shared instance of singleton bean 'enterpriseService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,635][DEBUG][main] Creating shared instance of singleton bean 'enterpriseEmployeeDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,644][DEBUG][main] Creating shared instance of singleton bean 'enterpriseEmployeeManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,655][DEBUG][main] Creating shared instance of singleton bean 'invoiceController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,655][DEBUG][main] Creating shared instance of singleton bean 'invoiceService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,656][DEBUG][main] Creating shared instance of singleton bean 'invoiceDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,667][DEBUG][main] Creating shared instance of singleton bean 'leaveController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,668][DEBUG][main] Creating shared instance of singleton bean 'leaveService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,668][DEBUG][main] Creating shared instance of singleton bean 'leaveDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,680][DEBUG][main] Creating shared instance of singleton bean 'leaveManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,685][DEBUG][main] Creating shared instance of singleton bean 'noticeController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,686][DEBUG][main] Creating shared instance of singleton bean 'noticeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,686][DEBUG][main] Creating shared instance of singleton bean 'noticeDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,697][DEBUG][main] Creating shared instance of singleton bean 'noticeManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,698][DEBUG][main] Creating shared instance of singleton bean 'noticeTypeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,699][DEBUG][main] Creating shared instance of singleton bean 'noticeTypeDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,715][DEBUG][main] Creating shared instance of singleton bean 'noticeEmployeeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,719][DEBUG][main] Creating shared instance of singleton bean 'addSignatureAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,719][DEBUG][main] Creating shared instance of singleton bean 'taskService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,719][DEBUG][main] Creating shared instance of singleton bean 'org.dromara.warm.flow.spring.boot.config.FlowAutoConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,723][DEBUG][main] Creating shared instance of singleton bean 'taskDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,727][DEBUG][main] Autowiring by type from bean name 'taskService' via factory method to bean named 'taskDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,737][DEBUG][main] Creating shared instance of singleton bean 'deputeAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,737][DEBUG][main] Creating shared instance of singleton bean 'reductionSignatureAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,738][DEBUG][main] Creating shared instance of singleton bean 'transferAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,738][DEBUG][main] Creating shared instance of singleton bean 'defController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,739][DEBUG][main] Creating shared instance of singleton bean 'flowDefinitionService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,740][DEBUG][main] Creating shared instance of singleton bean 'definitionService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,740][DEBUG][main] Creating shared instance of singleton bean 'definitionDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,742][DEBUG][main] Autowiring by type from bean name 'definitionService' via factory method to bean named 'definitionDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,746][DEBUG][main] Creating shared instance of singleton bean 'flowDefinitionDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,764][DEBUG][main] Creating shared instance of singleton bean 'chartService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,771][DEBUG][main] Creating shared instance of singleton bean 'executeController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,772][DEBUG][main] Creating shared instance of singleton bean 'roleService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,774][DEBUG][main] Creating shared instance of singleton bean 'hisTaskService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,775][DEBUG][main] Creating shared instance of singleton bean 'hisTaskDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,777][DEBUG][main] Autowiring by type from bean name 'hisTaskService' via factory method to bean named 'hisTaskDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,780][DEBUG][main] Creating shared instance of singleton bean 'nodeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,781][DEBUG][main] Creating shared instance of singleton bean 'nodeDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,783][DEBUG][main] Autowiring by type from bean name 'nodeService' via factory method to bean named 'nodeDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,788][DEBUG][main] Creating shared instance of singleton bean 'instanceService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,788][DEBUG][main] Creating shared instance of singleton bean 'instanceDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,791][DEBUG][main] Autowiring by type from bean name 'instanceService' via factory method to bean named 'instanceDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,795][DEBUG][main] Creating shared instance of singleton bean 'flowUserService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,795][DEBUG][main] Creating shared instance of singleton bean 'flowUserDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,797][DEBUG][main] Autowiring by type from bean name 'flowUserService' via factory method to bean named 'flowUserDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,805][DEBUG][main] Creating shared instance of singleton bean 'flowTaskServiceImpl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,807][DEBUG][main] Creating shared instance of singleton bean 'warmFlowMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,809][DEBUG][main] Creating shared instance of singleton bean 'flowInstanceMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,822][DEBUG][main] Creating shared instance of singleton bean 'flowTaskMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,833][DEBUG][main] Creating shared instance of singleton bean 'flowProcessEventHandler' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,834][DEBUG][main] Creating shared instance of singleton bean 'flowHisTaskMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,850][DEBUG][main] Creating shared instance of singleton bean 'hhDefServiceImpl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,850][DEBUG][main] Creating shared instance of singleton bean 'skipService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,850][DEBUG][main] Creating shared instance of singleton bean 'skipDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,853][DEBUG][main] Autowiring by type from bean name 'skipService' via factory method to bean named 'skipDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,859][DEBUG][main] Creating shared instance of singleton bean 'workflowPermissionHandler' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,860][DEBUG][main] Creating shared instance of singleton bean 'workflowGlobalListener' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,860][DEBUG][main] Autowiring by type from bean name 'workflowGlobalListener' via constructor to bean named 'flowProcessEventHandler' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,861][DEBUG][main] Creating shared instance of singleton bean 'flowInstanceServiceImpl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'instanceService' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'definitionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'chartService' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'taskService' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'flowHisTaskMapper' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'flowInstanceMapper' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'flowProcessEventHandler' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,862][DEBUG][main] Autowiring by type from bean name 'flowInstanceServiceImpl' via constructor to bean named 'flowTaskServiceImpl' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,866][DEBUG][main] Creating shared instance of singleton bean 'handlerSelectServiceImpl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,868][DEBUG][main] Creating shared instance of singleton bean 'nodeExtServiceImpl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,869][DEBUG][main] Creating shared instance of singleton bean 'dataScopeController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,869][DEBUG][main] Creating shared instance of singleton bean 'dataScopeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,872][DEBUG][main] Creating shared instance of singleton bean 'departmentController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,873][DEBUG][main] Creating shared instance of singleton bean 'employeeController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,876][DEBUG][main] Creating shared instance of singleton bean 'loginController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,877][DEBUG][main] Creating shared instance of singleton bean 'menuController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,878][DEBUG][main] Creating shared instance of singleton bean 'menuService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,878][DEBUG][main] Creating shared instance of singleton bean 'authUrl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,878][DEBUG][main] Creating shared instance of singleton bean 'urlConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,878][DEBUG][main] Creating shared instance of singleton bean 'requestMappingHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,878][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,879][DEBUG][main] Creating shared instance of singleton bean 'spring.web-org.springframework.boot.autoconfigure.web.WebProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,881][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration' via constructor to bean named 'spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,881][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration' via constructor to bean named 'spring.web-org.springframework.boot.autoconfigure.web.WebProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,881][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$EnableWebMvcConfiguration' via constructor to bean named 'org.springframework.beans.factory.support.DefaultListableBeanFactory@2b2f5fcf' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,886][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,887][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter' via constructor to bean named 'spring.web-org.springframework.boot.autoconfigure.web.WebProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,887][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter' via constructor to bean named 'spring.mvc-org.springframework.boot.autoconfigure.web.servlet.WebMvcProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,887][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.WebMvcAutoConfiguration$WebMvcAutoConfigurationAdapter' via constructor to bean named 'org.springframework.beans.factory.support.DefaultListableBeanFactory@2b2f5fcf' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,889][DEBUG][main] Creating shared instance of singleton bean 'org.dromara.warm.flow.ui.config.WarmFlowUiConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,890][DEBUG][main] Creating shared instance of singleton bean 'swaggerWebMvcConfigurer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,890][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.webmvc.ui.SwaggerConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,891][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.properties.SwaggerUiConfigParameters' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,892][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.properties.SwaggerUiConfigProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,895][DEBUG][main] Autowiring by type from bean name 'org.springdoc.core.properties.SwaggerUiConfigParameters' via constructor to bean named 'org.springdoc.core.properties.SwaggerUiConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,897][DEBUG][main] Creating shared instance of singleton bean 'indexPageTransformer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,897][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.properties.SwaggerUiOAuthProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,899][DEBUG][main] Creating shared instance of singleton bean 'swaggerWelcome' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,899][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.properties.SpringDocConfigProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,903][DEBUG][main] Creating shared instance of singleton bean 'springWebProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,903][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.webmvc.core.configuration.SpringDocWebMvcConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,906][DEBUG][main] Autowiring by type from bean name 'swaggerWelcome' via factory method to bean named 'org.springdoc.core.properties.SwaggerUiConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,906][DEBUG][main] Autowiring by type from bean name 'swaggerWelcome' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,906][DEBUG][main] Autowiring by type from bean name 'swaggerWelcome' via factory method to bean named 'org.springdoc.core.properties.SwaggerUiConfigParameters' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,906][DEBUG][main] Autowiring by type from bean name 'swaggerWelcome' via factory method to bean named 'springWebProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,910][DEBUG][main] Creating shared instance of singleton bean 'springdocObjectMapperProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,910][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,912][DEBUG][main] Autowiring by type from bean name 'springdocObjectMapperProvider' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,920][DEBUG][main] Autowiring by type from bean name 'indexPageTransformer' via factory method to bean named 'org.springdoc.core.properties.SwaggerUiConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,920][DEBUG][main] Autowiring by type from bean name 'indexPageTransformer' via factory method to bean named 'org.springdoc.core.properties.SwaggerUiOAuthProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,920][DEBUG][main] Autowiring by type from bean name 'indexPageTransformer' via factory method to bean named 'org.springdoc.core.properties.SwaggerUiConfigParameters' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,920][DEBUG][main] Autowiring by type from bean name 'indexPageTransformer' via factory method to bean named 'swaggerWelcome' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,920][DEBUG][main] Autowiring by type from bean name 'indexPageTransformer' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,921][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,921][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:02,922][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,923][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,923][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:02,923][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 10, name=org.springframework.boot:type=Admin,name=SpringApplication, attribute=Ready (LoggingProviderImpl.java:230) +[2026-06-02 18:55:02,924][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: [127.0.0.1] exception: (Log.java:236) +javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1073) ~[?:?] + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:632) ~[?:?] + at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:679) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1449) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1310) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1405) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:639) ~[?:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) ~[?:?] + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:02,924][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:02,924][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@48b6c645: connectionId=rmi://127.0.0.1 10] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:02,924][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@48b6c645: connectionId=rmi://127.0.0.1 10] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:02,924][DEBUG][main] Creating shared instance of singleton bean 'swaggerResourceResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,924][DEBUG][main] Autowiring by type from bean name 'swaggerResourceResolver' via factory method to bean named 'org.springdoc.core.properties.SwaggerUiConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,925][DEBUG][main] Autowiring by type from bean name 'swaggerWebMvcConfigurer' via factory method to bean named 'org.springdoc.core.properties.SwaggerUiConfigParameters' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,925][DEBUG][main] Autowiring by type from bean name 'swaggerWebMvcConfigurer' via factory method to bean named 'indexPageTransformer' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,925][DEBUG][main] Autowiring by type from bean name 'swaggerWebMvcConfigurer' via factory method to bean named 'swaggerResourceResolver' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,927][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.data.web.config.SpringDataWebConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,927][DEBUG][main] Autowiring by type from bean name 'org.springframework.data.web.config.SpringDataWebConfiguration' via constructor to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,929][DEBUG][main] Creating shared instance of singleton bean 'endpointObjectMapperWebMvcConfigurer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,929][DEBUG][main] Creating shared instance of singleton bean 'endpointObjectMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,929][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.jackson.JacksonEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,932][DEBUG][main] Autowiring by type from bean name 'endpointObjectMapperWebMvcConfigurer' via factory method to bean named 'endpointObjectMapper' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,939][DEBUG][main] Creating shared instance of singleton bean 'mvcContentNegotiationManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,942][DEBUG][main] Creating shared instance of singleton bean 'mvcConversionService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,943][DEBUG][main] Creating shared instance of singleton bean 'jsonConfig.StringToLocalDate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,944][DEBUG][main] Creating shared instance of singleton bean 'jsonConfig.StringToLocalDateTime' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,951][DEBUG][main] Creating shared instance of singleton bean 'mvcResourceUrlProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:02,952][DEBUG][main] Autowiring by type from bean name 'requestMappingHandlerMapping' via factory method to bean named 'mvcContentNegotiationManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,952][DEBUG][main] Autowiring by type from bean name 'requestMappingHandlerMapping' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,952][DEBUG][main] Autowiring by type from bean name 'requestMappingHandlerMapping' via factory method to bean named 'mvcResourceUrlProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:02,967][DEBUG][main] + n.l.s.a.m.b.c.c.CategoryController: + {POST [/category/update]}: update(CategoryUpdateForm) + {POST [/category/add]}: add(CategoryAddForm) + {GET [/category/delete/{categoryId}]}: delete(Long) + {GET [/category/{categoryId}]}: queryDetail(Long) + {POST [/category/tree]}: queryTree(CategoryTreeQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,970][DEBUG][main] + n.l.s.a.m.b.g.c.GoodsController: + {POST [/goods/update]}: update(GoodsUpdateForm) + {POST [/goods/add]}: add(GoodsAddForm) + {GET [/goods/delete/{goodsId}]}: delete(Long) + {POST [/goods/query]}: query(GoodsQueryForm) + {POST [/goods/batchDelete]}: batchDelete(ValidateList) + {POST [/goods/importGoods]}: importGoods(MultipartFile) + {GET [/goods/exportGoods]}: exportGoods(HttpServletResponse) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,971][DEBUG][main] + n.l.s.a.m.b.o.b.BankController: + {GET [/oa/bank/query/list/{enterpriseId}]}: queryList(Long) + {POST [/oa/bank/page/query]}: queryByPage(BankQueryForm) + {POST [/oa/bank/create]}: createBank(BankCreateForm) + {POST [/oa/bank/update]}: updateBank(BankUpdateForm) + {GET [/oa/bank/delete/{bankId}]}: deleteBank(Long) + {GET [/oa/bank/get/{bankId}]}: getDetail(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,972][DEBUG][main] + n.l.s.a.m.b.o.e.EnterpriseController: + {GET [/oa/enterprise/query/list]}: queryList(Integer) + {POST [/oa/enterprise/create]}: createEnterprise(EnterpriseCreateForm) + {POST [/oa/enterprise/update]}: updateEnterprise(EnterpriseUpdateForm) + {GET [/oa/enterprise/delete/{enterpriseId}]}: deleteEnterprise(Long) + {POST [/oa/enterprise/employee/queryPage]}: queryPageEmployeeList(EnterpriseEmployeeQueryForm) + {POST [/oa/enterprise/exportExcel]}: exportExcel(EnterpriseQueryForm,HttpServletResponse) + {POST [/oa/enterprise/page/query]}: queryByPage(EnterpriseQueryForm) + {POST [/oa/enterprise/employee/add]}: addEmployee(EnterpriseEmployeeForm) + {POST [/oa/enterprise/employee/list]}: employeeList(List) + {POST [/oa/enterprise/employee/delete]}: deleteEmployee(EnterpriseEmployeeForm) + {GET [/oa/enterprise/get/{enterpriseId}]}: getDetail(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,973][DEBUG][main] + n.l.s.a.m.b.o.i.InvoiceController: + {GET [/oa/invoice/query/list/{enterpriseId}]}: queryList(Long) + {POST [/oa/invoice/page/query]}: queryByPage(InvoiceQueryForm) + {POST [/oa/invoice/create]}: createInvoice(InvoiceAddForm) + {POST [/oa/invoice/update]}: updateInvoice(InvoiceUpdateForm) + {GET [/invoice/delete/{invoiceId}]}: deleteInvoice(Long) + {GET [/oa/invoice/get/{invoiceId}]}: getDetail(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,974][DEBUG][main] + n.l.s.a.m.b.o.l.c.LeaveController: + {POST [/leave/update]}: update(LeaveUpdateForm) + {POST [/leave/add]}: add(LeaveAddForm) + {GET [/leave/delete/{id}]}: batchDelete(Long) + {POST [/leave/batchDelete]}: batchDelete(ValidateList) + {POST [/leave/queryPage]}: queryPage(LeaveQueryForm) + {GET [/leave/{id}]}: getDetail(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,975][DEBUG][main] + n.l.s.a.m.b.o.n.c.NoticeController: + {GET [/oa/noticeType/update/{noticeTypeId}/{name}]}: update(Long,String) + {POST [/oa/notice/update]}: update(NoticeUpdateForm) + {POST [/oa/notice/add]}: add(NoticeAddForm) + {GET [/oa/noticeType/add/{name}]}: add(String) + {GET [/oa/notice/delete/{noticeId}]}: delete(Long) + {POST [/oa/notice/query]}: query(NoticeQueryForm) + {GET [/oa/noticeType/getAll]}: getAll() + {GET [/oa/notice/employee/view/{noticeId}]}: view(Long,HttpServletRequest) + {GET [/oa/notice/getUpdateVO/{noticeId}]}: getUpdateFormVO(Long) + {POST [/oa/notice/employee/queryViewRecord]}: queryViewRecord(NoticeViewRecordQueryForm) + {GET [/oa/noticeType/delete/{noticeTypeId}]}: deleteNoticeType(Long) + {POST [/oa/notice/employee/query]}: queryEmployeeNotice(NoticeEmployeeQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,978][DEBUG][main] + n.l.s.a.m.f.c.DefController: + {GET [/flow/definition/delete/{ids}]}: remove(List) + {POST [/flow/definition/add]}: add(FlowDefinition) + {GET [/flow/definition/publish/{id}]}: publish(Long) + {GET [/flow/definition/active/{definitionId}]}: active(Long) + {GET [/flow/definition/{id}]}: getInfo(Long) + {POST [/flow/definition/update]}: edit(FlowDefinition) + {POST [/flow/definition/importDefinition]}: importDefinition(MultipartFile) + {POST [/flow/definition/exportDefinition/{id}]}: exportDefinition(Long,HttpServletResponse) + {POST [/flow/definition/queryPage]}: queryPage(FlowDefinitionQueryForm) + {GET [/flow/definition/unPublish/{id}]}: unPublish(Long) + {GET [/flow/definition/copyDef/{id}]}: copyDef(Long) + {GET [/flow/definition/chartDef/{definitionId}]}: chartDef(Long) + {GET [/flow/definition/unActive/{definitionId}]}: unActive(Long) + {GET [/flow/definition/flowChart/{instanceId}]}: flowChart(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,979][DEBUG][main] + n.l.s.a.m.f.c.ExecuteController: + {GET [/flow/execute/active/{instanceId}]}: active(Long) + {POST [/flow/execute/approveTaskByInstance]}: approveTaskByInstance(ApproveTaskInsForm) + {GET [/flow/execute/getTaskDetail/{taskId}]}: getTaskDetailById(Long) + {POST [/flow/execute/interactiveType]}: interactiveType(WarmFlowInteractiveTypeVO) + {GET [/flow/execute/idReverseDisplayName/{ids}]}: idReverseDisplayName(Long[]) + {GET [/flow/execute/getDoneTaskDetail/{taskId}]}: getDoneTaskDetail(Long) + {POST [/flow/execute/startWorkFlow]}: startWorkFlow(StartProcessForm) + {POST [/flow/execute/completeTask]}: completeTask(CompleteTaskForm) + {GET [/flow/execute/toDoPage]}: toDoPage(FlowTask,int,int) + {GET [/flow/execute/copyPage]}: copyPage(FlowTask,int,int) + {GET [/flow/execute/donePage]}: donePage(FlowHisTask,int,int) + {GET [/flow/execute/doneList/{instanceId}]}: doneList(Long) + {GET [/flow/execute/getTaskById/{taskId}]}: getTaskById(Long) + {GET [/flow/execute/anyNodeList/{instanceId}]}: anyNodeList(Long) + {GET [/flow/execute/unActive/{instanceId}]}: unActive(Long) + {GET [/flow/execute/interactiveTypeEmployeeEntity]}: interactiveTypeEmployeeEntity(WarmFlowInteractiveTypeVO,int,int) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,980][DEBUG][main] + n.l.s.a.m.s.d.DataScopeController: + {GET [/dataScope/list]}: dataScopeList() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,980][DEBUG][main] + n.l.s.a.m.s.d.c.DepartmentController: + {POST [/department/update]}: updateDepartment(DepartmentUpdateForm) + {GET [/department/delete/{departmentId}]}: deleteDepartment(Long) + {GET [/department/listAll]}: listAll() + {GET [/department/treeList]}: departmentTree() + {POST [/department/add]}: addDepartment(DepartmentAddForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,981][DEBUG][main] + n.l.s.a.m.s.e.c.EmployeeController: + {POST [/employee/query]}: query(EmployeeQueryForm) + {GET [/employee/queryAll]}: queryAllEmployee(Boolean) + {GET [/employee/update/disabled/{employeeId}]}: updateDisableFlag(Long) + {POST [/employee/update/batch/delete]}: batchUpdateDeleteFlag(List) + {POST [/employee/update/batch/department]}: batchUpdateDepartment(EmployeeBatchUpdateDepartmentForm) + {POST [/employee/update]}: updateEmployee(EmployeeUpdateForm) + {POST [/employee/update/center]}: updateCenter(EmployeeUpdateCenterForm) + {POST [/employee/update/avatar]}: updateAvatar(EmployeeUpdateAvatarForm) + {POST [/employee/update/password]}: updatePassword(EmployeeUpdatePasswordForm) + {GET [/employee/update/password/reset/{employeeId}]}: resetPassword(Long) + {POST [/employee/add]}: addEmployee(EmployeeAddForm) + {GET [/employee/getPasswordComplexityEnabled]}: getPasswordComplexityEnabled() + {GET [/employee/getAllEmployeeByDepartmentId/{departmentId}]}: getAllEmployeeByDepartmentId(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,982][DEBUG][main] + n.l.s.a.m.s.l.c.LoginController: + {GET [/login/logout]}: logout() + {POST [/login]}: login(LoginForm,HttpServletRequest) + {GET [/login/getTwoFactorLoginFlag]}: getTwoFactorLoginFlag() + {GET [/login/getCaptcha]}: getCaptcha() + {GET [/login/sendEmailCode/{loginName}]}: sendEmailCode(String) + {GET [/login/getLoginInfo]}: getLoginInfo() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,982][DEBUG][main] + n.l.s.a.m.s.m.c.MenuController: + {GET [/menu/batchDelete]}: batchDeleteMenu(List) + {POST [/menu/add]}: addMenu(MenuAddForm) + {POST [/menu/update]}: updateMenu(MenuUpdateForm) + {GET [/menu/query]}: queryMenuList() + {GET [/menu/detail/{menuId}]}: getMenuDetail(Long) + {GET [/menu/tree]}: queryMenuTree(Boolean) + {GET [/menu/auth/url]}: getAuthUrl() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,983][DEBUG][main] + n.l.s.a.m.s.m.AdminMessageController: + {GET [/message/delete/{messageId}]}: delete(Long) + {POST [/message/query]}: query(MessageQueryForm) + {POST [/message/sendMessages]}: sendMessages(ValidateList) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,984][DEBUG][main] + n.l.s.a.m.s.p.c.PositionController: + {GET [/position/queryList]}: queryList() + {POST [/position/update]}: update(PositionUpdateForm) + {POST [/position/add]}: add(PositionAddForm) + {GET [/position/delete/{positionId}]}: batchDelete(Long) + {POST [/position/batchDelete]}: batchDelete(ValidateList) + {POST [/position/queryPage]}: queryPage(PositionQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,984][DEBUG][main] + n.l.s.a.m.s.r.c.RoleController: + {GET [/role/getAll]}: getAllRole() + {POST [/role/add]}: addRole(RoleAddForm) + {GET [/role/get/{roleId}]}: getRole(Long) + {GET [/role/delete/{roleId}]}: deleteRole(Long) + {POST [/role/update]}: updateRole(RoleUpdateForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,985][DEBUG][main] + n.l.s.a.m.s.r.c.RoleDataScopeController: + {GET [/role/dataScope/getRoleDataScopeList/{roleId}]}: dataScopeListByRole(Long) + {POST [/role/dataScope/updateRoleDataScopeList]}: updateRoleDataScopeList(RoleDataScopeUpdateForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,985][DEBUG][main] + n.l.s.a.m.s.r.c.RoleEmployeeController: + {GET [/role/employee/getAllEmployeeByRoleId/{roleId}]}: listAllEmployeeRoleId(Long) + {POST [/role/employee/batchRemoveRoleEmployee]}: batchRemoveEmployee(RoleEmployeeUpdateForm) + {POST [/role/employee/batchAddRoleEmployee]}: addEmployeeList(RoleEmployeeUpdateForm) + {GET [/role/employee/getRoles/{employeeId}]}: getRoleByEmployeeId(Long) + {POST [/role/employee/queryEmployee]}: queryEmployee(RoleEmployeeQueryForm) + {GET [/role/employee/removeEmployee]}: removeEmployee(Long,Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,986][DEBUG][main] + n.l.s.a.m.s.r.c.RoleMenuController: + {GET [/role/menu/getRoleSelectedMenu/{roleId}]}: getRoleSelectedMenu(Long) + {POST [/role/menu/updateRoleMenu]}: updateRoleMenu(RoleMenuUpdateForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,987][DEBUG][main] + n.l.s.a.m.s.s.AdminApiEncryptController: + {POST [/support/apiEncrypt/testRequestEncrypt]}: testRequestEncrypt(JweForm) + {POST [/support/apiEncrypt/testResponseEncrypt]}: testResponseEncrypt(JweForm) + {POST [/support/apiEncrypt/testDecryptAndEncrypt]}: testDecryptAndEncrypt(JweForm) + {POST [/support/apiEncrypt/testArray]}: testArray(ValidateList) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,987][DEBUG][main] + n.l.s.a.m.s.s.AdminCacheController: + {GET [/support/cache/remove/{cacheName}]}: removeCache(String) + {GET [/support/cache/names]}: cacheNames() + {GET [/support/cache/keys/{cacheName}]}: cacheKeys(String) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,988][DEBUG][main] + n.l.s.a.m.s.s.AdminChangeLogController: + {POST [/support/changeLog/update]}: update(ChangeLogUpdateForm) + {POST [/support/changeLog/add]}: add(ChangeLogAddForm) + {POST [/support/changeLog/batchDelete]}: batchDelete(ValidateList) + {GET [/support/changeLog/delete/{changeLogId}]}: batchDelete(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,989][DEBUG][main] + n.l.s.a.m.s.s.AdminConfigController: + {POST [/support/config/query]}: queryConfigPage(ConfigQueryForm) + {POST [/support/config/update]}: updateConfig(ConfigUpdateForm) + {POST [/support/config/add]}: addConfig(ConfigAddForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,989][DEBUG][main] + n.l.s.a.m.s.s.AdminDataMaskingDemoController: + {GET [/support/dataMasking/demo/query]}: query() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,990][DEBUG][main] + n.l.s.a.m.s.s.AdminDictController: + {POST [/support/dict/update]}: update(DictUpdateForm) + {POST [/support/dict/add]}: add(DictAddForm) + {GET [/support/dict/delete/{dictId}]}: delete(Long) + {GET [/support/dict/getAllDictData]}: getAll() + {GET [/support/dict/dictData/updateDisabled/{dictDataId}]}: updateDictDataDisabled(Long) + {POST [/support/dict/dictData/batchDelete]}: batchDeleteDictData(ValidateList) + {POST [/support/dict/batchDelete]}: batchDelete(ValidateList) + {POST [/support/dict/queryPage]}: queryPage(DictQueryForm) + {GET [/support/dict/getAllDict]}: getAllDict() + {GET [/support/dict/updateDisabled/{dictId}]}: updateDisabled(Long) + {GET [/support/dict/value/list/{dictCode}]}: queryDictData(String) + {GET [/support/dict/dictData/queryDictData/{dictId}]}: queryDictData(Long) + {POST [/support/dict/dictData/add]}: addDictData(DictDataAddForm) + {POST [/support/dict/dictData/update]}: updateDictData(DictDataUpdateForm) + {GET [/support/dict/dictData/delete/{dictDataId}]}: deleteDictData(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,991][DEBUG][main] + n.l.s.a.m.s.s.AdminFileController: + {POST [/support/file/queryPage]}: queryPage(FileQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,991][DEBUG][main] + n.l.s.a.m.s.s.AdminHeartBeatController: + {POST [/support/heartBeat/query]}: query(HeartBeatRecordQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,992][DEBUG][main] + n.l.s.a.m.s.s.AdminHelpDocController: + {POST [/support/helpDoc/update]}: update(HelpDocUpdateForm) + {POST [/support/helpDoc/add]}: add(HelpDocAddForm) + {GET [/support/helpDoc/delete/{helpDocId}]}: delete(Long) + {POST [/support/helpDoc/query]}: query(HelpDocQueryForm) + {POST [/support/helpDoc/helpDocCatalog/add]}: addHelpDocCatalog(HelpDocCatalogAddForm) + {POST [/support/helpDoc/helpDocCatalog/update]}: updateHelpDocCatalog(HelpDocCatalogUpdateForm) + {GET [/support/helpDoc/helpDocCatalog/delete/{helpDocCatalogId}]}: deleteHelpDocCatalog(Long) + {GET [/support/helpDoc/getDetail/{helpDocId}]}: getDetail(Long) + {GET [/support/helpDoc/queryHelpDocByRelationId/{relationId}]}: queryHelpDocByRelationId(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,993][DEBUG][main] + n.l.s.a.m.s.s.AdminLoginLogController: + {POST [/support/loginLog/page/query/login]}: queryByPageLogin(LoginLogQueryForm) + {POST [/support/loginLog/page/query]}: queryByPage(LoginLogQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,994][DEBUG][main] + n.l.s.a.m.s.s.AdminOperateLogController: + {GET [/support/operateLog/detail/{operateLogId}]}: detail(Long) + {POST [/support/operateLog/page/query/login]}: queryByPageLogin(OperateLogQueryForm) + {GET [/support/operateLog/module/list]}: moduleList() + {POST [/support/operateLog/page/query]}: queryByPage(OperateLogQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,994][DEBUG][main] + n.l.s.a.m.s.s.AdminProtectController: + {POST [/support/protect/loginFail/batchDelete]}: batchDelete(ValidateList) + {POST [/support/protect/loginFail/queryPage]}: queryPage(LoginFailQueryForm) + {POST [/support/protect/level3protect/updateConfig]}: updateConfig(Level3ProtectConfigForm) + {GET [/support/protect/level3protect/getConfig]}: getConfig() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,995][DEBUG][main] + n.l.s.a.m.s.s.AdminReloadController: + {GET [/support/reload/query]}: query() + {GET [/support/reload/result/{tag}]}: queryReloadResult(String) + {POST [/support/reload/update]}: updateByTag(ReloadForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,995][DEBUG][main] + n.l.s.a.m.s.s.AdminSerialNumberController: + {POST [/support/serialNumber/generate]}: generate(SerialNumberGenerateForm) + {GET [/support/serialNumber/all]}: getAll() + {POST [/support/serialNumber/queryRecord]}: queryRecord(SerialNumberRecordQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,996][DEBUG][main] + n.l.s.a.m.s.s.AdminSmartJobController: + {POST [/support/job/execute]}: execute(SmartJobExecuteForm) + {POST [/support/job/add]}: addJob(SmartJobAddForm) + {POST [/support/job/update/enabled]}: updateJobEnabled(SmartJobEnabledUpdateForm) + {GET [/support/job/{jobId}]}: queryJobInfo(Integer) + {POST [/support/job/query]}: queryJob(SmartJobQueryForm) + {POST [/support/job/update]}: updateJob(SmartJobUpdateForm) + {GET [/support/job/delete]}: deleteJob(Integer) + {POST [/support/job/log/query]}: queryJobLog(SmartJobLogQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,997][DEBUG][main] + n.l.s.b.m.s.c.CaptchaController: + {GET [/support/captcha]}: generateCaptcha() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,997][DEBUG][main] + n.l.s.b.m.s.c.c.ChangeLogController: + {POST [/support/changeLog/queryPage]}: queryPage(ChangeLogQueryForm) + {GET [/support/changeLog/getDetail/{changeLogId}]}: getDetail(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,998][DEBUG][main] + n.l.s.b.m.s.c.c.CodeGeneratorController: + {GET [/support/codeGenerator/table/getTableColumns/{table}]}: getTableColumns(String) + {POST [/support/codeGenerator/table/queryTableList]}: queryTableList(TableQueryForm) + {GET [/support/codeGenerator/table/getConfig/{table}]}: getTableConfig(String) + {POST [/support/codeGenerator/code/preview]}: preview(CodeGeneratorPreviewForm) + {GET [/support/codeGenerator/code/download/{tableName}], produces [application/octet-stream]}: download(String,HttpServletResponse) + {POST [/support/codeGenerator/table/updateConfig]}: updateConfig(CodeGeneratorConfigForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,999][DEBUG][main] + n.l.s.b.m.s.c.ConfigController: + {GET [/support/config/queryByKey]}: queryByKey(String) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,999][DEBUG][main] + n.l.s.b.m.s.d.c.DataTracerController: + {POST [/support/dataTracer/query]}: query(DataTracerQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,999][DEBUG][main] + n.l.s.b.m.s.f.c.FeedbackController: + {POST [/support/feedback/add]}: add(FeedbackAddForm) + {POST [/support/feedback/query]}: query(FeedbackQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:02,999][DEBUG][main] + n.l.s.b.m.s.f.c.FileController: + {GET [/support/file/getFileUrl]}: getUrl(String) + {POST [/support/file/upload]}: upload(MultipartFile,Integer) + {GET [/support/file/downLoad]}: downLoad(String,HttpServletRequest,HttpServletResponse) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,000][DEBUG][main] + n.l.s.b.m.s.h.c.HelpDocController: + {GET [/support/helpDoc/helpDocCatalog/getAll]}: getAll() + {GET [/support/helpDoc/user/view/{helpDocId}]}: view(Long,HttpServletRequest) + {GET [/support/helpDoc/user/queryAllHelpDocList]}: queryAllHelpDocList() + {POST [/support/helpDoc/user/queryViewRecord]}: queryViewRecord(HelpDocViewRecordQueryForm) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,001][DEBUG][main] + n.l.s.b.m.s.m.c.MessageController: + {POST [/support/message/queryMyMessage]}: query(MessageQueryForm) + {GET [/support/message/getUnreadCount]}: getUnreadCount() + {GET [/support/message/read/{messageId}]}: updateReadFlag(Long) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,001][DEBUG][main] + n.l.s.b.m.s.t.TableColumnController: + {GET [/support/tableColumn/delete/{tableId}]}: deleteTableColumn(Integer) + {POST [/support/tableColumn/update]}: updateTableColumn(TableColumnUpdateForm) + {GET [/support/tableColumn/getColumns/{tableId}]}: getColumns(Integer) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,003][DEBUG][main] + o.s.b.a.w.s.e.BasicErrorController: + { [/error]}: error(HttpServletRequest) + { [/error], produces [text/html]}: errorHtml(HttpServletRequest,HttpServletResponse) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,003][DEBUG][main] + o.d.w.f.u.c.WarmFlowUiController: + {GET [/warm-flow-ui/config]}: config() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,004][DEBUG][main] + o.d.w.f.u.c.WarmFlowController: + {GET [/warm-flow/execute/load/{taskId}]}: load(Long) + {POST [/warm-flow/execute/handle]}: handle(Map,Long,String,String,String) + {POST [/warm-flow/form-content]}: saveFormContent(FlowDto) + {GET [/warm-flow/handler-feedback]}: handlerFeedback(HandlerFeedBackDto) + {GET [/warm-flow/handler-type]}: handlerType() + {POST [/warm-flow/save-json]}: saveJson(DefJson) + {GET [/warm-flow/query-def/{id}]}: queryDef(Long) + {GET [/warm-flow/query-flow-chart/{id}]}: queryFlowChart(Long) + {GET [/warm-flow/handler-result]}: handlerResult(HandlerQuery) + {GET [/warm-flow/handler-dict]}: handlerDict() + {GET [/warm-flow/published-form]}: publishedForm() + {GET [/warm-flow/form-content/{id}]}: getFormContent(Long) + {GET [/warm-flow/execute/hisLoad/{taskId}]}: hisLoad(Long) + {GET [/warm-flow/node-ext]}: nodeExt() (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,009][DEBUG][main] + o.s.w.a.MultipleOpenApiWebMvcResource: + {GET [/v3/api-docs/{group}], produces [application/json]}: openapiJson(HttpServletRequest,String,String,Locale) + {GET [/v3/api-docs.yaml/{group}], produces [application/vnd.oai.openapi]}: openapiYaml(HttpServletRequest,String,String,Locale) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,011][DEBUG][main] + o.s.w.a.OpenApiWebMvcResource: + {GET [/v3/api-docs], produces [application/json]}: openapiJson(HttpServletRequest,String,Locale) + {GET [/v3/api-docs.yaml], produces [application/vnd.oai.openapi]}: openapiYaml(HttpServletRequest,String,Locale) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,012][DEBUG][main] + o.s.w.u.SwaggerWelcomeWebMvc: + {GET [/swagger-ui.html]}: redirectToUi(HttpServletRequest) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,012][DEBUG][main] + o.s.w.u.SwaggerConfigResource: + {GET [/v3/api-docs/swagger-config], produces [application/json]}: openapiJson(HttpServletRequest) (AbstractHandlerMethodMapping.java:294) +[2026-06-02 18:55:03,013][DEBUG][main] 253 mappings in 'requestMappingHandlerMapping' (AbstractHandlerMethodMapping.java:366) +[2026-06-02 18:55:03,030][DEBUG][main] Creating shared instance of singleton bean 'methodUrlMap' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,037][DEBUG][main] Autowiring by type from bean name 'authUrl' via factory method to bean named 'methodUrlMap' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,056][DEBUG][main] Creating shared instance of singleton bean 'adminMessageController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,057][DEBUG][main] Creating shared instance of singleton bean 'messageService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,057][DEBUG][main] Creating shared instance of singleton bean 'messageDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,065][DEBUG][main] Creating shared instance of singleton bean 'messageManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,073][DEBUG][main] Creating shared instance of singleton bean 'positionController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,074][DEBUG][main] Creating shared instance of singleton bean 'positionService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,076][DEBUG][main] Creating shared instance of singleton bean 'positionManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,081][DEBUG][main] Creating shared instance of singleton bean 'roleController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,082][DEBUG][main] Creating shared instance of singleton bean 'roleDataScopeController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,083][DEBUG][main] Creating shared instance of singleton bean 'roleDataScopeService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,083][DEBUG][main] Creating shared instance of singleton bean 'roleDataScopeManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,090][DEBUG][main] Creating shared instance of singleton bean 'roleEmployeeController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,091][DEBUG][main] Creating shared instance of singleton bean 'roleMenuController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,092][DEBUG][main] Creating shared instance of singleton bean 'adminApiEncryptController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,094][DEBUG][main] Creating shared instance of singleton bean 'adminCacheController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,094][DEBUG][main] Creating shared instance of singleton bean 'caffeineCacheService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,094][DEBUG][main] Creating shared instance of singleton bean 'cacheConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,099][DEBUG][main] Creating shared instance of singleton bean 'adminChangeLogController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,099][DEBUG][main] Creating shared instance of singleton bean 'changeLogService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,099][DEBUG][main] Creating shared instance of singleton bean 'changeLogDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,108][DEBUG][main] Creating shared instance of singleton bean 'adminConfigController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,110][DEBUG][main] Creating shared instance of singleton bean 'adminDataMaskingDemoController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,111][DEBUG][main] Creating shared instance of singleton bean 'adminDictController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,113][DEBUG][main] Creating shared instance of singleton bean 'adminFileController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,113][DEBUG][main] Creating shared instance of singleton bean 'fileService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,114][DEBUG][main] Creating shared instance of singleton bean 'fileDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,121][DEBUG][main] Creating shared instance of singleton bean 'securityFileService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,127][DEBUG][main] Creating shared instance of singleton bean 'adminHeartBeatController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,127][DEBUG][main] Creating shared instance of singleton bean 'heartBeatService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,127][DEBUG][main] Creating shared instance of singleton bean 'heartBeatRecordDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,137][DEBUG][main] Creating shared instance of singleton bean 'adminHelpDocController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,138][DEBUG][main] Creating shared instance of singleton bean 'helpDocService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,138][DEBUG][main] Creating shared instance of singleton bean 'helpDocDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,148][DEBUG][main] Creating shared instance of singleton bean 'helpDocManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,151][DEBUG][main] Creating shared instance of singleton bean 'helpDocCatalogService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,151][DEBUG][main] Creating shared instance of singleton bean 'helpDocCatalogDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,167][DEBUG][main] Creating shared instance of singleton bean 'adminLoginLogController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,168][DEBUG][main] Creating shared instance of singleton bean 'adminOperateLogController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,168][DEBUG][main] Creating shared instance of singleton bean 'operateLogService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,168][DEBUG][main] Creating shared instance of singleton bean 'operateLogDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,181][DEBUG][main] Creating shared instance of singleton bean 'adminProtectController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,182][DEBUG][main] Creating shared instance of singleton bean 'adminReloadController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,182][DEBUG][main] Creating shared instance of singleton bean 'reloadService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,185][DEBUG][main] Creating shared instance of singleton bean 'adminSerialNumberController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,185][DEBUG][main] Creating shared instance of singleton bean 'serialNumberDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,196][DEBUG][main] Creating shared instance of singleton bean 'serialNumberInternService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,197][DEBUG][main] Creating shared instance of singleton bean 'serialNumberRecordDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,214][DEBUG][main] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:03,214][DEBUG][main] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@60877629] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:03,214][DEBUG][main] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:03,214][DEBUG][main] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:03,214][DEBUG][main] ==> Preparing: SELECT serial_number_id,business_name,format,rule_type,init_number,step_random_range,remark,last_number,last_time,update_time,create_time FROM t_serial_number (BaseJdbcLogger.java:135) +[2026-06-02 18:55:03,215][DEBUG][main] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:03,253][DEBUG][main] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:03,253][DEBUG][main] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@60877629] (Logger.java:49) +[2026-06-02 18:55:03,256][DEBUG][main] Creating shared instance of singleton bean 'serialNumberRecordService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,259][DEBUG][main] Creating shared instance of singleton bean 'adminSmartJobController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,260][DEBUG][main] Creating shared instance of singleton bean 'smartJobService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,260][DEBUG][main] Creating shared instance of singleton bean 'smartJobDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,267][DEBUG][main] Creating shared instance of singleton bean 'smartJobLogDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,273][DEBUG][main] Creating shared instance of singleton bean 'smartJobClientManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,274][DEBUG][main] Creating shared instance of singleton bean 'initJobLauncher' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,274][DEBUG][main] Creating shared instance of singleton bean 'smartJobAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,274][DEBUG][main] Creating shared instance of singleton bean 'smart.job-net.lab1024.sa.base.module.support.job.config.SmartJobConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,275][DEBUG][main] Creating shared instance of singleton bean 'smartJobRepository' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,277][DEBUG][main] Creating shared instance of singleton bean 'smartJobSample1' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,278][DEBUG][main] Creating shared instance of singleton bean 'smartJobSample2' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,279][DEBUG][main] Autowiring by type from bean name 'smartJobAutoConfiguration' via constructor to bean named 'smart.job-net.lab1024.sa.base.module.support.job.config.SmartJobConfig' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,279][DEBUG][main] Autowiring by type from bean name 'smartJobAutoConfiguration' via constructor to bean named 'smartJobRepository' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,279][DEBUG][main] Autowiring by type from bean name 'smartJobAutoConfiguration' via constructor to bean named 'smartJobSample1' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,279][DEBUG][main] Autowiring by type from bean name 'smartJobAutoConfiguration' via constructor to bean named 'smartJobSample2' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,280][DEBUG][main] Autowiring by type from bean name 'initJobLauncher' via factory method to bean named 'redisson' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,281][DEBUG][main] Initializing ExecutorService (ExecutorConfigurationSupport.java:264) +[2026-06-02 18:55:03,283][DEBUG][main] Autowiring by type from bean name 'smartJobClientManager' via constructor to bean named 'initJobLauncher' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,283][DEBUG][main] Autowiring by type from bean name 'smartJobClientManager' via constructor to bean named 'smartJobRepository' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,283][DEBUG][main] Autowiring by type from bean name 'smartJobClientManager' via constructor to bean named 'smartJobSample1' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,283][DEBUG][main] Autowiring by type from bean name 'smartJobClientManager' via constructor to bean named 'smartJobSample2' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,283][DEBUG][main] Autowiring by type from bean name 'smartJobClientManager' via constructor to bean named 'redisson' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,297][DEBUG][main] Creating shared instance of singleton bean 'schemaEnumPropertyCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,298][DEBUG][main] Creating shared instance of singleton bean 'smartTableMetadataUtil' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,299][DEBUG][main] Creating shared instance of singleton bean 'asyncConfig.AsyncExceptionConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,300][DEBUG][main] Creating shared instance of singleton bean 'asyncConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,300][DEBUG][main] Creating shared instance of singleton bean 'heartBeatConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,300][DEBUG][main] Creating shared instance of singleton bean 'heartBeatRecordHandler' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,301][DEBUG][main] Found key 'heart-beat.interval-seconds' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,301][DEBUG][main] Creating shared instance of singleton bean 'jsonConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,302][DEBUG][main] Creating shared instance of singleton bean 'repeatSubmitConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,302][DEBUG][main] Creating shared instance of singleton bean 'restTemplateConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,302][DEBUG][main] Found key 'http.pool.max-total' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,302][DEBUG][main] Found key 'http.pool.connect-timeout' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,302][DEBUG][main] Found key 'http.pool.read-timeout' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,302][DEBUG][main] Found key 'http.pool.write-timeout' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,303][DEBUG][main] Found key 'http.pool.keep-alive' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,303][DEBUG][main] Creating shared instance of singleton bean 'scheduleConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,304][DEBUG][main] Creating shared instance of singleton bean 'swaggerConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,304][DEBUG][main] Found key 'springdoc.swagger-ui.server-base-url' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,304][DEBUG][main] Creating shared instance of singleton bean 'tokenConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,305][DEBUG][main] Creating shared instance of singleton bean 'getSaTokenConfig' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,305][DEBUG][main] Creating shared instance of singleton bean 'cn.dev33.satoken.spring.SaBeanRegister' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,310][DEBUG][main] Creating shared instance of singleton bean 'yamlProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,311][DEBUG][main] Creating shared instance of singleton bean 'globalExceptionHandler' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,312][DEBUG][main] Creating shared instance of singleton bean 'mybatisPlusFillHandler' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,314][DEBUG][main] Creating shared instance of singleton bean 'webServerListener' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,314][DEBUG][main] Found key 'reload.interval-seconds' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,314][DEBUG][main] Creating shared instance of singleton bean 'decryptRequestAdvice' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,315][DEBUG][main] Creating shared instance of singleton bean 'jacksonObjectMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,315][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,316][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonObjectMapperBuilderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,316][DEBUG][main] Creating shared instance of singleton bean 'customizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,318][DEBUG][main] Creating shared instance of singleton bean 'standardJacksonObjectMapperBuilderCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,318][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$Jackson2ObjectMapperBuilderCustomizerConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,318][DEBUG][main] Creating shared instance of singleton bean 'spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,321][DEBUG][main] Autowiring by type from bean name 'standardJacksonObjectMapperBuilderCustomizer' via factory method to bean named 'spring.jackson-org.springframework.boot.autoconfigure.jackson.JacksonProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,322][DEBUG][main] Creating shared instance of singleton bean 'parameterNamesModule' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,322][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$ParameterNamesModuleConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,325][DEBUG][main] Creating shared instance of singleton bean 'jsonMixinModule' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,325][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration$JacksonMixinConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,326][DEBUG][main] Creating shared instance of singleton bean 'jsonMixinModuleEntries' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,326][DEBUG][main] Autowiring by type from bean name 'jsonMixinModuleEntries' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,334][DEBUG][main] Autowiring by type from bean name 'jsonMixinModule' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,334][DEBUG][main] Autowiring by type from bean name 'jsonMixinModule' via factory method to bean named 'jsonMixinModuleEntries' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,335][DEBUG][main] Creating shared instance of singleton bean 'jsonComponentModule' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,335][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,339][DEBUG][main] Creating shared instance of singleton bean 'jacksonGeoModule' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,339][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.data.web.config.SpringDataJacksonConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,340][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.data.web.config.SpringDataWebSettings' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,342][DEBUG][main] Creating shared instance of singleton bean 'pageModule' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,344][DEBUG][main] Autowiring by type from bean name 'jacksonObjectMapperBuilder' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,344][DEBUG][main] Autowiring by type from bean name 'jacksonObjectMapperBuilder' via factory method to bean named 'customizer' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,344][DEBUG][main] Autowiring by type from bean name 'jacksonObjectMapperBuilder' via factory method to bean named 'standardJacksonObjectMapperBuilderCustomizer' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,382][DEBUG][main] Autowiring by type from bean name 'jacksonObjectMapper' via factory method to bean named 'jacksonObjectMapperBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,401][DEBUG][main] Creating shared instance of singleton bean 'encryptResponseAdvice' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,402][DEBUG][main] Creating shared instance of singleton bean 'captchaController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,403][DEBUG][main] Creating shared instance of singleton bean 'changeLogController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,405][DEBUG][main] Creating shared instance of singleton bean 'codeGeneratorController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,405][DEBUG][main] Creating shared instance of singleton bean 'codeGeneratorService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,405][DEBUG][main] Creating shared instance of singleton bean 'codeGeneratorDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,406][DEBUG][main] Creating shared instance of singleton bean 'codeGeneratorConfigDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,416][DEBUG][main] Creating shared instance of singleton bean 'codeGeneratorTemplateService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,424][DEBUG][main] Creating shared instance of singleton bean 'configController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,425][DEBUG][main] Creating shared instance of singleton bean 'dataTracerController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,426][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,426][DEBUG][main] Creating shared instance of singleton bean 'feedbackController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,427][DEBUG][main] Creating shared instance of singleton bean 'feedbackService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,427][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,427][DEBUG][main] Creating shared instance of singleton bean 'feedbackDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,427][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,427][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,427][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,427][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,427][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,427][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,428][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,434][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:03,434][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 11, name=org.springframework.boot:type=Admin,name=SpringApplication, attribute=Ready (LoggingProviderImpl.java:230) +[2026-06-02 18:55:03,434][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: [127.0.0.1] exception: (Log.java:236) +javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1073) ~[?:?] + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:632) ~[?:?] + at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:679) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1449) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1310) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1405) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:639) ~[?:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) ~[?:?] + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:03,435][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,435][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,435][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@28a78e58: connectionId=rmi://127.0.0.1 11] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:03,435][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@28a78e58: connectionId=rmi://127.0.0.1 11] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:03,442][DEBUG][main] Creating shared instance of singleton bean 'fileController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,443][DEBUG][main] Creating shared instance of singleton bean 'helpDocController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,443][DEBUG][main] Creating shared instance of singleton bean 'helpDocUserService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,446][DEBUG][main] Creating shared instance of singleton bean 'messageController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,447][DEBUG][main] Creating shared instance of singleton bean 'redissonService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,448][DEBUG][main] Autowiring by type from bean name 'redissonService' via constructor to bean named 'redisson' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,449][DEBUG][main] Creating shared instance of singleton bean 'tableColumnController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,449][DEBUG][main] Creating shared instance of singleton bean 'tableColumnService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,449][DEBUG][main] Creating shared instance of singleton bean 'tableColumnDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,460][DEBUG][main] Creating shared instance of singleton bean 'smart-async-executor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,460][DEBUG][main] Initializing ExecutorService (ExecutorConfigurationSupport.java:264) +[2026-06-02 18:55:03,460][DEBUG][main] Initializing ExecutorService 'smart-async-executor' (ExecutorConfigurationSupport.java:264) +[2026-06-02 18:55:03,468][DEBUG][main] Creating shared instance of singleton bean 'heartBeatManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,471][DEBUG][main] Creating shared instance of singleton bean 'zSetOperations' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,471][DEBUG][main] Autowiring by type from bean name 'zSetOperations' via factory method to bean named 'redisTemplate' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,483][DEBUG][main] Creating shared instance of singleton bean 'repeatSubmitAspect' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,483][DEBUG][main] Creating shared instance of singleton bean 'restTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,533][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:57:0a:11:97:42:c4:e3:cc, Subject:CN=Actalis Authentication Root CA, O=Actalis S.p.A./03358520967, L=Milan, C=IT, Issuer:CN=Actalis Authentication Root CA, O=Actalis S.p.A./03358520967, L=Milan, C=IT, Key type:RSA, Length:4096, Cert Id:1729119956, Valid from:2011/9/22 19:22, Valid until:2030/9/22 19:22 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,534][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:01, Subject:CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE, Issuer:CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE, Key type:RSA, Length:2048, Cert Id:3968614624, Valid from:2000/5/30 18:48, Valid until:2020/5/30 18:48 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,534][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:01, Subject:CN=AddTrust Qualified CA Root, OU=AddTrust TTP Network, O=AddTrust AB, C=SE, Issuer:CN=AddTrust Qualified CA Root, OU=AddTrust TTP Network, O=AddTrust AB, C=SE, Key type:RSA, Length:2048, Cert Id:607365522, Valid from:2000/5/30 18:44, Valid until:2020/5/30 18:44 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,535][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:06:6c:9f:cf:99:bf:8c:0a:39:e2:f0:78:8a:43:e6:96:36:5b:ca, Subject:CN=Amazon Root CA 1, O=Amazon, C=US, Issuer:CN=Amazon Root CA 1, O=Amazon, C=US, Key type:RSA, Length:2048, Cert Id:2822522334, Valid from:2015/5/26 08:00, Valid until:2038/1/17 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,535][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:06:6c:9f:d2:96:35:86:9f:0a:0f:e5:86:78:f8:5b:26:bb:8a:37, Subject:CN=Amazon Root CA 2, O=Amazon, C=US, Issuer:CN=Amazon Root CA 2, O=Amazon, C=US, Key type:RSA, Length:4096, Cert Id:2528834908, Valid from:2015/5/26 08:00, Valid until:2040/5/26 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,537][DEBUG][main] X509Certificate: Alg:SHA256withECDSA, Serial:06:6c:9f:d5:74:97:36:66:3f:3b:0b:9a:d9:e8:9e:76:03:f2:4a, Subject:CN=Amazon Root CA 3, O=Amazon, C=US, Issuer:CN=Amazon Root CA 3, O=Amazon, C=US, Key type:EC, Length:256, Cert Id:2732679773, Valid from:2015/5/26 08:00, Valid until:2040/5/26 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,538][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:06:6c:9f:d7:c1:bb:10:4c:29:43:e5:71:7b:7b:2c:c8:1a:c1:0e, Subject:CN=Amazon Root CA 4, O=Amazon, C=US, Issuer:CN=Amazon Root CA 4, O=Amazon, C=US, Key type:EC, Length:384, Cert Id:2640694783, Valid from:2015/5/26 08:00, Valid until:2040/5/26 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,538][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:02, Subject:CN=Buypass Class 2 Root CA, O=Buypass AS-983163327, C=NO, Issuer:CN=Buypass Class 2 Root CA, O=Buypass AS-983163327, C=NO, Key type:RSA, Length:4096, Cert Id:969960563, Valid from:2010/10/26 16:38, Valid until:2040/10/26 16:38 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,538][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:02, Subject:CN=Buypass Class 3 Root CA, O=Buypass AS-983163327, C=NO, Issuer:CN=Buypass Class 3 Root CA, O=Buypass AS-983163327, C=NO, Key type:RSA, Length:4096, Cert Id:1264269967, Valid from:2010/10/26 16:28, Valid until:2040/10/26 16:28 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,538][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:00:a3:da:42:7e:a4:b1:ae:da, Subject:CN=Chambers of Commerce Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU, Issuer:CN=Chambers of Commerce Root - 2008, O=AC Camerfirma S.A., SERIALNUMBER=A82743287, L=Madrid (see current address at www.camerfirma.com/address), C=EU, Key type:RSA, Length:4096, Cert Id:4266703372, Valid from:2008/8/1 20:29, Valid until:2038/7/31 20:29 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,538][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:06:25:33:b1:47:03:33:27:5c:f9:8d:9a:b9:bf:cc:f8, Subject:CN=Certainly Root E1, O=Certainly, C=US, Issuer:CN=Certainly Root E1, O=Certainly, C=US, Key type:EC, Length:384, Cert Id:792571453, Valid from:2021/4/1 08:00, Valid until:2046/4/1 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,538][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00:8e:0f:f9:4b:90:71:68:65:33:54:f4:d4:44:39:b7:e0, Subject:CN=Certainly Root R1, O=Certainly, C=US, Issuer:CN=Certainly Root R1, O=Certainly, C=US, Key type:RSA, Length:4096, Cert Id:2255958535, Valid from:2021/4/1 08:00, Valid until:2046/4/1 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,539][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:00:fe:dc:e3:01:0f:c9:48:ff, Subject:CN=Certigna, O=Dhimyotis, C=FR, Issuer:CN=Certigna, O=Dhimyotis, C=FR, Key type:RSA, Length:2048, Cert Id:3506875840, Valid from:2007/6/29 23:13, Valid until:2027/6/29 23:13 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,539][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00:ca:e9:1b:89:f1:55:03:0d:a3:e6:41:6d:c4:e3:a6:e1, Subject:CN=Certigna Root CA, OU=0002 48146308100036, O=Dhimyotis, C=FR, Issuer:CN=Certigna Root CA, OU=0002 48146308100036, O=Dhimyotis, C=FR, Key type:RSA, Length:4096, Cert Id:356684591, Valid from:2013/10/1 16:32, Valid until:2033/10/1 16:32 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,539][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:01:00:20, Subject:CN=Certum CA, O=Unizeto Sp. z o.o., C=PL, Issuer:CN=Certum CA, O=Unizeto Sp. z o.o., C=PL, Key type:RSA, Length:2048, Cert Id:3550516030, Valid from:2002/6/11 18:46, Valid until:2027/6/11 18:46 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,539][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:04:44:c0, Subject:CN=Certum Trusted Network CA, OU=Certum Certification Authority, O=Unizeto Technologies S.A., C=PL, Issuer:CN=Certum Trusted Network CA, OU=Certum Certification Authority, O=Unizeto Technologies S.A., C=PL, Key type:RSA, Length:2048, Cert Id:2014002193, Valid from:2008/10/22 20:07, Valid until:2029/12/31 20:07 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,539][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:15:c8:bd:65:47:5c:af:b8:97:00:5e:e4:06:d2:bc:9d, Subject:OU=ePKI Root Certification Authority, O="Chunghwa Telecom Co., Ltd.", C=TW, Issuer:OU=ePKI Root Certification Authority, O="Chunghwa Telecom Co., Ltd.", C=TW, Key type:RSA, Length:4096, Cert Id:3632331159, Valid from:2004/12/20 10:31, Valid until:2034/12/20 10:31 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,539][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:01, Subject:CN=AAA Certificate Services, O=Comodo CA Limited, L=Salford, ST=Greater Manchester, C=GB, Issuer:CN=AAA Certificate Services, O=Comodo CA Limited, L=Salford, ST=Greater Manchester, C=GB, Key type:RSA, Length:2048, Cert Id:3097386402, Valid from:2004/1/1 08:00, Valid until:2029/1/1 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,540][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:1f:47:af:aa:62:00:70:50:54:4c:01:9e:9b:63:99:2a, Subject:CN=COMODO ECC Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB, Issuer:CN=COMODO ECC Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB, Key type:EC, Length:384, Cert Id:1146488932, Valid from:2008/3/6 08:00, Valid until:2038/1/19 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,540][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d, Subject:CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB, Issuer:CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB, Key type:RSA, Length:4096, Cert Id:1769425049, Valid from:2010/1/19 08:00, Valid until:2038/1/19 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,540][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0b:93:1c:3a:d6:39:67:ea:67:23:bf:c3:af:9a:f4:4b, Subject:CN=DigiCert Assured ID Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3909568913, Valid from:2013/8/1 20:00, Valid until:2038/1/15 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,540][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:0b:a1:5a:fa:1d:df:a0:b5:49:44:af:cd:24:a0:6c:ec, Subject:CN=DigiCert Assured ID Root G3, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root G3, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:EC, Length:384, Cert Id:3649430051, Valid from:2013/8/1 20:00, Valid until:2038/1/15 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,540][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39, Subject:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:3434562768, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,540][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:03:69:8f:e7:12:d5:19:f3:ce:d0:fd:b7:b1:64:30:11, Subject:CN=DigiCert CS ECC P384 Root G5, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert CS ECC P384 Root G5, O="DigiCert, Inc.", C=US, Key type:EC, Length:384, Cert Id:381797637, Valid from:2021/1/15 08:00, Valid until:2046/1/15 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,540][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:06:ce:e1:31:be:6d:55:c8:07:f7:c0:c7:fb:44:e6:20, Subject:CN=DigiCert CS RSA4096 Root G5, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert CS RSA4096 Root G5, O="DigiCert, Inc.", C=US, Key type:RSA, Length:4096, Cert Id:1193514382, Valid from:2021/1/15 08:00, Valid until:2046/1/15 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,541][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:08:3b:e0:56:90:42:46:b1:a1:75:6a:c9:59:91:c7:4a, Subject:CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Global Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:1341898239, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,541][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:03:3a:f1:e6:a7:11:a9:a0:bb:28:64:b1:1d:09:fa:e5, Subject:CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Global Root G2, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:1136084297, Valid from:2013/8/1 20:00, Valid until:2038/1/15 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,541][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:05:55:56:bc:f2:5e:a4:35:35:c3:a4:0f:d5:ab:45:72, Subject:CN=DigiCert Global Root G3, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Global Root G3, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:EC, Length:384, Cert Id:3498998753, Valid from:2013/8/1 20:00, Valid until:2038/1/15 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,541][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:02:ac:5c:26:6a:0b:40:9b:8f:0b:79:f2:ae:46:25:77, Subject:CN=DigiCert High Assurance EV Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert High Assurance EV Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:2048, Cert Id:2884286942, Valid from:2006/11/10 08:00, Valid until:2031/11/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,541][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:09:e0:93:65:ac:f7:d9:c8:b9:3e:1c:0b:04:2a:2e:f3, Subject:CN=DigiCert TLS ECC P384 Root G5, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert TLS ECC P384 Root G5, O="DigiCert, Inc.", C=US, Key type:EC, Length:384, Cert Id:3940772018, Valid from:2021/1/15 08:00, Valid until:2046/1/15 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,541][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:08:f9:b4:78:a8:fa:7e:da:6a:33:37:89:de:7c:cf:8a, Subject:CN=DigiCert TLS RSA4096 Root G5, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert TLS RSA4096 Root G5, O="DigiCert, Inc.", C=US, Key type:RSA, Length:4096, Cert Id:165956757, Valid from:2021/1/15 08:00, Valid until:2046/1/15 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,542][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:05:9b:1b:57:9e:8e:21:32:e2:39:07:bd:a7:77:75:5c, Subject:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:4096, Cert Id:1057369358, Valid from:2013/8/1 20:00, Valid until:2038/1/15 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,542][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:09:83:f3, Subject:CN=D-TRUST Root Class 3 CA 2 2009, O=D-Trust GmbH, C=DE, Issuer:CN=D-TRUST Root Class 3 CA 2 2009, O=D-Trust GmbH, C=DE, Key type:RSA, Length:2048, Cert Id:1430153102, Valid from:2009/11/5 16:35, Valid until:2029/11/5 16:35 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,542][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:09:83:f4, Subject:CN=D-TRUST Root Class 3 CA 2 EV 2009, O=D-Trust GmbH, C=DE, Issuer:CN=D-TRUST Root Class 3 CA 2 EV 2009, O=D-Trust GmbH, C=DE, Key type:RSA, Length:2048, Cert Id:971313728, Valid from:2009/11/5 16:50, Valid until:2029/11/5 16:50 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,542][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:3c:f6:07:a9:68:70:0e:da:8b:84, Subject:CN=emSign ECC Root CA - G3, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN, Issuer:CN=emSign ECC Root CA - G3, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN, Key type:EC, Length:384, Cert Id:3832035707, Valid from:2018/2/19 02:30, Valid until:2043/2/19 02:30 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,542][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:31:f5:e4:62:0c:6c:58:ed:d6:d8, Subject:CN=emSign Root CA - G1, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN, Issuer:CN=emSign Root CA - G1, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN, Key type:RSA, Length:2048, Cert Id:392709196, Valid from:2018/2/19 02:30, Valid until:2043/2/19 02:30 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,542][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:00:86:4d:bf:0f:e3:5e:d7:7d:8e:d8, Subject:CN=emSign Root CA - G2, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN, Issuer:CN=emSign Root CA - G2, O=eMudhra Technologies Limited, OU=emSign PKI, C=IN, Key type:RSA, Length:4096, Cert Id:3373940126, Valid from:2018/2/19 02:30, Valid until:2043/2/19 02:30 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,542][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:38:63:de:f8, Subject:CN=Entrust.net Certification Authority (2048), OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net, Issuer:CN=Entrust.net Certification Authority (2048), OU=(c) 1999 Entrust.net Limited, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), O=Entrust.net, Key type:RSA, Length:2048, Cert Id:3966431214, Valid from:1999/12/25 01:50, Valid until:2029/7/24 22:15 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,543][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:45:6b:50:54, Subject:CN=Entrust Root Certification Authority, OU="(c) 2006 Entrust, Inc.", OU=www.entrust.net/CPS is incorporated by reference, O="Entrust, Inc.", C=US, Issuer:CN=Entrust Root Certification Authority, OU="(c) 2006 Entrust, Inc.", OU=www.entrust.net/CPS is incorporated by reference, O="Entrust, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:3033563200, Valid from:2006/11/28 04:23, Valid until:2026/11/28 04:53 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,543][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:00:a6:8b:79:29:00:00:00:00:50:d0:91:f9, Subject:CN=Entrust Root Certification Authority - EC1, OU="(c) 2012 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US, Issuer:CN=Entrust Root Certification Authority - EC1, OU="(c) 2012 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US, Key type:EC, Length:384, Cert Id:924514073, Valid from:2012/12/18 23:25, Valid until:2037/12/18 23:55 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,544][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:4a:53:8c:28, Subject:CN=Entrust Root Certification Authority - G2, OU="(c) 2009 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US, Issuer:CN=Entrust Root Certification Authority - G2, OU="(c) 2009 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:1936920337, Valid from:2009/7/8 01:25, Valid until:2030/12/8 01:55 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,544][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00:d9:b5:43:7f:af:a9:39:0f:00:00:00:00:55:65:ad:58, Subject:CN=Entrust Root Certification Authority - G4, OU="(c) 2015 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US, Issuer:CN=Entrust Root Certification Authority - G4, OU="(c) 2015 Entrust, Inc. - for authorized use only", OU=See www.entrust.net/legal-terms, O="Entrust, Inc.", C=US, Key type:RSA, Length:4096, Cert Id:1368037548, Valid from:2015/5/27 19:11, Valid until:2037/12/27 19:41 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,544][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:02:34:56, Subject:CN=GeoTrust Global CA, O=GeoTrust Inc., C=US, Issuer:CN=GeoTrust Global CA, O=GeoTrust Inc., C=US, Key type:RSA, Length:2048, Cert Id:2266349922, Valid from:2002/5/21 12:00, Valid until:2022/5/21 12:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,544][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:18:ac:b5:6a:fd:69:b6:15:3a:63:6c:af:da:fa:c4:a1, Subject:CN=GeoTrust Primary Certification Authority, O=GeoTrust Inc., C=US, Issuer:CN=GeoTrust Primary Certification Authority, O=GeoTrust Inc., C=US, Key type:RSA, Length:2048, Cert Id:3329622139, Valid from:2006/11/27 08:00, Valid until:2036/7/17 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,544][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:3c:b2:f4:48:0a:00:e2:fe:eb:24:3b:5e:60:3e:c3:6b, Subject:CN=GeoTrust Primary Certification Authority - G2, OU=(c) 2007 GeoTrust Inc. - For authorized use only, O=GeoTrust Inc., C=US, Issuer:CN=GeoTrust Primary Certification Authority - G2, OU=(c) 2007 GeoTrust Inc. - For authorized use only, O=GeoTrust Inc., C=US, Key type:EC, Length:384, Cert Id:3180663474, Valid from:2007/11/5 08:00, Valid until:2038/1/19 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,544][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:15:ac:6e:94:19:b2:79:4b:41:f6:27:a9:c3:18:0f:1f, Subject:CN=GeoTrust Primary Certification Authority - G3, OU=(c) 2008 GeoTrust Inc. - For authorized use only, O=GeoTrust Inc., C=US, Issuer:CN=GeoTrust Primary Certification Authority - G3, OU=(c) 2008 GeoTrust Inc. - For authorized use only, O=GeoTrust Inc., C=US, Key type:RSA, Length:2048, Cert Id:2964813538, Valid from:2008/4/2 08:00, Valid until:2037/12/2 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,544][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:01, Subject:CN=GeoTrust Universal CA, O=GeoTrust Inc., C=US, Issuer:CN=GeoTrust Universal CA, O=GeoTrust Inc., C=US, Key type:RSA, Length:4096, Cert Id:313566089, Valid from:2004/3/4 13:00, Valid until:2029/3/4 13:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,545][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:04:00:00:00:00:01:15:4b:5a:c3:94, Subject:CN=GlobalSign Root CA, OU=Root CA, O=GlobalSign nv-sa, C=BE, Issuer:CN=GlobalSign Root CA, OU=Root CA, O=GlobalSign nv-sa, C=BE, Key type:RSA, Length:2048, Cert Id:536948034, Valid from:1998/9/1 20:00, Valid until:2028/1/28 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,545][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:11:d2:bb:ba:33:6e:d4:bc:e6:24:68:c5:0d:84:1d:98:e8:43, Subject:CN=GlobalSign Root E46, O=GlobalSign nv-sa, C=BE, Issuer:CN=GlobalSign Root E46, O=GlobalSign nv-sa, C=BE, Key type:EC, Length:384, Cert Id:3405603905, Valid from:2019/3/20 08:00, Valid until:2046/3/20 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,545][DEBUG][main] X509Certificate: Alg:SHA256withECDSA, Serial:2a:38:a4:1c:96:0a:04:de:42:b2:28:a5:0b:e8:34:98:02, Subject:CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R4, Issuer:CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R4, Key type:EC, Length:256, Cert Id:2371693751, Valid from:2012/11/13 08:00, Valid until:2038/1/19 11:14 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,545][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:60:59:49:e0:26:2e:bb:55:f9:0a:77:8a:71:f9:4a:d8:6c, Subject:CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R5, Issuer:CN=GlobalSign, O=GlobalSign, OU=GlobalSign ECC Root CA - R5, Key type:EC, Length:384, Cert Id:1997048439, Valid from:2012/11/13 08:00, Valid until:2038/1/19 11:14 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:04:00:00:00:00:01:21:58:53:08:a2, Subject:CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R3, Issuer:CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R3, Key type:RSA, Length:2048, Cert Id:733875591, Valid from:2009/3/18 18:00, Valid until:2029/3/18 18:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:11:d2:bb:b9:d7:23:18:9e:40:5f:0a:9d:2d:d0:df:25:67:d1, Subject:CN=GlobalSign Root R46, O=GlobalSign nv-sa, C=BE, Issuer:CN=GlobalSign Root R46, O=GlobalSign nv-sa, C=BE, Key type:RSA, Length:4096, Cert Id:1275948927, Valid from:2019/3/20 08:00, Valid until:2046/3/20 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:45:e6:bb:03:83:33:c3:85:65:48:e6:ff:45:51, Subject:CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R6, Issuer:CN=GlobalSign, O=GlobalSign, OU=GlobalSign Root CA - R6, Key type:RSA, Length:4096, Cert Id:3788339543, Valid from:2014/12/10 08:00, Valid until:2034/12/10 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:00, Subject:OU=Go Daddy Class 2 Certification Authority, O="The Go Daddy Group, Inc.", C=US, Issuer:OU=Go Daddy Class 2 Certification Authority, O="The Go Daddy Group, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:4023522997, Valid from:2004/6/30 01:06, Valid until:2034/6/30 01:06 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00, Subject:CN=Go Daddy Root Certificate Authority - G2, O="GoDaddy.com, Inc.", L=Scottsdale, ST=Arizona, C=US, Issuer:CN=Go Daddy Root Certificate Authority - G2, O="GoDaddy.com, Inc.", L=Scottsdale, ST=Arizona, C=US, Key type:RSA, Length:2048, Cert Id:439600313, Valid from:2009/9/1 08:00, Valid until:2038/1/1 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:02:03:e5:93:6f:31:b0:13:49:88:6b:a2:17, Subject:CN=GTS Root R1, O=Google Trust Services LLC, C=US, Issuer:CN=GTS Root R1, O=Google Trust Services LLC, C=US, Key type:RSA, Length:4096, Cert Id:657172038, Valid from:2016/6/22 08:00, Valid until:2036/6/22 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:02:03:e5:ae:c5:8d:04:25:1a:ab:11:25:aa, Subject:CN=GTS Root R2, O=Google Trust Services LLC, C=US, Issuer:CN=GTS Root R2, O=Google Trust Services LLC, C=US, Key type:RSA, Length:4096, Cert Id:948387669, Valid from:2016/6/22 08:00, Valid until:2036/6/22 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,546][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:02:03:e5:b8:82:eb:20:f8:25:27:6d:3d:66, Subject:CN=GTS Root R3, O=Google Trust Services LLC, C=US, Issuer:CN=GTS Root R3, O=Google Trust Services LLC, C=US, Key type:EC, Length:384, Cert Id:1163081155, Valid from:2016/6/22 08:00, Valid until:2036/6/22 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:02:03:e5:c0:68:ef:63:1a:9c:72:90:50:52, Subject:CN=GTS Root R4, O=Google Trust Services LLC, C=US, Issuer:CN=GTS Root R4, O=Google Trust Services LLC, C=US, Key type:EC, Length:384, Cert Id:1326433111, Valid from:2016/6/22 08:00, Valid until:2036/6/22 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA256withECDSA, Serial:00, Subject:CN=Hellenic Academic and Research Institutions ECC RootCA 2015, O=Hellenic Academic and Research Institutions Cert. Authority, L=Athens, C=GR, Issuer:CN=Hellenic Academic and Research Institutions ECC RootCA 2015, O=Hellenic Academic and Research Institutions Cert. Authority, L=Athens, C=GR, Key type:EC, Length:384, Cert Id:513613456, Valid from:2015/7/7 18:37, Valid until:2040/6/30 18:37 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00, Subject:CN=Hellenic Academic and Research Institutions RootCA 2015, O=Hellenic Academic and Research Institutions Cert. Authority, L=Athens, C=GR, Issuer:CN=Hellenic Academic and Research Institutions RootCA 2015, O=Hellenic Academic and Research Institutions Cert. Authority, L=Athens, C=GR, Key type:RSA, Length:4096, Cert Id:3491990565, Valid from:2015/7/7 18:11, Valid until:2040/6/30 18:11 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:01:42:80:00:00:01:45:23:c8:44:b5:00:00:00:02, Subject:CN=IdenTrust Commercial Root CA 1, O=IdenTrust, C=US, Issuer:CN=IdenTrust Commercial Root CA 1, O=IdenTrust, C=US, Key type:RSA, Length:4096, Cert Id:1232565210, Valid from:2014/1/17 02:12, Valid until:2034/1/17 02:12 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:01:42:80:00:00:01:45:23:cf:46:7c:00:00:00:02, Subject:CN=IdenTrust Public Sector Root CA 1, O=IdenTrust, C=US, Issuer:CN=IdenTrust Public Sector Root CA 1, O=IdenTrust, C=US, Key type:RSA, Length:4096, Cert Id:2123370772, Valid from:2014/1/17 01:53, Valid until:2034/1/17 01:53 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00:82:10:cf:b0:d2:40:e3:59:44:63:e0:bb:63:82:8b:00, Subject:CN=ISRG Root X1, O=Internet Security Research Group, C=US, Issuer:CN=ISRG Root X1, O=Internet Security Research Group, C=US, Key type:RSA, Length:4096, Cert Id:1521974916, Valid from:2015/6/4 19:04, Valid until:2035/6/4 19:04 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:41:d2:9d:d1:72:ea:ee:a7:80:c1:2c:6c:e9:2f:87:52, Subject:CN=ISRG Root X2, O=Internet Security Research Group, C=US, Issuer:CN=ISRG Root X2, O=Internet Security Research Group, C=US, Key type:EC, Length:384, Cert Id:3398642244, Valid from:2020/9/4 08:00, Valid until:2040/9/18 00:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,547][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0a:7e:a6:df:4b:44:9e:da:6a:24:85:9e:e6:b8:15:d3:16:7f:bb:b1, Subject:CN=LuxTrust Global Root 2, O=LuxTrust S.A., C=LU, Issuer:CN=LuxTrust Global Root 2, O=LuxTrust S.A., C=LU, Key type:RSA, Length:4096, Cert Id:3055636602, Valid from:2015/3/5 21:21, Valid until:2035/3/5 21:21 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0b:b8, Subject:CN=LuxTrust Global Root, O=LuxTrust s.a., C=LU, Issuer:CN=LuxTrust Global Root, O=LuxTrust s.a., C=LU, Key type:RSA, Length:2048, Cert Id:1714819687, Valid from:2011/3/17 17:51, Valid until:2021/3/17 17:51 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:66:f2:3d:af:87:de:8b:b1:4a:ea:0c:57:31:01:c2:ec, Subject:CN=Microsoft ECC Root Certificate Authority 2017, O=Microsoft Corporation, C=US, Issuer:CN=Microsoft ECC Root Certificate Authority 2017, O=Microsoft Corporation, C=US, Key type:EC, Length:384, Cert Id:3240761285, Valid from:2019/12/19 07:06, Valid until:2042/7/19 07:16 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:1e:d3:97:09:5f:d8:b4:b3:47:70:1e:aa:be:7f:45:b3, Subject:CN=Microsoft RSA Root Certificate Authority 2017, O=Microsoft Corporation, C=US, Issuer:CN=Microsoft RSA Root Certificate Authority 2017, O=Microsoft Corporation, C=US, Key type:RSA, Length:4096, Cert Id:2848349048, Valid from:2019/12/19 06:51, Valid until:2042/7/19 07:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:3a:b6:50:8b, Subject:CN=QuoVadis Root Certification Authority, OU=Root Certification Authority, O=QuoVadis Limited, C=BM, Issuer:CN=QuoVadis Root Certification Authority, OU=Root Certification Authority, O=QuoVadis Limited, C=BM, Key type:RSA, Length:2048, Cert Id:2412561694, Valid from:2001/3/20 02:33, Valid until:2021/3/18 02:33 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:78:58:5f:2e:ad:2c:19:4b:e3:37:07:35:34:13:28:b5:96:d4:65:93, Subject:CN=QuoVadis Root CA 1 G3, O=QuoVadis Limited, C=BM, Issuer:CN=QuoVadis Root CA 1 G3, O=QuoVadis Limited, C=BM, Key type:RSA, Length:4096, Cert Id:3532531262, Valid from:2012/1/13 01:27, Valid until:2042/1/13 01:27 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:05:09, Subject:CN=QuoVadis Root CA 2, O=QuoVadis Limited, C=BM, Issuer:CN=QuoVadis Root CA 2, O=QuoVadis Limited, C=BM, Key type:RSA, Length:4096, Cert Id:338250116, Valid from:2006/11/25 02:27, Valid until:2031/11/25 02:23 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:44:57:34:24:5b:81:89:9b:35:f2:ce:b8:2b:3b:5b:a7:26:f0:75:28, Subject:CN=QuoVadis Root CA 2 G3, O=QuoVadis Limited, C=BM, Issuer:CN=QuoVadis Root CA 2 G3, O=QuoVadis Limited, C=BM, Key type:RSA, Length:4096, Cert Id:696763521, Valid from:2012/1/13 02:59, Valid until:2042/1/13 02:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,548][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:05:c6, Subject:CN=QuoVadis Root CA 3, O=QuoVadis Limited, C=BM, Issuer:CN=QuoVadis Root CA 3, O=QuoVadis Limited, C=BM, Key type:RSA, Length:4096, Cert Id:1470392860, Valid from:2006/11/25 03:11, Valid until:2031/11/25 03:06 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:2e:f5:9b:02:28:a7:db:7a:ff:d5:a3:a9:ee:bd:03:a0:cf:12:6a:1d, Subject:CN=QuoVadis Root CA 3 G3, O=QuoVadis Limited, C=BM, Issuer:CN=QuoVadis Root CA 3 G3, O=QuoVadis Limited, C=BM, Key type:RSA, Length:4096, Cert Id:3589344305, Valid from:2012/1/13 04:26, Valid until:2042/1/13 04:26 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00, Subject:OU=Security Communication RootCA2, O="SECOM Trust Systems CO.,LTD.", C=JP, Issuer:OU=Security Communication RootCA2, O="SECOM Trust Systems CO.,LTD.", C=JP, Key type:RSA, Length:2048, Cert Id:1521072570, Valid from:2009/5/29 13:00, Valid until:2029/5/29 13:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:50:24:9b:a2:ef:8e:a6:bf:6c:2c:1f:1a:63:85:d4:c3, Subject:CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB, Issuer:CN=Sectigo Public Code Signing Root E46, O=Sectigo Limited, C=GB, Key type:EC, Length:384, Cert Id:3143279241, Valid from:2021/3/22 08:00, Valid until:2046/3/22 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:4b:2c:3b:01:01:8b:ad:2a:bc:8c:7b:5b:3e:ed:90:57, Subject:CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB, Issuer:CN=Sectigo Public Code Signing Root R46, O=Sectigo Limited, C=GB, Key type:RSA, Length:4096, Cert Id:2667769042, Valid from:2021/3/22 08:00, Valid until:2046/3/22 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:42:f2:cc:da:1b:69:37:44:5f:15:fe:75:28:10:b8:f4, Subject:CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB, Issuer:CN=Sectigo Public Server Authentication Root E46, O=Sectigo Limited, C=GB, Key type:EC, Length:384, Cert Id:3789385269, Valid from:2021/3/22 08:00, Valid until:2046/3/22 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:75:8d:fd:8b:ae:7c:07:00:fa:a9:25:a7:e1:c7:ad:14, Subject:CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB, Issuer:CN=Sectigo Public Server Authentication Root R46, O=Sectigo Limited, C=GB, Key type:RSA, Length:4096, Cert Id:3806652169, Valid from:2021/3/22 08:00, Valid until:2046/3/22 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:0c:f0:8e:5c:08:16:a5:ad:42:7f:f0:eb:27:18:59:d0, Subject:CN=SecureTrust CA, O=SecureTrust Corporation, C=US, Issuer:CN=SecureTrust CA, O=SecureTrust Corporation, C=US, Key type:RSA, Length:2048, Cert Id:2034155325, Valid from:2006/11/8 03:31, Valid until:2030/1/1 03:40 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA256withECDSA, Serial:75:e6:df:cb:c1:68:5b:a8, Subject:CN=SSL.com Root Certification Authority ECC, O=SSL Corporation, L=Houston, ST=Texas, C=US, Issuer:CN=SSL.com Root Certification Authority ECC, O=SSL Corporation, L=Houston, ST=Texas, C=US, Key type:EC, Length:384, Cert Id:2926673683, Valid from:2016/2/13 02:14, Valid until:2041/2/13 02:14 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,549][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:56:b6:29:cd:34:bc:78:f6, Subject:CN=SSL.com EV Root Certification Authority RSA R2, O=SSL Corporation, L=Houston, ST=Texas, C=US, Issuer:CN=SSL.com EV Root Certification Authority RSA R2, O=SSL Corporation, L=Houston, ST=Texas, C=US, Key type:RSA, Length:4096, Cert Id:1381862403, Valid from:2017/6/1 02:14, Valid until:2042/5/31 02:14 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:7b:2c:9b:d3:16:80:32:99, Subject:CN=SSL.com Root Certification Authority RSA, O=SSL Corporation, L=Houston, ST=Texas, C=US, Issuer:CN=SSL.com Root Certification Authority RSA, O=SSL Corporation, L=Houston, ST=Texas, C=US, Key type:RSA, Length:4096, Cert Id:156725711, Valid from:2016/2/13 01:39, Valid until:2041/2/13 01:39 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:14:03:f5:ab:fb:37:8b:17:40:5b:e2:43:b2:a5:d1:c4, Subject:CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US, Issuer:CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US, Key type:EC, Length:384, Cert Id:683561703, Valid from:2022/8/26 00:33, Valid until:2046/8/20 00:33 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:6f:be:da:ad:73:bd:08:40:e2:8b:4d:be:d4:f7:5b:91, Subject:CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US, Issuer:CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US, Key type:RSA, Length:4096, Cert Id:556880013, Valid from:2022/8/26 00:34, Valid until:2046/8/20 00:34 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:00, Subject:OU=Starfield Class 2 Certification Authority, O="Starfield Technologies, Inc.", C=US, Issuer:OU=Starfield Class 2 Certification Authority, O="Starfield Technologies, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:1825617644, Valid from:2004/6/30 01:39, Valid until:2034/6/30 01:39 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00, Subject:CN=Starfield Root Certificate Authority - G2, O="Starfield Technologies, Inc.", L=Scottsdale, ST=Arizona, C=US, Issuer:CN=Starfield Root Certificate Authority - G2, O="Starfield Technologies, Inc.", L=Scottsdale, ST=Arizona, C=US, Key type:RSA, Length:2048, Cert Id:3268325709, Valid from:2009/9/1 08:00, Valid until:2038/1/1 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:00, Subject:CN=Starfield Services Root Certificate Authority - G2, O="Starfield Technologies, Inc.", L=Scottsdale, ST=Arizona, C=US, Issuer:CN=Starfield Services Root Certificate Authority - G2, O="Starfield Technologies, Inc.", L=Scottsdale, ST=Arizona, C=US, Key type:RSA, Length:2048, Cert Id:1964785574, Valid from:2009/9/1 08:00, Valid until:2038/1/1 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:00:bb:40:1c:43:f5:5e:4f:b0, Subject:CN=SwissSign Gold CA - G2, O=SwissSign AG, C=CH, Issuer:CN=SwissSign Gold CA - G2, O=SwissSign AG, C=CH, Key type:RSA, Length:4096, Cert Id:1516221943, Valid from:2006/10/25 16:30, Valid until:2036/10/25 16:30 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:4e:b2:00:67:0c:03:5d:4f, Subject:CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH, Issuer:CN=SwissSign Platinum CA - G2, O=SwissSign AG, C=CH, Key type:RSA, Length:4096, Cert Id:771312514, Valid from:2006/10/25 16:36, Valid until:2036/10/25 16:36 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,550][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:4f:1b:d4:2f:54:bb:2f:4b, Subject:CN=SwissSign Silver CA - G2, O=SwissSign AG, C=CH, Issuer:CN=SwissSign Silver CA - G2, O=SwissSign AG, C=CH, Key type:RSA, Length:4096, Cert Id:126726124, Valid from:2006/10/25 16:32, Valid until:2036/10/25 16:32 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:01:67:5f:27:d6:fe:7a:e3:e4:ac:be:09:5b:05:9e, Subject:CN=Telia Root CA v2, O=Telia Finland Oyj, C=FI, Issuer:CN=Telia Root CA v2, O=Telia Finland Oyj, C=FI, Key type:RSA, Length:4096, Cert Id:3473063976, Valid from:2018/11/29 19:55, Valid until:2043/11/29 19:55 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:00:95:be:16:a0:f7:2e:46:f1:7b:39:82:72:fa:8b:cd:96, Subject:CN=TeliaSonera Root CA v1, O=TeliaSonera, Issuer:CN=TeliaSonera Root CA v1, O=TeliaSonera, Key type:RSA, Length:4096, Cert Id:1495358374, Valid from:2007/10/18 20:00, Valid until:2032/10/18 20:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:34:4e:d5:57:20:d5:ed:ec:49:f4:2f:ce:37:db:2b:6d, Subject:CN=thawte Primary Root CA, OU="(c) 2006 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US, Issuer:CN=thawte Primary Root CA, OU="(c) 2006 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:643000026, Valid from:2006/11/17 08:00, Valid until:2036/7/17 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:35:fc:26:5c:d9:84:4f:c9:3d:26:3d:57:9b:ae:d7:56, Subject:CN=thawte Primary Root CA - G2, OU="(c) 2007 thawte, Inc. - For authorized use only", O="thawte, Inc.", C=US, Issuer:CN=thawte Primary Root CA - G2, OU="(c) 2007 thawte, Inc. - For authorized use only", O="thawte, Inc.", C=US, Key type:EC, Length:384, Cert Id:2068083090, Valid from:2007/11/5 08:00, Valid until:2038/1/19 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:60:01:97:b7:46:a7:ea:b4:b4:9a:d6:4b:2f:f7:90:fb, Subject:CN=thawte Primary Root CA - G3, OU="(c) 2008 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US, Issuer:CN=thawte Primary Root CA - G3, OU="(c) 2008 thawte, Inc. - For authorized use only", OU=Certification Services Division, O="thawte, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:1032730720, Valid from:2008/4/2 08:00, Valid until:2037/12/2 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:01, Subject:CN=T-TeleSec GlobalRoot Class 2, OU=T-Systems Trust Center, O=T-Systems Enterprise Services GmbH, C=DE, Issuer:CN=T-TeleSec GlobalRoot Class 2, OU=T-Systems Trust Center, O=T-Systems Enterprise Services GmbH, C=DE, Key type:RSA, Length:2048, Cert Id:3056503257, Valid from:2008/10/1 18:40, Valid until:2033/10/2 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:01, Subject:CN=T-TeleSec GlobalRoot Class 3, OU=T-Systems Trust Center, O=T-Systems Enterprise Services GmbH, C=DE, Issuer:CN=T-TeleSec GlobalRoot Class 3, OU=T-Systems Trust Center, O=T-Systems Enterprise Services GmbH, C=DE, Key type:RSA, Length:2048, Cert Id:1894096264, Valid from:2008/10/1 18:29, Valid until:2033/10/2 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:0c:be, Subject:CN=TWCA Global Root CA, OU=Root CA, O=TAIWAN-CA, C=TW, Issuer:CN=TWCA Global Root CA, OU=Root CA, O=TAIWAN-CA, C=TW, Key type:RSA, Length:4096, Cert Id:861175838, Valid from:2012/6/27 14:28, Valid until:2030/12/31 23:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:5c:8b:99:c5:5a:94:c5:d2:71:56:de:cd:89:80:cc:26, Subject:CN=USERTrust ECC Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US, Issuer:CN=USERTrust ECC Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US, Key type:EC, Length:384, Cert Id:3329287386, Valid from:2010/2/1 08:00, Valid until:2038/1/19 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,551][DEBUG][main] X509Certificate: Alg:SHA384withRSA, Serial:01:fd:6d:30:fc:a3:ca:51:a8:1b:bc:64:0e:35:03:2d, Subject:CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US, Issuer:CN=USERTrust RSA Certification Authority, O=The USERTRUST Network, L=Jersey City, ST=New Jersey, C=US, Key type:RSA, Length:4096, Cert Id:3947601401, Valid from:2010/2/1 08:00, Valid until:2038/1/19 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,552][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:44:be:0c:8b:50:00:24:b4:11:d3:36:2d:e0:b3:5f:1b, Subject:CN=UTN-USERFirst-Object, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, ST=UT, C=US, Issuer:CN=UTN-USERFirst-Object, OU=http://www.usertrust.com, O=The USERTRUST Network, L=Salt Lake City, ST=UT, C=US, Key type:RSA, Length:2048, Cert Id:3997913868, Valid from:1999/7/10 02:31, Valid until:2019/7/10 02:40 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,552][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:00:9b:7e:06:49:a3:3e:62:b9:d5:ee:90:48:71:29:ef:57, Subject:CN=VeriSign Class 3 Public Primary Certification Authority - G3, OU="(c) 1999 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Issuer:CN=VeriSign Class 3 Public Primary Certification Authority - G3, OU="(c) 1999 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:2057300190, Valid from:1999/10/1 08:00, Valid until:2036/7/17 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,552][DEBUG][main] X509Certificate: Alg:SHA384withECDSA, Serial:2f:80:fe:23:8c:0e:22:0f:48:67:12:28:91:87:ac:b3, Subject:CN=VeriSign Class 3 Public Primary Certification Authority - G4, OU="(c) 2007 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Issuer:CN=VeriSign Class 3 Public Primary Certification Authority - G4, OU="(c) 2007 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Key type:EC, Length:384, Cert Id:4163473319, Valid from:2007/11/5 08:00, Valid until:2038/1/19 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,552][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:18:da:d1:9e:26:7d:e8:bb:4a:21:58:cd:cc:6b:3b:4a, Subject:CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Issuer:CN=VeriSign Class 3 Public Primary Certification Authority - G5, OU="(c) 2006 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:303010488, Valid from:2006/11/8 08:00, Valid until:2036/7/17 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,552][DEBUG][main] X509Certificate: Alg:SHA256withRSA, Serial:40:1a:c4:64:21:b3:13:21:03:0e:bb:e4:12:1a:c5:1d, Subject:CN=VeriSign Universal Root Certification Authority, OU="(c) 2008 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Issuer:CN=VeriSign Universal Root Certification Authority, OU="(c) 2008 VeriSign, Inc. - For authorized use only", OU=VeriSign Trust Network, O="VeriSign, Inc.", C=US, Key type:RSA, Length:2048, Cert Id:2318285810, Valid from:2008/4/2 08:00, Valid until:2037/12/2 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,552][DEBUG][main] X509Certificate: Alg:SHA1withRSA, Serial:50:94:6c:ec:18:ea:d5:9c:4d:d5:97:ef:75:8f:a0:ad, Subject:CN=XRamp Global Certification Authority, O=XRamp Security Services Inc, OU=www.xrampsecurity.com, C=US, Issuer:CN=XRamp Global Certification Authority, O=XRamp Security Services Inc, OU=www.xrampsecurity.com, C=US, Key type:RSA, Length:2048, Cert Id:3342493210, Valid from:2004/11/2 01:14, Valid until:2035/1/1 13:37 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:03,581][DEBUG][main] Creating shared instance of singleton bean 'x509TrustManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,581][DEBUG][main] Creating shared instance of singleton bean 'sslSocketFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,583][DEBUG][main] Creating shared instance of singleton bean 'businessApi' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,584][DEBUG][main] Creating shared instance of singleton bean 'supportApi' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,584][DEBUG][main] Creating shared instance of singleton bean 'noNeedLoginUrlList' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,584][DEBUG][main] Autowiring by type from bean name 'noNeedLoginUrlList' via factory method to bean named 'methodUrlMap' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,585][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,586][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.websocket.servlet.WebSocketServletAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,586][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,586][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$ThreadPoolTaskExecutorBuilderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,587][DEBUG][main] Creating shared instance of singleton bean 'threadPoolTaskExecutorBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,587][DEBUG][main] Creating shared instance of singleton bean 'spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,588][DEBUG][main] Autowiring by type from bean name 'threadPoolTaskExecutorBuilder' via factory method to bean named 'spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,590][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$TaskExecutorBuilderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,590][DEBUG][main] Creating shared instance of singleton bean 'taskExecutorBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,590][DEBUG][main] Autowiring by type from bean name 'taskExecutorBuilder' via factory method to bean named 'spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,591][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,592][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.task.TaskExecutorConfigurations$SimpleAsyncTaskExecutorBuilderConfiguration' via constructor to bean named 'spring.task.execution-org.springframework.boot.autoconfigure.task.TaskExecutionProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,592][DEBUG][main] Creating shared instance of singleton bean 'simpleAsyncTaskExecutorBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,593][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskExecutionAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,593][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.validation.ValidationAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,594][DEBUG][main] Creating shared instance of singleton bean 'defaultValidator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,594][DEBUG][main] Autowiring by type from bean name 'defaultValidator' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,595][DEBUG][main] Loaded expression factory via original TCCL (ResourceBundleMessageInterpolator.java:175) +[2026-06-02 18:55:03,596][DEBUG][main] Setting custom MessageInterpolator of type org.springframework.validation.beanvalidation.LocaleContextMessageInterpolator (AbstractConfigurationImpl.java:176) +[2026-06-02 18:55:03,596][DEBUG][main] Setting custom ConstraintValidatorFactory of type org.springframework.validation.beanvalidation.SpringConstraintValidatorFactory (AbstractConfigurationImpl.java:208) +[2026-06-02 18:55:03,597][DEBUG][main] Trying to load META-INF/validation.xml for XML based Validator configuration. (ValidationXmlParser.java:122) +[2026-06-02 18:55:03,597][DEBUG][main] Trying to load META-INF/validation.xml via user class loader (ResourceLoaderHelper.java:54) +[2026-06-02 18:55:03,597][DEBUG][main] Trying to load META-INF/validation.xml via TCCL (ResourceLoaderHelper.java:61) +[2026-06-02 18:55:03,597][DEBUG][main] Trying to load META-INF/validation.xml via Hibernate Validator's class loader (ResourceLoaderHelper.java:67) +[2026-06-02 18:55:03,597][DEBUG][main] No META-INF/validation.xml found. Using annotation based configuration only. (ValidationXmlParser.java:129) +[2026-06-02 18:55:03,597][DEBUG][main] Cannot find jakarta.persistence.Persistence on classpath. Assuming non JPA 2 environment. All properties will per default be traversable. (TraversableResolvers.java:61) +[2026-06-02 18:55:03,598][DEBUG][main] HV000252: Using org.hibernate.validator.internal.engine.DefaultPropertyNodeNameProvider as property node name provider. (ValidatorFactoryConfigurationHelper.java:355) +[2026-06-02 18:55:03,598][DEBUG][main] HV000234: Using org.springframework.validation.beanvalidation.LocaleContextMessageInterpolator as ValidatorFactory-scoped message interpolator. (ValidatorFactoryConfigurationHelper.java:447) +[2026-06-02 18:55:03,598][DEBUG][main] HV000234: Using org.hibernate.validator.internal.engine.resolver.TraverseAllTraversableResolver as ValidatorFactory-scoped traversable resolver. (ValidatorFactoryConfigurationHelper.java:448) +[2026-06-02 18:55:03,598][DEBUG][main] HV000234: Using org.hibernate.validator.internal.util.ExecutableParameterNameProvider as ValidatorFactory-scoped parameter name provider. (ValidatorFactoryConfigurationHelper.java:449) +[2026-06-02 18:55:03,598][DEBUG][main] HV000234: Using org.hibernate.validator.internal.engine.DefaultClockProvider as ValidatorFactory-scoped clock provider. (ValidatorFactoryConfigurationHelper.java:450) +[2026-06-02 18:55:03,598][DEBUG][main] HV000234: Using org.hibernate.validator.internal.engine.scripting.DefaultScriptEvaluatorFactory as ValidatorFactory-scoped script evaluator factory. (ValidatorFactoryConfigurationHelper.java:451) +[2026-06-02 18:55:03,603][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$WhitelabelErrorViewConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,604][DEBUG][main] Creating shared instance of singleton bean 'error' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,604][DEBUG][main] Creating shared instance of singleton bean 'beanNameViewResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,605][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,605][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration' via constructor to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,605][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.web.servlet.error.ErrorMvcAutoConfiguration$DefaultErrorViewResolverConfiguration' via constructor to bean named 'spring.web-org.springframework.boot.autoconfigure.web.WebProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,606][DEBUG][main] Creating shared instance of singleton bean 'conventionErrorViewResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,606][DEBUG][main] Creating shared instance of singleton bean 'errorAttributes' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,608][DEBUG][main] Creating shared instance of singleton bean 'basicErrorController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,608][DEBUG][main] Autowiring by type from bean name 'basicErrorController' via factory method to bean named 'errorAttributes' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,610][DEBUG][main] Creating shared instance of singleton bean 'welcomePageHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,610][DEBUG][main] Autowiring by type from bean name 'welcomePageHandlerMapping' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,610][DEBUG][main] Autowiring by type from bean name 'welcomePageHandlerMapping' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,610][DEBUG][main] Autowiring by type from bean name 'welcomePageHandlerMapping' via factory method to bean named 'mvcResourceUrlProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,616][DEBUG][main] Creating shared instance of singleton bean 'welcomePageNotAcceptableHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,616][DEBUG][main] Autowiring by type from bean name 'welcomePageNotAcceptableHandlerMapping' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,616][DEBUG][main] Autowiring by type from bean name 'welcomePageNotAcceptableHandlerMapping' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,616][DEBUG][main] Autowiring by type from bean name 'welcomePageNotAcceptableHandlerMapping' via factory method to bean named 'mvcResourceUrlProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,619][DEBUG][main] Creating shared instance of singleton bean 'localeResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,620][DEBUG][main] Creating shared instance of singleton bean 'themeResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,621][DEBUG][main] Creating shared instance of singleton bean 'flashMapManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,623][DEBUG][main] Creating shared instance of singleton bean 'mvcValidator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,625][DEBUG][main] Creating shared instance of singleton bean 'mvcPatternParser' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,625][DEBUG][main] Creating shared instance of singleton bean 'mvcUrlPathHelper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,626][DEBUG][main] Creating shared instance of singleton bean 'mvcPathMatcher' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,627][DEBUG][main] Creating shared instance of singleton bean 'viewControllerHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,628][DEBUG][main] Autowiring by type from bean name 'viewControllerHandlerMapping' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,628][DEBUG][main] Autowiring by type from bean name 'viewControllerHandlerMapping' via factory method to bean named 'mvcResourceUrlProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,628][DEBUG][main] Creating shared instance of singleton bean 'beanNameHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,628][DEBUG][main] Autowiring by type from bean name 'beanNameHandlerMapping' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,628][DEBUG][main] Autowiring by type from bean name 'beanNameHandlerMapping' via factory method to bean named 'mvcResourceUrlProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,629][DEBUG][main] 'beanNameHandlerMapping' {} (AbstractDetectingUrlHandlerMapping.java:86) +[2026-06-02 18:55:03,631][DEBUG][main] Creating shared instance of singleton bean 'routerFunctionMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,631][DEBUG][main] Autowiring by type from bean name 'routerFunctionMapping' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,631][DEBUG][main] Autowiring by type from bean name 'routerFunctionMapping' via factory method to bean named 'mvcResourceUrlProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,632][DEBUG][main] Creating shared instance of singleton bean 'messageConverters' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,632][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,633][DEBUG][main] Creating shared instance of singleton bean 'stringHttpMessageConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,633][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.HttpMessageConvertersAutoConfiguration$StringHttpMessageConverterConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,634][DEBUG][main] Autowiring by type from bean name 'stringHttpMessageConverter' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,636][DEBUG][main] Creating shared instance of singleton bean 'mappingJackson2HttpMessageConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,636][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration$MappingJackson2HttpMessageConverterConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,636][DEBUG][main] Autowiring by type from bean name 'mappingJackson2HttpMessageConverter' via factory method to bean named 'jacksonObjectMapper' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,662][DEBUG][main] Creating shared instance of singleton bean 'resourceHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,662][DEBUG][main] Autowiring by type from bean name 'resourceHandlerMapping' via factory method to bean named 'mvcContentNegotiationManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,662][DEBUG][main] Autowiring by type from bean name 'resourceHandlerMapping' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,662][DEBUG][main] Autowiring by type from bean name 'resourceHandlerMapping' via factory method to bean named 'mvcResourceUrlProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,667][DEBUG][main] 'resourceHandlerMapping' {/webjars/**=ResourceHttpRequestHandler [classpath [META-INF/resources/webjars/]], /**=ResourceHttpRequestHandler [classpath [META-INF/resources/], classpath [resources/], classpath [static/], classpath [public/], ServletContext [/]], /doc.html=ResourceHttpRequestHandler [classpath [META-INF/resources/]], /warm-flow-ui/**=ResourceHttpRequestHandler [classpath [META-INF/resources/warm-flow-ui/], classpath [warm-flow-ui/]], /upload/**=ResourceHttpRequestHandler [URL [file:../upload/]], /swagger-ui*/*swagger-initializer.js=ResourceHttpRequestHandler [classpath [META-INF/resources/webjars/]], /swagger-ui*/**=ResourceHttpRequestHandler [classpath [META-INF/resources/webjars/]]} (SimpleUrlHandlerMapping.java:176) +[2026-06-02 18:55:03,670][DEBUG][main] Creating shared instance of singleton bean 'defaultServletHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,670][DEBUG][main] Creating shared instance of singleton bean 'requestMappingHandlerAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,670][DEBUG][main] Autowiring by type from bean name 'requestMappingHandlerAdapter' via factory method to bean named 'mvcContentNegotiationManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,670][DEBUG][main] Autowiring by type from bean name 'requestMappingHandlerAdapter' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,670][DEBUG][main] Autowiring by type from bean name 'requestMappingHandlerAdapter' via factory method to bean named 'mvcValidator' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,674][DEBUG][main] Creating shared instance of singleton bean 'sortResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,675][DEBUG][main] Creating shared instance of singleton bean 'sortCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,675][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,676][DEBUG][main] Creating shared instance of singleton bean 'spring.data.web-org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,676][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.data.web.SpringDataWebAutoConfiguration' via constructor to bean named 'spring.data.web-org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,680][DEBUG][main] Creating shared instance of singleton bean 'pageableResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,680][DEBUG][main] Creating shared instance of singleton bean 'pageableCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,687][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocConfiguration$OpenApiResourceAdvice' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,688][DEBUG][main] Autowiring by type from bean name 'org.springdoc.core.configuration.SpringDocConfiguration$OpenApiResourceAdvice' via constructor to bean named 'org.springdoc.core.configuration.SpringDocConfiguration' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,689][DEBUG][main] ControllerAdvice beans: 0 @ModelAttribute, 0 @InitBinder, 2 RequestBodyAdvice, 2 ResponseBodyAdvice (RequestMappingHandlerAdapter.java:634) +[2026-06-02 18:55:03,708][DEBUG][main] Creating shared instance of singleton bean 'handlerFunctionAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,709][DEBUG][main] Creating shared instance of singleton bean 'mvcUriComponentsContributor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,710][DEBUG][main] Autowiring by type from bean name 'mvcUriComponentsContributor' via factory method to bean named 'mvcConversionService' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,710][DEBUG][main] Autowiring by type from bean name 'mvcUriComponentsContributor' via factory method to bean named 'requestMappingHandlerAdapter' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,711][DEBUG][main] Creating shared instance of singleton bean 'httpRequestHandlerAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,711][DEBUG][main] Creating shared instance of singleton bean 'simpleControllerHandlerAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,711][DEBUG][main] Creating shared instance of singleton bean 'handlerExceptionResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,712][DEBUG][main] Autowiring by type from bean name 'handlerExceptionResolver' via factory method to bean named 'mvcContentNegotiationManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,715][DEBUG][main] ControllerAdvice beans: 2 @ExceptionHandler, 2 ResponseBodyAdvice (ExceptionHandlerExceptionResolver.java:305) +[2026-06-02 18:55:03,716][DEBUG][main] Creating shared instance of singleton bean 'mvcViewResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,716][DEBUG][main] Autowiring by type from bean name 'mvcViewResolver' via factory method to bean named 'mvcContentNegotiationManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,718][DEBUG][main] Creating shared instance of singleton bean 'viewNameTranslator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,719][DEBUG][main] Creating shared instance of singleton bean 'defaultViewResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,725][DEBUG][main] Creating shared instance of singleton bean 'viewResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,725][DEBUG][main] Autowiring by type from bean name 'viewResolver' via factory method to bean named 'org.springframework.beans.factory.support.DefaultListableBeanFactory@2b2f5fcf' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,726][DEBUG][main] Creating shared instance of singleton bean 'viewResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,726][DEBUG][main] Creating shared instance of singleton bean 'freeMarkerViewResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,726][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.freemarker.FreeMarkerServletWebConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,727][DEBUG][main] Creating shared instance of singleton bean 'spring.freemarker-org.springframework.boot.autoconfigure.freemarker.FreeMarkerProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,729][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.freemarker.FreeMarkerServletWebConfiguration' via constructor to bean named 'spring.freemarker-org.springframework.boot.autoconfigure.freemarker.FreeMarkerProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,734][DEBUG][main] Creating shared instance of singleton bean 'cn.dev33.satoken.dao.SaTokenDaoForRedisTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,737][DEBUG][main] Creating shared instance of singleton bean 'cn.dev33.satoken.spring.SaBeanInject' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,739][DEBUG][main] Autowiring by type from bean name 'cn.dev33.satoken.spring.SaBeanInject' via constructor to bean named 'getSaTokenConfig' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,744][DEBUG][main] Creating shared instance of singleton bean 'getSaTokenContextForSpringInJakartaServlet' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,749][DEBUG][main] Creating shared instance of singleton bean 'getApplicationContextPathLoading' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,749][DEBUG][main] Found key 'server.servlet.context-path' in PropertySource 'environmentProperties' with value of type String (PropertySourcesPropertyResolver.java:115) +[2026-06-02 18:55:03,750][DEBUG][main] Creating shared instance of singleton bean 'com.alibaba.druid.spring.boot3.autoconfigure.stat.DruidFilterConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,754][DEBUG][main] Creating shared instance of singleton bean 'com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceAutoConfigure' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,755][DEBUG][main] Creating shared instance of singleton bean 'spring.datasource.druid-com.alibaba.druid.spring.boot3.autoconfigure.properties.DruidStatProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,755][DEBUG][main] Creating shared instance of singleton bean 'spring.datasource-org.springframework.boot.autoconfigure.jdbc.DataSourceProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,759][DEBUG][main] Creating shared instance of singleton bean 'com.baomidou.mybatisplus.autoconfigure.DdlAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,760][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration$HikariPoolDataSourceMetadataProviderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,760][DEBUG][main] Creating shared instance of singleton bean 'hikariPoolDataSourceMetadataProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,761][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.metadata.DataSourcePoolMetadataProvidersConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,761][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,762][DEBUG][main] Creating shared instance of singleton bean 'com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,762][DEBUG][main] Creating shared instance of singleton bean 'knife4j-com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,764][DEBUG][main] Autowiring by type from bean name 'com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration' via constructor to bean named 'knife4j-com.github.xiaoymin.knife4j.spring.configuration.Knife4jProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,764][DEBUG][main] Autowiring by type from bean name 'com.github.xiaoymin.knife4j.spring.configuration.Knife4jAutoConfiguration' via constructor to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,764][DEBUG][main] Creating shared instance of singleton bean 'knife4jOpenApiCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,764][DEBUG][main] Register Knife4jOpenApiCustomizer (Knife4jAutoConfiguration.java:61) +[2026-06-02 18:55:03,765][DEBUG][main] Creating shared instance of singleton bean 'knife4jJakartaOperationCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,765][DEBUG][main] Creating shared instance of singleton bean 'knife4j.basic-com.github.xiaoymin.knife4j.spring.configuration.Knife4jHttpBasic' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,766][DEBUG][main] Creating shared instance of singleton bean 'knife4j.setting-com.github.xiaoymin.knife4j.spring.configuration.Knife4jSetting' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,768][DEBUG][main] Creating shared instance of singleton bean 'warmFlowSpringUtil' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,768][DEBUG][main] Creating shared instance of singleton bean 'org.dromara.warm.plugin.modes.sb.helper.SpelHelper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,769][DEBUG][main] Creating shared instance of singleton bean 'formDao' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,771][DEBUG][main] Creating shared instance of singleton bean 'flowFormService' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,771][DEBUG][main] Autowiring by type from bean name 'flowFormService' via factory method to bean named 'formDao' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,774][DEBUG][main] Creating shared instance of singleton bean 'initFlow' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,776][DEBUG][main] Creating shared instance of singleton bean 'warm-flow-org.dromara.warm.plugin.modes.sb.config.WarmFlowProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,892][DEBUG][main] Creating shared instance of singleton bean 'org.dromara.warm.flow.ui.controller.WarmFlowUiController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,893][DEBUG][main] Creating shared instance of singleton bean 'org.dromara.warm.flow.ui.controller.WarmFlowController' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,895][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocConfiguration$QuerydslProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,896][DEBUG][main] Creating shared instance of singleton bean 'queryDslQuerydslPredicateOperationCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,896][DEBUG][main] Autowiring by type from bean name 'queryDslQuerydslPredicateOperationCustomizer' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,896][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocConfiguration$SpringDocWebFluxSupportConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,897][DEBUG][main] Creating shared instance of singleton bean 'webFluxSupportConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,897][DEBUG][main] Autowiring by type from bean name 'webFluxSupportConverter' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,897][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocConfiguration$SpringDocSpringDataWebPropertiesProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,898][DEBUG][main] Creating shared instance of singleton bean 'springDataWebPropertiesProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,898][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocConfiguration$WebConversionServiceConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,898][DEBUG][main] Creating shared instance of singleton bean 'webConversionServiceProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,899][DEBUG][main] Creating shared instance of singleton bean 'localSpringDocParameterNameDiscoverer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,899][DEBUG][main] Creating shared instance of singleton bean 'additionalModelsConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,899][DEBUG][main] Autowiring by type from bean name 'additionalModelsConverter' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,900][DEBUG][main] Creating shared instance of singleton bean 'propertyCustomizingConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,900][DEBUG][main] Creating shared instance of singleton bean 'fileSupportConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,901][DEBUG][main] Autowiring by type from bean name 'fileSupportConverter' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,901][DEBUG][main] Creating shared instance of singleton bean 'responseSupportConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,901][DEBUG][main] Autowiring by type from bean name 'responseSupportConverter' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,901][DEBUG][main] Creating shared instance of singleton bean 'schemaPropertyDeprecatingConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,902][DEBUG][main] Creating shared instance of singleton bean 'polymorphicModelConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,902][DEBUG][main] Autowiring by type from bean name 'polymorphicModelConverter' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,902][DEBUG][main] Creating shared instance of singleton bean 'modelConverterRegistrar' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,903][DEBUG][main] Creating shared instance of singleton bean 'pageableOpenAPIConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,903][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocPageableConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,903][DEBUG][main] Autowiring by type from bean name 'pageableOpenAPIConverter' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,904][DEBUG][main] Creating shared instance of singleton bean 'sortOpenAPIConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,904][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocSortConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,904][DEBUG][main] Autowiring by type from bean name 'sortOpenAPIConverter' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,905][DEBUG][main] Autowiring by type from bean name 'modelConverterRegistrar' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,916][DEBUG][main] Creating shared instance of singleton bean 'operationBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,916][DEBUG][main] Creating shared instance of singleton bean 'parameterBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,917][DEBUG][main] Creating shared instance of singleton bean 'propertyResolverUtils' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,917][DEBUG][main] Autowiring by type from bean name 'propertyResolverUtils' via factory method to bean named 'org.springframework.beans.factory.support.DefaultListableBeanFactory@2b2f5fcf' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,917][DEBUG][main] Autowiring by type from bean name 'propertyResolverUtils' via factory method to bean named 'messageSource' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,917][DEBUG][main] Autowiring by type from bean name 'propertyResolverUtils' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,918][DEBUG][main] Creating shared instance of singleton bean 'delegatingMethodParameterCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,920][DEBUG][main] Autowiring by type from bean name 'parameterBuilder' via factory method to bean named 'propertyResolverUtils' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,920][DEBUG][main] Autowiring by type from bean name 'parameterBuilder' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,922][DEBUG][main] Creating shared instance of singleton bean 'requestBodyBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,922][DEBUG][main] Autowiring by type from bean name 'requestBodyBuilder' via factory method to bean named 'parameterBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,924][DEBUG][main] Creating shared instance of singleton bean 'securityParser' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,924][DEBUG][main] Autowiring by type from bean name 'securityParser' via factory method to bean named 'propertyResolverUtils' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,925][DEBUG][main] Autowiring by type from bean name 'operationBuilder' via factory method to bean named 'parameterBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,925][DEBUG][main] Autowiring by type from bean name 'operationBuilder' via factory method to bean named 'requestBodyBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,925][DEBUG][main] Autowiring by type from bean name 'operationBuilder' via factory method to bean named 'securityParser' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,925][DEBUG][main] Autowiring by type from bean name 'operationBuilder' via factory method to bean named 'propertyResolverUtils' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,926][DEBUG][main] Creating shared instance of singleton bean 'genericReturnTypeParser' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,927][DEBUG][main] Creating shared instance of singleton bean 'springDocProviders' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,928][DEBUG][main] Creating shared instance of singleton bean 'routerFunctionProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,928][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.webmvc.core.configuration.SpringDocWebMvcConfiguration$SpringDocWebMvcRouterConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,929][DEBUG][main] Autowiring by type from bean name 'springDocProviders' via factory method to bean named 'springdocObjectMapperProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,930][DEBUG][main] Creating shared instance of singleton bean 'springDocCustomizers' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,933][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocKotlinConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,934][DEBUG][main] Creating shared instance of singleton bean 'kotlinCoroutinesReturnTypeParser' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,935][DEBUG][main] Creating shared instance of singleton bean 'nullableKotlinRequestParameterCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,936][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.core.configuration.SpringDocUIConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,936][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.webmvc.core.configuration.MultipleOpenApiSupportConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,937][DEBUG][main] Creating shared instance of singleton bean 'multipleOpenApiResource' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,937][DEBUG][main] Creating shared instance of singleton bean 'requestBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,938][DEBUG][main] Autowiring by type from bean name 'requestBuilder' via factory method to bean named 'parameterBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,938][DEBUG][main] Autowiring by type from bean name 'requestBuilder' via factory method to bean named 'requestBodyBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,938][DEBUG][main] Autowiring by type from bean name 'requestBuilder' via factory method to bean named 'operationBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,938][DEBUG][main] Autowiring by type from bean name 'requestBuilder' via factory method to bean named 'localSpringDocParameterNameDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,940][DEBUG][main] Creating shared instance of singleton bean 'responseBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,940][DEBUG][main] Autowiring by type from bean name 'responseBuilder' via factory method to bean named 'operationBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,940][DEBUG][main] Autowiring by type from bean name 'responseBuilder' via factory method to bean named 'genericReturnTypeParser' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,941][DEBUG][main] Autowiring by type from bean name 'responseBuilder' via factory method to bean named 'kotlinCoroutinesReturnTypeParser' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,941][DEBUG][main] Autowiring by type from bean name 'responseBuilder' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,941][DEBUG][main] Autowiring by type from bean name 'responseBuilder' via factory method to bean named 'propertyResolverUtils' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,942][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,942][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,942][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'businessApi' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'supportApi' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'requestBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'responseBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'operationBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'springDocProviders' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][main] Autowiring by type from bean name 'multipleOpenApiResource' via factory method to bean named 'springDocCustomizers' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,943][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,943][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,943][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,943][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,943][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,943][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,943][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:03,944][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:03,944][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:03,944][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,944][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,944][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:03,944][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 12, name=org.springframework.boot:type=Admin,name=SpringApplication, attribute=Ready (LoggingProviderImpl.java:230) +[2026-06-02 18:55:03,944][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: [127.0.0.1] exception: (Log.java:236) +javax.management.InstanceNotFoundException: org.springframework.boot:type=Admin,name=SpringApplication + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getMBean(DefaultMBeanServerInterceptor.java:1073) ~[?:?] + at java.management/com.sun.jmx.interceptor.DefaultMBeanServerInterceptor.getAttribute(DefaultMBeanServerInterceptor.java:632) ~[?:?] + at java.management/com.sun.jmx.mbeanserver.JmxMBeanServer.getAttribute(JmxMBeanServer.java:679) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doOperation(RMIConnectionImpl.java:1449) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl$PrivilegedOperation.run(RMIConnectionImpl.java:1310) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.doPrivilegedOperation(RMIConnectionImpl.java:1405) ~[?:?] + at java.management.rmi/javax.management.remote.rmi.RMIConnectionImpl.getAttribute(RMIConnectionImpl.java:639) ~[?:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at java.rmi/sun.rmi.server.UnicastServerRef.dispatch(UnicastServerRef.java:360) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:200) ~[?:?] + at java.rmi/sun.rmi.transport.Transport$1.run(Transport.java:197) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:714) ~[?:?] + at java.rmi/sun.rmi.transport.Transport.serviceCall(Transport.java:196) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport.handleMessages(TCPTransport.java:598) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run0(TCPTransport.java:844) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.lambda$run$0(TCPTransport.java:721) ~[?:?] + at java.base/java.security.AccessController.doPrivileged(AccessController.java:400) ~[?:?] + at java.rmi/sun.rmi.transport.tcp.TCPTransport$ConnectionHandler.run(TCPTransport.java:720) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1144) ~[?:?] + at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:642) ~[?:?] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:03,945][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:03,945][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@7320b9b4: connectionId=rmi://127.0.0.1 12] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:03,945][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@7320b9b4: connectionId=rmi://127.0.0.1 12] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:03,948][DEBUG][main] Autowiring by type from bean name 'openApiBuilder' via factory method to bean named 'securityParser' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,948][DEBUG][main] Autowiring by type from bean name 'openApiBuilder' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,948][DEBUG][main] Autowiring by type from bean name 'openApiBuilder' via factory method to bean named 'propertyResolverUtils' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,951][DEBUG][main] Creating shared instance of singleton bean 'org.springdoc.webmvc.core.configuration.SpringDocWebMvcConfiguration$SpringDocWebMvcActuatorConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,952][DEBUG][main] Creating shared instance of singleton bean 'openApiResource' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,952][DEBUG][main] Autowiring by type from bean name 'openApiResource' via factory method to bean named 'requestBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,952][DEBUG][main] Autowiring by type from bean name 'openApiResource' via factory method to bean named 'responseBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,952][DEBUG][main] Autowiring by type from bean name 'openApiResource' via factory method to bean named 'operationBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,952][DEBUG][main] Autowiring by type from bean name 'openApiResource' via factory method to bean named 'org.springdoc.core.properties.SpringDocConfigProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,952][DEBUG][main] Autowiring by type from bean name 'openApiResource' via factory method to bean named 'springDocProviders' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,952][DEBUG][main] Autowiring by type from bean name 'openApiResource' via factory method to bean named 'springDocCustomizers' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,958][DEBUG][main] Creating shared instance of singleton bean 'swaggerConfigResource' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,958][DEBUG][main] Autowiring by type from bean name 'swaggerConfigResource' via factory method to bean named 'swaggerWelcome' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,958][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.audit.AuditEventsEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,959][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,959][DEBUG][main] Creating shared instance of singleton bean 'applicationAvailability' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,961][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.availability.AvailabilityHealthContributorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,961][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.beans.BeansEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,962][DEBUG][main] Creating shared instance of singleton bean 'beansEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,962][DEBUG][main] Autowiring by type from bean name 'beansEndpoint' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,964][DEBUG][main] Creating shared instance of singleton bean 'meterRegistryCloser' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,964][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,965][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.redis.LettuceMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,965][DEBUG][main] Creating shared instance of singleton bean 'micrometerOptions' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,967][DEBUG][main] Creating shared instance of singleton bean 'lettuceMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,967][DEBUG][main] Autowiring by type from bean name 'lettuceMetrics' via factory method to bean named 'simpleMeterRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,967][DEBUG][main] Autowiring by type from bean name 'lettuceMetrics' via factory method to bean named 'micrometerOptions' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,968][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,968][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration' via constructor to bean named 'spring.data.redis-org.springframework.boot.autoconfigure.data.redis.RedisProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,968][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.data.redis.LettuceConnectionConfiguration' via constructor to bean named 'redisConnectionDetails' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,971][DEBUG][main] Creating shared instance of singleton bean 'lettuceClientResources' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,972][DEBUG][main] Starting with netty's non-blocking DNS resolver library (AddressResolverGroupProvider.java:34) +[2026-06-02 18:55:03,973][DEBUG][main] Starting without optional kqueue library (KqueueProvider.java:73) +[2026-06-02 18:55:03,973][DEBUG][main] Starting without optional io_uring library (IOUringProvider.java:75) +[2026-06-02 18:55:03,974][DEBUG][main] Starting without optional epoll library (EpollProvider.java:76) +[2026-06-02 18:55:03,974][DEBUG][main] -Dio.netty.eventLoopThreads: 10 (DefaultClientResources.java:122) +[2026-06-02 18:55:03,977][DEBUG][main] Creating executor io.netty.util.concurrent.DefaultEventExecutorGroup (DefaultEventLoopGroupProvider.java:231) +[2026-06-02 18:55:03,979][DEBUG][main] Using Slf4j logging framework (Loggers.java:254) +[2026-06-02 18:55:03,980][DEBUG][main] Starting with JFR support (EventRecorderHolder.java:47) +[2026-06-02 18:55:03,985][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizationAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,986][DEBUG][main] Creating shared instance of singleton bean 'platformTransactionManagerCustomizers' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,986][DEBUG][main] Creating shared instance of singleton bean 'transactionExecutionListeners' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,987][DEBUG][main] Creating shared instance of singleton bean 'spring.transaction-org.springframework.boot.autoconfigure.transaction.TransactionProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,989][DEBUG][main] Creating shared instance of singleton bean 'java.lang.Object' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,989][DEBUG][main] Creating shared instance of singleton bean 'cacheAutoConfigurationValidator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,989][DEBUG][main] Autowiring by type from bean name 'cacheAutoConfigurationValidator' via factory method to bean named 'spring.cache-org.springframework.boot.autoconfigure.cache.CacheProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,989][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.cache.CachesEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,990][DEBUG][main] Creating shared instance of singleton bean 'cachesEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,990][DEBUG][main] Autowiring by type from bean name 'cachesEndpoint' via factory method to bean named 'cacheManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,992][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.health.HealthEndpointConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,992][DEBUG][main] Creating shared instance of singleton bean 'healthStatusAggregator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,993][DEBUG][main] Creating shared instance of singleton bean 'management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,994][DEBUG][main] Autowiring by type from bean name 'healthStatusAggregator' via factory method to bean named 'management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,995][DEBUG][main] Creating shared instance of singleton bean 'healthHttpCodeStatusMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,995][DEBUG][main] Autowiring by type from bean name 'healthHttpCodeStatusMapper' via factory method to bean named 'management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,996][DEBUG][main] Creating shared instance of singleton bean 'healthEndpointGroups' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,996][DEBUG][main] Autowiring by type from bean name 'healthEndpointGroups' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,996][DEBUG][main] Autowiring by type from bean name 'healthEndpointGroups' via factory method to bean named 'management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:03,998][DEBUG][main] Creating shared instance of singleton bean 'healthContributorRegistry' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,999][DEBUG][main] Creating shared instance of singleton bean 'diskSpaceHealthIndicator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,999][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthContributorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:03,999][DEBUG][main] Creating shared instance of singleton bean 'management.health.diskspace-org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,000][DEBUG][main] Autowiring by type from bean name 'diskSpaceHealthIndicator' via factory method to bean named 'management.health.diskspace-org.springframework.boot.actuate.autoconfigure.system.DiskSpaceHealthIndicatorProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,001][DEBUG][main] Creating shared instance of singleton bean 'pingHealthContributor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,001][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,002][DEBUG][main] Creating shared instance of singleton bean 'dbHealthContributor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,002][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthContributorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,003][DEBUG][main] Creating shared instance of singleton bean 'management.health.db-org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,003][DEBUG][main] Autowiring by type from bean name 'dbHealthContributor' via factory method to bean named 'druidDataSource' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,003][DEBUG][main] Autowiring by type from bean name 'dbHealthContributor' via factory method to bean named 'management.health.db-org.springframework.boot.actuate.autoconfigure.jdbc.DataSourceHealthIndicatorProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,007][DEBUG][main] Creating shared instance of singleton bean 'redisHealthContributor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,007][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.data.redis.RedisReactiveHealthContributorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,008][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.data.redis.RedisReactiveHealthContributorAutoConfiguration' via constructor to bean named 'redissonConnectionFactory' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,011][DEBUG][main] Autowiring by type from bean name 'healthContributorRegistry' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,011][DEBUG][main] Autowiring by type from bean name 'healthContributorRegistry' via factory method to bean named 'healthEndpointGroups' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,011][DEBUG][main] Autowiring by type from bean name 'healthContributorRegistry' via factory method to bean named 'diskSpaceHealthIndicator' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,011][DEBUG][main] Autowiring by type from bean name 'healthContributorRegistry' via factory method to bean named 'pingHealthContributor' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,011][DEBUG][main] Autowiring by type from bean name 'healthContributorRegistry' via factory method to bean named 'dbHealthContributor' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,011][DEBUG][main] Autowiring by type from bean name 'healthContributorRegistry' via factory method to bean named 'redisHealthContributor' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,014][DEBUG][main] Creating shared instance of singleton bean 'healthEndpointGroupMembershipValidator' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,015][DEBUG][main] Autowiring by type from bean name 'healthEndpointGroupMembershipValidator' via factory method to bean named 'management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,015][DEBUG][main] Autowiring by type from bean name 'healthEndpointGroupMembershipValidator' via factory method to bean named 'healthContributorRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,015][DEBUG][main] Creating shared instance of singleton bean 'healthEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,016][DEBUG][main] Autowiring by type from bean name 'healthEndpoint' via factory method to bean named 'healthContributorRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,016][DEBUG][main] Autowiring by type from bean name 'healthEndpoint' via factory method to bean named 'healthEndpointGroups' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,016][DEBUG][main] Autowiring by type from bean name 'healthEndpoint' via factory method to bean named 'management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,018][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.health.ReactiveHealthEndpointConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,018][DEBUG][main] Creating shared instance of singleton bean 'reactiveHealthContributorRegistry' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,018][DEBUG][main] Autowiring by type from bean name 'reactiveHealthContributorRegistry' via factory method to bean named 'diskSpaceHealthIndicator' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,018][DEBUG][main] Autowiring by type from bean name 'reactiveHealthContributorRegistry' via factory method to bean named 'pingHealthContributor' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,018][DEBUG][main] Autowiring by type from bean name 'reactiveHealthContributorRegistry' via factory method to bean named 'dbHealthContributor' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,018][DEBUG][main] Autowiring by type from bean name 'reactiveHealthContributorRegistry' via factory method to bean named 'redisHealthContributor' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,018][DEBUG][main] Autowiring by type from bean name 'reactiveHealthContributorRegistry' via factory method to bean named 'healthEndpointGroups' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,020][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration$MvcAdditionalHealthEndpointPathsConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,020][DEBUG][main] Creating shared instance of singleton bean 'healthEndpointWebMvcHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,021][DEBUG][main] Creating shared instance of singleton bean 'webEndpointDiscoverer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,021][DEBUG][main] Creating shared instance of singleton bean 'endpointOperationParameterMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,021][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,023][DEBUG][main] Creating shared instance of singleton bean 'endpointMediaTypes' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,024][DEBUG][main] Autowiring by type from bean name 'webEndpointDiscoverer' via factory method to bean named 'endpointOperationParameterMapper' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,024][DEBUG][main] Autowiring by type from bean name 'webEndpointDiscoverer' via factory method to bean named 'endpointMediaTypes' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,024][DEBUG][main] Creating shared instance of singleton bean 'endpointCachingOperationInvokerAdvisor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,024][DEBUG][main] Autowiring by type from bean name 'endpointCachingOperationInvokerAdvisor' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,025][DEBUG][main] Creating shared instance of singleton bean 'webExposeExcludePropertyEndpointFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,028][DEBUG][main] Autowiring by type from bean name 'healthEndpointWebMvcHandlerMapping' via factory method to bean named 'webEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,028][DEBUG][main] Autowiring by type from bean name 'healthEndpointWebMvcHandlerMapping' via factory method to bean named 'healthEndpointGroups' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,037][DEBUG][main] Creating shared instance of singleton bean 'healthEndpointWebExtension' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,037][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.health.HealthEndpointWebExtensionConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,038][DEBUG][main] Autowiring by type from bean name 'healthEndpointWebExtension' via factory method to bean named 'healthContributorRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,038][DEBUG][main] Autowiring by type from bean name 'healthEndpointWebExtension' via factory method to bean named 'healthEndpointGroups' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,038][DEBUG][main] Autowiring by type from bean name 'healthEndpointWebExtension' via factory method to bean named 'management.endpoint.health-org.springframework.boot.actuate.autoconfigure.health.HealthEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,039][DEBUG][main] Creating shared instance of singleton bean 'infoEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,039][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.info.InfoEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,041][DEBUG][main] Creating shared instance of singleton bean 'conditionsReportEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,041][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,041][DEBUG][main] Autowiring by type from bean name 'conditionsReportEndpoint' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,041][DEBUG][main] Creating shared instance of singleton bean 'configurationPropertiesReportEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,041][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,042][DEBUG][main] Creating shared instance of singleton bean 'management.endpoint.configprops-org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,043][DEBUG][main] Autowiring by type from bean name 'configurationPropertiesReportEndpoint' via factory method to bean named 'management.endpoint.configprops-org.springframework.boot.actuate.autoconfigure.context.properties.ConfigurationPropertiesReportEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,047][DEBUG][main] Creating shared instance of singleton bean 'environmentEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,047][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,048][DEBUG][main] Creating shared instance of singleton bean 'management.endpoint.env-org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,048][DEBUG][main] Autowiring by type from bean name 'environmentEndpoint' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,048][DEBUG][main] Autowiring by type from bean name 'environmentEndpoint' via factory method to bean named 'management.endpoint.env-org.springframework.boot.actuate.autoconfigure.env.EnvironmentEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,050][DEBUG][main] Creating shared instance of singleton bean 'loggersEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,050][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.logging.LoggersEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,051][DEBUG][main] Autowiring by type from bean name 'loggersEndpoint' via factory method to bean named 'springBootLoggingSystem' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,052][DEBUG][main] Creating shared instance of singleton bean 'heapDumpWebEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,052][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.management.HeapDumpWebEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,053][DEBUG][main] Creating shared instance of singleton bean 'dumpEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,053][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.management.ThreadDumpEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,054][DEBUG][main] Creating shared instance of singleton bean 'metricsEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,054][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.MetricsEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,055][DEBUG][main] Autowiring by type from bean name 'metricsEndpoint' via factory method to bean named 'simpleMeterRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,056][DEBUG][main] Creating shared instance of singleton bean 'sbomEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,056][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.sbom.SbomEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,056][DEBUG][main] Creating shared instance of singleton bean 'management.endpoint.sbom-org.springframework.boot.actuate.sbom.SbomProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,057][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.sbom.SbomEndpointAutoConfiguration' via constructor to bean named 'management.endpoint.sbom-org.springframework.boot.actuate.sbom.SbomProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,057][DEBUG][main] Autowiring by type from bean name 'sbomEndpoint' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,058][DEBUG][main] Creating shared instance of singleton bean 'scheduledTasksEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,058][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,059][DEBUG][main] Creating shared instance of singleton bean 'mappingsEndpoint' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,059][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,059][DEBUG][main] Autowiring by type from bean name 'mappingsEndpoint' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,060][DEBUG][main] Creating shared instance of singleton bean 'dispatcherServletMappingDescriptionProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,060][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration$ServletWebConfiguration$SpringMvcConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,061][DEBUG][main] Creating shared instance of singleton bean 'servletMappingDescriptionProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,061][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.mappings.MappingsEndpointAutoConfiguration$ServletWebConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,062][DEBUG][main] Creating shared instance of singleton bean 'filterMappingDescriptionProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,072][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.health.HealthEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,073][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,073][DEBUG][main] Creating shared instance of singleton bean 'spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,074][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration' via constructor to bean named 'spring.info-org.springframework.boot.autoconfigure.info.ProjectInfoProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,074][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,076][DEBUG][main] Creating shared instance of singleton bean 'management.info-org.springframework.boot.actuate.autoconfigure.info.InfoContributorProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,077][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.servlet.ServletManagementContextAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,077][DEBUG][main] Creating shared instance of singleton bean 'servletWebChildContextFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,078][DEBUG][main] Creating shared instance of singleton bean 'managementServletContext' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,078][DEBUG][main] Autowiring by type from bean name 'managementServletContext' via factory method to bean named 'management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,079][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.data.redis.RedisReactiveAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,080][DEBUG][main] Creating shared instance of singleton bean 'reactiveRedisTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,080][DEBUG][main] Autowiring by type from bean name 'reactiveRedisTemplate' via factory method to bean named 'redissonConnectionFactory' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,080][DEBUG][main] Autowiring by type from bean name 'reactiveRedisTemplate' via factory method to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,094][DEBUG][main] Creating shared instance of singleton bean 'reactiveStringRedisTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,094][DEBUG][main] Autowiring by type from bean name 'reactiveStringRedisTemplate' via factory method to bean named 'redissonConnectionFactory' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,096][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.data.redis.RedisHealthContributorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,097][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,098][DEBUG][main] Creating shared instance of singleton bean 'spring.jmx-org.springframework.boot.autoconfigure.jmx.JmxProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,099][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.jmx.JmxAutoConfiguration' via constructor to bean named 'spring.jmx-org.springframework.boot.autoconfigure.jmx.JmxProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,099][DEBUG][main] Creating shared instance of singleton bean 'mbeanExporter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,100][DEBUG][main] Creating shared instance of singleton bean 'objectNamingStrategy' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,102][DEBUG][main] Autowiring by type from bean name 'mbeanExporter' via factory method to bean named 'objectNamingStrategy' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,102][DEBUG][main] Autowiring by type from bean name 'mbeanExporter' via factory method to bean named 'org.springframework.beans.factory.support.DefaultListableBeanFactory@2b2f5fcf' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,104][DEBUG][main] Creating shared instance of singleton bean 'mbeanServer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,105][DEBUG][main] Found MBeanServer: com.sun.jmx.mbeanserver.JmxMBeanServer@5e4c8041 (JmxUtils.java:127) +[2026-06-02 18:55:04,114][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,114][DEBUG][main] Creating shared instance of singleton bean 'management.endpoints.jmx-org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,115][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration' via constructor to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,115][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration' via constructor to bean named 'management.endpoints.jmx-org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,115][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.endpoint.jmx.JmxEndpointAutoConfiguration' via constructor to bean named 'spring.jmx-org.springframework.boot.autoconfigure.jmx.JmxProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,116][DEBUG][main] Creating shared instance of singleton bean 'jmxAnnotationEndpointDiscoverer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,116][DEBUG][main] Autowiring by type from bean name 'jmxAnnotationEndpointDiscoverer' via factory method to bean named 'endpointOperationParameterMapper' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,116][DEBUG][main] Creating shared instance of singleton bean 'jmxIncludeExcludePropertyEndpointFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,118][DEBUG][main] Creating shared instance of singleton bean 'endpointObjectNameFactory' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,118][DEBUG][main] Autowiring by type from bean name 'endpointObjectNameFactory' via factory method to bean named 'mbeanServer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,118][DEBUG][main] Creating shared instance of singleton bean 'jmxMBeanExporter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,119][DEBUG][main] Autowiring by type from bean name 'jmxMBeanExporter' via factory method to bean named 'mbeanServer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,119][DEBUG][main] Autowiring by type from bean name 'jmxMBeanExporter' via factory method to bean named 'endpointObjectNameFactory' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,119][DEBUG][main] Autowiring by type from bean name 'jmxMBeanExporter' via factory method to bean named 'jmxAnnotationEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,132][DEBUG][main] Creating shared instance of singleton bean 'eagerlyInitializeJmxEndpointExporter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,134][DEBUG][main] Creating shared instance of singleton bean 'controllerEndpointDiscoverer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,134][DEBUG][main] Creating shared instance of singleton bean 'controllerExposeExcludePropertyEndpointFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,136][DEBUG][main] Creating shared instance of singleton bean 'pathMappedEndpoints' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,136][DEBUG][main] Autowiring by type from bean name 'pathMappedEndpoints' via factory method to bean named 'jmxAnnotationEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,136][DEBUG][main] Autowiring by type from bean name 'pathMappedEndpoints' via factory method to bean named 'servletEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,136][DEBUG][main] Autowiring by type from bean name 'pathMappedEndpoints' via factory method to bean named 'webEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,136][DEBUG][main] Autowiring by type from bean name 'pathMappedEndpoints' via factory method to bean named 'controllerEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,142][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,143][DEBUG][main] Creating shared instance of singleton bean 'management.endpoint.logfile-org.springframework.boot.actuate.autoconfigure.logging.LogFileWebEndpointProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,143][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.mail.MailSenderAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,143][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.JvmMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,144][DEBUG][main] Creating shared instance of singleton bean 'jvmGcMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,145][DEBUG][main] Using SLF4J as the default logging framework (InternalLoggerFactory.java:59) +[2026-06-02 18:55:04,147][DEBUG][main] Creating shared instance of singleton bean 'jvmHeapPressureMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,149][DEBUG][main] Creating shared instance of singleton bean 'jvmMemoryMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,149][DEBUG][main] Creating shared instance of singleton bean 'jvmThreadMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,150][DEBUG][main] Creating shared instance of singleton bean 'classLoaderMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,150][DEBUG][main] Creating shared instance of singleton bean 'jvmInfoMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,150][DEBUG][main] Creating shared instance of singleton bean 'jvmCompilationMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,151][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.Log4J2MetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,151][DEBUG][main] Creating shared instance of singleton bean 'log4j2Metrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,152][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.SystemMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,152][DEBUG][main] Creating shared instance of singleton bean 'uptimeMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,153][DEBUG][main] Creating shared instance of singleton bean 'processorMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,154][DEBUG][main] Creating shared instance of singleton bean 'fileDescriptorMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,154][DEBUG][main] Creating shared instance of singleton bean 'diskSpaceMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,155][DEBUG][main] Autowiring by type from bean name 'diskSpaceMetrics' via factory method to bean named 'management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,155][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMeterBinderProvidersConfiguration$RedisCacheMeterBinderProviderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,155][DEBUG][main] Creating shared instance of singleton bean 'redisCacheMeterBinderProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,156][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMeterBinderProvidersConfiguration$JCacheCacheMeterBinderProviderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,156][DEBUG][main] Creating shared instance of singleton bean 'jCacheCacheMeterBinderProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,157][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMeterBinderProvidersConfiguration$CaffeineCacheMeterBinderProviderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,157][DEBUG][main] Creating shared instance of singleton bean 'caffeineCacheMeterBinderProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,157][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMeterBinderProvidersConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,157][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsRegistrarConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,158][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsRegistrarConfiguration' via constructor to bean named 'simpleMeterRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,158][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsRegistrarConfiguration' via constructor to bean named 'redisCacheMeterBinderProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,158][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsRegistrarConfiguration' via constructor to bean named 'jCacheCacheMeterBinderProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,158][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsRegistrarConfiguration' via constructor to bean named 'caffeineCacheMeterBinderProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,158][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsRegistrarConfiguration' via constructor to bean named 'cacheManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,159][DEBUG][main] Creating shared instance of singleton bean 'cacheMetricsRegistrar' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,159][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.cache.CacheMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,159][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.data.RepositoryMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,159][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.metrics.data.RepositoryMetricsAutoConfiguration' via constructor to bean named 'management.metrics-org.springframework.boot.actuate.autoconfigure.metrics.MetricsProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,160][DEBUG][main] Creating shared instance of singleton bean 'repositoryTagsProvider' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,160][DEBUG][main] Creating shared instance of singleton bean 'metricsRepositoryMethodInvocationListener' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,161][DEBUG][main] Autowiring by type from bean name 'metricsRepositoryMethodInvocationListener' via factory method to bean named 'repositoryTagsProvider' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,162][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,162][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$HikariDataSourceMetricsConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,163][DEBUG][main] Creating shared instance of singleton bean 'hikariDataSourceMeterBinder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,163][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration$DataSourcePoolMetadataMetricsConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,164][DEBUG][main] Creating shared instance of singleton bean 'dataSourcePoolMetadataMeterBinder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,164][DEBUG][main] Autowiring by type from bean name 'dataSourcePoolMetadataMeterBinder' via factory method to bean named 'druidDataSource' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,164][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.jdbc.DataSourcePoolMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,164][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.startup.StartupTimeMetricsListenerAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,165][DEBUG][main] Creating shared instance of singleton bean 'startupTimeMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,165][DEBUG][main] Autowiring by type from bean name 'startupTimeMetrics' via factory method to bean named 'simpleMeterRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,166][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$ThreadPoolTaskSchedulerBuilderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,166][DEBUG][main] Creating shared instance of singleton bean 'threadPoolTaskSchedulerBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,167][DEBUG][main] Creating shared instance of singleton bean 'spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,167][DEBUG][main] Autowiring by type from bean name 'threadPoolTaskSchedulerBuilder' via factory method to bean named 'spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,169][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$TaskSchedulerBuilderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,169][DEBUG][main] Creating shared instance of singleton bean 'taskSchedulerBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,169][DEBUG][main] Autowiring by type from bean name 'taskSchedulerBuilder' via factory method to bean named 'spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,170][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,170][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$SimpleAsyncTaskSchedulerBuilderConfiguration' via constructor to bean named 'spring.task.scheduling-org.springframework.boot.autoconfigure.task.TaskSchedulingProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,170][DEBUG][main] Creating shared instance of singleton bean 'simpleAsyncTaskSchedulerBuilder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,171][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskSchedulingConfigurations$TaskSchedulerConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,172][DEBUG][main] Creating shared instance of singleton bean 'taskScheduler' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,172][DEBUG][main] Autowiring by type from bean name 'taskScheduler' via factory method to bean named 'taskSchedulerBuilder' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,173][DEBUG][main] Initializing ExecutorService 'taskScheduler' (ExecutorConfigurationSupport.java:264) +[2026-06-02 18:55:04,178][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.task.TaskSchedulingAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,179][DEBUG][main] Creating shared instance of singleton bean 'scheduledBeanLazyInitializationExcludeFilter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,179][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.task.TaskExecutorMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,184][DEBUG][main] Creating shared instance of singleton bean 'eagerTaskExecutorMetrics' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,184][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.metrics.web.tomcat.TomcatMetricsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,184][DEBUG][main] Creating shared instance of singleton bean 'tomcatMetricsBinder' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,184][DEBUG][main] Autowiring by type from bean name 'tomcatMetricsBinder' via factory method to bean named 'simpleMeterRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,185][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$ObservedAspectConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,185][DEBUG][main] Creating shared instance of singleton bean 'observedAspect' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,186][DEBUG][main] Autowiring by type from bean name 'observedAspect' via factory method to bean named 'observationRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,186][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.ObservationAutoConfiguration$MeterObservationHandlerConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,186][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.http.JacksonHttpMessageConvertersConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,186][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.client.RestClientAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,187][DEBUG][main] Creating shared instance of singleton bean 'httpMessageConvertersRestClientCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,187][DEBUG][main] Creating shared instance of singleton bean 'restClientSsl' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,187][DEBUG][main] Autowiring by type from bean name 'restClientSsl' via factory method to bean named 'sslBundleRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,188][DEBUG][main] Creating shared instance of singleton bean 'restClientBuilderConfigurer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,188][DEBUG][main] Creating shared instance of singleton bean 'observationRestClientCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,188][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.web.client.RestClientObservationConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,188][DEBUG][main] Autowiring by type from bean name 'observationRestClientCustomizer' via factory method to bean named 'observationRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,188][DEBUG][main] Autowiring by type from bean name 'observationRestClientCustomizer' via factory method to bean named 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,190][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.client.RestTemplateAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,190][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.web.client.RestTemplateObservationConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,190][DEBUG][main] Creating shared instance of singleton bean 'observationRestTemplateCustomizer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,190][DEBUG][main] Autowiring by type from bean name 'observationRestTemplateCustomizer' via factory method to bean named 'observationRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,190][DEBUG][main] Autowiring by type from bean name 'observationRestTemplateCustomizer' via factory method to bean named 'management.observations-org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,191][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.observation.web.client.HttpClientObservationsAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,191][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.scheduling.ScheduledTasksObservabilityAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,191][DEBUG][main] Creating shared instance of singleton bean 'observabilitySchedulingConfigurer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,191][DEBUG][main] Autowiring by type from bean name 'observabilitySchedulingConfigurer' via factory method to bean named 'observationRegistry' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,192][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesEndpointAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,192][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,192][DEBUG][main] Creating shared instance of singleton bean 'springApplicationAdminRegistrar' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,192][DEBUG][main] Autowiring by type from bean name 'springApplicationAdminRegistrar' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,193][DEBUG][main] Application Admin MBean registered with name 'org.springframework.boot:type=Admin,name=SpringApplication' (SpringApplicationAdminMXBeanRegistrar.java:131) +[2026-06-02 18:55:04,195][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration$CglibAutoProxyConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,195][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.aop.AopAutoConfiguration$AspectJAutoProxyingConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,196][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.aop.AopAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,196][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,196][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,196][DEBUG][main] Creating shared instance of singleton bean 'lifecycleProcessor' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,197][DEBUG][main] Creating shared instance of singleton bean 'spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,197][DEBUG][main] Autowiring by type from bean name 'lifecycleProcessor' via factory method to bean named 'spring.lifecycle-org.springframework.boot.autoconfigure.context.LifecycleProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,199][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.dao.PersistenceExceptionTranslationAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,199][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,199][DEBUG][main] Creating shared instance of singleton bean 'redisIndexConfiguration#0' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,200][DEBUG][main] Creating shared instance of singleton bean 'redisKeyspaceConfiguration#0' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,200][DEBUG][main] Creating shared instance of singleton bean 'redisMappingConfiguration#0' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,200][DEBUG][main] Creating shared instance of singleton bean 'keyValueMappingContext' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,207][DEBUG][main] Creating shared instance of singleton bean 'redisCustomConversions' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,208][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,210][DEBUG][main] Creating shared instance of singleton bean 'redisReferenceResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,210][DEBUG][main] Creating shared instance of singleton bean 'redisConverter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,211][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.String to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.lang.String as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.Number to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.lang.Number as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.Enum to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.lang.Enum as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.Boolean to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.lang.Boolean as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.util.Date to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.util.Date as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.util.UUID to class [B as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.util.UUID as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.LocalDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.LocalDate to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.LocalTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.ZonedDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.ZonedDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.Instant to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.ZoneId to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.Period to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.Duration to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.OffsetDateTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.OffsetDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.OffsetTime to class [B as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class [B to class java.time.OffsetTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.LocalDate to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.util.Date to class java.time.LocalTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.LocalTime to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.util.Date to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.Instant to class java.util.Date as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.LocalDateTime to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.Instant to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.ZoneId to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.String to class java.time.ZoneId as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.Duration to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.String to class java.time.Duration as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.time.Period to class java.lang.String as writing converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.String to class java.time.Period as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDate as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.String to class java.time.LocalDateTime as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,212][DEBUG][main] Adding converter from class java.lang.String to class java.time.Instant as reading converter (CustomConversions.java:349) +[2026-06-02 18:55:04,216][DEBUG][main] Creating shared instance of singleton bean 'redisKeyValueAdapter' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,220][DEBUG][main] Starting RedisMessageListenerContainer... (RedisMessageListenerContainer.java:1007) +[2026-06-02 18:55:04,220][DEBUG][main] Postpone listening for Redis messages until actual listeners are added (RedisMessageListenerContainer.java:1007) +[2026-06-02 18:55:04,223][DEBUG][main] Creating shared instance of singleton bean 'redisKeyValueTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,227][DEBUG][main] Creating shared instance of singleton bean 'data-redis.repository-aot-processor#0' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,233][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.data.web.config.ProjectingArgumentResolverRegistrar' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,234][DEBUG][main] Creating shared instance of singleton bean 'offsetResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,236][DEBUG][main] Creating shared instance of singleton bean 'freeMarkerConfigurer' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,270][DEBUG][main] File system access not preferred: using SpringTemplateLoader (FreeMarkerConfigurationFactory.java:362) +[2026-06-02 18:55:04,271][DEBUG][main] SpringTemplateLoader for FreeMarker: using resource loader [org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244, started on Tue Jun 02 18:54:57 CST 2026] and template loader path [classpath:/templates/] (SpringTemplateLoader.java:62) +[2026-06-02 18:55:04,273][DEBUG][main] Creating shared instance of singleton bean 'freeMarkerConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,273][DEBUG][main] Autowiring by type from bean name 'freeMarkerConfiguration' via factory method to bean named 'freeMarkerConfigurer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,287][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,287][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration' via constructor to bean named 'org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,287][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.freemarker.FreeMarkerAutoConfiguration' via constructor to bean named 'spring.freemarker-org.springframework.boot.autoconfigure.freemarker.FreeMarkerProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,288][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.JdbcTemplateConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,289][DEBUG][main] Creating shared instance of singleton bean 'jdbcTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,289][DEBUG][main] Creating shared instance of singleton bean 'spring.jdbc-org.springframework.boot.autoconfigure.jdbc.JdbcProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,290][DEBUG][main] Autowiring by type from bean name 'jdbcTemplate' via factory method to bean named 'druidDataSource' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,290][DEBUG][main] Autowiring by type from bean name 'jdbcTemplate' via factory method to bean named 'spring.jdbc-org.springframework.boot.autoconfigure.jdbc.JdbcProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,300][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.NamedParameterJdbcTemplateConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,300][DEBUG][main] Creating shared instance of singleton bean 'namedParameterJdbcTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,301][DEBUG][main] Autowiring by type from bean name 'namedParameterJdbcTemplate' via factory method to bean named 'jdbcTemplate' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,306][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,306][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.JdbcClientAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,306][DEBUG][main] Creating shared instance of singleton bean 'jdbcClient' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,307][DEBUG][main] Autowiring by type from bean name 'jdbcClient' via factory method to bean named 'namedParameterJdbcTemplate' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,308][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,308][DEBUG][main] Creating shared instance of singleton bean 'spring.netty-org.springframework.boot.autoconfigure.netty.NettyProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,308][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.netty.NettyAutoConfiguration' via constructor to bean named 'spring.netty-org.springframework.boot.autoconfigure.netty.NettyProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,309][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,309][DEBUG][main] Creating shared instance of singleton bean 'spring.reactor-org.springframework.boot.autoconfigure.reactor.ReactorProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,309][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.autoconfigure.reactor.ReactorAutoConfiguration' via constructor to bean named 'spring.reactor-org.springframework.boot.autoconfigure.reactor.ReactorProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,310][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.sql.init.SqlInitializationAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,310][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration$JdbcTransactionManagerConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,310][DEBUG][main] Creating shared instance of singleton bean 'transactionManager' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,310][DEBUG][main] Autowiring by type from bean name 'transactionManager' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,310][DEBUG][main] Autowiring by type from bean name 'transactionManager' via factory method to bean named 'druidDataSource' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,318][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.jdbc.DataSourceTransactionManagerAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,318][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$TransactionTemplateConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,318][DEBUG][main] Creating shared instance of singleton bean 'transactionTemplate' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,319][DEBUG][main] Autowiring by type from bean name 'transactionTemplate' via factory method to bean named 'transactionManager' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,321][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,321][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.autoconfigure.web.embedded.EmbeddedWebServerFactoryCustomizerAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,322][DEBUG][main] Creating shared instance of singleton bean 'multipartResolver' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,322][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.endpoint.web.servlet.WebMvcEndpointManagementContextConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,323][DEBUG][main] Creating shared instance of singleton bean 'webEndpointServletHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,324][DEBUG][main] Creating shared instance of singleton bean 'management.endpoints.web.cors-org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,325][DEBUG][main] Autowiring by type from bean name 'webEndpointServletHandlerMapping' via factory method to bean named 'webEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,325][DEBUG][main] Autowiring by type from bean name 'webEndpointServletHandlerMapping' via factory method to bean named 'servletEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,325][DEBUG][main] Autowiring by type from bean name 'webEndpointServletHandlerMapping' via factory method to bean named 'controllerEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,325][DEBUG][main] Autowiring by type from bean name 'webEndpointServletHandlerMapping' via factory method to bean named 'endpointMediaTypes' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,325][DEBUG][main] Autowiring by type from bean name 'webEndpointServletHandlerMapping' via factory method to bean named 'management.endpoints.web.cors-org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,325][DEBUG][main] Autowiring by type from bean name 'webEndpointServletHandlerMapping' via factory method to bean named 'management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,325][DEBUG][main] Autowiring by type from bean name 'webEndpointServletHandlerMapping' via factory method to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,333][DEBUG][main] Creating shared instance of singleton bean 'controllerEndpointHandlerMapping' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,333][DEBUG][main] Autowiring by type from bean name 'controllerEndpointHandlerMapping' via factory method to bean named 'controllerEndpointDiscoverer' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,333][DEBUG][main] Autowiring by type from bean name 'controllerEndpointHandlerMapping' via factory method to bean named 'management.endpoints.web.cors-org.springframework.boot.actuate.autoconfigure.endpoint.web.CorsEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,333][DEBUG][main] Autowiring by type from bean name 'controllerEndpointHandlerMapping' via factory method to bean named 'management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,340][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration$SameManagementContextConfiguration$EnableSameManagementContextConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,341][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration$SameManagementContextConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,341][DEBUG][main] Autowiring by type from bean name 'org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration$SameManagementContextConfiguration' via constructor to bean named 'environment' (ConstructorResolver.java:945) +[2026-06-02 18:55:04,341][DEBUG][main] Creating shared instance of singleton bean 'org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,341][DEBUG][main] Creating shared instance of singleton bean 'management.server-org.springframework.boot.actuate.autoconfigure.web.server.ManagementServerProperties' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,342][DEBUG][main] Creating shared instance of singleton bean 'flowDefinitionMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,347][DEBUG][main] Creating shared instance of singleton bean 'flowFormMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,351][DEBUG][main] Creating shared instance of singleton bean 'flowNodeMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,356][DEBUG][main] Creating shared instance of singleton bean 'flowSkipMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,360][DEBUG][main] Creating shared instance of singleton bean 'flowUserMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,363][DEBUG][main] Creating shared instance of singleton bean 'warmMapper' (DefaultSingletonBeanRegistry.java:225) +[2026-06-02 18:55:04,392][DEBUG][main] Registering beans for JMX exposure on startup (MBeanExporter.java:450) +[2026-06-02 18:55:04,393][DEBUG][main] Auto-detecting user-defined JMX MBeans (MBeanExporter.java:557) +[2026-06-02 18:55:04,393][DEBUG][main] Bean with name 'druidDataSource' has been autodetected for JMX exposure (MBeanExporter.java:911) +[2026-06-02 18:55:04,397][DEBUG][main] Located MBean 'druidDataSource': registering with JMX server as MBean [com.alibaba.druid.pool:name=druidDataSource,type=DruidDataSource] (MBeanExporter.java:684) +[2026-06-02 18:55:04,398][DEBUG][main] Starting beans in phase -2147483647 (DefaultLifecycleProcessor.java:466) +[2026-06-02 18:55:04,398][DEBUG][main] Successfully started bean 'springBootLoggingLifecycle' (DefaultLifecycleProcessor.java:291) +[2026-06-02 18:55:04,398][DEBUG][main] Starting beans in phase 2147481599 (DefaultLifecycleProcessor.java:466) +[2026-06-02 18:55:04,399][DEBUG][main] Setting state for [Connector["http-nio-1024"]] to [STARTING_PREP] (DirectJDKLog.java:173) +[2026-06-02 18:55:04,399][DEBUG][main] Setting state for [Connector["http-nio-1024"]] to [STARTING] (DirectJDKLog.java:173) +[2026-06-02 18:55:04,402][DEBUG][main] Setting state for [Connector["http-nio-1024"]] to [STARTED] (DirectJDKLog.java:173) +[2026-06-02 18:55:04,408][DEBUG][main] Successfully started bean 'webServerStartStop' (DefaultLifecycleProcessor.java:291) +[2026-06-02 18:55:04,408][DEBUG][main] Starting beans in phase 2147482623 (DefaultLifecycleProcessor.java:466) +[2026-06-02 18:55:04,408][DEBUG][main] Successfully started bean 'webServerGracefulShutdown' (DefaultLifecycleProcessor.java:291) +[2026-06-02 18:55:04,408][DEBUG][main] Starting beans in phase 2147483647 (DefaultLifecycleProcessor.java:466) +[2026-06-02 18:55:04,417][DEBUG][main] + + +============================ +CONDITIONS EVALUATION REPORT +============================ + + +Positive matches: +----------------- + + AdminSmartJobController matched: + - @ConditionalOnBean (types: net.lab1024.sa.base.module.support.job.config.SmartJobAutoConfiguration; SearchStrategy: all) found bean 'smartJobAutoConfiguration' (OnBeanCondition) + + AopAutoConfiguration matched: + - @ConditionalOnProperty (spring.aop.auto=true) matched (OnPropertyCondition) + + AopAutoConfiguration.AspectJAutoProxyingConfiguration matched: + - @ConditionalOnClass found required class 'org.aspectj.weaver.Advice' (OnClassCondition) + + AopAutoConfiguration.AspectJAutoProxyingConfiguration.CglibAutoProxyConfiguration matched: + - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition) + + ApplicationAvailabilityAutoConfiguration#applicationAvailability matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.availability.ApplicationAvailability; SearchStrategy: all) did not find any beans (OnBeanCondition) + + AuditEventsEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + BeansEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + BeansEndpointAutoConfiguration#beansEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.beans.BeansEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + CacheAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.cache.CacheManager' (OnClassCondition) + - @ConditionalOnBean (types: org.springframework.cache.interceptor.CacheAspectSupport; SearchStrategy: all) found bean 'cacheInterceptor'; @ConditionalOnMissingBean (names: cacheResolver types: org.springframework.cache.CacheManager; SearchStrategy: all) did not find any beans (OnBeanCondition) + + CacheAutoConfiguration#cacheManagerCustomizers matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers; SearchStrategy: all) did not find any beans (OnBeanCondition) + + CacheConfig#caffeineCacheService matched: + - @ConditionalOnProperty (spring.cache.type=caffeine) matched (OnPropertyCondition) + + CacheMeterBinderProvidersConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.binder.MeterBinder' (OnClassCondition) + + CacheMeterBinderProvidersConfiguration.CaffeineCacheMeterBinderProviderConfiguration matched: + - @ConditionalOnClass found required classes 'org.springframework.cache.caffeine.CaffeineCache', 'com.github.benmanes.caffeine.cache.Cache' (OnClassCondition) + + CacheMeterBinderProvidersConfiguration.JCacheCacheMeterBinderProviderConfiguration matched: + - @ConditionalOnClass found required classes 'org.springframework.cache.jcache.JCacheCache', 'javax.cache.CacheManager' (OnClassCondition) + + CacheMeterBinderProvidersConfiguration.RedisCacheMeterBinderProviderConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.data.redis.cache.RedisCache' (OnClassCondition) + + CacheMetricsAutoConfiguration matched: + - @ConditionalOnBean (types: org.springframework.cache.CacheManager; SearchStrategy: all) found bean 'cacheManager' (OnBeanCondition) + + CacheMetricsRegistrarConfiguration matched: + - @ConditionalOnBean (types: org.springframework.boot.actuate.metrics.cache.CacheMeterBinderProvider,io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found beans 'caffeineCacheMeterBinderProvider', 'simpleMeterRegistry', 'redisCacheMeterBinderProvider', 'jCacheCacheMeterBinderProvider' (OnBeanCondition) + + CachesEndpointAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.cache.CacheManager' (OnClassCondition) + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + CachesEndpointAutoConfiguration#cachesEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.cache.CachesEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + CaffeineCacheConfiguration matched: + - @ConditionalOnClass found required classes 'com.github.benmanes.caffeine.cache.Caffeine', 'org.springframework.cache.caffeine.CaffeineCacheManager' (OnClassCondition) + - Cache org.springframework.boot.autoconfigure.cache.CaffeineCacheConfiguration CAFFEINE cache type (CacheCondition) + - @ConditionalOnMissingBean (types: org.springframework.cache.CacheManager; SearchStrategy: all) did not find any beans (OnBeanCondition) + + CompositeMeterRegistryAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.composite.CompositeMeterRegistry' (OnClassCondition) + + ConditionsReportEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + ConditionsReportEndpointAutoConfiguration#conditionsReportEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.autoconfigure.condition.ConditionsReportEndpoint; SearchStrategy: current) did not find any beans (OnBeanCondition) + + ConfigurationPropertiesReportEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + ConfigurationPropertiesReportEndpointAutoConfiguration#configurationPropertiesReportEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + DataSourceAutoConfiguration matched: + - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition) + - @ConditionalOnMissingBean (types: io.r2dbc.spi.ConnectionFactory; SearchStrategy: all) did not find any beans (OnBeanCondition) + + DataSourceConfiguration.Hikari matched: + - @ConditionalOnClass found required class 'com.zaxxer.hikari.HikariDataSource' (OnClassCondition) + - @ConditionalOnProperty (spring.datasource.type=com.zaxxer.hikari.HikariDataSource) matched (OnPropertyCondition) + + DataSourceHealthContributorAutoConfiguration matched: + - @ConditionalOnClass found required classes 'org.springframework.jdbc.core.JdbcTemplate', 'org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource' (OnClassCondition) + - @ConditionalOnEnabledHealthIndicator management.health.defaults.enabled is considered true (OnEnabledHealthIndicatorCondition) + - @ConditionalOnBean (types: javax.sql.DataSource; SearchStrategy: all) found bean 'druidDataSource' (OnBeanCondition) + + DataSourceHealthContributorAutoConfiguration#dbHealthContributor matched: + - @ConditionalOnMissingBean (names: dbHealthIndicator,dbHealthContributor; SearchStrategy: all) did not find any beans (OnBeanCondition) + + DataSourceInitializationConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.jdbc.datasource.init.DatabasePopulator' (OnClassCondition) + - @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) found a single bean 'druidDataSource'; @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.sql.init.SqlDataSourceScriptDatabaseInitializer,org.springframework.boot.autoconfigure.sql.init.SqlR2dbcScriptDatabaseInitializer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + DataSourceJmxConfiguration matched: + - @ConditionalOnProperty (spring.jmx.enabled=true) matched (OnPropertyCondition) + + DataSourceJmxConfiguration.Hikari matched: + - @ConditionalOnClass found required class 'com.zaxxer.hikari.HikariDataSource' (OnClassCondition) + + DataSourcePoolMetadataProvidersConfiguration.HikariPoolDataSourceMetadataProviderConfiguration matched: + - @ConditionalOnClass found required class 'com.zaxxer.hikari.HikariDataSource' (OnClassCondition) + + DataSourcePoolMetricsAutoConfiguration matched: + - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'io.micrometer.core.instrument.MeterRegistry' (OnClassCondition) + - @ConditionalOnBean (types: javax.sql.DataSource,io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found beans 'simpleMeterRegistry', 'druidDataSource' (OnBeanCondition) + + DataSourcePoolMetricsAutoConfiguration.DataSourcePoolMetadataMetricsConfiguration matched: + - @ConditionalOnBean (types: org.springframework.boot.jdbc.metadata.DataSourcePoolMetadataProvider; SearchStrategy: all) found bean 'hikariPoolDataSourceMetadataProvider' (OnBeanCondition) + + DataSourcePoolMetricsAutoConfiguration.HikariDataSourceMetricsConfiguration matched: + - @ConditionalOnClass found required class 'com.zaxxer.hikari.HikariDataSource' (OnClassCondition) + + DataSourceTransactionManagerAutoConfiguration matched: + - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.core.JdbcTemplate', 'org.springframework.transaction.TransactionManager' (OnClassCondition) + + DataSourceTransactionManagerAutoConfiguration.JdbcTransactionManagerConfiguration matched: + - @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) found a single bean 'druidDataSource' (OnBeanCondition) + + DataSourceTransactionManagerAutoConfiguration.JdbcTransactionManagerConfiguration#transactionManager matched: + - @ConditionalOnMissingBean (types: org.springframework.transaction.TransactionManager; SearchStrategy: all) did not find any beans (OnBeanCondition) + + DdlAutoConfiguration matched: + - @ConditionalOnClass found required class 'com.baomidou.mybatisplus.extension.ddl.IDdl' (OnClassCondition) + + DiskSpaceHealthContributorAutoConfiguration matched: + - @ConditionalOnEnabledHealthIndicator management.health.defaults.enabled is considered true (OnEnabledHealthIndicatorCondition) + + DiskSpaceHealthContributorAutoConfiguration#diskSpaceHealthIndicator matched: + - @ConditionalOnMissingBean (names: diskSpaceHealthIndicator; SearchStrategy: all) did not find any beans (OnBeanCondition) + + DispatcherServletAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + + DispatcherServletAutoConfiguration.DispatcherServletConfiguration matched: + - @ConditionalOnClass found required class 'jakarta.servlet.ServletRegistration' (OnClassCondition) + - Default DispatcherServlet did not find dispatcher servlet beans (DispatcherServletAutoConfiguration.DefaultDispatcherServletCondition) + + DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration matched: + - @ConditionalOnClass found required class 'jakarta.servlet.ServletRegistration' (OnClassCondition) + - DispatcherServlet Registration did not find servlet registration bean (DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition) + - DispatcherServlet Registration found servlet registration beans 'druidServlet' and none is named dispatcherServletRegistration (DispatcherServletAutoConfiguration.DispatcherServletRegistrationCondition) + + DispatcherServletAutoConfiguration.DispatcherServletRegistrationConfiguration#dispatcherServletRegistration matched: + - @ConditionalOnBean (names: dispatcherServlet types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found bean 'dispatcherServlet' (OnBeanCondition) + + DruidDataSourceAutoConfigure matched: + - @ConditionalOnClass found required class 'com.alibaba.druid.pool.DruidDataSource' (OnClassCondition) + - @ConditionalOnProperty (spring.datasource.type=com.alibaba.druid.pool.DruidDataSource) matched (OnPropertyCondition) + + EmbeddedWebServerFactoryCustomizerAutoConfiguration matched: + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnWarDeployment the application is not deployed as a WAR file. (OnWarDeploymentCondition) + + EmbeddedWebServerFactoryCustomizerAutoConfiguration.TomcatWebServerFactoryCustomizerConfiguration matched: + - @ConditionalOnClass found required classes 'org.apache.catalina.startup.Tomcat', 'org.apache.coyote.UpgradeProtocol' (OnClassCondition) + + EndpointAutoConfiguration#endpointCachingOperationInvokerAdvisor matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor; SearchStrategy: all) did not find any beans (OnBeanCondition) + + EndpointAutoConfiguration#endpointOperationParameterMapper matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.invoke.ParameterValueMapper; SearchStrategy: all) did not find any beans (OnBeanCondition) + + EnvironmentEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + EnvironmentEndpointAutoConfiguration#environmentEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.env.EnvironmentEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ErrorMvcAutoConfiguration matched: + - @ConditionalOnClass found required classes 'jakarta.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + + ErrorMvcAutoConfiguration#basicErrorController matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.web.servlet.error.ErrorController; SearchStrategy: current) did not find any beans (OnBeanCondition) + + ErrorMvcAutoConfiguration#errorAttributes matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.web.servlet.error.ErrorAttributes; SearchStrategy: current) did not find any beans (OnBeanCondition) + + ErrorMvcAutoConfiguration.DefaultErrorViewResolverConfiguration#conventionErrorViewResolver matched: + - @ConditionalOnBean (types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found bean 'dispatcherServlet'; @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.servlet.error.ErrorViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration matched: + - @ConditionalOnProperty (server.error.whitelabel.enabled) matched (OnPropertyCondition) + - ErrorTemplate Missing did not find error template view (ErrorMvcAutoConfiguration.ErrorTemplateMissingCondition) + + ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration#beanNameViewResolver matched: + - @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.BeanNameViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ErrorMvcAutoConfiguration.WhitelabelErrorViewConfiguration#defaultErrorView matched: + - @ConditionalOnMissingBean (names: error; SearchStrategy: all) did not find any beans (OnBeanCondition) + + FileConfig#initLocalFileService matched: + - @ConditionalOnProperty (file.storage.mode=local) matched (OnPropertyCondition) + + FlowAutoConfig matched: + - @ConditionalOnProperty (warm-flow.enabled=true) matched (OnPropertyCondition) + + FlowInstanceServiceImpl matched: + - @ConditionalOnProperty (warm-flow.enabled=true) matched (OnPropertyCondition) + + FlowProcessEventHandler matched: + - @ConditionalOnProperty (warm-flow.enabled=true) matched (OnPropertyCondition) + + FreeMarkerAutoConfiguration matched: + - @ConditionalOnClass found required classes 'freemarker.template.Configuration', 'org.springframework.ui.freemarker.FreeMarkerConfigurationFactory' (OnClassCondition) + + FreeMarkerServletWebConfiguration matched: + - @ConditionalOnClass found required classes 'jakarta.servlet.Servlet', 'org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + + FreeMarkerServletWebConfiguration#freeMarkerConfigurer matched: + - @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.freemarker.FreeMarkerConfig; SearchStrategy: all) did not find any beans (OnBeanCondition) + + FreeMarkerServletWebConfiguration#freeMarkerViewResolver matched: + - @ConditionalOnProperty (spring.freemarker.enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (names: freeMarkerViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HealthContributorAutoConfiguration#pingHealthContributor matched: + - @ConditionalOnEnabledHealthIndicator management.health.defaults.enabled is considered true (OnEnabledHealthIndicatorCondition) + + HealthEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + HealthEndpointConfiguration#healthContributorRegistry matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.health.HealthContributorRegistry; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HealthEndpointConfiguration#healthEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.health.HealthEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HealthEndpointConfiguration#healthEndpointGroupMembershipValidator matched: + - @ConditionalOnProperty (management.endpoint.health.validate-group-membership=true) matched (OnPropertyCondition) + + HealthEndpointConfiguration#healthEndpointGroups matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.health.HealthEndpointGroups; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HealthEndpointConfiguration#healthHttpCodeStatusMapper matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.health.HttpCodeStatusMapper; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HealthEndpointConfiguration#healthStatusAggregator matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.health.StatusAggregator; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HealthEndpointWebExtensionConfiguration matched: + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.web.exposure' property (OnAvailableEndpointCondition) + - @ConditionalOnBean (types: org.springframework.boot.actuate.health.HealthEndpoint; SearchStrategy: all) found bean 'healthEndpoint' (OnBeanCondition) + + HealthEndpointWebExtensionConfiguration#healthEndpointWebExtension matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.health.HealthEndpointWebExtension; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HealthEndpointWebExtensionConfiguration.MvcAdditionalHealthEndpointPathsConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.web.exposure' property (OnAvailableEndpointCondition) + - @ConditionalOnBean (types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found bean 'dispatcherServlet' (OnBeanCondition) + + HeapDumpWebEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + HeapDumpWebEndpointAutoConfiguration#heapDumpWebEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.management.HeapDumpWebEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HttpClientObservationsAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.observation.Observation' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.observation.ObservationRegistry; SearchStrategy: all) found bean 'observationRegistry' (OnBeanCondition) + + HttpClientObservationsAutoConfiguration.MeterFilterConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.MeterRegistry' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + HttpEncodingAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.filter.CharacterEncodingFilter' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (server.servlet.encoding.enabled) matched (OnPropertyCondition) + + HttpEncodingAutoConfiguration#characterEncodingFilter matched: + - @ConditionalOnMissingBean (types: org.springframework.web.filter.CharacterEncodingFilter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HttpExchangesEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + HttpMessageConvertersAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.http.converter.HttpMessageConverter' (OnClassCondition) + - NoneNestedConditions 0 matched 1 did not; NestedCondition on HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition.ReactiveWebApplication did not find reactive web application classes (HttpMessageConvertersAutoConfiguration.NotReactiveWebApplicationCondition) + + HttpMessageConvertersAutoConfiguration#messageConverters matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.http.HttpMessageConverters; SearchStrategy: all) did not find any beans (OnBeanCondition) + + HttpMessageConvertersAutoConfiguration.StringHttpMessageConverterConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.http.converter.StringHttpMessageConverter' (OnClassCondition) + + HttpMessageConvertersAutoConfiguration.StringHttpMessageConverterConfiguration#stringHttpMessageConverter matched: + - @ConditionalOnMissingBean (types: org.springframework.http.converter.StringHttpMessageConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + InfoEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + InfoEndpointAutoConfiguration#infoEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.info.InfoEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JacksonAutoConfiguration matched: + - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper' (OnClassCondition) + + JacksonAutoConfiguration.Jackson2ObjectMapperBuilderCustomizerConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.http.converter.json.Jackson2ObjectMapperBuilder' (OnClassCondition) + + JacksonAutoConfiguration.JacksonObjectMapperBuilderConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.http.converter.json.Jackson2ObjectMapperBuilder' (OnClassCondition) + + JacksonAutoConfiguration.JacksonObjectMapperBuilderConfiguration#jacksonObjectMapperBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JacksonAutoConfiguration.JacksonObjectMapperConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.http.converter.json.Jackson2ObjectMapperBuilder' (OnClassCondition) + + JacksonAutoConfiguration.JacksonObjectMapperConfiguration#jacksonObjectMapper matched: + - @ConditionalOnMissingBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JacksonAutoConfiguration.ParameterNamesModuleConfiguration matched: + - @ConditionalOnClass found required class 'com.fasterxml.jackson.module.paramnames.ParameterNamesModule' (OnClassCondition) + + JacksonAutoConfiguration.ParameterNamesModuleConfiguration#parameterNamesModule matched: + - @ConditionalOnMissingBean (types: com.fasterxml.jackson.module.paramnames.ParameterNamesModule; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JacksonEndpointAutoConfiguration#endpointObjectMapper matched: + - @ConditionalOnClass found required classes 'com.fasterxml.jackson.databind.ObjectMapper', 'org.springframework.http.converter.json.Jackson2ObjectMapperBuilder' (OnClassCondition) + - @ConditionalOnProperty (management.endpoints.jackson.isolated-object-mapper) matched (OnPropertyCondition) + + JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration matched: + - @ConditionalOnClass found required class 'com.fasterxml.jackson.databind.ObjectMapper' (OnClassCondition) + - @ConditionalOnProperty (spring.mvc.converters.preferred-json-mapper=jackson) matched (OnPropertyCondition) + - @ConditionalOnBean (types: com.fasterxml.jackson.databind.ObjectMapper; SearchStrategy: all) found bean 'jacksonObjectMapper' (OnBeanCondition) + + JacksonHttpMessageConvertersConfiguration.MappingJackson2HttpMessageConverterConfiguration#mappingJackson2HttpMessageConverter matched: + - @ConditionalOnMissingBean (types: org.springframework.http.converter.json.MappingJackson2HttpMessageConverter ignored: org.springframework.hateoas.server.mvc.TypeConstrainedMappingJackson2HttpMessageConverter,org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JdbcClientAutoConfiguration matched: + - @ConditionalOnSingleCandidate (types: org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate; SearchStrategy: all) found a single bean 'namedParameterJdbcTemplate'; @ConditionalOnMissingBean (types: org.springframework.jdbc.core.simple.JdbcClient; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JdbcTemplateAutoConfiguration matched: + - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.core.JdbcTemplate' (OnClassCondition) + - @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) found a single bean 'druidDataSource' (OnBeanCondition) + + JdbcTemplateConfiguration matched: + - @ConditionalOnMissingBean (types: org.springframework.jdbc.core.JdbcOperations; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JmxAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.jmx.export.MBeanExporter' (OnClassCondition) + - @ConditionalOnProperty (spring.jmx.enabled=true) matched (OnPropertyCondition) + + JmxAutoConfiguration#mbeanExporter matched: + - @ConditionalOnMissingBean (types: org.springframework.jmx.export.MBeanExporter; SearchStrategy: current) did not find any beans (OnBeanCondition) + + JmxAutoConfiguration#mbeanServer matched: + - @ConditionalOnMissingBean (types: javax.management.MBeanServer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JmxAutoConfiguration#objectNamingStrategy matched: + - @ConditionalOnMissingBean (types: org.springframework.jmx.export.naming.ObjectNamingStrategy; SearchStrategy: current) did not find any beans (OnBeanCondition) + + JmxEndpointAutoConfiguration matched: + - @ConditionalOnProperty (spring.jmx.enabled=true) matched (OnPropertyCondition) + + JmxEndpointAutoConfiguration#endpointObjectNameFactory matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.jmx.EndpointObjectNameFactory; SearchStrategy: current) did not find any beans (OnBeanCondition) + + JmxEndpointAutoConfiguration#jmxAnnotationEndpointDiscoverer matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.jmx.JmxEndpointsSupplier; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JmxEndpointAutoConfiguration#jmxMBeanExporter matched: + - @ConditionalOnSingleCandidate (types: javax.management.MBeanServer; SearchStrategy: all) found a single bean 'mbeanServer' (OnBeanCondition) + + JvmMetricsAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.MeterRegistry' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + JvmMetricsAutoConfiguration#classLoaderMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JvmMetricsAutoConfiguration#jvmCompilationMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.jvm.JvmCompilationMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JvmMetricsAutoConfiguration#jvmGcMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JvmMetricsAutoConfiguration#jvmHeapPressureMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.jvm.JvmHeapPressureMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JvmMetricsAutoConfiguration#jvmInfoMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.jvm.JvmInfoMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JvmMetricsAutoConfiguration#jvmMemoryMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + JvmMetricsAutoConfiguration#jvmThreadMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + Knife4jAutoConfiguration matched: + - @ConditionalOnProperty (knife4j.enable=true) matched (OnPropertyCondition) + + Knife4jAutoConfiguration#knife4jJakartaOperationCustomizer matched: + - @ConditionalOnMissingBean (types: com.github.xiaoymin.knife4j.spring.extension.Knife4jJakartaOperationCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + Knife4jAutoConfiguration#knife4jOpenApiCustomizer matched: + - @ConditionalOnMissingBean (types: com.github.xiaoymin.knife4j.spring.extension.Knife4jOpenApiCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + LettuceConnectionConfiguration matched: + - @ConditionalOnClass found required class 'io.lettuce.core.RedisClient' (OnClassCondition) + - @ConditionalOnProperty (spring.data.redis.client-type=lettuce) matched (OnPropertyCondition) + + LettuceConnectionConfiguration#lettuceClientResources matched: + - @ConditionalOnMissingBean (types: io.lettuce.core.resource.ClientResources; SearchStrategy: all) did not find any beans (OnBeanCondition) + + LettuceMetricsAutoConfiguration matched: + - @ConditionalOnClass found required classes 'io.lettuce.core.RedisClient', 'io.lettuce.core.metrics.MicrometerCommandLatencyRecorder' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + LettuceMetricsAutoConfiguration#micrometerOptions matched: + - @ConditionalOnMissingBean (types: io.lettuce.core.metrics.MicrometerOptions; SearchStrategy: all) did not find any beans (OnBeanCondition) + + LifecycleAutoConfiguration#defaultLifecycleProcessor matched: + - @ConditionalOnMissingBean (names: lifecycleProcessor; SearchStrategy: current) did not find any beans (OnBeanCondition) + + Log4J2MetricsAutoConfiguration matched: + - @ConditionalOnClass found required classes 'io.micrometer.core.instrument.binder.logging.Log4j2Metrics', 'org.apache.logging.log4j.LogManager', 'org.apache.logging.log4j.core.LoggerContext' (OnClassCondition) + - LoggerContext was an instance of org.apache.logging.log4j.core.LoggerContext (Log4J2MetricsAutoConfiguration.Log4JCoreLoggerContextCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + Log4J2MetricsAutoConfiguration#log4j2Metrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.logging.Log4j2Metrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + LogFileWebEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + LoggersEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + LoggersEndpointAutoConfiguration#loggersEndpoint matched: + - Logging System enabled (LoggersEndpointAutoConfiguration.OnEnabledLoggingSystemCondition) + - @ConditionalOnBean (types: org.springframework.boot.logging.LoggingSystem; SearchStrategy: all) found bean 'springBootLoggingSystem'; @ConditionalOnMissingBean (types: org.springframework.boot.actuate.logging.LoggersEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MailSenderAutoConfiguration matched: + - @ConditionalOnClass found required classes 'jakarta.mail.internet.MimeMessage', 'jakarta.activation.MimeType', 'org.springframework.mail.MailSender' (OnClassCondition) + - AnyNestedCondition 1 matched 1 did not; NestedCondition on MailSenderAutoConfiguration.MailSenderCondition.JndiNameProperty @ConditionalOnProperty (spring.mail.jndi-name) did not find property 'jndi-name'; NestedCondition on MailSenderAutoConfiguration.MailSenderCondition.HostProperty @ConditionalOnProperty (spring.mail.host) matched (MailSenderAutoConfiguration.MailSenderCondition) + - @ConditionalOnMissingBean (types: org.springframework.mail.MailSender; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MailSenderPropertiesConfiguration matched: + - @ConditionalOnProperty (spring.mail.host) matched (OnPropertyCondition) + + MailSenderPropertiesConfiguration#mailSender matched: + - @ConditionalOnMissingBean (types: org.springframework.mail.javamail.JavaMailSender; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ManagementContextAutoConfiguration.SameManagementContextConfiguration matched: + - Management Port actual port type (SAME) matched required type (OnManagementPortCondition) + + MappingsEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + MappingsEndpointAutoConfiguration.ServletWebConfiguration matched: + - found 'session' scope (OnWebApplicationCondition) + + MappingsEndpointAutoConfiguration.ServletWebConfiguration.SpringMvcConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition) + - @ConditionalOnBean (types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found bean 'dispatcherServlet' (OnBeanCondition) + + MetricsAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.annotation.Timed' (OnClassCondition) + + MetricsAutoConfiguration#micrometerClock matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.Clock; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MetricsEndpointAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.annotation.Timed' (OnClassCondition) + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + MetricsEndpointAutoConfiguration#metricsEndpoint matched: + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry'; @ConditionalOnMissingBean (types: org.springframework.boot.actuate.metrics.MetricsEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MultipartAutoConfiguration matched: + - @ConditionalOnClass found required classes 'jakarta.servlet.Servlet', 'org.springframework.web.multipart.support.StandardServletMultipartResolver', 'jakarta.servlet.MultipartConfigElement' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (spring.servlet.multipart.enabled) matched (OnPropertyCondition) + + MultipartAutoConfiguration#multipartConfigElement matched: + - @ConditionalOnMissingBean (types: jakarta.servlet.MultipartConfigElement; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MultipartAutoConfiguration#multipartResolver matched: + - @ConditionalOnMissingBean (types: org.springframework.web.multipart.MultipartResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MultipleOpenApiSupportConfiguration matched: + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (springdoc.api-docs.enabled) matched (OnPropertyCondition) + - AnyNestedCondition 1 matched 1 did not; NestedCondition on MultipleOpenApiSupportCondition.OnActuatorDifferentPort found non-matching nested conditions Management Port actual port type (SAME) did not match required type (DIFFERENT), @ConditionalOnProperty (springdoc.show-actuator) did not find property 'springdoc.show-actuator'; NestedCondition on MultipleOpenApiSupportCondition.OnMultipleOpenApiSupportCondition AnyNestedCondition 1 matched 1 did not; NestedCondition on MultipleOpenApiGroupsCondition.OnGroupConfigProperty @ConditionalOnProperty (springdoc.group-configs[0].group) did not find property 'springdoc.group-configs[0].group'; NestedCondition on MultipleOpenApiGroupsCondition.OnGroupedOpenApiBean @ConditionalOnBean (types: org.springdoc.core.models.GroupedOpenApi; SearchStrategy: all) found beans 'supportApi', 'businessApi' (MultipleOpenApiSupportCondition) + + MultipleOpenApiSupportConfiguration#multipleOpenApiResource matched: + - @ConditionalOnProperty (springdoc.use-management-port=false) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.api.MultipleOpenApiWebMvcResource; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MybatisPlusAutoConfiguration matched: + - @ConditionalOnClass found required classes 'org.apache.ibatis.session.SqlSessionFactory', 'org.mybatis.spring.SqlSessionFactoryBean' (OnClassCondition) + - @ConditionalOnSingleCandidate (types: javax.sql.DataSource; SearchStrategy: all) found a single bean 'druidDataSource' (OnBeanCondition) + + MybatisPlusAutoConfiguration#sqlSessionTemplate matched: + - @ConditionalOnMissingBean (types: org.mybatis.spring.SqlSessionTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition) + + MybatisPlusLanguageDriverAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.apache.ibatis.scripting.LanguageDriver' (OnClassCondition) + + NamedParameterJdbcTemplateConfiguration matched: + - @ConditionalOnSingleCandidate (types: org.springframework.jdbc.core.JdbcTemplate; SearchStrategy: all) found a single bean 'jdbcTemplate'; @ConditionalOnMissingBean (types: org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; SearchStrategy: all) did not find any beans (OnBeanCondition) + + NettyAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.netty.util.NettyRuntime' (OnClassCondition) + + ObservationAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.observation.ObservationRegistry' (OnClassCondition) + + ObservationAutoConfiguration#observationRegistry matched: + - @ConditionalOnMissingBean (types: io.micrometer.observation.ObservationRegistry; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ObservationAutoConfiguration.MeterObservationHandlerConfiguration matched: + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry'; @ConditionalOnMissingBean (types: io.micrometer.core.instrument.observation.MeterObservationHandler; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ObservationAutoConfiguration.MeterObservationHandlerConfiguration.OnlyMetricsMeterObservationHandlerConfiguration matched: + - @ConditionalOnMissingBean (types: io.micrometer.tracing.Tracer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ObservationAutoConfiguration.ObservedAspectConfiguration matched: + - @ConditionalOnClass found required class 'org.aspectj.weaver.Advice' (OnClassCondition) + + ObservationAutoConfiguration.ObservedAspectConfiguration#observedAspect matched: + - @ConditionalOnMissingBean (types: io.micrometer.observation.aop.ObservedAspect; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ObservationAutoConfiguration.OnlyMetricsConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.MeterRegistry'; @ConditionalOnMissingClass did not find unwanted class 'io.micrometer.tracing.Tracer' (OnClassCondition) + + PersistenceExceptionTranslationAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor' (OnClassCondition) + + PersistenceExceptionTranslationAutoConfiguration#persistenceExceptionTranslationPostProcessor matched: + - @ConditionalOnProperty (spring.dao.exceptiontranslation.enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; SearchStrategy: all) did not find any beans (OnBeanCondition) + + PropertyPlaceholderAutoConfiguration#propertySourcesPlaceholderConfigurer matched: + - @ConditionalOnMissingBean (types: org.springframework.context.support.PropertySourcesPlaceholderConfigurer; SearchStrategy: current) did not find any beans (OnBeanCondition) + + ReactiveHealthEndpointConfiguration matched: + - @ConditionalOnClass found required class 'reactor.core.publisher.Flux' (OnClassCondition) + - @ConditionalOnBean (types: org.springframework.boot.actuate.health.HealthEndpoint; SearchStrategy: all) found bean 'healthEndpoint' (OnBeanCondition) + + ReactiveHealthEndpointConfiguration#reactiveHealthContributorRegistry matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.health.ReactiveHealthContributorRegistry; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ReactorAutoConfiguration matched: + - @ConditionalOnClass found required class 'reactor.core.publisher.Hooks' (OnClassCondition) + + RedisAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.data.redis.core.RedisOperations' (OnClassCondition) + + RedisAutoConfiguration#redisConnectionDetails matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.data.redis.RedisConnectionDetails; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedisHealthContributorAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.data.redis.connection.RedisConnectionFactory' (OnClassCondition) + - @ConditionalOnEnabledHealthIndicator management.health.defaults.enabled is considered true (OnEnabledHealthIndicatorCondition) + - @ConditionalOnBean (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) found bean 'redissonConnectionFactory' (OnBeanCondition) + + RedisReactiveAutoConfiguration matched: + - @ConditionalOnClass found required classes 'org.springframework.data.redis.connection.ReactiveRedisConnectionFactory', 'org.springframework.data.redis.core.ReactiveRedisTemplate', 'reactor.core.publisher.Flux' (OnClassCondition) + + RedisReactiveAutoConfiguration#reactiveRedisTemplate matched: + - @ConditionalOnBean (types: org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; SearchStrategy: all) found bean 'redissonConnectionFactory'; @ConditionalOnMissingBean (names: reactiveRedisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedisReactiveAutoConfiguration#reactiveStringRedisTemplate matched: + - @ConditionalOnBean (types: org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; SearchStrategy: all) found bean 'redissonConnectionFactory'; @ConditionalOnMissingBean (names: reactiveStringRedisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedisReactiveHealthContributorAutoConfiguration matched: + - @ConditionalOnClass found required classes 'org.springframework.data.redis.connection.ReactiveRedisConnectionFactory', 'reactor.core.publisher.Flux' (OnClassCondition) + - @ConditionalOnEnabledHealthIndicator management.health.defaults.enabled is considered true (OnEnabledHealthIndicatorCondition) + - @ConditionalOnBean (types: org.springframework.data.redis.connection.ReactiveRedisConnectionFactory; SearchStrategy: all) found bean 'redissonConnectionFactory' (OnBeanCondition) + + RedisReactiveHealthContributorAutoConfiguration#redisHealthContributor matched: + - @ConditionalOnMissingBean (names: redisHealthIndicator,redisHealthContributor; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedisRepositoriesAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.data.redis.repository.configuration.EnableRedisRepositories' (OnClassCondition) + - @ConditionalOnProperty (spring.data.redis.repositories.enabled=true) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) found bean 'redissonConnectionFactory'; @ConditionalOnMissingBean (types: org.springframework.data.redis.repository.support.RedisRepositoryFactoryBean; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedissonAutoConfiguration#redisson matched: + - @ConditionalOnMissingBean (types: org.redisson.api.RedissonClient; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedissonAutoConfiguration#redissonConnectionFactory matched: + - @ConditionalOnMissingBean (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedissonAutoConfiguration#redissonReactive matched: + - @ConditionalOnMissingBean (types: org.redisson.api.RedissonReactiveClient; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedissonAutoConfiguration#redissonRxJava matched: + - @ConditionalOnMissingBean (types: org.redisson.api.RedissonRxClient; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedissonAutoConfiguration#stringRedisTemplate matched: + - @ConditionalOnMissingBean (types: org.springframework.data.redis.core.StringRedisTemplate; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RedissonAutoConfigurationV2 matched: + - @ConditionalOnClass found required classes 'org.redisson.Redisson', 'org.springframework.data.redis.core.RedisOperations' (OnClassCondition) + + RepositoryMetricsAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.data.repository.Repository' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + RepositoryMetricsAutoConfiguration#metricsRepositoryMethodInvocationListener matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.metrics.data.MetricsRepositoryMethodInvocationListener; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RepositoryMetricsAutoConfiguration#repositoryTagsProvider matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.metrics.data.RepositoryTagsProvider; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RestClientAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.client.RestClient' (OnClassCondition) + - NoneNestedConditions 0 matched 1 did not; NestedCondition on NotReactiveWebApplicationCondition.ReactiveWebApplication did not find reactive web application classes (NotReactiveWebApplicationCondition) + + RestClientAutoConfiguration#httpMessageConvertersRestClientCustomizer matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.client.HttpMessageConvertersRestClientCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RestClientAutoConfiguration#restClientBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.web.client.RestClient$Builder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RestClientAutoConfiguration#restClientBuilderConfigurer matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.client.RestClientBuilderConfigurer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RestClientAutoConfiguration#restClientSsl matched: + - @ConditionalOnBean (types: org.springframework.boot.ssl.SslBundles; SearchStrategy: all) found bean 'sslBundleRegistry'; @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.web.client.RestClientSsl; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RestClientObservationConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.client.RestClient' (OnClassCondition) + - @ConditionalOnBean (types: org.springframework.web.client.RestClient$Builder; SearchStrategy: all) found bean 'restClientBuilder' (OnBeanCondition) + + RestTemplateAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.client.RestTemplate' (OnClassCondition) + - NoneNestedConditions 0 matched 1 did not; NestedCondition on NotReactiveWebApplicationCondition.ReactiveWebApplication did not find reactive web application classes (NotReactiveWebApplicationCondition) + + RestTemplateAutoConfiguration#restTemplateBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.web.client.RestTemplateBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + RestTemplateObservationConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.client.RestTemplate' (OnClassCondition) + - @ConditionalOnBean (types: org.springframework.boot.web.client.RestTemplateBuilder; SearchStrategy: all) found bean 'restTemplateBuilder' (OnBeanCondition) + + SbomEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + SbomEndpointAutoConfiguration#sbomEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.sbom.SbomEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ScheduledTasksEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + ScheduledTasksEndpointAutoConfiguration#scheduledTasksEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.scheduling.ScheduledTasksEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ScheduledTasksObservabilityAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.observation.ObservationRegistry; SearchStrategy: all) found bean 'observationRegistry' (OnBeanCondition) + + ServletEndpointManagementContextConfiguration matched: + - found 'session' scope (OnWebApplicationCondition) + + ServletEndpointManagementContextConfiguration.WebMvcServletEndpointManagementContextConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition) + + ServletManagementContextAutoConfiguration matched: + - @ConditionalOnClass found required class 'jakarta.servlet.Servlet' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + + ServletWebServerFactoryAutoConfiguration matched: + - @ConditionalOnClass found required class 'jakarta.servlet.ServletRequest' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + + ServletWebServerFactoryAutoConfiguration#tomcatServletWebServerFactoryCustomizer matched: + - @ConditionalOnClass found required class 'org.apache.catalina.startup.Tomcat' (OnClassCondition) + + ServletWebServerFactoryConfiguration.EmbeddedTomcat matched: + - @ConditionalOnClass found required classes 'jakarta.servlet.Servlet', 'org.apache.catalina.startup.Tomcat', 'org.apache.coyote.UpgradeProtocol' (OnClassCondition) + - @ConditionalOnMissingBean (types: org.springframework.boot.web.servlet.server.ServletWebServerFactory; SearchStrategy: current) did not find any beans (OnBeanCondition) + + SimpleMetricsExportAutoConfiguration matched: + - @ConditionalOnEnabledMetricsExport management.defaults.metrics.export.enabled is considered true (OnMetricsExportEnabledCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.Clock; SearchStrategy: all) found bean 'micrometerClock'; @ConditionalOnMissingBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SimpleMetricsExportAutoConfiguration#simpleConfig matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.simple.SimpleConfig; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SmartJobAutoConfiguration matched: + - @ConditionalOnProperty (smart.job.enabled=true) matched (OnPropertyCondition) + + SmartJobClientManager matched: + - @ConditionalOnBean (types: net.lab1024.sa.base.module.support.job.config.SmartJobAutoConfiguration; SearchStrategy: all) found bean 'smartJobAutoConfiguration' (OnBeanCondition) + + SmartJobService matched: + - @ConditionalOnBean (types: net.lab1024.sa.base.module.support.job.config.SmartJobAutoConfiguration; SearchStrategy: all) found bean 'smartJobAutoConfiguration' (OnBeanCondition) + + SpringApplicationAdminJmxAutoConfiguration matched: + - @ConditionalOnProperty (spring.application.admin.enabled=true) matched (OnPropertyCondition) + + SpringApplicationAdminJmxAutoConfiguration#springApplicationAdminRegistrar matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.admin.SpringApplicationAdminMXBeanRegistrar; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDataWebAutoConfiguration matched: + - @ConditionalOnClass found required classes 'org.springframework.data.web.PageableHandlerMethodArgumentResolver', 'org.springframework.web.servlet.config.annotation.WebMvcConfigurer' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnMissingBean (types: org.springframework.data.web.PageableHandlerMethodArgumentResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDataWebAutoConfiguration#pageableCustomizer matched: + - @ConditionalOnMissingBean (types: org.springframework.data.web.config.PageableHandlerMethodArgumentResolverCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDataWebAutoConfiguration#sortCustomizer matched: + - @ConditionalOnMissingBean (types: org.springframework.data.web.config.SortHandlerMethodArgumentResolverCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfigProperties matched: + - @ConditionalOnProperty (springdoc.api-docs.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SpringDocConfiguration matched: + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (springdoc.api-docs.enabled) matched (OnPropertyCondition) + + SpringDocConfiguration#fileSupportConverter matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.converters.FileSupportConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#operationBuilder matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.service.OperationService; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#parameterBuilder matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.service.GenericParameterService; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#polymorphicModelConverter matched: + - @ConditionalOnProperty (springdoc.model-converters.polymorphic-converter.enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.core.converters.PolymorphicModelConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#propertyCustomizingConverter matched: + - @ConditionalOnBean (types: org.springdoc.core.customizers.PropertyCustomizer; SearchStrategy: all) found bean 'schemaEnumPropertyCustomizer' (OnBeanCondition) + + SpringDocConfiguration#requestBodyBuilder matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.service.RequestBodyService; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#responseSupportConverter matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.converters.ResponseSupportConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#schemaPropertyDeprecatingConverter matched: + - @ConditionalOnProperty (springdoc.model-converters.deprecating-converter.enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.core.converters.SchemaPropertyDeprecatingConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#securityParser matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.service.SecurityService; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#springDocCustomizers matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.customizers.SpringDocCustomizers; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#springDocProviders matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.providers.SpringDocProviders; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration#springdocBeanFactoryPostProcessor matched: + - @ConditionalOnClass found required class 'org.springframework.boot.context.properties.bind.BindResult' (OnClassCondition) + - AnyNestedCondition 1 matched 1 did not; NestedCondition on CacheOrGroupedOpenApiCondition.OnCacheDisabled found non-matching nested conditions @ConditionalOnProperty (springdoc.cache.disabled) did not find property 'springdoc.cache.disabled', @ConditionalOnMissingBean (types: org.springdoc.core.models.GroupedOpenApi; SearchStrategy: all) found beans of type 'org.springdoc.core.models.GroupedOpenApi' businessApi, supportApi; NestedCondition on CacheOrGroupedOpenApiCondition.OnMultipleOpenApiSupportCondition AnyNestedCondition 1 matched 1 did not; NestedCondition on MultipleOpenApiSupportCondition.OnActuatorDifferentPort found non-matching nested conditions Management Port actual port type (SAME) did not match required type (DIFFERENT), @ConditionalOnProperty (springdoc.show-actuator) did not find property 'springdoc.show-actuator'; NestedCondition on MultipleOpenApiSupportCondition.OnMultipleOpenApiSupportCondition AnyNestedCondition 1 matched 1 did not; NestedCondition on MultipleOpenApiGroupsCondition.OnGroupConfigProperty @ConditionalOnProperty (springdoc.group-configs[0].group) did not find property 'springdoc.group-configs[0].group'; NestedCondition on MultipleOpenApiGroupsCondition.OnGroupedOpenApiBean @ConditionalOnBean (types: org.springdoc.core.models.GroupedOpenApi; SearchStrategy: all) found beans 'supportApi', 'businessApi' (CacheOrGroupedOpenApiCondition) + + SpringDocConfiguration#springdocObjectMapperProvider matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.providers.ObjectMapperProvider; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration.QuerydslProvider matched: + - @ConditionalOnClass found required class 'org.springframework.data.querydsl.binding.QuerydslBindingsFactory' (OnClassCondition) + + SpringDocConfiguration.QuerydslProvider#queryDslQuerydslPredicateOperationCustomizer matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.customizers.QuerydslPredicateOperationCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration.SpringDocSpringDataWebPropertiesProvider matched: + - @ConditionalOnClass found required class 'org.springframework.boot.autoconfigure.data.web.SpringDataWebProperties' (OnClassCondition) + + SpringDocConfiguration.SpringDocSpringDataWebPropertiesProvider#springDataWebPropertiesProvider matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.providers.SpringDataWebPropertiesProvider; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration.SpringDocWebFluxSupportConfiguration matched: + - @ConditionalOnClass found required class 'reactor.core.publisher.Flux' (OnClassCondition) + + SpringDocConfiguration.SpringDocWebFluxSupportConfiguration#webFluxSupportConverter matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.converters.WebFluxSupportConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocConfiguration.WebConversionServiceConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.boot.autoconfigure.web.format.WebConversionService' (OnClassCondition) + + SpringDocKotlinConfiguration matched: + - @ConditionalOnClass found required class 'kotlin.coroutines.Continuation' (OnClassCondition) + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (springdoc.api-docs.enabled) matched (OnPropertyCondition) + - @ConditionalOnExpression (#{${springdoc.api-docs.enabled:true} and ${springdoc.enable-kotlin:true}}) resulted in true (OnExpressionCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SpringDocKotlinConfiguration#kotlinCoroutinesReturnTypeParser matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.parsers.KotlinCoroutinesReturnTypeParser; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocKotlinConfiguration#nullableKotlinRequestParameterCustomizer matched: + - @ConditionalOnProperty (springdoc.nullable-request-parameter-enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.core.customizers.ParameterCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocPageableConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.data.domain.Pageable' (OnClassCondition) + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (springdoc.api-docs.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SpringDocPageableConfiguration#delegatingMethodParameterCustomizer matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.customizers.DelegatingMethodParameterCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocPageableConfiguration#pageableOpenAPIConverter matched: + - @ConditionalOnProperty (springdoc.model-converters.pageable-converter.enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.core.converters.PageableOpenAPIConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocSortConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.data.domain.Sort' (OnClassCondition) + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (springdoc.api-docs.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SpringDocSortConfiguration#sortOpenAPIConverter matched: + - @ConditionalOnProperty (springdoc.model-converters.sort-converter.enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.core.converters.SortOpenAPIConverter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocUIConfiguration matched: + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SpringDocWebMvcConfiguration matched: + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (springdoc.api-docs.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SpringDocWebMvcConfiguration#openApiResource matched: + - @ConditionalOnProperty (springdoc.use-management-port=false) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.api.OpenApiWebMvcResource; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocWebMvcConfiguration#requestBuilder matched: + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.core.service.RequestService; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocWebMvcConfiguration#responseBuilder matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.service.GenericResponseService; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocWebMvcConfiguration#springWebProvider matched: + - @ConditionalOnMissingBean (types: org.springdoc.core.providers.SpringWebProvider; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SpringDocWebMvcConfiguration.SpringDocWebMvcActuatorConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping' (OnClassCondition) + + SpringDocWebMvcConfiguration.SpringDocWebMvcRouterConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.servlet.function.RouterFunction' (OnClassCondition) + + SpringDocWebMvcConfiguration.SpringDocWebMvcRouterConfiguration#routerFunctionProvider matched: + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.core.providers.RouterFunctionWebMvcProvider; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SqlInitializationAutoConfiguration matched: + - @ConditionalOnProperty (spring.sql.init.enabled) matched (OnPropertyCondition) + - NoneNestedConditions 0 matched 1 did not; NestedCondition on SqlInitializationAutoConfiguration.SqlInitializationModeCondition.ModeIsNever @ConditionalOnProperty (spring.sql.init.mode=never) did not find property 'mode' (SqlInitializationAutoConfiguration.SqlInitializationModeCondition) + + SslAutoConfiguration#sslBundleRegistry matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.ssl.SslBundleRegistry,org.springframework.boot.ssl.SslBundles; SearchStrategy: all) did not find any beans (OnBeanCondition) + + StartupTimeMetricsListenerAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.MeterRegistry' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + StartupTimeMetricsListenerAutoConfiguration#startupTimeMetrics matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.metrics.startup.StartupTimeMetricsListener; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SwaggerConfig matched: + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (springdoc.swagger-ui.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SwaggerConfig#indexPageTransformer matched: + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.ui.SwaggerIndexTransformer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SwaggerConfig#swaggerConfigResource matched: + - @ConditionalOnProperty (springdoc.use-management-port=false) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.ui.SwaggerConfigResource; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SwaggerConfig#swaggerResourceResolver matched: + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.ui.SwaggerResourceResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SwaggerConfig#swaggerWebMvcConfigurer matched: + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.ui.SwaggerWebMvcConfigurer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SwaggerConfig#swaggerWelcome matched: + - @ConditionalOnProperty (springdoc.use-management-port=false) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springdoc.webmvc.ui.SwaggerWelcomeWebMvc; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SwaggerUiConfigParameters matched: + - @ConditionalOnProperty (springdoc.swagger-ui.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SwaggerUiConfigProperties matched: + - @ConditionalOnProperty (springdoc.swagger-ui.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SwaggerUiOAuthProperties matched: + - @ConditionalOnProperty (springdoc.swagger-ui.enabled) matched (OnPropertyCondition) + - @ConditionalOnBean (types: org.springdoc.core.configuration.SpringDocConfiguration; SearchStrategy: all) found bean 'org.springdoc.core.configuration.SpringDocConfiguration' (OnBeanCondition) + + SystemMetricsAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.MeterRegistry' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + SystemMetricsAutoConfiguration#diskSpaceMetrics matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.metrics.system.DiskSpaceMetricsBinder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SystemMetricsAutoConfiguration#fileDescriptorMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.system.FileDescriptorMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SystemMetricsAutoConfiguration#processorMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.system.ProcessorMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SystemMetricsAutoConfiguration#uptimeMetrics matched: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.system.UptimeMetrics; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TaskExecutionAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor' (OnClassCondition) + + TaskExecutorConfigurations.SimpleAsyncTaskExecutorBuilderConfiguration#simpleAsyncTaskExecutorBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.SimpleAsyncTaskExecutorBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + - @ConditionalOnThreading found PLATFORM (OnThreadingCondition) + + TaskExecutorConfigurations.TaskExecutorBuilderConfiguration#taskExecutorBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.TaskExecutorBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TaskExecutorConfigurations.ThreadPoolTaskExecutorBuilderConfiguration#threadPoolTaskExecutorBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.TaskExecutorBuilder,org.springframework.boot.task.ThreadPoolTaskExecutorBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TaskExecutorMetricsAutoConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.binder.jvm.ExecutorServiceMetrics' (OnClassCondition) + - @ConditionalOnBean (types: java.util.concurrent.Executor,io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found beans 'smart-async-executor', 'simpleMeterRegistry', 'taskScheduler' (OnBeanCondition) + + TaskSchedulingAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler' (OnClassCondition) + + TaskSchedulingAutoConfiguration#scheduledBeanLazyInitializationExcludeFilter matched: + - @ConditionalOnBean (names: org.springframework.context.annotation.internalScheduledAnnotationProcessor; SearchStrategy: all) found bean 'org.springframework.context.annotation.internalScheduledAnnotationProcessor' (OnBeanCondition) + + TaskSchedulingConfigurations.SimpleAsyncTaskSchedulerBuilderConfiguration#simpleAsyncTaskSchedulerBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.SimpleAsyncTaskSchedulerBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + - @ConditionalOnThreading found PLATFORM (OnThreadingCondition) + + TaskSchedulingConfigurations.TaskSchedulerBuilderConfiguration#taskSchedulerBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.TaskSchedulerBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TaskSchedulingConfigurations.TaskSchedulerConfiguration matched: + - @ConditionalOnBean (names: org.springframework.context.annotation.internalScheduledAnnotationProcessor; SearchStrategy: all) found bean 'org.springframework.context.annotation.internalScheduledAnnotationProcessor'; @ConditionalOnMissingBean (types: org.springframework.scheduling.TaskScheduler,java.util.concurrent.ScheduledExecutorService; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TaskSchedulingConfigurations.TaskSchedulerConfiguration#taskScheduler matched: + - @ConditionalOnThreading found PLATFORM (OnThreadingCondition) + + TaskSchedulingConfigurations.ThreadPoolTaskSchedulerBuilderConfiguration#threadPoolTaskSchedulerBuilder matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.TaskSchedulerBuilder,org.springframework.boot.task.ThreadPoolTaskSchedulerBuilder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ThreadDumpEndpointAutoConfiguration matched: + - @ConditionalOnAvailableEndpoint marked as exposed by a 'management.endpoints.jmx.exposure' property (OnAvailableEndpointCondition) + + ThreadDumpEndpointAutoConfiguration#dumpEndpoint matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.management.ThreadDumpEndpoint; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TomcatMetricsAutoConfiguration matched: + - @ConditionalOnClass found required classes 'io.micrometer.core.instrument.binder.tomcat.TomcatMetrics', 'org.apache.catalina.Manager' (OnClassCondition) + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + + TomcatMetricsAutoConfiguration#tomcatMetricsBinder matched: + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry'; @ConditionalOnMissingBean (types: io.micrometer.core.instrument.binder.tomcat.TomcatMetrics,org.springframework.boot.actuate.metrics.web.tomcat.TomcatMetricsBinder; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TransactionAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.transaction.PlatformTransactionManager' (OnClassCondition) + + TransactionAutoConfiguration.TransactionTemplateConfiguration matched: + - @ConditionalOnSingleCandidate (types: org.springframework.transaction.PlatformTransactionManager; SearchStrategy: all) found a single bean 'transactionManager' (OnBeanCondition) + + TransactionAutoConfiguration.TransactionTemplateConfiguration#transactionTemplate matched: + - @ConditionalOnMissingBean (types: org.springframework.transaction.support.TransactionOperations; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TransactionManagerCustomizationAutoConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.transaction.PlatformTransactionManager' (OnClassCondition) + + TransactionManagerCustomizationAutoConfiguration#platformTransactionManagerCustomizers matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.autoconfigure.transaction.TransactionManagerCustomizers; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ValidationAutoConfiguration matched: + - @ConditionalOnClass found required class 'jakarta.validation.executable.ExecutableValidator' (OnClassCondition) + - @ConditionalOnResource found location classpath:META-INF/services/jakarta.validation.spi.ValidationProvider (OnResourceCondition) + + ValidationAutoConfiguration#defaultValidator matched: + - @ConditionalOnMissingBean (types: jakarta.validation.Validator; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ValidationAutoConfiguration#methodValidationPostProcessor matched: + - @ConditionalOnMissingBean (types: org.springframework.validation.beanvalidation.MethodValidationPostProcessor; SearchStrategy: current) did not find any beans (OnBeanCondition) + + WarmFlowUiConfig matched: + - @ConditionalOnProperty (warm-flow.ui=true) matched (OnPropertyCondition) + + WebEndpointAutoConfiguration matched: + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + + WebEndpointAutoConfiguration#controllerEndpointDiscoverer matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.web.annotation.ControllerEndpointsSupplier; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebEndpointAutoConfiguration#endpointMediaTypes matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.web.EndpointMediaTypes; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebEndpointAutoConfiguration#pathMappedEndpoints matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.web.PathMappedEndpoints; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebEndpointAutoConfiguration#webEndpointDiscoverer matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebEndpointAutoConfiguration.WebEndpointServletConfiguration matched: + - found 'session' scope (OnWebApplicationCondition) + + WebEndpointAutoConfiguration.WebEndpointServletConfiguration#servletEndpointDiscoverer matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.web.annotation.ServletEndpointsSupplier; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration matched: + - @ConditionalOnClass found required classes 'jakarta.servlet.Servlet', 'org.springframework.web.servlet.DispatcherServlet', 'org.springframework.web.servlet.config.annotation.WebMvcConfigurer' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnMissingBean (types: org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration#formContentFilter matched: + - @ConditionalOnProperty (spring.mvc.formcontent.filter.enabled) matched (OnPropertyCondition) + - @ConditionalOnMissingBean (types: org.springframework.web.filter.FormContentFilter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration.EnableWebMvcConfiguration#flashMapManager matched: + - @ConditionalOnMissingBean (names: flashMapManager; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration.EnableWebMvcConfiguration#localeResolver matched: + - @ConditionalOnMissingBean (names: localeResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration.EnableWebMvcConfiguration#themeResolver matched: + - @ConditionalOnMissingBean (names: themeResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#defaultViewResolver matched: + - @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.InternalResourceViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#requestContextFilter matched: + - @ConditionalOnMissingBean (types: org.springframework.web.context.request.RequestContextListener,org.springframework.web.filter.RequestContextFilter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#viewResolver matched: + - @ConditionalOnBean (types: org.springframework.web.servlet.ViewResolver; SearchStrategy: all) found beans 'defaultViewResolver', 'beanNameViewResolver', 'mvcViewResolver'; @ConditionalOnMissingBean (names: viewResolver types: org.springframework.web.servlet.view.ContentNegotiatingViewResolver; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcEndpointManagementContextConfiguration matched: + - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnBean (types: org.springframework.web.servlet.DispatcherServlet,org.springframework.boot.actuate.endpoint.web.WebEndpointsSupplier; SearchStrategy: all) found beans 'webEndpointDiscoverer', 'dispatcherServlet' (OnBeanCondition) + + WebMvcEndpointManagementContextConfiguration#controllerEndpointHandlerMapping matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.web.servlet.ControllerEndpointHandlerMapping; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcEndpointManagementContextConfiguration#endpointObjectMapperWebMvcConfigurer matched: + - @ConditionalOnBean (types: org.springframework.boot.actuate.endpoint.jackson.EndpointObjectMapper; SearchStrategy: all) found bean 'endpointObjectMapper' (OnBeanCondition) + + WebMvcEndpointManagementContextConfiguration#webEndpointServletHandlerMapping matched: + - @ConditionalOnMissingBean (types: org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcObservationAutoConfiguration matched: + - @ConditionalOnClass found required classes 'org.springframework.web.servlet.DispatcherServlet', 'io.micrometer.observation.Observation' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnBean (types: io.micrometer.observation.ObservationRegistry; SearchStrategy: all) found bean 'observationRegistry' (OnBeanCondition) + + WebMvcObservationAutoConfiguration#webMvcObservationFilter matched: + - @ConditionalOnMissingBean (types: org.springframework.web.filter.ServerHttpObservationFilter; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WebMvcObservationAutoConfiguration.MeterFilterConfiguration matched: + - @ConditionalOnClass found required class 'io.micrometer.core.instrument.MeterRegistry' (OnClassCondition) + - @ConditionalOnBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found bean 'simpleMeterRegistry' (OnBeanCondition) + + WebSocketServletAutoConfiguration matched: + - @ConditionalOnClass found required classes 'jakarta.servlet.Servlet', 'jakarta.websocket.server.ServerContainer' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + + WebSocketServletAutoConfiguration.TomcatWebSocketConfiguration matched: + - @ConditionalOnClass found required classes 'org.apache.catalina.startup.Tomcat', 'org.apache.tomcat.websocket.server.WsSci' (OnClassCondition) + + WebSocketServletAutoConfiguration.TomcatWebSocketConfiguration#websocketServletWebServerCustomizer matched: + - @ConditionalOnMissingBean (names: websocketServletWebServerCustomizer; SearchStrategy: all) did not find any beans (OnBeanCondition) + + WorkflowGlobalListener matched: + - @ConditionalOnProperty (warm-flow.enabled=true) matched (OnPropertyCondition) + + WorkflowPermissionHandler matched: + - @ConditionalOnProperty (warm-flow.enabled=true) matched (OnPropertyCondition) + + +Negative matches: +----------------- + + ActiveMQAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.jms.ConnectionFactory' (OnClassCondition) + + AopAutoConfiguration.AspectJAutoProxyingConfiguration.JdkDynamicAutoProxyConfiguration: + Did not match: + - @ConditionalOnProperty (spring.aop.proxy-target-class=false) did not find property 'proxy-target-class' (OnPropertyCondition) + + AopAutoConfiguration.ClassProxyingConfiguration: + Did not match: + - @ConditionalOnMissingClass found unwanted class 'org.aspectj.weaver.Advice' (OnClassCondition) + + AppOpticsMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.appoptics.AppOpticsMeterRegistry' (OnClassCondition) + + ArtemisAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.jms.ConnectionFactory' (OnClassCondition) + + AtlasMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.atlas.AtlasMeterRegistry' (OnClassCondition) + + AuditAutoConfiguration: + Did not match: + - @ConditionalOnBean (types: org.springframework.boot.actuate.audit.AuditEventRepository; SearchStrategy: all) did not find any beans of type org.springframework.boot.actuate.audit.AuditEventRepository (OnBeanCondition) + Matched: + - @ConditionalOnProperty (management.auditevents.enabled) matched (OnPropertyCondition) + + AuditEventsEndpointAutoConfiguration#auditEventsEndpoint: + Did not match: + - @ConditionalOnBean (types: org.springframework.boot.actuate.audit.AuditEventRepository; SearchStrategy: all) did not find any beans of type org.springframework.boot.actuate.audit.AuditEventRepository (OnBeanCondition) + + AvailabilityHealthContributorAutoConfiguration#livenessStateHealthIndicator: + Did not match: + - @ConditionalOnProperty (management.health.livenessstate.enabled=true) did not find property 'enabled' (OnPropertyCondition) + + AvailabilityHealthContributorAutoConfiguration#readinessStateHealthIndicator: + Did not match: + - @ConditionalOnProperty (management.health.readinessstate.enabled=true) did not find property 'enabled' (OnPropertyCondition) + + AvailabilityProbesAutoConfiguration: + Did not match: + - Probes availability not running on a supported cloud platform (AvailabilityProbesAutoConfiguration.ProbesCondition) + + BatchAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.batch.core.launch.JobLauncher' (OnClassCondition) + + BatchObservationAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.batch.core.configuration.annotation.BatchObservabilityBeanPostProcessor' (OnClassCondition) + + BraveAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'brave.Tracer' (OnClassCondition) + + Cache2kCacheConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.cache2k.Cache2kBuilder' (OnClassCondition) + + CacheAutoConfiguration.CacheManagerEntityManagerFactoryDependsOnPostProcessor: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean' (OnClassCondition) + + CacheConfig#redisCacheService: + Did not match: + - @ConditionalOnProperty (spring.cache.type=redis) found different value in property 'type' (OnPropertyCondition) + + CacheMeterBinderProvidersConfiguration.Cache2kCacheMeterBinderProviderConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'org.cache2k.Cache2kBuilder', 'org.cache2k.extra.spring.SpringCache2kCache', 'org.cache2k.extra.micrometer.Cache2kCacheMetrics' (OnClassCondition) + + CacheMeterBinderProvidersConfiguration.HazelcastCacheMeterBinderProviderConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'com.hazelcast.spring.cache.HazelcastCache', 'com.hazelcast.core.Hazelcast' (OnClassCondition) + + CachesEndpointAutoConfiguration#cachesEndpointWebExtension: + Did not match: + - @ConditionalOnAvailableEndpoint no 'management.endpoints' property marked it as exposed (OnAvailableEndpointCondition) + Matched: + - @ConditionalOnBean (types: org.springframework.boot.actuate.cache.CachesEndpoint; SearchStrategy: all) found bean 'cachesEndpoint'; @ConditionalOnMissingBean (types: org.springframework.boot.actuate.cache.CachesEndpointWebExtension; SearchStrategy: all) did not find any beans (OnBeanCondition) + + CassandraAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.datastax.oss.driver.api.core.CqlSession' (OnClassCondition) + + CassandraDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.datastax.oss.driver.api.core.CqlSession' (OnClassCondition) + + CassandraHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.datastax.oss.driver.api.core.CqlSession' (OnClassCondition) + + CassandraReactiveDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.datastax.oss.driver.api.core.CqlSession' (OnClassCondition) + + CassandraReactiveHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.datastax.oss.driver.api.core.CqlSession' (OnClassCondition) + + CassandraReactiveRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.cassandra.ReactiveSession' (OnClassCondition) + + CassandraRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.datastax.oss.driver.api.core.CqlSession' (OnClassCondition) + + ClientHttpConnectorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient' (OnClassCondition) + + CloudFoundryActuatorAutoConfiguration: + Did not match: + - @ConditionalOnCloudPlatform did not find CLOUD_FOUNDRY (OnCloudPlatformCondition) + Matched: + - @ConditionalOnClass found required class 'org.springframework.web.servlet.DispatcherServlet' (OnClassCondition) + - found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (management.cloudfoundry.enabled) matched (OnPropertyCondition) + + CodecsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient' (OnClassCondition) + + CompositeMeterRegistryConfiguration: + Did not match: + - NoneNestedConditions 1 matched 1 did not; NestedCondition on CompositeMeterRegistryConfiguration.MultipleNonPrimaryMeterRegistriesCondition.SingleInjectableMeterRegistry @ConditionalOnSingleCandidate (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found a single bean 'simpleMeterRegistry'; NestedCondition on CompositeMeterRegistryConfiguration.MultipleNonPrimaryMeterRegistriesCondition.NoMeterRegistryCondition @ConditionalOnMissingBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found beans of type 'io.micrometer.core.instrument.MeterRegistry' simpleMeterRegistry (CompositeMeterRegistryConfiguration.MultipleNonPrimaryMeterRegistriesCondition) + + ConfigurationPropertiesReportEndpointAutoConfiguration#configurationPropertiesReportEndpointWebExtension: + Did not match: + - @ConditionalOnAvailableEndpoint no 'management.endpoints' property marked it as exposed (OnAvailableEndpointCondition) + Matched: + - @ConditionalOnBean (types: org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpoint; SearchStrategy: all) found bean 'configurationPropertiesReportEndpoint'; @ConditionalOnMissingBean (types: org.springframework.boot.actuate.context.properties.ConfigurationPropertiesReportEndpointWebExtension; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ConnectionFactoryHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.r2dbc.spi.ConnectionFactory' (OnClassCondition) + + ConnectionPoolMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.r2dbc.pool.ConnectionPool' (OnClassCondition) + + CouchbaseAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Cluster' (OnClassCondition) + + CouchbaseCacheConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Cluster' (OnClassCondition) + + CouchbaseDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Bucket' (OnClassCondition) + + CouchbaseHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Cluster' (OnClassCondition) + + CouchbaseReactiveDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Cluster' (OnClassCondition) + + CouchbaseReactiveHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Cluster' (OnClassCondition) + + CouchbaseReactiveRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Cluster' (OnClassCondition) + + CouchbaseRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.couchbase.client.java.Bucket' (OnClassCondition) + + DataSourceAutoConfiguration.EmbeddedDatabaseConfiguration: + Did not match: + - EmbeddedDataSource spring.datasource.url is set (DataSourceAutoConfiguration.EmbeddedDatabaseCondition) + + DataSourceAutoConfiguration.PooledDataSourceConfiguration: + Did not match: + - @ConditionalOnMissingBean (types: javax.sql.DataSource,javax.sql.XADataSource; SearchStrategy: all) found beans of type 'javax.sql.DataSource' druidDataSource (OnBeanCondition) + Matched: + - AnyNestedCondition 1 matched 1 did not; NestedCondition on DataSourceAutoConfiguration.PooledDataSourceCondition.PooledDataSourceAvailable PooledDataSource found supported DataSource; NestedCondition on DataSourceAutoConfiguration.PooledDataSourceCondition.ExplicitType @ConditionalOnProperty (spring.datasource.type) did not find property 'type' (DataSourceAutoConfiguration.PooledDataSourceCondition) + + DataSourceCheckpointRestoreConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.crac.Resource' (OnClassCondition) + + DataSourceConfiguration.Dbcp2: + Did not match: + - @ConditionalOnClass did not find required class 'org.apache.commons.dbcp2.BasicDataSource' (OnClassCondition) + + DataSourceConfiguration.Generic: + Did not match: + - @ConditionalOnProperty (spring.datasource.type) did not find property 'spring.datasource.type' (OnPropertyCondition) + + DataSourceConfiguration.OracleUcp: + Did not match: + - @ConditionalOnClass did not find required classes 'oracle.ucp.jdbc.PoolDataSourceImpl', 'oracle.jdbc.OracleConnection' (OnClassCondition) + + DataSourceConfiguration.Tomcat: + Did not match: + - @ConditionalOnClass did not find required class 'org.apache.tomcat.jdbc.pool.DataSource' (OnClassCondition) + + DataSourceJmxConfiguration.TomcatDataSourceJmxConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.apache.tomcat.jdbc.pool.DataSourceProxy' (OnClassCondition) + + DataSourcePoolMetadataProvidersConfiguration.CommonsDbcp2PoolDataSourceMetadataProviderConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.apache.commons.dbcp2.BasicDataSource' (OnClassCondition) + + DataSourcePoolMetadataProvidersConfiguration.OracleUcpPoolDataSourceMetadataProviderConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'oracle.ucp.jdbc.PoolDataSource', 'oracle.jdbc.OracleConnection' (OnClassCondition) + + DataSourcePoolMetadataProvidersConfiguration.TomcatDataSourcePoolMetadataProviderConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.apache.tomcat.jdbc.pool.DataSource' (OnClassCondition) + + DatadogMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.datadog.DatadogMeterRegistry' (OnClassCondition) + + DdlAutoConfiguration#ddlApplicationRunner: + Did not match: + - @ConditionalOnBean (types: com.baomidou.mybatisplus.extension.ddl.IDdl; SearchStrategy: all) did not find any beans of type com.baomidou.mybatisplus.extension.ddl.IDdl (OnBeanCondition) + + DispatcherServletAutoConfiguration.DispatcherServletConfiguration#multipartResolver: + Did not match: + - @ConditionalOnBean (types: org.springframework.web.multipart.MultipartResolver; SearchStrategy: all) did not find any beans of type org.springframework.web.multipart.MultipartResolver (OnBeanCondition) + + DruidDataSourceAutoConfigure#dataSource: + Did not match: + - @ConditionalOnMissingBean (types: com.alibaba.druid.spring.boot3.autoconfigure.DruidDataSourceWrapper,com.alibaba.druid.pool.DruidDataSource,javax.sql.DataSource; SearchStrategy: all) found beans of type 'javax.sql.DataSource' druidDataSource (OnBeanCondition) + + DruidFilterConfiguration#commonsLogFilter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.commons-log.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#configFilter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.config.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#encodingConvertFilter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.encoding.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#log4j2Filter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.log4j2.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#log4jFilter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.log4j.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#slf4jLogFilter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.slf4j.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#statFilter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.stat.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#wallConfig: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.wall.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidFilterConfiguration#wallFilter: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.filter.wall.enabled) did not find property 'enabled' (OnPropertyCondition) + + DruidSpringAopConfiguration: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.aop-patterns) did not find property 'spring.datasource.druid.aop-patterns' (OnPropertyCondition) + + DruidStatViewServletConfiguration: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.stat-view-servlet.enabled=true) did not find property 'spring.datasource.druid.stat-view-servlet.enabled' (OnPropertyCondition) + Matched: + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + + DruidWebStatFilterConfiguration: + Did not match: + - @ConditionalOnProperty (spring.datasource.druid.web-stat-filter.enabled=true) did not find property 'spring.datasource.druid.web-stat-filter.enabled' (OnPropertyCondition) + Matched: + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + + DynatraceMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.dynatrace.DynatraceMeterRegistry' (OnClassCondition) + + ElasticMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.elastic.ElasticMeterRegistry' (OnClassCondition) + + ElasticsearchClientAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'co.elastic.clients.elasticsearch.ElasticsearchClient' (OnClassCondition) + + ElasticsearchDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate' (OnClassCondition) + + ElasticsearchReactiveHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient' (OnClassCondition) + + ElasticsearchRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.elasticsearch.repository.ElasticsearchRepository' (OnClassCondition) + + ElasticsearchRestClientAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.elasticsearch.client.RestClientBuilder' (OnClassCondition) + + ElasticsearchRestHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.elasticsearch.client.RestClient' (OnClassCondition) + + EmbeddedLdapAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.unboundid.ldap.listener.InMemoryDirectoryServer' (OnClassCondition) + + EmbeddedWebServerFactoryCustomizerAutoConfiguration.JettyWebServerFactoryCustomizerConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'org.eclipse.jetty.server.Server', 'org.eclipse.jetty.util.Loader', 'org.eclipse.jetty.ee10.webapp.WebAppContext' (OnClassCondition) + + EmbeddedWebServerFactoryCustomizerAutoConfiguration.NettyWebServerFactoryCustomizerConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'reactor.netty.http.server.HttpServer' (OnClassCondition) + + EmbeddedWebServerFactoryCustomizerAutoConfiguration.TomcatWebServerFactoryCustomizerConfiguration#tomcatVirtualThreadsProtocolHandlerCustomizer: + Did not match: + - @ConditionalOnThreading did not find VIRTUAL (OnThreadingCondition) + + EmbeddedWebServerFactoryCustomizerAutoConfiguration.UndertowWebServerFactoryCustomizerConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'io.undertow.Undertow', 'org.xnio.SslClientAuthMode' (OnClassCondition) + + EnvironmentEndpointAutoConfiguration#environmentEndpointWebExtension: + Did not match: + - @ConditionalOnAvailableEndpoint no 'management.endpoints' property marked it as exposed (OnAvailableEndpointCondition) + Matched: + - @ConditionalOnBean (types: org.springframework.boot.actuate.env.EnvironmentEndpoint; SearchStrategy: all) found bean 'environmentEndpoint'; @ConditionalOnMissingBean (types: org.springframework.boot.actuate.env.EnvironmentEndpointWebExtension; SearchStrategy: all) did not find any beans (OnBeanCondition) + + ErrorWebFluxAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.config.WebFluxConfigurer' (OnClassCondition) + + FileConfig#initAmazonS3: + Did not match: + - @ConditionalOnProperty (file.storage.mode=cloud) found different value in property 'mode' (OnPropertyCondition) + + FileConfig#initCloudFileService: + Did not match: + - @ConditionalOnProperty (file.storage.mode=cloud) found different value in property 'mode' (OnPropertyCondition) + + FlywayAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.flywaydb.core.Flyway' (OnClassCondition) + + FlywayEndpointAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.flywaydb.core.Flyway' (OnClassCondition) + + FreeMarkerNonWebConfiguration: + Did not match: + - @ConditionalOnWebApplication found 'session' scope and did not find reactive web application classes (OnWebApplicationCondition) + + FreeMarkerReactiveWebConfiguration: + Did not match: + - did not find reactive web application classes (OnWebApplicationCondition) + + FreeMarkerServletWebConfiguration#resourceUrlEncodingFilter: + Did not match: + - @ConditionalOnEnabledResourceChain did not find class org.webjars.WebJarAssetLocator (OnEnabledResourceChainCondition) + + GangliaMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.ganglia.GangliaMeterRegistry' (OnClassCondition) + + GenericCacheConfiguration: + Did not match: + - Cache org.springframework.boot.autoconfigure.cache.GenericCacheConfiguration unknown cache type (CacheCondition) + + GraphQlAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlObservationAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlQueryByExampleAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlQuerydslAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.querydsl.core.Query' (OnClassCondition) + + GraphQlRSocketAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlReactiveQueryByExampleAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlReactiveQuerydslAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.querydsl.core.Query' (OnClassCondition) + + GraphQlWebFluxAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlWebFluxSecurityAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlWebMvcAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphQlWebMvcSecurityAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + GraphiteMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.graphite.GraphiteMeterRegistry' (OnClassCondition) + + GroovyTemplateAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'groovy.text.markup.MarkupTemplateEngine' (OnClassCondition) + + GsonAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.google.gson.Gson' (OnClassCondition) + + GsonHttpMessageConvertersConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.google.gson.Gson' (OnClassCondition) + + H2ConsoleAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.h2.server.web.JakartaWebServlet' (OnClassCondition) + + HazelcastAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.hazelcast.core.HazelcastInstance' (OnClassCondition) + + HazelcastCacheConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.hazelcast.core.HazelcastInstance' (OnClassCondition) + + HazelcastHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.hazelcast.core.HazelcastInstance' (OnClassCondition) + + HazelcastJpaDependencyAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.hazelcast.core.HazelcastInstance' (OnClassCondition) + + HealthEndpointReactiveWebExtensionConfiguration: + Did not match: + - did not find reactive web application classes (OnWebApplicationCondition) + + HealthEndpointWebExtensionConfiguration.JerseyAdditionalHealthEndpointPathsConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.glassfish.jersey.server.ResourceConfig' (OnClassCondition) + + HibernateJpaAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.persistence.EntityManager' (OnClassCondition) + + HibernateMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.persistence.EntityManagerFactory' (OnClassCondition) + + HttpExchangesAutoConfiguration: + Did not match: + - @ConditionalOnBean (types: org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository; SearchStrategy: all) did not find any beans of type org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository (OnBeanCondition) + Matched: + - @ConditionalOnWebApplication (required) found 'session' scope (OnWebApplicationCondition) + - @ConditionalOnProperty (management.httpexchanges.recording.enabled) matched (OnPropertyCondition) + + HttpExchangesAutoConfiguration.ReactiveHttpExchangesConfiguration: + Did not match: + - did not find reactive web application classes (OnWebApplicationCondition) + - Ancestor org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesAutoConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition) + + HttpExchangesAutoConfiguration.ServletHttpExchangesConfiguration: + Did not match: + - Ancestor org.springframework.boot.actuate.autoconfigure.web.exchanges.HttpExchangesAutoConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition) + Matched: + - found 'session' scope (OnWebApplicationCondition) + + HttpExchangesEndpointAutoConfiguration#httpExchangesEndpoint: + Did not match: + - @ConditionalOnBean (types: org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository; SearchStrategy: all) did not find any beans of type org.springframework.boot.actuate.web.exchanges.HttpExchangeRepository (OnBeanCondition) + + HttpHandlerAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.DispatcherHandler' (OnClassCondition) + + HumioMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.humio.HumioMeterRegistry' (OnClassCondition) + + HypermediaAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.hateoas.EntityModel' (OnClassCondition) + + IdentifierGeneratorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.cloud.commons.util.InetUtils' (OnClassCondition) + + InfinispanCacheConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.infinispan.spring.embedded.provider.SpringEmbeddedCacheManager' (OnClassCondition) + + InfluxDbAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.influxdb.InfluxDB' (OnClassCondition) + + InfluxDbHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.influxdb.InfluxDB' (OnClassCondition) + + InfluxMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.influx.InfluxMeterRegistry' (OnClassCondition) + + InfoContributorAutoConfiguration#buildInfoContributor: + Did not match: + - @ConditionalOnSingleCandidate (types: org.springframework.boot.info.BuildProperties; SearchStrategy: all) did not find any beans (OnBeanCondition) + Matched: + - @ConditionalOnEnabledInfoContributor management.info.defaults.enabled is considered true (OnEnabledInfoContributorCondition) + + InfoContributorAutoConfiguration#envInfoContributor: + Did not match: + - @ConditionalOnEnabledInfoContributor management.info.env.enabled is not true (OnEnabledInfoContributorCondition) + + InfoContributorAutoConfiguration#gitInfoContributor: + Did not match: + - @ConditionalOnSingleCandidate (types: org.springframework.boot.info.GitProperties; SearchStrategy: all) did not find any beans (OnBeanCondition) + Matched: + - @ConditionalOnEnabledInfoContributor management.info.defaults.enabled is considered true (OnEnabledInfoContributorCondition) + + InfoContributorAutoConfiguration#javaInfoContributor: + Did not match: + - @ConditionalOnEnabledInfoContributor management.info.java.enabled is not true (OnEnabledInfoContributorCondition) + + InfoContributorAutoConfiguration#osInfoContributor: + Did not match: + - @ConditionalOnEnabledInfoContributor management.info.os.enabled is not true (OnEnabledInfoContributorCondition) + + InfoContributorAutoConfiguration#processInfoContributor: + Did not match: + - @ConditionalOnEnabledInfoContributor management.info.process.enabled is not true (OnEnabledInfoContributorCondition) + + IntegrationAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.integration.config.EnableIntegration' (OnClassCondition) + + IntegrationGraphEndpointAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.integration.graph.IntegrationGraphServer' (OnClassCondition) + + JCacheCacheConfiguration: + Did not match: + - Cache org.springframework.boot.autoconfigure.cache.JCacheCacheConfiguration unknown cache type (CacheCondition) + Matched: + - @ConditionalOnClass found required classes 'javax.cache.Caching', 'org.springframework.cache.jcache.JCacheCacheManager' (OnClassCondition) + + JacksonHttpMessageConvertersConfiguration.MappingJackson2XmlHttpMessageConverterConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.fasterxml.jackson.dataformat.xml.XmlMapper' (OnClassCondition) + + JdbcRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.jdbc.repository.config.AbstractJdbcConfiguration' (OnClassCondition) + + JedisConnectionConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'redis.clients.jedis.Jedis' (OnClassCondition) + + JerseyAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.glassfish.jersey.server.spring.SpringComponentProvider' (OnClassCondition) + + JerseySameManagementContextConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.glassfish.jersey.server.ResourceConfig' (OnClassCondition) + + JerseyServerMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.glassfish.jersey.micrometer.server.ObservationApplicationEventListener' (OnClassCondition) + + JerseyWebEndpointManagementContextConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.glassfish.jersey.server.ResourceConfig' (OnClassCondition) + + JettyMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.eclipse.jetty.server.Server' (OnClassCondition) + + JmsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.jms.Message' (OnClassCondition) + + JmsHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.jms.ConnectionFactory' (OnClassCondition) + + JmxMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.jmx.JmxMeterRegistry' (OnClassCondition) + + JndiConnectionFactoryAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.jms.core.JmsTemplate' (OnClassCondition) + + JndiDataSourceAutoConfiguration: + Did not match: + - @ConditionalOnProperty (spring.datasource.jndi-name) did not find property 'jndi-name' (OnPropertyCondition) + Matched: + - @ConditionalOnClass found required classes 'javax.sql.DataSource', 'org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType' (OnClassCondition) + + JooqAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.jooq.DSLContext' (OnClassCondition) + + JpaRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.jpa.repository.JpaRepository' (OnClassCondition) + + JsonbAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.json.bind.Jsonb' (OnClassCondition) + + JsonbHttpMessageConvertersConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.json.bind.Jsonb' (OnClassCondition) + + JtaAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.transaction.Transaction' (OnClassCondition) + + KafkaAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.kafka.core.KafkaTemplate' (OnClassCondition) + + KafkaMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.kafka.core.ProducerFactory' (OnClassCondition) + + KairosMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.kairos.KairosMeterRegistry' (OnClassCondition) + + Knife4jAutoConfiguration#corsFilter: + Did not match: + - @ConditionalOnProperty (knife4j.cors=true) did not find property 'knife4j.cors' (OnPropertyCondition) + + Knife4jAutoConfiguration#productionSecurityFilter: + Did not match: + - @ConditionalOnProperty (knife4j.production=true) did not find property 'knife4j.production' (OnPropertyCondition) + + Knife4jAutoConfiguration#securityBasicAuthFilter: + Did not match: + - @ConditionalOnProperty (knife4j.basic.enable=true) found different value in property 'knife4j.basic.enable' (OnPropertyCondition) + + Knife4jInsightAutoConfiguration: + Did not match: + - @ConditionalOnProperty (knife4j.insight.enable=true) did not find property 'knife4j.insight.enable' (OnPropertyCondition) + + LdapAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.ldap.core.ContextSource' (OnClassCondition) + + LdapHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.ldap.core.LdapOperations' (OnClassCondition) + + LdapRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.ldap.repository.LdapRepository' (OnClassCondition) + + LettuceConnectionConfiguration#redisConnectionFactory: + Did not match: + - @ConditionalOnMissingBean (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) found beans of type 'org.springframework.data.redis.connection.RedisConnectionFactory' redissonConnectionFactory (OnBeanCondition) + + LettuceConnectionConfiguration#redisConnectionFactoryVirtualThreads: + Did not match: + - @ConditionalOnMissingBean (types: org.springframework.data.redis.connection.RedisConnectionFactory; SearchStrategy: all) found beans of type 'org.springframework.data.redis.connection.RedisConnectionFactory' redissonConnectionFactory (OnBeanCondition) + + LiquibaseAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'liquibase.change.DatabaseChange' (OnClassCondition) + + LiquibaseEndpointAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'liquibase.integration.spring.SpringLiquibase' (OnClassCondition) + + LogFileWebEndpointAutoConfiguration#logFileWebEndpoint: + Did not match: + - Log File did not find logging file (LogFileWebEndpointAutoConfiguration.LogFileCondition) + + LogbackMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'ch.qos.logback.classic.LoggerContext' (OnClassCondition) + + MailHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnEnabledHealthIndicator management.health.mail.enabled is false (OnEnabledHealthIndicatorCondition) + Matched: + - @ConditionalOnClass found required class 'org.springframework.mail.javamail.JavaMailSenderImpl' (OnClassCondition) + + MailSenderJndiConfiguration: + Did not match: + - @ConditionalOnProperty (spring.mail.jndi-name) did not find property 'jndi-name' (OnPropertyCondition) + Matched: + - @ConditionalOnClass found required class 'jakarta.mail.Session' (OnClassCondition) + + MailSenderValidatorAutoConfiguration: + Did not match: + - @ConditionalOnProperty (spring.mail.test-connection) did not find property 'test-connection' (OnPropertyCondition) + + ManagementContextAutoConfiguration.DifferentManagementContextConfiguration: + Did not match: + - Management Port actual port type (SAME) did not match required type (DIFFERENT) (OnManagementPortCondition) + + ManagementWebSecurityAutoConfiguration: + Did not match: + - AllNestedConditions 1 matched 1 did not; NestedCondition on DefaultWebSecurityCondition.Beans @ConditionalOnMissingBean (types: org.springframework.security.web.SecurityFilterChain; SearchStrategy: all) did not find any beans; NestedCondition on DefaultWebSecurityCondition.Classes @ConditionalOnClass did not find required classes 'org.springframework.security.web.SecurityFilterChain', 'org.springframework.security.config.annotation.web.builders.HttpSecurity' (DefaultWebSecurityCondition) + Matched: + - found 'session' scope (OnWebApplicationCondition) + + MappingsEndpointAutoConfiguration.ReactiveWebConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.DispatcherHandler' (OnClassCondition) + + MessageSourceAutoConfiguration: + Did not match: + - ResourceBundle did not find bundle with basename messages (MessageSourceAutoConfiguration.ResourceBundleCondition) + + MetricsAspectsAutoConfiguration: + Did not match: + - AnyNestedCondition 0 matched 2 did not; NestedCondition on MetricsAspectsAutoConfiguration.ObservationAnnotationsEnabledCondition.ManagementObservationsEnabledCondition @ConditionalOnProperty (management.observations.annotations.enabled=true) did not find property 'enabled'; NestedCondition on MetricsAspectsAutoConfiguration.ObservationAnnotationsEnabledCondition.MicrometerObservationsEnabledCondition @ConditionalOnProperty (micrometer.observations.annotations.enabled=true) did not find property 'enabled' (MetricsAspectsAutoConfiguration.ObservationAnnotationsEnabledCondition) + Matched: + - @ConditionalOnClass found required classes 'io.micrometer.core.instrument.MeterRegistry', 'org.aspectj.weaver.Advice' (OnClassCondition) + + MicrometerTracingAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.Tracer' (OnClassCondition) + + MongoAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.mongodb.client.MongoClient' (OnClassCondition) + + MongoDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.mongodb.client.MongoClient' (OnClassCondition) + + MongoHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.mongodb.core.MongoTemplate' (OnClassCondition) + + MongoMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.mongodb.MongoClientSettings' (OnClassCondition) + + MongoReactiveAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.mongodb.reactivestreams.client.MongoClient' (OnClassCondition) + + MongoReactiveDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.mongodb.reactivestreams.client.MongoClient' (OnClassCondition) + + MongoReactiveHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.mongodb.core.ReactiveMongoTemplate' (OnClassCondition) + + MongoReactiveRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.mongodb.reactivestreams.client.MongoClient' (OnClassCondition) + + MongoRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.mongodb.client.MongoClient' (OnClassCondition) + + MultipleOpenApiSupportConfiguration.SpringDocWebMvcActuatorDifferentConfiguration: + Did not match: + - Management Port actual port type (SAME) did not match required type (DIFFERENT) (OnManagementPortCondition) + Matched: + - @ConditionalOnClass found required class 'org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping' (OnClassCondition) + + MustacheAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.samskivert.mustache.Mustache' (OnClassCondition) + + MybatisPlusAutoConfiguration#sqlSessionFactory: + Did not match: + - @ConditionalOnMissingBean (types: org.apache.ibatis.session.SqlSessionFactory; SearchStrategy: all) found beans of type 'org.apache.ibatis.session.SqlSessionFactory' sqlSessionFactory (OnBeanCondition) + + MybatisPlusAutoConfiguration.MapperScannerRegistrarNotFoundConfiguration: + Did not match: + - @ConditionalOnMissingBean (types: org.mybatis.spring.mapper.MapperFactoryBean,org.mybatis.spring.mapper.MapperScannerConfigurer; SearchStrategy: all) found beans of type 'org.mybatis.spring.mapper.MapperScannerConfigurer' net.lab1024.sa.admin.AdminApplication#MapperScannerRegistrar#0 (OnBeanCondition) + + MybatisPlusInnerInterceptorAutoConfiguration: + Did not match: + - @ConditionalOnBean (types: com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor; SearchStrategy: all) did not find any beans of type com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor (OnBeanCondition) + + MybatisPlusLanguageDriverAutoConfiguration.FreeMarkerConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver', 'org.mybatis.scripting.freemarker.FreeMarkerLanguageDriverConfig' (OnClassCondition) + + MybatisPlusLanguageDriverAutoConfiguration.LegacyFreeMarkerConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.mybatis.scripting.freemarker.FreeMarkerLanguageDriver' (OnClassCondition) + + MybatisPlusLanguageDriverAutoConfiguration.LegacyVelocityConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.mybatis.scripting.velocity.Driver' (OnClassCondition) + + MybatisPlusLanguageDriverAutoConfiguration.ThymeleafConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.mybatis.scripting.thymeleaf.ThymeleafLanguageDriver' (OnClassCondition) + + MybatisPlusLanguageDriverAutoConfiguration.VelocityConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'org.mybatis.scripting.velocity.VelocityLanguageDriver', 'org.mybatis.scripting.velocity.VelocityLanguageDriverConfig' (OnClassCondition) + + Neo4jAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.neo4j.driver.Driver' (OnClassCondition) + + Neo4jDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.neo4j.driver.Driver' (OnClassCondition) + + Neo4jHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.neo4j.driver.Driver' (OnClassCondition) + + Neo4jReactiveDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.neo4j.driver.Driver' (OnClassCondition) + + Neo4jReactiveRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.neo4j.driver.Driver' (OnClassCondition) + + Neo4jRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.neo4j.driver.Driver' (OnClassCondition) + + NewRelicMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.newrelic.NewRelicMeterRegistry' (OnClassCondition) + + NoOpCacheConfiguration: + Did not match: + - Cache org.springframework.boot.autoconfigure.cache.NoOpCacheConfiguration unknown cache type (CacheCondition) + + NoOpMeterRegistryConfiguration: + Did not match: + - @ConditionalOnMissingBean (types: io.micrometer.core.instrument.MeterRegistry; SearchStrategy: all) found beans of type 'io.micrometer.core.instrument.MeterRegistry' simpleMeterRegistry (OnBeanCondition) + + NoopTracerAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.Tracer' (OnClassCondition) + + OAuth2AuthorizationServerAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.oauth2.server.authorization.OAuth2Authorization' (OnClassCondition) + + OAuth2AuthorizationServerJwtAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.oauth2.server.authorization.OAuth2Authorization' (OnClassCondition) + + OAuth2ClientAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.configuration.EnableWebSecurity' (OnClassCondition) + + OAuth2ResourceServerAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.oauth2.server.resource.authentication.BearerTokenAuthenticationToken' (OnClassCondition) + + ObservationAutoConfiguration.MeterObservationHandlerConfiguration.TracingAndMetricsObservationHandlerConfiguration: + Did not match: + - @ConditionalOnBean did not find required type 'io.micrometer.tracing.Tracer' (OnBeanCondition) + - @ConditionalOnBean (types: io.micrometer.tracing.Tracer; SearchStrategy: all) did not find any beans of type io.micrometer.tracing.Tracer (OnBeanCondition) + + ObservationAutoConfiguration.MetricsWithTracingConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.Tracer' (OnClassCondition) + + ObservationAutoConfiguration.OnlyTracingConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.Tracer' (OnClassCondition) + + org.springframework.boot.actuate.autoconfigure.opentelemetry.OpenTelemetryAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.opentelemetry.sdk.OpenTelemetrySdk' (OnClassCondition) + + org.springframework.boot.actuate.autoconfigure.tracing.OpenTelemetryAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.otel.bridge.OtelTracer' (OnClassCondition) + + OtlpAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.otel.bridge.OtelTracer' (OnClassCondition) + + OtlpMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.registry.otlp.OtlpMeterRegistry' (OnClassCondition) + + ProjectInfoAutoConfiguration#buildProperties: + Did not match: + - @ConditionalOnResource did not find resource '${spring.info.build.location:classpath:META-INF/build-info.properties}' (OnResourceCondition) + + ProjectInfoAutoConfiguration#gitProperties: + Did not match: + - GitResource did not find git info at classpath:git.properties (ProjectInfoAutoConfiguration.GitResourceAvailableCondition) + + PrometheusExemplarsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.Tracer' (OnClassCondition) + + PrometheusMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.prometheusmetrics.PrometheusMeterRegistry' (OnClassCondition) + + PrometheusSimpleclientExemplarsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.tracing.Tracer' (OnClassCondition) + + PrometheusSimpleclientMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.prometheus.PrometheusMeterRegistry' (OnClassCondition) + + PulsarAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.apache.pulsar.client.api.PulsarClient' (OnClassCondition) + + PulsarReactiveAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.apache.pulsar.client.api.PulsarClient' (OnClassCondition) + + QuartzAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.quartz.Scheduler' (OnClassCondition) + + QuartzEndpointAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.quartz.Scheduler' (OnClassCondition) + + R2dbcAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.r2dbc.spi.ConnectionFactory' (OnClassCondition) + + R2dbcDataAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.r2dbc.core.R2dbcEntityTemplate' (OnClassCondition) + + R2dbcInitializationConfiguration: + Did not match: + - @ConditionalOnClass did not find required classes 'io.r2dbc.spi.ConnectionFactory', 'org.springframework.r2dbc.connection.init.DatabasePopulator' (OnClassCondition) + + R2dbcObservationAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.r2dbc.proxy.ProxyConnectionFactory' (OnClassCondition) + + R2dbcRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.r2dbc.spi.ConnectionFactory' (OnClassCondition) + + R2dbcTransactionManagerAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.r2dbc.connection.R2dbcTransactionManager' (OnClassCondition) + + RSocketGraphQlClientAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'graphql.GraphQL' (OnClassCondition) + + RSocketMessagingAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.rsocket.RSocket' (OnClassCondition) + + RSocketRequesterAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.rsocket.RSocket' (OnClassCondition) + + RSocketSecurityAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.rsocket.core.SecuritySocketAcceptorInterceptor' (OnClassCondition) + + RSocketServerAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.rsocket.core.RSocketServer' (OnClassCondition) + + RSocketStrategiesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.rsocket.RSocket' (OnClassCondition) + + RabbitAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.rabbitmq.client.Channel' (OnClassCondition) + + RabbitHealthContributorAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.amqp.rabbit.core.RabbitTemplate' (OnClassCondition) + + RabbitMetricsAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.rabbitmq.client.ConnectionFactory' (OnClassCondition) + + ReactiveCloudFoundryActuatorAutoConfiguration: + Did not match: + - @ConditionalOnWebApplication did not find reactive web application classes (OnWebApplicationCondition) + + ReactiveElasticsearchClientAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'co.elastic.clients.transport.ElasticsearchTransport' (OnClassCondition) + + ReactiveElasticsearchRepositoriesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.elasticsearch.client.elc.ReactiveElasticsearchClient' (OnClassCondition) + + ReactiveManagementContextAutoConfiguration: + Did not match: + - @ConditionalOnWebApplication did not find reactive web application classes (OnWebApplicationCondition) + + ReactiveManagementWebSecurityAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity' (OnClassCondition) + + ReactiveMultipartAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.config.WebFluxConfigurer' (OnClassCondition) + + ReactiveOAuth2ClientAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity' (OnClassCondition) + + ReactiveOAuth2ResourceServerAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity' (OnClassCondition) + + ReactiveSecurityAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity' (OnClassCondition) + + ReactiveUserDetailsServiceAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.authentication.ReactiveAuthenticationManager' (OnClassCondition) + + ReactiveWebServerFactoryAutoConfiguration: + Did not match: + - @ConditionalOnWebApplication did not find reactive web application classes (OnWebApplicationCondition) + + RedisAutoConfiguration#redisTemplate: + Did not match: + - @ConditionalOnMissingBean (names: redisTemplate; SearchStrategy: all) found beans named redisTemplate (OnBeanCondition) + + RedisAutoConfiguration#stringRedisTemplate: + Did not match: + - @ConditionalOnMissingBean (types: org.springframework.data.redis.core.StringRedisTemplate; SearchStrategy: all) found beans of type 'org.springframework.data.redis.core.StringRedisTemplate' stringRedisTemplate (OnBeanCondition) + + RedisCacheConfiguration: + Did not match: + - Cache org.springframework.boot.autoconfigure.cache.RedisCacheConfiguration unknown cache type (CacheCondition) + Matched: + - @ConditionalOnClass found required class 'org.springframework.data.redis.connection.RedisConnectionFactory' (OnClassCondition) + + RedisHealthContributorAutoConfiguration#redisHealthContributor: + Did not match: + - @ConditionalOnMissingBean (names: redisHealthIndicator,redisHealthContributor; SearchStrategy: all) found beans named redisHealthContributor (OnBeanCondition) + + RedissonAutoConfiguration#redisTemplate: + Did not match: + - @ConditionalOnMissingBean (names: redisTemplate; SearchStrategy: all) found beans named redisTemplate (OnBeanCondition) + + RepositoryRestMvcAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration' (OnClassCondition) + + SaOAuth2BeanInject: + Did not match: + - @ConditionalOnClass did not find required class 'cn.dev33.satoken.oauth2.SaOAuth2Manager' (OnClassCondition) + + SaOAuth2BeanRegister: + Did not match: + - @ConditionalOnClass did not find required class 'cn.dev33.satoken.oauth2.SaOAuth2Manager' (OnClassCondition) + + SaSsoBeanInject: + Did not match: + - @ConditionalOnClass did not find required class 'cn.dev33.satoken.sso.SaSsoManager' (OnClassCondition) + + SaSsoBeanRegister: + Did not match: + - @ConditionalOnClass did not find required class 'cn.dev33.satoken.sso.SaSsoManager' (OnClassCondition) + + Saml2RelyingPartyAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.saml2.provider.service.registration.RelyingPartyRegistrationRepository' (OnClassCondition) + + SbomEndpointAutoConfiguration#sbomEndpointWebExtension: + Did not match: + - @ConditionalOnAvailableEndpoint no 'management.endpoints' property marked it as exposed (OnAvailableEndpointCondition) + Matched: + - @ConditionalOnBean (types: org.springframework.boot.actuate.sbom.SbomEndpoint; SearchStrategy: all) found bean 'sbomEndpoint'; @ConditionalOnMissingBean (types: org.springframework.boot.actuate.sbom.SbomEndpointWebExtension; SearchStrategy: all) did not find any beans (OnBeanCondition) + + SecurityAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.authentication.DefaultAuthenticationEventPublisher' (OnClassCondition) + + SecurityFilterAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.config.http.SessionCreationPolicy' (OnClassCondition) + + SecurityRequestMatchersManagementContextConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.web.util.matcher.RequestMatcher' (OnClassCondition) + + SendGridAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.sendgrid.SendGrid' (OnClassCondition) + + ServletEndpointManagementContextConfiguration.JerseyServletEndpointManagementContextConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.glassfish.jersey.server.ResourceConfig' (OnClassCondition) + + ServletManagementContextAutoConfiguration.ApplicationContextFilterConfiguration: + Did not match: + - @ConditionalOnProperty (management.server.add-application-context-header=true) did not find property 'add-application-context-header' (OnPropertyCondition) + + ServletWebServerFactoryAutoConfiguration.ForwardedHeaderFilterConfiguration: + Did not match: + - @ConditionalOnProperty (server.forward-headers-strategy=framework) did not find property 'server.forward-headers-strategy' (OnPropertyCondition) + + ServletWebServerFactoryConfiguration.EmbeddedJetty: + Did not match: + - @ConditionalOnClass did not find required classes 'org.eclipse.jetty.server.Server', 'org.eclipse.jetty.util.Loader', 'org.eclipse.jetty.ee10.webapp.WebAppContext' (OnClassCondition) + + ServletWebServerFactoryConfiguration.EmbeddedUndertow: + Did not match: + - @ConditionalOnClass did not find required classes 'io.undertow.Undertow', 'org.xnio.SslClientAuthMode' (OnClassCondition) + + SessionAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.session.Session' (OnClassCondition) + + SessionsEndpointAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.session.Session' (OnClassCondition) + + ShutdownEndpointAutoConfiguration: + Did not match: + - @ConditionalOnAvailableEndpoint no property management.endpoint.shutdown.enabled found so using endpoint default of false (OnAvailableEndpointCondition) + + SignalFxMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.signalfx.SignalFxMeterRegistry' (OnClassCondition) + + SimpleCacheConfiguration: + Did not match: + - Cache org.springframework.boot.autoconfigure.cache.SimpleCacheConfiguration unknown cache type (CacheCondition) + + SpringDocConfiguration#openAPIBuilder: + Did not match: + - @ConditionalOnMissingBean (types: org.springdoc.core.service.OpenAPIService; SearchStrategy: all) found beans of type 'org.springdoc.core.service.OpenAPIService' openApiBuilder (OnBeanCondition) + + SpringDocConfiguration#propertiesResolverForSchema: + Did not match: + - @ConditionalOnProperty (springdoc.api-docs.resolve-schema-properties) did not find property 'springdoc.api-docs.resolve-schema-properties' (OnPropertyCondition) + + SpringDocConfiguration#springdocBeanFactoryPostProcessor2: + Did not match: + - @ConditionalOnMissingClass found unwanted class 'org.springframework.boot.context.properties.bind.BindResult' (OnClassCondition) + + SpringDocConfiguration.SpringDocActuatorConfiguration: + Did not match: + - @ConditionalOnProperty (springdoc.show-actuator) did not find property 'springdoc.show-actuator' (OnPropertyCondition) + Matched: + - @ConditionalOnClass found required class 'org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties' (OnClassCondition) + + SpringDocConfiguration.SpringDocRepositoryRestConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.rest.core.config.RepositoryRestConfiguration' (OnClassCondition) + + SpringDocDataRestConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.data.rest.core.config.RepositoryRestConfiguration' (OnClassCondition) + + SpringDocFunctionCatalogConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.cloud.function.web.function.FunctionEndpointInitializer' (OnClassCondition) + + SpringDocGroovyConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'groovy.lang.MetaClass' (OnClassCondition) + + SpringDocHateoasConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.hateoas.server.LinkRelationProvider' (OnClassCondition) + + SpringDocJacksonKotlinModuleConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.fasterxml.jackson.module.kotlin.KotlinModule' (OnClassCondition) + + SpringDocJavadocConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.github.therapi.runtimejavadoc.CommentFormatter' (OnClassCondition) + + SpringDocKotlinxConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'kotlinx.coroutines.flow.Flow' (OnClassCondition) + + SpringDocSecurityConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.security.web.SecurityFilterChain' (OnClassCondition) + + SpringDocSortConfiguration#delegatingMethodParameterCustomizer: + Did not match: + - @ConditionalOnMissingBean (types: org.springdoc.core.customizers.DelegatingMethodParameterCustomizer; SearchStrategy: all) found beans of type 'org.springdoc.core.customizers.DelegatingMethodParameterCustomizer' delegatingMethodParameterCustomizer (OnBeanCondition) + + SpringDocWebMvcConfiguration.SpringDocWebMvcActuatorConfiguration#actuatorProvider: + Did not match: + - @ConditionalOnExpression (#{${springdoc.show-actuator:false} or ${springdoc.use-management-port:false}}) resulted in false (OnExpressionCondition) + + SpringDocWebMvcConfiguration.SpringDocWebMvcActuatorConfiguration#openApiActuatorResource: + Did not match: + - @ConditionalOnProperty (springdoc.use-management-port) did not find property 'springdoc.use-management-port' (OnPropertyCondition) + + StackdriverMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.stackdriver.StackdriverMeterRegistry' (OnClassCondition) + + StartupEndpointAutoConfiguration: + Did not match: + - ApplicationStartup configured applicationStartup is of type class org.springframework.core.metrics.DefaultApplicationStartup, expected BufferingApplicationStartup. (StartupEndpointAutoConfiguration.ApplicationStartupCondition) + + StatsdMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.micrometer.statsd.StatsdMeterRegistry' (OnClassCondition) + + SwaggerConfig#springWebProvider: + Did not match: + - @ConditionalOnMissingBean (types: org.springdoc.core.providers.SpringWebProvider; SearchStrategy: all) found beans of type 'org.springdoc.core.providers.SpringWebProvider' springWebProvider (OnBeanCondition) + + SwaggerConfig#swaggerUiConfigParameters: + Did not match: + - @ConditionalOnMissingBean (types: org.springdoc.core.properties.SwaggerUiConfigParameters; SearchStrategy: all) found beans of type 'org.springdoc.core.properties.SwaggerUiConfigParameters' org.springdoc.core.properties.SwaggerUiConfigParameters (OnBeanCondition) + + SwaggerConfig#swaggerUiHome: + Did not match: + - @ConditionalOnProperty (springdoc.swagger-ui.use-root-path=true) did not find property 'springdoc.swagger-ui.use-root-path' (OnPropertyCondition) + + SwaggerConfig.SwaggerActuatorWelcomeConfiguration: + Did not match: + - @ConditionalOnProperty (springdoc.use-management-port) did not find property 'springdoc.use-management-port' (OnPropertyCondition) + Matched: + - @ConditionalOnClass found required class 'org.springframework.boot.actuate.endpoint.web.servlet.WebMvcEndpointHandlerMapping' (OnClassCondition) + + TaskExecutorConfigurations.SimpleAsyncTaskExecutorBuilderConfiguration#simpleAsyncTaskExecutorBuilderVirtualThreads: + Did not match: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.SimpleAsyncTaskExecutorBuilder; SearchStrategy: all) found beans of type 'org.springframework.boot.task.SimpleAsyncTaskExecutorBuilder' simpleAsyncTaskExecutorBuilder (OnBeanCondition) + + TaskExecutorConfigurations.TaskExecutorConfiguration: + Did not match: + - @ConditionalOnMissingBean (types: java.util.concurrent.Executor; SearchStrategy: all) found beans of type 'java.util.concurrent.Executor' smart-async-executor (OnBeanCondition) + + TaskSchedulingConfigurations.SimpleAsyncTaskSchedulerBuilderConfiguration#simpleAsyncTaskSchedulerBuilderVirtualThreads: + Did not match: + - @ConditionalOnMissingBean (types: org.springframework.boot.task.SimpleAsyncTaskSchedulerBuilder; SearchStrategy: all) found beans of type 'org.springframework.boot.task.SimpleAsyncTaskSchedulerBuilder' simpleAsyncTaskSchedulerBuilder (OnBeanCondition) + + TaskSchedulingConfigurations.TaskSchedulerConfiguration#taskSchedulerVirtualThreads: + Did not match: + - @ConditionalOnThreading did not find VIRTUAL (OnThreadingCondition) + + ThymeleafAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.thymeleaf.spring6.SpringTemplateEngine' (OnClassCondition) + + TransactionAutoConfiguration#transactionalOperator: + Did not match: + - @ConditionalOnSingleCandidate (types: org.springframework.transaction.ReactiveTransactionManager; SearchStrategy: all) did not find any beans (OnBeanCondition) + + TransactionAutoConfiguration.AspectJTransactionManagementConfiguration: + Did not match: + - @ConditionalOnBean did not find required type 'org.springframework.transaction.aspectj.AbstractTransactionAspect' (OnBeanCondition) + - @ConditionalOnBean (types: org.springframework.transaction.aspectj.AbstractTransactionAspect; SearchStrategy: all) did not find any beans of type org.springframework.transaction.aspectj.AbstractTransactionAspect (OnBeanCondition) + + TransactionAutoConfiguration.EnableTransactionManagementConfiguration: + Did not match: + - @ConditionalOnMissingBean (types: org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration; SearchStrategy: all) found beans of type 'org.springframework.transaction.annotation.AbstractTransactionManagementConfiguration' org.springframework.transaction.annotation.ProxyTransactionManagementConfiguration (OnBeanCondition) + + TransactionAutoConfiguration.EnableTransactionManagementConfiguration.CglibAutoProxyConfiguration: + Did not match: + - Ancestor org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition) + Matched: + - @ConditionalOnProperty (spring.aop.proxy-target-class=true) matched (OnPropertyCondition) + + TransactionAutoConfiguration.EnableTransactionManagementConfiguration.JdkDynamicAutoProxyConfiguration: + Did not match: + - @ConditionalOnProperty (spring.aop.proxy-target-class=false) did not find property 'proxy-target-class' (OnPropertyCondition) + - Ancestor org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration$EnableTransactionManagementConfiguration did not match (ConditionEvaluationReport.AncestorsMatchedCondition) + + WavefrontAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.wavefront.sdk.common.application.ApplicationTags' (OnClassCondition) + + WavefrontMetricsExportAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.wavefront.sdk.common.WavefrontSender' (OnClassCondition) + + WavefrontTracingAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'com.wavefront.sdk.common.WavefrontSender' (OnClassCondition) + + WebClientAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient' (OnClassCondition) + + WebClientObservationConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.function.client.WebClient' (OnClassCondition) + + WebFluxAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.config.WebFluxConfigurer' (OnClassCondition) + + WebFluxEndpointManagementContextConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.reactive.DispatcherHandler' (OnClassCondition) + + WebFluxObservationAutoConfiguration: + Did not match: + - @ConditionalOnWebApplication did not find reactive web application classes (OnWebApplicationCondition) + + WebMvcAutoConfiguration#hiddenHttpMethodFilter: + Did not match: + - @ConditionalOnProperty (spring.mvc.hiddenmethod.filter.enabled) did not find property 'enabled' (OnPropertyCondition) + + WebMvcAutoConfiguration.ProblemDetailsErrorHandlingConfiguration: + Did not match: + - @ConditionalOnProperty (spring.mvc.problemdetails.enabled=true) did not find property 'enabled' (OnPropertyCondition) + + WebMvcAutoConfiguration.ResourceChainCustomizerConfiguration: + Did not match: + - @ConditionalOnEnabledResourceChain did not find class org.webjars.WebJarAssetLocator (OnEnabledResourceChainCondition) + + WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter#beanNameViewResolver: + Did not match: + - @ConditionalOnMissingBean (types: org.springframework.web.servlet.view.BeanNameViewResolver; SearchStrategy: all) found beans of type 'org.springframework.web.servlet.view.BeanNameViewResolver' beanNameViewResolver (OnBeanCondition) + + WebMvcEndpointManagementContextConfiguration#managementHealthEndpointWebMvcHandlerMapping: + Did not match: + - Management Port actual port type (SAME) did not match required type (DIFFERENT) (OnManagementPortCondition) + + WebServiceTemplateAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.ws.client.core.WebServiceTemplate' (OnClassCondition) + + WebServicesAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.ws.transport.http.MessageDispatcherServlet' (OnClassCondition) + + WebSessionIdResolverAutoConfiguration: + Did not match: + - @ConditionalOnWebApplication did not find reactive web application classes (OnWebApplicationCondition) + + WebSocketMessagingAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer' (OnClassCondition) + + WebSocketReactiveAutoConfiguration: + Did not match: + - @ConditionalOnWebApplication did not find reactive web application classes (OnWebApplicationCondition) + + WebSocketServletAutoConfiguration.JettyWebSocketConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketServletContainerInitializer' (OnClassCondition) + + WebSocketServletAutoConfiguration.UndertowWebSocketConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'io.undertow.websockets.jsr.Bootstrap' (OnClassCondition) + + XADataSourceAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'jakarta.transaction.TransactionManager' (OnClassCondition) + + ZipkinAutoConfiguration: + Did not match: + - @ConditionalOnClass did not find required class 'zipkin2.reporter.Encoding' (OnClassCondition) + + +Exclusions: +----------- + + org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration + + +Unconditional classes: +---------------------- + + cn.dev33.satoken.spring.SaTokenContextRegister + + cn.dev33.satoken.spring.SaBeanRegister + + org.springframework.boot.autoconfigure.context.ConfigurationPropertiesAutoConfiguration + + cn.dev33.satoken.dao.SaTokenDaoForRedisTemplate + + org.springframework.boot.actuate.autoconfigure.availability.AvailabilityHealthContributorAutoConfiguration + + org.springframework.boot.autoconfigure.ssl.SslAutoConfiguration + + org.springframework.boot.actuate.autoconfigure.info.InfoContributorAutoConfiguration + + org.springframework.boot.autoconfigure.context.PropertyPlaceholderAutoConfiguration + + org.springframework.boot.autoconfigure.context.LifecycleAutoConfiguration + + org.springframework.boot.actuate.autoconfigure.metrics.integration.IntegrationMetricsAutoConfiguration + + org.springframework.boot.actuate.autoconfigure.endpoint.EndpointAutoConfiguration + + org.springframework.boot.actuate.autoconfigure.web.server.ManagementContextAutoConfiguration + + org.springframework.boot.actuate.autoconfigure.health.HealthContributorAutoConfiguration + + cn.dev33.satoken.spring.SaBeanInject + + org.springframework.boot.actuate.autoconfigure.endpoint.jackson.JacksonEndpointAutoConfiguration + + cn.hutool.extra.spring.SpringUtil + + org.springframework.boot.autoconfigure.availability.ApplicationAvailabilityAutoConfiguration + + org.springframework.boot.autoconfigure.info.ProjectInfoAutoConfiguration + + + (ConditionEvaluationReportLogger.java:72) +[2026-06-02 18:55:04,421][DEBUG][main] Application availability state LivenessState changed to CORRECT (ApplicationAvailabilityBean.java:77) +[2026-06-02 18:55:04,423][DEBUG][main] Application availability state ReadinessState changed to ACCEPTING_TRAFFIC (ApplicationAvailabilityBean.java:77) +[2026-06-02 18:55:04,449][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,449][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,450][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,451][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,451][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,451][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,451][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,451][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,451][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 13, name=org.springframework.boot:type=Admin,name=SpringApplication, attribute=Ready (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,453][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,453][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,453][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@509a49a0: connectionId=rmi://127.0.0.1 13] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,453][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@509a49a0: connectionId=rmi://127.0.0.1 13] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,453][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: accepted socket from [127.0.0.1:57579] (Log.java:228) +[2026-06-02 18:55:04,453][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: accepted socket from [127.0.0.1:57578] (Log.java:228) +[2026-06-02 18:55:04,453][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,454][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,455][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,456][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 14 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,456][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,456][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,456][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 14, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,456][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,456][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@32f22a83: connectionId=rmi://127.0.0.1 14] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@32f22a83: connectionId=rmi://127.0.0.1 14] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,457][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,458][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 15, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@256f2b39: connectionId=rmi://127.0.0.1 15] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@256f2b39: connectionId=rmi://127.0.0.1 15] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,459][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 16, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@95b2347: connectionId=rmi://127.0.0.1 16] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@95b2347: connectionId=rmi://127.0.0.1 16] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,460][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,461][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,461][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 17 unwrapping query with defaultClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,461][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 17, name=org.springframework.boot:type=Endpoint,name=Beans,*, query=java.rmi.MarshalledObject@d (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 17 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,464][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 17, name=org.springframework.boot:type=Endpoint,name=Beans, operationName=beans, signature=[] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,512][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,513][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,513][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@673476f2: connectionId=rmi://127.0.0.1 17] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,513][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@673476f2: connectionId=rmi://127.0.0.1 17] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,514][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,514][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,514][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,514][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,514][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,514][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: accepted socket from [127.0.0.1:57580] (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,515][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,516][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,517][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 20 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 18 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 20, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 18, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,518][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 20 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 20, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,519][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 18 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 18, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 20 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,520][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 18 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 20, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 18, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,521][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 20 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 18 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 18, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 20, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 20 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,522][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 19, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 21, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 18 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 20, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 18, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(4)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@6e1a9f88: connectionId=rmi://127.0.0.1 19] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(4)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@6e1a9f88: connectionId=rmi://127.0.0.1 19] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,523][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 21 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 21, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 20 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 18 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 20, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 18, name=org.springframework.boot:type=Admin,name=SpringApplication, operationName=getProperty, signature=[java.lang.String] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@100b766b: connectionId=rmi://127.0.0.1 21] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@2077aa4c: connectionId=rmi://127.0.0.1 20] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@100b766b: connectionId=rmi://127.0.0.1 21] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,524][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@28a09e37: connectionId=rmi://127.0.0.1 18] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,525][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@28a09e37: connectionId=rmi://127.0.0.1 18] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,525][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@2077aa4c: connectionId=rmi://127.0.0.1 20] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,526][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,526][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,526][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,526][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,527][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.Lease", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 84 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,528][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 23 unwrapping query with defaultClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 22 unwrapping query with defaultClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 24 unwrapping query with defaultClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 23, name=org.springframework.boot:type=Endpoint,name=Mappings,*, query=java.rmi.MarshalledObject@d (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 24, name=org.springframework.boot:type=Endpoint,name=Health,*, query=java.rmi.MarshalledObject@d (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 22, name=org.springframework.boot:type=Endpoint,name=Env,*, query=java.rmi.MarshalledObject@d (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 25 unwrapping query with defaultClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 25, name=org.springframework.boot:type=Endpoint,name=Conditions,*, query=java.rmi.MarshalledObject@d (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,529][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 22 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 23 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(4)-127.0.0.1] connectionId=rmi://127.0.0.1 22, name=org.springframework.boot:type=Endpoint,name=Env, operationName=environment, signature=[] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "javax.management.ObjectName", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 24 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "java.rmi.MarshalledObject", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(3)-127.0.0.1] connectionId=rmi://127.0.0.1 23, name=org.springframework.boot:type=Endpoint,name=Mappings, operationName=mappings, signature=[] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[B", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(2)-127.0.0.1] connectionId=rmi://127.0.0.1 24, name=org.springframework.boot:type=Endpoint,name=Health, operationName=health, signature=[] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "" (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 25 unwrapping params with MBean extended ClassLoader. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: name = "[Ljava.lang.String;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:04,530][DEBUG][RMI TCP Connection(1)-127.0.0.1] connectionId=rmi://127.0.0.1 25, name=org.springframework.boot:type=Endpoint,name=Conditions, operationName=conditions, signature=[] (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,532][DEBUG][RMI TCP Connection(2)-127.0.0.1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:04,535][DEBUG][RMI TCP Connection(3)-127.0.0.1] Detected StandardServletMultipartResolver (DispatcherServlet.java:533) +[2026-06-02 18:55:04,535][DEBUG][RMI TCP Connection(3)-127.0.0.1] Detected AcceptHeaderLocaleResolver (DispatcherServlet.java:557) +[2026-06-02 18:55:04,535][DEBUG][RMI TCP Connection(3)-127.0.0.1] Detected FixedThemeResolver (DispatcherServlet.java:583) +[2026-06-02 18:55:04,535][DEBUG][RMI TCP Connection(2)-127.0.0.1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:04,536][DEBUG][RMI TCP Connection(3)-127.0.0.1] Detected org.springframework.web.servlet.view.DefaultRequestToViewNameTranslator@5b610c90 (DispatcherServlet.java:733) +[2026-06-02 18:55:04,536][DEBUG][RMI TCP Connection(3)-127.0.0.1] Detected org.springframework.web.servlet.support.SessionFlashMapManager@4dc24d88 (DispatcherServlet.java:797) +[2026-06-02 18:55:04,536][DEBUG][RMI TCP Connection(3)-127.0.0.1] enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data (FrameworkServlet.java:549) +[2026-06-02 18:55:04,545][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,545][DEBUG][RMI TCP Connection(4)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@5838d70: connectionId=rmi://127.0.0.1 22] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,546][DEBUG][RMI TCP Connection(4)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@5838d70: connectionId=rmi://127.0.0.1 22] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,567][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,568][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,568][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@3b24ce62: connectionId=rmi://127.0.0.1 25] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,568][DEBUG][RMI TCP Connection(1)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@3b24ce62: connectionId=rmi://127.0.0.1 25] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,576][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 82 (Log.java:228) +[2026-06-02 18:55:04,577][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,577][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@74d7239b: connectionId=rmi://127.0.0.1 23] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,577][DEBUG][RMI TCP Connection(3)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@74d7239b: connectionId=rmi://127.0.0.1 23] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,614][DEBUG][boundedElastic-1] acquired connection for command (INFO) and params [server] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:04,617][DEBUG][redisson-netty-2-2] connection released for command (INFO) and params [server] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@54765504[Completed normally], command=(INFO), params=[server], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:04,624][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:04,624][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@337b99b: connectionId=rmi://127.0.0.1 24] closing. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:04,624][DEBUG][RMI TCP Connection(2)-127.0.0.1] [javax.management.remote.rmi.RMIConnectionImpl@337b99b: connectionId=rmi://127.0.0.1 24] closed. (LoggingProviderImpl.java:230) +[2026-06-02 18:55:08,250][DEBUG][http-nio-1024-exec-1] Loading persistent provider registrations from [/Users/wang/sanduoyun/developspace/smart-flow-master/logs/sa-admin/dev/tomcat-logs/conf/jaspic-providers.xml] (DirectJDKLog.java:173) +[2026-06-02 18:55:08,271][DEBUG][http-nio-1024-exec-1] GET "/login/getLoginInfo", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,274][DEBUG][http-nio-1024-exec-1] Mapped to net.lab1024.sa.admin.module.system.login.controller.LoginController#getLoginInfo() (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,275][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,288][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,289][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3d319d9b[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,290][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,290][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,291][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,291][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4be92c66[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,291][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,304][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:08,532][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: (port 57518) connection closed (Log.java:228) +[2026-06-02 18:55:08,532][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: (port 57518) connection closed (Log.java:228) +[2026-06-02 18:55:08,533][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: (port 57518) connection closed (Log.java:228) +[2026-06-02 18:55:08,532][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: (port 57518) connection closed (Log.java:228) +[2026-06-02 18:55:08,533][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: close connection, socket: Socket[addr=/127.0.0.1,port=57579,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,533][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: close connection, socket: Socket[addr=/127.0.0.1,port=57520,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,533][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: close connection, socket: Socket[addr=/127.0.0.1,port=57578,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,533][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: close connection, socket: Socket[addr=/127.0.0.1,port=57580,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,533][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: accepted socket from [127.0.0.1:57658] (Log.java:228) +[2026-06-02 18:55:08,534][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: (port 57518) op = 80 (Log.java:228) +[2026-06-02 18:55:08,535][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: name = "[Ljava.rmi.server.ObjID;", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:08,535][DEBUG][RMI TCP Connection(4)-127.0.0.1] RMI TCP Connection(4)-127.0.0.1: socket close: Socket[addr=/127.0.0.1,port=57580,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,535][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: name = "java.rmi.server.ObjID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:08,535][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: name = "java.rmi.server.UID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:08,535][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: name = "java.rmi.dgc.VMID", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:08,535][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: name = "[B", codebase = "", defaultLoader = jdk.internal.loader.ClassLoaders$PlatformClassLoader@7188af83 (Log.java:228) +[2026-06-02 18:55:08,535][DEBUG][RMI TCP Connection(3)-127.0.0.1] RMI TCP Connection(3)-127.0.0.1: socket close: Socket[addr=/127.0.0.1,port=57579,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,536][DEBUG][RMI TCP Connection(1)-127.0.0.1] RMI TCP Connection(1)-127.0.0.1: socket close: Socket[addr=/127.0.0.1,port=57520,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,536][DEBUG][RMI TCP Connection(2)-127.0.0.1] RMI TCP Connection(2)-127.0.0.1: socket close: Socket[addr=/127.0.0.1,port=57578,localport=57518] (Log.java:228) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-1] POST "/support/feedback/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-10] POST "/support/changeLog/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-1] Mapped to net.lab1024.sa.base.module.support.feedback.controller.FeedbackController#query(FeedbackQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-5] POST "/oa/notice/employee/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-10] Mapped to net.lab1024.sa.base.module.support.changelog.controller.ChangeLogController#queryPage(ChangeLogQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-5] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#queryEmployeeNotice(NoticeEmployeeQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-9] POST "/oa/notice/employee/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-8] GET "/support/helpDoc/queryHelpDocByRelationId/0", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,644][DEBUG][http-nio-1024-exec-9] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#queryEmployeeNotice(NoticeEmployeeQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,644][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,644][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,643][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,644][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,644][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,645][DEBUG][http-nio-1024-exec-8] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,645][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,645][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,646][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1453bc3d[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,646][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2b929707[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,646][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@248e37e4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,646][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@447ae2e3[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,646][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,647][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,647][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3dddc50b[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,647][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,647][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:08,647][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:08,648][DEBUG][redisson-netty-2-24] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@ec3e208[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,651][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@25d3fa79[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,648][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@b439887[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,651][DEBUG][redisson-netty-2-26] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1f227a36[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,651][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,651][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,651][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6ebe5a57[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:08,652][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,652][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,652][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:08,652][DEBUG][http-nio-1024-exec-5] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:08,652][DEBUG][http-nio-1024-exec-10] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:08,652][DEBUG][http-nio-1024-exec-9] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:08,654][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:08,654][DEBUG][http-nio-1024-exec-8] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:08,820][DEBUG][http-nio-1024-exec-2] GET "/login/getTwoFactorLoginFlag", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,820][DEBUG][http-nio-1024-exec-3] GET "/login/getCaptcha", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:08,820][DEBUG][http-nio-1024-exec-2] Mapped to net.lab1024.sa.admin.module.system.login.controller.LoginController#getTwoFactorLoginFlag() (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,820][DEBUG][http-nio-1024-exec-3] Mapped to net.lab1024.sa.admin.module.system.login.controller.LoginController#getCaptcha() (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:08,861][DEBUG][http-nio-1024-exec-2] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:08,862][DEBUG][http-nio-1024-exec-2] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=false, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:08,875][DEBUG][http-nio-1024-exec-2] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:09,453][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:09,454][DEBUG][http-nio-1024-exec-3] acquired connection for command (SETEX) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...], 65, [51, 50, 48, 51]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:09,457][DEBUG][redisson-netty-2-30] connection released for command (SETEX) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...], 65, [51, 50, 48, 51]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7ef1a8cd[Completed normally], command=(SETEX), params=[[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...], 65, [51, 50, 48, 51]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:09,457][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:09,459][DEBUG][http-nio-1024-exec-3] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:09,460][DEBUG][http-nio-1024-exec-3] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=CaptchaVO(captchaUuid=504aee1c830e4bb1ba3140 (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:09,460][DEBUG][http-nio-1024-exec-3] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:11,015][DEBUG][smart-reload] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:11,016][DEBUG][smart-reload] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@68e483d7] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:11,016][DEBUG][smart-reload] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:11,016][DEBUG][smart-reload] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:11,016][DEBUG][smart-reload] ==> Preparing: SELECT tag,args,identification,update_time,create_time FROM t_reload_item (BaseJdbcLogger.java:135) +[2026-06-02 18:55:11,017][DEBUG][smart-reload] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:11,055][DEBUG][smart-reload] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:11,056][DEBUG][smart-reload] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@68e483d7] (Logger.java:49) +[2026-06-02 18:55:13,286][DEBUG][SmartJobLauncher-0] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:13,286][DEBUG][SmartJobLauncher-0] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@44d2f00d] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:13,286][DEBUG][SmartJobLauncher-0] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:13,286][DEBUG][SmartJobLauncher-0] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:13,287][DEBUG][SmartJobLauncher-0] ==> Preparing: SELECT job_id,job_name,job_class,trigger_type,trigger_value,param,enabled_flag,last_execute_time,last_execute_log_id,remark,sort,deleted_flag,update_name,update_time,create_time FROM t_smart_job (BaseJdbcLogger.java:135) +[2026-06-02 18:55:13,287][DEBUG][SmartJobLauncher-0] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:13,355][DEBUG][SmartJobLauncher-0] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:13,355][DEBUG][SmartJobLauncher-0] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@44d2f00d] (Logger.java:49) +[2026-06-02 18:55:19,317][DEBUG][http-nio-1024-exec-6] POST "/login", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:19,317][DEBUG][http-nio-1024-exec-6] Mapped to net.lab1024.sa.admin.module.system.login.controller.LoginController#login(LoginForm, HttpServletRequest) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:19,337][DEBUG][http-nio-1024-exec-6] Read "application/json;charset=UTF-8" to [LoginForm(loginName=admin, password=NzFlNWI2MjE5ODUyODAxOWM0OTI3ZDhkM2ZkNWY1ODY=, loginDevice=1, ema (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:19,370][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,371][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,373][DEBUG][redisson-netty-2-1] connection released for command (GET) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7378ac72[Completed normally], command=(GET), params=[[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,373][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,373][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,374][DEBUG][http-nio-1024-exec-6] acquired connection for command (DEL) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,374][DEBUG][redisson-netty-2-2] connection released for command (DEL) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2fec5eaa[Completed normally], command=(DEL), params=[[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]], codec=org.redisson.client.codec.LongCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,374][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,374][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:19,375][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3d31b5cd] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:19,375][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:19,375][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:19,375][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT * FROM t_employee WHERE login_name = ? AND deleted_flag = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,380][DEBUG][http-nio-1024-exec-6] ==> Parameters: admin(String), false(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,427][DEBUG][http-nio-1024-exec-6] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,427][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3d31b5cd] (Logger.java:49) +[2026-06-02 18:55:19,431][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA1withDSA, Serial:10, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Sun Microsystems Inc, L=Palo Alto, ST=CA, C=US, Key type:DSA, Length:1024, Cert Id:1776909028, Valid from:2001/4/25 15:00, Valid until:2020/4/25 15:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,431][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA1withDSA, Serial:40:21:68:11, Subject:CN=JCE Code Signing CA, OU=IBM Code Signing, O=IBM Corporation, C=US, Issuer:CN=JCE Code Signing CA, OU=IBM Code Signing, O=IBM Corporation, C=US, Key type:DSA, Length:1024, Cert Id:2468334409, Valid from:2004/2/5 05:45, Valid until:2020/5/27 04:45 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,431][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA256withRSA, Serial:3c:9e:b1:fc:89:f7:33:d3, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:RSA, Length:2048, Cert Id:3044386973, Valid from:2016/7/7 07:48, Valid until:2030/12/31 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,433][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA1withDSA, Serial:37:f9:39:e5, Subject:CN=JCE Development, OU=Java Software, O=Sun Microsystems, L=Cupertino, ST=CA, C=US, Issuer:CN=JCE Development, OU=Java Software, O=Sun Microsystems, L=Cupertino, ST=CA, C=US, Key type:DSA, Length:1024, Cert Id:437846785, Valid from:1999/10/5 07:36, Valid until:2000/10/4 07:36 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,434][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:MD5withRSA, Serial:01, Subject:CN=JCE Development, OU=Java Software, O=Sun Microsystems, L=Cupertino, ST=CA, C=US, Issuer:CN=JCE Development, OU=Java Software, O=Sun Microsystems, L=Cupertino, ST=CA, C=US, Key type:RSA, Length:512, Cert Id:3945841328, Valid from:2002/10/31 23:27, Valid until:2007/10/31 23:27 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,434][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:MD5withRSA, Serial:02, Subject:CN=JCE Development, OU=Java Software, O=Sun Microsystems, L=Cupertino, ST=CA, C=US, Issuer:CN=JCE Development, OU=Java Software, O=Sun Microsystems, L=Cupertino, ST=CA, C=US, Key type:RSA, Length:512, Cert Id:1200127482, Valid from:2002/10/31 23:27, Valid until:2007/10/31 23:27 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,446][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA256withRSA, Serial:3c:9e:b1:fc:89:f7:33:d3, Subject:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:RSA, Length:2048, Cert Id:3044386973, Valid from:2016/7/7 07:48, Valid until:2030/12/31 08:00 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,446][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA256withRSA, Serial:08:87:4f:23:f4:bb:f6:3b:d8:06:a7:ae:b0:a1:2c:f4:67:2b:ba:2a, Subject:CN=Legion of the Bouncy Castle Inc., OU=Java Software Code Signing, O=Oracle Corporation, Issuer:CN=JCE Code Signing CA, OU=Java Software Code Signing, O=Oracle Corporation, Key type:DSA, Length:2048, Cert Id:2266411741, Valid from:2022/1/25 08:58, Valid until:2027/1/25 08:58 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,448][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA256withRSA, Serial:0b:ae:66:bc:5a:ba:7f:95:87:c6:f9:e9:04:e3:33:04, Subject:CN=DigiCert Timestamp 2024, O=DigiCert, C=US, Issuer:CN=DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA, O="DigiCert, Inc.", C=US, Key type:RSA, Length:4096, Cert Id:3934399196, Valid from:2024/9/26 08:00, Valid until:2035/11/26 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,448][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA256withRSA, Serial:07:36:37:b7:24:54:7c:d8:47:ac:fd:28:66:2a:5e:5b, Subject:CN=DigiCert Trusted G4 RSA4096 SHA256 TimeStamping CA, O="DigiCert, Inc.", C=US, Issuer:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:4096, Cert Id:3207540671, Valid from:2022/3/23 08:00, Valid until:2037/3/23 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,448][DEBUG][http-nio-1024-exec-6] X509Certificate: Alg:SHA384withRSA, Serial:0e:9b:18:8e:f9:d0:2d:e7:ef:db:50:e2:08:40:18:5a, Subject:CN=DigiCert Trusted Root G4, OU=www.digicert.com, O=DigiCert Inc, C=US, Issuer:CN=DigiCert Assured ID Root CA, OU=www.digicert.com, O=DigiCert Inc, C=US, Key type:RSA, Length:4096, Cert Id:845088433, Valid from:2022/8/1 08:00, Valid until:2031/11/10 07:59 (LoggingProviderImpl.java:274) +[2026-06-02 18:55:19,616][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:19,616][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40c51b2b] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:19,616][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:19,616][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:19,616][DEBUG][http-nio-1024-exec-6] ==> Preparing: select * from t_login_fail where user_id = ? and user_type = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,617][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long), 1(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,667][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,667][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40c51b2b] (Logger.java:49) +[2026-06-02 18:55:19,729][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,729][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,730][DEBUG][redisson-netty-2-4] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1e94013[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,730][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,740][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,740][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,741][DEBUG][redisson-netty-2-6] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@33702ae7[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,742][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,742][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,742][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 1030592, [123, 34, 64, 99, 108, 97, 115, 115, 34, 58, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,743][DEBUG][redisson-netty-2-8] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 1030592, [123, 34, 64, 99, 108, 97, 115, 115, 34, 58, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2671da77[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 1030592, [123, 34, 64, 99, 108, 97, 115, 115, 34, 58, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,743][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,743][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,743][DEBUG][http-nio-1024-exec-6] acquired connection for command (DEL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,744][DEBUG][redisson-netty-2-10] connection released for command (DEL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@43dc8b34[Completed normally], command=(DEL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.LongCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,744][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,744][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,744][DEBUG][http-nio-1024-exec-6] acquired connection for command (DEL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,744][DEBUG][redisson-netty-2-12] connection released for command (DEL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4ef89b3e[Completed normally], command=(DEL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.LongCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,744][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,744][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,744][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,745][DEBUG][redisson-netty-2-14] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@ce7c10c[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,745][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,745][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,745][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 1030592, [45, 52]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,745][DEBUG][redisson-netty-2-16] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 1030592, [45, 52]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2c9986cf[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 1030592, [45, 52]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,745][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,746][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,746][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,746][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7e6b7522[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,746][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,746][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,746][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,747][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@fce5352[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,747][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,747][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,747][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,747][DEBUG][redisson-netty-2-6] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5e74f2d6[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,747][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,748][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,748][DEBUG][http-nio-1024-exec-6] acquired connection for command (PEXPIRE) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000000] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,748][DEBUG][redisson-netty-2-8] connection released for command (PEXPIRE) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000000] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@46fa340d[Completed normally], command=(PEXPIRE), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000000], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,748][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,749][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,749][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,750][DEBUG][redisson-netty-2-16] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@492369e2[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,750][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,750][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,750][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [123, 34, 64, 99, 108, 97, 115, 115, 34, 58, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,750][DEBUG][redisson-netty-2-10] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [123, 34, 64, 99, 108, 97, 115, 115, 34, 58, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@78aa5b37[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [123, 34, 64, 99, 108, 97, 115, 115, 34, 58, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,750][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,750][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,750][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [49, 58, 49]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,751][DEBUG][redisson-netty-2-14] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [49, 58, 49]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6e8ab4f4[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [49, 58, 49]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,751][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,751][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,751][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [49, 55, 56, 48, 51, 57, 55, 55, 49, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,751][DEBUG][redisson-netty-2-12] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [49, 55, 56, 48, 51, 57, 55, 55, 49, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5c637853[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2592000, [49, 55, 56, 48, 51, 57, 55, 55, 49, 57, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,751][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,751][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,751][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,752][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6a6a812d[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,752][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,752][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:19,752][DEBUG][http-nio-1024-exec-6] acquired connection for command (DEL) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:19,752][DEBUG][redisson-netty-2-24] connection released for command (DEL) and params [[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@21d26293[Completed normally], command=(DEL), params=[[115, 97, 45, 97, 100, 109, 105, 110, 58, 100, ...]], codec=org.redisson.client.codec.LongCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:19,752][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:19,757][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:19,757][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6475e296] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:19,758][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:19,758][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:19,758][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT t_department.*, t_employee.actual_name as managerName, parent_department.name as parentName FROM t_department left join t_employee on t_department.manager_id = t_employee.employee_id left join t_department parent_department on t_department.parent_id = parent_department.department_id order by sort desc (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,760][DEBUG][http-nio-1024-exec-6] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,822][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,822][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6475e296] (Logger.java:49) +[2026-06-02 18:55:19,823][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:19,823][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ab6d13d] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:19,823][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:19,823][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:19,823][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT t_role.* FROM t_role_employee left join t_role on t_role_employee.role_id = t_role.role_id WHERE t_role_employee.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,823][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,870][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,870][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ab6d13d] (Logger.java:49) +[2026-06-02 18:55:19,872][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:19,872][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@123a961c] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:19,872][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:19,872][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:19,872][DEBUG][http-nio-1024-exec-6] ==> Preparing: delete from t_login_fail where user_id = ? and user_type = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,879][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long), 1(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,921][DEBUG][http-nio-1024-exec-6] <== Updates: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,922][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@123a961c] (Logger.java:49) +[2026-06-02 18:55:19,922][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:19,922][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@771c492c] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:19,922][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:19,922][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:19,922][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT t_role.* FROM t_role_employee left join t_role on t_role_employee.role_id = t_role.role_id WHERE t_role_employee.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,923][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,971][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,972][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@771c492c] (Logger.java:49) +[2026-06-02 18:55:19,972][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:19,972][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14001fb5] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:19,977][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:19,978][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:19,978][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT distinct t_menu.* from t_menu left join t_role_menu on t_role_menu.menu_id = t_menu.menu_id WHERE t_menu.deleted_flag = ? ORDER BY t_menu.sort ASC (BaseJdbcLogger.java:135) +[2026-06-02 18:55:19,978][DEBUG][http-nio-1024-exec-6] ==> Parameters: false(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,081][DEBUG][http-nio-1024-exec-6] <== Total: 133 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,081][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@14001fb5] (Logger.java:49) +[2026-06-02 18:55:20,085][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,085][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69806bac] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,086][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,086][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,086][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT t_role.* FROM t_role_employee left join t_role on t_role_employee.role_id = t_role.role_id WHERE t_role_employee.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,086][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,141][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,141][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@69806bac] (Logger.java:49) +[2026-06-02 18:55:20,142][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,142][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@20bc0eac] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,142][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,142][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,142][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,142][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,189][DEBUG][http-nio-1024-exec-6] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,189][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@20bc0eac] (Logger.java:49) +[2026-06-02 18:55:20,189][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,189][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7447888f] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,190][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,190][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,190][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT distinct t_menu.* from t_menu left join t_role_menu on t_role_menu.menu_id = t_menu.menu_id WHERE t_menu.deleted_flag = ? ORDER BY t_menu.sort ASC (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,190][DEBUG][http-nio-1024-exec-6] ==> Parameters: false(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,241][DEBUG][http-nio-1024-exec-6] <== Total: 133 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,242][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7447888f] (Logger.java:49) +[2026-06-02 18:55:20,244][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,244][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d14979c] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,244][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,244][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,244][DEBUG][http-nio-1024-exec-6] ==> Preparing: select * from t_login_log where user_id = ? and user_type = ? and login_result = ? order by login_log_id desc limit 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,246][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long), 1(Integer), 0(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,287][DEBUG][http-nio-1024-exec-6] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,287][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@d14979c] (Logger.java:49) +[2026-06-02 18:55:20,287][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,287][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@444f1695] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,288][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,288][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,288][DEBUG][http-nio-1024-exec-6] ==> Preparing: select * from t_password_log where user_id = ? and user_type = ? order by id desc limit 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,288][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long), 1(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,324][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,324][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@444f1695] (Logger.java:49) +[2026-06-02 18:55:20,324][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,324][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,325][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6b48bbf8[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,325][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,325][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,325][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,326][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@15024340[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,326][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,329][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,329][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@57aeb895] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,330][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,330][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,330][DEBUG][http-nio-1024-exec-6] ==> Preparing: INSERT INTO t_login_log ( user_id, user_type, user_name, login_ip, login_ip_region, user_agent, remark, login_device, login_result, create_time ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,332][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long), 1(Integer), 管理员(String), 127.0.0.1(String), (String), Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36(String), (String), 电脑端(String), 0(Integer), 2026-06-02T18:55:20.328905(LocalDateTime) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,382][DEBUG][http-nio-1024-exec-6] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,383][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@57aeb895] (Logger.java:49) +[2026-06-02 18:55:20,408][DEBUG][http-nio-1024-exec-6] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,409][DEBUG][smart-operate-log1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,409][DEBUG][smart-operate-log1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@758e0b8f] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,409][DEBUG][http-nio-1024-exec-6] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=LoginResultVO(token=769d485013454588bae06839 (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,410][DEBUG][smart-operate-log1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,410][DEBUG][smart-operate-log1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,410][DEBUG][smart-operate-log1] ==> Preparing: INSERT INTO t_operate_log ( operate_user_id, operate_user_type, operate_user_name, operate_user_account, operate_user_role, module, content, url, method, http_method, operation_type, param, ip, ip_region, user_agent, device_info, os_info, response_result, success_flag ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,411][DEBUG][smart-operate-log1] ==> Parameters: 0(Long), 0(Integer), 匿名(String), (String), (String), 系统-员工登录(String), 登录 @author 卓大(String), /login(String), net.lab1024.sa.admin.module.system.login.controller.LoginController.login(String), POST(String), OTHER(String), [{"captchaCode":"3203","password":"***","loginName":"admin","loginDevice":1,"captchaUuid":"504aee1c830e4bb1ba314040fef4dfa1"}](String), 127.0.0.1(String), (String), Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36(String), Chrome 148.0.0.0(String), macOS 10.15.7(String), {"msg":"操作成功","code":0,"data":{"administratorFlag":true,"departmentName":"","loginAccount":"admin","menuList":[{"createUserId":1,"updateUserId":1,"apiPerms":"system:menu:batchDelete","disabledFlag":false,"menuName":"删除","updateTime":1696673750000,"frameFlag":false,"parentId":26,"contextMenuId":26,"cacheFlag":false,"createTime":1628732756000,"permsType":1,"menuId":40,"menuType":3,"webPerms":"system:menu:batchDelete","visibleFlag":true},{"createUserId":1,"disabledFlag":false,"icon":"ClearOutlined","menuName":"组件演示","updateTime":1653059806000,"frameFlag":false,"parentId":84,"path":"/demonstration/index","component":"/support/demonstration/index.vue","cacheFlag":false,"createTime":1653059806000,"menuId":85,"menuType":2,"visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:employee:add","disabledFlag":false,"menuName":"添加员工","updateTime":1696674466000,"frameFlag":false,"parentId":46,"cacheFlag":false,"createTime":1653581498000,"permsType":1,"menuId":91,"menuType":3,"webPerms":"system:employee:add","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:employee:update","disabledFlag":false,"menuName":"编辑员工","updateTime":1696674469000,"frameFlag":false,"parentId":46,"cacheFlag":false,"createTime":1653581530000,"permsType":1,"menuId":92,"menuType":3,"webPerms":"system:employee:update","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:employee:disabled","disabledFlag":false,"menuName":"禁用启用员工","updateTime":1696674473000,"frameFlag":false,"parentId":46,"cacheFlag":false,"createTime":1653581557000,"permsType":1,"menuId":93,"menuType":3,"webPerms":"system:employee:disabled","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:employee:department:update","disabledFlag":false,"menuName":"调整员工部门","updateTime":1696674454000,"frameFlag":false,"parentId":46,"cacheFlag":false,"createTime":1653581579000,"permsType":1,"menuId":94,"menuType":3,"webPerms":"system:employee:department:update","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:employee:password:reset","disabledFlag":false,"menuName":"重置密码","updateTime":1696674477000,"frameFlag":false,"parentId":46,"cacheFlag":false,"createTime":1653581610000,"permsType":1,"menuId":95,"menuType":3,"webPerms":"system:employee:password:reset","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:employee:delete","disabledFlag":false,"menuName":"删除员工","updateTime":1696674481000,"frameFlag":false,"parentId":46,"cacheFlag":false,"createTime":1653581648000,"permsType":1,"menuId":96,"menuType":3,"webPerms":"system:employee:delete","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:role:add","disabledFlag":false,"menuName":"添加角色","updateTime":1696675351000,"frameFlag":false,"parentId":76,"cacheFlag":false,"createTime":1653582840000,"permsType":1,"menuId":97,"menuType":3,"webPerms":"system:role:add","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:role:delete","disabledFlag":false,"menuName":"删除角色","updateTime":1696675355000,"frameFlag":false,"parentId":76,"cacheFlag":false,"createTime":1653582859000,"permsType":1,"menuId":98,"menuType":3,"webPerms":"system:role:delete","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:role:update","disabledFlag":false,"menuName":"编辑角色","updateTime":1696675364000,"frameFlag":false,"parentId":76,"cacheFlag":false,"createTime":1653582895000,"permsType":1,"menuId":99,"menuType":3,"webPerms":"system:role:update","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:role:dataScope:update","disabledFlag":false,"menuName":"更新数据范围","updateTime":1696675309000,"frameFlag":false,"parentId":76,"cacheFlag":false,"createTime":1653583023000,"permsType":1,"menuId":100,"menuType":3,"webPerms":"system:role:dataScope:update","visibleFlag":true},{"createUserId":1,"updateUserId":1,"apiPerms":"system:role:employee:batch:delete","disabledFlag":false,"menuName":"批量移除员工","up...(truncated)(String), true(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,415][DEBUG][http-nio-1024-exec-6] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,425][DEBUG][http-nio-1024-exec-10] GET "/support/dict/getAllDictData", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:20,425][DEBUG][http-nio-1024-exec-1] GET "/support/message/getUnreadCount", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:20,426][DEBUG][http-nio-1024-exec-10] Mapped to net.lab1024.sa.admin.module.system.support.AdminDictController#getAll() (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:20,426][DEBUG][http-nio-1024-exec-1] Mapped to net.lab1024.sa.base.module.support.message.controller.MessageController#getUnreadCount() (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:20,426][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,426][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,426][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,426][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,427][DEBUG][redisson-netty-2-26] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4b8da92f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,427][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@388f12d9[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,427][DEBUG][redisson-netty-2-30] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@44e5983e[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,427][DEBUG][redisson-netty-2-1] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3f57e20f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,427][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,428][DEBUG][redisson-netty-2-4] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4247aed3[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,428][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4aef69a2[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-1] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-10] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,428][DEBUG][redisson-netty-2-8] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4472baa8[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,428][DEBUG][redisson-netty-2-6] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@28ddd14d[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-10] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,428][DEBUG][http-nio-1024-exec-1] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,429][DEBUG][redisson-netty-2-10] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@696e0aa3[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,429][DEBUG][redisson-netty-2-12] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7ecb2477[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,429][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,429][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,431][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,431][DEBUG][http-nio-1024-exec-1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,431][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5c7e7817] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,431][DEBUG][http-nio-1024-exec-1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@be0b3] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,432][DEBUG][http-nio-1024-exec-1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,432][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,432][DEBUG][http-nio-1024-exec-1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,432][DEBUG][http-nio-1024-exec-1] ==> Preparing: SELECT count(1) FROM t_message where receiver_user_type = ? AND receiver_user_id = ? AND read_flag = false (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,432][DEBUG][http-nio-1024-exec-1] ==> Parameters: 1(Integer), 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,478][DEBUG][smart-operate-log1] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,479][DEBUG][smart-operate-log1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@758e0b8f] (Logger.java:49) +[2026-06-02 18:55:20,479][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,479][DEBUG][http-nio-1024-exec-10] ==> Preparing: select t_dict_data.*, t_dict.dict_code from t_dict_data left join t_dict on t_dict_data.dict_id = t_dict.dict_id order by t_dict_data.sort_order desc (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,479][DEBUG][http-nio-1024-exec-10] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,481][DEBUG][http-nio-1024-exec-1] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,481][DEBUG][http-nio-1024-exec-1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@be0b3] (Logger.java:49) +[2026-06-02 18:55:20,481][DEBUG][http-nio-1024-exec-1] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,481][DEBUG][http-nio-1024-exec-1] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=0, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,482][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,518][DEBUG][http-nio-1024-exec-10] <== Total: 7 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,518][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5c7e7817] (Logger.java:49) +[2026-06-02 18:55:20,520][DEBUG][http-nio-1024-exec-10] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,520][DEBUG][http-nio-1024-exec-10] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[DictDataVO(dictDataId=2, dictId=1, dictCode (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,521][DEBUG][http-nio-1024-exec-10] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,683][DEBUG][http-nio-1024-exec-6] POST "/oa/notice/employee/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:20,683][DEBUG][http-nio-1024-exec-4] GET "/support/helpDoc/queryHelpDocByRelationId/0", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:20,683][DEBUG][http-nio-1024-exec-6] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#queryEmployeeNotice(NoticeEmployeeQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:20,683][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,683][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,684][DEBUG][http-nio-1024-exec-4] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:20,684][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,684][DEBUG][http-nio-1024-exec-7] POST "/support/feedback/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:20,684][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,684][DEBUG][http-nio-1024-exec-2] POST "/support/changeLog/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:20,684][DEBUG][http-nio-1024-exec-1] POST "/oa/notice/employee/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:20,685][DEBUG][http-nio-1024-exec-2] Mapped to net.lab1024.sa.base.module.support.changelog.controller.ChangeLogController#queryPage(ChangeLogQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:20,685][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,685][DEBUG][http-nio-1024-exec-7] Mapped to net.lab1024.sa.base.module.support.feedback.controller.FeedbackController#query(FeedbackQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:20,685][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,686][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,686][DEBUG][http-nio-1024-exec-1] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#queryEmployeeNotice(NoticeEmployeeQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:20,686][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,686][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,685][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,686][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@610dd31b[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,687][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,687][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,687][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,687][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@71a4220[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,688][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@101a2af2[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,688][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,688][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@561c7e21[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,688][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@164aff96[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,688][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,688][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,688][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,689][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6cf86233[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,689][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,690][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,690][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,690][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7a109097[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,690][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5e184a92[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,690][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,690][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@ea1b4aa[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,691][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2baf1d5d[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,692][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,691][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,691][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@53a1c74[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,692][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,692][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,692][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,692][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,693][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5b1b78e4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,693][DEBUG][redisson-netty-2-26] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6b9d2943[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,693][DEBUG][redisson-netty-2-24] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2bfceaa5[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,693][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4d9fec29[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,693][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@447085e3[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,693][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,693][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,693][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,693][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,693][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,693][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,693][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-4] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-2] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-1] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,694][DEBUG][http-nio-1024-exec-7] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,696][DEBUG][redisson-netty-2-1] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@262aeb34[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,696][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,696][DEBUG][redisson-netty-2-30] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@478bc86d[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,696][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,696][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,696][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,696][DEBUG][http-nio-1024-exec-2] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,696][DEBUG][redisson-netty-2-2] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5b9efafb[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,697][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,696][DEBUG][redisson-netty-2-4] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3199dea1[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,696][DEBUG][http-nio-1024-exec-7] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,697][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,697][DEBUG][redisson-netty-2-8] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@477e91f9[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,697][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,697][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,697][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:20,697][DEBUG][http-nio-1024-exec-4] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,697][DEBUG][http-nio-1024-exec-1] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:20,698][DEBUG][redisson-netty-2-12] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2104427d[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,698][DEBUG][redisson-netty-2-6] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@560bd605[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,699][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,699][DEBUG][redisson-netty-2-10] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5d3231ca[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,699][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,699][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,699][DEBUG][redisson-netty-2-14] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6c451ffc[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591999, [49, 55, 56, 48, 51, 57, 55, 55, 50, 48, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:20,700][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:20,701][DEBUG][http-nio-1024-exec-4] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,701][DEBUG][http-nio-1024-exec-4] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@58aaa7a6] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,701][DEBUG][http-nio-1024-exec-4] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,701][DEBUG][http-nio-1024-exec-4] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,702][DEBUG][http-nio-1024-exec-4] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,702][DEBUG][http-nio-1024-exec-4] ==> Parameters: 0(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,704][DEBUG][http-nio-1024-exec-6] Read "application/json;charset=UTF-8" to [NoticeEmployeeQueryForm(keywords=null, noticeTypeId=1, publishTimeBegin=null, notViewFlag=null, publ (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,704][DEBUG][http-nio-1024-exec-7] Read "application/json;charset=UTF-8" to [FeedbackQueryForm(searchWord=null, startDate=null, endDate=null)] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,706][DEBUG][http-nio-1024-exec-2] Read "application/json;charset=UTF-8" to [ChangeLogQueryForm(type=null, keyword=null, publicDateBegin=null, publicDateEnd=null, createTime=nul (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,706][DEBUG][http-nio-1024-exec-1] Read "application/json;charset=UTF-8" to [NoticeEmployeeQueryForm(keywords=null, noticeTypeId=2, publishTimeBegin=null, notViewFlag=null, publ (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,726][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,726][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,727][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,728][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3dcdf6ef] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,728][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@33bb6466] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,730][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,730][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f3ab0fc] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,726][DEBUG][http-nio-1024-exec-1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,730][DEBUG][http-nio-1024-exec-1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@31fbb87e] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,731][DEBUG][http-nio-1024-exec-1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,731][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,731][DEBUG][http-nio-1024-exec-6] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,732][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,733][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,750][DEBUG][http-nio-1024-exec-4] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,750][DEBUG][http-nio-1024-exec-4] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@58aaa7a6] (Logger.java:49) +[2026-06-02 18:55:20,750][DEBUG][http-nio-1024-exec-1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,751][DEBUG][http-nio-1024-exec-1] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,751][DEBUG][http-nio-1024-exec-4] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,751][DEBUG][http-nio-1024-exec-1] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,751][DEBUG][http-nio-1024-exec-4] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,752][DEBUG][http-nio-1024-exec-4] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,776][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,797][DEBUG][http-nio-1024-exec-6] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,797][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3dcdf6ef] (Logger.java:49) +[2026-06-02 18:55:20,797][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,798][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,798][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@48491557] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,799][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,799][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT * FROM t_change_log order by t_change_log.version desc LIMIT ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,800][DEBUG][http-nio-1024-exec-2] ==> Parameters: 8(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-1] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@31fbb87e] (Logger.java:49) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@781ad253] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT COUNT(*) AS total FROM t_feedback (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,802][DEBUG][http-nio-1024-exec-7] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,853][DEBUG][http-nio-1024-exec-2] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,853][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@f3ab0fc] (Logger.java:49) +[2026-06-02 18:55:20,854][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,854][DEBUG][http-nio-1024-exec-6] ==> Preparing: select t_notice.notice_id, t_notice.notice_type_id, t_notice.title, t_notice.all_visible_flag, t_notice.scheduled_publish_flag, t_notice.publish_time, t_notice.content_text, t_notice.content_html, t_notice.attachment, t_notice.page_view_count, t_notice.user_view_count, t_notice.source, t_notice.author, t_notice.document_number, t_notice.instance_id, t_notice.node_name, t_notice.flow_status, t_notice.deleted_flag, t_notice.create_user_id, t_notice.update_time, t_notice.create_time , t_notice_type.notice_type_name, (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = ? and t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag from t_notice left join t_notice_type on t_notice.notice_type_id = t_notice_type.notice_type_id WHERE t_notice.deleted_flag = ? and t_notice.publish_time < now() AND t_notice_type.notice_type_id = ? order by t_notice.publish_time desc LIMIT ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,858][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long), false(Boolean), 1(Long), 6(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,859][DEBUG][smart-operate-log1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:20,859][DEBUG][smart-operate-log1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b49fb4e] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:20,859][DEBUG][http-nio-1024-exec-2] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,859][DEBUG][http-nio-1024-exec-2] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=8, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,860][DEBUG][smart-operate-log1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:20,860][DEBUG][http-nio-1024-exec-7] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,861][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@33bb6466] (Logger.java:49) +[2026-06-02 18:55:20,861][DEBUG][http-nio-1024-exec-1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,861][DEBUG][http-nio-1024-exec-1] ==> Preparing: select t_notice.notice_id, t_notice.notice_type_id, t_notice.title, t_notice.all_visible_flag, t_notice.scheduled_publish_flag, t_notice.publish_time, t_notice.content_text, t_notice.content_html, t_notice.attachment, t_notice.page_view_count, t_notice.user_view_count, t_notice.source, t_notice.author, t_notice.document_number, t_notice.instance_id, t_notice.node_name, t_notice.flow_status, t_notice.deleted_flag, t_notice.create_user_id, t_notice.update_time, t_notice.create_time , t_notice_type.notice_type_name, (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = ? and t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag from t_notice left join t_notice_type on t_notice.notice_type_id = t_notice_type.notice_type_id WHERE t_notice.deleted_flag = ? and t_notice.publish_time < now() AND t_notice_type.notice_type_id = ? order by t_notice.publish_time desc LIMIT ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,861][DEBUG][http-nio-1024-exec-2] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,862][DEBUG][http-nio-1024-exec-1] ==> Parameters: 1(Long), false(Boolean), 2(Long), 6(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,863][DEBUG][http-nio-1024-exec-7] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,863][DEBUG][http-nio-1024-exec-7] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=20, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,863][DEBUG][http-nio-1024-exec-7] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,913][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,913][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@48491557] (Logger.java:49) +[2026-06-02 18:55:20,913][DEBUG][smart-operate-log1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:20,913][DEBUG][smart-operate-log1] ==> Preparing: INSERT INTO t_operate_log ( operate_user_id, operate_user_type, operate_user_name, operate_user_account, operate_user_role, module, content, url, method, http_method, operation_type, param, ip, ip_region, user_agent, device_info, os_info, response_result, success_flag ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,913][DEBUG][smart-operate-log1] ==> Parameters: 1(Long), 1(Integer), 管理员(String), admin(String), (String), 业务支撑-更新日志(String), 分页查询 @author 卓大(String), /support/changeLog/queryPage(String), net.lab1024.sa.base.module.support.changelog.controller.ChangeLogController.queryPage(String), POST(String), UPDATE(String), [{"searchCount":false,"pageSize":8,"pageNum":1}](String), 127.0.0.1(String), (String), Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36(String), Chrome 148.0.0.0(String), macOS 10.15.7(String), {"msg":"操作成功","code":0,"data":{"total":0,"pages":0,"pageSize":8,"list":[],"pageNum":1,"emptyFlag":true},"dataType":1,"ok":true}(String), true(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,915][DEBUG][http-nio-1024-exec-6] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,915][DEBUG][http-nio-1024-exec-6] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=6, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,915][DEBUG][http-nio-1024-exec-6] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,916][DEBUG][http-nio-1024-exec-1] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,917][DEBUG][http-nio-1024-exec-1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@781ad253] (Logger.java:49) +[2026-06-02 18:55:20,917][DEBUG][http-nio-1024-exec-1] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:20,917][DEBUG][http-nio-1024-exec-1] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=6, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:20,917][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:20,965][DEBUG][smart-operate-log1] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:20,965][DEBUG][smart-operate-log1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7b49fb4e] (Logger.java:49) +[2026-06-02 18:55:28,329][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: (port 57518) connection closed (Log.java:228) +[2026-06-02 18:55:28,329][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: close connection, socket: Socket[addr=/127.0.0.1,port=57658,localport=57518] (Log.java:228) +[2026-06-02 18:55:28,329][DEBUG][RMI TCP Connection(5)-127.0.0.1] RMI TCP Connection(5)-127.0.0.1: socket close: Socket[addr=/127.0.0.1,port=57658,localport=57518] (Log.java:228) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-6] GET "/support/helpDoc/queryHelpDocByRelationId/132", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-2] GET "/oa/noticeType/getAll", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-7] POST "/oa/notice/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-4] GET "/support/tableColumn/getColumns/30001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-7] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#query(NoticeQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-2] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#getAll() (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-4] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-6] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,502][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,503][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6eeef44f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,503][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@282fa724[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,503][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2b58addc[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,503][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@26b76619[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,503][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,505][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3cd0ec09[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,505][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@50339f47[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,505][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@776bbab8[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,505][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@57532b94[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,505][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,506][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7ed4dd7f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,506][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@666207ee[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,506][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@c2e3bf5[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,506][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4c8b54a0[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-4] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-2] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,506][DEBUG][http-nio-1024-exec-7] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,507][DEBUG][redisson-netty-2-28] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1a90a1a8[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,507][DEBUG][redisson-netty-2-26] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3025213d[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,507][DEBUG][redisson-netty-2-24] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7ca61314[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,507][DEBUG][redisson-netty-2-1] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@66cd0cca[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-2] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-4] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,507][DEBUG][http-nio-1024-exec-7] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,508][DEBUG][redisson-netty-2-4] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7cbfa183[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,508][DEBUG][redisson-netty-2-2] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1724b914[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,508][DEBUG][redisson-netty-2-30] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@69d760ad[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,508][DEBUG][redisson-netty-2-8] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1c5c813[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,508][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,508][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,508][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,508][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,509][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:32,509][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5134950f] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:32,509][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:32,509][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:32,510][DEBUG][http-nio-1024-exec-6] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,510][DEBUG][http-nio-1024-exec-4] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:32,510][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:32,510][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3890cd60] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:32,510][DEBUG][http-nio-1024-exec-4] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@64cd59b9] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:32,512][DEBUG][http-nio-1024-exec-4] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:32,513][DEBUG][http-nio-1024-exec-4] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:32,513][DEBUG][http-nio-1024-exec-4] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,514][DEBUG][http-nio-1024-exec-6] ==> Parameters: 132(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,514][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:32,514][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:32,514][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT notice_type_id,notice_type_name,update_time,create_time FROM t_notice_type (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,515][DEBUG][http-nio-1024-exec-2] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,516][DEBUG][http-nio-1024-exec-4] ==> Parameters: 1(Long), 30001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,519][DEBUG][http-nio-1024-exec-7] Read "application/json;charset=UTF-8" to [NoticeQueryForm(noticeTypeId=null, keywords=, documentNumber=, createUserName=null, nodeName=null, f (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:32,524][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:32,524][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62761436] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:32,533][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:32,551][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,551][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5134950f] (Logger.java:49) +[2026-06-02 18:55:32,551][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:32,551][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT COUNT(*) AS total FROM t_notice (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,552][DEBUG][http-nio-1024-exec-7] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,552][DEBUG][http-nio-1024-exec-6] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:32,552][DEBUG][http-nio-1024-exec-6] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:32,552][DEBUG][http-nio-1024-exec-6] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:32,552][DEBUG][http-nio-1024-exec-2] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,553][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3890cd60] (Logger.java:49) +[2026-06-02 18:55:32,553][DEBUG][http-nio-1024-exec-2] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:32,553][DEBUG][http-nio-1024-exec-2] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:32,553][DEBUG][http-nio-1024-exec-2] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:32,559][DEBUG][http-nio-1024-exec-4] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,559][DEBUG][http-nio-1024-exec-4] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@64cd59b9] (Logger.java:49) +[2026-06-02 18:55:32,559][DEBUG][http-nio-1024-exec-4] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:32,559][DEBUG][http-nio-1024-exec-4] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:32,559][DEBUG][http-nio-1024-exec-4] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:32,560][DEBUG][http-nio-1024-exec-1] GET "/support/tableColumn/getColumns/30001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:32,561][DEBUG][http-nio-1024-exec-1] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:32,561][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,561][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,562][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4df1ae50[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,562][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,562][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,562][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,563][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@412d6fc9[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,563][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,563][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,563][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,563][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6e498de4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,563][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,563][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,563][DEBUG][http-nio-1024-exec-1] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,564][DEBUG][redisson-netty-2-14] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5849bf6e[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,564][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,564][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:32,564][DEBUG][http-nio-1024-exec-1] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:32,564][DEBUG][redisson-netty-2-2] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@56534229[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591987, [49, 55, 56, 48, 51, 57, 55, 55, 51, 50, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:32,564][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:32,564][DEBUG][http-nio-1024-exec-1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:32,565][DEBUG][http-nio-1024-exec-1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5aff4999] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:32,565][DEBUG][http-nio-1024-exec-1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:32,565][DEBUG][http-nio-1024-exec-1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:32,565][DEBUG][http-nio-1024-exec-1] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,565][DEBUG][http-nio-1024-exec-1] ==> Parameters: 1(Long), 30001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,594][DEBUG][http-nio-1024-exec-7] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,594][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@62761436] (Logger.java:49) +[2026-06-02 18:55:32,596][DEBUG][http-nio-1024-exec-7] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:32,596][DEBUG][http-nio-1024-exec-7] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=10, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:32,597][DEBUG][http-nio-1024-exec-7] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:32,608][DEBUG][http-nio-1024-exec-1] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:32,608][DEBUG][http-nio-1024-exec-1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5aff4999] (Logger.java:49) +[2026-06-02 18:55:32,609][DEBUG][http-nio-1024-exec-1] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:32,609][DEBUG][http-nio-1024-exec-1] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:32,609][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:33,321][DEBUG][http-nio-1024-exec-8] GET "/support/helpDoc/queryHelpDocByRelationId/257", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:33,321][DEBUG][http-nio-1024-exec-10] POST "/leave/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:33,321][DEBUG][http-nio-1024-exec-10] Mapped to net.lab1024.sa.admin.module.business.oa.leave.controller.LeaveController#queryPage(LeaveQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:33,322][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,322][DEBUG][http-nio-1024-exec-8] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:33,322][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,322][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,322][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,322][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@cfd50a6[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,322][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@698ea2f1[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,323][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3318483a[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,323][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6a094f8e[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,323][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,324][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@10232c92[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,324][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2e03dbe2[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,324][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-8] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-10] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,325][DEBUG][redisson-netty-2-14] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4419322f[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,325][DEBUG][redisson-netty-2-18] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2cad997f[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-10] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591986, [49, 55, 56, 48, 51, 57, 55, 55, 51, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,325][DEBUG][http-nio-1024-exec-8] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591986, [49, 55, 56, 48, 51, 57, 55, 55, 51, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:33,325][DEBUG][redisson-netty-2-12] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591986, [49, 55, 56, 48, 51, 57, 55, 55, 51, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@12bbd744[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591986, [49, 55, 56, 48, 51, 57, 55, 55, 51, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,325][DEBUG][redisson-netty-2-20] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591986, [49, 55, 56, 48, 51, 57, 55, 55, 51, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6232b1b2[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591986, [49, 55, 56, 48, 51, 57, 55, 55, 51, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:33,326][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,326][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:33,326][DEBUG][http-nio-1024-exec-8] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:33,326][DEBUG][http-nio-1024-exec-8] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67e0bdd3] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:33,326][DEBUG][http-nio-1024-exec-8] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:33,326][DEBUG][http-nio-1024-exec-8] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:33,326][DEBUG][http-nio-1024-exec-8] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:33,327][DEBUG][http-nio-1024-exec-8] ==> Parameters: 257(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:33,327][DEBUG][http-nio-1024-exec-10] Read "application/json;charset=UTF-8" to [LeaveQueryForm(type=null, startTimeBegin=null, startTimeEnd=null, reason=null, flowStatus=null)] (LogFormatUtils.java:120) +[2026-06-02 18:55:33,329][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:33,329][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@52bbeb28] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:33,334][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:33,334][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:33,334][DEBUG][http-nio-1024-exec-10] ==> Preparing: SELECT COUNT(*) AS total FROM t_leave WHERE t_leave.deleted_flag = 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:33,334][DEBUG][http-nio-1024-exec-10] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:33,399][DEBUG][http-nio-1024-exec-10] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:33,399][DEBUG][http-nio-1024-exec-8] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:33,399][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@52bbeb28] (Logger.java:49) +[2026-06-02 18:55:33,399][DEBUG][http-nio-1024-exec-8] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@67e0bdd3] (Logger.java:49) +[2026-06-02 18:55:33,400][DEBUG][http-nio-1024-exec-8] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:33,400][DEBUG][http-nio-1024-exec-8] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:33,401][DEBUG][http-nio-1024-exec-8] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:33,403][DEBUG][http-nio-1024-exec-10] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:33,403][DEBUG][http-nio-1024-exec-10] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=10, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:33,403][DEBUG][http-nio-1024-exec-10] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-3] POST "/flow/definition/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-1] GET "/support/helpDoc/queryHelpDocByRelationId/253", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-7] GET "/support/tableColumn/getColumns/10001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-3] Mapped to net.lab1024.sa.admin.module.flow.controller.DefController#queryPage(FlowDefinitionQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-7] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,182][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,183][DEBUG][http-nio-1024-exec-1] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:39,183][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,183][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,183][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3694083b[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,183][DEBUG][redisson-netty-2-26] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3c5a1ec5[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,183][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6603c4f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,183][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,184][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,184][DEBUG][redisson-netty-2-24] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6de47d2a[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,185][DEBUG][redisson-netty-2-1] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5060375d[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,185][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7ab6333a[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,185][DEBUG][redisson-netty-2-30] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1a130a9a[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,185][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1d417682[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,185][DEBUG][redisson-netty-2-4] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@371d8fdf[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,185][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-7] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-1] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-3] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,186][DEBUG][redisson-netty-2-6] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4ce14c2[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,186][DEBUG][redisson-netty-2-12] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@11af78c4[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,186][DEBUG][redisson-netty-2-10] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5cd3f33d[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-7] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-1] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,186][DEBUG][http-nio-1024-exec-3] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,187][DEBUG][redisson-netty-2-14] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@e76faf[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,187][DEBUG][redisson-netty-2-2] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@67ac15db[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,187][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2c8b17a2] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29f46c1a] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:39,188][DEBUG][http-nio-1024-exec-1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:39,189][DEBUG][http-nio-1024-exec-1] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,189][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:39,189][DEBUG][http-nio-1024-exec-7] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,189][DEBUG][http-nio-1024-exec-7] ==> Parameters: 1(Long), 10001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,189][DEBUG][http-nio-1024-exec-1] ==> Parameters: 253(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,189][DEBUG][redisson-netty-2-16] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@735c920c[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,190][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,194][DEBUG][http-nio-1024-exec-3] Read "application/json;charset=UTF-8" to [FlowDefinitionQueryForm(flowCode=null, flowName=null, category=null, version=null, deletedFlag=null)] (LogFormatUtils.java:120) +[2026-06-02 18:55:39,223][DEBUG][http-nio-1024-exec-3] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:39,223][DEBUG][http-nio-1024-exec-3] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@528a8163] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:39,231][DEBUG][http-nio-1024-exec-3] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:39,231][DEBUG][http-nio-1024-exec-3] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:39,231][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT COUNT(*) AS total FROM flow_definition WHERE del_flag = '0' (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,232][DEBUG][http-nio-1024-exec-3] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,265][DEBUG][http-nio-1024-exec-7] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,265][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2c8b17a2] (Logger.java:49) +[2026-06-02 18:55:39,265][DEBUG][http-nio-1024-exec-7] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:39,265][DEBUG][http-nio-1024-exec-7] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:39,266][DEBUG][http-nio-1024-exec-7] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:39,267][DEBUG][http-nio-1024-exec-7] GET "/support/tableColumn/getColumns/10001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:39,267][DEBUG][http-nio-1024-exec-7] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:39,267][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,267][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,268][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@510d95f8[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,268][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,268][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,268][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-1] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@29f46c1a] (Logger.java:49) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-1] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:39,269][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@42f5f77b[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-1] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,269][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:39,270][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@485798ca[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,270][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,270][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,270][DEBUG][http-nio-1024-exec-7] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,270][DEBUG][redisson-netty-2-8] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@51440bca[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,270][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,270][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:39,270][DEBUG][http-nio-1024-exec-7] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:39,271][DEBUG][redisson-netty-2-10] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@76c73c65[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591980, [49, 55, 56, 48, 51, 57, 55, 55, 51, 57, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:39,271][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:39,271][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:39,271][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@54b05491] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:39,272][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:39,272][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:39,272][DEBUG][http-nio-1024-exec-7] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,272][DEBUG][http-nio-1024-exec-7] ==> Parameters: 1(Long), 10001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,279][DEBUG][http-nio-1024-exec-3] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,279][DEBUG][http-nio-1024-exec-3] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@528a8163] (Logger.java:49) +[2026-06-02 18:55:39,281][DEBUG][http-nio-1024-exec-3] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:39,282][DEBUG][http-nio-1024-exec-3] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=0, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:39,282][DEBUG][http-nio-1024-exec-3] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:39,321][DEBUG][http-nio-1024-exec-7] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:39,321][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@54b05491] (Logger.java:49) +[2026-06-02 18:55:39,322][DEBUG][http-nio-1024-exec-7] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:39,322][DEBUG][http-nio-1024-exec-7] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:39,322][DEBUG][http-nio-1024-exec-7] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:46,431][DEBUG][http-nio-1024-exec-5] GET "/support/helpDoc/queryHelpDocByRelationId/254", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:46,432][DEBUG][http-nio-1024-exec-5] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:46,432][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,432][DEBUG][http-nio-1024-exec-10] GET "/flow/execute/toDoPage?pageNum=1&pageSize=10", parameters={masked} (LogFormatUtils.java:120) +[2026-06-02 18:55:46,432][DEBUG][http-nio-1024-exec-10] Mapped to net.lab1024.sa.admin.module.flow.controller.ExecuteController#toDoPage(FlowTask, int, int) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:46,432][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,432][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,432][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,433][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1a92f57f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,433][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4e26fbac[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,433][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,433][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,433][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,433][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,433][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,433][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,434][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@67044068[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,434][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,434][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2f39051f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,434][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,434][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,434][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,434][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,434][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,434][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@310b45ea[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,435][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@46b9ff80[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-5] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-10] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,435][DEBUG][redisson-netty-2-26] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1ab81cb0[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-5] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591973, [49, 55, 56, 48, 51, 57, 55, 55, 52, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,435][DEBUG][redisson-netty-2-24] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5f904cff[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-10] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591973, [49, 55, 56, 48, 51, 57, 55, 55, 52, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:46,435][DEBUG][redisson-netty-2-1] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591973, [49, 55, 56, 48, 51, 57, 55, 55, 52, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5027e0c4[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591973, [49, 55, 56, 48, 51, 57, 55, 55, 52, 54, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,435][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,436][DEBUG][redisson-netty-2-2] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591973, [49, 55, 56, 48, 51, 57, 55, 55, 52, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5572fc23[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591973, [49, 55, 56, 48, 51, 57, 55, 55, 52, 54, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:46,436][DEBUG][http-nio-1024-exec-5] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:46,436][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:46,436][DEBUG][http-nio-1024-exec-5] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1cbb778c] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:46,436][DEBUG][http-nio-1024-exec-5] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:46,436][DEBUG][http-nio-1024-exec-5] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:46,436][DEBUG][http-nio-1024-exec-5] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,436][DEBUG][http-nio-1024-exec-5] ==> Parameters: 254(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,439][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:46,439][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@cafc5e7] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:46,439][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:46,439][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:46,439][DEBUG][http-nio-1024-exec-10] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,440][DEBUG][http-nio-1024-exec-10] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-5] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-10] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-5] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1cbb778c] (Logger.java:49) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@cafc5e7] (Logger.java:49) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@132fa80c] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-5] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:46,487][DEBUG][http-nio-1024-exec-5] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:46,488][DEBUG][http-nio-1024-exec-10] ==> Preparing: SELECT er.role_id FROM t_role_employee er WHERE er.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,488][DEBUG][http-nio-1024-exec-5] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:46,490][DEBUG][http-nio-1024-exec-10] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,531][DEBUG][http-nio-1024-exec-10] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,532][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@132fa80c] (Logger.java:49) +[2026-06-02 18:55:46,532][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:46,532][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2522f59b] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:46,532][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:46,532][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:46,532][DEBUG][http-nio-1024-exec-10] ==> Preparing: SELECT role_id,role_name,role_code,remark,update_time,create_time FROM t_role (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,532][DEBUG][http-nio-1024-exec-10] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,572][DEBUG][http-nio-1024-exec-10] <== Total: 6 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,573][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2522f59b] (Logger.java:49) +[2026-06-02 18:55:46,575][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:46,575][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cd67740] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:46,589][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:46,589][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:46,589][DEBUG][http-nio-1024-exec-10] ==> Preparing: SELECT COUNT(*) FROM (SELECT DISTINCT t.id, t.node_code, t.node_name, t.node_type, t.definition_id, t.instance_id, t.create_time, t.update_time, t.tenant_id, i.business_id, i.flow_status, i.activity_status, d.flow_name, t.form_custom, t.form_path FROM flow_task AS t LEFT JOIN flow_user uu ON uu.associated = t.id LEFT JOIN flow_definition d ON t.definition_id = d.id LEFT JOIN flow_instance i ON t.instance_id = i.id WHERE t.node_type = 1 AND t.del_flag = 0 AND uu.processed_by IN (?, ?, ?, ?, ?, ?, ?, ?) ORDER BY t.create_time DESC) TOTAL (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,591][DEBUG][http-nio-1024-exec-10] ==> Parameters: role:1(String), role:34(String), role:35(String), role:36(String), role:37(String), role:59(String), 1(String), dept:1(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,642][DEBUG][http-nio-1024-exec-10] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,642][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5cd67740] (Logger.java:49) +[2026-06-02 18:55:46,658][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:46,658][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40678fa5] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:46,659][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:46,659][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:46,659][DEBUG][http-nio-1024-exec-10] ==> Preparing: SELECT id,create_time,update_time,tenant_id,del_flag,type,processed_by,associated,create_by FROM flow_user WHERE del_flag='0' (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,660][DEBUG][http-nio-1024-exec-10] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,704][DEBUG][http-nio-1024-exec-10] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:46,704][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@40678fa5] (Logger.java:49) +[2026-06-02 18:55:46,710][DEBUG][http-nio-1024-exec-10] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:46,710][DEBUG][http-nio-1024-exec-10] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=10, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:46,711][DEBUG][http-nio-1024-exec-10] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:53,048][DEBUG][http-nio-1024-exec-3] POST "/flow/definition/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:53,048][DEBUG][http-nio-1024-exec-8] GET "/support/tableColumn/getColumns/10001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:53,048][DEBUG][http-nio-1024-exec-7] GET "/support/helpDoc/queryHelpDocByRelationId/253", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-3] Mapped to net.lab1024.sa.admin.module.flow.controller.DefController#queryPage(FlowDefinitionQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-8] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-7] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,049][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,053][DEBUG][redisson-netty-2-30] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@725f558e[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,054][DEBUG][redisson-netty-2-4] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@48d39ed9[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,055][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,055][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,055][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,055][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,055][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,055][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,055][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7eeed4a1[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,055][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,056][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,056][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,056][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5443a9f4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,056][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@114e32a7[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,057][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,057][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,057][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,057][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,057][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,058][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,058][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4d7d3866[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,058][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,058][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,059][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5b018fc9[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,059][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@197caeae[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,059][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@54d2221b[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-7] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-3] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,059][DEBUG][http-nio-1024-exec-8] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,060][DEBUG][redisson-netty-2-16] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@52be3d21[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,060][DEBUG][redisson-netty-2-6] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@77d03848[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,060][DEBUG][redisson-netty-2-18] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6bba278f[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,060][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,060][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,060][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,060][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,060][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,060][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,061][DEBUG][http-nio-1024-exec-7] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,061][DEBUG][http-nio-1024-exec-8] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,061][DEBUG][http-nio-1024-exec-3] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,062][DEBUG][redisson-netty-2-18] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2b1c3de6[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,062][DEBUG][redisson-netty-2-8] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4e02cc55[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,062][DEBUG][redisson-netty-2-10] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5d0d5852[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,062][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,062][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,062][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,063][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:53,063][DEBUG][http-nio-1024-exec-3] Read "application/json;charset=UTF-8" to [FlowDefinitionQueryForm(flowCode=null, flowName=null, category=null, version=null, deletedFlag=null)] (LogFormatUtils.java:120) +[2026-06-02 18:55:53,063][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@542ea934] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-7] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-3] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-8] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-8] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@400ffbc5] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-3] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7595e5ba] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:53,064][DEBUG][http-nio-1024-exec-7] ==> Parameters: 253(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,065][DEBUG][http-nio-1024-exec-8] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:53,065][DEBUG][http-nio-1024-exec-8] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:53,065][DEBUG][http-nio-1024-exec-8] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,065][DEBUG][http-nio-1024-exec-8] ==> Parameters: 1(Long), 10001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,069][DEBUG][http-nio-1024-exec-3] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:53,069][DEBUG][http-nio-1024-exec-3] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:53,070][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT COUNT(*) AS total FROM flow_definition WHERE del_flag = '0' (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,070][DEBUG][http-nio-1024-exec-3] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,102][DEBUG][http-nio-1024-exec-7] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,103][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@542ea934] (Logger.java:49) +[2026-06-02 18:55:53,104][DEBUG][http-nio-1024-exec-7] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:53,104][DEBUG][http-nio-1024-exec-7] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:53,105][DEBUG][http-nio-1024-exec-7] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:53,114][DEBUG][http-nio-1024-exec-8] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,114][DEBUG][http-nio-1024-exec-3] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,114][DEBUG][http-nio-1024-exec-8] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@400ffbc5] (Logger.java:49) +[2026-06-02 18:55:53,114][DEBUG][http-nio-1024-exec-3] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7595e5ba] (Logger.java:49) +[2026-06-02 18:55:53,115][DEBUG][http-nio-1024-exec-3] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:53,115][DEBUG][http-nio-1024-exec-8] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:53,115][DEBUG][http-nio-1024-exec-8] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:53,115][DEBUG][http-nio-1024-exec-3] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=0, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:53,116][DEBUG][http-nio-1024-exec-8] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:53,116][DEBUG][http-nio-1024-exec-3] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:53,117][DEBUG][http-nio-1024-exec-9] GET "/support/tableColumn/getColumns/10001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:53,117][DEBUG][http-nio-1024-exec-9] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:53,118][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,118][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,119][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@568456cc[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,119][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,119][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,119][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,120][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@130c77a[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,120][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,120][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,120][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,121][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2f659444[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,121][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,121][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,122][DEBUG][http-nio-1024-exec-9] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,124][DEBUG][redisson-netty-2-22] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@719481b5[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,124][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,124][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:53,124][DEBUG][http-nio-1024-exec-9] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:53,125][DEBUG][redisson-netty-2-28] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7475bdda[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591966, [49, 55, 56, 48, 51, 57, 55, 55, 53, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:53,126][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:53,126][DEBUG][http-nio-1024-exec-9] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:53,127][DEBUG][http-nio-1024-exec-9] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@646a7a1e] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:53,127][DEBUG][http-nio-1024-exec-9] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:53,127][DEBUG][http-nio-1024-exec-9] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:53,127][DEBUG][http-nio-1024-exec-9] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,127][DEBUG][http-nio-1024-exec-9] ==> Parameters: 1(Long), 10001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,185][DEBUG][http-nio-1024-exec-9] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:53,186][DEBUG][http-nio-1024-exec-9] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@646a7a1e] (Logger.java:49) +[2026-06-02 18:55:53,186][DEBUG][http-nio-1024-exec-9] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:53,186][DEBUG][http-nio-1024-exec-9] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:53,187][DEBUG][http-nio-1024-exec-9] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:54,242][DEBUG][http-nio-1024-exec-6] GET "/support/helpDoc/queryHelpDocByRelationId/254", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:54,242][DEBUG][http-nio-1024-exec-2] GET "/flow/execute/toDoPage?pageNum=1&pageSize=10", parameters={masked} (LogFormatUtils.java:120) +[2026-06-02 18:55:54,243][DEBUG][http-nio-1024-exec-2] Mapped to net.lab1024.sa.admin.module.flow.controller.ExecuteController#toDoPage(FlowTask, int, int) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:54,243][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,243][DEBUG][http-nio-1024-exec-6] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:54,243][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,243][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,243][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,244][DEBUG][redisson-netty-2-24] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@13753c6a[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,244][DEBUG][redisson-netty-2-26] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@18ede995[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,244][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,244][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,244][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,244][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,245][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,245][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,246][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@52987158[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,246][DEBUG][redisson-netty-2-1] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@21a5d2bf[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,246][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,246][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,246][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,246][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,246][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,247][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,248][DEBUG][redisson-netty-2-30] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6b8e2308[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,248][DEBUG][redisson-netty-2-4] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@37c02db4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,248][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,248][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,248][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,248][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,248][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,248][DEBUG][http-nio-1024-exec-2] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,249][DEBUG][redisson-netty-2-8] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@58615671[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,249][DEBUG][redisson-netty-2-10] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1e8402d5[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,250][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,250][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,250][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,250][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:54,250][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591965, [49, 55, 56, 48, 51, 57, 55, 55, 53, 52, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,250][DEBUG][http-nio-1024-exec-2] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591965, [49, 55, 56, 48, 51, 57, 55, 55, 53, 52, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:54,251][DEBUG][redisson-netty-2-12] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591965, [49, 55, 56, 48, 51, 57, 55, 55, 53, 52, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6bb3f6c0[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591965, [49, 55, 56, 48, 51, 57, 55, 55, 53, 52, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,251][DEBUG][redisson-netty-2-6] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591965, [49, 55, 56, 48, 51, 57, 55, 55, 53, 52, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@34c5a74[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591965, [49, 55, 56, 48, 51, 57, 55, 55, 53, 52, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:54,251][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,251][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:54,252][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:54,252][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@64395a9f] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:54,252][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:54,252][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3d536c88] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:54,252][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:54,252][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:54,253][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:54,253][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:54,253][DEBUG][http-nio-1024-exec-6] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,253][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,254][DEBUG][http-nio-1024-exec-6] ==> Parameters: 254(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,254][DEBUG][http-nio-1024-exec-2] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,320][DEBUG][http-nio-1024-exec-2] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,321][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3d536c88] (Logger.java:49) +[2026-06-02 18:55:54,321][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:54,322][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ed442e3] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:54,322][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:54,322][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:54,322][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT er.role_id FROM t_role_employee er WHERE er.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,324][DEBUG][http-nio-1024-exec-2] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,329][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,330][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@64395a9f] (Logger.java:49) +[2026-06-02 18:55:54,331][DEBUG][http-nio-1024-exec-6] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:54,331][DEBUG][http-nio-1024-exec-6] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:54,332][DEBUG][http-nio-1024-exec-6] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:54,367][DEBUG][http-nio-1024-exec-2] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,368][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4ed442e3] (Logger.java:49) +[2026-06-02 18:55:54,368][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:54,369][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@43a9539d] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:54,369][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:54,370][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:54,370][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT role_id,role_name,role_code,remark,update_time,create_time FROM t_role (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,371][DEBUG][http-nio-1024-exec-2] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,418][DEBUG][http-nio-1024-exec-2] <== Total: 6 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,418][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@43a9539d] (Logger.java:49) +[2026-06-02 18:55:54,419][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:54,419][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7fc12106] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:54,427][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:54,428][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:54,428][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT COUNT(*) FROM (SELECT DISTINCT t.id, t.node_code, t.node_name, t.node_type, t.definition_id, t.instance_id, t.create_time, t.update_time, t.tenant_id, i.business_id, i.flow_status, i.activity_status, d.flow_name, t.form_custom, t.form_path FROM flow_task AS t LEFT JOIN flow_user uu ON uu.associated = t.id LEFT JOIN flow_definition d ON t.definition_id = d.id LEFT JOIN flow_instance i ON t.instance_id = i.id WHERE t.node_type = 1 AND t.del_flag = 0 AND uu.processed_by IN (?, ?, ?, ?, ?, ?, ?, ?) ORDER BY t.create_time DESC) TOTAL (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,433][DEBUG][http-nio-1024-exec-2] ==> Parameters: role:1(String), role:34(String), role:35(String), role:36(String), role:37(String), role:59(String), 1(String), dept:1(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,496][DEBUG][http-nio-1024-exec-2] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,496][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7fc12106] (Logger.java:49) +[2026-06-02 18:55:54,497][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:54,497][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35ffb7c9] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:54,498][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:54,498][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:54,498][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT id,create_time,update_time,tenant_id,del_flag,type,processed_by,associated,create_by FROM flow_user WHERE del_flag='0' (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,499][DEBUG][http-nio-1024-exec-2] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,551][DEBUG][http-nio-1024-exec-2] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:54,552][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@35ffb7c9] (Logger.java:49) +[2026-06-02 18:55:54,554][DEBUG][http-nio-1024-exec-2] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:54,554][DEBUG][http-nio-1024-exec-2] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=10, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:54,555][DEBUG][http-nio-1024-exec-2] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-7] GET "/flow/execute/donePage?pageNum=1&pageSize=10", parameters={masked} (LogFormatUtils.java:120) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-8] GET "/support/helpDoc/queryHelpDocByRelationId/255", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-7] Mapped to net.lab1024.sa.admin.module.flow.controller.ExecuteController#donePage(FlowHisTask, int, int) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-8] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,459][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,460][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@551db41d[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,460][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6da5c1a4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,460][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,460][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,460][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,460][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,460][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,460][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,461][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1d67d3a4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,461][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3ed3bdb0[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,461][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,461][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,462][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,462][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,462][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,462][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,463][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1ca82c74[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,463][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@463f59d1[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-7] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-8] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,463][DEBUG][redisson-netty-2-10] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@516f2174[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,463][DEBUG][redisson-netty-2-8] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@290a0cec[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,463][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,464][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,464][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:55,464][DEBUG][http-nio-1024-exec-7] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591964, [49, 55, 56, 48, 51, 57, 55, 55, 53, 53, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,464][DEBUG][http-nio-1024-exec-8] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591964, [49, 55, 56, 48, 51, 57, 55, 55, 53, 53, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:55,464][DEBUG][redisson-netty-2-14] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591964, [49, 55, 56, 48, 51, 57, 55, 55, 53, 53, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1427ac27[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591964, [49, 55, 56, 48, 51, 57, 55, 55, 53, 53, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,464][DEBUG][redisson-netty-2-18] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591964, [49, 55, 56, 48, 51, 57, 55, 55, 53, 53, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4b0b6564[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591964, [49, 55, 56, 48, 51, 57, 55, 55, 53, 53, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:55,464][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,464][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:55,465][DEBUG][http-nio-1024-exec-8] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:55,465][DEBUG][http-nio-1024-exec-8] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e5fd797] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:55,465][DEBUG][http-nio-1024-exec-8] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:55,465][DEBUG][http-nio-1024-exec-8] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:55,465][DEBUG][http-nio-1024-exec-8] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,465][DEBUG][http-nio-1024-exec-8] ==> Parameters: 255(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,466][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:55,466][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4f9132ed] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:55,466][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:55,466][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:55,466][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,467][DEBUG][http-nio-1024-exec-7] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,515][DEBUG][http-nio-1024-exec-8] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,515][DEBUG][http-nio-1024-exec-8] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3e5fd797] (Logger.java:49) +[2026-06-02 18:55:55,516][DEBUG][http-nio-1024-exec-8] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:55,516][DEBUG][http-nio-1024-exec-8] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:55,517][DEBUG][http-nio-1024-exec-8] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:55,526][DEBUG][http-nio-1024-exec-7] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,527][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4f9132ed] (Logger.java:49) +[2026-06-02 18:55:55,527][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:55,527][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@323b3e76] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:55,527][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:55,527][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:55,528][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT er.role_id FROM t_role_employee er WHERE er.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,528][DEBUG][http-nio-1024-exec-7] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,574][DEBUG][http-nio-1024-exec-7] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,574][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@323b3e76] (Logger.java:49) +[2026-06-02 18:55:55,574][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:55,574][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@e5c11d4] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:55,575][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:55,575][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:55,575][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT role_id,role_name,role_code,remark,update_time,create_time FROM t_role (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,576][DEBUG][http-nio-1024-exec-7] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,622][DEBUG][http-nio-1024-exec-7] <== Total: 6 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,623][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@e5c11d4] (Logger.java:49) +[2026-06-02 18:55:55,624][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:55,624][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@77894e8f] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:55,649][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:55,649][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:55,649][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT COUNT(*) AS total FROM (SELECT MAX(id) AS id FROM flow_his_task WHERE approver IN (?, ?, ?, ?, ?, ?, ?, ?) GROUP BY instance_id) tmp (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,655][DEBUG][http-nio-1024-exec-7] ==> Parameters: role:1(String), role:34(String), role:35(String), role:36(String), role:37(String), role:59(String), 1(String), dept:1(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,710][DEBUG][http-nio-1024-exec-7] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,710][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@77894e8f] (Logger.java:49) +[2026-06-02 18:55:55,711][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:55,711][DEBUG][http-nio-1024-exec-7] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3d7d68dd] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:55,712][DEBUG][http-nio-1024-exec-7] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:55,712][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:55,712][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT t_employee.*, t_department.name AS departmentName FROM t_employee LEFT JOIN t_department ON t_department.department_id = t_employee.department_id WHERE t_employee.disabled_flag = ? AND t_employee.deleted_flag = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,713][DEBUG][http-nio-1024-exec-7] ==> Parameters: false(Boolean), false(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,763][DEBUG][http-nio-1024-exec-7] <== Total: 3 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:55,763][DEBUG][http-nio-1024-exec-7] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3d7d68dd] (Logger.java:49) +[2026-06-02 18:55:55,772][DEBUG][http-nio-1024-exec-7] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:55,772][DEBUG][http-nio-1024-exec-7] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=10, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:55,773][DEBUG][http-nio-1024-exec-7] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:56,062][DEBUG][http-nio-1024-exec-5] GET "/flow/execute/copyPage?pageNum=1&pageSize=10", parameters={masked} (LogFormatUtils.java:120) +[2026-06-02 18:55:56,062][DEBUG][http-nio-1024-exec-10] GET "/support/helpDoc/queryHelpDocByRelationId/256", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:56,062][DEBUG][http-nio-1024-exec-5] Mapped to net.lab1024.sa.admin.module.flow.controller.ExecuteController#copyPage(FlowTask, int, int) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:56,063][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,063][DEBUG][http-nio-1024-exec-10] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:56,063][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,063][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,063][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,064][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2ef1ecde[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,064][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@395deb5c[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,065][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,065][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,065][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,065][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,065][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,065][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,066][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6bf7df1d[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,066][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@c18fde1[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,066][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,066][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,066][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,066][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,067][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,067][DEBUG][http-nio-1024-exec-5] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,068][DEBUG][redisson-netty-2-26] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1d80f7c[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,068][DEBUG][redisson-netty-2-24] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5f87a3a3[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,068][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,068][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,068][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,068][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,069][DEBUG][http-nio-1024-exec-10] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,069][DEBUG][http-nio-1024-exec-5] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,070][DEBUG][redisson-netty-2-2] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@17ccd979[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,070][DEBUG][redisson-netty-2-1] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2f80311d[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,070][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,070][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,070][DEBUG][http-nio-1024-exec-5] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,070][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,071][DEBUG][http-nio-1024-exec-10] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591963, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,071][DEBUG][http-nio-1024-exec-5] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591963, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,073][DEBUG][redisson-netty-2-4] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591963, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@36722176[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591963, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,073][DEBUG][redisson-netty-2-30] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591963, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@390ee4dc[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591963, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,073][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,073][DEBUG][http-nio-1024-exec-5] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,074][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,075][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@71149c8b] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,075][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,075][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,075][DEBUG][http-nio-1024-exec-10] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,076][DEBUG][http-nio-1024-exec-5] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,076][DEBUG][http-nio-1024-exec-5] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50ecfede] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,076][DEBUG][http-nio-1024-exec-10] ==> Parameters: 256(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,076][DEBUG][http-nio-1024-exec-5] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,077][DEBUG][http-nio-1024-exec-5] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,077][DEBUG][http-nio-1024-exec-5] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,077][DEBUG][http-nio-1024-exec-5] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,127][DEBUG][http-nio-1024-exec-10] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,128][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@71149c8b] (Logger.java:49) +[2026-06-02 18:55:56,128][DEBUG][http-nio-1024-exec-10] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:56,129][DEBUG][http-nio-1024-exec-10] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:56,130][DEBUG][http-nio-1024-exec-10] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:56,134][DEBUG][http-nio-1024-exec-5] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,134][DEBUG][http-nio-1024-exec-5] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@50ecfede] (Logger.java:49) +[2026-06-02 18:55:56,135][DEBUG][http-nio-1024-exec-5] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,135][DEBUG][http-nio-1024-exec-5] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@fa185a5] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,136][DEBUG][http-nio-1024-exec-5] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,136][DEBUG][http-nio-1024-exec-5] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,136][DEBUG][http-nio-1024-exec-5] ==> Preparing: SELECT er.role_id FROM t_role_employee er WHERE er.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,137][DEBUG][http-nio-1024-exec-5] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,190][DEBUG][http-nio-1024-exec-5] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,190][DEBUG][http-nio-1024-exec-5] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@fa185a5] (Logger.java:49) +[2026-06-02 18:55:56,191][DEBUG][http-nio-1024-exec-5] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,191][DEBUG][http-nio-1024-exec-5] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3774237e] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,192][DEBUG][http-nio-1024-exec-5] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,192][DEBUG][http-nio-1024-exec-5] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,192][DEBUG][http-nio-1024-exec-5] ==> Preparing: SELECT role_id,role_name,role_code,remark,update_time,create_time FROM t_role (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,193][DEBUG][http-nio-1024-exec-5] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,242][DEBUG][http-nio-1024-exec-5] <== Total: 6 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,243][DEBUG][http-nio-1024-exec-5] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3774237e] (Logger.java:49) +[2026-06-02 18:55:56,244][DEBUG][http-nio-1024-exec-5] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,244][DEBUG][http-nio-1024-exec-5] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1737ed88] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,250][DEBUG][http-nio-1024-exec-5] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,250][DEBUG][http-nio-1024-exec-5] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,250][DEBUG][http-nio-1024-exec-5] ==> Preparing: SELECT COUNT(*) AS total FROM flow_user a WHERE a.type = 4 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,251][DEBUG][http-nio-1024-exec-5] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,306][DEBUG][http-nio-1024-exec-5] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,307][DEBUG][http-nio-1024-exec-5] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1737ed88] (Logger.java:49) +[2026-06-02 18:55:56,308][DEBUG][http-nio-1024-exec-5] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:56,309][DEBUG][http-nio-1024-exec-5] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=10, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:56,309][DEBUG][http-nio-1024-exec-5] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:56,961][DEBUG][http-nio-1024-exec-6] GET "/support/tableColumn/getColumns/10001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:56,961][DEBUG][http-nio-1024-exec-2] POST "/flow/definition/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:56,961][DEBUG][http-nio-1024-exec-1] GET "/support/helpDoc/queryHelpDocByRelationId/253", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:56,961][DEBUG][http-nio-1024-exec-2] Mapped to net.lab1024.sa.admin.module.flow.controller.DefController#queryPage(FlowDefinitionQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-1] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-6] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,962][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,964][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@aeb4f6e[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,964][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@21498eb0[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,964][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@182a2ea4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,964][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,965][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5ee87bc7[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,965][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6bb91cf0[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,965][DEBUG][redisson-netty-2-14] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@438f16ad[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,965][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,965][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,965][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,966][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,966][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,966][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,966][DEBUG][http-nio-1024-exec-1] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,966][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,966][DEBUG][http-nio-1024-exec-6] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,967][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@280c1a2a[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,967][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@71b7b5d5[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,967][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@43f71069[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-6] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-2] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,967][DEBUG][http-nio-1024-exec-1] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,969][DEBUG][redisson-netty-2-16] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@60836a03[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,969][DEBUG][redisson-netty-2-10] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2fd22a3b[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,969][DEBUG][redisson-netty-2-8] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@79719ea8[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-1] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-6] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-1] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-6] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,969][DEBUG][http-nio-1024-exec-2] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:56,971][DEBUG][redisson-netty-2-18] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3b8e4508[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,971][DEBUG][redisson-netty-2-12] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@d67525e[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,971][DEBUG][redisson-netty-2-14] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@37490a26[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 54, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:56,971][DEBUG][http-nio-1024-exec-6] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,971][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,971][DEBUG][http-nio-1024-exec-1] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-6] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17387874] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-6] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b892c18] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-2] Read "application/json;charset=UTF-8" to [FlowDefinitionQueryForm(flowCode=null, flowName=null, category=null, version=null, deletedFlag=null)] (LogFormatUtils.java:120) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-6] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,972][DEBUG][http-nio-1024-exec-6] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,973][DEBUG][http-nio-1024-exec-6] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,973][DEBUG][http-nio-1024-exec-1] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,973][DEBUG][http-nio-1024-exec-6] ==> Parameters: 1(Long), 10001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,973][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:56,973][DEBUG][http-nio-1024-exec-1] ==> Parameters: 253(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,974][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4be8061f] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:56,979][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:56,979][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:56,979][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT COUNT(*) AS total FROM flow_definition WHERE del_flag = '0' (BaseJdbcLogger.java:135) +[2026-06-02 18:55:56,980][DEBUG][http-nio-1024-exec-2] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:55:57,031][DEBUG][http-nio-1024-exec-1] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:57,032][DEBUG][http-nio-1024-exec-1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@17387874] (Logger.java:49) +[2026-06-02 18:55:57,034][DEBUG][http-nio-1024-exec-1] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:57,034][DEBUG][http-nio-1024-exec-1] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:57,035][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:57,035][DEBUG][http-nio-1024-exec-6] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:57,036][DEBUG][http-nio-1024-exec-6] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2b892c18] (Logger.java:49) +[2026-06-02 18:55:57,036][DEBUG][http-nio-1024-exec-6] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:57,036][DEBUG][http-nio-1024-exec-6] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:57,037][DEBUG][http-nio-1024-exec-6] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:57,038][DEBUG][http-nio-1024-exec-4] GET "/support/tableColumn/getColumns/10001", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:55:57,039][DEBUG][http-nio-1024-exec-4] Mapped to net.lab1024.sa.base.module.support.table.TableColumnController#getColumns(Integer) (AbstractHandlerMapping.java:531) +[2026-06-02 18:55:57,039][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:57,040][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:57,041][DEBUG][redisson-netty-2-20] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4e1572e4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:57,041][DEBUG][http-nio-1024-exec-2] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:57,042][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:57,042][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:57,042][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@4be8061f] (Logger.java:49) +[2026-06-02 18:55:57,042][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:57,043][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6c720468[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:57,043][DEBUG][http-nio-1024-exec-2] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:57,043][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:57,043][DEBUG][http-nio-1024-exec-2] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=0, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:55:57,044][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:57,044][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:57,044][DEBUG][http-nio-1024-exec-2] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:55:57,045][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1adbe989[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:57,046][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:57,046][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:57,046][DEBUG][http-nio-1024-exec-4] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:57,047][DEBUG][redisson-netty-2-26] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6d1895b4[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:57,047][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:57,047][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:55:57,047][DEBUG][http-nio-1024-exec-4] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:55:57,048][DEBUG][redisson-netty-2-24] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@11c48854[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591962, [49, 55, 56, 48, 51, 57, 55, 55, 53, 55, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:55:57,048][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:55:57,049][DEBUG][http-nio-1024-exec-4] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:55:57,049][DEBUG][http-nio-1024-exec-4] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b34af1a] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:55:57,049][DEBUG][http-nio-1024-exec-4] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:55:57,049][DEBUG][http-nio-1024-exec-4] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:55:57,049][DEBUG][http-nio-1024-exec-4] ==> Preparing: select * from t_table_column where user_id = ? and table_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:55:57,051][DEBUG][http-nio-1024-exec-4] ==> Parameters: 1(Long), 10001(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:55:57,102][DEBUG][http-nio-1024-exec-4] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:55:57,102][DEBUG][http-nio-1024-exec-4] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b34af1a] (Logger.java:49) +[2026-06-02 18:55:57,103][DEBUG][http-nio-1024-exec-4] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:55:57,103][DEBUG][http-nio-1024-exec-4] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=null, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:55:57,104][DEBUG][http-nio-1024-exec-4] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:03,478][DEBUG][smart-heart-beat] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:03,479][DEBUG][smart-heart-beat] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@535f420d] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:03,480][DEBUG][smart-heart-beat] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:03,480][DEBUG][smart-heart-beat] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:03,480][DEBUG][smart-heart-beat] ==> Preparing: select * from t_heart_beat_record where project_path = ? and server_ip = ? and process_no =? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,482][DEBUG][smart-heart-beat] ==> Parameters: /Users/wang/sanduoyun/developspace/smart-flow-master(String), 198.18.0.1;172.20.10.11;127.0.0.1(String), 66984(Integer) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,527][DEBUG][smart-heart-beat] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,527][DEBUG][smart-heart-beat] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@535f420d] (Logger.java:49) +[2026-06-02 18:56:03,528][DEBUG][smart-heart-beat] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:03,528][DEBUG][smart-heart-beat] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6cb5ee8d] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:03,529][DEBUG][smart-heart-beat] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:03,530][DEBUG][smart-heart-beat] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:03,530][DEBUG][smart-heart-beat] ==> Preparing: INSERT INTO t_heart_beat_record ( project_path, server_ip, process_no, process_start_time, heart_beat_time ) VALUES ( ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,530][DEBUG][smart-heart-beat] ==> Parameters: /Users/wang/sanduoyun/developspace/smart-flow-master(String), 198.18.0.1;172.20.10.11;127.0.0.1(String), 66984(Integer), 2026-06-02T18:54:56.634(LocalDateTime), 2026-06-02T18:56:03.477098(LocalDateTime) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,567][DEBUG][smart-heart-beat] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,568][DEBUG][smart-heart-beat] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6cb5ee8d] (Logger.java:49) +[2026-06-02 18:56:03,885][DEBUG][http-nio-1024-exec-7] POST "/flow/definition/add", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:03,885][DEBUG][http-nio-1024-exec-7] Mapped to net.lab1024.sa.admin.module.flow.controller.DefController#add(FlowDefinition) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:03,885][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:03,886][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:03,887][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7a3aa26e[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:03,887][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:03,888][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:03,888][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:03,888][DEBUG][redisson-netty-2-1] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7e0b316f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:03,889][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:03,889][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:03,889][DEBUG][http-nio-1024-exec-7] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:03,890][DEBUG][redisson-netty-2-4] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6d4a3310[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:03,890][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:03,890][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:03,890][DEBUG][http-nio-1024-exec-7] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:03,890][DEBUG][redisson-netty-2-30] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3b4b6ebd[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:03,891][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:03,891][DEBUG][http-nio-1024-exec-7] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:03,891][DEBUG][http-nio-1024-exec-7] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591955, [49, 55, 56, 48, 51, 57, 55, 55, 54, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:03,891][DEBUG][redisson-netty-2-10] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591955, [49, 55, 56, 48, 51, 57, 55, 55, 54, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@11fe17be[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591955, [49, 55, 56, 48, 51, 57, 55, 55, 54, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:03,891][DEBUG][http-nio-1024-exec-7] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:03,897][DEBUG][http-nio-1024-exec-7] Read "application/json;charset=UTF-8" to [FlowDefinition(id=null, createTime=null, updateTime=null, tenantId=null, delFlag=null, flowCode=111, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:03,906][DEBUG][http-nio-1024-exec-7] Creating new transaction with name [net.lab1024.sa.admin.module.flow.controller.DefController.add]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,-java.lang.Exception (AbstractPlatformTransactionManager.java:402) +[2026-06-02 18:56:03,907][DEBUG][http-nio-1024-exec-7] Acquired Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] for JDBC transaction (DataSourceTransactionManager.java:271) +[2026-06-02 18:56:03,909][DEBUG][http-nio-1024-exec-7] Switching JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] to manual commit (DataSourceTransactionManager.java:289) +[2026-06-02 18:56:03,911][DEBUG][http-nio-1024-exec-7] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:03,911][DEBUG][http-nio-1024-exec-7] Registering transaction synchronization for SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:03,914][DEBUG][http-nio-1024-exec-7] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will be managed by Spring (Logger.java:49) +[2026-06-02 18:56:03,914][DEBUG][http-nio-1024-exec-7] ==> Preparing: SELECT id,create_time,update_time,tenant_id,del_flag,flow_code,flow_name,category,version,is_publish,form_custom,form_path,activity_status,listener_type,listener_path,ext FROM flow_definition WHERE del_flag='0' AND (flow_code IN (?)) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,915][DEBUG][http-nio-1024-exec-7] ==> Parameters: 111(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,985][DEBUG][http-nio-1024-exec-7] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:03,986][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,017][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,019][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_node ( id, create_time, update_time, node_type, definition_id, node_code, node_name, node_ratio, coordinate, version ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,023][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763773574627330(Long), 2026-06-02 18:56:03.995(Timestamp), 2026-06-02 18:56:03.995(Timestamp), 0(Integer), 2061763773549461506(Long), start(String), 开始(String), 0(BigDecimal), 260,200|260,200(String), 1(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,061][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,062][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,062][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,062][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_node ( id, create_time, update_time, node_type, definition_id, node_code, node_name, node_ratio, coordinate, version ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,062][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763773574627331(Long), 2026-06-02 18:56:03.995(Timestamp), 2026-06-02 18:56:03.995(Timestamp), 1(Integer), 2061763773549461506(Long), submit(String), 中间节点-或签1(String), 0(BigDecimal), 420,200|420,200(String), 1(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,110][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,110][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,110][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,110][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_node ( id, create_time, update_time, node_type, definition_id, node_code, node_name, node_ratio, coordinate, version ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,111][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763773574627332(Long), 2026-06-02 18:56:03.995(Timestamp), 2026-06-02 18:56:03.995(Timestamp), 1(Integer), 2061763773549461506(Long), approval(String), 中间节点-或签2(String), 0(BigDecimal), 600,200|600,200(String), 1(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,151][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,152][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,152][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,153][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_node ( id, create_time, update_time, node_type, definition_id, node_code, node_name, node_ratio, coordinate, version ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,154][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763773574627333(Long), 2026-06-02 18:56:03.995(Timestamp), 2026-06-02 18:56:03.995(Timestamp), 2(Integer), 2061763773549461506(Long), end(String), 结束(String), 0(BigDecimal), 760,200|760,200(String), 1(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,194][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,194][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,211][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,212][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_skip ( id, create_time, update_time, definition_id, now_node_code, now_node_type, next_node_code, next_node_type, skip_type, coordinate ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,212][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763774413488130(Long), 2026-06-02 18:56:04.196(Timestamp), 2026-06-02 18:56:04.196(Timestamp), 2061763773549461506(Long), start(String), 0(Integer), submit(String), 1(Integer), PASS(String), 280,200;370,200(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,251][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,251][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,251][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,251][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_skip ( id, create_time, update_time, definition_id, now_node_code, now_node_type, next_node_code, next_node_type, skip_type, coordinate ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,252][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763774413488131(Long), 2026-06-02 18:56:04.196(Timestamp), 2026-06-02 18:56:04.196(Timestamp), 2061763773549461506(Long), submit(String), 1(Integer), approval(String), 1(Integer), PASS(String), 470,200;550,200(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,303][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,303][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,303][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,303][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_skip ( id, create_time, update_time, definition_id, now_node_code, now_node_type, next_node_code, next_node_type, skip_type, coordinate ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,303][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763774413488132(Long), 2026-06-02 18:56:04.196(Timestamp), 2026-06-02 18:56:04.196(Timestamp), 2061763773549461506(Long), approval(String), 1(Integer), end(String), 2(Integer), PASS(String), 650,200;740,200(String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,355][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,355][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,356][DEBUG][http-nio-1024-exec-7] Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] from current transaction (Logger.java:49) +[2026-06-02 18:56:04,357][DEBUG][http-nio-1024-exec-7] ==> Preparing: INSERT INTO flow_definition ( id, create_time, update_time, flow_code, flow_name, version, form_custom, form_path, listener_type, listener_path ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,358][DEBUG][http-nio-1024-exec-7] ==> Parameters: 2061763773549461506(Long), 2026-06-02 18:56:04.356(Timestamp), 2026-06-02 18:56:04.356(Timestamp), 111(String), 11(String), 1(String), N(String), 11(String), (String), (String) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,407][DEBUG][http-nio-1024-exec-7] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,408][DEBUG][http-nio-1024-exec-7] Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,419][DEBUG][smart-operate-log1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:04,419][DEBUG][smart-operate-log1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7f7660ff] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:04,419][DEBUG][http-nio-1024-exec-7] Transaction synchronization committing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,420][DEBUG][smart-operate-log1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:04,420][DEBUG][smart-operate-log1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:04,420][DEBUG][http-nio-1024-exec-7] Transaction synchronization deregistering SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,420][DEBUG][smart-operate-log1] ==> Preparing: INSERT INTO t_operate_log ( operate_user_id, operate_user_type, operate_user_name, operate_user_account, operate_user_role, module, content, url, method, http_method, operation_type, param, ip, ip_region, user_agent, device_info, os_info, response_result, success_flag ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,420][DEBUG][http-nio-1024-exec-7] Transaction synchronization closing SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ec5d171] (Logger.java:49) +[2026-06-02 18:56:04,421][DEBUG][http-nio-1024-exec-7] Initiating transaction commit (AbstractPlatformTransactionManager.java:790) +[2026-06-02 18:56:04,421][DEBUG][http-nio-1024-exec-7] Committing JDBC transaction on Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] (DataSourceTransactionManager.java:334) +[2026-06-02 18:56:04,422][DEBUG][smart-operate-log1] ==> Parameters: 1(Long), 1(Integer), 管理员(String), admin(String), (String), 工作流-流程定义(String), 添加(String), /flow/definition/add(String), net.lab1024.sa.admin.module.flow.controller.DefController.add(String), POST(String), CREATE(String), [{"formPath":"11","listenerPath":"","formCustom":"N","userList":[],"flowCode":"111","createTime":1780397764356,"listenerType":"","updateTime":1780397764356,"id":2061763773549461506,"flowName":"11","nodeList":[],"version":"1"}](String), 127.0.0.1(String), (String), Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36(String), Chrome 148.0.0.0(String), macOS 10.15.7(String), {"msg":"操作成功","code":0,"data":true,"dataType":1,"ok":true}(String), true(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,472][DEBUG][http-nio-1024-exec-7] Releasing JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] after transaction (DataSourceTransactionManager.java:393) +[2026-06-02 18:56:04,473][DEBUG][http-nio-1024-exec-7] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:04,474][DEBUG][http-nio-1024-exec-7] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=true, dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:56:04,475][DEBUG][http-nio-1024-exec-7] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:04,481][DEBUG][smart-operate-log1] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,482][DEBUG][smart-operate-log1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@7f7660ff] (Logger.java:49) +[2026-06-02 18:56:04,501][DEBUG][http-nio-1024-exec-3] POST "/flow/definition/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:04,502][DEBUG][http-nio-1024-exec-3] Mapped to net.lab1024.sa.admin.module.flow.controller.DefController#queryPage(FlowDefinitionQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:04,502][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:04,502][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:04,503][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7916b0c4[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:04,503][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:04,504][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:04,504][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:04,505][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@2b718d29[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:04,505][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:04,505][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:04,505][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:04,506][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@49726aa5[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:04,506][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:04,506][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:04,506][DEBUG][http-nio-1024-exec-3] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:04,507][DEBUG][redisson-netty-2-2] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@42bf4c68[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:04,507][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:04,507][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:04,507][DEBUG][http-nio-1024-exec-3] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591954, [49, 55, 56, 48, 51, 57, 55, 55, 54, 52, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:04,508][DEBUG][redisson-netty-2-14] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591954, [49, 55, 56, 48, 51, 57, 55, 55, 54, 52, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@74a2458a[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591954, [49, 55, 56, 48, 51, 57, 55, 55, 54, 52, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:04,509][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:04,510][DEBUG][http-nio-1024-exec-3] Read "application/json;charset=UTF-8" to [FlowDefinitionQueryForm(flowCode=null, flowName=null, category=null, version=null, deletedFlag=null)] (LogFormatUtils.java:120) +[2026-06-02 18:56:04,511][DEBUG][http-nio-1024-exec-3] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:04,511][DEBUG][http-nio-1024-exec-3] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b433e3c] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:04,517][DEBUG][http-nio-1024-exec-3] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:04,517][DEBUG][http-nio-1024-exec-3] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:04,518][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT COUNT(*) AS total FROM flow_definition WHERE del_flag = '0' (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,520][DEBUG][http-nio-1024-exec-3] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,571][DEBUG][http-nio-1024-exec-3] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,572][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT id,create_time,update_time,tenant_id,del_flag,flow_code,flow_name,category,version,is_publish,form_custom,form_path,activity_status,listener_type,listener_path,ext FROM flow_definition WHERE del_flag='0' ORDER BY create_time DESC LIMIT ? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,574][DEBUG][http-nio-1024-exec-3] ==> Parameters: 10(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,632][DEBUG][http-nio-1024-exec-3] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:04,633][DEBUG][http-nio-1024-exec-3] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1b433e3c] (Logger.java:49) +[2026-06-02 18:56:04,640][DEBUG][http-nio-1024-exec-3] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:04,644][DEBUG][http-nio-1024-exec-3] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=1, total=1, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:04,646][DEBUG][http-nio-1024-exec-3] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:08,048][DEBUG][http-nio-1024-exec-10] GET "/warm-flow-ui/index.html?id=2061763773549461506&disabled=false&Authorization=Bearer%20769d485013454588bae0683951df166e", parameters={masked} (LogFormatUtils.java:120) +[2026-06-02 18:56:08,051][DEBUG][http-nio-1024-exec-10] Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/warm-flow-ui/], classpath [warm-flow-ui/]] (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:08,054][DEBUG][http-nio-1024-exec-10] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:08,058][DEBUG][http-nio-1024-exec-1] GET "/warm-flow-ui/css/index-Da60mrLX.css", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:08,058][DEBUG][http-nio-1024-exec-5] GET "/warm-flow-ui/js/index-Bfpt7KC4.js", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:08,059][DEBUG][http-nio-1024-exec-1] Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/warm-flow-ui/], classpath [warm-flow-ui/]] (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:08,059][DEBUG][http-nio-1024-exec-5] Mapped to ResourceHttpRequestHandler [classpath [META-INF/resources/warm-flow-ui/], classpath [warm-flow-ui/]] (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:08,063][DEBUG][http-nio-1024-exec-1] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:08,085][DEBUG][http-nio-1024-exec-5] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:08,176][DEBUG][http-nio-1024-exec-6] GET "/warm-flow-ui/config", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:08,184][DEBUG][http-nio-1024-exec-6] Mapped to org.dromara.warm.flow.ui.controller.WarmFlowUiController#config() (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:08,188][DEBUG][http-nio-1024-exec-6] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:08,188][DEBUG][http-nio-1024-exec-6] Writing [org.dromara.warm.flow.core.dto.ApiResult@4bccdb5e] (LogFormatUtils.java:120) +[2026-06-02 18:56:08,190][DEBUG][http-nio-1024-exec-6] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:08,206][DEBUG][http-nio-1024-exec-2] GET "/warm-flow/query-def/2061763773549461506", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:08,206][DEBUG][http-nio-1024-exec-2] Mapped to org.dromara.warm.flow.ui.controller.WarmFlowController#queryDef(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:08,207][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:08,207][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@182bce40] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:08,208][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:08,208][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:08,208][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT id,create_time,update_time,tenant_id,del_flag,flow_code,flow_name,category,version,is_publish,form_custom,form_path,activity_status,listener_type,listener_path,ext FROM flow_definition WHERE id=? AND del_flag='0' (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,209][DEBUG][http-nio-1024-exec-2] ==> Parameters: 2061763773549461506(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,260][DEBUG][http-nio-1024-exec-2] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,260][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@182bce40] (Logger.java:49) +[2026-06-02 18:56:08,261][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:08,262][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@23133e08] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:08,271][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:08,271][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:08,271][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT id,create_time,update_time,tenant_id,del_flag,node_type,definition_id,node_code,node_name,permission_flag,node_ratio,coordinate,version,any_node_skip,listener_type,listener_path,handler_type,handler_path,form_custom,form_path,ext FROM flow_node WHERE del_flag='0' AND definition_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,272][DEBUG][http-nio-1024-exec-2] ==> Parameters: 2061763773549461506(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,319][DEBUG][http-nio-1024-exec-2] <== Total: 4 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,320][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@23133e08] (Logger.java:49) +[2026-06-02 18:56:08,320][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:08,320][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6845f0d2] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:08,321][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:08,321][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:08,321][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT id,create_time,update_time,tenant_id,del_flag,definition_id,now_node_code,now_node_type,next_node_code,next_node_type,skip_name,skip_type,skip_condition,coordinate FROM flow_skip WHERE del_flag='0' AND definition_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,321][DEBUG][http-nio-1024-exec-2] ==> Parameters: 2061763773549461506(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,372][DEBUG][http-nio-1024-exec-2] <== Total: 3 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:08,373][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6845f0d2] (Logger.java:49) +[2026-06-02 18:56:08,374][DEBUG][http-nio-1024-exec-2] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:08,374][DEBUG][http-nio-1024-exec-2] Writing [org.dromara.warm.flow.core.dto.ApiResult@24ef1d82] (LogFormatUtils.java:120) +[2026-06-02 18:56:08,377][DEBUG][http-nio-1024-exec-2] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:11,461][DEBUG][http-nio-1024-exec-4] GET "/warm-flow/node-ext", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:11,461][DEBUG][http-nio-1024-exec-8] GET "/warm-flow/handler-feedback", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:11,461][DEBUG][http-nio-1024-exec-8] Mapped to org.dromara.warm.flow.ui.controller.WarmFlowController#handlerFeedback(HandlerFeedBackDto) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:11,461][DEBUG][http-nio-1024-exec-4] Mapped to org.dromara.warm.flow.ui.controller.WarmFlowController#nodeExt() (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:11,463][DEBUG][http-nio-1024-exec-8] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:11,463][DEBUG][http-nio-1024-exec-8] Writing [org.dromara.warm.flow.core.dto.ApiResult@644568b] (LogFormatUtils.java:120) +[2026-06-02 18:56:11,464][DEBUG][http-nio-1024-exec-8] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:11,464][DEBUG][http-nio-1024-exec-4] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:11,464][DEBUG][http-nio-1024-exec-4] Writing [org.dromara.warm.flow.core.dto.ApiResult@1bff96bb] (LogFormatUtils.java:120) +[2026-06-02 18:56:11,466][DEBUG][http-nio-1024-exec-4] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:13,361][DEBUG][SmartJobLauncher-0] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:13,362][DEBUG][SmartJobLauncher-0] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@b281cdc] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:13,363][DEBUG][SmartJobLauncher-0] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:13,363][DEBUG][SmartJobLauncher-0] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:13,363][DEBUG][SmartJobLauncher-0] ==> Preparing: SELECT job_id,job_name,job_class,trigger_type,trigger_value,param,enabled_flag,last_execute_time,last_execute_log_id,remark,sort,deleted_flag,update_name,update_time,create_time FROM t_smart_job (BaseJdbcLogger.java:135) +[2026-06-02 18:56:13,364][DEBUG][SmartJobLauncher-0] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:56:13,426][DEBUG][SmartJobLauncher-0] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:13,427][DEBUG][SmartJobLauncher-0] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@b281cdc] (Logger.java:49) +[2026-06-02 18:56:23,051][DEBUG][http-nio-1024-exec-3] GET "/flow/execute/copyPage?pageNum=1&pageSize=10", parameters={masked} (LogFormatUtils.java:120) +[2026-06-02 18:56:23,051][DEBUG][http-nio-1024-exec-10] GET "/support/helpDoc/queryHelpDocByRelationId/256", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:23,051][DEBUG][http-nio-1024-exec-3] Mapped to net.lab1024.sa.admin.module.flow.controller.ExecuteController#copyPage(FlowTask, int, int) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:23,051][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,051][DEBUG][http-nio-1024-exec-10] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:23,051][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,052][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,052][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,053][DEBUG][redisson-netty-2-6] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@6a6f6006[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,053][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@435a7f44[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,053][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,053][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,053][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,053][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,053][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,053][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,054][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@39b2e074[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,055][DEBUG][redisson-netty-2-18] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@17f317a0[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,055][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,055][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,055][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,055][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,055][DEBUG][http-nio-1024-exec-3] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,055][DEBUG][http-nio-1024-exec-10] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,056][DEBUG][redisson-netty-2-16] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1ecc20d7[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,056][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@52e589c7[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,056][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,056][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,056][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,056][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,056][DEBUG][http-nio-1024-exec-10] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,056][DEBUG][http-nio-1024-exec-3] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,057][DEBUG][redisson-netty-2-18] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@459117959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0e4b39cc, L:/127.0.0.1:57558 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5b261196[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,057][DEBUG][redisson-netty-2-14] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1806990078 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x7808fecb, L:/127.0.0.1:57556 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@5dcd99ad[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,057][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,057][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,057][DEBUG][http-nio-1024-exec-3] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,057][DEBUG][http-nio-1024-exec-10] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:23,058][DEBUG][http-nio-1024-exec-3] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591935, [49, 55, 56, 48, 51, 57, 55, 55, 56, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,058][DEBUG][http-nio-1024-exec-10] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591935, [49, 55, 56, 48, 51, 57, 55, 55, 56, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:23,059][DEBUG][redisson-netty-2-12] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591935, [49, 55, 56, 48, 51, 57, 55, 55, 56, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@520776176 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x9fe51c28, L:/127.0.0.1:57555 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@58a02424[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591935, [49, 55, 56, 48, 51, 57, 55, 55, 56, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,059][DEBUG][redisson-netty-2-20] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591935, [49, 55, 56, 48, 51, 57, 55, 55, 56, 51, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1669800014 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x5dbc4068, L:/127.0.0.1:57559 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@296387c4[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591935, [49, 55, 56, 48, 51, 57, 55, 55, 56, 51, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:23,059][DEBUG][http-nio-1024-exec-3] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,059][DEBUG][http-nio-1024-exec-10] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:23,059][DEBUG][http-nio-1024-exec-10] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:23,059][DEBUG][http-nio-1024-exec-10] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3c36b5cc] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:23,059][DEBUG][http-nio-1024-exec-3] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:23,059][DEBUG][http-nio-1024-exec-10] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-3] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ffa5142] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-10] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-10] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-3] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-3] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-10] ==> Parameters: 256(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,060][DEBUG][http-nio-1024-exec-3] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,106][DEBUG][http-nio-1024-exec-3] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,106][DEBUG][http-nio-1024-exec-3] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1ffa5142] (Logger.java:49) +[2026-06-02 18:56:23,107][DEBUG][http-nio-1024-exec-3] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:23,107][DEBUG][http-nio-1024-exec-3] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ec94d9b] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:23,108][DEBUG][http-nio-1024-exec-3] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:23,108][DEBUG][http-nio-1024-exec-3] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:23,108][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT er.role_id FROM t_role_employee er WHERE er.employee_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,108][DEBUG][http-nio-1024-exec-3] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,118][DEBUG][http-nio-1024-exec-10] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,118][DEBUG][http-nio-1024-exec-10] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3c36b5cc] (Logger.java:49) +[2026-06-02 18:56:23,120][DEBUG][http-nio-1024-exec-10] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:23,120][DEBUG][http-nio-1024-exec-10] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:56:23,121][DEBUG][http-nio-1024-exec-10] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:23,156][DEBUG][http-nio-1024-exec-3] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,157][DEBUG][http-nio-1024-exec-3] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5ec94d9b] (Logger.java:49) +[2026-06-02 18:56:23,157][DEBUG][http-nio-1024-exec-3] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:23,157][DEBUG][http-nio-1024-exec-3] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@47de0b8] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:23,158][DEBUG][http-nio-1024-exec-3] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:23,158][DEBUG][http-nio-1024-exec-3] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:23,158][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT role_id,role_name,role_code,remark,update_time,create_time FROM t_role (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,159][DEBUG][http-nio-1024-exec-3] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,208][DEBUG][http-nio-1024-exec-3] <== Total: 6 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,208][DEBUG][http-nio-1024-exec-3] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@47de0b8] (Logger.java:49) +[2026-06-02 18:56:23,209][DEBUG][http-nio-1024-exec-3] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:23,209][DEBUG][http-nio-1024-exec-3] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6cbc05f0] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:23,216][DEBUG][http-nio-1024-exec-3] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:23,216][DEBUG][http-nio-1024-exec-3] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:23,216][DEBUG][http-nio-1024-exec-3] ==> Preparing: SELECT COUNT(*) AS total FROM flow_user a WHERE a.type = 4 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,217][DEBUG][http-nio-1024-exec-3] ==> Parameters: (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,267][DEBUG][http-nio-1024-exec-3] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:23,268][DEBUG][http-nio-1024-exec-3] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6cbc05f0] (Logger.java:49) +[2026-06-02 18:56:23,270][DEBUG][http-nio-1024-exec-3] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:23,270][DEBUG][http-nio-1024-exec-3] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=10, total=0, (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:23,271][DEBUG][http-nio-1024-exec-3] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:27,797][DEBUG][http-nio-1024-exec-8] POST "/oa/notice/employee/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:27,798][DEBUG][http-nio-1024-exec-8] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#queryEmployeeNotice(NoticeEmployeeQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:27,798][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,798][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,800][DEBUG][http-nio-1024-exec-4] GET "/support/helpDoc/queryHelpDocByRelationId/0", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:27,801][DEBUG][http-nio-1024-exec-2] POST "/oa/notice/employee/query", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:27,802][DEBUG][http-nio-1024-exec-4] Mapped to net.lab1024.sa.admin.module.system.support.AdminHelpDocController#queryHelpDocByRelationId(Long) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:27,802][DEBUG][http-nio-1024-exec-2] Mapped to net.lab1024.sa.admin.module.business.oa.notice.controller.NoticeController#queryEmployeeNotice(NoticeEmployeeQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:27,802][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,802][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,802][DEBUG][redisson-netty-2-28] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@448015959 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x541d330c, L:/127.0.0.1:57563 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@653ea399[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-9] POST "/support/changeLog/queryPage", parameters={} (LogFormatUtils.java:120) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-9] Mapped to net.lab1024.sa.base.module.support.changelog.controller.ChangeLogController#queryPage(ChangeLogQueryForm) (AbstractHandlerMapping.java:531) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,803][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,804][DEBUG][redisson-netty-2-26] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1659106873 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa76ce844, L:/127.0.0.1:57562 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@28b76b32[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,804][DEBUG][redisson-netty-2-22] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@305428161 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xda7489bb, L:/127.0.0.1:57560 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@7194cb2d[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,804][DEBUG][redisson-netty-2-24] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@271284986 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xad6e8414, L:/127.0.0.1:57561 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4c6ec927[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,805][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@754370241 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa23d3f60, L:/127.0.0.1:57566 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@33495257[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-8] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,805][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,806][DEBUG][redisson-netty-2-1] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1853684738 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xa5689acc, L:/127.0.0.1:57565 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1145dfaa[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,806][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,806][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,806][DEBUG][redisson-netty-2-10] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@65057122 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xb846b7b0, L:/127.0.0.1:57570 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@70a4a6e8[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,806][DEBUG][redisson-netty-2-4] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@831295943 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xbc8df318, L:/127.0.0.1:57567 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@39bb4d36[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,806][DEBUG][redisson-netty-2-30] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1244979154 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xcb988a77, L:/127.0.0.1:57564 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@33b0af7f[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,806][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-8] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,806][DEBUG][http-nio-1024-exec-4] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-9] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,807][DEBUG][http-nio-1024-exec-2] acquired connection for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,808][DEBUG][redisson-netty-2-6] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@600380527 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1204cc30, L:/127.0.0.1:57568 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@774418cf[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,808][DEBUG][redisson-netty-2-8] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@857327457 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x05df13a2, L:/127.0.0.1:57569 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3f34a125[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,808][DEBUG][redisson-netty-2-2] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1503453252 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x577a3abf, L:/127.0.0.1:57550 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@10348652[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,808][DEBUG][redisson-netty-2-12] connection released for command (GET) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@819945749 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x85f40f2a, L:/127.0.0.1:57571 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@8609061[Completed normally], command=(GET), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.ByteArrayCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-8] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-2] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-9] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-4] acquired connection for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,808][DEBUG][http-nio-1024-exec-8] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,809][DEBUG][redisson-netty-2-14] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1147239564 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x4edea812, L:/127.0.0.1:57572 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@664cd6c7[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,809][DEBUG][redisson-netty-2-16] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@96926130 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x6ef3edc7, L:/127.0.0.1:57573 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@65c31f3f[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,809][DEBUG][redisson-netty-2-6] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@1463937780 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0xc35a792c, L:/127.0.0.1:57552 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@3f518147[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,809][DEBUG][redisson-netty-2-10] connection released for command (TTL) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@741715936 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x1ee17a15, L:/127.0.0.1:57554 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4e99c935[Completed normally], command=(TTL), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-8] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-2] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-4] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-9] Fetching Redis Connection from RedisConnectionFactory (RedisConnectionUtils.java:143) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-9] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-2] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,810][DEBUG][http-nio-1024-exec-4] acquired connection for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using node 127.0.0.1/127.0.0.1:6379... RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=null, usage=1] (RedisExecutor.java:633) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-8] Read "application/json;charset=UTF-8" to [NoticeEmployeeQueryForm(keywords=null, noticeTypeId=1, publishTimeBegin=null, notViewFlag=null, publ (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:27,811][DEBUG][redisson-netty-2-18] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@881368552 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x0ebddc8d, L:/127.0.0.1:57574 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@1249a9ff[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,811][DEBUG][redisson-netty-2-8] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@483188732 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x8b395847, L:/127.0.0.1:57553 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@4ac5fcb5[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,811][DEBUG][redisson-netty-2-16] connection released for command (SETEX) and params [[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]] from slot NodeSource [slot=0, addr=null, redisClient=null, redirect=null, entry=null] using connection RedisConnection@705947636 [redisClient=[addr=redis://127.0.0.1:6379], channel=[id: 0x3d21aef0, L:/127.0.0.1:57557 - R:127.0.0.1/127.0.0.1:6379], currentCommand=CommandData [promise=java.util.concurrent.CompletableFuture@716e0db4[Completed normally], command=(SETEX), params=[[65, 117, 116, 104, 111, 114, 105, 122, 97, 116, ...], 2591930, [49, 55, 56, 48, 51, 57, 55, 55, 56, 55, ...]], codec=org.redisson.client.codec.StringCodec], usage=0] (RedisExecutor.java:668) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-4] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-9] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-2] Closing Redis Connection (RedisConnectionUtils.java:380) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-8] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-4] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-8] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b718574] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-4] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@41a7a5b7] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-2] Read "application/json;charset=UTF-8" to [NoticeEmployeeQueryForm(keywords=null, noticeTypeId=2, publishTimeBegin=null, notViewFlag=null, publ (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-9] Read "application/json;charset=UTF-8" to [ChangeLogQueryForm(type=null, keyword=null, publicDateBegin=null, publicDateEnd=null, createTime=nul (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-8] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:27,811][DEBUG][http-nio-1024-exec-4] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-9] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-4] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:32.948, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:33.005}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-8] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-9] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@579fee81] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-4] ==> Preparing: select t_help_doc.* from t_help_doc_relation left join t_help_doc on t_help_doc.help_doc_id = t_help_doc_relation.help_doc_id where t_help_doc_relation.relation_id = ? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-8] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@113ec71] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-9] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-2] ==> Preparing: SELECT employee_id,login_name,login_pwd,actual_name,avatar,gender,phone,email,department_id,position_id,administrator_flag,disabled_flag,deleted_flag,remark,update_time,create_time FROM t_employee WHERE employee_id=? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-9] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-8] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-4] ==> Parameters: 0(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-9] ==> Preparing: SELECT * FROM t_change_log order by t_change_log.version desc LIMIT ? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,812][DEBUG][http-nio-1024-exec-2] ==> Parameters: 1(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,813][DEBUG][http-nio-1024-exec-9] ==> Parameters: 8(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,858][DEBUG][http-nio-1024-exec-8] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,858][DEBUG][http-nio-1024-exec-8] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6b718574] (Logger.java:49) +[2026-06-02 18:56:27,859][DEBUG][http-nio-1024-exec-8] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:27,859][DEBUG][http-nio-1024-exec-8] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@209c557a] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:27,860][DEBUG][http-nio-1024-exec-8] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:27,860][DEBUG][http-nio-1024-exec-8] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.044, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.084}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:27,860][DEBUG][http-nio-1024-exec-8] ==> Preparing: select t_notice.notice_id, t_notice.notice_type_id, t_notice.title, t_notice.all_visible_flag, t_notice.scheduled_publish_flag, t_notice.publish_time, t_notice.content_text, t_notice.content_html, t_notice.attachment, t_notice.page_view_count, t_notice.user_view_count, t_notice.source, t_notice.author, t_notice.document_number, t_notice.instance_id, t_notice.node_name, t_notice.flow_status, t_notice.deleted_flag, t_notice.create_user_id, t_notice.update_time, t_notice.create_time , t_notice_type.notice_type_name, (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = ? and t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag from t_notice left join t_notice_type on t_notice.notice_type_id = t_notice_type.notice_type_id WHERE t_notice.deleted_flag = ? and t_notice.publish_time < now() AND t_notice_type.notice_type_id = ? order by t_notice.publish_time desc LIMIT ? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,861][DEBUG][http-nio-1024-exec-8] ==> Parameters: 1(Long), false(Boolean), 1(Long), 6(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,864][DEBUG][http-nio-1024-exec-4] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,864][DEBUG][http-nio-1024-exec-4] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@41a7a5b7] (Logger.java:49) +[2026-06-02 18:56:27,865][DEBUG][http-nio-1024-exec-4] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:27,865][DEBUG][http-nio-1024-exec-4] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=[], dataType=1)] (LogFormatUtils.java:120) +[2026-06-02 18:56:27,866][DEBUG][http-nio-1024-exec-4] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:27,870][DEBUG][http-nio-1024-exec-9] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,870][DEBUG][http-nio-1024-exec-2] <== Total: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,870][DEBUG][http-nio-1024-exec-9] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@579fee81] (Logger.java:49) +[2026-06-02 18:56:27,870][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@113ec71] (Logger.java:49) +[2026-06-02 18:56:27,870][DEBUG][http-nio-1024-exec-2] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:27,870][DEBUG][http-nio-1024-exec-2] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e5e358e] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:27,871][DEBUG][http-nio-1024-exec-2] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:27,871][DEBUG][http-nio-1024-exec-2] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:20.861, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:20.919}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:27,871][DEBUG][http-nio-1024-exec-2] ==> Preparing: select t_notice.notice_id, t_notice.notice_type_id, t_notice.title, t_notice.all_visible_flag, t_notice.scheduled_publish_flag, t_notice.publish_time, t_notice.content_text, t_notice.content_html, t_notice.attachment, t_notice.page_view_count, t_notice.user_view_count, t_notice.source, t_notice.author, t_notice.document_number, t_notice.instance_id, t_notice.node_name, t_notice.flow_status, t_notice.deleted_flag, t_notice.create_user_id, t_notice.update_time, t_notice.create_time , t_notice_type.notice_type_name, (select count(*) from t_notice_view_record where t_notice_view_record.employee_id = ? and t_notice_view_record.notice_id = t_notice.notice_id) as viewFlag from t_notice left join t_notice_type on t_notice.notice_type_id = t_notice_type.notice_type_id WHERE t_notice.deleted_flag = ? and t_notice.publish_time < now() AND t_notice_type.notice_type_id = ? order by t_notice.publish_time desc LIMIT ? (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,873][DEBUG][smart-operate-log1] Creating a new SqlSession (Logger.java:49) +[2026-06-02 18:56:27,873][DEBUG][smart-operate-log1] SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3a74f175] was not registered for synchronization because synchronization is not active (Logger.java:49) +[2026-06-02 18:56:27,873][DEBUG][http-nio-1024-exec-9] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:27,873][DEBUG][http-nio-1024-exec-9] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=8, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:27,874][DEBUG][smart-operate-log1] Fetching JDBC Connection from DataSource (DataSourceUtils.java:117) +[2026-06-02 18:56:27,874][DEBUG][smart-operate-log1] JDBC Connection [ConnectionProxyImpl{connectedTime=2026-06-02 18:55:00.487, closeCount=0, lastValidateTimeMillis=2026-06-02 18:55:00.524}] will not be managed by Spring (Logger.java:49) +[2026-06-02 18:56:27,874][DEBUG][smart-operate-log1] ==> Preparing: INSERT INTO t_operate_log ( operate_user_id, operate_user_type, operate_user_name, operate_user_account, operate_user_role, module, content, url, method, http_method, operation_type, param, ip, ip_region, user_agent, device_info, os_info, response_result, success_flag ) VALUES ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,875][DEBUG][http-nio-1024-exec-9] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:27,875][DEBUG][http-nio-1024-exec-2] ==> Parameters: 1(Long), false(Boolean), 2(Long), 6(Long) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,875][DEBUG][smart-operate-log1] ==> Parameters: 1(Long), 1(Integer), 管理员(String), admin(String), (String), 业务支撑-更新日志(String), 分页查询 @author 卓大(String), /support/changeLog/queryPage(String), net.lab1024.sa.base.module.support.changelog.controller.ChangeLogController.queryPage(String), POST(String), UPDATE(String), [{"searchCount":false,"pageSize":8,"pageNum":1}](String), 127.0.0.1(String), (String), Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/148.0.0.0 Safari/537.36(String), Chrome 148.0.0.0(String), macOS 10.15.7(String), {"msg":"操作成功","code":0,"data":{"total":0,"pages":0,"pageSize":8,"list":[],"pageNum":1,"emptyFlag":true},"dataType":1,"ok":true}(String), true(Boolean) (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,913][DEBUG][http-nio-1024-exec-8] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,914][DEBUG][http-nio-1024-exec-8] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@209c557a] (Logger.java:49) +[2026-06-02 18:56:27,914][DEBUG][http-nio-1024-exec-8] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:27,915][DEBUG][http-nio-1024-exec-8] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=6, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:27,915][DEBUG][http-nio-1024-exec-8] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:27,926][DEBUG][http-nio-1024-exec-2] <== Total: 0 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,926][DEBUG][http-nio-1024-exec-2] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@1e5e358e] (Logger.java:49) +[2026-06-02 18:56:27,927][DEBUG][http-nio-1024-exec-2] Using 'application/json', given [application/json, text/plain, */*] and supported [application/json, application/*+json, application/cbor] (AbstractMessageConverterMethodProcessor.java:275) +[2026-06-02 18:56:27,928][DEBUG][http-nio-1024-exec-2] Writing [ResponseDTO(code=0, level=null, msg=操作成功, ok=true, data=PageResult(pageNum=1, pageSize=6, total=0, p (truncated)...] (LogFormatUtils.java:120) +[2026-06-02 18:56:27,928][DEBUG][smart-operate-log1] <== Updates: 1 (BaseJdbcLogger.java:135) +[2026-06-02 18:56:27,928][DEBUG][smart-operate-log1] Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@3a74f175] (Logger.java:49) +[2026-06-02 18:56:27,928][DEBUG][http-nio-1024-exec-2] Completed 200 OK (FrameworkServlet.java:1138) +[2026-06-02 18:56:47,481][DEBUG][SIGINT handler] Runtime.exit() called with status: 130 (LoggingProviderImpl.java:257) +java.lang.Throwable: Runtime.exit(130) + at java.base/java.lang.Shutdown.logRuntimeExit(Shutdown.java:179) ~[?:?] + at java.base/java.lang.Shutdown.exit(Shutdown.java:160) ~[?:?] + at java.base/java.lang.Terminator$1.handle(Terminator.java:51) ~[?:?] + at java.base/jdk.internal.misc.Signal$1.run(Signal.java:218) ~[?:?] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:56:47,482][DEBUG][SpringApplicationShutdownHook] Application availability state ReadinessState changed from ACCEPTING_TRAFFIC to REFUSING_TRAFFIC (ApplicationAvailabilityBean.java:77) +[2026-06-02 18:56:47,483][DEBUG][SpringApplicationShutdownHook] Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@351f2244, started on Tue Jun 02 18:54:57 CST 2026 (AbstractApplicationContext.java:1125) +[2026-06-02 18:56:47,484][DEBUG][SpringApplicationShutdownHook] Stopping beans in phase 2147483647 (DefaultLifecycleProcessor.java:478) +[2026-06-02 18:56:47,484][DEBUG][SpringApplicationShutdownHook] Bean 'smart-async-executor' completed its stop procedure (DefaultLifecycleProcessor.java:350) +[2026-06-02 18:56:47,484][DEBUG][SpringApplicationShutdownHook] Stopping beans in phase 2147482623 (DefaultLifecycleProcessor.java:478) +[2026-06-02 18:56:47,485][DEBUG][SpringApplicationShutdownHook] Bean 'webServerGracefulShutdown' completed its stop procedure (DefaultLifecycleProcessor.java:350) +[2026-06-02 18:56:47,485][DEBUG][SpringApplicationShutdownHook] Stopping beans in phase 2147481599 (DefaultLifecycleProcessor.java:478) +[2026-06-02 18:56:47,494][DEBUG][SpringApplicationShutdownHook] Bean 'webServerStartStop' completed its stop procedure (DefaultLifecycleProcessor.java:350) +[2026-06-02 18:56:47,494][DEBUG][SpringApplicationShutdownHook] Stopping beans in phase -2147483647 (DefaultLifecycleProcessor.java:478) +[2026-06-02 18:56:47,494][DEBUG][SpringApplicationShutdownHook] Bean 'springBootLoggingLifecycle' completed its stop procedure (DefaultLifecycleProcessor.java:350) +[2026-06-02 18:56:47,494][DEBUG][SpringApplicationShutdownHook] Stopped RedisMessageListenerContainer (RedisMessageListenerContainer.java:1007) +[2026-06-02 18:56:47,495][DEBUG][SpringApplicationShutdownHook] Shutting down ExecutorService 'taskScheduler' (ExecutorConfigurationSupport.java:328) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Beans' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Caches' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Health' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Info' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Conditions' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Configprops' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Env' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Loggers' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Threaddump' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Metrics' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Sbom' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Scheduledtasks' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,496][DEBUG][SpringApplicationShutdownHook] Unregister endpoint with ObjectName 'org.springframework.boot:type=Endpoint,name=Mappings' from the JMX domain (JmxEndpointExporter.java:115) +[2026-06-02 18:56:47,497][DEBUG][SpringApplicationShutdownHook] Unregistering JMX-exposed beans on shutdown (MBeanExporter.java:468) +[2026-06-02 18:56:47,497][DEBUG][SpringApplicationShutdownHook] Unregistering JMX-exposed beans (MBeanRegistrationSupport.java:186) +[2026-06-02 18:56:47,497][DEBUG][SpringApplicationShutdownHook] Initiate shutdown (0, 2, SECONDS) (DefaultClientResources.java:735) +[2026-06-02 18:56:47,498][DEBUG][SpringApplicationShutdownHook] Initiate shutdown (0, 2, SECONDS) (DefaultEventLoopGroupProvider.java:317) +[2026-06-02 18:56:47,499][DEBUG][SpringApplicationShutdownHook] Custom destroy method 'shutdown' on bean with name 'lettuceClientResources' completed asynchronously (DisposableBeanAdapter.java:361) +[2026-06-02 18:56:47,499][DEBUG][SpringApplicationShutdownHook] Shutting down ExecutorService 'smart-async-executor' (ExecutorConfigurationSupport.java:328) +[2026-06-02 18:56:47,505][DEBUG][SpringApplicationShutdownHook] Shutting down ExecutorService (ExecutorConfigurationSupport.java:328) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-20] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-20 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-18] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-18 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-8] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-8 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-24] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-24 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-22] Freed 6 thread-local buffer(s) from thread: redisson-netty-2-22 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-2] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-2 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-26] Freed 6 thread-local buffer(s) from thread: redisson-netty-2-26 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-30] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-30 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-4] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-4 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-16] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-16 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-12] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-12 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-1] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-1 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-10] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-10 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-14] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-14 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-6] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-6 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-28] Freed 7 thread-local buffer(s) from thread: redisson-netty-2-28 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,513][DEBUG][redisson-netty-2-3] Freed 5 thread-local buffer(s) from thread: redisson-netty-2-3 (PoolThreadCache.java:214) +[2026-06-02 18:56:47,514][DEBUG][SpringApplicationShutdownHook] Custom destroy method 'shutdown' on bean with name 'redisson' completed (DisposableBeanAdapter.java:361) +[2026-06-02 18:56:47,514][DEBUG][SpringApplicationShutdownHook] Custom destroy method 'close' on bean with name 'simpleMeterRegistry' completed (DisposableBeanAdapter.java:361) diff --git a/logs/sa-admin/dev/error/error.log b/logs/sa-admin/dev/error/error.log new file mode 100644 index 0000000..d53e36d --- /dev/null +++ b/logs/sa-admin/dev/error/error.log @@ -0,0 +1,425 @@ +[2026-06-02 18:55:20,327][ERROR][http-nio-1024-exec-6] 解析ip地址出错 (SmartIpUtil.java:80) +java.lang.NullPointerException: Cannot invoke "org.lionsoul.ip2region.xdb.Searcher.search(String)" because "net.lab1024.sa.base.common.util.SmartIpUtil.IP_SEARCHER" is null + at net.lab1024.sa.base.common.util.SmartIpUtil.getRegion(SmartIpUtil.java:78) ~[classes/:?] + at net.lab1024.sa.admin.module.system.login.service.LoginService.saveLoginLog(LoginService.java:427) ~[classes/:?] + at net.lab1024.sa.admin.module.system.login.service.LoginService.login(LoginService.java:237) ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at com.alibaba.druid.support.spring.stat.DruidStatInterceptor.invoke(DruidStatInterceptor.java:70) ~[druid-1.2.23.jar:?] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.10.jar:6.1.10] + at net.lab1024.sa.admin.module.system.login.service.LoginService$$SpringCGLIB$$1.login() ~[classes/:?] + at net.lab1024.sa.admin.module.system.login.controller.LoginController.login(LoginController.java:45) ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:354) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:89) ~[spring-aop-6.1.10.jar:6.1.10] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.aroundController(OperateLogAspect.java:100) ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:627) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.10.jar:6.1.10] + at net.lab1024.sa.admin.module.system.login.controller.LoginController$$SpringCGLIB$$0.login() ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at com.alibaba.druid.support.jakarta.WebStatFilter.doFilter(WebStatFilter.java:73) ~[druid-1.2.23.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at cn.dev33.satoken.filter.SaFirewallCheckFilterForJakartaServlet.doFilter(SaFirewallCheckFilterForJakartaServlet.java:68) ~[sa-token-spring-boot3-starter-1.41.0.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:107) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:663) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:20,407][ERROR][http-nio-1024-exec-6] 解析ip地址出错 (SmartIpUtil.java:80) +java.lang.NullPointerException: Cannot invoke "org.lionsoul.ip2region.xdb.Searcher.search(String)" because "net.lab1024.sa.base.common.util.SmartIpUtil.IP_SEARCHER" is null + at net.lab1024.sa.base.common.util.SmartIpUtil.getRegion(SmartIpUtil.java:78) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.enqueueLog(OperateLogAspect.java:233) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.aroundController(OperateLogAspect.java:107) ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:627) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.10.jar:6.1.10] + at net.lab1024.sa.admin.module.system.login.controller.LoginController$$SpringCGLIB$$0.login() ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at com.alibaba.druid.support.jakarta.WebStatFilter.doFilter(WebStatFilter.java:73) ~[druid-1.2.23.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at cn.dev33.satoken.filter.SaFirewallCheckFilterForJakartaServlet.doFilter(SaFirewallCheckFilterForJakartaServlet.java:68) ~[sa-token-spring-boot3-starter-1.41.0.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:107) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:663) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:55:20,858][ERROR][http-nio-1024-exec-2] 解析ip地址出错 (SmartIpUtil.java:80) +java.lang.NullPointerException: Cannot invoke "org.lionsoul.ip2region.xdb.Searcher.search(String)" because "net.lab1024.sa.base.common.util.SmartIpUtil.IP_SEARCHER" is null + at net.lab1024.sa.base.common.util.SmartIpUtil.getRegion(SmartIpUtil.java:78) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.enqueueLog(OperateLogAspect.java:233) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.aroundController(OperateLogAspect.java:107) ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:627) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.10.jar:6.1.10] + at net.lab1024.sa.base.module.support.changelog.controller.ChangeLogController$$SpringCGLIB$$0.queryPage() ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at com.alibaba.druid.support.jakarta.WebStatFilter.doFilter(WebStatFilter.java:73) ~[druid-1.2.23.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at cn.dev33.satoken.filter.SaFirewallCheckFilterForJakartaServlet.doFilter(SaFirewallCheckFilterForJakartaServlet.java:68) ~[sa-token-spring-boot3-starter-1.41.0.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:107) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:663) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:56:04,416][ERROR][http-nio-1024-exec-7] 解析ip地址出错 (SmartIpUtil.java:80) +java.lang.NullPointerException: Cannot invoke "org.lionsoul.ip2region.xdb.Searcher.search(String)" because "net.lab1024.sa.base.common.util.SmartIpUtil.IP_SEARCHER" is null + at net.lab1024.sa.base.common.util.SmartIpUtil.getRegion(SmartIpUtil.java:78) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.enqueueLog(OperateLogAspect.java:233) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.aroundController(OperateLogAspect.java:107) ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:627) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123) ~[spring-tx-6.1.10.jar:6.1.10] + at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:392) ~[spring-tx-6.1.10.jar:6.1.10] + at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.10.jar:6.1.10] + at net.lab1024.sa.admin.module.flow.controller.DefController$$SpringCGLIB$$0.add() ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at com.alibaba.druid.support.jakarta.WebStatFilter.doFilter(WebStatFilter.java:73) ~[druid-1.2.23.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at cn.dev33.satoken.filter.SaFirewallCheckFilterForJakartaServlet.doFilter(SaFirewallCheckFilterForJakartaServlet.java:68) ~[sa-token-spring-boot3-starter-1.41.0.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:107) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:663) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] +[2026-06-02 18:56:27,871][ERROR][http-nio-1024-exec-9] 解析ip地址出错 (SmartIpUtil.java:80) +java.lang.NullPointerException: Cannot invoke "org.lionsoul.ip2region.xdb.Searcher.search(String)" because "net.lab1024.sa.base.common.util.SmartIpUtil.IP_SEARCHER" is null + at net.lab1024.sa.base.common.util.SmartIpUtil.getRegion(SmartIpUtil.java:78) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.enqueueLog(OperateLogAspect.java:233) ~[classes/:?] + at net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect.aroundController(OperateLogAspect.java:107) ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethodWithGivenArgs(AbstractAspectJAdvice.java:637) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AbstractAspectJAdvice.invokeAdviceMethod(AbstractAspectJAdvice.java:627) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.aspectj.AspectJAroundAdvice.invoke(AspectJAroundAdvice.java:71) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768) ~[spring-aop-6.1.10.jar:6.1.10] + at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720) ~[spring-aop-6.1.10.jar:6.1.10] + at net.lab1024.sa.base.module.support.changelog.controller.ChangeLogController$$SpringCGLIB$$0.queryPage() ~[classes/:?] + at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:103) ~[?:?] + at java.base/java.lang.reflect.Method.invoke(Method.java:580) ~[?:?] + at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:255) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:188) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:118) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:926) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:831) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1089) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:979) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1014) ~[spring-webmvc-6.1.10.jar:6.1.10] + at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:914) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:590) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:885) ~[spring-webmvc-6.1.10.jar:6.1.10] + at jakarta.servlet.http.HttpServlet.service(HttpServlet.java:658) ~[tomcat-embed-core-10.1.25.jar:6.0] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:195) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) ~[tomcat-embed-websocket-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CorsFilter.doFilterInternal(CorsFilter.java:91) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at com.alibaba.druid.support.jakarta.WebStatFilter.doFilter(WebStatFilter.java:73) ~[druid-1.2.23.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at cn.dev33.satoken.filter.SaFirewallCheckFilterForJakartaServlet.doFilter(SaFirewallCheckFilterForJakartaServlet.java:68) ~[sa-token-spring-boot3-starter-1.41.0.jar:?] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.ServerHttpObservationFilter.doFilterInternal(ServerHttpObservationFilter.java:107) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) ~[spring-web-6.1.10.jar:6.1.10] + at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116) ~[spring-web-6.1.10.jar:6.1.10] + at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:164) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:140) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:167) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:482) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:115) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:663) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:344) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:389) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:904) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1741) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1190) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:63) ~[tomcat-embed-core-10.1.25.jar:10.1.25] + at java.base/java.lang.Thread.run(Thread.java:1583) [?:?] diff --git a/logs/sa-admin/dev/info/info.log b/logs/sa-admin/dev/info/info.log new file mode 100644 index 0000000..ff25aa9 --- /dev/null +++ b/logs/sa-admin/dev/info/info.log @@ -0,0 +1,32 @@ +[2026-06-02 18:54:57,776][INFO ][background-preinit] HV000001: Hibernate Validator 8.0.1.Final (Version.java:21) +[2026-06-02 18:54:57,850][INFO ][main] Starting AdminApplication using Java 21.0.11 with PID 66984 (/Users/wang/sanduoyun/developspace/smart-flow-master/smart-flow-api/sa-admin/target/classes started by wang in /Users/wang/sanduoyun/developspace/smart-flow-master) (StartupInfoLogger.java:50) +[2026-06-02 18:54:57,853][INFO ][main] The following 1 profile is active: "dev" (SpringApplication.java:660) +[2026-06-02 18:54:59,079][INFO ][main] Multiple Spring Data modules found, entering strict repository configuration mode (RepositoryConfigurationDelegate.java:295) +[2026-06-02 18:54:59,081][INFO ][main] Bootstrapping Spring Data Redis repositories in DEFAULT mode. (RepositoryConfigurationDelegate.java:143) +[2026-06-02 18:54:59,110][INFO ][main] Finished Spring Data repository scanning in 12 ms. Found 0 Redis repository interfaces. (RepositoryConfigurationDelegate.java:211) +[2026-06-02 18:55:00,573][INFO ][main] {dataSource-1} inited (DruidDataSource.java:1002) +[2026-06-02 18:55:01,181][INFO ][main] Tomcat initialized with port 1024 (http) (TomcatWebServer.java:111) +[2026-06-02 18:55:01,188][INFO ][main] Initializing ProtocolHandler ["http-nio-1024"] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][INFO ][main] Starting service [Tomcat] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,189][INFO ][main] Starting Servlet engine: [Apache Tomcat/10.1.25] (DirectJDKLog.java:173) +[2026-06-02 18:55:01,226][INFO ][main] Initializing Spring embedded WebApplicationContext (DirectJDKLog.java:173) +[2026-06-02 18:55:01,226][INFO ][main] Root WebApplicationContext: initialization completed in 3328 ms (ServletWebServerApplicationContext.java:296) +[2026-06-02 18:55:01,736][INFO ][main] ################# 系统配置缓存初始化完毕:2 ################### (ConfigService.java:58) +[2026-06-02 18:55:02,021][INFO ][main] Redisson 3.25.0 (Version.java:43) +[2026-06-02 18:55:02,144][INFO ][redisson-netty-2-5] 1 connections initialized for 127.0.0.1/127.0.0.1:6379 (ConnectionPool.java:137) +[2026-06-02 18:55:02,185][INFO ][redisson-netty-2-19] 24 connections initialized for 127.0.0.1/127.0.0.1:6379 (ConnectionPool.java:137) +[2026-06-02 18:55:03,293][INFO ][main] ==== SmartJob ==== client-manager init (SmartJobClientManager.java:67) +[2026-06-02 18:55:03,584][INFO ][main] 不需要登录的URL:[/login, /login/sendEmailCode/{loginName}, /login/getTwoFactorLoginFlag, /login/getCaptcha] (UrlConfig.java:134) +[2026-06-02 18:55:03,891][INFO ][main] 【warm-flow】,加载完成 (BeanConfig.java:152) +[2026-06-02 18:55:04,326][INFO ][main] Exposing 1 endpoint beneath base path '/actuator' (EndpointLinksResolver.java:60) +[2026-06-02 18:55:04,399][INFO ][main] Starting ProtocolHandler ["http-nio-1024"] (DirectJDKLog.java:173) +[2026-06-02 18:55:04,403][INFO ][main] Tomcat started on port 1024 (http) with context path '/' (TomcatWebServer.java:243) +[2026-06-02 18:55:04,419][INFO ][main] Started AdminApplication in 7.041 seconds (process running for 8.728) (StartupInfoLogger.java:56) +[2026-06-02 18:55:04,535][INFO ][RMI TCP Connection(3)-127.0.0.1] Initializing Spring DispatcherServlet 'dispatcherServlet' (DirectJDKLog.java:173) +[2026-06-02 18:55:04,535][INFO ][RMI TCP Connection(3)-127.0.0.1] Initializing Servlet 'dispatcherServlet' (FrameworkServlet.java:532) +[2026-06-02 18:55:04,536][INFO ][RMI TCP Connection(3)-127.0.0.1] Completed initialization in 1 ms (FrameworkServlet.java:554) +[2026-06-02 18:55:13,355][INFO ][SmartJobLauncher-0] ==== SmartJob ==== job list empty (SmartJobLauncher.java:84) +[2026-06-02 18:56:13,428][INFO ][SmartJobLauncher-0] ==== SmartJob ==== job list empty (SmartJobLauncher.java:84) +[2026-06-02 18:56:47,505][INFO ][SpringApplicationShutdownHook] ==== SmartJob ==== destroy job (SmartJobLauncher.java:151) +[2026-06-02 18:56:47,516][INFO ][SpringApplicationShutdownHook] {dataSource-1} closing ... (DruidDataSource.java:2204) +[2026-06-02 18:56:47,518][INFO ][SpringApplicationShutdownHook] {dataSource-1} closed (DruidDataSource.java:2277) diff --git a/logs/sa-admin/dev/slow-sql/slow-sql.log b/logs/sa-admin/dev/slow-sql/slow-sql.log new file mode 100644 index 0000000..1d16bfc --- /dev/null +++ b/logs/sa-admin/dev/slow-sql/slow-sql.log @@ -0,0 +1,2 @@ +[2026-05-15 16:16:09,470][ERROR][smart-heart-beat] slow sql 1447 millis. select * from t_heart_beat_record where project_path = ? and server_ip = ? and process_no =? ["/Users/wang/sanduoyun/developspace/smart-flow-master","198.18.0.1;172.20.10.11;127.0.0.1",50714] (StatFilter.java:518) +[2026-05-15 17:51:47,396][ERROR][smart-reload] slow sql 2133 millis. SELECT tag,args,identification,update_time,create_time FROM t_reload_item [] (StatFilter.java:518) diff --git a/logs/sa-admin/dev/tomcat-logs/logs/access_log.2026-06-02.log b/logs/sa-admin/dev/tomcat-logs/logs/access_log.2026-06-02.log new file mode 100644 index 0000000..0ce572c --- /dev/null +++ b/logs/sa-admin/dev/tomcat-logs/logs/access_log.2026-06-02.log @@ -0,0 +1,103 @@ +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 OPTIONS /login/getLoginInfo HTTP/1.1 200 (33561 ms) http-nio-1024-exec-1 (0 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 GET /login/getLoginInfo HTTP/1.1 200 (36716 ms) http-nio-1024-exec-1 (124 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/0 HTTP/1.1 200 (1125 ms) http-nio-1024-exec-2 (0 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 OPTIONS /oa/notice/employee/query HTTP/1.1 200 (931 ms) http-nio-1024-exec-3 (0 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 OPTIONS /oa/notice/employee/query HTTP/1.1 200 (1093 ms) http-nio-1024-exec-4 (0 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 OPTIONS /support/changeLog/queryPage HTTP/1.1 200 (1020 ms) http-nio-1024-exec-6 (0 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 OPTIONS /support/feedback/query HTTP/1.1 200 (1252 ms) http-nio-1024-exec-5 (0 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 POST /oa/notice/employee/query HTTP/1.1 200 (11817 ms) http-nio-1024-exec-5 (124 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 POST /support/changeLog/queryPage HTTP/1.1 200 (11223 ms) http-nio-1024-exec-10 (124 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 POST /support/feedback/query HTTP/1.1 200 (11884 ms) http-nio-1024-exec-1 (124 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 POST /oa/notice/employee/query HTTP/1.1 200 (12371 ms) http-nio-1024-exec-9 (124 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/0 HTTP/1.1 200 (18045 ms) http-nio-1024-exec-8 (124 byte) +[02/Jun/2026:18:55:08 +0800] - 127.0.0.1 GET /login/getTwoFactorLoginFlag HTTP/1.1 200 (56754 ms) http-nio-1024-exec-2 (91 byte) +[02/Jun/2026:18:55:09 +0800] - 127.0.0.1 GET /login/getCaptcha HTTP/1.1 200 (642008 ms) http-nio-1024-exec-3 (4043 byte) +[02/Jun/2026:18:55:19 +0800] - 127.0.0.1 OPTIONS /login HTTP/1.1 200 (1155 ms) http-nio-1024-exec-4 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 POST /login HTTP/1.1 200 (1098225 ms) http-nio-1024-exec-6 (57493 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 OPTIONS /support/dict/getAllDictData HTTP/1.1 200 (581 ms) http-nio-1024-exec-5 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 OPTIONS /support/message/getUnreadCount HTTP/1.1 200 (610 ms) http-nio-1024-exec-7 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 GET /support/message/getUnreadCount HTTP/1.1 200 (56566 ms) http-nio-1024-exec-1 (87 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 GET /support/dict/getAllDictData HTTP/1.1 200 (96085 ms) http-nio-1024-exec-10 (1570 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/0 HTTP/1.1 200 (2259 ms) http-nio-1024-exec-8 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 OPTIONS /oa/notice/employee/query HTTP/1.1 200 (3373 ms) http-nio-1024-exec-9 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 OPTIONS /support/feedback/query HTTP/1.1 200 (949 ms) http-nio-1024-exec-4 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 OPTIONS /oa/notice/employee/query HTTP/1.1 200 (1076 ms) http-nio-1024-exec-3 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 OPTIONS /support/changeLog/queryPage HTTP/1.1 200 (2471 ms) http-nio-1024-exec-2 (0 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/0 HTTP/1.1 200 (70447 ms) http-nio-1024-exec-4 (88 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 POST /support/changeLog/queryPage HTTP/1.1 200 (178257 ms) http-nio-1024-exec-2 (159 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 POST /support/feedback/query HTTP/1.1 200 (180456 ms) http-nio-1024-exec-7 (160 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 POST /oa/notice/employee/query HTTP/1.1 200 (233612 ms) http-nio-1024-exec-6 (159 byte) +[02/Jun/2026:18:55:20 +0800] - 127.0.0.1 POST /oa/notice/employee/query HTTP/1.1 200 (233414 ms) http-nio-1024-exec-1 (159 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 OPTIONS /support/tableColumn/getColumns/30001 HTTP/1.1 200 (803 ms) http-nio-1024-exec-3 (0 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 OPTIONS /support/tableColumn/getColumns/30001 HTTP/1.1 200 (872 ms) http-nio-1024-exec-10 (0 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/132 HTTP/1.1 200 (859 ms) http-nio-1024-exec-9 (0 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 OPTIONS /oa/notice/query HTTP/1.1 200 (827 ms) http-nio-1024-exec-8 (0 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 OPTIONS /oa/noticeType/getAll HTTP/1.1 200 (726 ms) http-nio-1024-exec-5 (0 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/132 HTTP/1.1 200 (50806 ms) http-nio-1024-exec-6 (88 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 GET /oa/noticeType/getAll HTTP/1.1 200 (52185 ms) http-nio-1024-exec-2 (88 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/30001 HTTP/1.1 200 (58510 ms) http-nio-1024-exec-4 (90 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 POST /oa/notice/query HTTP/1.1 200 (95796 ms) http-nio-1024-exec-7 (160 byte) +[02/Jun/2026:18:55:32 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/30001 HTTP/1.1 200 (49720 ms) http-nio-1024-exec-1 (90 byte) +[02/Jun/2026:18:55:33 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/257 HTTP/1.1 200 (600 ms) http-nio-1024-exec-3 (0 byte) +[02/Jun/2026:18:55:33 +0800] - 127.0.0.1 OPTIONS /leave/queryPage HTTP/1.1 200 (600 ms) http-nio-1024-exec-9 (0 byte) +[02/Jun/2026:18:55:33 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/257 HTTP/1.1 200 (79931 ms) http-nio-1024-exec-8 (88 byte) +[02/Jun/2026:18:55:33 +0800] - 127.0.0.1 POST /leave/queryPage HTTP/1.1 200 (82516 ms) http-nio-1024-exec-10 (160 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/253 HTTP/1.1 200 (678 ms) http-nio-1024-exec-2 (0 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 OPTIONS /flow/definition/queryPage HTTP/1.1 200 (766 ms) http-nio-1024-exec-6 (0 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 OPTIONS /support/tableColumn/getColumns/10001 HTTP/1.1 200 (743 ms) http-nio-1024-exec-5 (0 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 OPTIONS /support/tableColumn/getColumns/10001 HTTP/1.1 200 (687 ms) http-nio-1024-exec-4 (0 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/10001 HTTP/1.1 200 (84075 ms) http-nio-1024-exec-7 (90 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/253 HTTP/1.1 200 (87686 ms) http-nio-1024-exec-1 (88 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 POST /flow/definition/queryPage HTTP/1.1 200 (100290 ms) http-nio-1024-exec-3 (160 byte) +[02/Jun/2026:18:55:39 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/10001 HTTP/1.1 200 (56289 ms) http-nio-1024-exec-7 (90 byte) +[02/Jun/2026:18:55:46 +0800] - 127.0.0.1 OPTIONS /flow/execute/toDoPage?pageNum=1&pageSize=10 HTTP/1.1 200 (743 ms) http-nio-1024-exec-8 (0 byte) +[02/Jun/2026:18:55:46 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/254 HTTP/1.1 200 (898 ms) http-nio-1024-exec-9 (0 byte) +[02/Jun/2026:18:55:46 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/254 HTTP/1.1 200 (57345 ms) http-nio-1024-exec-5 (88 byte) +[02/Jun/2026:18:55:46 +0800] - 127.0.0.1 GET /flow/execute/toDoPage?pageNum=1&pageSize=10 HTTP/1.1 200 (280605 ms) http-nio-1024-exec-10 (160 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/253 HTTP/1.1 200 (1449 ms) http-nio-1024-exec-2 (0 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 OPTIONS /support/tableColumn/getColumns/10001 HTTP/1.1 200 (1400 ms) http-nio-1024-exec-1 (0 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 OPTIONS /flow/definition/queryPage HTTP/1.1 200 (1443 ms) http-nio-1024-exec-6 (0 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 OPTIONS /support/tableColumn/getColumns/10001 HTTP/1.1 200 (1449 ms) http-nio-1024-exec-4 (0 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/253 HTTP/1.1 200 (57837 ms) http-nio-1024-exec-7 (88 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/10001 HTTP/1.1 200 (68804 ms) http-nio-1024-exec-8 (90 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 POST /flow/definition/queryPage HTTP/1.1 200 (68877 ms) http-nio-1024-exec-3 (160 byte) +[02/Jun/2026:18:55:53 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/10001 HTTP/1.1 200 (70754 ms) http-nio-1024-exec-9 (90 byte) +[02/Jun/2026:18:55:54 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/254 HTTP/1.1 200 (914 ms) http-nio-1024-exec-5 (0 byte) +[02/Jun/2026:18:55:54 +0800] - 127.0.0.1 OPTIONS /flow/execute/toDoPage?pageNum=1&pageSize=10 HTTP/1.1 200 (914 ms) http-nio-1024-exec-10 (0 byte) +[02/Jun/2026:18:55:54 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/254 HTTP/1.1 200 (90798 ms) http-nio-1024-exec-6 (88 byte) +[02/Jun/2026:18:55:54 +0800] - 127.0.0.1 GET /flow/execute/toDoPage?pageNum=1&pageSize=10 HTTP/1.1 200 (313977 ms) http-nio-1024-exec-2 (160 byte) +[02/Jun/2026:18:55:55 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/255 HTTP/1.1 200 (928 ms) http-nio-1024-exec-1 (0 byte) +[02/Jun/2026:18:55:55 +0800] - 127.0.0.1 OPTIONS /flow/execute/donePage?pageNum=1&pageSize=10 HTTP/1.1 200 (928 ms) http-nio-1024-exec-4 (0 byte) +[02/Jun/2026:18:55:55 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/255 HTTP/1.1 200 (59595 ms) http-nio-1024-exec-8 (88 byte) +[02/Jun/2026:18:55:55 +0800] - 127.0.0.1 GET /flow/execute/donePage?pageNum=1&pageSize=10 HTTP/1.1 200 (315290 ms) http-nio-1024-exec-7 (160 byte) +[02/Jun/2026:18:55:56 +0800] - 127.0.0.1 OPTIONS /flow/execute/copyPage?pageNum=1&pageSize=10 HTTP/1.1 200 (972 ms) http-nio-1024-exec-9 (0 byte) +[02/Jun/2026:18:55:56 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/256 HTTP/1.1 200 (972 ms) http-nio-1024-exec-3 (0 byte) +[02/Jun/2026:18:55:56 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/256 HTTP/1.1 200 (68533 ms) http-nio-1024-exec-10 (88 byte) +[02/Jun/2026:18:55:56 +0800] - 127.0.0.1 GET /flow/execute/copyPage?pageNum=1&pageSize=10 HTTP/1.1 200 (248546 ms) http-nio-1024-exec-5 (160 byte) +[02/Jun/2026:18:55:57 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/253 HTTP/1.1 200 (75474 ms) http-nio-1024-exec-1 (88 byte) +[02/Jun/2026:18:55:57 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/10001 HTTP/1.1 200 (77439 ms) http-nio-1024-exec-6 (90 byte) +[02/Jun/2026:18:55:57 +0800] - 127.0.0.1 POST /flow/definition/queryPage HTTP/1.1 200 (84910 ms) http-nio-1024-exec-2 (160 byte) +[02/Jun/2026:18:55:57 +0800] - 127.0.0.1 GET /support/tableColumn/getColumns/10001 HTTP/1.1 200 (67450 ms) http-nio-1024-exec-4 (90 byte) +[02/Jun/2026:18:56:03 +0800] - 127.0.0.1 OPTIONS /flow/definition/add HTTP/1.1 200 (1770 ms) http-nio-1024-exec-8 (0 byte) +[02/Jun/2026:18:56:04 +0800] - 127.0.0.1 POST /flow/definition/add HTTP/1.1 200 (591842 ms) http-nio-1024-exec-7 (90 byte) +[02/Jun/2026:18:56:04 +0800] - 127.0.0.1 OPTIONS /flow/definition/queryPage HTTP/1.1 200 (1749 ms) http-nio-1024-exec-9 (0 byte) +[02/Jun/2026:18:56:04 +0800] - 127.0.0.1 POST /flow/definition/queryPage HTTP/1.1 200 (145708 ms) http-nio-1024-exec-3 (465 byte) +[02/Jun/2026:18:56:08 +0800] - 127.0.0.1 GET /warm-flow-ui/index.html?id=2061763773549461506&disabled=false&Authorization=Bearer%20769d485013454588bae0683951df166e HTTP/1.1 200 (7228 ms) http-nio-1024-exec-10 (5765 byte) +[02/Jun/2026:18:56:08 +0800] - 127.0.0.1 GET /warm-flow-ui/css/index-Da60mrLX.css HTTP/1.1 200 (6007 ms) http-nio-1024-exec-1 (378939 byte) +[02/Jun/2026:18:56:08 +0800] - 127.0.0.1 GET /warm-flow-ui/js/index-Bfpt7KC4.js HTTP/1.1 200 (28252 ms) http-nio-1024-exec-5 (2923865 byte) +[02/Jun/2026:18:56:08 +0800] - 127.0.0.1 GET /warm-flow-ui/config HTTP/1.1 200 (14453 ms) http-nio-1024-exec-6 (87 byte) +[02/Jun/2026:18:56:08 +0800] - 127.0.0.1 GET /warm-flow/query-def/2061763773549461506 HTTP/1.1 200 (172483 ms) http-nio-1024-exec-2 (2058 byte) +[02/Jun/2026:18:56:11 +0800] - 127.0.0.1 GET /warm-flow/handler-feedback HTTP/1.1 200 (4043 ms) http-nio-1024-exec-8 (54 byte) +[02/Jun/2026:18:56:11 +0800] - 127.0.0.1 GET /warm-flow/node-ext HTTP/1.1 200 (5785 ms) http-nio-1024-exec-4 (934 byte) +[02/Jun/2026:18:56:23 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/256 HTTP/1.1 200 (1103 ms) http-nio-1024-exec-7 (0 byte) +[02/Jun/2026:18:56:23 +0800] - 127.0.0.1 OPTIONS /flow/execute/copyPage?pageNum=1&pageSize=10 HTTP/1.1 200 (1103 ms) http-nio-1024-exec-9 (0 byte) +[02/Jun/2026:18:56:23 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/256 HTTP/1.1 200 (70857 ms) http-nio-1024-exec-10 (88 byte) +[02/Jun/2026:18:56:23 +0800] - 127.0.0.1 GET /flow/execute/copyPage?pageNum=1&pageSize=10 HTTP/1.1 200 (221223 ms) http-nio-1024-exec-3 (160 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 OPTIONS /oa/notice/employee/query HTTP/1.1 200 (526 ms) http-nio-1024-exec-6 (0 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 OPTIONS /support/helpDoc/queryHelpDocByRelationId/0 HTTP/1.1 200 (839 ms) http-nio-1024-exec-5 (0 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 OPTIONS /oa/notice/employee/query HTTP/1.1 200 (1537 ms) http-nio-1024-exec-1 (0 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 OPTIONS /support/changeLog/queryPage HTTP/1.1 200 (1546 ms) http-nio-1024-exec-2 (0 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 GET /support/helpDoc/queryHelpDocByRelationId/0 HTTP/1.1 200 (69491 ms) http-nio-1024-exec-4 (88 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 POST /support/changeLog/queryPage HTTP/1.1 200 (73561 ms) http-nio-1024-exec-9 (159 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 POST /oa/notice/employee/query HTTP/1.1 200 (118811 ms) http-nio-1024-exec-8 (159 byte) +[02/Jun/2026:18:56:27 +0800] - 127.0.0.1 POST /oa/notice/employee/query HTTP/1.1 200 (132858 ms) http-nio-1024-exec-2 (159 byte) diff --git a/logs/sa-admin/dev/warn/warn.log b/logs/sa-admin/dev/warn/warn.log new file mode 100644 index 0000000..4312d47 --- /dev/null +++ b/logs/sa-admin/dev/warn/warn.log @@ -0,0 +1,34 @@ +[2026-06-02 18:54:59,550][WARN ][main] Bean 'mybatisPlusConfig' of type [net.lab1024.sa.base.config.MybatisPlusConfig$$SpringCGLIB$$0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:54:59,556][WARN ][main] Bean 'paginationInterceptor' of type [com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:54:59,559][WARN ][main] Bean 'myBatisPlugin' of type [net.lab1024.sa.admin.module.system.datascope.MyBatisPlugin] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:54:59,563][WARN ][main] Bean 'dataSourceConfig' of type [net.lab1024.sa.base.config.DataSourceConfig$$SpringCGLIB$$0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:54:59,565][WARN ][main] Bean 'jdkRegexpMethodPointcut' of type [org.springframework.aop.support.JdkRegexpMethodPointcut] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:54:59,567][WARN ][main] Bean 'defaultPointcutAdvisor' of type [org.springframework.aop.support.DefaultPointcutAdvisor] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,576][WARN ][main] Bean 'druidDataSource' of type [com.alibaba.druid.pool.DruidDataSource] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,912][WARN ][main] [net.lab1024.sa.base.module.support.operatelog.OperateLogDao.deleteByIds] Has been loaded by XML or SqlProvider or Mybatis's Annotation, so ignoring this injection for [class com.baomidou.mybatisplus.core.injector.methods.DeleteByIds] (AbstractMethod.java:407) +[2026-06-02 18:55:00,956][WARN ][main] Bean 'sqlSessionFactory' of type [org.apache.ibatis.session.defaults.DefaultSqlSessionFactory] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,958][WARN ][main] Bean 'org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration' of type [org.springframework.boot.autoconfigure.sql.init.DataSourceInitializationConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,964][WARN ][main] Bean 'spring.sql.init-org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties' of type [org.springframework.boot.autoconfigure.sql.init.SqlInitializationProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,967][WARN ][main] Bean 'dataSourceScriptDatabaseInitializer' of type [org.springframework.boot.autoconfigure.sql.init.SqlDataSourceScriptDatabaseInitializer] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,971][WARN ][main] Bean 'mybatis-plus-com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties' of type [com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,976][WARN ][main] Bean 'mybatisDatabaseIdProviderConfig' of type [net.lab1024.sa.base.config.MybatisDatabaseIdProviderConfig$$SpringCGLIB$$0] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,976][WARN ][main] Bean 'databaseIdProvider' of type [org.apache.ibatis.mapping.VendorDatabaseIdProvider] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,979][WARN ][main] Bean 'com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration' of type [com.baomidou.mybatisplus.autoconfigure.MybatisPlusAutoConfiguration] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,983][WARN ][main] Bean 'sqlSessionTemplate' of type [org.mybatis.spring.SqlSessionTemplate] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,985][WARN ][main] Bean 'reloadItemDao' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,989][WARN ][main] Bean 'reloadItemDao' of type [jdk.proxy2.$Proxy131] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,998][WARN ][main] Bean 'reloadResultDao' of type [org.mybatis.spring.mapper.MapperFactoryBean] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:00,999][WARN ][main] Bean 'reloadResultDao' of type [jdk.proxy2.$Proxy133] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:01,008][WARN ][main] Bean 'reloadCommand' of type [net.lab1024.sa.base.module.support.reload.ReloadCommand] is not eligible for getting processed by all BeanPostProcessors (for example: not eligible for auto-proxying). Is this bean getting eagerly injected into a currently created BeanPostProcessor [smartReloadManager]? Check the corresponding BeanPostProcessor declaration and its dependencies. (PostProcessorRegistrationDelegate.java:437) +[2026-06-02 18:55:02,045][WARN ][main] Can not find io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider in the classpath, fallback to system defaults. This may result in incorrect DNS resolutions on MacOS. Check whether you have a dependency on 'io.netty:netty-resolver-dns-native-macos' (DnsServerAddressStreamProviders.java:70) +[2026-06-02 18:55:04,288][WARN ][main] Cannot find template location: [classpath:/templates/] (please add some templates, check your FreeMarker configuration, or set spring.freemarker.check-template-location=false) (FreeMarkerAutoConfiguration.java:66) +[2026-06-02 18:55:04,408][WARN ][main] +-------------【sa-admin】 服务已成功启动 (sa-admin started successfully)------------- + 当前启动环境: dev , 开发环境 + 返回码初始化: 完成15个返回码初始化 + 服务本机地址: http://localhost:1024/ + 服务外网地址: http://198.18.0.1:1024/ + Swagger地址: http://localhost:1024/swagger-ui/index.html + knife4j地址: http://localhost:1024/doc.html +------------------------------------------------------------------------------------- + (WebServerListener.java:66) diff --git a/smart-flow-api/pom.xml b/smart-flow-api/pom.xml new file mode 100644 index 0000000..8584520 --- /dev/null +++ b/smart-flow-api/pom.xml @@ -0,0 +1,465 @@ + + 4.0.0 + + net.lab1024 + sa-parent + 3.0.1 + pom + + sa-parent + SmartFlow project + + + sa-base + sa-admin + + + + 21 + UTF-8 + UTF-8 + 3.3.1 + 2.0.8 + 6.4.3 + 8.3.0 + 8.6.0 + 3.5.7 + 3.9.1 + 4.4.0 + 2.0.52 + 1.2.23 + 1.4.2 + 20.0 + 1.21 + 0.9.11 + 2.15.0 + 3.12.0 + 4.4 + 1.26.0 + 1.13 + 1.9 + 2.12.0 + 1.0.0 + 5.2.4 + 1.4 + 1.11.842 + 2.23.1 + 5.8.29 + 2.3 + 0.9.1 + 0.9.0 + 3.1 + 1.41.0 + 1.7.3 + 2.7.0 + 1.80 + 2.13.4 + 2.16.1 + 1.2.0 + 3.25.0 + 2.2 + 2.3.33 + 1.18.1 + 3.1.0 + + + + + + + + org.springframework.boot + spring-boot-dependencies + ${springboot.version} + pom + import + + + + + com.mysql + mysql-connector-j + ${mysql.version} + + + + + cn.com.kingbase + kingbase8 + ${kingbase8.version} + + + + com.baomidou + mybatis-plus-spring-boot3-starter + ${mybatis-plus.version} + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.security + spring-security-crypto + ${spring-security-crypto.version} + + + + p6spy + p6spy + ${p6spy.version} + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + ${knife4j.version} + + + + com.alibaba + fastjson + ${fastjson.version} + + + + + com.alibaba + druid-spring-boot-3-starter + ${druid.version} + + + + com.googlecode.concurrentlinkedhashmap + concurrentlinkedhashmap-lru + ${google-linkedhashmap.version} + + + + com.google.guava + guava + ${google-guava.version} + + + + eu.bitwalker + UserAgentUtils + ${user-agent-utils.version} + + + + org.reflections + reflections + ${reflections.version} + + + guava + com.google.guava + + + + + + commons-io + commons-io + ${commons-io.version} + + + + org.apache.commons + commons-lang3 + ${commons-lang3.version} + + + + org.apache.commons + commons-collections4 + ${commons-collections4.version} + + + + org.apache.commons + commons-compress + ${commons-compress.version} + + + + commons-codec + commons-codec + ${commons-codec.version} + + + + com.amazonaws + aws-java-sdk-s3 + ${aws-java-sdk.version} + + + commons-logging + commons-logging + + + + + + org.apache.commons + commons-text + ${commons-text.version} + + + + cn.hutool + hutool-all + ${hutool.version} + + + + io.jsonwebtoken + jjwt + ${jjwt.version} + + + + com.auth0 + jwks-rsa + ${jwks-rsa.version} + + + + + org.apache.velocity + velocity-engine-core + ${velocity-engine-core.version} + + + org.apache.velocity.tools + velocity-tools-generic + ${velocity-tools.version} + + + + + + cn.dev33 + sa-token-spring-boot3-starter + ${sa-token.version} + + + + + cn.dev33 + sa-token-redis-jackson + ${sa-token.version} + + + + + + org.dromara.warm + warm-flow-mybatis-plus-sb3-starter + ${warm-flow.version} + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + ${warm-flow.version} + + + org.dromara.warm + warm-flow-mybatis-plus-core + ${warm-flow.version} + + + + + + org.lionsoul + ip2region + ${ip2region.version} + + + + org.bouncycastle + bcprov-jdk18on + ${bcprov.version} + + + + cn.idev.excel + fastexcel + ${fast-excel.version} + + + logback-classic + ch.qos.logback + + + + + + org.apache.poi + poi + ${poi.version} + + + + org.apache.poi + poi-ooxml + ${poi.version} + + + + org.apache.poi + poi-scratchpad + ${poi.version} + + + + org.apache.poi + ooxml-schemas + ${ooxml-schemas.version} + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + ${jackson-datatype-jsr310.version} + + + + com.fasterxml.jackson.dataformat + jackson-dataformat-yaml + ${jackson-dataformat-yaml.version} + + + + net.1024lab + smartdb + ${smartdb.version} + + + + + org.redisson + redisson-spring-boot-starter + ${redisson.version} + + + + org.yaml + snakeyaml + ${snakeyaml.version} + + + + org.jsoup + jsoup + ${jsoup.version} + + + + org.freemarker + freemarker + ${freemarker.version} + + + + org.apache.tika + tika-core + ${tika.version} + + + + + + + + ${project.name}-${profiles.active}-${project.version} + + + false + src/main/resources + + dev/* + test/* + pre/* + prod/* + + + + + src/main/resources/${profiles.active} + true + + *.yaml + + + + + src/main/resources/${profiles.active} + false + + *.* + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.13.0 + + -parameters + 21 + 21 + UTF-8 + + + + org.springframework.boot + spring-boot-maven-plugin + ${springboot.version} + + + + + + + + dev + + dev + + + true + + + + + test + + test + + + + + pre + + pre + + + + + prod + + prod + + + + + diff --git a/smart-flow-api/sa-admin/pom.xml b/smart-flow-api/sa-admin/pom.xml new file mode 100644 index 0000000..9950d7f --- /dev/null +++ b/smart-flow-api/sa-admin/pom.xml @@ -0,0 +1,67 @@ + + 4.0.0 + + net.lab1024 + sa-parent + 3.0.1 + ../pom.xml + + + sa-admin + 3.0.1 + jar + + sa-admin + sa-admin project + + + + + net.lab1024 + sa-base + ${project.version} + + + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + org.dromara.warm + warm-flow-mybatis-plus-core + + + + org.dromara.warm + warm-flow-mybatis-plus-sb3-starter + + + org.dromara.warm + warm-flow-plugin-ui-sb-web + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + net.lab1024.sa.admin.AdminApplication + + true + + + + + repackage + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/AdminApplication.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/AdminApplication.java new file mode 100644 index 0000000..2b958cd --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/AdminApplication.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.admin; + +import net.lab1024.sa.base.listener.Ip2RegionListener; +import net.lab1024.sa.base.listener.LogVariableListener; +import org.apache.ibatis.annotations.Mapper; +import org.mybatis.spring.annotation.MapperScan; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.security.servlet.UserDetailsServiceAutoConfiguration; +import org.springframework.cache.annotation.EnableCaching; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.EnableAspectJAutoProxy; +import org.springframework.scheduling.annotation.EnableScheduling; + +/** + * SmartAdmin 项目启动类 + * + * @Date 2022-08-29 21:00:58 + * @Author wzh + */ +@EnableCaching +@EnableScheduling +@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) +@ComponentScan(AdminApplication.COMPONENT_SCAN) +@MapperScan(value = AdminApplication.COMPONENT_SCAN, annotationClass = Mapper.class) +@SpringBootApplication(exclude = {UserDetailsServiceAutoConfiguration.class}) +public class AdminApplication { + + public static final String COMPONENT_SCAN = "net.lab1024.sa"; + + public static void main(String[] args) { + SpringApplication application = new SpringApplication(AdminApplication.class); + // 添加 日志监听器,使 log4j2-spring.xml 可以间接读取到配置文件的属性 + application.addListeners(new LogVariableListener(), new Ip2RegionListener()); + application.run(args); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/MvcConfig.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/MvcConfig.java new file mode 100644 index 0000000..3cb50b2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/MvcConfig.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.admin.config; + +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.interceptor.AdminInterceptor; +import net.lab1024.sa.base.config.SwaggerConfig; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * web相关配置 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ +@Configuration +public class MvcConfig implements WebMvcConfigurer { + + @Resource + private AdminInterceptor adminInterceptor; + + + + @Override + public void addInterceptors(InterceptorRegistry registry) { + registry.addInterceptor(adminInterceptor) + .excludePathPatterns(SwaggerConfig.SWAGGER_WHITELIST) + .addPathPatterns("/**") + // 以上是sa-token案例,下面才是需要排除的地址 + .excludePathPatterns("/warm-flow-ui/**", "/warm-flow/**"); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("doc.html").addResourceLocations("classpath:/META-INF/resources/"); + registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/"); + registry.addResourceHandler("/warm-flow-ui/**").addResourceLocations("classpath:/META-INF/resources/warm-flow-ui/"); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/OperateLogAspectConfig.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/OperateLogAspectConfig.java new file mode 100644 index 0000000..c8afe15 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/config/OperateLogAspectConfig.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.admin.config; + +import net.lab1024.sa.base.module.support.operatelog.core.OperateLogAspect; +import net.lab1024.sa.base.module.support.operatelog.core.OperateLogConfig; +import org.springframework.context.annotation.Configuration; + +import java.util.Arrays; + +/** + * 操作日志切面 配置 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +@Configuration +public class OperateLogAspectConfig extends OperateLogAspect { + + /** + * 配置信息 + */ + @Override + public OperateLogConfig getOperateLogConfig() { + return OperateLogConfig.builder() + .corePoolSize(1) + .queueCapacity(10000) + .ignoreUrlPatterns(Arrays.asList( + "/support/operateLog/", + "/support/file/upload", + "/support/file/downLoad", + "/support/captcha", + "/support/heartBeat", + "/login/sendEmailCode" + )) + .maxParamLength(4000) + .maxResultLength(4000) + .recordResponse(true) + // 先关闭查询类日志(GET / QUERY),避免日志量过大;需要时改为 true + .recordQuery(false) + .build(); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminCacheConst.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminCacheConst.java new file mode 100644 index 0000000..cfab585 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminCacheConst.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.admin.constant; + +import net.lab1024.sa.base.constant.CacheKeyConst; + +/** + * 缓存 key + * + * @Date 2022-01-07 18:59:22 + * @Author wzh + */ +public class AdminCacheConst extends CacheKeyConst { + + public static class Department { + + /** + * 部门列表 + */ + public static final String DEPARTMENT_LIST_CACHE = "department_list_cache"; + + /** + * 部门map + */ + public static final String DEPARTMENT_MAP_CACHE = "department_map_cache"; + + /** + * 部门树 + */ + public static final String DEPARTMENT_TREE_CACHE = "department_tree_cache"; + + /** + * 某个部门以及下级的id列表 + */ + public static final String DEPARTMENT_SELF_CHILDREN_CACHE = "department_self_children_cache"; + + /** + * 部门路径 缓存 + */ + public static final String DEPARTMENT_PATH_CACHE = "department_path_cache"; + + } + + /** + * 分类相关缓存 + */ + public static class Category { + + public static final String CATEGORY_ENTITY = "category_cache"; + + public static final String CATEGORY_SUB = "category_sub_cache"; + + public static final String CATEGORY_TREE = "category_tree_cache"; + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminRedisKeyConst.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminRedisKeyConst.java new file mode 100644 index 0000000..757e625 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminRedisKeyConst.java @@ -0,0 +1,14 @@ +package net.lab1024.sa.admin.constant; + +import net.lab1024.sa.base.constant.RedisKeyConst; + +/** + * redis key 常量类 + * + * @Date 2022-01-07 18:59:22 + * @Author wzh + */ +public class AdminRedisKeyConst extends RedisKeyConst { + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java new file mode 100644 index 0000000..2f49229 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/constant/AdminSwaggerTagConst.java @@ -0,0 +1,65 @@ +package net.lab1024.sa.admin.constant; + +import net.lab1024.sa.base.constant.SwaggerTagConst; + +/** + * swagger + * + * @Date 2022-01-07 18:59:22 + * @Author wzh + */ +public class AdminSwaggerTagConst extends SwaggerTagConst { + + public static class Business { + public static final String MANAGER_CATEGORY = "ERP进销存-分类管理"; + + public static final String MANAGER_GOODS = "ERP进销存-商品管理"; + + public static final String OA_BANK = "OA办公-银行卡信息"; + + public static final String OA_ENTERPRISE = "OA办公-企业"; + + public static final String OA_INVOICE = "OA办公-发票信息"; + + public static final String OA_NOTICE = "OA办公-通知公告"; + + } + + + public static class System { + + public static final String SYSTEM_LOGIN = "系统-员工登录"; + + public static final String SYSTEM_EMPLOYEE = "系统-员工管理"; + + public static final String SYSTEM_DEPARTMENT = "系统-部门管理"; + + public static final String SYSTEM_MENU = "系统-菜单"; + + public static final String SYSTEM_DATA_SCOPE = "系统-系统-数据范围"; + + public static final String SYSTEM_ROLE = "系统-角色"; + + public static final String SYSTEM_ROLE_DATA_SCOPE = "系统-角色-数据范围"; + + public static final String SYSTEM_ROLE_EMPLOYEE = "系统-角色-员工"; + + public static final String SYSTEM_ROLE_MENU = "系统-角色-菜单"; + + public static final String SYSTEM_POSITION = "系统-职务管理"; + + public static final String SYSTEM_MESSAGE = "系统-消息"; + + + + } + public static class Flow { + + public static final String FLOW_DEFINITION = "工作流-流程定义"; + + public static final String FLOW_INSTANCE = "工作流-流程实例"; + + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java new file mode 100644 index 0000000..61ab3c9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/interceptor/AdminInterceptor.java @@ -0,0 +1,140 @@ +package net.lab1024.sa.admin.interceptor; + +import cn.dev33.satoken.annotation.SaIgnore; +import cn.dev33.satoken.exception.SaTokenException; +import cn.dev33.satoken.stp.StpUtil; +import cn.dev33.satoken.strategy.SaAnnotationStrategy; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee; +import net.lab1024.sa.admin.module.system.login.service.LoginService; +import net.lab1024.sa.base.common.annoation.NoNeedLogin; +import net.lab1024.sa.base.common.code.SystemErrorCode; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.common.util.SmartResponseUtil; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import java.lang.reflect.Method; + +/** + * admin 拦截器 + * + * @Date 2023/7/26 20:20:33 + * @Author wzh + */ + +@Component +@Slf4j +public class AdminInterceptor implements HandlerInterceptor { + + @Resource + private LoginService loginService; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { + + // OPTIONS请求直接return + if (HttpMethod.OPTIONS.toString().equals(request.getMethod())) { + response.setStatus(HttpStatus.NO_CONTENT.value()); + return false; + } + + boolean isHandler = handler instanceof HandlerMethod; + if (!isHandler) { + return true; + } + + try { + // --------------- 第一步: 根据token 获取用户 --------------- + + String tokenValue = StpUtil.getTokenValue(); + String loginId = (String) StpUtil.getLoginIdByToken(tokenValue); + RequestEmployee requestEmployee = loginService.getLoginEmployee(loginId, request); + + // --------------- 第二步: 校验 登录 --------------- + + Method method = ((HandlerMethod) handler).getMethod(); + NoNeedLogin noNeedLogin = ((HandlerMethod) handler).getMethodAnnotation(NoNeedLogin.class); + if (noNeedLogin != null) { + checkActiveTimeout(requestEmployee); + return true; + } + + if (requestEmployee == null) { + SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID)); + return false; + } + + // 检测token 活跃频率 + checkActiveTimeout(requestEmployee); + + + // --------------- 第三步: 校验 权限 --------------- + + SmartRequestUtil.setRequestUser(requestEmployee); + if (SaAnnotationStrategy.instance.isAnnotationPresent.apply(method, SaIgnore.class)) { + return true; + } + + // 如果是超级管理员的话,不需要校验权限 + if (requestEmployee.getAdministratorFlag()) { + return true; + } + + SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method); + + } catch (SaTokenException e) { + /* + * sa-token 异常状态码 + * 具体请看: https://sa-token.cc/doc.html#/fun/exception-code + */ + int code = e.getCode(); + if (code == 11041 || code == 11051) { + SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.NO_PERMISSION)); + } else if (code == 11016) { + SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_ACTIVE_TIMEOUT)); + } else if (code >= 11011 && code <= 11015) { + SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.LOGIN_STATE_INVALID)); + } else { + SmartResponseUtil.write(response, ResponseDTO.error(UserErrorCode.PARAM_ERROR)); + } + return false; + } catch (Throwable e) { + SmartResponseUtil.write(response, ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR)); + log.error(e.getMessage(), e); + return false; + } + + // 通过验证 + return true; + } + + + /** + * 检测:token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结 + */ + private void checkActiveTimeout(RequestEmployee requestEmployee) { + // 用户不在线,也不用检测 + if (requestEmployee == null) { + return; + } + + StpUtil.checkActiveTimeout(); + StpUtil.updateLastActiveToNow(); + } + + + @Override + public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { + // 清除上下文 + SmartRequestUtil.remove(); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/constant/CategoryTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/constant/CategoryTypeEnum.java new file mode 100644 index 0000000..b408a08 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/constant/CategoryTypeEnum.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.admin.module.business.category.constant; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 分类类型 枚举 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@AllArgsConstructor +@Getter +public enum CategoryTypeEnum implements BaseEnum { + + /** + * 1 商品 + */ + GOODS(1, "商品"), + + /** + * 2 自定义 + */ + CUSTOM(2, "自定义"), + + ; + + private final Integer value; + + private final String desc; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/controller/CategoryController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/controller/CategoryController.java new file mode 100644 index 0000000..dcca8ce --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/controller/CategoryController.java @@ -0,0 +1,66 @@ +package net.lab1024.sa.admin.module.business.category.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.business.category.domain.form.CategoryAddForm; +import net.lab1024.sa.admin.module.business.category.domain.form.CategoryTreeQueryForm; +import net.lab1024.sa.admin.module.business.category.domain.form.CategoryUpdateForm; +import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO; +import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryVO; +import net.lab1024.sa.admin.module.business.category.service.CategoryService; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 类目 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.Business.MANAGER_CATEGORY) +public class CategoryController { + + @Resource + private CategoryService categoryService; + + @Operation(summary = "添加类目") + @PostMapping("/category/add") + @SaCheckPermission("category:add") + public ResponseDTO add(@RequestBody @Valid CategoryAddForm addForm) { + return categoryService.add(addForm); + } + + @Operation(summary = "更新类目 ") + @PostMapping("/category/update") + @SaCheckPermission("category:update") + public ResponseDTO update(@RequestBody @Valid CategoryUpdateForm updateForm) { + return categoryService.update(updateForm); + } + + @Operation(summary = "查询类目详情") + @GetMapping("/category/{categoryId}") + public ResponseDTO queryDetail(@PathVariable Long categoryId) { + return categoryService.queryDetail(categoryId); + } + + @Operation(summary = "查询类目层级树") + @PostMapping("/category/tree") + @SaCheckPermission("category:tree") + public ResponseDTO> queryTree(@RequestBody @Valid CategoryTreeQueryForm queryForm) { + return categoryService.queryTree(queryForm); + } + + @Operation(summary = "删除类目") + @GetMapping("/category/delete/{categoryId}") + @SaCheckPermission("category:delete") + public ResponseDTO delete(@PathVariable Long categoryId) { + return categoryService.delete(categoryId); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.java new file mode 100644 index 0000000..a676fd5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/dao/CategoryDao.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.admin.module.business.category.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; +import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 类目 dao + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Mapper +public interface CategoryDao extends BaseMapper { + + /** + * 根据父级id 类型 查询子类 + * + * @param parentIdList 父级id集合 + * @param deletedFlag 删除标识 + * @return 列表 + */ + List queryByParentId(@Param("parentIdList") List parentIdList, + @Param("deletedFlag") Boolean deletedFlag); + + /** + * 根据父级id 类型 查询子类 + * + * @param parentIdList 父级id集合 + * @param categoryType {@link CategoryTypeEnum} + * @param deletedFlag 删除标识 + * @return 列表 + */ + List queryByParentIdAndType(@Param("parentIdList") List parentIdList, + @Param("categoryType") Integer categoryType, + @Param("deletedFlag") Boolean deletedFlag); + + /** + * 某个类型的所有 + */ + List queryByType(@Param("categoryType") Integer categoryType, + @Param("deletedFlag") Boolean deletedFlag); + + /** + * 根据类型和id查询 + */ + CategoryEntity selectByTypeAndId(@Param("categoryType") Integer categoryType, @Param("categoryId") Long categoryId); + + /** + * 查看类目 具体条件 看sql + */ + CategoryEntity selectOne(CategoryEntity entity); + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategoryBaseDTO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategoryBaseDTO.java new file mode 100644 index 0000000..4849d60 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategoryBaseDTO.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.admin.module.business.category.domain.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 类目 基础属性 DTO 类 + * + * @author 胡克 + * @date 2021/1/20 16:17 + */ +@Data +public class CategoryBaseDTO { + + @Schema(description = "类目名称", required = true) + @NotBlank(message = "类目名称不能为空") + @Length(max = 20, message = "类目名称最多20字符") + private String categoryName; + + @SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class) + @CheckEnum(value = CategoryTypeEnum.class, required = true, message = "分类错误") + private Integer categoryType; + + @Schema(description = "父级类目id|可选") + private Long parentId; + + @Schema(description = "排序|可选") + private Integer sort; + + @Schema(description = "备注|可选") + @Length(max = 200, message = "备注最多200字符") + private String remark; + + @Schema(description = "禁用状态") + @NotNull(message = "禁用状态不能为空") + private Boolean disabledFlag; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategorySimpleDTO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategorySimpleDTO.java new file mode 100644 index 0000000..97d0310 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/dto/CategorySimpleDTO.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.admin.module.business.category.domain.dto; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 类目 基础属性 DTO 类 + * + * @author 胡克 + * @date 2021/1/20 16:17 + */ +@Data +public class CategorySimpleDTO { + + @Schema(description = "类目id") + private Long categoryId; + + @Schema(description = "类目名称") + private String categoryName; + + @Schema(description = "类目层级全称") + private String categoryFullName; + + @Schema(description = "父级id") + private Long parentId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/entity/CategoryEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/entity/CategoryEntity.java new file mode 100644 index 0000000..8ebeeca --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/entity/CategoryEntity.java @@ -0,0 +1,67 @@ +package net.lab1024.sa.admin.module.business.category.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 类目 实体类 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Data +@TableName("t_category") +public class CategoryEntity implements Serializable { + + private static final long serialVersionUID = 1L; + + @TableId(type = IdType.AUTO) + private Long categoryId; + + /** + * 类目名称 + */ + private String categoryName; + + /** + * 类目 类型 + * + * @see CategoryTypeEnum + */ + private Integer categoryType; + + /** + * 父级类目id + */ + private Long parentId; + + /** + * 是否禁用 + */ + private Boolean disabledFlag; + + /** + * 排序 + */ + private Integer sort; + + /** + * 删除状态 + */ + private Boolean deletedFlag; + + /** + * 备注 + */ + private String remark; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryAddForm.java new file mode 100644 index 0000000..01b3a1d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryAddForm.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.business.category.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 类目 添加 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Data +public class CategoryAddForm { + + @Schema(description = "类目名称", required = true) + @NotBlank(message = "类目名称不能为空") + @Length(max = 20, message = "类目名称最多20字符") + private String categoryName; + + @SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class) + @CheckEnum(value = CategoryTypeEnum.class, required = true, message = "分类错误") + private Integer categoryType; + + @Schema(description = "父级类目id|可选") + private Long parentId; + + @Schema(description = "排序|可选") + private Integer sort; + + @Schema(description = "备注|可选") + @Length(max = 200, message = "备注最多200字符") + private String remark; + + @Schema(description = "禁用状态") + @NotNull(message = "禁用状态不能为空") + private Boolean disabledFlag; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryTreeQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryTreeQueryForm.java new file mode 100644 index 0000000..25835e8 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryTreeQueryForm.java @@ -0,0 +1,22 @@ +package net.lab1024.sa.admin.module.business.category.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +/** + * 类目 层级树查询 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Data +public class CategoryTreeQueryForm { + + @SchemaEnum(desc = "分类类型|可选", value = CategoryTypeEnum.class) + private Integer categoryType; + + @Schema(description = "父级类目id|可选") + private Long parentId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryUpdateForm.java new file mode 100644 index 0000000..49acbcf --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/form/CategoryUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.business.category.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 类目 更新 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Data +public class CategoryUpdateForm extends CategoryAddForm { + + @Schema(description = "类目id") + @NotNull(message = "类目id不能为空") + private Long categoryId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryTreeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryTreeVO.java new file mode 100644 index 0000000..a7a6962 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryTreeVO.java @@ -0,0 +1,51 @@ +package net.lab1024.sa.admin.module.business.category.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 类目 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Data +public class CategoryTreeVO { + + @Schema(description = "类目名称", required = true) + private String categoryName; + + @SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class) + private Integer categoryType; + + @Schema(description = "父级类目id|可选") + private Long parentId; + + @Schema(description = "排序|可选") + private Integer sort; + + @Schema(description = "备注|可选") + private String remark; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "类目id") + private Long categoryId; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; + + private String label; + private Long value; + private String categoryFullName; + private List children; + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryVO.java new file mode 100644 index 0000000..6c5754a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/domain/vo/CategoryVO.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.admin.module.business.category.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +import java.time.LocalDateTime; + +/** + * 类目 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Data +public class CategoryVO { + + @Schema(description = "类目名称", required = true) + private String categoryName; + + @SchemaEnum(desc = "分类类型", value = CategoryTypeEnum.class) + private Integer categoryType; + + @Schema(description = "父级类目id|可选") + private Long parentId; + + @Schema(description = "排序|可选") + private Integer sort; + + @Schema(description = "备注|可选") + private String remark; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "类目id") + private Long categoryId; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/manager/CategoryCacheManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/manager/CategoryCacheManager.java new file mode 100644 index 0000000..d6eed13 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/manager/CategoryCacheManager.java @@ -0,0 +1,110 @@ +package net.lab1024.sa.admin.module.business.category.manager; + +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.constant.AdminCacheConst; +import net.lab1024.sa.admin.module.business.category.dao.CategoryDao; +import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity; +import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 类目 查询 缓存 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Service +@Slf4j +public class CategoryCacheManager { + + + @Resource + private CategoryDao categoryDao; + + + /** + * 根据类目id 移除缓存 + */ + @CacheEvict(value = {AdminCacheConst.Category.CATEGORY_ENTITY, AdminCacheConst.Category.CATEGORY_SUB, AdminCacheConst.Category.CATEGORY_TREE}, allEntries = true) + public void removeCache() { + log.info("clear CATEGORY ,CATEGORY_SUB ,CATEGORY_TREE"); + } + + /** + * 查詢类目 + * + */ + @Cacheable(AdminCacheConst.Category.CATEGORY_ENTITY) + public CategoryEntity queryCategory(Long categoryId) { + return categoryDao.selectById(categoryId); + } + + /** + * 查询类目 子级 + * + */ + @Cacheable(AdminCacheConst.Category.CATEGORY_SUB) + public List querySubCategory(Long categoryId) { + return categoryDao.queryByParentId(Lists.newArrayList(categoryId), false); + } + + + /** + * 查询类目 层级树 + * 优先查询缓存 + */ + @Cacheable(AdminCacheConst.Category.CATEGORY_TREE) + public List queryCategoryTree(Long parentId, Integer categoryType) { + List allCategoryEntityList = categoryDao.queryByType(categoryType, false); + + List categoryEntityList = allCategoryEntityList.stream().filter(e -> e.getParentId().equals(parentId)).collect(Collectors.toList()); + List treeList = SmartBeanUtil.copyList(categoryEntityList, CategoryTreeVO.class); + treeList.forEach(e -> { + e.setLabel(e.getCategoryName()); + e.setValue(e.getCategoryId()); + e.setCategoryFullName(e.getCategoryName()); + }); + // 递归设置子类 + this.queryAndSetSubCategory(treeList, allCategoryEntityList); + return treeList; + } + + /** + * 递归查询设置类目子类 + * 从缓存查询子类 + * + */ + private void queryAndSetSubCategory(List treeList, List allCategoryEntityList) { + if (CollectionUtils.isEmpty(treeList)) { + return; + } + List parentIdList = treeList.stream().map(CategoryTreeVO::getValue).collect(Collectors.toList()); + List categoryEntityList = allCategoryEntityList.stream().filter(e -> parentIdList.contains(e.getParentId())).collect(Collectors.toList()); + Map> categorySubMap = categoryEntityList.stream().collect(Collectors.groupingBy(CategoryEntity::getParentId)); + treeList.forEach(e -> { + List childrenEntityList = categorySubMap.getOrDefault(e.getValue(), Lists.newArrayList()); + List childrenVOList = SmartBeanUtil.copyList(childrenEntityList, CategoryTreeVO.class); + childrenVOList.forEach(item -> { + item.setLabel(item.getCategoryName()); + item.setValue(item.getCategoryId()); + item.setCategoryFullName(e.getCategoryFullName() + StringConst.SEPARATOR_SLASH + item.getCategoryName()); + }); + // 递归查询 + this.queryAndSetSubCategory(childrenVOList, allCategoryEntityList); + e.setChildren(childrenVOList); + }); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryQueryService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryQueryService.java new file mode 100644 index 0000000..07ac0be --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryQueryService.java @@ -0,0 +1,185 @@ +package net.lab1024.sa.admin.module.business.category.service; + +import cn.hutool.core.util.StrUtil; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.business.category.domain.dto.CategorySimpleDTO; +import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity; +import net.lab1024.sa.admin.module.business.category.manager.CategoryCacheManager; +import net.lab1024.sa.base.common.constant.StringConst; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 类目 查询 业务类 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Service +@Slf4j +public class CategoryQueryService { + + private static final Long DEFAULT_CATEGORY_PARENT_ID = 0L; + + @Resource + private CategoryCacheManager categoryCacheManager; + + /** + * 根据 id 查询未删除的类目 + * + * @param categoryId + * @return 可能 null + */ + public Optional queryCategory(Long categoryId) { + if (null == categoryId) { + return Optional.empty(); + } + CategoryEntity entity = categoryCacheManager.queryCategory(categoryId); + if (null == entity || entity.getDeletedFlag()) { + return Optional.empty(); + } + return Optional.of(entity); + } + + + /** + * 根据 类目id集合 查询未删除的类目集合 + */ + public Map queryCategoryList(List categoryIdList) { + if (CollectionUtils.isEmpty(categoryIdList)) { + return Collections.emptyMap(); + } + categoryIdList = categoryIdList.stream().distinct().collect(Collectors.toList()); + Map categoryEntityMap = Maps.newHashMap(); + for (Long categoryId : categoryIdList) { + CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId); + if (categoryEntity != null) { + categoryEntityMap.put(categoryId, categoryEntity); + } + } + return categoryEntityMap; + } + + + /** + * 根据类目id 递归查询该id的所有子类id 递归查询 + * 同时存入缓存 + * 注意:查询出来的集合 不包含传递的父类参数 + */ + public List queryCategorySubId(List categoryIdList) { + if (CollectionUtils.isEmpty(categoryIdList)) { + return Collections.emptyList(); + } + //所有子类 + List categoryEntityList = Lists.newArrayList(); + categoryIdList.forEach(e -> { + categoryEntityList.addAll(categoryCacheManager.querySubCategory(e)); + }); + Map> subTypeMap = categoryEntityList.stream().collect(Collectors.groupingBy(CategoryEntity::getCategoryId)); + // 递归查询子类 + categoryIdList = subTypeMap.values().stream().flatMap(Collection::stream).map(CategoryEntity::getCategoryId).distinct().collect(Collectors.toList()); + if (CollectionUtils.isEmpty(categoryIdList)) { + return Lists.newArrayList(); + } + categoryIdList.addAll(this.queryCategorySubId(categoryIdList)); + return categoryIdList; + } + + + /** + * 处理类目名称 + */ + public List queryCategoryName(List categoryIdList) { + if (CollectionUtils.isEmpty(categoryIdList)) { + return null; + } + Map categoryMap = this.queryCategoryList(categoryIdList); + List categoryNameList = Lists.newArrayList(); + categoryIdList.forEach(e -> { + CategoryEntity categoryEntity = categoryMap.get(e); + if (categoryEntity != null) { + categoryNameList.add(categoryMap.get(e).getCategoryName()); + } + }); + return categoryNameList; + } + + /** + * 根据类目id 查询类目名称 + */ + public String queryCategoryName(Long categoryId) { + CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId); + if (null == categoryEntity || categoryEntity.getDeletedFlag()) { + return null; + } + return categoryEntity.getCategoryName(); + } + + /** + * 根据类目id 查询类目详情 包含类目全称 如:医考/医师资格/临床执业 + */ + public CategorySimpleDTO queryCategoryInfo(Long categoryId) { + CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId); + if (null == categoryEntity || categoryEntity.getDeletedFlag()) { + return null; + } + String fullName = this.queryFullName(categoryId); + // 返回DTO + CategorySimpleDTO categoryDTO = new CategorySimpleDTO(); + categoryDTO.setCategoryId(categoryId); + categoryDTO.setCategoryName(categoryEntity.getCategoryName()); + categoryDTO.setCategoryFullName(fullName); + categoryDTO.setParentId(categoryEntity.getParentId()); + return categoryDTO; + } + + /** + * 递归查询分类和所有父级类目 + * ps:特别注意返回的集合中 包含自己 + */ + public List queryCategoryAndParent(Long categoryId) { + List parentCategoryList = Lists.newArrayList(); + CategoryEntity categoryEntity = categoryCacheManager.queryCategory(categoryId); + if (null == categoryEntity || categoryEntity.getDeletedFlag()) { + return parentCategoryList; + } + + // 父级始终放在第一位 + parentCategoryList.add(0, categoryEntity); + Long parentId = categoryEntity.getParentId(); + if (Objects.equals(DEFAULT_CATEGORY_PARENT_ID, parentId)) { + return parentCategoryList; + } + parentCategoryList.addAll(0, this.queryCategoryAndParent(parentId)); + return parentCategoryList; + } + + /** + * 查询 分类全称 如:医考/医师资格/临床执业 + */ + public String queryFullName(Long categoryId) { + List parentCategoryList = this.queryCategoryAndParent(categoryId); + // 拼接父级类目名称 斜杠分隔返回 + List nameList = parentCategoryList.stream().map(CategoryEntity::getCategoryName).collect(Collectors.toList()); + return StrUtil.join(StringConst.SEPARATOR_SLASH, nameList); + } + + /** + * 查询 分类全称 如:医考/医师资格/临床执业 + */ + public Map queryFullName(List categoryIdList) { + if (CollectionUtils.isEmpty(categoryIdList)) { + return Maps.newHashMap(); + } + // 循环内查询的缓存 还ok + return categoryIdList.stream().collect(Collectors.toMap(Function.identity(), this::queryFullName)); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryService.java new file mode 100644 index 0000000..27b280d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/category/service/CategoryService.java @@ -0,0 +1,203 @@ +package net.lab1024.sa.admin.module.business.category.service; + +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.business.category.dao.CategoryDao; +import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity; +import net.lab1024.sa.admin.module.business.category.domain.form.CategoryAddForm; +import net.lab1024.sa.admin.module.business.category.domain.form.CategoryTreeQueryForm; +import net.lab1024.sa.admin.module.business.category.domain.form.CategoryUpdateForm; +import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryTreeVO; +import net.lab1024.sa.admin.module.business.category.domain.vo.CategoryVO; +import net.lab1024.sa.admin.module.business.category.manager.CategoryCacheManager; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * 类目 + * + * @Date 2021/08/05 21:26:58 + * @Author wzh + */ +@Service +public class CategoryService { + + @Resource + private CategoryDao categoryDao; + + @Resource + private CategoryQueryService categoryQueryService; + + @Resource + private CategoryCacheManager categoryCacheManager; + + /** + * 添加类目 + */ + public ResponseDTO add(CategoryAddForm addForm) { + // 校验类目 + CategoryEntity categoryEntity = SmartBeanUtil.copy(addForm, CategoryEntity.class); + ResponseDTO res = this.checkCategory(categoryEntity, false); + if (!res.getOk()) { + return res; + } + // 没有父类则使用默认父类 + Long parentId = null == addForm.getParentId() ? NumberUtils.LONG_ZERO : addForm.getParentId(); + categoryEntity.setParentId(parentId); + categoryEntity.setSort(null == addForm.getSort() ? 0 : addForm.getSort()); + categoryEntity.setDeletedFlag(false); + + // 保存数据 + categoryDao.insert(categoryEntity); + + // 更新缓存 + categoryCacheManager.removeCache(); + return ResponseDTO.ok(); + } + + /** + * 更新类目 + * 不能更新父级类目 + * + */ + public ResponseDTO update(CategoryUpdateForm updateForm) { + // 校验类目 + Long categoryId = updateForm.getCategoryId(); + Optional optional = categoryQueryService.queryCategory(categoryId); + if (!optional.isPresent()) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + CategoryEntity categoryEntity = SmartBeanUtil.copy(updateForm, CategoryEntity.class); + + /* + 不更新类目类型 + 不更新父类id + */ + Integer categoryType = optional.get().getCategoryType(); + categoryEntity.setCategoryType(categoryType); + categoryEntity.setParentId(optional.get().getParentId()); + + ResponseDTO responseDTO = this.checkCategory(categoryEntity, true); + if (!responseDTO.getOk()) { + return responseDTO; + } + categoryDao.updateById(categoryEntity); + + // 更新缓存 + categoryCacheManager.removeCache(); + return ResponseDTO.ok(); + } + + /** + * 新增/更新 类目时的 校验 + * + */ + private ResponseDTO checkCategory(CategoryEntity categoryEntity, boolean isUpdate) { + // 校验父级是否存在 + Long parentId = categoryEntity.getParentId(); + Integer categoryType = categoryEntity.getCategoryType(); + if (null != parentId) { + if (Objects.equals(categoryEntity.getCategoryId(), parentId)) { + return ResponseDTO.userErrorParam("父级类目怎么和自己相同了"); + } + if (!Objects.equals(parentId, NumberUtils.LONG_ZERO)) { + Optional optional = categoryQueryService.queryCategory(parentId); + if (!optional.isPresent()) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "父级类目不存在~"); + } + + CategoryEntity parent = optional.get(); + if (!Objects.equals(categoryType, parent.getCategoryType())) { + return ResponseDTO.userErrorParam("与父级类目类型不一致"); + } + } + + } else { + // 如果没有父类 使用默认父类 + parentId = NumberUtils.LONG_ZERO; + } + + // 校验同父类下 名称是否重复 + CategoryEntity queryEntity = new CategoryEntity(); + queryEntity.setParentId(parentId); + queryEntity.setCategoryType(categoryType); + queryEntity.setCategoryName(categoryEntity.getCategoryName()); + queryEntity.setDeletedFlag(false); + queryEntity = categoryDao.selectOne(queryEntity); + if (null != queryEntity) { + if (isUpdate) { + if (!Objects.equals(queryEntity.getCategoryId(), categoryEntity.getCategoryId())) { + return ResponseDTO.userErrorParam("同级下已存在相同类目~"); + } + } else { + return ResponseDTO.userErrorParam("同级下已存在相同类目~"); + } + } + return ResponseDTO.ok(); + } + + /** + * 查询 类目详情 + * + */ + public ResponseDTO queryDetail(Long categoryId) { + Optional optional = categoryQueryService.queryCategory(categoryId); + if (!optional.isPresent()) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + CategoryVO adminVO = SmartBeanUtil.copy(optional.get(), CategoryVO.class); + return ResponseDTO.ok(adminVO); + } + + /** + * 根据父级id 查询所有子类 返回层级树 + * 如果父类id 为空 返回所有类目层级 + * + */ + public ResponseDTO> queryTree(CategoryTreeQueryForm queryForm) { + if (null == queryForm.getParentId()) { + if (null == queryForm.getCategoryType()) { + return ResponseDTO.userErrorParam("类目类型不能为空"); + } + queryForm.setParentId(NumberUtils.LONG_ZERO); + } + List treeList = categoryCacheManager.queryCategoryTree(queryForm.getParentId(), queryForm.getCategoryType()); + return ResponseDTO.ok(treeList); + } + + /** + * 删除类目 + * 如果有未删除的子类 则无法删除 + * + */ + public ResponseDTO delete(Long categoryId) { + Optional optional = categoryQueryService.queryCategory(categoryId); + if (!optional.isPresent()) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + List categorySubId = categoryQueryService.queryCategorySubId(Lists.newArrayList(categoryId)); + if (CollectionUtils.isNotEmpty(categorySubId)) { + return ResponseDTO.userErrorParam("请先删除子级类目"); + } + + // 更新数据 + CategoryEntity categoryEntity = new CategoryEntity(); + categoryEntity.setCategoryId(categoryId); + categoryEntity.setDeletedFlag(true); + categoryDao.updateById(categoryEntity); + + // 更新缓存 + categoryCacheManager.removeCache(); + return ResponseDTO.ok(); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/constant/GoodsStatusEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/constant/GoodsStatusEnum.java new file mode 100644 index 0000000..4af7bdc --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/constant/GoodsStatusEnum.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.admin.module.business.goods.constant; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 商品状态 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@AllArgsConstructor +@Getter +public enum GoodsStatusEnum implements BaseEnum { + + /** + * 1 预约中 + */ + APPOINTMENT(1, "预约中"), + + /** + * 2 售卖 + */ + SELL(2, "售卖中"), + + /** + * 3 售罄 + */ + SELL_OUT(3, "售罄"), + + + ; + + private final Integer value; + + private final String desc; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java new file mode 100644 index 0000000..50efbf0 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/controller/GoodsController.java @@ -0,0 +1,91 @@ +package net.lab1024.sa.admin.module.business.goods.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsAddForm; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsUpdateForm; +import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsExcelVO; +import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO; +import net.lab1024.sa.admin.module.business.goods.service.GoodsService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.ValidateList; +import net.lab1024.sa.base.common.util.SmartExcelUtil; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.List; + +/** + * 商品业务 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.Business.MANAGER_GOODS) +public class GoodsController { + + @Resource + private GoodsService goodsService; + + @Operation(summary = "分页查询 ") + @PostMapping("/goods/query") + @SaCheckPermission("goods:query") + public ResponseDTO> query(@RequestBody @Valid GoodsQueryForm queryForm) { + return goodsService.query(queryForm); + } + + @Operation(summary = "添加商品 ") + @PostMapping("/goods/add") + @SaCheckPermission("goods:add") + public ResponseDTO add(@RequestBody @Valid GoodsAddForm addForm) { + return goodsService.add(addForm); + } + + @Operation(summary = "更新商品 ") + @PostMapping("/goods/update") + @SaCheckPermission("goods:update") + public ResponseDTO update(@RequestBody @Valid GoodsUpdateForm updateForm) { + return goodsService.update(updateForm); + } + + @Operation(summary = "删除 @author 卓大") + @GetMapping("/goods/delete/{goodsId}") + @SaCheckPermission("goods:delete") + public ResponseDTO delete(@PathVariable Long goodsId) { + return goodsService.delete(goodsId); + } + + @Operation(summary = "批量 @author 卓大") + @PostMapping("/goods/batchDelete") + @SaCheckPermission("goods:batchDelete") + public ResponseDTO batchDelete(@RequestBody @Valid ValidateList idList) { + return goodsService.batchDelete(idList); + } + + // --------------- 导出和导入 ------------------- + + @Operation(summary = "导入 @author 卓大") + @PostMapping("/goods/importGoods") + @SaCheckPermission("goods:importGoods") + public ResponseDTO importGoods(@RequestParam MultipartFile file) { + return goodsService.importGoods(file); + } + + @Operation(summary = "导出 @author 卓大") + @GetMapping("/goods/exportGoods") + @SaCheckPermission("goods:exportGoods") + public void exportGoods(HttpServletResponse response) throws IOException { + List goodsList = goodsService.getAllGoods(); + SmartExcelUtil.exportExcel(response,"商品列表.xlsx","商品",GoodsExcelVO.class, goodsList); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.java new file mode 100644 index 0000000..9f8ac41 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/dao/GoodsDao.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.admin.module.business.goods.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.business.goods.domain.entity.GoodsEntity; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm; +import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 商品 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Mapper +public interface GoodsDao extends BaseMapper { + + /** + * 分页 查询商品 + * + */ + List query(Page page, @Param("query") GoodsQueryForm query); + + /** + * 批量更新删除状态 + */ + + void batchUpdateDeleted(@Param("goodsIdList")List goodsIdList,@Param("deletedFlag")Boolean deletedFlag); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/entity/GoodsEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/entity/GoodsEntity.java new file mode 100644 index 0000000..ad003e7 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/entity/GoodsEntity.java @@ -0,0 +1,68 @@ +package net.lab1024.sa.admin.module.business.goods.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 商品 实体类 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Data +@TableName("t_goods") +public class GoodsEntity { + + @TableId(type = IdType.AUTO) + private Long goodsId; + + /** + * 商品状态:[1:预约中,2:售卖中,3:售罄] + */ + private Integer goodsStatus; + + /** + * 商品分类 + */ + private Long categoryId; + + /** + * 商品名称 + */ + private String goodsName; + + /** + * 产地 + */ + private String place; + + /** + * 商品价格 + */ + private BigDecimal price; + + + /** + * 上架状态 + */ + private Boolean shelvesFlag; + + /** + * 删除状态 + */ + private Boolean deletedFlag; + + /** + * 备注 + */ + private String remark; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsAddForm.java new file mode 100644 index 0000000..1442f61 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsAddForm.java @@ -0,0 +1,53 @@ +package net.lab1024.sa.admin.module.business.goods.domain.form; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum; +import net.lab1024.sa.base.common.json.deserializer.DictDataDeserializer; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; + +import java.math.BigDecimal; + +/** + * 商品 添加表单 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Data +public class GoodsAddForm { + + @Schema(description = "商品分类") + @NotNull(message = "商品分类不能为空") + private Long categoryId; + + @Schema(description = "商品名称") + @NotBlank(message = "商品名称不能为空") + private String goodsName; + + @SchemaEnum(GoodsStatusEnum.class) + @CheckEnum(message = "商品状态错误", value = GoodsStatusEnum.class, required = true) + private Integer goodsStatus; + + @Schema(description = "产地") + @NotBlank(message = "产地 不能为空 ") + @JsonDeserialize(using = DictDataDeserializer.class) + private String place; + + @Schema(description = "商品价格") + @NotNull(message = "商品价格不能为空") + @DecimalMin(value = "0", message = "商品价格最低0") + private BigDecimal price; + + @Schema(description = "上架状态") + @NotNull(message = "上架状态不能为空") + private Boolean shelvesFlag; + + @Schema(description = "备注|可选") + private String remark; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsImportForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsImportForm.java new file mode 100644 index 0000000..79db672 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsImportForm.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.admin.module.business.goods.domain.form; + +import cn.idev.excel.annotation.ExcelProperty; +import lombok.Data; + +import java.math.BigDecimal; + +/** + * 商品 导入表单 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Data +public class GoodsImportForm { + + @ExcelProperty("商品分类") + private String categoryName; + + @ExcelProperty("商品名称") + private String goodsName; + + @ExcelProperty("商品状态错误") + private String goodsStatus; + + @ExcelProperty("产地") + private String place; + + @ExcelProperty("商品价格") + private BigDecimal price; + + @ExcelProperty("备注") + private String remark; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsQueryForm.java new file mode 100644 index 0000000..79573d6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsQueryForm.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.admin.module.business.goods.domain.form; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.json.deserializer.DictDataDeserializer; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 商品 分页查询 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Data +public class GoodsQueryForm extends PageParam { + + @Schema(description = "商品分类") + private Integer categoryId; + + @Schema(description = "搜索词") + @Length(max = 30, message = "搜索词最多30字符") + private String searchWord; + + @SchemaEnum(GoodsStatusEnum.class) + @CheckEnum(message = "商品状态错误", value = GoodsStatusEnum.class, required = false) + private Integer goodsStatus; + + @Schema(description = "产地") + @JsonDeserialize(using = DictDataDeserializer.class) + private String place; + + @Schema(description = "上架状态") + private Boolean shelvesFlag; + + @Schema(hidden = true) + private Boolean deletedFlag; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsUpdateForm.java new file mode 100644 index 0000000..ae07176 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/form/GoodsUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.business.goods.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 商品 更新表单 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Data +public class GoodsUpdateForm extends GoodsAddForm { + + @Schema(description = "商品id") + @NotNull(message = "商品id不能为空") + private Long goodsId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsExcelVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsExcelVO.java new file mode 100644 index 0000000..e261988 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsExcelVO.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.admin.module.business.goods.domain.vo; + + +import cn.idev.excel.annotation.ExcelProperty; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * excel商品 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class GoodsExcelVO { + + @ExcelProperty("商品分类") + private String categoryName; + + @ExcelProperty("商品名称") + private String goodsName; + + @ExcelProperty("商品状态错误") + private String goodsStatus; + + @ExcelProperty("产地") + private String place; + + @ExcelProperty("商品价格") + private BigDecimal price; + + @ExcelProperty("备注") + private String remark; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsVO.java new file mode 100644 index 0000000..1cd6397 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/domain/vo/GoodsVO.java @@ -0,0 +1,51 @@ +package net.lab1024.sa.admin.module.business.goods.domain.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * 商品 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Data +public class GoodsVO { + + @Schema(description = "商品分类") + private Long categoryId; + + @Schema(description = "商品名称") + private String goodsName; + + @SchemaEnum(GoodsStatusEnum.class) + private Integer goodsStatus; + + @Schema(description = "产地") + private String place; + + @Schema(description = "商品价格") + private BigDecimal price; + + @Schema(description = "上架状态") + private Boolean shelvesFlag; + + @Schema(description = "备注|可选") + private String remark; + + @Schema(description = "商品id") + private Long goodsId; + + @Schema(description = "商品分类") + private String categoryName; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/service/GoodsService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/service/GoodsService.java new file mode 100644 index 0000000..476a335 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/goods/service/GoodsService.java @@ -0,0 +1,208 @@ +package net.lab1024.sa.admin.module.business.goods.service; + +import cn.idev.excel.FastExcel; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.business.category.constant.CategoryTypeEnum; +import net.lab1024.sa.admin.module.business.category.domain.entity.CategoryEntity; +import net.lab1024.sa.admin.module.business.category.service.CategoryQueryService; +import net.lab1024.sa.admin.module.business.goods.constant.GoodsStatusEnum; +import net.lab1024.sa.admin.module.business.goods.dao.GoodsDao; +import net.lab1024.sa.admin.module.business.goods.domain.entity.GoodsEntity; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsAddForm; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsImportForm; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsQueryForm; +import net.lab1024.sa.admin.module.business.goods.domain.form.GoodsUpdateForm; +import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsExcelVO; +import net.lab1024.sa.admin.module.business.goods.domain.vo.GoodsVO; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.exception.BusinessException; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService; +import net.lab1024.sa.base.module.support.dict.service.DictService; +import org.apache.commons.collections4.CollectionUtils; +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.stream.Collectors; + +/** + * 商品 + * + * @Date 2021-10-25 20:26:54 + * @Author wzh + */ +@Service +@Slf4j +public class GoodsService { + + @Resource + private GoodsDao goodsDao; + + @Resource + private CategoryQueryService categoryQueryService; + + @Resource + private DataTracerService dataTracerService; + + @Resource + private DictService dictService; + + /** + * 添加商品 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO add(GoodsAddForm addForm) { + // 商品校验 + ResponseDTO res = this.checkGoods(addForm); + if (!res.getOk()) { + return res; + } + GoodsEntity goodsEntity = SmartBeanUtil.copy(addForm, GoodsEntity.class); + goodsEntity.setDeletedFlag(Boolean.FALSE); + goodsDao.insert(goodsEntity); + dataTracerService.insert(goodsEntity.getGoodsId(), DataTracerTypeEnum.GOODS); + return ResponseDTO.ok(); + } + + /** + * 更新商品 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO update(GoodsUpdateForm updateForm) { + // 商品校验 + ResponseDTO res = this.checkGoods(updateForm); + if (!res.getOk()) { + return res; + } + GoodsEntity originEntity = goodsDao.selectById(updateForm.getGoodsId()); + GoodsEntity goodsEntity = SmartBeanUtil.copy(updateForm, GoodsEntity.class); + goodsDao.updateById(goodsEntity); + dataTracerService.update(updateForm.getGoodsId(), DataTracerTypeEnum.GOODS, originEntity, goodsEntity); + return ResponseDTO.ok(); + } + + /** + * 添加/更新 商品校验 + */ + private ResponseDTO checkGoods(GoodsAddForm addForm) { + // 校验类目id + Long categoryId = addForm.getCategoryId(); + Optional optional = categoryQueryService.queryCategory(categoryId); + if (!optional.isPresent() || !CategoryTypeEnum.GOODS.equalsValue(optional.get().getCategoryType())) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST, "商品类目不存在~"); + } + + return ResponseDTO.ok(); + } + + /** + * 删除 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO delete(Long goodsId) { + GoodsEntity goodsEntity = goodsDao.selectById(goodsId); + if (goodsEntity == null) { + return ResponseDTO.userErrorParam("商品不存在"); + } + + if (!goodsEntity.getGoodsStatus().equals(GoodsStatusEnum.SELL_OUT.getValue())) { + return ResponseDTO.userErrorParam("只有售罄的商品才可以删除"); + } + + batchDelete(Collections.singletonList(goodsId)); + dataTracerService.batchDelete(Collections.singletonList(goodsId), DataTracerTypeEnum.GOODS); + return ResponseDTO.ok(); + } + + /** + * 批量删除 + */ + public ResponseDTO batchDelete(List goodsIdList) { + if (CollectionUtils.isEmpty(goodsIdList)) { + return ResponseDTO.ok(); + } + + goodsDao.batchUpdateDeleted(goodsIdList, Boolean.TRUE); + return ResponseDTO.ok(); + } + + + /** + * 分页查询 + */ + public ResponseDTO> query(GoodsQueryForm queryForm) { + queryForm.setDeletedFlag(false); + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = goodsDao.query(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, list); + if (pageResult.getEmptyFlag()) { + return ResponseDTO.ok(pageResult); + } + // 查询分类名称 + List categoryIdList = list.stream().map(GoodsVO::getCategoryId).distinct().collect(Collectors.toList()); + Map categoryMap = categoryQueryService.queryCategoryList(categoryIdList); + list.forEach(e -> { + CategoryEntity categoryEntity = categoryMap.get(e.getCategoryId()); + if (categoryEntity != null) { + e.setCategoryName(categoryEntity.getCategoryName()); + } + }); + return ResponseDTO.ok(pageResult); + } + + /** + * 商品导入 + * + * @param file 上传文件 + * @return 结果 + */ + public ResponseDTO importGoods(MultipartFile file) { + List dataList; + try { + dataList = FastExcel.read(file.getInputStream()).head(GoodsImportForm.class) + .sheet() + .doReadSync(); + } catch (IOException e) { + log.error(e.getMessage(), e); + throw new BusinessException("数据格式存在问题,无法读取"); + } + + if (CollectionUtils.isEmpty(dataList)) { + return ResponseDTO.userErrorParam("数据为空"); + } + + return ResponseDTO.okMsg("成功导入" + dataList.size() + "条,具体数据为:" + JSON.toJSONString(dataList)); + } + + /** + * 商品导出 + */ + public List getAllGoods() { + List goodsEntityList = goodsDao.selectList(null); + String dictCode = "GOODS_PLACE"; + return goodsEntityList.stream() + .map(e -> + GoodsExcelVO.builder() + .goodsStatus(SmartEnumUtil.getEnumDescByValue(e.getGoodsStatus(), GoodsStatusEnum.class)) + .categoryName(categoryQueryService.queryCategoryName(e.getCategoryId())) + .place(Arrays.stream(e.getPlace().split(",")).map(code -> dictService.getDictDataLabel(dictCode, code)).collect(Collectors.joining(","))) + .price(e.getPrice()) + .goodsName(e.getGoodsName()) + .remark(e.getRemark()) + .build() + ) + .collect(Collectors.toList()); + + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankController.java new file mode 100644 index 0000000..988053f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankController.java @@ -0,0 +1,78 @@ +package net.lab1024.sa.admin.module.business.oa.bank; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.business.oa.bank.domain.BankCreateForm; +import net.lab1024.sa.admin.module.business.oa.bank.domain.BankQueryForm; +import net.lab1024.sa.admin.module.business.oa.bank.domain.BankUpdateForm; +import net.lab1024.sa.admin.module.business.oa.bank.domain.BankVO; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * OA办公-OA银行信息 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.Business.OA_BANK) +public class BankController { + + @Resource + private BankService bankService; + + @Operation(summary = "分页查询银行信息 @author 善逸") + @PostMapping("/oa/bank/page/query") + @SaCheckPermission("oa:bank:query") + public ResponseDTO> queryByPage(@RequestBody @Valid BankQueryForm queryForm) { + return bankService.queryByPage(queryForm); + } + + @Operation(summary = "根据企业ID查询银行信息列表 @author 善逸") + @GetMapping("/oa/bank/query/list/{enterpriseId}") + @SaCheckPermission("oa:bank:query") + public ResponseDTO> queryList(@PathVariable Long enterpriseId) { + return bankService.queryList(enterpriseId); + } + + @Operation(summary = "查询银行信息详情 @author 善逸") + @GetMapping("/oa/bank/get/{bankId}") + @SaCheckPermission("oa:bank:query") + public ResponseDTO getDetail(@PathVariable Long bankId) { + return bankService.getDetail(bankId); + } + + @Operation(summary = "新建银行信息 @author 善逸") + @PostMapping("/oa/bank/create") + @SaCheckPermission("oa:bank:add") + public ResponseDTO createBank(@RequestBody @Valid BankCreateForm createVO) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + createVO.setCreateUserId(requestUser.getUserId()); + createVO.setCreateUserName(requestUser.getUserName()); + return bankService.createBank(createVO); + } + + @Operation(summary = "编辑银行信息 @author 善逸") + @PostMapping("/oa/bank/update") + @SaCheckPermission("oa:bank:update") + public ResponseDTO updateBank(@RequestBody @Valid BankUpdateForm updateVO) { + return bankService.updateBank(updateVO); + } + + @Operation(summary = "删除银行信息 @author 善逸") + @GetMapping("/oa/bank/delete/{bankId}") + @SaCheckPermission("oa:bank:delete") + public ResponseDTO deleteBank(@PathVariable Long bankId) { + return bankService.deleteBank(bankId); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankDao.java new file mode 100644 index 0000000..571b75e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankDao.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.business.oa.bank; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.business.oa.bank.domain.BankEntity; +import net.lab1024.sa.admin.module.business.oa.bank.domain.BankQueryForm; +import net.lab1024.sa.admin.module.business.oa.bank.domain.BankVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * OA办公-OA银行信息 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Mapper +public interface BankDao extends BaseMapper { + + /** + * 根据账号查询 + */ + BankEntity queryByAccountNumber(@Param("enterpriseId") Long enterpriseId, @Param("accountNumber") String accountNumber, @Param("excludeBankId") Long excludeBankId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 删除银行信息 + * + */ + void deleteBank(@Param("bankId") Long bankId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 银行信息分页查询 + * + */ + List queryPage(Page page, @Param("queryForm") BankQueryForm queryForm); + + /** + * 查询银行信息详情 + */ + BankVO getDetail(@Param("bankId") Long bankId, @Param("deletedFlag") Boolean deletedFlag); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankService.java new file mode 100644 index 0000000..883649a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/BankService.java @@ -0,0 +1,142 @@ +package net.lab1024.sa.admin.module.business.oa.bank; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.business.oa.bank.domain.*; +import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseDao; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; + +/** + * OA办公-OA银行信息 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Service +@Slf4j +public class BankService { + + @Resource + private BankDao bankDao; + + @Resource + private EnterpriseDao enterpriseDao; + + @Resource + private DataTracerService dataTracerService; + + /** + * 分页查询银行信息 + */ + public ResponseDTO> queryByPage(BankQueryForm queryForm) { + queryForm.setDeletedFlag(Boolean.FALSE); + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List bankList = bankDao.queryPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, bankList); + return ResponseDTO.ok(pageResult); + } + + /** + * 根据企业ID查询不分页的银行列表 + */ + public ResponseDTO> queryList(Long enterpriseId) { + BankQueryForm queryForm = new BankQueryForm(); + queryForm.setEnterpriseId(enterpriseId); + queryForm.setDeletedFlag(Boolean.FALSE); + List bankList = bankDao.queryPage(null, queryForm); + return ResponseDTO.ok(bankList); + } + + /** + * 查询银行信息详情 + */ + public ResponseDTO getDetail(Long bankId) { + // 校验银行信息是否存在 + BankVO bankVO = bankDao.getDetail(bankId, Boolean.FALSE); + if (Objects.isNull(bankVO)) { + return ResponseDTO.userErrorParam("银行信息不存在"); + } + return ResponseDTO.ok(bankVO); + } + + /** + * 新建银行信息 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO createBank(BankCreateForm createVO) { + Long enterpriseId = createVO.getEnterpriseId(); + // 校验企业是否存在 + EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId); + if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("企业不存在"); + } + // 验证银行信息账号是否重复 + BankEntity validateBank = bankDao.queryByAccountNumber(enterpriseId, createVO.getAccountNumber(), null, Boolean.FALSE); + if (Objects.nonNull(validateBank)) { + return ResponseDTO.userErrorParam("银行信息账号重复"); + } + // 数据插入 + BankEntity insertBank = SmartBeanUtil.copy(createVO, BankEntity.class); + bankDao.insert(insertBank); + dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "新增银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(insertBank)); + return ResponseDTO.ok(); + } + + /** + * 编辑银行信息 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO updateBank(BankUpdateForm updateVO) { + Long enterpriseId = updateVO.getEnterpriseId(); + // 校验企业是否存在 + EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId); + if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("企业不存在"); + } + Long bankId = updateVO.getBankId(); + // 校验银行信息是否存在 + BankEntity bankDetail = bankDao.selectById(bankId); + if (Objects.isNull(bankDetail) || bankDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("银行信息不存在"); + } + // 验证银行信息账号是否重复 + BankEntity validateBank = bankDao.queryByAccountNumber(updateVO.getEnterpriseId(), updateVO.getAccountNumber(), bankId, Boolean.FALSE); + if (Objects.nonNull(validateBank)) { + return ResponseDTO.userErrorParam("银行信息账号重复"); + } + // 数据编辑 + BankEntity updateBank = SmartBeanUtil.copy(updateVO, BankEntity.class); + bankDao.updateById(updateBank); + dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "更新银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(bankDetail, updateBank)); + return ResponseDTO.ok(); + } + + + /** + * 删除银行信息 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO deleteBank(Long bankId) { + // 校验银行信息是否存在 + BankEntity bankDetail = bankDao.selectById(bankId); + if (Objects.isNull(bankDetail) || bankDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("银行信息不存在"); + } + bankDao.deleteBank(bankId, Boolean.TRUE); + dataTracerService.addTrace(bankDetail.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE, "删除银行:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(bankDetail)); + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankCreateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankCreateForm.java new file mode 100644 index 0000000..41ecd20 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankCreateForm.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.admin.module.business.oa.bank.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * OA办公-银行信息新建 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Data +public class BankCreateForm { + + @Schema(description = "开户银行") + @NotBlank(message = "开户银行不能为空") + @Length(max = 200, message = "开户银行最多200字符") + private String bankName; + + @Schema(description = "账户名称") + @NotBlank(message = "账户名称不能为空") + @Length(max = 200, message = "账户名称最多200字符") + private String accountName; + + @Schema(description = "账号") + @NotBlank(message = "账号不能为空") + @Length(max = 200, message = "账号最多200字符") + private String accountNumber; + + @Schema(description = "备注") + @Length(max = 500, message = "备注最多500字符") + private String remark; + + @Schema(description = "是否对公") + @NotNull(message = "是否对公不能为空") + private Boolean businessFlag; + + @Schema(description = "企业") + @NotNull(message = "企业不能为空") + private Long enterpriseId; + + @Schema(description = "禁用状态") + @NotNull(message = "禁用状态不能为空") + private Boolean disabledFlag; + + @Schema(hidden = true) + private Long createUserId; + + @Schema(hidden = true) + private String createUserName; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankEntity.java new file mode 100644 index 0000000..6023a70 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankEntity.java @@ -0,0 +1,92 @@ +package net.lab1024.sa.admin.module.business.oa.bank.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldLabel; + +import java.time.LocalDateTime; + +/** + * OA办公-OA银行信息 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Data +@TableName("t_oa_bank") +public class BankEntity { + + /** + * 银行信息ID + */ + @TableId(type = IdType.AUTO) + @DataTracerFieldLabel("银行信息ID") + private Long bankId; + + /** + * 开户银行 + */ + @DataTracerFieldLabel("开户银行") + private String bankName; + + /** + * 账户名称 + */ + @DataTracerFieldLabel("账户名称") + private String accountName; + + /** + * 账号 + */ + @DataTracerFieldLabel("账号") + private String accountNumber; + + /** + * 备注 + */ + @DataTracerFieldLabel("备注") + private String remark; + + /** + * 是否对公 + */ + @DataTracerFieldLabel("是否对公") + private Boolean businessFlag; + + /** + * 企业ID + */ + private Long enterpriseId; + + /** + * 禁用状态 + */ + @DataTracerFieldLabel("禁用状态") + private Boolean disabledFlag; + + /** + * 删除状态 + */ + private Boolean deletedFlag; + + /** + * 创建人ID + */ + private Long createUserId; + + /** + * 创建人ID + */ + private String createUserName; + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankQueryForm.java new file mode 100644 index 0000000..ab69435 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankQueryForm.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.admin.module.business.oa.bank.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; + +/** + * OA办公-OA银行信息查询 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Data +public class BankQueryForm extends PageParam { + + @Schema(description = "企业ID") + private Long enterpriseId; + + @Schema(description = "关键字") + @Length(max = 200, message = "关键字最多200字符") + private String keywords; + + @Schema(description = "开始时间") + private LocalDate startTime; + + @Schema(description = "结束时间") + private LocalDate endTime; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "删除状态", hidden = true) + private Boolean deletedFlag; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankUpdateForm.java new file mode 100644 index 0000000..c87bee9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.business.oa.bank.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * OA办公-银行信息更新 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Data +public class BankUpdateForm extends BankCreateForm { + + @Schema(description = "银行信息ID") + @NotNull(message = "银行信息ID不能为空") + private Long bankId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankVO.java new file mode 100644 index 0000000..0f63f05 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/bank/domain/BankVO.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.admin.module.business.oa.bank.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * OA办公-OA银行信息 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Data +public class BankVO { + + @Schema(description = "银行信息ID") + private Long bankId; + + @Schema(description = "开户银行") + private String bankName; + + @Schema(description = "账户名称") + private String accountName; + + @Schema(description = "账号") + private String accountNumber; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "是否对公") + private Boolean businessFlag; + + @Schema(description = "企业ID") + private Long enterpriseId; + + @Schema(description = "企业名称") + private String enterpriseName; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "创建人ID") + private Long createUserId; + + @Schema(description = "创建人名称") + private String createUserName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java new file mode 100644 index 0000000..eb2dad9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseController.java @@ -0,0 +1,134 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.*; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO; +import net.lab1024.sa.admin.util.AdminRequestUtil; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.*; +import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.List; + +/** + * 企业 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Slf4j +@RestController +@Tag(name = AdminSwaggerTagConst.Business.OA_ENTERPRISE) +@OperateLog +public class EnterpriseController { + + @Resource + private EnterpriseService enterpriseService; + + @Operation(summary = "分页查询企业模块 @author 开云") + @PostMapping("/oa/enterprise/page/query") + @SaCheckPermission("oa:enterprise:query") + public ResponseDTO> queryByPage(@RequestBody @Valid EnterpriseQueryForm queryForm) { + return enterpriseService.queryByPage(queryForm); + } + + @Operation(summary = "导出企业信息 @author 卓大") + @PostMapping("/oa/enterprise/exportExcel") + public void exportExcel(@RequestBody @Valid EnterpriseQueryForm queryForm, HttpServletResponse response) throws IOException { + List data = enterpriseService.getExcelExportData(queryForm); + if (CollectionUtils.isEmpty(data)) { + SmartResponseUtil.write(response, ResponseDTO.userErrorParam("暂无数据")); + return; + } + + String watermark = AdminRequestUtil.getRequestUser().getActualName(); + watermark += SmartLocalDateUtil.format(LocalDateTime.now(), SmartDateFormatterEnum.YMD_HMS); + + SmartExcelUtil.exportExcelWithWatermark(response,"企业基本信息.xlsx","企业信息",EnterpriseExcelVO.class,data,watermark); + + } + + @Operation(summary = "查询企业详情 @author 开云") + @GetMapping("/oa/enterprise/get/{enterpriseId}") + @SaCheckPermission("oa:enterprise:detail") + public ResponseDTO getDetail(@PathVariable Long enterpriseId) { + return ResponseDTO.ok(enterpriseService.getDetail(enterpriseId)); + } + + @Operation(summary = "新建企业 @author 开云") + @PostMapping("/oa/enterprise/create") + @SaCheckPermission("oa:enterprise:add") + public ResponseDTO createEnterprise(@RequestBody @Valid EnterpriseCreateForm createVO) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + createVO.setCreateUserId(requestUser.getUserId()); + createVO.setCreateUserName(requestUser.getUserName()); + return enterpriseService.createEnterprise(createVO); + } + + @Operation(summary = "编辑企业 @author 开云") + @PostMapping("/oa/enterprise/update") + @SaCheckPermission("oa:enterprise:update") + public ResponseDTO updateEnterprise(@RequestBody @Valid EnterpriseUpdateForm updateVO) { + return enterpriseService.updateEnterprise(updateVO); + } + + @Operation(summary = "删除企业 @author 开云") + @GetMapping("/oa/enterprise/delete/{enterpriseId}") + @SaCheckPermission("oa:enterprise:delete") + public ResponseDTO deleteEnterprise(@PathVariable Long enterpriseId) { + return enterpriseService.deleteEnterprise(enterpriseId); + } + + @Operation(summary = "按照类型查询企业 @author 开云") + @GetMapping("/oa/enterprise/query/list") + @SaCheckPermission("oa:enterprise:query") + public ResponseDTO> queryList(@RequestParam(value = "type", required = false) Integer type) { + return enterpriseService.queryList(type); + } + + + @Operation(summary = "企业添加员工 @author 罗伊") + @PostMapping("/oa/enterprise/employee/add") + @SaCheckPermission("oa:enterprise:addEmployee") + public ResponseDTO addEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) { + return enterpriseService.addEmployee(enterpriseEmployeeForm); + } + + @Operation(summary = "查询企业全部员工 @author 罗伊") + @PostMapping("/oa/enterprise/employee/list") + @SaCheckPermission("oa:enterprise:queryEmployee") + public ResponseDTO> employeeList(@RequestBody @Valid List enterpriseIdList) { + return ResponseDTO.ok(enterpriseService.employeeList(enterpriseIdList)); + } + + @Operation(summary = "分页查询企业员工 @author 卓大") + @PostMapping("/oa/enterprise/employee/queryPage") + @SaCheckPermission("oa:enterprise:queryEmployee") + public ResponseDTO> queryPageEmployeeList(@RequestBody @Valid EnterpriseEmployeeQueryForm queryForm) { + return ResponseDTO.ok(enterpriseService.queryPageEmployeeList(queryForm)); + } + + + @Operation(summary = "企业删除员工 @author 罗伊") + @PostMapping("/oa/enterprise/employee/delete") + @SaCheckPermission("oa:enterprise:deleteEmployee") + public ResponseDTO deleteEmployee(@RequestBody @Valid EnterpriseEmployeeForm enterpriseEmployeeForm) { + return enterpriseService.deleteEmployee(enterpriseEmployeeForm); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.java new file mode 100644 index 0000000..234caf6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseEmployeeManager.java @@ -0,0 +1,16 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity; +import org.springframework.stereotype.Service; + +/** + * 企业员工关系 manager + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Service +public class EnterpriseEmployeeManager extends ServiceImpl { +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseService.java new file mode 100644 index 0000000..24f02ba --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/EnterpriseService.java @@ -0,0 +1,235 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseDao; +import net.lab1024.sa.admin.module.business.oa.enterprise.dao.EnterpriseEmployeeDao; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.*; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.domain.form.DataTracerForm; +import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 企业 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Service +@Slf4j +public class EnterpriseService { + + @Resource + private EnterpriseDao enterpriseDao; + + @Resource + private EnterpriseEmployeeDao enterpriseEmployeeDao; + + @Resource + private EnterpriseEmployeeManager enterpriseEmployeeManager; + + @Resource + private DataTracerService dataTracerService; + + @Resource + private DepartmentService departmentService; + + /** + * 分页查询企业模块 + * + */ + public ResponseDTO> queryByPage(EnterpriseQueryForm queryForm) { + queryForm.setDeletedFlag(Boolean.FALSE); + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List enterpriseList = enterpriseDao.queryPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, enterpriseList); + return ResponseDTO.ok(pageResult); + } + + /** + * 获取导出数据 + */ + public List getExcelExportData(EnterpriseQueryForm queryForm) { + queryForm.setDeletedFlag(false); + return enterpriseDao.selectExcelExportData(queryForm); + } + + /** + * 查询企业详情 + * + */ + public EnterpriseVO getDetail(Long enterpriseId) { + return enterpriseDao.getDetail(enterpriseId, Boolean.FALSE); + } + + /** + * 新建企业 + * + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO createEnterprise(EnterpriseCreateForm createVO) { + // 验证企业名称是否重复 + EnterpriseEntity validateEnterprise = enterpriseDao.queryByEnterpriseName(createVO.getEnterpriseName(), null, Boolean.FALSE); + if (Objects.nonNull(validateEnterprise)) { + return ResponseDTO.userErrorParam("企业名称重复"); + } + // 数据插入 + EnterpriseEntity insertEnterprise = SmartBeanUtil.copy(createVO, EnterpriseEntity.class); + enterpriseDao.insert(insertEnterprise); + dataTracerService.insert(insertEnterprise.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE); + return ResponseDTO.ok(); + } + + /** + * 编辑企业 + * + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO updateEnterprise(EnterpriseUpdateForm updateVO) { + Long enterpriseId = updateVO.getEnterpriseId(); + // 校验企业是否存在 + EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId); + if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("企业不存在"); + } + // 验证企业名称是否重复 + EnterpriseEntity validateEnterprise = enterpriseDao.queryByEnterpriseName(updateVO.getEnterpriseName(), enterpriseId, Boolean.FALSE); + if (Objects.nonNull(validateEnterprise)) { + return ResponseDTO.userErrorParam("企业名称重复"); + } + // 数据编辑 + EnterpriseEntity updateEntity = SmartBeanUtil.copy(enterpriseDetail, EnterpriseEntity.class); + SmartBeanUtil.copyProperties(updateVO, updateEntity); + enterpriseDao.updateById(updateEntity); + + //变更记录 + DataTracerForm dataTracerForm = DataTracerForm.builder() + .dataId(updateVO.getEnterpriseId()) + .type(DataTracerTypeEnum.OA_ENTERPRISE) + .content("修改企业信息") + .diffOld(dataTracerService.getChangeContent(enterpriseDetail)) + .diffNew(dataTracerService.getChangeContent(updateEntity)) + .build(); + + dataTracerService.addTrace(dataTracerForm); + return ResponseDTO.ok(); + } + + + /** + * 删除企业 + * + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO deleteEnterprise(Long enterpriseId) { + // 校验企业是否存在 + EnterpriseEntity enterpriseDetail = enterpriseDao.selectById(enterpriseId); + if (Objects.isNull(enterpriseDetail) || enterpriseDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("企业不存在"); + } + enterpriseDao.deleteEnterprise(enterpriseId, Boolean.TRUE); + dataTracerService.delete(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE); + return ResponseDTO.ok(); + } + + /** + * 企业列表查询 + */ + public ResponseDTO> queryList(Integer type) { + List enterpriseList = enterpriseDao.queryList(type, Boolean.FALSE, Boolean.FALSE); + return ResponseDTO.ok(enterpriseList); + } + + //----------------------------------------- 以下为员工相关-------------------------------------------- + + /** + * 企业添加员工 + * + */ + public synchronized ResponseDTO addEmployee(EnterpriseEmployeeForm enterpriseEmployeeForm) { + Long enterpriseId = enterpriseEmployeeForm.getEnterpriseId(); + EnterpriseEntity enterpriseEntity = enterpriseDao.selectById(enterpriseId); + if (enterpriseEntity == null || enterpriseEntity.getDeletedFlag()) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + //过滤掉已存在的员工 + List waitAddEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList(); + List enterpriseEmployeeEntityList = enterpriseEmployeeDao.selectByEnterpriseAndEmployeeIdList(enterpriseId, waitAddEmployeeIdList); + if (CollectionUtils.isNotEmpty(enterpriseEmployeeEntityList)) { + List existEmployeeIdList = enterpriseEmployeeEntityList.stream().map(EnterpriseEmployeeEntity::getEmployeeId).collect(Collectors.toList()); + waitAddEmployeeIdList = waitAddEmployeeIdList.stream().filter(e -> !existEmployeeIdList.contains(e)).collect(Collectors.toList()); + } + if (CollectionUtils.isEmpty(waitAddEmployeeIdList)) { + return ResponseDTO.ok(); + } + List batchAddList = Lists.newArrayList(); + for (Long employeeId : waitAddEmployeeIdList) { + EnterpriseEmployeeEntity enterpriseEmployeeEntity = new EnterpriseEmployeeEntity(); + enterpriseEmployeeEntity.setEnterpriseId(enterpriseId); + enterpriseEmployeeEntity.setEmployeeId(employeeId); + batchAddList.add(enterpriseEmployeeEntity); + } + enterpriseEmployeeManager.saveBatch(batchAddList); + return ResponseDTO.ok(); + } + + /** + * 企业删除员工 + * + */ + public synchronized ResponseDTO deleteEmployee(EnterpriseEmployeeForm enterpriseEmployeeForm) { + Long enterpriseId = enterpriseEmployeeForm.getEnterpriseId(); + EnterpriseEntity enterpriseEntity = enterpriseDao.selectById(enterpriseId); + if (enterpriseEntity == null || enterpriseEntity.getDeletedFlag()) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + List waitDeleteEmployeeIdList = enterpriseEmployeeForm.getEmployeeIdList(); + enterpriseEmployeeDao.deleteByEnterpriseAndEmployeeIdList(enterpriseId, waitDeleteEmployeeIdList); + return ResponseDTO.ok(); + } + + /** + * 企业下员工列表 + * + */ + public List employeeList(List enterpriseIdList) { + if (CollectionUtils.isEmpty(enterpriseIdList)) { + return Lists.newArrayList(); + } + return enterpriseEmployeeDao.selectByEnterpriseIdList(enterpriseIdList); + } + + /** + * 分页查询企业员工 + * + */ + public PageResult queryPageEmployeeList(EnterpriseEmployeeQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List enterpriseEmployeeVOList = enterpriseEmployeeDao.queryPageEmployeeList(page, queryForm); + for (EnterpriseEmployeeVO enterpriseEmployeeVO : enterpriseEmployeeVOList) { + enterpriseEmployeeVO.setDepartmentName(departmentService.getDepartmentPath(enterpriseEmployeeVO.getDepartmentId())); + } + return SmartPageUtil.convert2PageResult(page, enterpriseEmployeeVOList); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/constant/EnterpriseTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/constant/EnterpriseTypeEnum.java new file mode 100644 index 0000000..43ee91d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/constant/EnterpriseTypeEnum.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.constant; + + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 企业类型 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +public enum EnterpriseTypeEnum implements BaseEnum { + + /** + * 有限企业 + */ + NORMAL(1, "有限企业"), + + /** + * 外资企业 + */ + FOREIGN(2, "外资企业"), + ; + + private Integer value; + private String desc; + + EnterpriseTypeEnum(Integer value, String desc) { + this.value = value; + this.desc = desc; + } + + + @Override + public Integer getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.java new file mode 100644 index 0000000..9f3ea36 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseDao.java @@ -0,0 +1,61 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEntity; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.EnterpriseQueryForm; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseExcelVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseListVO; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 企业 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Mapper +public interface EnterpriseDao extends BaseMapper { + + /** + * 根据企业名称查询 + * + */ + EnterpriseEntity queryByEnterpriseName(@Param("enterpriseName") String enterpriseName, @Param("excludeEnterpriseId") Long excludeEnterpriseId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 删除企业 + */ + void deleteEnterprise(@Param("enterpriseId") Long enterpriseId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 企业分页查询 + * + */ + List queryPage(Page page, @Param("queryForm") EnterpriseQueryForm queryForm); + + /** + * 查询导出的数据 + * + */ + List selectExcelExportData(@Param("queryForm") EnterpriseQueryForm queryForm); + + /** + * 查询企业详情 + * + */ + EnterpriseVO getDetail(@Param("enterpriseId") Long enterpriseId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 查询列表 + * + */ + List queryList(@Param("type") Integer type, @Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag); + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.java new file mode 100644 index 0000000..128d87a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/dao/EnterpriseEmployeeDao.java @@ -0,0 +1,66 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity.EnterpriseEmployeeEntity; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.form.EnterpriseEmployeeQueryForm; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseEmployeeVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; + +/** + * 企业员工 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Mapper +public interface EnterpriseEmployeeDao extends BaseMapper { + + + /** + * 根据员工查询 + */ + List selectByEmployeeIdList(@Param("employeeIdList")Collection employeeIdList); + + /** + * 查询员工关联的企业 + */ + List selectEnterpriseIdByEmployeeId(@Param("employeeId")Long employeeId); + /** + * 根据企业查询 + */ + List selectByEnterpriseIdList(@Param("enterpriseIdList")Collection enterpriseIdList); + /** + * 根据企业查询 + */ + List selectByEnterpriseId(@Param("enterpriseId")Long enterpriseId); + + /** + * 查询企业下的所有员工id + */ + List selectEmployeeIdByEnterpriseIdList(@Param("enterpriseIdList")Collection enterpriseIdList); + /** + * 根据员工删除 + */ + void deleteByEnterpriseAndEmployeeIdList(@Param("enterpriseId")Long enterpriseId, @Param("employeeIdList")Collection employeeIdList); + + /** + * 根据员工查询 + */ + List selectByEnterpriseAndEmployeeIdList(@Param("enterpriseId")Long enterpriseId, @Param("employeeIdList")Collection employeeIdList); + + /** + * 删除某员工关联的所有企业 + */ + void deleteByEmployeeId(@Param("employeeId")Long employeeId); + + /** + * 分页查询企业员工 + */ + List queryPageEmployeeList(Page page,@Param("queryForm") EnterpriseEmployeeQueryForm queryForm); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEmployeeEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEmployeeEntity.java new file mode 100644 index 0000000..1c44ce4 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEmployeeEntity.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * 企业员工 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +@TableName("t_oa_enterprise_employee") +@NoArgsConstructor +public class EnterpriseEmployeeEntity { + + @TableId(type = IdType.AUTO) + private Long enterpriseEmployeeId; + + /** + * 企业ID + */ + private Long enterpriseId; + /** + * 员工 + */ + private Long employeeId; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + public EnterpriseEmployeeEntity(Long enterpriseId, Long employeeId) { + this.enterpriseId = enterpriseId; + this.employeeId = employeeId; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEntity.java new file mode 100644 index 0000000..b378729 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/entity/EnterpriseEntity.java @@ -0,0 +1,150 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldEnum; +import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldLabel; + +import java.time.LocalDateTime; + +/** + * 企业 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +@TableName("t_oa_enterprise") +public class EnterpriseEntity { + + /** + * 企业ID + */ + @TableId(type = IdType.AUTO) + private Long enterpriseId; + + /** + * 企业名称 + */ + @DataTracerFieldLabel("企业名称") + private String enterpriseName; + + /** + * 企业logo + */ + @DataTracerFieldLabel("企业logo") + private String enterpriseLogo; + + /** + * 统一社会信用代码 + */ + @DataTracerFieldLabel("统一社会信用代码") + private String unifiedSocialCreditCode; + + /** + * 类型 + * + * @see EnterpriseTypeEnum + */ + @DataTracerFieldLabel("类型") + @DataTracerFieldEnum(enumClass = EnterpriseTypeEnum.class) + private Integer type; + + /** + * 联系人 + */ + @DataTracerFieldLabel("联系人") + private String contact; + + /** + * 联系人电话 + */ + @DataTracerFieldLabel("联系人电话") + private String contactPhone; + + /** + * 邮箱 + */ + @DataTracerFieldLabel("邮箱") + private String email; + + /** + * 省份 + */ + private Integer province; + + /** + * 省份名称 + */ + @DataTracerFieldLabel("省份名称") + private String provinceName; + + /** + * 城市 + */ + private Integer city; + + /** + * 城市名称 + */ + @DataTracerFieldLabel("城市名称") + private String cityName; + + /** + * 区县 + */ + private Integer district; + + /** + * 区县名称 + */ + @DataTracerFieldLabel("区县名称") + private String districtName; + + /** + * 详细地址 + */ + @DataTracerFieldLabel("详细地址") + private String address; + + /** + * 营业执照 + */ + @DataTracerFieldLabel("营业执照") + private String businessLicense; + + /** + * 禁用状态 + */ + @DataTracerFieldLabel("禁用状态") + private Boolean disabledFlag; + + /** + * 删除状态 + */ + @DataTracerFieldLabel("删除状态") + private Boolean deletedFlag; + + /** + * 创建人ID + */ + private Long createUserId; + + /** + * 创建人ID + */ + private String createUserName; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseCreateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseCreateForm.java new file mode 100644 index 0000000..33d63e1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseCreateForm.java @@ -0,0 +1,97 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.Data; +import net.lab1024.sa.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum; +import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer; +import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.util.SmartVerificationUtil; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.hibernate.validator.constraints.Length; + +/** + * OA企业模块创建 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +public class EnterpriseCreateForm { + + @Schema(description = "企业名称") + @NotBlank(message = "企业名称不能为空") + @Length(max = 200, message = "企业名称最多200字符") + private String enterpriseName; + + @Schema(description = "企业logo") + @JsonSerialize(using = FileKeyVoSerializer.class) + @JsonDeserialize(using = FileKeyVoDeserializer.class) + private String enterpriseLogo; + + @Schema(description = "统一社会信用代码") + @NotBlank(message = "统一社会信用代码不能为空") + @Length(max = 200, message = "统一社会信用代码最多200字符") + private String unifiedSocialCreditCode; + + @Schema(description = "联系人") + @NotBlank(message = "联系人不能为空") + @Length(max = 100, message = "联系人最多100字符") + private String contact; + + @Schema(description = "联系人电话") + @NotBlank(message = "联系人电话不能为空") + @Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确") + private String contactPhone; + + @SchemaEnum(desc = "类型", value = EnterpriseTypeEnum.class) + @CheckEnum(message = "类型不正确", value = EnterpriseTypeEnum.class) + private Integer type; + + @Schema(description = "邮箱") + @Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱格式不正确") + private String email; + + @Schema(description = "省份") + private Integer province; + + @Schema(description = "省份名称") + private String provinceName; + + @Schema(description = "城市") + private Integer city; + + @Schema(description = "城市名称") + private String cityName; + + @Schema(description = "区县") + private Integer district; + + @Schema(description = "区县名称") + private String districtName; + + @Schema(description = "详细地址") + @Length(max = 500, message = "详细地址最多500字符") + private String address; + + @Schema(description = "营业执照") + @JsonSerialize(using = FileKeyVoSerializer.class) + @JsonDeserialize(using = FileKeyVoDeserializer.class) + private String businessLicense; + + @Schema(description = "禁用状态") + @NotNull(message = "禁用状态不能为空") + private Boolean disabledFlag; + + @Schema(description = "创建人", hidden = true) + private Long createUserId; + + @Schema(description = "创建人", hidden = true) + private String createUserName; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeForm.java new file mode 100644 index 0000000..5878e6b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeForm.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +/** + * 企业员工 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +public class EnterpriseEmployeeForm { + + @Schema(description = "企业id") + @NotNull(message = "企业id不能为空") + private Long enterpriseId; + + @Schema(description = "员工信息id") + @NotEmpty(message = "员工信息id不能为空") + private List employeeIdList; +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeQueryForm.java new file mode 100644 index 0000000..55057e1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseEmployeeQueryForm.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +/** + * 查询企业员工 + * + * @Date 2021-12-20 21:06:49 + * @Author wzh + */ +@Data +public class EnterpriseEmployeeQueryForm extends PageParam { + + @Schema(description = "搜索词") + @Length(max = 20, message = "搜索词最多20字符") + private String keyword; + + @Schema(description = "公司Id") + @NotNull(message = "公司id 不能为空") + private Long enterpriseId; + + @Schema(description = "删除标识", hidden = true) + private Boolean deletedFlag; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseQueryForm.java new file mode 100644 index 0000000..d736de3 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseQueryForm.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; + +/** + * OA企业模块分页查询 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +public class EnterpriseQueryForm extends PageParam { + + @Schema(description = "关键字") + @Length(max = 200, message = "关键字最多200字符") + private String keywords; + + @Schema(description = "开始时间") + private LocalDate startTime; + + @Schema(description = "结束时间") + private LocalDate endTime; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "删除状态", hidden = true) + private Boolean deletedFlag; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseUpdateForm.java new file mode 100644 index 0000000..5488e44 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/form/EnterpriseUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * OA企业模块编辑 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +public class EnterpriseUpdateForm extends EnterpriseCreateForm { + + @Schema(description = "企业ID") + @NotNull(message = "企业ID不能为空") + private Long enterpriseId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseEmployeeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseEmployeeVO.java new file mode 100644 index 0000000..2037848 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseEmployeeVO.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 企业员工信息 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +public class EnterpriseEmployeeVO { + + private Long enterpriseEmployeeId; + + @Schema(description = "企业ID") + private Long enterpriseId; + + @Schema(description = "企业名称") + private String enterpriseName; + + @Schema(description = "员工") + private Long employeeId; + + @Schema(description = "登录账号") + private String loginName; + + @Schema(description = "员工名称") + private String actualName; + + @Schema(description = "手机号码") + private String phone; + + @Schema(description = "部门id") + private Long departmentId; + + @Schema(description = "是否被禁用") + private Boolean disabledFlag; + + @Schema(description = "部门名称") + private String departmentName; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseExcelVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseExcelVO.java new file mode 100644 index 0000000..eed79b7 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseExcelVO.java @@ -0,0 +1,45 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo; + +import cn.idev.excel.annotation.ExcelProperty; +import lombok.Data; + +/** + * 企业信息 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +public class EnterpriseExcelVO { + + @ExcelProperty("企业名称") + private String enterpriseName; + + @ExcelProperty("统一社会信用代码") + private String unifiedSocialCreditCode; + + @ExcelProperty("企业类型") + private String typeName; + + @ExcelProperty("联系人") + private String contact; + + @ExcelProperty("联系人电话") + private String contactPhone; + + @ExcelProperty("邮箱") + private String email; + + @ExcelProperty("省份名称") + private String provinceName; + + @ExcelProperty("城市名称") + private String cityName; + + @ExcelProperty("区县名称") + private String districtName; + + @ExcelProperty("详细地址") + private String address; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseListVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseListVO.java new file mode 100644 index 0000000..761fc6d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseListVO.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * OA企业模块列表 + * + * @date 2022/6/23 14:31 + */ +@Data +public class EnterpriseListVO { + + @Schema(description = "企业ID") + private Long enterpriseId; + + @Schema(description = "企业名称") + private String enterpriseName; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseVO.java new file mode 100644 index 0000000..f1f2346 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/enterprise/domain/vo/EnterpriseVO.java @@ -0,0 +1,86 @@ +package net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.business.oa.enterprise.constant.EnterpriseTypeEnum; +import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +import java.time.LocalDateTime; + +/** + * 企业信息 + * + * @Date 2022/7/28 20:37:15 + * @Author wzh + */ +@Data +public class EnterpriseVO { + + @Schema(description = "企业ID") + private Long enterpriseId; + + @Schema(description = "企业名称") + private String enterpriseName; + + @Schema(description = "企业logo") + @JsonSerialize(using = FileKeyVoSerializer.class) + private String enterpriseLogo; + + @Schema(description = "统一社会信用代码") + private String unifiedSocialCreditCode; + + @SchemaEnum(desc = "类型", value = EnterpriseTypeEnum.class) + private Integer type; + + @Schema(description = "联系人") + private String contact; + + @Schema(description = "联系人电话") + private String contactPhone; + + @Schema(description = "邮箱") + private String email; + + @Schema(description = "省份") + private Integer province; + + @Schema(description = "省份名称") + private String provinceName; + + @Schema(description = "城市") + private Integer city; + + @Schema(description = "城市名称") + private String cityName; + + @Schema(description = "区县") + private Integer district; + + @Schema(description = "区县名称") + private String districtName; + + @Schema(description = "详细地址") + private String address; + + @Schema(description = "营业执照") + @JsonSerialize(using = FileKeyVoSerializer.class) + private String businessLicense; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "创建人ID") + private Long createUserId; + + @Schema(description = "创建人名称") + private String createUserName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceController.java new file mode 100644 index 0000000..ec5c4c1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceController.java @@ -0,0 +1,84 @@ +package net.lab1024.sa.admin.module.business.oa.invoice; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceAddForm; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceQueryForm; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceUpdateForm; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceVO; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * OA发票信息 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Slf4j +@RestController +@Tag(name = AdminSwaggerTagConst.Business.OA_INVOICE) +public class InvoiceController { + + @Resource + private InvoiceService invoiceService; + + @Operation(summary = "分页查询发票信息 @author 善逸") + @PostMapping("/oa/invoice/page/query") + @SaCheckPermission("oa:invoice:query") + public ResponseDTO> queryByPage(@RequestBody @Valid InvoiceQueryForm queryForm) { + return invoiceService.queryByPage(queryForm); + } + + @Operation(summary = "查询发票信息详情 @author 善逸") + @GetMapping("/oa/invoice/get/{invoiceId}") + @SaCheckPermission("oa:invoice:query") + public ResponseDTO getDetail(@PathVariable Long invoiceId) { + return invoiceService.getDetail(invoiceId); + } + + @Operation(summary = "新建发票信息 @author 善逸") + @PostMapping("/oa/invoice/create") + @SaCheckPermission("oa:invoice:add") + public ResponseDTO createInvoice(@RequestBody @Valid InvoiceAddForm createVO) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + createVO.setCreateUserId(requestUser.getUserId()); + createVO.setCreateUserName(requestUser.getUserName()); + return invoiceService.createInvoice(createVO); + } + + @OperateLog + @Operation(summary = "编辑发票信息 @author 善逸") + @PostMapping("/oa/invoice/update") + @SaCheckPermission("oa:invoice:update") + public ResponseDTO updateInvoice(@RequestBody @Valid InvoiceUpdateForm updateVO) { + return invoiceService.updateInvoice(updateVO); + } + + @Operation(summary = "删除发票信息 @author 善逸") + @GetMapping("/invoice/delete/{invoiceId}") + @SaCheckPermission("oa:invoice:delete") + public ResponseDTO deleteInvoice(@PathVariable Long invoiceId) { + return invoiceService.deleteInvoice(invoiceId); + } + + @Operation(summary = "查询列表") + @GetMapping("/oa/invoice/query/list/{enterpriseId}") + @SaCheckPermission("oa:invoice:query") + public ResponseDTO> queryList(@PathVariable Long enterpriseId) { + return invoiceService.queryList(enterpriseId); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.java new file mode 100644 index 0000000..ae5852f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceDao.java @@ -0,0 +1,57 @@ +package net.lab1024.sa.admin.module.business.oa.invoice; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceEntity; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceQueryForm; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.InvoiceVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * OA发票信息 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Mapper +public interface InvoiceDao extends BaseMapper { + + /** + * 根据账号查询 + * @param enterpriseId + * @param accountNumber + * @param excludeInvoiceId + * @param deletedFlag + * @return + */ + InvoiceEntity queryByAccountNumber(@Param("enterpriseId") Long enterpriseId, @Param("accountNumber") String accountNumber, @Param("excludeInvoiceId") Long excludeInvoiceId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 删除发票信息 + * + * @param invoiceId + * @param deletedFlag + */ + void deleteInvoice(@Param("invoiceId") Long invoiceId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 发票信息分页查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") InvoiceQueryForm queryForm); + + /** + * 查询发票信息详情 + * @param invoiceId + * @param deletedFlag + * @return + */ + InvoiceVO getDetail(@Param("invoiceId") Long invoiceId, @Param("deletedFlag") Boolean deletedFlag); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceService.java new file mode 100644 index 0000000..2cb5456 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/InvoiceService.java @@ -0,0 +1,140 @@ +package net.lab1024.sa.admin.module.business.oa.invoice; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.business.oa.enterprise.EnterpriseService; +import net.lab1024.sa.admin.module.business.oa.enterprise.domain.vo.EnterpriseVO; +import net.lab1024.sa.admin.module.business.oa.invoice.domain.*; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Objects; + +/** + * OA发票信息 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Service +@Slf4j +public class InvoiceService { + + @Resource + private InvoiceDao invoiceDao; + + @Resource + private EnterpriseService enterpriseService; + + @Resource + private DataTracerService dataTracerService; + + /** + * 分页查询发票信息 + */ + public ResponseDTO> queryByPage(InvoiceQueryForm queryForm) { + queryForm.setDeletedFlag(Boolean.FALSE); + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List invoiceList = invoiceDao.queryPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, invoiceList); + return ResponseDTO.ok(pageResult); + } + + public ResponseDTO> queryList(Long enterpriseId) { + InvoiceQueryForm queryForm = new InvoiceQueryForm(); + queryForm.setDeletedFlag(Boolean.FALSE); + queryForm.setDisabledFlag(Boolean.FALSE); + queryForm.setEnterpriseId(enterpriseId); + List invoiceList = invoiceDao.queryPage(null, queryForm); + return ResponseDTO.ok(invoiceList); + } + + /** + * 查询发票信息详情 + */ + public ResponseDTO getDetail(Long invoiceId) { + // 校验发票信息是否存在 + InvoiceVO invoiceVO = invoiceDao.getDetail(invoiceId, Boolean.FALSE); + if (Objects.isNull(invoiceVO)) { + return ResponseDTO.userErrorParam("发票信息不存在"); + } + return ResponseDTO.ok(invoiceVO); + } + + /** + * 新建发票信息 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO createInvoice(InvoiceAddForm createVO) { + Long enterpriseId = createVO.getEnterpriseId(); + // 校验企业是否存在 + EnterpriseVO enterpriseVO = enterpriseService.getDetail(enterpriseId); + if (Objects.isNull(enterpriseVO)) { + return ResponseDTO.userErrorParam("企业不存在"); + } + // 验证发票信息账号是否重复 + InvoiceEntity validateInvoice = invoiceDao.queryByAccountNumber(enterpriseId, createVO.getAccountNumber(), null, Boolean.FALSE); + if (Objects.nonNull(validateInvoice)) { + return ResponseDTO.userErrorParam("发票信息账号重复"); + } + // 数据插入 + InvoiceEntity insertInvoice = SmartBeanUtil.copy(createVO, InvoiceEntity.class); + invoiceDao.insert(insertInvoice); + dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "新增发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(insertInvoice)); + return ResponseDTO.ok(); + } + + /** + * 编辑发票信息 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO updateInvoice(InvoiceUpdateForm updateVO) { + Long enterpriseId = updateVO.getEnterpriseId(); + // 校验企业是否存在 + EnterpriseVO enterpriseVO = enterpriseService.getDetail(enterpriseId); + if (Objects.isNull(enterpriseVO)) { + return ResponseDTO.userErrorParam("企业不存在"); + } + Long invoiceId = updateVO.getInvoiceId(); + // 校验发票信息是否存在 + InvoiceEntity invoiceDetail = invoiceDao.selectById(invoiceId); + if (Objects.isNull(invoiceDetail) || invoiceDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("发票信息不存在"); + } + // 验证发票信息账号是否重复 + InvoiceEntity validateInvoice = invoiceDao.queryByAccountNumber(updateVO.getEnterpriseId(), updateVO.getAccountNumber(), invoiceId, Boolean.FALSE); + if (Objects.nonNull(validateInvoice)) { + return ResponseDTO.userErrorParam("发票信息账号重复"); + } + // 数据编辑 + InvoiceEntity updateInvoice = SmartBeanUtil.copy(updateVO, InvoiceEntity.class); + invoiceDao.updateById(updateInvoice); + dataTracerService.addTrace(enterpriseId, DataTracerTypeEnum.OA_ENTERPRISE, "更新发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(invoiceDetail, updateInvoice)); + return ResponseDTO.ok(); + } + + + /** + * 删除发票信息 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO deleteInvoice(Long invoiceId) { + // 校验发票信息是否存在 + InvoiceEntity invoiceDetail = invoiceDao.selectById(invoiceId); + if (Objects.isNull(invoiceDetail) || invoiceDetail.getDeletedFlag()) { + return ResponseDTO.userErrorParam("发票信息不存在"); + } + invoiceDao.deleteInvoice(invoiceId, Boolean.TRUE); + dataTracerService.addTrace(invoiceDetail.getEnterpriseId(), DataTracerTypeEnum.OA_ENTERPRISE, "删除发票:" + DataTracerConst.HTML_BR + dataTracerService.getChangeContent(invoiceDetail)); + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceAddForm.java new file mode 100644 index 0000000..e663b05 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceAddForm.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.admin.module.business.oa.invoice.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * OA发票信息新建 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Data +public class InvoiceAddForm { + + @Schema(description = "开票抬头") + @NotBlank(message = "开票抬头不能为空") + @Length(max = 200, message = "开票抬头最多200字符") + private String invoiceHeads; + + @Schema(description = "纳税人识别号") + @NotBlank(message = "纳税人识别号不能为空") + @Length(max = 200, message = "纳税人识别号最多200字符") + private String taxpayerIdentificationNumber; + + @Schema(description = "银行账户") + @NotBlank(message = "银行账户不能为空") + @Length(max = 200, message = "银行账户最多200字符") + private String accountNumber; + + @Schema(description = "开户行") + @NotBlank(message = "开户行不能为空") + @Length(max = 200, message = "开户行最多200字符") + private String bankName; + + @Schema(description = "启用状态") + @NotNull(message = "启用状态不能为空") + private Boolean disabledFlag; + + @Schema(description = "备注") + @Length(max = 500, message = "备注最多500字符") + private String remark; + + @Schema(description = "企业") + @NotNull(message = "企业不能为空") + private Long enterpriseId; + + @Schema(description = "创建人", hidden = true) + private Long createUserId; + + @Schema(description = "创建人名称", hidden = true) + private String createUserName; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceEntity.java new file mode 100644 index 0000000..273ca1d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceEntity.java @@ -0,0 +1,95 @@ +package net.lab1024.sa.admin.module.business.oa.invoice.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.base.module.support.datatracer.annoation.DataTracerFieldLabel; + +import java.time.LocalDateTime; + +/** + * OA发票信息 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Data +@TableName("t_oa_invoice") +public class InvoiceEntity { + + /** + * 发票信息ID + */ + @TableId(type = IdType.AUTO) + private Long invoiceId; + + /** + * 开票抬头 + */ + @DataTracerFieldLabel("开票抬头") + private String invoiceHeads; + + /** + * 纳税人识别号 + */ + @DataTracerFieldLabel("纳税人识别号") + private String taxpayerIdentificationNumber; + + /** + * 银行账户 + */ + @DataTracerFieldLabel("银行账户") + private String accountNumber; + + /** + * 开户行 + */ + @DataTracerFieldLabel("开户行") + private String bankName; + + /** + * 备注 + */ + @DataTracerFieldLabel("备注") + private String remark; + + /** + * 企业ID + */ + private Long enterpriseId; + + /** + * 禁用状态 + */ + @DataTracerFieldLabel("禁用状态") + private Boolean disabledFlag; + + /** + * 删除状态 + */ + @DataTracerFieldLabel("删除状态") + private Boolean deletedFlag; + + /** + * 创建人ID + */ + private Long createUserId; + + /** + * 创建人ID + */ + private String createUserName; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceQueryForm.java new file mode 100644 index 0000000..06412f9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceQueryForm.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.admin.module.business.oa.invoice.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; + +/** + * OA发票信息查询 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Data +public class InvoiceQueryForm extends PageParam { + + @Schema(description = "企业ID") + private Long enterpriseId; + + @Schema(description = "关键字") + @Length(max = 200, message = "关键字最多200字符") + private String keywords; + + @Schema(description = "开始时间") + private LocalDate startTime; + + @Schema(description = "结束时间") + private LocalDate endTime; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "删除状态", hidden = true) + private Boolean deletedFlag; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceUpdateForm.java new file mode 100644 index 0000000..ea82736 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.business.oa.invoice.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * OA发票信息编辑 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Data +public class InvoiceUpdateForm extends InvoiceAddForm { + + @Schema(description = "发票信息ID") + @NotNull(message = "发票信息ID不能为空") + private Long invoiceId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceVO.java new file mode 100644 index 0000000..df65d70 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/invoice/domain/InvoiceVO.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.admin.module.business.oa.invoice.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * OA发票信息 + * + * @Date 2022-06-23 19:32:59 + * @Author wzh + */ +@Data +public class InvoiceVO { + + @Schema(description = "发票信息ID") + private Long invoiceId; + + @Schema(description = "开票抬头") + private String invoiceHeads; + + @Schema(description = "纳税人识别号") + private String taxpayerIdentificationNumber; + + @Schema(description = "银行账户") + private String accountNumber; + + @Schema(description = "开户行") + private String bankName; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "企业") + private Long enterpriseId; + + @Schema(description = "企业名称") + private String enterpriseName; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "创建人ID") + private Long createUserId; + + @Schema(description = "创建人名称") + private String createUserName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/controller/LeaveController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/controller/LeaveController.java new file mode 100644 index 0000000..a1d0942 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/controller/LeaveController.java @@ -0,0 +1,77 @@ +package net.lab1024.sa.admin.module.business.oa.leave.controller; + +import net.lab1024.sa.admin.module.business.oa.leave.domain.form.LeaveAddForm; +import net.lab1024.sa.admin.module.business.oa.leave.domain.form.LeaveQueryForm; +import net.lab1024.sa.admin.module.business.oa.leave.domain.form.LeaveUpdateForm; +import net.lab1024.sa.admin.module.business.oa.leave.domain.vo.LeaveVO; +import net.lab1024.sa.admin.module.business.oa.leave.service.LeaveService; +import net.lab1024.sa.base.common.domain.ValidateList; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.PageResult; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import cn.dev33.satoken.annotation.SaCheckPermission; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; + +/** + * OA 请假申请表 Controller + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@RestController +@Tag(name = "OA 请假申请表") +public class LeaveController { + + @Resource + private LeaveService leaveService; + + @Operation(summary = "分页查询") + @PostMapping("/leave/queryPage") + @SaCheckPermission("leave:query") + public ResponseDTO> queryPage(@RequestBody @Valid LeaveQueryForm queryForm) { + return ResponseDTO.ok(leaveService.queryPage(queryForm)); + } + + @Operation(summary = "添加") + @PostMapping("/leave/add") + @SaCheckPermission("leave:add") + public ResponseDTO add(@RequestBody @Valid LeaveAddForm addForm) { + addForm.setCreateUserId(Long.valueOf(SmartRequestUtil.getRequestUserId())); + return leaveService.add(addForm); + } + + @Operation(summary = "更新") + @PostMapping("/leave/update") + @SaCheckPermission("leave:update") + public ResponseDTO update(@RequestBody @Valid LeaveUpdateForm updateForm) { + return leaveService.update(updateForm); + } + + @Operation(summary = "批量删除") + @PostMapping("/leave/batchDelete") + @SaCheckPermission("leave:delete") + public ResponseDTO batchDelete(@RequestBody ValidateList idList) { + return leaveService.batchDelete(idList); + } + + @Operation(summary = "单个删除") + @GetMapping("/leave/delete/{id}") + @SaCheckPermission("leave:delete") + public ResponseDTO batchDelete(@PathVariable Long id) { + return leaveService.delete(id); + } + + @GetMapping("/leave/{id}") + public ResponseDTO getDetail(@PathVariable Long id) { + return ResponseDTO.ok(leaveService.getDetail(id)); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/dao/LeaveDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/dao/LeaveDao.java new file mode 100644 index 0000000..de1a1af --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/dao/LeaveDao.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.business.oa.leave.dao; + +import java.util.List; +import net.lab1024.sa.admin.module.business.oa.leave.domain.entity.LeaveEntity; +import net.lab1024.sa.admin.module.business.oa.leave.domain.form.LeaveQueryForm; +import net.lab1024.sa.admin.module.business.oa.leave.domain.vo.LeaveVO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +/** + * OA 请假申请表 Dao + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@Mapper +public interface LeaveDao extends BaseMapper { + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") LeaveQueryForm queryForm); + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/entity/LeaveEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/entity/LeaveEntity.java new file mode 100644 index 0000000..19274f2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/entity/LeaveEntity.java @@ -0,0 +1,97 @@ +package net.lab1024.sa.admin.module.business.oa.leave.domain.entity; + +import com.baomidou.mybatisplus.annotation.FieldFill; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * OA 请假申请表 实体类 + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@Data +@TableName("t_leave") +public class LeaveEntity { + + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Long leaveId; + + /** + * 请假类型 + */ + private String type; + + /** + * 请假原因 + */ + private String reason; + + /** + * 开始时间 + */ + private LocalDate startTime; + + /** + * 结束时间 + */ + private LocalDate endTime; + + /** + * 请假天数 + */ + private Integer day; + + /** + * 流程实例的id + */ + private Long instanceId; + + /** + * 节点编码 + */ + private String nodeCode; + + /** + * 流程节点名称 + */ + private String nodeName; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效) + */ + private String flowStatus; + + private Boolean deletedFlag; + + private Long createUserId; + + /** + * 创建时间 + */ + @TableField(fill = FieldFill.INSERT) + private LocalDateTime createTime; + + + /** + * 更新时间 + */ + @TableField(fill = FieldFill.INSERT_UPDATE) + private LocalDateTime updateTime; + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveAddForm.java new file mode 100644 index 0000000..7cb9032 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveAddForm.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.admin.module.business.oa.leave.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * OA 请假申请表 新建表单 + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@Data +public class LeaveAddForm { + + @Schema(description = "请假类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请假类型 不能为空") + private String type; + + @Schema(description = "请假原因", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请假原因 不能为空") + private String reason; + + /** + * 开始时间 + */ + private LocalDate startTime; + + /** + * 结束时间 + */ + private LocalDate endTime; + + /** + * 请假天数 + */ + private Integer day; + + @Schema(description = "创建者") + private Long createUserId; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveQueryForm.java new file mode 100644 index 0000000..7bd23ec --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveQueryForm.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.business.oa.leave.domain.form; + +import net.lab1024.sa.base.common.domain.PageParam; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDate; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * OA 请假申请表 分页查询表单 + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@Data +@EqualsAndHashCode(callSuper = false) +public class LeaveQueryForm extends PageParam { + + @Schema(description = "请假类型") + private String type; + + @Schema(description = "开始时间") + private LocalDate startTimeBegin; + + @Schema(description = "开始时间") + private LocalDate startTimeEnd; + + @Schema(description = "请假原因") + private String reason; + + @Schema(description = "流程状态") + private String flowStatus; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveUpdateForm.java new file mode 100644 index 0000000..635c574 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/form/LeaveUpdateForm.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.admin.module.business.oa.leave.domain.form; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * OA 请假申请表 更新表单 + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@Data +public class LeaveUpdateForm { + + @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "主键 不能为空") + private Long leaveId; + + @Schema(description = "请假类型", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "请假类型 不能为空") + private String type; + + @Schema(description = "请假原因", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "请假原因 不能为空") + private String reason; + + /** + * 开始时间 + */ + private LocalDate startTime; + + /** + * 结束时间 + */ + private LocalDate endTime; + /** + * 请假天数 + */ + private Integer day; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/vo/LeaveVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/vo/LeaveVO.java new file mode 100644 index 0000000..6e54857 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/domain/vo/LeaveVO.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.admin.module.business.oa.leave.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * OA 请假申请表 列表VO + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@Data +public class LeaveVO { + + + @Schema(description = "主键") + private Long leaveId; + + @Schema(description = "请假类型") + private String type; + + @Schema(description = "请假原因") + private String reason; + + /** + * 开始时间 + */ + private LocalDate startTime; + + /** + * 结束时间 + */ + private LocalDate endTime; + + @Schema(description = "请假天数") + private Integer day; + + @Schema(description = "流程节点名称") + private String nodeName; + + @Schema(description = "流程状态(0待提交 1审批中 2 审批通过 3自动通过 4终止 5作废 6撤销 7取回 8已完成 9已退回 10失效)") + private String flowStatus; + + @Schema(description = "创建者") + private String createUserName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + /** + * 流程实例的id + */ + @Schema(description = "流程实例的id") + private Long instanceId; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/manager/LeaveManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/manager/LeaveManager.java new file mode 100644 index 0000000..602729c --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/manager/LeaveManager.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.business.oa.leave.manager; + +import net.lab1024.sa.admin.module.business.oa.leave.domain.entity.LeaveEntity; +import net.lab1024.sa.admin.module.business.oa.leave.dao.LeaveDao; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + * OA 请假申请表 Manager + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ +@Service +public class LeaveManager extends ServiceImpl { + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/service/LeaveService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/service/LeaveService.java new file mode 100644 index 0000000..086fb0a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/leave/service/LeaveService.java @@ -0,0 +1,89 @@ +package net.lab1024.sa.admin.module.business.oa.leave.service; + +import java.util.List; +import net.lab1024.sa.admin.module.business.oa.leave.dao.LeaveDao; +import net.lab1024.sa.admin.module.business.oa.leave.domain.entity.LeaveEntity; +import net.lab1024.sa.admin.module.business.oa.leave.domain.form.LeaveAddForm; +import net.lab1024.sa.admin.module.business.oa.leave.domain.form.LeaveQueryForm; +import net.lab1024.sa.admin.module.business.oa.leave.domain.form.LeaveUpdateForm; +import net.lab1024.sa.admin.module.business.oa.leave.domain.vo.LeaveVO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.PageResult; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +/** + * OA 请假申请表 Service + * + * @Author wzh + * @Date 2025-05-31 20:00:10 + */ + +@Service +public class LeaveService { + + @Resource + private LeaveDao leaveDao; + + /** + * 分页查询 + */ + public PageResult queryPage(LeaveQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = leaveDao.queryPage(page, queryForm); + return SmartPageUtil.convert2PageResult(page, list); + } + + /** + * 添加 + */ + public ResponseDTO add(LeaveAddForm addForm) { + LeaveEntity leaveEntity = SmartBeanUtil.copy(addForm, LeaveEntity.class); + leaveDao.insert(leaveEntity); + return ResponseDTO.ok(); + } + + /** + * 更新 + * + */ + public ResponseDTO update(LeaveUpdateForm updateForm) { + LeaveEntity leaveEntity = SmartBeanUtil.copy(updateForm, LeaveEntity.class); + leaveDao.updateById(leaveEntity); + return ResponseDTO.ok(); + } + + /** + * 批量删除 + */ + public ResponseDTO batchDelete(List idList) { + if (CollectionUtils.isEmpty(idList)){ + return ResponseDTO.ok(); + } + + leaveDao.deleteBatchIds(idList); + return ResponseDTO.ok(); + } + + /** + * 单个删除 + */ + public ResponseDTO delete(Long id) { + if (null == id){ + return ResponseDTO.ok(); + } + + leaveDao.deleteById(id); + return ResponseDTO.ok(); + } + + public LeaveVO getDetail(Long id) { + LeaveEntity leaveEntity = leaveDao.selectById(id); + return SmartBeanUtil.copy(leaveEntity, LeaveVO.class); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/constant/NoticeVisibleRangeDataTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/constant/NoticeVisibleRangeDataTypeEnum.java new file mode 100644 index 0000000..9c3f58a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/constant/NoticeVisibleRangeDataTypeEnum.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.admin.module.business.oa.notice.constant; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 公告、通知 可见范围类型 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Getter +@AllArgsConstructor +public enum NoticeVisibleRangeDataTypeEnum implements BaseEnum { + + /** + * 员工 + */ + EMPLOYEE(1, "员工"), + + /** + * 部门 + */ + DEPARTMENT(2, "部门"), + + ; + + private final Integer value; + + private final String desc; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/controller/NoticeController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/controller/NoticeController.java new file mode 100644 index 0000000..90237d1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/controller/NoticeController.java @@ -0,0 +1,138 @@ +package net.lab1024.sa.admin.module.business.oa.notice.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.hutool.extra.servlet.JakartaServletUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.*; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.*; +import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeEmployeeService; +import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeService; +import net.lab1024.sa.admin.module.business.oa.notice.service.NoticeTypeService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog; +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 公告、通知、新闻等等 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Tag(name = AdminSwaggerTagConst.Business.OA_NOTICE) +@RestController +@OperateLog +public class NoticeController { + + @Resource + private NoticeService noticeService; + + @Resource + private NoticeTypeService noticeTypeService; + + @Resource + private NoticeEmployeeService noticeEmployeeService; + + // --------------------- 通知公告类型 ------------------------- + + @Operation(summary = "通知公告类型-获取全部 @author 卓大") + @GetMapping("/oa/noticeType/getAll") + public ResponseDTO> getAll() { + return ResponseDTO.ok(noticeTypeService.getAll()); + } + + @Operation(summary = "通知公告类型-添加 @author 卓大") + @GetMapping("/oa/noticeType/add/{name}") + public ResponseDTO add(@PathVariable String name) { + return noticeTypeService.add(name); + } + + @Operation(summary = "通知公告类型-修改 @author 卓大") + @GetMapping("/oa/noticeType/update/{noticeTypeId}/{name}") + public ResponseDTO update(@PathVariable Long noticeTypeId, @PathVariable String name) { + return noticeTypeService.update(noticeTypeId, name); + } + + @Operation(summary = "通知公告类型-删除 @author 卓大") + @GetMapping("/oa/noticeType/delete/{noticeTypeId}") + public ResponseDTO deleteNoticeType(@PathVariable Long noticeTypeId) { + return noticeTypeService.delete(noticeTypeId); + } + + // --------------------- 【管理】通知公告------------------------- + + + @Operation(summary = "【管理】通知公告-分页查询 @author 卓大") + @PostMapping("/oa/notice/query") + @SaCheckPermission("oa:notice:query") + public ResponseDTO> query(@RequestBody @Valid NoticeQueryForm queryForm) { + return ResponseDTO.ok(noticeService.query(queryForm)); + } + + @Operation(summary = "【管理】通知公告-添加 @author 卓大") + @PostMapping("/oa/notice/add") + @RepeatSubmit + @SaCheckPermission("oa:notice:add") + public ResponseDTO add(@RequestBody @Valid NoticeAddForm addForm) { + addForm.setCreateUserId(SmartRequestUtil.getRequestUserId()); + return noticeService.add(addForm); + } + + @Operation(summary = "【管理】通知公告-更新 @author 卓大") + @PostMapping("/oa/notice/update") + @RepeatSubmit + @SaCheckPermission("oa:notice:update") + public ResponseDTO update(@RequestBody @Valid NoticeUpdateForm updateForm) { + + return noticeService.update(updateForm); + } + + @Operation(summary = "【管理】通知公告-更新详情 @author 卓大") + @GetMapping("/oa/notice/getUpdateVO/{noticeId}") + @SaCheckPermission("oa:notice:update") + public ResponseDTO getUpdateFormVO(@PathVariable Long noticeId) { + return ResponseDTO.ok(noticeService.getUpdateFormVO(noticeId)); + } + + @Operation(summary = "【管理】通知公告-删除 @author 卓大") + @GetMapping("/oa/notice/delete/{noticeId}") + @SaCheckPermission("oa:notice:delete") + public ResponseDTO delete(@PathVariable Long noticeId) { + return noticeService.delete(noticeId); + } + + // --------------------- 【员工】查看 通知公告 ------------------------- + + + @Operation(summary = "【员工】通知公告-查看详情 @author 卓大") + @GetMapping("/oa/notice/employee/view/{noticeId}") + public ResponseDTO view(@PathVariable Long noticeId, HttpServletRequest request) { + return noticeEmployeeService.view( + SmartRequestUtil.getRequestUserId(), + noticeId, + JakartaServletUtil.getClientIP(request), + request.getHeader("User-Agent") + ); + } + + @Operation(summary = "【员工】通知公告-查询全部 @author 卓大") + @PostMapping("/oa/notice/employee/query") + public ResponseDTO> queryEmployeeNotice(@RequestBody @Valid NoticeEmployeeQueryForm noticeEmployeeQueryForm) { + return noticeEmployeeService.queryList(SmartRequestUtil.getRequestUserId(), noticeEmployeeQueryForm); + } + + @Operation(summary = "【员工】通知公告-查询 查看记录 @author 卓大") + @PostMapping("/oa/notice/employee/queryViewRecord") + public ResponseDTO> queryViewRecord(@RequestBody @Valid NoticeViewRecordQueryForm noticeViewRecordQueryForm) { + return ResponseDTO.ok(noticeEmployeeService.queryViewRecord(noticeViewRecordQueryForm)); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.java new file mode 100644 index 0000000..4e828d2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeDao.java @@ -0,0 +1,123 @@ +package net.lab1024.sa.admin.module.business.oa.notice.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeEmployeeQueryForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeQueryForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeViewRecordQueryForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeEmployeeVO; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeViewRecordVO; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVisibleRangeVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 公告、通知、新闻等等 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Mapper +public interface NoticeDao extends BaseMapper { + + // ================================= 数据范围相关 【子表】 ================================= + + /** + * 保存可见范围 + * + */ + void insertVisibleRange(@Param("noticeId") Long noticeId, @Param("visibleRangeFormList") List visibleRangeFormList); + + /** + * 删除可见范围 + * + */ + void deleteVisibleRange(@Param("noticeId") Long noticeId); + + /** + * 相关可见范围 + * + */ + List queryVisibleRange(@Param("noticeId") Long noticeId); + + // ================================= 通知公告【主表】 相关 ================================= + + /** + * 后管分页查询资讯 + * + */ + List query(Page page, @Param("query") NoticeQueryForm queryForm); + + + /** + * 更新删除状态 + * + */ + void updateDeletedFlag(@Param("noticeId") Long noticeId); + + // ================================= 通知公告【员工查看】 相关 ================================= + + /** + * 查询 员工 查看到的通知公告 + * + */ + List queryEmployeeNotice(Page page, + @Param("requestEmployeeId") Long requestEmployeeId, + @Param("query") NoticeEmployeeQueryForm noticeEmployeeQueryForm, + @Param("requestEmployeeDepartmentIdList") List requestEmployeeDepartmentIdList, + @Param("deletedFlag") boolean deletedFlag, + @Param("administratorFlag") boolean administratorFlag, + @Param("departmentDataType") Integer departmentDataType, + @Param("employeeDataType") Integer employeeDataType + + ); + + /** + * 查询 员工 未读的通知公告 + * + */ + List queryEmployeeNotViewNotice(Page page, + @Param("requestEmployeeId") Long requestEmployeeId, + @Param("query") NoticeEmployeeQueryForm noticeEmployeeQueryForm, + @Param("requestEmployeeDepartmentIdList") List requestEmployeeDepartmentIdList, + @Param("deletedFlag") boolean deletedFlag, + @Param("administratorFlag") boolean administratorFlag, + @Param("departmentDataType") Integer departmentDataType, + @Param("employeeDataType") Integer employeeDataType + + ); + + long viewRecordCount(@Param("noticeId")Long noticeId, @Param("employeeId")Long employeeId); + + /** + * 查询通知、公告的 查看记录 + */ + List queryNoticeViewRecordList(Page page,@Param("queryForm") NoticeViewRecordQueryForm noticeViewRecordQueryForm); + + /** + * 保存查看记录 + */ + void insertViewRecord(@Param("noticeId") Long noticeId, @Param("employeeId") Long employeeId, @Param("ip") String ip, @Param("userAgent") String userAgent,@Param("pageViewCount") Integer pageViewCount); + + /** + * 更新查看记录 + */ + void updateViewRecord(@Param("noticeId")Long noticeId, @Param("employeeId")Long requestEmployeeId,@Param("ip") String ip, @Param("userAgent")String userAgent); + + /** + * 更新 浏览量 + * + * @param noticeId 通知 id + * @param pageViewCountIncrement 页面浏览量的增量 + * @param userViewCountIncrement 用户浏览量的增量 + */ + void updateViewCount(@Param("noticeId")Long noticeId,@Param("pageViewCountIncrement") Integer pageViewCountIncrement, @Param("userViewCountIncrement")Integer userViewCountIncrement); + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.java new file mode 100644 index 0000000..eab04b6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/dao/NoticeTypeDao.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.admin.module.business.oa.notice.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeTypeEntity; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +/** + * 通知公告类型 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Mapper +public interface NoticeTypeDao extends BaseMapper { + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeEntity.java new file mode 100644 index 0000000..8d09869 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeEntity.java @@ -0,0 +1,111 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 通知公告 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +@TableName("t_notice") +public class NoticeEntity { + + @TableId(type = IdType.AUTO) + private Long noticeId; + + /** + * 类型 + */ + private Long noticeTypeId; + + /** + * 标题 + */ + private String title; + + /** + * 是否全部可见 + */ + private Boolean allVisibleFlag; + + /** + * 是否定时发布 + */ + private Boolean scheduledPublishFlag; + + /** + * 发布时间 + */ + private LocalDateTime publishTime; + + /** + * 内容 纯文本 + */ + private String contentText; + + /** + * 内容 html + */ + private String contentHtml; + + /** + * 附件 + * 多个英文逗号分隔 + */ + private String attachment; + + /** + * 页面浏览量 + */ + private Integer pageViewCount; + + /** + * 用户浏览量 + */ + private Integer userViewCount; + + /** + * 来源 + */ + private String source; + + /** + * 作者 + */ + private String author; + + /** + * 文号 + */ + private String documentNumber; + + /** + * 流程实例的id + */ + private Long instanceId; + + /** + * 流程节点名称 + */ + private String nodeName; + + /** + * 流程状态 + */ + private String flowStatus; + + private Boolean deletedFlag; + + private Long createUserId; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeTypeEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeTypeEntity.java new file mode 100644 index 0000000..6d8739b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/entity/NoticeTypeEntity.java @@ -0,0 +1,38 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * 通知公告类型 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +@TableName("t_notice_type") +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class NoticeTypeEntity { + + @TableId(type = IdType.AUTO) + private Long noticeTypeId; + + /** + * 名称 + */ + private String noticeTypeName; + + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeAddForm.java new file mode 100644 index 0000000..8c5e10e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeAddForm.java @@ -0,0 +1,75 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.form; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 通知公告 添加表单 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeAddForm { + + @Schema(description = "标题") + @NotBlank(message = "标题不能为空") + @Length(max = 200, message = "标题最多200字符") + private String title; + + @Schema(description = "分类") + @NotNull(message = "分类不能为空") + private Long noticeTypeId; + + @Schema(description = "是否全部可见") + @NotNull(message = "是否全部可见不能为空") + private Boolean allVisibleFlag; + + @Schema(description = "是否定时发布") + @NotNull(message = "是否定时发布不能为空") + private Boolean scheduledPublishFlag; + + @Schema(description = "发布时间") + @NotNull(message = "发布时间不能为空") + private LocalDateTime publishTime; + + @Schema(description = "纯文本内容") + @NotNull(message = "文本内容不能为空") + private String contentText; + + @Schema(description = "html内容") + @NotNull(message = "html内容不能为空") + private String contentHtml; + + @Schema(description = "附件,多个英文逗号分隔|可选") + @Length(max = 1000, message = "最多1000字符") + @JsonDeserialize(using = FileKeyVoDeserializer.class) + private String attachment; + + @Schema(description = "作者") + @NotBlank(message = "作者不能为空") + private String author; + + @Schema(description = "来源") + @NotBlank(message = "标题不能为空") + private String source; + + @Schema(description = "文号") + private String documentNumber; + + @Schema(hidden = true) + private Long createUserId; + + @Schema(description = "可见范围设置|可选") + @Valid + private List visibleRangeList; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeEmployeeQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeEmployeeQueryForm.java new file mode 100644 index 0000000..8a2d6bd --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeEmployeeQueryForm.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +import java.time.LocalDate; + +/** + * 通知公告 员工查询表单 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeEmployeeQueryForm extends PageParam { + + @Schema(description = "标题、作者、来源、文号") + private String keywords; + + @Schema(description = "分类") + private Long noticeTypeId; + + @Schema(description = "发布-开始时间") + private LocalDate publishTimeBegin; + + @Schema(description = "未读标识") + private Boolean notViewFlag; + + @Schema(description = "发布-截止时间") + private LocalDate publishTimeEnd; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeQueryForm.java new file mode 100644 index 0000000..6be167f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeQueryForm.java @@ -0,0 +1,57 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +import java.time.LocalDate; + +/** + * 通知公告 管理查询表单 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeQueryForm extends PageParam { + + @Schema(description = "分类") + private Long noticeTypeId; + + @Schema(description = "标题、作者、来源") + private String keywords; + + @Schema(description = "文号") + private String documentNumber; + + @Schema(description = "创建人") + private String createUserName; + + /** + * 流程节点名称 + */ + @Schema(description = "流程节点") + private String nodeName; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + @Schema(description = "删除标识") + private Boolean deletedFlag; + + @Schema(description = "创建-开始时间") + private LocalDate createTimeBegin; + + @Schema(description = "创建-截止时间") + private LocalDate createTimeEnd; + + @Schema(description = "发布-开始时间") + private LocalDate publishTimeBegin; + + @Schema(description = "发布-截止时间") + private LocalDate publishTimeEnd; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeUpdateForm.java new file mode 100644 index 0000000..a84ba4a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeUpdateForm.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 通知公告 更新表单 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeUpdateForm extends NoticeAddForm { + + @Schema(description = "id") + @NotNull(message = "通知id不能为空") + private Long noticeId; + /** + * 流程实例的id + */ + @Schema(description = "流程实例的id") + private Long instanceId; + + /** + * 流程节点名称 + */ + @Schema(description = "流程节点") + private String nodeName; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeViewRecordQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeViewRecordQueryForm.java new file mode 100644 index 0000000..c83e837 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeViewRecordQueryForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +/** + * 通知公告 阅读记录查询 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeViewRecordQueryForm extends PageParam { + + @Schema(description = "通知公告id") + @NotNull(message = "通知公告id不能为空") + private Long noticeId; + + @Schema(description = "部门id") + private Long departmentId; + + @Schema(description = "关键字") + private String keywords; + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeVisibleRangeForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeVisibleRangeForm.java new file mode 100644 index 0000000..696da75 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/form/NoticeVisibleRangeForm.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; + +/** + * 通知公告 可见范围数据 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class NoticeVisibleRangeForm { + + @SchemaEnum(NoticeVisibleRangeDataTypeEnum.class) + @CheckEnum(value = NoticeVisibleRangeDataTypeEnum.class, required = true, message = "数据类型错误") + private Integer dataType; + + @Schema(description = "员工/部门id") + @NotNull(message = "员工/部门id不能为空") + private Long dataId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeDetailVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeDetailVO.java new file mode 100644 index 0000000..b835871 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeDetailVO.java @@ -0,0 +1,81 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer; + +import java.time.LocalDateTime; + +/** + * 通知公告 详情 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeDetailVO { + + @Schema(description = "id") + private Long noticeId; + + @Schema(description = "标题") + private String title; + + @Schema(description = "分类") + private Long noticeTypeId; + + @Schema(description = "分类名称") + private Long noticeTypeName; + + @Schema(description = "是否全部可见") + @NotNull(message = "是否全部可见不能为空") + private Boolean allVisibleFlag; + + @Schema(description = "是否定时发布") + @NotNull(message = "是否定时发布不能为空") + private Boolean scheduledPublishFlag; + + @Schema(description = "纯文本内容") + private String contentText; + + @Schema(description = "html内容") + private String contentHtml; + + @Schema(description = "附件") + @JsonSerialize(using = FileKeyVoSerializer.class) + private String attachment; + + @Schema(description = "发布时间") + @NotNull(message = "发布时间不能为空") + private LocalDateTime publishTime; + + @Schema(description = "作者") + @NotBlank(message = "作者不能为空") + private String author; + + @Schema(description = "来源") + @NotBlank(message = "标题不能为空") + private String source; + + @Schema(description = "文号") + private String documentNumber; + + @Schema(description = "页面浏览量") + private Integer pageViewCount; + + @Schema(description = "用户浏览量") + private Integer userViewCount; + + @Schema(description = "创建人名称") + private Long createUserName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeEmployeeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeEmployeeVO.java new file mode 100644 index 0000000..987d82e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeEmployeeVO.java @@ -0,0 +1,23 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; + +/** + * 通知公告 员工查看 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeEmployeeVO extends NoticeVO { + + @Schema(description = "是否查看") + private Boolean viewFlag; + + @Schema(description = "发布日期") + private LocalDate publishDate; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeTypeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeTypeVO.java new file mode 100644 index 0000000..d9201ba --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeTypeVO.java @@ -0,0 +1,21 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 通知公告 类型 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeTypeVO { + + @Schema(description = "通知类型id") + private Long noticeTypeId; + + @Schema(description = "通知类型-名称") + private String noticeTypeName; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeUpdateFormVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeUpdateFormVO.java new file mode 100644 index 0000000..436d810 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeUpdateFormVO.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer; + +import java.util.List; + +/** + * 用于更新 【通知、公告】 的 VO 对象 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeUpdateFormVO extends NoticeVO { + + @Schema(description = "纯文本内容") + private String contentText; + + @Schema(description = "html内容") + private String contentHtml; + + @Schema(description = "附件") + @JsonSerialize(using = FileKeyVoSerializer.class) + private String attachment; + + @Schema(description = "可见范围") + private List visibleRangeList; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVO.java new file mode 100644 index 0000000..9320f5a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVO.java @@ -0,0 +1,87 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + + +/** + * 新闻、公告 VO + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeVO { + + @Schema(description = "id") + private Long noticeId; + + @Schema(description = "标题") + private String title; + + @Schema(description = "分类") + private Long noticeTypeId; + + @Schema(description = "分类名称") + private String noticeTypeName; + + @Schema(description = "是否全部可见") + private Boolean allVisibleFlag; + + @Schema(description = "是否定时发布") + private Boolean scheduledPublishFlag; + + @Schema(description = "发布状态") + private Boolean publishFlag; + + @Schema(description = "发布时间") + private LocalDateTime publishTime; + + @Schema(description = "作者") + private String author; + + @Schema(description = "来源") + private String source; + + @Schema(description = "文号") + private String documentNumber; + + @Schema(description = "页面浏览量") + private Integer pageViewCount; + + @Schema(description = "用户浏览量") + private Integer userViewCount; + + @Schema(description = "删除标识") + private Boolean deletedFlag; + + /** + * 流程实例的id + */ + @Schema(description = "流程实例的id") + private Long instanceId; + + /** + * 流程节点名称 + */ + @Schema(description = "流程节点") + private String nodeName; + + /** + * 流程状态 + */ + @Schema(description = "流程状态") + private String flowStatus; + + @Schema(description = "创建人名称") + private String createUserName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeViewRecordVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeViewRecordVO.java new file mode 100644 index 0000000..bff065f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeViewRecordVO.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 浏览记录 VO + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeViewRecordVO { + + @Schema(description = "员工ID") + private Long employeeId; + + @Schema(description = "员工姓名") + private String employeeName; + + @Schema(description = "员工部门名称") + private String departmentName; + + @Schema(description = "查看次数") + private Integer pageViewCount; + + @Schema(description = "首次ip") + private String firstIp; + + @Schema(description = "首次用户设备等标识") + private String firstUserAgent; + + @Schema(description = "首次查看时间") + private LocalDateTime createTime; + + @Schema(description = "最后一次 ip") + private String lastIp; + + @Schema(description = "最后一次 用户设备等标识") + private String lastUserAgent; + + @Schema(description = "最后一次查看时间") + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVisibleRangeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVisibleRangeVO.java new file mode 100644 index 0000000..5d29407 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/domain/vo/NoticeVisibleRangeVO.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.admin.module.business.oa.notice.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +/** + * 新闻、公告 可见范围数据 VO + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Data +public class NoticeVisibleRangeVO { + + @SchemaEnum(NoticeVisibleRangeDataTypeEnum.class) + private Integer dataType; + + @Schema(description = "员工/部门id") + private Long dataId; + + @Schema(description = "员工/部门 名称") + private String dataName; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/manager/NoticeManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/manager/NoticeManager.java new file mode 100644 index 0000000..379106f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/manager/NoticeManager.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.admin.module.business.oa.notice.manager; + +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao; +import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 通知、公告 manager + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Service +public class NoticeManager { + + @Resource + private NoticeDao noticeDao; + + @Resource + private DataTracerService dataTracerService; + + /** + * 保存 + */ + @Transactional(rollbackFor = Throwable.class) + public void save(NoticeEntity noticeEntity, List visibleRangeFormList) { + noticeDao.insert(noticeEntity); + Long noticeId = noticeEntity.getNoticeId(); + // 保存可见范围 + if (CollectionUtils.isNotEmpty(visibleRangeFormList)) { + noticeDao.insertVisibleRange(noticeId, visibleRangeFormList); + } + dataTracerService.insert(noticeId, DataTracerTypeEnum.OA_NOTICE); + } + + /** + * 更新 + * + */ + @Transactional(rollbackFor = Throwable.class) + public void update(NoticeEntity old, NoticeEntity noticeEntity, List visibleRangeList) { + noticeDao.updateById(noticeEntity); + Long noticeId = noticeEntity.getNoticeId(); + // 保存可见范围 + if (CollectionUtils.isNotEmpty(visibleRangeList)) { + noticeDao.deleteVisibleRange(noticeId); + noticeDao.insertVisibleRange(noticeId, visibleRangeList); + } + dataTracerService.update(noticeId, DataTracerTypeEnum.OA_NOTICE, old, noticeEntity); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeEmployeeService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeEmployeeService.java new file mode 100644 index 0000000..57cde02 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeEmployeeService.java @@ -0,0 +1,152 @@ +package net.lab1024.sa.admin.module.business.oa.notice.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum; +import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeEmployeeQueryForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeViewRecordQueryForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.*; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + + +/** + * 员工查看 通知。公告 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Service +public class NoticeEmployeeService { + + @Resource + private NoticeDao noticeDao; + + @Resource + private NoticeService noticeService; + + @Resource + private DepartmentService departmentService; + + @Resource + private EmployeeService employeeService; + + /** + * 查询我的 通知、公告清单 + */ + public ResponseDTO> queryList(Long requestEmployeeId, NoticeEmployeeQueryForm noticeEmployeeQueryForm) { + Page page = SmartPageUtil.convert2PageQuery(noticeEmployeeQueryForm); + + List employeeDepartmentIdList = Lists.newArrayList(); + EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId); + // 如果不是管理员 则获取请求人的 部门及其子部门 + if (!employeeEntity.getAdministratorFlag() && employeeEntity.getDepartmentId() != null) { + employeeDepartmentIdList = departmentService.selfAndChildrenIdList(employeeEntity.getDepartmentId()); + } + + List noticeList = null; + //只查询未读的 + if (noticeEmployeeQueryForm.getNotViewFlag() != null && noticeEmployeeQueryForm.getNotViewFlag()) { + noticeList = noticeDao.queryEmployeeNotViewNotice(page, + requestEmployeeId, + noticeEmployeeQueryForm, + employeeDepartmentIdList, + false, + employeeEntity.getAdministratorFlag(), + NoticeVisibleRangeDataTypeEnum.DEPARTMENT.getValue(), + NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue()); + } else { + // 查询全部 + noticeList = noticeDao.queryEmployeeNotice(page, + requestEmployeeId, + noticeEmployeeQueryForm, + employeeDepartmentIdList, + false, + employeeEntity.getAdministratorFlag(), + NoticeVisibleRangeDataTypeEnum.DEPARTMENT.getValue(), + NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue()); + } + // 设置发布日期 + noticeList.forEach(notice -> notice.setPublishDate(notice.getPublishTime().toLocalDate())); + + return ResponseDTO.ok(SmartPageUtil.convert2PageResult(page, noticeList)); + } + + + /** + * 查询我的 待查看的 通知、公告清单 + */ + public ResponseDTO view(Long requestEmployeeId, Long noticeId, String ip, String userAgent) { + NoticeUpdateFormVO updateFormVO = noticeService.getUpdateFormVO(noticeId); + if (updateFormVO == null || Boolean.TRUE.equals(updateFormVO.getDeletedFlag())) { + return ResponseDTO.userErrorParam("通知公告不存在"); + } + + EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId); + if (!updateFormVO.getAllVisibleFlag() && !checkVisibleRange(updateFormVO.getVisibleRangeList(), requestEmployeeId, employeeEntity.getDepartmentId())) { + return ResponseDTO.userErrorParam("对不起,您没有权限查看内容"); + } + + NoticeDetailVO noticeDetailVO = SmartBeanUtil.copy(updateFormVO, NoticeDetailVO.class); + long viewCount = noticeDao.viewRecordCount(noticeId, requestEmployeeId); + if (viewCount == 0) { + noticeDao.insertViewRecord(noticeId, requestEmployeeId, ip, userAgent, 1); + // 该员工对于这个通知是第一次查看 页面浏览量+1 用户浏览量+1 + noticeDao.updateViewCount(noticeId, 1, 1); + noticeDetailVO.setPageViewCount(noticeDetailVO.getPageViewCount() + 1); + noticeDetailVO.setUserViewCount(noticeDetailVO.getUserViewCount() + 1); + } else { + noticeDao.updateViewRecord(noticeId, requestEmployeeId, ip, userAgent); + // 该员工对于这个通知不是第一次查看 页面浏览量+1 用户浏览量+0 + noticeDao.updateViewCount(noticeId, 1, 0); + noticeDetailVO.setPageViewCount(noticeDetailVO.getPageViewCount() + 1); + } + + return ResponseDTO.ok(noticeDetailVO); + } + + /** + * 校验是否有查看权限的范围 + * + */ + public boolean checkVisibleRange(List visibleRangeList, Long employeeId, Long departmentId) { + // 员工范围 + boolean anyMatch = visibleRangeList.stream().anyMatch(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.equalsValue(e.getDataType()) && Objects.equals(e.getDataId(), employeeId)); + if (anyMatch) { + return true; + } + + //部门范围 + List visibleDepartmentIdList = visibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType())) + .map(NoticeVisibleRangeVO::getDataId).collect(Collectors.toList()); + + for (Long visibleDepartmentId : visibleDepartmentIdList) { + List departmentIdList = departmentService.selfAndChildrenIdList(visibleDepartmentId); + if (departmentIdList.contains(departmentId)) { + return true; + } + } + return false; + } + + /** + * 分页查询 查看记录 + */ + public PageResult queryViewRecord(NoticeViewRecordQueryForm noticeViewRecordQueryForm) { + Page page = SmartPageUtil.convert2PageQuery(noticeViewRecordQueryForm); + List noticeViewRecordList = noticeDao.queryNoticeViewRecordList(page, noticeViewRecordQueryForm); + return SmartPageUtil.convert2PageResult(page, noticeViewRecordList); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeService.java new file mode 100644 index 0000000..27e486b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeService.java @@ -0,0 +1,237 @@ +package net.lab1024.sa.admin.module.business.oa.notice.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Maps; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.business.oa.notice.constant.NoticeVisibleRangeDataTypeEnum; +import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeDao; +import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeEntity; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeAddForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeQueryForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeUpdateForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.form.NoticeVisibleRangeForm; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeTypeVO; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeUpdateFormVO; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVO; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeVisibleRangeVO; +import net.lab1024.sa.admin.module.business.oa.notice.manager.NoticeManager; +import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao; +import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 通知。公告 后台管理业务 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Service +public class NoticeService { + + @Resource + private NoticeDao noticeDao; + + @Resource + private NoticeManager noticeManager; + + @Resource + private EmployeeDao employeeDao; + + @Resource + private DepartmentDao departmentDao; + + @Resource + private DepartmentService departmentService; + + @Resource + private NoticeTypeService noticeTypeService; + + @Resource + private DataTracerService dataTracerService; + + /** + * 查询 通知、公告 + * + */ + public PageResult query(NoticeQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = noticeDao.query(page, queryForm); + LocalDateTime now = LocalDateTime.now(); + list.forEach(e -> e.setPublishFlag(e.getPublishTime().isBefore(now))); + return SmartPageUtil.convert2PageResult(page, list); + } + + /** + * 添加 + */ + public ResponseDTO add(NoticeAddForm addForm) { + // 校验并获取可见范围 + ResponseDTO validate = this.checkAndBuildVisibleRange(addForm); + if (!validate.getOk()) { + return ResponseDTO.error(validate); + } + + // build 资讯 + NoticeEntity noticeEntity = SmartBeanUtil.copy(addForm, NoticeEntity.class); + // 发布时间:不是定时发布时 默认为 当前 + if (!addForm.getScheduledPublishFlag()) { + noticeEntity.setPublishTime(LocalDateTime.now()); + } + // 保存数据 + noticeManager.save(noticeEntity, addForm.getVisibleRangeList()); + return ResponseDTO.ok(); + } + + /** + * 校验并返回可见范围 + * + */ + private ResponseDTO checkAndBuildVisibleRange(NoticeAddForm form) { + // 校验资讯分类 + NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(form.getNoticeTypeId()); + if (noticeType == null) { + return ResponseDTO.userErrorParam("分类不存在"); + } + + if (form.getAllVisibleFlag()) { + return ResponseDTO.ok(); + } + + /* + * 校验可见范围 + * 非全部可见时 校验选择的员工|部门 + */ + List visibleRangeUpdateList = form.getVisibleRangeList(); + if (CollectionUtils.isEmpty(visibleRangeUpdateList)) { + return ResponseDTO.userErrorParam("未设置可见范围"); + } + + // 校验可见范围-> 员工 + List employeeIdList = visibleRangeUpdateList.stream() + .filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.equalsValue(e.getDataType())) + .map(NoticeVisibleRangeForm::getDataId) + .distinct().collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(employeeIdList)) { + employeeIdList = employeeIdList.stream().distinct().collect(Collectors.toList()); + List dbEmployeeIdList = employeeDao.selectBatchIds(employeeIdList).stream().map(EmployeeEntity::getEmployeeId).collect(Collectors.toList()); + Collection subtract = CollectionUtils.subtract(employeeIdList, dbEmployeeIdList); + if (!subtract.isEmpty()) { + return ResponseDTO.userErrorParam("员工id不存在:" + subtract); + } + } + + // 校验可见范围-> 部门 + List deptIdList = visibleRangeUpdateList.stream() + .filter(e -> NoticeVisibleRangeDataTypeEnum.DEPARTMENT.equalsValue(e.getDataType())) + .map(NoticeVisibleRangeForm::getDataId) + .distinct().collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(deptIdList)) { + deptIdList = deptIdList.stream().distinct().collect(Collectors.toList()); + List dbDeptIdList = departmentDao.selectBatchIds(deptIdList).stream().map(DepartmentEntity::getDepartmentId).collect(Collectors.toList()); + Collection subtract = CollectionUtils.subtract(deptIdList, dbDeptIdList); + if (!subtract.isEmpty()) { + return ResponseDTO.userErrorParam("部门id不存在:" + subtract); + } + } + return ResponseDTO.ok(); + } + + + /** + * 更新 + * + */ + public ResponseDTO update(NoticeUpdateForm updateForm) { + + NoticeEntity oldNoticeEntity = noticeDao.selectById(updateForm.getNoticeId()); + if (oldNoticeEntity == null) { + return ResponseDTO.userErrorParam("通知不存在"); + } + + // 校验并获取可见范围 + ResponseDTO res = this.checkAndBuildVisibleRange(updateForm); + if (!res.getOk()) { + return ResponseDTO.error(res); + } + + // 更新 + NoticeEntity noticeEntity = SmartBeanUtil.copy(updateForm, NoticeEntity.class); + noticeManager.update(oldNoticeEntity, noticeEntity, updateForm.getVisibleRangeList()); + return ResponseDTO.ok(); + } + + + /** + * 删除 + * + */ + public ResponseDTO delete(Long noticeId) { + NoticeEntity noticeEntity = noticeDao.selectById(noticeId); + if (null == noticeEntity || noticeEntity.getDeletedFlag()) { + return ResponseDTO.userErrorParam("通知公告不存在"); + } + // 更新删除状态 + noticeDao.updateDeletedFlag(noticeId); + dataTracerService.delete(noticeId, DataTracerTypeEnum.OA_NOTICE); + return ResponseDTO.ok(); + } + + /** + * 获取更新表单用的详情 + */ + public NoticeUpdateFormVO getUpdateFormVO(Long noticeId) { + NoticeEntity noticeEntity = noticeDao.selectById(noticeId); + if (null == noticeEntity) { + return null; + } + + NoticeUpdateFormVO updateFormVO = SmartBeanUtil.copy(noticeEntity, NoticeUpdateFormVO.class); + NoticeTypeVO noticeType = noticeTypeService.getByNoticeTypeId(noticeEntity.getNoticeTypeId()); + updateFormVO.setNoticeTypeName(noticeType.getNoticeTypeName()); + updateFormVO.setPublishFlag(updateFormVO.getPublishTime() != null && updateFormVO.getPublishTime().isBefore(LocalDateTime.now())); + + if (!updateFormVO.getAllVisibleFlag()) { + List noticeVisibleRangeList = noticeDao.queryVisibleRange(noticeId); + List employeeIdList = noticeVisibleRangeList.stream().filter(e -> NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue().equals(e.getDataType())) + .map(NoticeVisibleRangeVO::getDataId) + .collect(Collectors.toList()); + + Map employeeMap = null; + if (CollectionUtils.isNotEmpty(employeeIdList)) { + employeeMap = employeeDao.selectBatchIds(employeeIdList).stream().collect(Collectors.toMap(EmployeeEntity::getEmployeeId, Function.identity())); + } else { + employeeMap = Maps.newHashMap(); + } + for (NoticeVisibleRangeVO noticeVisibleRange : noticeVisibleRangeList) { + if (noticeVisibleRange.getDataType().equals(NoticeVisibleRangeDataTypeEnum.EMPLOYEE.getValue())) { + EmployeeEntity employeeEntity = employeeMap.get(noticeVisibleRange.getDataId()); + noticeVisibleRange.setDataName(employeeEntity == null ? StringConst.EMPTY : employeeEntity.getActualName()); + } else { + DepartmentVO departmentVO = departmentService.getDepartmentById(noticeVisibleRange.getDataId()); + noticeVisibleRange.setDataName(departmentVO == null ? StringConst.EMPTY : departmentVO.getName()); + } + } + updateFormVO.setVisibleRangeList(noticeVisibleRangeList); + } + return updateFormVO; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeTypeService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeTypeService.java new file mode 100644 index 0000000..6d65c66 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/business/oa/notice/service/NoticeTypeService.java @@ -0,0 +1,84 @@ +package net.lab1024.sa.admin.module.business.oa.notice.service; + +import cn.hutool.core.util.StrUtil; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.business.oa.notice.dao.NoticeTypeDao; +import net.lab1024.sa.admin.module.business.oa.notice.domain.entity.NoticeTypeEntity; +import net.lab1024.sa.admin.module.business.oa.notice.domain.vo.NoticeTypeVO; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +/** + * 通知。公告 类型 + * + * @Date 2022-08-12 21:40:39 + * @Author wzh + */ +@Service +public class NoticeTypeService { + + @Resource + private NoticeTypeDao noticeTypeDao; + + /** + * 查询全部 + * @return + */ + public List getAll() { + return SmartBeanUtil.copyList(noticeTypeDao.selectList(null), NoticeTypeVO.class); + } + + public NoticeTypeVO getByNoticeTypeId(Long noticceTypeId) { + return SmartBeanUtil.copy(noticeTypeDao.selectById(noticceTypeId), NoticeTypeVO.class); + } + + public synchronized ResponseDTO add(String name) { + if (StrUtil.isBlank(name)) { + return ResponseDTO.userErrorParam("类型名称不能为空"); + } + + List noticeTypeEntityList = noticeTypeDao.selectList(null); + if (!CollectionUtils.isEmpty(noticeTypeEntityList)) { + boolean exist = noticeTypeEntityList.stream().map(NoticeTypeEntity::getNoticeTypeName).collect(Collectors.toSet()).contains(name); + if (exist) { + return ResponseDTO.userErrorParam("类型名称已经存在"); + } + } + noticeTypeDao.insert(NoticeTypeEntity.builder().noticeTypeName(name).build()); + return ResponseDTO.ok(); + } + + public synchronized ResponseDTO update(Long noticeTypeId, String name) { + if (StrUtil.isBlank(name)) { + return ResponseDTO.userErrorParam("类型名称不能为空"); + } + + NoticeTypeEntity noticeTypeEntity = noticeTypeDao.selectById(noticeTypeId); + if (noticeTypeEntity == null) { + return ResponseDTO.userErrorParam("类型名称不存在"); + } + + List noticeTypeEntityList = noticeTypeDao.selectList(null); + if (!CollectionUtils.isEmpty(noticeTypeEntityList)) { + Optional optionalNoticeTypeEntity = noticeTypeEntityList.stream().filter(e -> e.getNoticeTypeName().equals(name)).findFirst(); + if (optionalNoticeTypeEntity.isPresent() && !optionalNoticeTypeEntity.get().getNoticeTypeId().equals(noticeTypeId)) { + return ResponseDTO.userErrorParam("类型名称已经存在"); + } + } + noticeTypeEntity.setNoticeTypeName(name); + noticeTypeDao.updateById(noticeTypeEntity); + return ResponseDTO.ok(); + } + + public synchronized ResponseDTO delete(Long noticeTypeId) { + noticeTypeDao.deleteById(noticeTypeId); + return ResponseDTO.ok(); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/AbstractWarmFlowAdapter.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/AbstractWarmFlowAdapter.java new file mode 100644 index 0000000..402e169 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/AbstractWarmFlowAdapter.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.flow.adapter; + +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleSelectedVO; +import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.core.utils.StreamUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +@Service +public abstract class AbstractWarmFlowAdapter { + @Resource + protected TaskService taskService; + + @Resource + private RoleEmployeeService roleEmployeeService; + + /** + * 获取权限 + * + * @return 权限列表 + */ + protected List permissionList(EmployeeEntity employee, String userId) { + List roles = roleEmployeeService.getRoleInfoListByEmployeeId(employee.getEmployeeId()); + List permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId()); + permissionList.add(userId); + permissionList.add("dept:" + employee.getEmployeeId()); + return permissionList; + } + + /** + * 根据类型获取描述 + * + * @param type 流程类型 + * @return value + */ + protected String type(Integer type) { + return CooperateType.getValueByKey(type); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/AddSignatureAdapter.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/AddSignatureAdapter.java new file mode 100644 index 0000000..7199ba6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/AddSignatureAdapter.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.flow.adapter; + +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 加签适配器 + */ +@Component +public class AddSignatureAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.ADD_SIGNATURE.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVO obj) { + Long taskId = obj.getTaskId(); + String userId = String.valueOf(SmartRequestUtil.getRequestUserId()); + EmployeeEntity employee = new EmployeeEntity(); + employee.setEmployeeId(Long.parseLong(userId)); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(employee, userId)) + .addHandlers(obj.getAddHandlers()) + .message(this.type(obj.getOperatorType())); + + return super.taskService.addSignature(taskId, flowParams); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/DeputeAdapter.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/DeputeAdapter.java new file mode 100644 index 0000000..ab77b01 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/DeputeAdapter.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.flow.adapter; + +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 委派适配器 + */ +@Component +public class DeputeAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.DEPUTE.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVO obj) { + Long taskId = obj.getTaskId(); + String userId = String.valueOf(SmartRequestUtil.getRequestUserId()); + EmployeeEntity employee = new EmployeeEntity(); + employee.setEmployeeId(Long.parseLong(userId)); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(employee, userId)) + .addHandlers(obj.getAddHandlers()) + .message(this.type(obj.getOperatorType())); + + return super.taskService.depute(taskId, flowParams); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/ReductionSignatureAdapter.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/ReductionSignatureAdapter.java new file mode 100644 index 0000000..0494a2f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/ReductionSignatureAdapter.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.flow.adapter; + +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 减签适配器 + */ +@Component +public class ReductionSignatureAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVO obj) { + Long taskId = obj.getTaskId(); + String userId = String.valueOf(SmartRequestUtil.getRequestUserId()); + EmployeeEntity employee = new EmployeeEntity(); + employee.setEmployeeId(Long.parseLong(userId)); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(employee, userId)) + .reductionHandlers(obj.getAddHandlers()) + .message(type(obj.getOperatorType())); + + return super.taskService.reductionSignature(taskId, flowParams); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/TransferAdapter.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/TransferAdapter.java new file mode 100644 index 0000000..8c2de24 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/TransferAdapter.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.flow.adapter; + +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * 转办适配器 + */ +@Component +public class TransferAdapter extends AbstractWarmFlowAdapter implements WarmFlowAdapter { + @Override + public boolean isAdapter(Integer warmFlowType) { + return Objects.equals(CooperateType.TRANSFER.getKey(), warmFlowType); + } + + @Override + public boolean adapter(WarmFlowInteractiveTypeVO obj) { + Long taskId = obj.getTaskId(); + String userId = String.valueOf(SmartRequestUtil.getRequestUserId()); + EmployeeEntity employee = new EmployeeEntity(); + employee.setEmployeeId(Long.parseLong(userId)); + FlowParams flowParams = new FlowParams() + .handler(userId) + .permissionFlag(permissionList(employee, userId)) + .addHandlers(obj.getAddHandlers()) + .message(this.type(obj.getOperatorType())); + + return super.taskService.transfer(taskId, flowParams); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/WarmFlowAdapter.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/WarmFlowAdapter.java new file mode 100644 index 0000000..96502cc --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/adapter/WarmFlowAdapter.java @@ -0,0 +1,9 @@ +package net.lab1024.sa.admin.module.flow.adapter; + +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; + +public interface WarmFlowAdapter { + boolean isAdapter(Integer warmFlowType); + + boolean adapter(WarmFlowInteractiveTypeVO obj); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/annoation/ConditionalOnEnable.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/annoation/ConditionalOnEnable.java new file mode 100644 index 0000000..015b8be --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/annoation/ConditionalOnEnable.java @@ -0,0 +1,14 @@ +package net.lab1024.sa.admin.module.flow.annoation; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target({ ElementType.TYPE, ElementType.METHOD }) +@ConditionalOnProperty(value = "warm-flow.enabled", havingValue = "true") +public @interface ConditionalOnEnable { +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/controller/DefController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/controller/DefController.java new file mode 100644 index 0000000..6768174 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/controller/DefController.java @@ -0,0 +1,211 @@ +package net.lab1024.sa.admin.module.flow.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.flow.domain.form.FlowDefinitionQueryForm; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowDefinitionVO; +import net.lab1024.sa.admin.module.flow.service.FlowDefinitionService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartResponseUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.service.ChartService; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.MediaTypeFactory; +import org.springframework.http.ResponseEntity; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.util.List; + +/** + * 流程定义Controller + * + * @author hh + * @date 2023-04-11 + */ +@Validated +@RestController +@Tag(name = AdminSwaggerTagConst.Flow.FLOW_DEFINITION) +@RequestMapping("/flow/definition") +public class DefController { + @Resource + private FlowDefinitionService flowDefinitionService; + + @Resource + private DefService defService; + + @Resource + private ChartService chartService; + + /** + * 分页查询流程定义列表 + */ + @Operation(summary = "分页查询") + @PostMapping("/queryPage") + public ResponseDTO> queryPage(@RequestBody @Valid FlowDefinitionQueryForm queryForm) { + return ResponseDTO.ok(flowDefinitionService.queryPage(queryForm)); + } + + /** + * 获取流程定义详细信息 + */ + @Operation(summary = "获取流程定义详细信息") + @SaCheckPermission("flow:definition:query") + @GetMapping(value = "/{id}") + public ResponseDTO getInfo(@PathVariable("id") Long id) { + return ResponseDTO.ok(defService.getById(id)); + } + + /** + * 新增流程定义 + */ + @Operation(summary = "添加") + @SaCheckPermission("flow:definition:add") + @PostMapping("/add") + @Transactional(rollbackFor = Exception.class) + public ResponseDTO add(@RequestBody FlowDefinition flowDefinition) { + return ResponseDTO.ok(defService.saveAndInitNode(flowDefinition)); + } + + /** + * 发布流程定义 + */ + @Operation(summary = "发布流程定义") + @SaCheckPermission("flow:definition:publish") + @GetMapping("/publish/{id}") + @Transactional(rollbackFor = Exception.class) + public ResponseDTO publish(@PathVariable("id") Long id) { + return ResponseDTO.ok(defService.publish(id)); + } + + /** + * 取消发布流程定义 + */ + @Operation(summary = "取消发布流程定义") + @SaCheckPermission("flow:definition:publish") + @GetMapping("/unPublish/{id}") + @Transactional(rollbackFor = Exception.class) + public ResponseDTO unPublish(@PathVariable("id") Long id) { + defService.unPublish(id); + return ResponseDTO.ok(); + } + + /** + * 修改流程定义 + */ + @Operation(summary = "更新") + @SaCheckPermission("flow:definition:edit") + @PostMapping("/update") + @Transactional(rollbackFor = Exception.class) + public ResponseDTO edit(@RequestBody FlowDefinition flowDefinition) { + return ResponseDTO.ok(defService.updateById(flowDefinition)); + } + + /** + * 删除流程定义 + */ + @Operation(summary = "删除") + @SaCheckPermission("flow:definition:remove") + @GetMapping("/delete/{ids}") + @Transactional(rollbackFor = Exception.class) + public ResponseDTO remove(@PathVariable List ids) { + return ResponseDTO.ok(defService.removeDef(ids)); + } + + /** + * 复制流程定义 + */ + @Operation(summary = "复制流程定义") + @SaCheckPermission("flow:definition:publish") + @GetMapping("/copyDef/{id}") + @Transactional(rollbackFor = Exception.class) + public ResponseDTO copyDef(@PathVariable("id") Long id) { + return ResponseDTO.ok(defService.copyDef(id)); + } + + @Operation(summary = "流程定义导入") + @SaCheckPermission("flow:definition:importDefinition") + @PostMapping("/importDefinition") + @Transactional(rollbackFor = Exception.class) + public ResponseDTO importDefinition(MultipartFile file) throws Exception { + defService.importIs(file.getInputStream()); + return ResponseDTO.ok(); + } + + @Operation(summary = "流程定义导出") + @SaCheckPermission("flow:definition:exportDefinition") + @PostMapping("/exportDefinition/{id}") + public void exportDefinition(@PathVariable("id") Long id, HttpServletResponse response) throws IOException { + // 要导出的字符串 + String content = defService.exportJson(id); + + if (SmartStringUtil.isNotEmpty(content)) { + SmartResponseUtil.setDownloadFileHeader(response, "flowDefinition" + id + ".json", (long) content.getBytes().length); + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM + ";charset=utf-8"); + response.getOutputStream().write(content.getBytes()); + } + } + + /** + * 查询流程图 + * + * @param definitionId + * + * @return + */ + @Operation(summary = "查询流程图") + @GetMapping("/chartDef/{definitionId}") + public ResponseDTO chartDef(@PathVariable("definitionId") Long definitionId) { + return ResponseDTO.ok(chartService.chartDef(definitionId)); + } + + /** + * 查询流程图 + * + * @param instanceId + * @return + */ + @Operation(summary = "查询流程图") + @GetMapping("/flowChart/{instanceId}") + public ResponseDTO flowChart(@PathVariable("instanceId") Long instanceId) throws IOException { + return ResponseDTO.ok(chartService.chartIns(instanceId)); + } + + /** + * 激活流程 + * + * @param definitionId + * @return + */ + @Operation(summary = "激活流程") + @GetMapping("/active/{definitionId}") + public ResponseDTO active(@PathVariable("definitionId") Long definitionId) { + return ResponseDTO.ok(defService.active(definitionId)); + } + + /** + * 挂起流程 + * + * @param definitionId + * @return + */ + @Operation(summary = "挂起流程") + @GetMapping("/unActive/{definitionId}") + public ResponseDTO unActive(@PathVariable("definitionId") Long definitionId) { + return ResponseDTO.ok(defService.unActive(definitionId)); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/controller/ExecuteController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/controller/ExecuteController.java new file mode 100644 index 0000000..3e840ea --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/controller/ExecuteController.java @@ -0,0 +1,491 @@ +package net.lab1024.sa.admin.module.flow.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.flow.domain.form.ApproveTaskInsForm; +import net.lab1024.sa.admin.module.flow.domain.form.CompleteTaskForm; +import net.lab1024.sa.admin.module.flow.domain.form.StartProcessForm; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowTaskVO; +import net.lab1024.sa.admin.module.flow.domain.vo.StartProcessReturnVO; +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.admin.module.flow.service.FlowTaskService; +import net.lab1024.sa.admin.module.flow.service.HhDefService; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleSelectedVO; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; +import net.lab1024.sa.admin.module.system.role.service.RoleService; +import net.lab1024.sa.base.common.code.UnexpectedErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.dromara.warm.flow.core.FlowEngine; +import org.dromara.warm.flow.core.entity.*; +import org.dromara.warm.flow.core.enums.CooperateType; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.enums.UserType; +import org.dromara.warm.flow.core.service.*; +import org.dromara.warm.flow.core.utils.StreamUtils; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.springframework.beans.BeanUtils; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/**load + * 流程实例Controller + * + * @author hh + * @date 2023-04-18 + */ +@Validated +@RestController +@Tag(name = AdminSwaggerTagConst.Flow.FLOW_INSTANCE) +@RequestMapping("/flow/execute") +public class ExecuteController { + @Resource + private EmployeeService employeeService; + + @Resource + private DepartmentService deptService; + + @Resource + private RoleService roleService; + + @Resource + private HisTaskService hisTaskService; + + @Resource + private TaskService taskService; + + @Resource + private NodeService nodeService; + + @Resource + private InsService insService; + + @Resource + private UserService flowUserservice; + + @Resource + private FlowTaskService flowTaskService; + + @Resource + private HhDefService hhDefService; + + @Resource + private RoleEmployeeService roleEmployeeService; + + + + /** + * 启动任务 + * + * @param startProcessForm 启动流程参数 + */ + @SaCheckPermission("flow:execute:startTask") + @PostMapping("/startWorkFlow") + public ResponseDTO startWorkFlow(@Validated() @RequestBody StartProcessForm startProcessForm) { + StartProcessReturnVO startProcessReturn = flowTaskService.startWorkFlow(startProcessForm); + return ResponseDTO.ok( startProcessReturn); + } + /** + * 审批任务 + * + * @param completeTaskForm 办理任务参数 + */ + @SaCheckPermission("flow:execute:approve") + @PostMapping("/completeTask") + public ResponseDTO completeTask(@RequestBody CompleteTaskForm completeTaskForm) { + boolean result = flowTaskService.completeTask(completeTaskForm); + if(result) + return ResponseDTO.ok(); + else + return ResponseDTO.error(UnexpectedErrorCode.BUSINESS_HANDING, "流程办理失败"); + } + + /** + *审批任务 + * + * @param approveTaskInsForm 办理任务参数 + */ + @SaCheckPermission("flow:execute:approve") + @PostMapping("/approveTaskByInstance") + public ResponseDTO approveTaskByInstance(@RequestBody ApproveTaskInsForm approveTaskInsForm) { + boolean result = flowTaskService.approveTaskByInstance(approveTaskInsForm); + if(result) + return ResponseDTO.ok(); + else + return ResponseDTO.error(UnexpectedErrorCode.BUSINESS_HANDING, "流程办理失败"); + } + + + /** + * 分页待办任务列表 + */ + @GetMapping("/toDoPage") + public ResponseDTO> toDoPage(FlowTask flowTask, @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize) { + long userId = SmartRequestUtil.getRequestUserId(); + EmployeeEntity employee = employeeService.getById(userId); + List permissionList = permissionList(String.valueOf(employee.getEmployeeId()), employee.getDepartmentId(), employee); + flowTask.setPermissionList(permissionList); + // 使用 PageHelper 分页 + IPage pageParam = new Page<>(pageNum, pageSize); + IPage page = flowTaskService.toDoPage(pageParam, flowTask); + List list = page.getRecords(); + List taskIds = StreamUtils.toList(list, FlowTaskVO::getId); + List userList = flowUserservice.getByAssociateds(taskIds); + Map> map = StreamUtils.groupByKey(userList, User::getAssociated); + for (FlowTaskVO taskVo : list) { + if (SmartStringUtil.isNotNull(taskVo)) { + List users = map.get(taskVo.getId()); + if (CollectionUtils.isNotEmpty(users)) { + for (User user : users) { + if (UserType.APPROVAL.getKey().equals(user.getType())) { + if (SmartStringUtil.isEmpty(taskVo.getApprover())) { + taskVo.setApprover(""); + } + String name = getName(user.getProcessedBy()); + if (SmartStringUtil.isNotEmpty(name)) taskVo.setApprover(taskVo.getApprover().concat(name).concat(";")); + } else if (UserType.TRANSFER.getKey().equals(user.getType())) { + if (SmartStringUtil.isEmpty(taskVo.getTransferredBy())) { + taskVo.setTransferredBy(""); + } + String name = getName(user.getProcessedBy()); + if (SmartStringUtil.isNotEmpty(name)) taskVo.setTransferredBy(taskVo.getTransferredBy().concat(name).concat(";")); + } else if (UserType.DEPUTE.getKey().equals(user.getType())) { + if (SmartStringUtil.isEmpty(taskVo.getDelegate())) { + taskVo.setDelegate(""); + } + String name = getName(user.getProcessedBy()); + if (SmartStringUtil.isNotEmpty(name)) taskVo.setDelegate(taskVo.getDelegate().concat(name).concat(";")); + } + } + } + } + } + // 转换为自定义分页响应对象 + PageResult pageResult = new PageResult<>(); + pageResult.setList(page.getRecords()); + pageResult.setTotal(page.getTotal()); + pageResult.setPageNum( page.getCurrent()); + pageResult.setPageSize( page.getSize()); + pageResult.setPages( page.getPages()); + return ResponseDTO.ok(pageResult); + } + + /** + * 分页抄送任务列表 + * author:暗影 + */ + @GetMapping("/copyPage") + public ResponseDTO> copyPage(FlowTask flowTask, @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize) { + long userId = SmartRequestUtil.getRequestUserId(); + EmployeeEntity employee = employeeService.getById(userId); + List permissionList = permissionList(String.valueOf(employee.getEmployeeId()), employee.getDepartmentId(), employee); + flowTask.setPermissionList(permissionList); + // 使用 PageHelper 分页 + IPage pageParam = new Page<>(pageNum, pageSize); + IPage page = flowTaskService.copyPage(pageParam, flowTask); + + // 转换为自定义分页响应对象 + PageResult pageResult = new PageResult<>(); + pageResult.setList(page.getRecords()); + pageResult.setTotal(page.getTotal()); + pageResult.setPageNum( page.getCurrent()); + pageResult.setPageSize( page.getSize()); + pageResult.setPages( page.getPages()); + return ResponseDTO.ok(pageResult); + } + /** + * 分页已办任务列表 + */ + @GetMapping("/donePage") + public ResponseDTO> donePage(FlowHisTask flowHisTask, @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize) { + + long userId = SmartRequestUtil.getRequestUserId(); + EmployeeEntity employee = employeeService.getById(userId); + List permissionList = permissionList(String.valueOf(employee.getEmployeeId()), employee.getDepartmentId(), employee); + flowHisTask.setPermissionList(permissionList); + // 使用 PageHelper 分页 + IPage pageParam = new Page<>(pageNum, pageSize); + IPage page = flowTaskService.donePage(pageParam,flowHisTask); + List list = page.getRecords(); + Map userMap = StreamUtils.toMap(employeeService.queryAllEmployee(false).getData() + , EmployeeVO::getEmployeeId, EmployeeVO::getActualName); + if (CollectionUtils.isNotEmpty(list)) { + for (FlowHisTask hisTask : list) { + if (SmartStringUtil.isNotEmpty(hisTask.getApprover())) { + String name = getName(hisTask.getApprover()); + hisTask.setApprover(name); + } + if (SmartStringUtil.isNotEmpty(hisTask.getCollaborator())) { + String[] split = hisTask.getCollaborator().split(","); + if (split.length > 1) { + List names = new ArrayList<>(); + for (String s : split) { + names.add(userMap.get(Long.valueOf(s))); + } + hisTask.setCollaborator(StringUtils.join(names, ",")); + } + } + } + } + // 转换为自定义分页响应对象 + PageResult pageResult = new PageResult<>(); + pageResult.setList(page.getRecords()); + pageResult.setTotal(page.getTotal()); + pageResult.setPageNum( page.getCurrent()); + pageResult.setPageSize( page.getSize()); + pageResult.setPages( page.getPages()); + return ResponseDTO.ok(pageResult); + } + + private String getName(String id) { + Map userMap = StreamUtils.toMap(employeeService.queryAllEmployee(false).getData() + , EmployeeVO::getEmployeeId, EmployeeVO::getActualName); + Map deptMap = StreamUtils.toMap(deptService.listAll() + , DepartmentVO::getDepartmentId, DepartmentVO::getName); + Map roleMap = StreamUtils.toMap(roleService.getAllRole().getData() + , RoleVO::getRoleId, RoleVO::getRoleName); + if (SmartStringUtil.isNotNull(id)) { + if (id.contains("user:")) { + String name = userMap.get(Long.valueOf(id.replace("user:", ""))); + if (SmartStringUtil.isNotEmpty(name)) { + return "用户:" + name; + } + } else if (id.contains("dept:")) { + String name = deptMap.get(Long.valueOf(id.replace("dept:", ""))); + if (SmartStringUtil.isNotEmpty(name)) { + return "部门:" + name; + } + } else if (id.contains("role")) { + String name = roleMap.get(Long.valueOf(id.replace("role:", ""))); + if (SmartStringUtil.isNotEmpty(name)) { + return "角色:" + name; + } + } else { + try { + long parseLong = Long.parseLong(id); + String name = userMap.get(parseLong); + if (SmartStringUtil.isNotEmpty(name)) { + return "用户:" + name; + } + } catch (NumberFormatException e) { + return id; + } + + } + } + return ""; + } + + + /** + * 查询已办任务历史记录 + */ + @GetMapping("/doneList/{instanceId}") + public ResponseDTO> doneList(@PathVariable("instanceId") Long instanceId) { + List flowHisTasks = hisTaskService.orderById().desc().list(new FlowHisTask().setInstanceId(instanceId)); + Map userMap = StreamUtils.toMap(employeeService.queryAllEmployee(false).getData() + , EmployeeVO::getEmployeeId, EmployeeVO::getActualName); + List flowHisTaskList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(flowHisTasks)) { + for (HisTask hisTask : flowHisTasks) { + if (SmartStringUtil.isNotEmpty(hisTask.getApprover())) { + String name = getName(hisTask.getApprover()); + hisTask.setApprover(name); + } + if (SmartStringUtil.isNotEmpty(hisTask.getCollaborator())) { + String[] split = hisTask.getCollaborator().split(","); + if (split.length > 1) { + List names = new ArrayList<>(); + for (String s : split) { + names.add(userMap.get(Long.valueOf(s))); + } + hisTask.setCollaborator(StringUtils.join(names, ",")); + } + } + FlowHisTask flowHisTask = new FlowHisTask(); + BeanUtils.copyProperties(hisTask, flowHisTask); + flowHisTaskList.add(flowHisTask); + } + } + return ResponseDTO.ok(flowHisTaskList); + } + + /** + * 根据taskId查询代表任务 + * + * @param taskId + * @return + */ + @GetMapping("/getTaskById/{taskId}") + public ResponseDTO getTaskById(@PathVariable("taskId") Long taskId) { + return ResponseDTO.ok(taskService.getById(taskId)); + } + + /** + * 根据taskId查询代表任务 + * + * @param taskId + * @return + */ + @GetMapping("/getTaskDetail/{taskId}") + public ResponseDTO getTaskDetailById(@PathVariable("taskId") Long taskId) { + return ResponseDTO.ok(flowTaskService.getTaskDetailById(taskId)); + } + + /** + * 根据taskId查询代表任务 + * + * @param taskId + * @return + */ + @GetMapping("/getDoneTaskDetail/{taskId}") + public ResponseDTO getDoneTaskDetail(@PathVariable("taskId") Long taskId) { + return ResponseDTO.ok(flowTaskService.getDoneTaskDetailById(taskId)); + } + + /** + * 查询跳转任意节点列表 + */ + @SaCheckPermission("flow:execute:goAnyNode") + @GetMapping("/anyNodeList/{instanceId}") + public ResponseDTO> anyNodeList(@PathVariable("instanceId") Long instanceId) { + Instance instance = insService.getById(instanceId); + List nodeList = nodeService.list(FlowEngine.newNode().setDefinitionId(instance.getDefinitionId())); + nodeList.removeIf(node -> NodeType.isGateWay(node.getNodeType())); + return ResponseDTO.ok(nodeList); + } + + /** + * 处理非办理的流程交互类型 + * + * @param WarmFlowInteractiveTypeVO 要转办用户 + * @return 是否成功 + */ + @PostMapping("/interactiveType") + public ResponseDTO interactiveType(WarmFlowInteractiveTypeVO WarmFlowInteractiveTypeVO) { + return ResponseDTO.ok(hhDefService.interactiveType(WarmFlowInteractiveTypeVO)); + } + + /** + * 交互类型可以选择的用户 + * + * @param warmFlowInteractiveTypeVO 交互类型请求类 + * @return 是否成功 + */ + @GetMapping("/interactiveTypeEmployeeEntity") + public ResponseDTO> interactiveTypeEmployeeEntity(WarmFlowInteractiveTypeVO warmFlowInteractiveTypeVO, @RequestParam(defaultValue = "1") int pageNum, + @RequestParam(defaultValue = "10") int pageSize) { + + long userId = SmartRequestUtil.getRequestUserId(); + Integer operatorType = warmFlowInteractiveTypeVO.getOperatorType(); + // 构建分页对象 + Page pageParam = new Page<>(pageNum, pageSize); + // 根据操作类型查询分页数据 + Page page; + + Long taskId = warmFlowInteractiveTypeVO.getTaskId(); + List users = flowUserservice.listByAssociatedAndTypes(taskId); + if (!Objects.equals(CooperateType.REDUCTION_SIGNATURE.getKey(), operatorType)) { + List userIds = StreamUtils.toList(users, User::getProcessedBy); + warmFlowInteractiveTypeVO.setUserIds(userIds); + page = employeeService.selectNotUserList(pageParam,warmFlowInteractiveTypeVO); + } else { + List userIds = StreamUtils.toList(users, User::getProcessedBy); + warmFlowInteractiveTypeVO.setUserIds(userIds); + page = employeeService.selectUserList(pageParam,warmFlowInteractiveTypeVO); + // 过滤当前用户(内存过滤,适用于小数据量) + List filteredList = page.getRecords().stream() + .filter(employee -> !Objects.equals(employee.getEmployeeId(), userId)) + .collect(Collectors.toList()); + page.setRecords(filteredList);} + // 转换为自定义分页响应对象 + PageResult pageResult = new PageResult<>(); + pageResult.setList(page.getRecords()); + pageResult.setTotal(page.getTotal()); + pageResult.setPageNum( page.getCurrent()); + pageResult.setPageSize( page.getSize()); + pageResult.setPages( page.getPages()); + return ResponseDTO.ok(pageResult); + } + + /** + * 激活流程 + * + * @param instanceId + * @return + */ + @GetMapping("/active/{instanceId}") + public ResponseDTO active(@PathVariable("instanceId") Long instanceId) { + return ResponseDTO.ok(insService.active(instanceId)); + } + + /** + * 挂起流程 + * + * @param instanceId + * @return + */ + @GetMapping("/unActive/{instanceId}") + public ResponseDTO unActive(@PathVariable("instanceId") Long instanceId) { + return ResponseDTO.ok(insService.unActive(instanceId)); + } + + /** + * 获取权限 + * + * @param userId 用户编号 + * @param deptId 部门编号 + * @param employee 登陆用户 + * @return 权限列表 + */ + private List permissionList(String userId, Long deptId, EmployeeEntity employee) { + List roles = roleEmployeeService.getRoleInfoListByEmployeeId(employee.getEmployeeId()); + List permissionList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(roles)) { + permissionList = StreamUtils.toList(roles, role -> "role:" + role.getRoleId()); + } + permissionList.add(userId); + if (Objects.nonNull(deptId)) { + permissionList.add("dept:" + deptId); + } + return permissionList; + } + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link ResponseDTO< List>} + * @author liangli + * @date 2024/8/21 17:08 + **/ + @GetMapping(value = "/idReverseDisplayName/{ids}") + public ResponseDTO> idReverseDisplayName(@PathVariable Long[] ids) { + return ResponseDTO.ok(flowTaskService.idReverseDisplayName(ids)); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/contstant/FlowConstant.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/contstant/FlowConstant.java new file mode 100644 index 0000000..b45a279 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/contstant/FlowConstant.java @@ -0,0 +1,71 @@ +package net.lab1024.sa.admin.module.flow.contstant; + + +/** + * 工作流常量 + * + * @author may + */ +public interface FlowConstant { + + /** + * 流程发起人 + */ + String INITIATOR = "initiator"; + + /** + * 流程实例id + */ + String PROCESS_INSTANCE_ID = "processInstanceId"; + + + /** + * 业务表 + */ + String BUSINESS_TABLE = "businessTable"; + /** + * 业务id + */ + String BUSINESS_ID = "businessId"; + + /** + * 任务id + */ + String TASK_ID = "taskId"; + + /** + * 委托 + */ + String DELEGATE_TASK = "delegateTask"; + + /** + * 转办 + */ + String TRANSFER_TASK = "transferTask"; + + /** + * 加签 + */ + String ADD_SIGNATURE = "addSignature"; + + /** + * 减签 + */ + String REDUCTION_SIGNATURE = "reductionSignature"; + + /** + * 流程分类Id转名称 + */ + String CATEGORY_ID_TO_NAME = "category_id_to_name"; + + /** + * 流程分类名称 + */ + String FLOW_CATEGORY_NAME = "flow_category_name#30d"; + + /** + * 默认租户OA申请分类id + */ + Long FLOW_CATEGORY_ID = 100L; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/dao/FlowDefinitionDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/dao/FlowDefinitionDao.java new file mode 100644 index 0000000..ca53de5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/dao/FlowDefinitionDao.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.flow.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.flow.domain.form.FlowDefinitionQueryForm; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowDefinitionVO; +import net.lab1024.sa.admin.module.system.position.domain.entity.PositionEntity; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionQueryForm; +import net.lab1024.sa.admin.module.system.position.domain.vo.PositionVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 职务表 Dao + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Mapper +@Component +public interface FlowDefinitionDao extends BaseMapper { + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") FlowDefinitionQueryForm queryForm); + + + /** + * 查询 + * @param deletedFlag + * @return + */ + List queryList(@Param("deletedFlag") Boolean deletedFlag); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/ApproveTaskInsForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/ApproveTaskInsForm.java new file mode 100644 index 0000000..3712431 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/ApproveTaskInsForm.java @@ -0,0 +1,79 @@ +package net.lab1024.sa.admin.module.flow.domain.form; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowCopyVO; + +import java.io.Serial; +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 办理任务请求对象 + * + * @author may + */ +@Data +public class ApproveTaskInsForm implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 任务id + */ + @NotNull(message = "任务id不能为空") + private Long InstanceId; + + /** + * 附件id + */ + private String fileId; + + /** + * 抄送人员 + */ + private List flowCopyList; + + /** + * 消息类型 + */ + private List messageType; + + /** + * 办理意见 + */ + private String message; + + /** + * 消息通知 + */ + private String notice; + + /** + * 流程变量 + */ + private Map variables; + + /** + * 弹窗选择的办理人 + */ + private Map assigneeMap; + + /** + * 扩展变量(此处为逗号分隔的ossId) + */ + private String ext; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/CompleteTaskForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/CompleteTaskForm.java new file mode 100644 index 0000000..b06cfeb --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/CompleteTaskForm.java @@ -0,0 +1,79 @@ +package net.lab1024.sa.admin.module.flow.domain.form; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowCopyVO; + +import java.io.Serial; +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * 办理任务请求对象 + * + * @author may + */ +@Data +public class CompleteTaskForm implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 任务id + */ + @NotNull(message = "任务id不能为空") + private Long taskId; + + /** + * 附件id + */ + private String fileId; + + /** + * 抄送人员 + */ + private List flowCopyList; + + /** + * 消息类型 + */ + private List messageType; + + /** + * 办理意见 + */ + private String message; + + /** + * 消息通知 + */ + private String notice; + + /** + * 流程变量 + */ + private Map variables; + + /** + * 弹窗选择的办理人 + */ + private Map assigneeMap; + + /** + * 扩展变量(此处为逗号分隔的ossId) + */ + private String ext; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionAddForm.java new file mode 100644 index 0000000..dea2cf2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionAddForm.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.admin.module.flow.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 职务表 新建表单 + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Data +public class FlowDefinitionAddForm { + + @Schema(description = "流程编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "流程编码不能为空") + private String flowCode; + + @Schema(description = "流程名称") + @NotBlank(message = "流程名称不能为空") + private String flowName; + + @Schema(description = "流程类别") + private String category; + + /** + * 审批表单是否自定义(Y是 N否) + */ + @Schema(description = "审批表单是否自定义") + @NotBlank(message = "审批表单是否自定义不能为空") + private String formCustom; + + /** + * 审批表单路径 + */ + @Schema(description = "审批表单路径") + private String formPath; + + /** + * 监听器类型 + */ + @Schema(description = "监听器类型") + private String listenerType; + + /** + * 监听器路径 + */ + @Schema(description = "监听器路径") + private String listenerPath; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionQueryForm.java new file mode 100644 index 0000000..6e480ed --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionQueryForm.java @@ -0,0 +1,16 @@ +package net.lab1024.sa.admin.module.flow.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +@Data +public class FlowDefinitionQueryForm extends PageParam { + private String flowCode; + private String flowName; + private String category; + private String version; + + @Schema(hidden = true) + private Boolean deletedFlag; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionUpdateForm.java new file mode 100644 index 0000000..ea2902d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/FlowDefinitionUpdateForm.java @@ -0,0 +1,21 @@ +package net.lab1024.sa.admin.module.flow.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 职务表 更新表单 + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Data +public class FlowDefinitionUpdateForm extends FlowDefinitionAddForm { + + @Schema(description = "流程ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "流程ID 不能为空") + private Long id; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/StartProcessForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/StartProcessForm.java new file mode 100644 index 0000000..a1e3d2a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/form/StartProcessForm.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.admin.module.flow.domain.form; + + +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import java.io.Serial; +import java.io.Serializable; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * 启动流程对象 + * + * @author may + */ +@Data +public class StartProcessForm implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 业务唯一值id + */ + @NotBlank(message = "业务ID不能为空") + private String businessId; + + /** + * 流程定义编码 + */ + @NotBlank(message = "流程定义编码不能为空") + private String flowCode; + + /** + * 流程变量,前端会提交一个元素{'entity': {业务详情数据对象}} + */ + private Map variables; + + public Map getVariables() { + if (variables == null) { + return new HashMap<>(16); + } + variables.entrySet().removeIf(entry -> Objects.isNull(entry.getValue())); + return variables; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowCopyVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowCopyVO.java new file mode 100644 index 0000000..ee6dd4b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowCopyVO.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.admin.module.flow.domain.vo; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 抄送 + * + * @author may + */ +@Data +public class FlowCopyVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 用户id + */ + private Long userId; + + /** + * 用户名称 + */ + private String userName; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowDefinitionVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowDefinitionVO.java new file mode 100644 index 0000000..6f8c6cd --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowDefinitionVO.java @@ -0,0 +1,95 @@ +package net.lab1024.sa.admin.module.flow.domain.vo; + +import lombok.Data; +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 流程定义视图 + * + * @author may + */ +@Data +public class FlowDefinitionVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程版本 + */ + private String version; + + /** + * 是否发布(0未发布 1已发布 9失效) + */ + private Integer isPublish; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 流程激活状态(0挂起 1激活) + */ + private Integer activityStatus; + + /** + * 监听器类型 + */ + private String listenerType; + + /** + * 监听器路径 + */ + private String listenerPath; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowInstanceVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowInstanceVO.java new file mode 100644 index 0000000..2c08d86 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowInstanceVO.java @@ -0,0 +1,131 @@ +package net.lab1024.sa.admin.module.flow.domain.vo; + +import lombok.Data; +import java.util.Date; + +/** + * 流程实例视图 + * + * @author may + */ +@Data +public class FlowInstanceVO { + + private Long id; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 租户ID + */ + private String tenantId; + + /** + * 删除标记 + */ + private String delFlag; + + /** + * 对应flow_definition表的id + */ + private Long definitionId; + + /** + * 流程定义名称 + */ + private String flowName; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 业务id + */ + private String businessId; + + /** + * 节点类型(0开始节点 1中间节点 2结束节点 3互斥网关 4并行网关) + */ + private Integer nodeType; + + /** + * 流程节点编码 每个流程的nodeCode是唯一的,即definitionId+nodeCode唯一,在数据库层面做了控制 + */ + private String nodeCode; + + /** + * 流程节点名称 + */ + private String nodeName; + + /** + * 流程变量 + */ + private String variable; + + /** + * 流程状态(0待提交 1审批中 2 审批通过 3自动通过 8已完成 9已退回 10失效) + */ + private String flowStatus; + + /** + * 流程状态 + */ + private String flowStatusName; + + /** + * 流程激活状态(0挂起 1激活) + */ + private Integer activityStatus; + + /** + * 审批表单是否自定义(Y是 N否) + */ + private String formCustom; + + /** + * 审批表单路径 + */ + private String formPath; + + /** + * 扩展字段,预留给业务系统使用 + */ + private String ext; + + /** + * 流程定义版本 + */ + private String version; + + /** + * 创建者 + */ + private String createBy; + + /** + * 申请人 + */ + private String createByName; + + /** + * 流程分类id + */ + private String category; + + /** + * 流程分类名称 + */ + private String categoryName; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowTaskVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowTaskVO.java new file mode 100644 index 0000000..bbc68c2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/FlowTaskVO.java @@ -0,0 +1,130 @@ +package net.lab1024.sa.admin.module.flow.domain.vo; + +import cn.hutool.json.JSONObject; +import org.dromara.warm.flow.orm.entity.FlowTask; + +import java.util.Map; + +/** + * 待办任务vo + * + * @author warm + */ +public class FlowTaskVO extends FlowTask { + + /** + * 计划审批人 + */ + private String initiator; + + /** + * 计划审批人 + */ + private String approver; + + /** + * 转办人 + */ + private String transferredBy; + + /** + * 委派人 + */ + private String delegate; + /** + * 流程编码 + */ + private String flowCode; + + /** + * 流程状态 + */ + private String flowStatus; + + private JSONObject businessFormMetaData; + + + private Map businessForm; + + /** + * 激活状态 + */ + private Integer activityStatus; + + public String getApprover() { + return approver; + } + + public FlowTaskVO setApprover(String approver) { + this.approver = approver; + return this; + } + + public String getTransferredBy() { + return transferredBy; + } + + public FlowTaskVO setTransferredBy(String transferredBy) { + this.transferredBy = transferredBy; + return this; + } + + public String getDelegate() { + return delegate; + } + + public FlowTaskVO setDelegate(String delegate) { + this.delegate = delegate; + return this; + } + + public String getFlowStatus() { + return flowStatus; + } + + public FlowTaskVO setFlowStatus(String flowStatus) { + this.flowStatus = flowStatus; + return this; + } + + public Integer getActivityStatus() { + return activityStatus; + } + + public FlowTaskVO setActivityStatus(Integer activityStatus) { + this.activityStatus = activityStatus; + return this; + } + + public String getFlowCode() { + return flowCode; + } + + public void setFlowCode(String flowCode) { + this.flowCode = flowCode; + } + + public JSONObject getBusinessFormMetaData() { + return businessFormMetaData; + } + + public void setBusinessFormMetaData(JSONObject businessFormMetaData) { + this.businessFormMetaData = businessFormMetaData; + } + + public Map getBusinessForm() { + return businessForm; + } + + public void setBusinessForm(Map businessForm) { + this.businessForm = businessForm; + } + + public String getInitiator() { + return initiator; + } + + public void setInitiator(String initiator) { + this.initiator = initiator; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/StartProcessReturnVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/StartProcessReturnVO.java new file mode 100644 index 0000000..17117f1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/StartProcessReturnVO.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.admin.module.flow.domain.vo; + + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 启动流程返回对象 + * + * @author Lion Li + */ +@Data +public class StartProcessReturnVO implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程实例id + */ + private Long processInstanceId; + + /** + * 任务id + */ + private Long taskId; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/WarmFlowInteractiveTypeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/WarmFlowInteractiveTypeVO.java new file mode 100644 index 0000000..313ab04 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/domain/vo/WarmFlowInteractiveTypeVO.java @@ -0,0 +1,88 @@ +package net.lab1024.sa.admin.module.flow.domain.vo; + +import com.fasterxml.jackson.annotation.JsonInclude; + +import java.io.Serializable; +import java.util.List; +import java.util.Map; + +public class WarmFlowInteractiveTypeVO implements Serializable { + /** + * 任务id + */ + private Long taskId; + + /** + * 增加办理人 + */ + private List addHandlers; + + /** + * 操作类型[2:转办,6:加签,3:委派,7:减签] + */ + private Integer operatorType; + + /** + * 部门ID + */ + private Long departmentId; + + private List userIds; + + /** 请求参数 */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) + private Map params; + + public Long getTaskId() { + return taskId; + } + + public WarmFlowInteractiveTypeVO setTaskId(Long taskId) { + this.taskId = taskId; + return this; + } + + public List getAddHandlers() { + return addHandlers; + } + + public WarmFlowInteractiveTypeVO setAddHandlers(List addHandlers) { + this.addHandlers = addHandlers; + return this; + } + + public Integer getOperatorType() { + return operatorType; + } + + public WarmFlowInteractiveTypeVO setOperatorType(Integer operatorType) { + this.operatorType = operatorType; + return this; + } + + public Long getDepartmentId() { + return departmentId; + } + + public void setDepartmentId(Long departmentId) { + this.departmentId = departmentId; + } + + public List getUserIds() { + return userIds; + } + + public WarmFlowInteractiveTypeVO setUserIds(List userIds) { + this.userIds = userIds; + return this; + } + + public Map getParams() { + return params; + } + + public void setParams(Map params) { + this.params = params; + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/BusinessStatusEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/BusinessStatusEnum.java new file mode 100644 index 0000000..4b77e35 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/BusinessStatusEnum.java @@ -0,0 +1,214 @@ +package net.lab1024.sa.admin.module.flow.enums; + +import cn.hutool.core.util.StrUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.exception.BusinessException; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 业务状态枚举 + * + * @author may + */ +@Getter +@AllArgsConstructor +public enum BusinessStatusEnum { + + /** + * 已撤销 + */ + CANCEL("cancel", "已撤销"), + + /** + * 草稿 + */ + DRAFT("draft", "草稿"), + + /** + * 待审核 + */ + WAITING("waiting", "待审核"), + + /** + * 已完成 + */ + FINISH("finish", "已完成"), + + /** + * 已作废 + */ + INVALID("invalid", "已作废"), + + /** + * 已退回 + */ + BACK("back", "已退回"), + + /** + * 已终止 + */ + TERMINATION("termination", "已终止"); + + /** + * 状态 + */ + private final String status; + + /** + * 描述 + */ + private final String desc; + + private static final Map STATUS_MAP = Arrays.stream(BusinessStatusEnum.values()) + .collect(Collectors.toConcurrentMap(BusinessStatusEnum::getStatus, Function.identity())); + + /** + * 根据状态获取对应的 BusinessStatusEnum 枚举 + * + * @param status 业务状态码 + * @return 对应的 BusinessStatusEnum 枚举,如果找不到则返回 null + */ + public static BusinessStatusEnum getByStatus(String status) { + // 使用 STATUS_MAP 获取对应的枚举,若找不到则返回 null + return STATUS_MAP.get(status); + } + + /** + * 根据状态获取对应的业务状态描述信息 + * + * @param status 业务状态码 + * @return 返回业务状态描述,若状态码为空或未找到对应的枚举,返回空字符串 + */ + public static String findByStatus(String status) { + if (SmartStringUtil.isEmpty(status)) { + return StrUtil.EMPTY; + } + BusinessStatusEnum statusEnum = STATUS_MAP.get(status); + return (statusEnum != null) ? statusEnum.getDesc() : StrUtil.EMPTY; + } + + /** + * 判断是否为指定的状态之一:草稿、已撤销或已退回 + * + * @param status 要检查的状态 + * @return 如果状态为草稿、已撤销或已退回之一,则返回 true;否则返回 false + */ + public static boolean isDraftOrCancelOrBack(String status) { + return DRAFT.status.equals(status) || CANCEL.status.equals(status) || BACK.status.equals(status); + } + + /** + * 判断是否为撤销,退回,作废,终止 + * + * @param status status + * @return 结果 + */ + public static boolean initialState(String status) { + return CANCEL.status.equals(status) || BACK.status.equals(status) || INVALID.status.equals(status) || TERMINATION.status.equals(status); + } + + /** + * 获取运行中的实例状态列表 + * + * @return 包含运行中实例状态的不可变列表 + * (包含 DRAFT、WAITING、BACK 和 CANCEL 状态) + */ + public static List runningStatus() { + return Arrays.asList(DRAFT.status, WAITING.status, BACK.status, CANCEL.status); + } + + /** + * 获取结束实例的状态列表 + * + * @return 包含结束实例状态的不可变列表 + * (包含 FINISH、INVALID 和 TERMINATION 状态) + */ + public static List finishStatus() { + return Arrays.asList(FINISH.status, INVALID.status, TERMINATION.status); + } + + /** + * 启动流程校验 + * + * @param status 状态 + */ + public static void checkStartStatus(String status) { + if (WAITING.getStatus().equals(status)) { + throw new BusinessException("该单据已提交过申请,正在审批中!"); + } else if (FINISH.getStatus().equals(status)) { + throw new BusinessException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new BusinessException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new BusinessException("该单据已终止!"); + } else if (SmartStringUtil.isEmpty(status)) { + throw new BusinessException("流程状态为空!"); + } + } + + /** + * 撤销流程校验 + * + * @param status 状态 + */ + public static void checkCancelStatus(String status) { + if (CANCEL.getStatus().equals(status)) { + throw new BusinessException("该单据已撤销!"); + } else if (FINISH.getStatus().equals(status)) { + throw new BusinessException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new BusinessException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new BusinessException("该单据已终止!"); + } else if (BACK.getStatus().equals(status)) { + throw new BusinessException("该单据已退回!"); + } else if (SmartStringUtil.isEmpty(status)) { + throw new BusinessException("流程状态为空!"); + } + } + + /** + * 驳回流程校验 + * + * @param status 状态 + */ + public static void checkBackStatus(String status) { + if (BACK.getStatus().equals(status)) { + throw new BusinessException("该单据已退回!"); + } else if (FINISH.getStatus().equals(status)) { + throw new BusinessException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new BusinessException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new BusinessException("该单据已终止!"); + } else if (CANCEL.getStatus().equals(status)) { + throw new BusinessException("该单据已撤销!"); + } else if (SmartStringUtil.isEmpty(status)) { + throw new BusinessException("流程状态为空!"); + } + } + + /** + * 作废,终止流程校验 + * + * @param status 状态 + */ + public static void checkInvalidStatus(String status) { + if (FINISH.getStatus().equals(status)) { + throw new BusinessException("该单据已完成申请!"); + } else if (INVALID.getStatus().equals(status)) { + throw new BusinessException("该单据已作废!"); + } else if (TERMINATION.getStatus().equals(status)) { + throw new BusinessException("该单据已终止!"); + } else if (SmartStringUtil.isEmpty(status)) { + throw new BusinessException("流程状态为空!"); + } + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/FlowStatusEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/FlowStatusEnum.java new file mode 100644 index 0000000..1618743 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/FlowStatusEnum.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.admin.module.flow.enums; + +public enum FlowStatusEnum { + + PENDING_SUBMIT(0, "待提交"), + APPROVING(1, "审批中"), + APPROVED(2, "审批通过"), + AUTO_APPROVED(3, "自动通过"), + TERMINATED(4, "终止"), + INVALID(5, "作废"), + REVOKED(6, "撤销"), + RETRIEVED(7, "取回"), + COMPLETED(8, "已完成"), + RETURNED(9, "已退回"), + EXPIRED(10, "失效"); + + private final int value; + private final String desc; + + FlowStatusEnum(int value, String desc) { + this.value = value; + this.desc = desc; + } + + public int getValue() { + return value; + } + + public String getDesc() { + return desc; + } + + // 通过数值获取枚举实例 + public static FlowStatusEnum fromValue(int value) { + for (FlowStatusEnum status : values()) { + if (status.value == value) { + return status; + } + } + throw new IllegalArgumentException("无效的状态值: " + value); + } + + // 通过描述获取枚举实例 + public static FlowStatusEnum fromDesc(String desc) { + for (FlowStatusEnum status : values()) { + if (status.desc.equals(desc)) { + return status; + } + } + throw new IllegalArgumentException("无效的状态描述: " + desc); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskAssigneeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskAssigneeEnum.java new file mode 100644 index 0000000..22e0e79 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskAssigneeEnum.java @@ -0,0 +1,109 @@ +package net.lab1024.sa.admin.module.flow.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.exception.BusinessException; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 任务分配人枚举 + * + * @author AprilWind + */ +@Getter +@AllArgsConstructor +public enum TaskAssigneeEnum { + + /** + * 用户 + */ + USER("用户", ""), + + /** + * 角色 + */ + ROLE("角色", "role:"), + + /** + * 部门 + */ + DEPT("部门", "dept:"), + + /** + * 岗位 + */ + POST("岗位", "post:"); + + private final String desc; + private final String code; + + /** + * 根据描述获取对应的枚举类型 + *

+ * 通过传入描述,查找并返回匹配的枚举项。如果未找到匹配项,会抛出 {@link BusinessException}。 + *

+ * + * @param desc 描述,用于匹配对应的枚举项 + * @return TaskAssigneeEnum 返回对应的枚举类型 + * @throws BusinessException 如果未找到匹配的枚举项 + */ + public static TaskAssigneeEnum fromDesc(String desc) { + for (TaskAssigneeEnum type : values()) { + if (type.getDesc().equals(desc)) { + return type; + } + } + throw new BusinessException("未知的办理人类型: " + desc); + } + + /** + * 根据代码获取对应的枚举类型 + *

+ * 通过传入代码,查找并返回匹配的枚举项。如果未找到匹配项,会抛出 {@link BusinessException}。 + *

+ * + * @param code 代码,用于匹配对应的枚举项 + * @return TaskAssigneeEnum 返回对应的枚举类型 + * @throws IllegalArgumentException 如果未找到匹配的枚举项 + */ + public static TaskAssigneeEnum fromCode(String code) { + for (TaskAssigneeEnum type : values()) { + if (type.getCode().equals(code)) { + return type; + } + } + throw new BusinessException("未知的办理人类型代码: " + code); + } + + /** + * 获取所有办理人类型的描述列表 + *

+ * 获取当前枚举类所有项的描述字段列表,通常用于展示选择项。 + *

+ * + * @return List 返回所有办理人类型的描述列表 + */ + public static List getAssigneeTypeList() { + return Arrays.stream(values()) + .map(TaskAssigneeEnum::getDesc) + .collect(Collectors.toList()); + } + + /** + * 获取所有办理人类型的代码列表 + *

+ * 获取当前枚举类所有项的代码字段列表,通常用于程序内部逻辑的判断。 + *

+ * + * @return List 返回所有办理人类型的代码列表 + */ + public static List getAssigneeCodeList() { + return Arrays.stream(values()) + .map(TaskAssigneeEnum::getCode) + .collect(Collectors.toList()); + } +} + diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskAssigneeType.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskAssigneeType.java new file mode 100644 index 0000000..148b1e9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskAssigneeType.java @@ -0,0 +1,49 @@ +package net.lab1024.sa.admin.module.flow.enums; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 人员类型 + * + * @author AprilWind + */ +@Getter +@AllArgsConstructor +public enum TaskAssigneeType { + + /** + * 待办任务的审批人权限 + *

该权限表示用户是待办任务的审批人,负责审核任务的执行情况。

+ */ + APPROVER("1", "待办任务的审批人权限"), + + /** + * 待办任务的转办人权限 + *

该权限表示用户是待办任务的转办人,负责将任务分配给其他人员。

+ */ + TRANSFER("2", "待办任务的转办人权限"), + + /** + * 待办任务的委托人权限 + *

该权限表示用户是待办任务的委托人,能够委托其他人代为处理任务。

+ */ + DELEGATE("3", "待办任务的委托人权限"), + + /** + * 待办任务的抄送人权限 + *

该权限表示用户是待办任务的抄送人,仅接收任务信息的通知,不参与任务的审批或处理。

+ */ + COPY("4", "待办任务的抄送人权限"); + + /** + * 类型 + */ + private final String code; + + /** + * 描述 + */ + private final String description; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskStatusEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskStatusEnum.java new file mode 100644 index 0000000..2ea4b3a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/enums/TaskStatusEnum.java @@ -0,0 +1,104 @@ +package net.lab1024.sa.admin.module.flow.enums; + +import cn.hutool.core.util.StrUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 任务状态枚举 + * + * @author may + */ +@Getter +@AllArgsConstructor +public enum TaskStatusEnum { + + /** + * 撤销 + */ + CANCEL("cancel", "撤销"), + + /** + * 通过 + */ + PASS("pass", "通过"), + + /** + * 待审核 + */ + WAITING("waiting", "待审核"), + + /** + * 作废 + */ + INVALID("invalid", "作废"), + + /** + * 退回 + */ + BACK("back", "退回"), + + /** + * 终止 + */ + TERMINATION("termination", "终止"), + + /** + * 转办 + */ + TRANSFER("transfer", "转办"), + + /** + * 委托 + */ + DEPUTE("depute", "委托"), + + /** + * 抄送 + */ + COPY("copy", "抄送"), + + /** + * 加签 + */ + SIGN("sign", "加签"), + + /** + * 减签 + */ + SIGN_OFF("sign_off", "减签"), + + /** + * 超时 + */ + TIMEOUT("timeout", "超时"); + + /** + * 状态 + */ + private final String status; + + /** + * 描述 + */ + private final String desc; + + private static final Map STATUS_DESC_MAP = Arrays.stream(values()) + .collect(Collectors.toConcurrentMap(TaskStatusEnum::getStatus, TaskStatusEnum::getDesc)); + + /** + * 任务业务状态 + * + * @param status 状态 + */ + public static String findByStatus(String status) { + // 从缓存中直接获取描述 + return STATUS_DESC_MAP.getOrDefault(status, StrUtil.EMPTY); + } + +} + diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessCreateTaskEvent.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessCreateTaskEvent.java new file mode 100644 index 0000000..1cd87a2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessCreateTaskEvent.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.admin.module.flow.event; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 流程创建任务监听 + * + * @author may + */ +@Data +public class ProcessCreateTaskEvent implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 审批节点编码 + */ + private String nodeCode; + + /** + * 任务id + */ + private Long taskId; + + /** + * 业务id + */ + private String businessId; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessDeleteEvent.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessDeleteEvent.java new file mode 100644 index 0000000..942e414 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessDeleteEvent.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.admin.module.flow.event; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + +/** + * 删除流程监听 + * + * @author AprilWind + */ +@Data +public class ProcessDeleteEvent implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 业务id + */ + private String businessId; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessEvent.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessEvent.java new file mode 100644 index 0000000..f4f698a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/event/ProcessEvent.java @@ -0,0 +1,45 @@ +package net.lab1024.sa.admin.module.flow.event; + +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Map; + +/** + * 总体流程监听 + * + * @author may + */ +@Data +public class ProcessEvent implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * 流程定义编码 + */ + private String flowCode; + + /** + * 业务id + */ + private String businessId; + + /** + * 状态 + */ + private String status; + + /** + * 办理参数 + */ + private Map params; + + /** + * 当为true时为申请人节点办理 + */ + private boolean submit; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/handler/FlowProcessEventHandler.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/handler/FlowProcessEventHandler.java new file mode 100644 index 0000000..a38eb63 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/handler/FlowProcessEventHandler.java @@ -0,0 +1,74 @@ +package net.lab1024.sa.admin.module.flow.handler; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.flow.annoation.ConditionalOnEnable; +import net.lab1024.sa.admin.module.flow.event.ProcessCreateTaskEvent; +import net.lab1024.sa.admin.module.flow.event.ProcessDeleteEvent; +import net.lab1024.sa.admin.module.flow.event.ProcessEvent; +import org.springframework.stereotype.Component; +import net.lab1024.sa.base.common.util.SpringUtils; +import java.util.Map; + +/** + * 流程监听服务 + * + * @author may + * @date 2024-06-02 + */ +@ConditionalOnEnable +@Slf4j +@Component +public class FlowProcessEventHandler { + + /** + * 总体流程监听(例如: 草稿,撤销,退回,作废,终止,已完成,单任务完成等) + * + * @param flowCode 流程定义编码 + * @param businessId 业务id + * @param status 状态 + * @param submit 当为true时为申请人节点办理 + */ + public void processHandler(String flowCode, String businessId, String status, Map params, boolean submit) { + log.info("发布流程事件,租户ID: {}, 流程状态: {}, 流程编码: {}, 业务ID: {}, 是否申请人节点办理: {}", status, flowCode, businessId, submit); + ProcessEvent processEvent = new ProcessEvent(); + processEvent.setFlowCode(flowCode); + processEvent.setBusinessId(businessId); + processEvent.setStatus(status); + processEvent.setParams(params); + processEvent.setSubmit(submit); + SpringUtils.getApplicationContext().publishEvent(processEvent); + } + + /** + * 执行创建任务监听 + * + * @param flowCode 流程定义编码 + * @param nodeCode 审批节点编码 + * @param taskId 任务id + * @param businessId 业务id + */ + public void processCreateTaskHandler(String flowCode, String nodeCode, Long taskId, String businessId) { + log.info("发布流程任务事件, 租户ID: {}, 流程编码: {}, 节点编码: {}, 任务ID: {}, 业务ID: {}",flowCode, nodeCode, taskId, businessId); + ProcessCreateTaskEvent processCreateTaskEvent = new ProcessCreateTaskEvent(); + processCreateTaskEvent.setFlowCode(flowCode); + processCreateTaskEvent.setNodeCode(nodeCode); + processCreateTaskEvent.setTaskId(taskId); + processCreateTaskEvent.setBusinessId(businessId); + SpringUtils.getApplicationContext().publishEvent(processCreateTaskEvent); + } + + /** + * 删除流程监听 + * + * @param flowCode 流程定义编码 + * @param businessId 业务ID + */ + public void processDeleteHandler(String flowCode, String businessId) { + log.info("发布删除流程事件, 租户ID: {}, 流程编码: {}, 业务ID: {}", flowCode, businessId); + ProcessDeleteEvent processDeleteEvent = new ProcessDeleteEvent(); + processDeleteEvent.setFlowCode(flowCode); + processDeleteEvent.setBusinessId(businessId); + SpringUtils.getApplicationContext().publishEvent(processDeleteEvent); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/handler/WorkflowPermissionHandler.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/handler/WorkflowPermissionHandler.java new file mode 100644 index 0000000..b46050e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/handler/WorkflowPermissionHandler.java @@ -0,0 +1,83 @@ +package net.lab1024.sa.admin.module.flow.handler; + +import cn.hutool.core.util.ObjectUtil; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.flow.annoation.ConditionalOnEnable; +import net.lab1024.sa.admin.module.flow.enums.TaskAssigneeEnum; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleQueryForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; +import net.lab1024.sa.admin.module.system.role.service.RoleService; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.handler.PermissionHandler; +import org.dromara.warm.flow.core.service.impl.TaskServiceImpl; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 办理人权限处理器 + * + * @author AprilWind + */ +@ConditionalOnEnable +@RequiredArgsConstructor +@Component +@Slf4j +public class WorkflowPermissionHandler implements PermissionHandler { + @Resource + private EmployeeService userService; + @Resource + private RoleEmployeeService roleEmployeeService; + /** + * 审批前获取当前办理人,办理时会校验的该权限集合 + * 返回当前用户权限集合 + */ + @Override + public List permissions() { + long userId = SmartRequestUtil.getRequestUserId(); + EmployeeEntity loginUser = userService.getById(userId); + if (ObjectUtil.isNull(loginUser)) { + return new ArrayList<>(); + } + List roleList = roleEmployeeService.getRoleIdList(userId); + + // 使用一个流来构建权限列表 + return Stream.of( + // 角色权限前缀 + roleList.stream() + .map(role -> TaskAssigneeEnum.ROLE.getCode() + role.getRoleId()), + + // 岗位权限前缀 + Stream.ofNullable(loginUser.getDepartmentId()) + .map(post -> TaskAssigneeEnum.POST.getCode() + post), + + // 用户和部门权限 + Stream.of(String.valueOf(loginUser.getEmployeeId()), + TaskAssigneeEnum.DEPT.getCode() + loginUser.getEmployeeId() + ) + ) + .flatMap(stream -> stream) + .collect(Collectors.toList()); + } + + /** + * 获取当前办理人 + * + * @return 当前办理人 + */ + @Override + public String getHandler() { + return String.valueOf(SmartRequestUtil.getRequestUserId()); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/listener/WorkflowGlobalListener.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/listener/WorkflowGlobalListener.java new file mode 100644 index 0000000..ed5a61b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/listener/WorkflowGlobalListener.java @@ -0,0 +1,136 @@ +package net.lab1024.sa.admin.module.flow.listener; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.flow.annoation.ConditionalOnEnable; +import net.lab1024.sa.admin.module.flow.enums.BusinessStatusEnum; +import net.lab1024.sa.admin.module.flow.handler.FlowProcessEventHandler; +import net.lab1024.sa.admin.module.flow.service.FlowInstanceService; +import net.lab1024.sa.admin.module.flow.service.FlowTaskService; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.listener.GlobalListener; +import org.dromara.warm.flow.core.listener.ListenerVariable; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.springframework.stereotype.Component; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 全局任务办理监听 + * + * @author may + */ +@ConditionalOnEnable +@Component +@Slf4j +@RequiredArgsConstructor +public class WorkflowGlobalListener implements GlobalListener { + + @Resource + private FlowTaskService flowTaskService; + + @Resource + private FlowInstanceService flowInstanceService; + + private final FlowProcessEventHandler flowProcessEventHandler; + + /** + * 创建监听器,任务创建时执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void create(ListenerVariable listenerVariable) { + Instance instance = listenerVariable.getInstance(); + Definition definition = listenerVariable.getDefinition(); + String businessId = instance.getBusinessId(); + String flowStatus = instance.getFlowStatus(); + Task task = listenerVariable.getTask(); + if (task != null && BusinessStatusEnum.WAITING.getStatus().equals(flowStatus)) { + // 判断流程状态(发布审批中事件) + flowProcessEventHandler.processCreateTaskHandler(definition.getFlowCode(), task.getNodeCode(), task.getId(), businessId); + } + } + + /** + * 开始监听器,任务开始办理时执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void start(ListenerVariable listenerVariable) { + } + + /** + * 分派监听器,动态修改代办任务信息 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void assignment(ListenerVariable listenerVariable) { + } + + /** + * 完成监听器,当前任务完成后执行 + * + * @param listenerVariable 监听器变量 + */ + @Override + public void finish(ListenerVariable listenerVariable) { + Instance instance = listenerVariable.getInstance(); + Definition definition = listenerVariable.getDefinition(); + String businessId = instance.getBusinessId(); + String flowStatus = instance.getFlowStatus(); + Map params = new HashMap<>(); + FlowParams flowParams = listenerVariable.getFlowParams(); + if (ObjectUtil.isNotNull(flowParams)) { + // 历史任务扩展(通常为附件) + params.put("hisTaskExt", flowParams.getHisTaskExt()); + // 办理人 + params.put("handler", flowParams.getHandler()); + // 办理意见 + params.put("message", flowParams.getMessage()); + } + // 判断流程状态(发布:撤销,退回,作废,终止,已完成事件) + String status = determineFlowStatus(instance, flowStatus); + if (SmartStringUtil.isNotBlank(status)) { + flowProcessEventHandler.processHandler(definition.getFlowCode(), businessId, status, params, false); + } + } + + /** + * 根据流程实例和当前流程状态确定最终状态 + * + * @param instance 流程实例 + * @param flowStatus 流程实例当前状态 + * @return 流程最终状态 + */ + private String determineFlowStatus(Instance instance, String flowStatus) { + if (SmartStringUtil.isNotBlank(flowStatus) && BusinessStatusEnum.initialState(flowStatus)) { + log.info("流程实例当前状态: {}", flowStatus); + return flowStatus; + } else { + Long instanceId = instance.getId(); + List flowTasks = flowTaskService.selectByInstId(instanceId); +// if (CollUtil.isEmpty(flowTasks)) { +//// String status = BusinessStatusEnum.FINISH.getStatus(); +// // 更新流程状态为已完成 +//// flowInstanceService.updateStatus(instanceId, status); +// log.info("流程已结束,状态更新为: {}", status); +// return status; +// } + return null; + } + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/mapper/WarmFlowMapper.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/mapper/WarmFlowMapper.java new file mode 100644 index 0000000..428ee9d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/mapper/WarmFlowMapper.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.admin.module.flow.mapper; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowTaskVO; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.dromara.warm.flow.core.entity.HisTask; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; + +import java.util.List; + +/** + * warm-flow工作流Mapper接口 + * + * @author ruoyi + * @date 2024-03-07 + */ +@Mapper +public interface WarmFlowMapper { + /** + * 分页查询待办任务 + * + * @param task 条件实体 + */ + IPage toDoPage(IPage page, @Param("task") Task task); + + /** + * 获取最新的已办任务 + * + * @param hisTask + * @return + */ + IPage donePage(IPage page, @Param("hisTask") HisTask hisTask); + + /** + * 分页获取抄送任务 + * @param flowTask + * @return + */ + IPage copyPage(IPage page, @Param("task") FlowTask flowTask); + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link List} + * @author liangli + * @date 2024/8/21 17:11 + **/ + List idReverseDisplayName(@Param("ids") Long[] ids); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowDefinitionService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowDefinitionService.java new file mode 100644 index 0000000..bfb7fa8 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowDefinitionService.java @@ -0,0 +1,131 @@ +package net.lab1024.sa.admin.module.flow.service; + +import cn.hutool.core.convert.Convert; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.flow.dao.FlowDefinitionDao; +import net.lab1024.sa.admin.module.flow.domain.form.FlowDefinitionAddForm; +import net.lab1024.sa.admin.module.flow.domain.form.FlowDefinitionQueryForm; +import net.lab1024.sa.admin.module.flow.domain.form.FlowDefinitionUpdateForm; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowDefinitionVO; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowTaskVO; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.enums.PublishStatus; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.utils.page.Page; +import org.dromara.warm.flow.orm.entity.FlowDefinition; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 职务表 Service + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Service +public class FlowDefinitionService { + + @Resource + private DefService defService; + + @Resource + private FlowDefinitionDao flowDefinitionDao; + + /** + * 分页查询 + * + * @param queryForm + * @return + */ + public PageResult queryPage(FlowDefinitionQueryForm queryForm) { + FlowDefinition flowDefinition = SmartBeanUtil.copy(queryForm, FlowDefinition.class); + Page page = Page.pageOf(queryForm.getPageNum().intValue(), queryForm.getPageSize().intValue()); + page = defService.orderByCreateTime().desc().page(flowDefinition, page); + // 转换为自定义分页响应对象 + PageResult pageResult = new PageResult<>(); + pageResult.setList(SmartBeanUtil.copyList(page.getList(), FlowDefinitionVO.class)); + pageResult.setTotal(page.getTotal()); + pageResult.setPageNum( (long)page.getPageNum()); + pageResult.setPageSize( page.getTotal()); + pageResult.setPages( (long)page.getPageSize()); + return pageResult; + } + + /** + * 添加 + */ + public ResponseDTO add(FlowDefinitionAddForm addForm) { + FlowDefinition flowDefinition = SmartBeanUtil.copy(addForm, FlowDefinition.class); + flowDefinitionDao.insert(flowDefinition); + return ResponseDTO.ok(); + } + + /** + * 更新 + * + * @param updateForm + * @return + */ + public ResponseDTO update(FlowDefinitionUpdateForm updateForm) { + FlowDefinition flowDefinition = SmartBeanUtil.copy(updateForm, FlowDefinition.class); + flowDefinitionDao.updateById(flowDefinition); + return ResponseDTO.ok(); + } + + /** + * 批量删除 + * + * @param idList + * @return + */ + public ResponseDTO batchDelete(List idList) { + if (CollectionUtils.isEmpty(idList)){ + return ResponseDTO.ok(); + } + + flowDefinitionDao.deleteBatchIds(idList); + return ResponseDTO.ok(); + } + + /** + * 单个删除 + */ + public ResponseDTO delete(Long positionId) { + if (null == positionId){ + return ResponseDTO.ok(); + } + + flowDefinitionDao.deleteById(positionId); + return ResponseDTO.ok(); + } + + /** + * 分页查询 + * + * @return + */ + public List queryList() { + List list = flowDefinitionDao.queryList(Boolean.FALSE); + return list; + } + + private LambdaQueryWrapper buildQueryWrapper(FlowDefinition flowDefinition) { + LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(); + wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowCode()), FlowDefinition::getFlowCode, flowDefinition.getFlowCode()); + wrapper.like(StringUtils.isNotBlank(flowDefinition.getFlowName()), FlowDefinition::getFlowName, flowDefinition.getFlowName()); + wrapper.like(StringUtils.isNotBlank(flowDefinition.getCategory()), FlowDefinition::getCategory, flowDefinition.getCategory()); + + wrapper.orderByDesc(FlowDefinition::getCreateTime); + return wrapper; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowInstanceService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowInstanceService.java new file mode 100644 index 0000000..1f65def --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowInstanceService.java @@ -0,0 +1,78 @@ +package net.lab1024.sa.admin.module.flow.service; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowInstanceVO; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import java.util.List; +import java.util.Map; + +/** + * 流程实例 服务层 + * + * @author may + */ +public interface FlowInstanceService { + + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + * @return 结果 + */ + FlowInstanceVO queryByBusinessId(Long businessId); + + /** + * 按照业务id查询流程实例 + * + * @param businessId 业务id + * @return 结果 + */ + FlowInstance selectInstByBusinessId(String businessId); + + /** + * 按照实例id查询流程实例 + * + * @param instanceId 实例id + * @return 结果 + */ + FlowInstance selectInstById(Long instanceId); + + /** + * 按照实例id查询流程实例 + * + * @param instanceIds 实例id + * @return 结果 + */ + List selectInstListByIdList(List instanceIds); + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + * @return 结果 + */ + boolean deleteByBusinessIds(List businessIds); + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + * @return 结果 + */ + boolean deleteByInstanceIds(List instanceIds); + + /** + * 按照实例id更新状态 + * + * @param instanceId 实例id + * @param status 状态 + */ + void updateStatus(Long instanceId, String status); + + /** + * 设置流程变量 + * + * @param instanceId 实例id + * @param variable 流程变量 + */ + void setVariable(Long instanceId, Map variable); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowTaskService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowTaskService.java new file mode 100644 index 0000000..3fe3237 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/FlowTaskService.java @@ -0,0 +1,65 @@ +package net.lab1024.sa.admin.module.flow.service; + +import com.baomidou.mybatisplus.core.metadata.IPage; +import net.lab1024.sa.admin.module.flow.domain.form.ApproveTaskInsForm; +import net.lab1024.sa.admin.module.flow.domain.form.CompleteTaskForm; +import net.lab1024.sa.admin.module.flow.domain.form.StartProcessForm; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowTaskVO; +import net.lab1024.sa.admin.module.flow.domain.vo.StartProcessReturnVO; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import org.dromara.warm.flow.core.entity.HisTask; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowTask; + +import java.util.List; + +/** + * 流程执行service + * + * @author warm + * @since 2023/5/29 13:09 + */ +public interface FlowTaskService { + + /** + * 分页查询待办任务 + * + * @param task 条件实体 + * @return + */ + IPage toDoPage(IPage page, Task task); + + /** + * 获取已办任务 + * + * @param hisTask + * @return + */ + IPage donePage(IPage page, HisTask hisTask); + + IPage copyPage(IPage page, FlowTask flowTask); + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link List} + * @author liangli + * @date 2024/8/21 17:11 + **/ + List idReverseDisplayName(Long[] ids); + + StartProcessReturnVO startWorkFlow(StartProcessForm startProcessForm); + + boolean completeTask(CompleteTaskForm completeTaskForm); + + List selectByInstId(Long instanceId); + + boolean approveTaskByInstance(ApproveTaskInsForm approveTaskInsForm); + + + FlowTaskVO getTaskDetailById(Long taskId); + + FlowTaskVO getDoneTaskDetailById(Long taskId); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/HhDefService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/HhDefService.java new file mode 100644 index 0000000..d1f18a9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/HhDefService.java @@ -0,0 +1,14 @@ +package net.lab1024.sa.admin.module.flow.service; + +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; + +/** + * 流程定义service + * + * @author warm + * @since 2023/5/29 13:09 + */ +public interface HhDefService { + + Boolean interactiveType(WarmFlowInteractiveTypeVO warmFlowInteractiveTypeVo); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/FlowInstanceServiceImpl.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/FlowInstanceServiceImpl.java new file mode 100644 index 0000000..6c64d20 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/FlowInstanceServiceImpl.java @@ -0,0 +1,190 @@ +package net.lab1024.sa.admin.module.flow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.flow.annoation.ConditionalOnEnable; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowInstanceVO; +import net.lab1024.sa.admin.module.flow.handler.FlowProcessEventHandler; +import net.lab1024.sa.admin.module.flow.service.FlowInstanceService; +import net.lab1024.sa.admin.module.flow.service.FlowTaskService; +import net.lab1024.sa.base.common.exception.BusinessException; +import org.dromara.warm.flow.core.FlowEngine; +import org.dromara.warm.flow.core.constant.ExceptionCons; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.enums.NodeType; +import org.dromara.warm.flow.core.service.ChartService; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.core.utils.StreamUtils; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 流程实例 服务层实现 + * + * @author may + */ +@ConditionalOnEnable +@Slf4j +@RequiredArgsConstructor +@Service +public class FlowInstanceServiceImpl implements FlowInstanceService { + + private final InsService insService; + private final DefService defService; + private final ChartService chartService; + private final TaskService taskService; + private final FlowHisTaskMapper flowHisTaskMapper; + private final FlowInstanceMapper flowInstanceMapper; + private final FlowProcessEventHandler flowProcessEventHandler; + private final FlowTaskService flowTaskService; + + + /** + * 根据业务id查询流程实例详细信息 + * + * @param businessId 业务id + * @return 结果 + */ + @Override + public FlowInstanceVO queryByBusinessId(Long businessId) { + FlowInstance instance = this.selectInstByBusinessId(String.valueOf(businessId)); + FlowInstanceVO instanceVo = BeanUtil.toBean(instance, FlowInstanceVO.class); + Definition definition = defService.getById(instanceVo.getDefinitionId()); + instanceVo.setFlowName(definition.getFlowName()); + instanceVo.setFlowCode(definition.getFlowCode()); + instanceVo.setVersion(definition.getVersion()); + instanceVo.setFormCustom(definition.getFormCustom()); + instanceVo.setFormPath(definition.getFormPath()); + instanceVo.setCategory(definition.getCategory()); + return instanceVo; + } + + /** + * 根据业务id查询流程实例 + * + * @param businessId 业务id + */ + @Override + public FlowInstance selectInstByBusinessId(String businessId) { + return flowInstanceMapper.selectOne(new LambdaQueryWrapper().eq(FlowInstance::getBusinessId, businessId)); + } + + /** + * 按照实例id查询流程实例 + * + * @param instanceId 实例id + */ + @Override + public FlowInstance selectInstById(Long instanceId) { + return flowInstanceMapper.selectById(instanceId); + } + + /** + * 按照实例id查询流程实例 + * + * @param instanceIds 实例id + */ + @Override + public List selectInstListByIdList(List instanceIds) { + return flowInstanceMapper.selectBatchIds(instanceIds); + } + + /** + * 按照业务id删除流程实例 + * + * @param businessIds 业务id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteByBusinessIds(List businessIds) { + List flowInstances = flowInstanceMapper.selectList(new LambdaQueryWrapper().in(FlowInstance::getBusinessId, StreamUtils.toList(businessIds,Convert::toStr))); + if (CollUtil.isEmpty(flowInstances)) { + log.warn("未找到对应的流程实例信息,无法执行删除操作。"); + return false; + } + return insService.remove(StreamUtils.toList(flowInstances, FlowInstance::getId)); + } + + /** + * 按照实例id删除流程实例 + * + * @param instanceIds 实例id + */ + @Override + @Transactional(rollbackFor = Exception.class) + public boolean deleteByInstanceIds(List instanceIds) { + // 获取实例信息 + List instances = insService.getByIds(instanceIds); + if (CollUtil.isEmpty(instances)) { + log.warn("未找到对应的流程实例信息,无法执行删除操作。"); + return false; + } + // 获取定义信息 + Map definitionMap = defService.getByIds( + StreamUtils.toList(instances, Instance::getDefinitionId) + ).stream().collect(Collectors.toMap(Definition::getId, definition -> definition)); + + // 逐一触发删除事件 + instances.forEach(instance -> { + Definition definition = definitionMap.get(instance.getDefinitionId()); + if (ObjectUtil.isNull(definition)) { + log.warn("实例 ID: {} 对应的流程定义信息未找到,跳过删除事件触发。", instance.getId()); + return; + } + flowProcessEventHandler.processDeleteHandler(definition.getFlowCode(), instance.getBusinessId()); + }); + + // 删除实例 + return insService.remove(instanceIds); + } + + /** + * 按照实例id更新状态 + * + * @param instanceId 实例id + * @param status 状态 + */ + @Override + public void updateStatus(Long instanceId, String status) { + LambdaUpdateWrapper wrapper = new LambdaUpdateWrapper<>(); + wrapper.set(FlowInstance::getFlowStatus, status); + wrapper.eq(FlowInstance::getId, instanceId); + flowInstanceMapper.update(wrapper); + } + /** + * 设置流程变量 + * + * @param instanceId 实例id + * @param variable 流程变量 + */ + @Override + public void setVariable(Long instanceId, Map variable) { + Instance instance = insService.getById(instanceId); + if (instance != null) { + taskService.mergeVariable(instance, variable); + insService.updateById(instance); + } + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/FlowTaskServiceImpl.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/FlowTaskServiceImpl.java new file mode 100644 index 0000000..24a468a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/FlowTaskServiceImpl.java @@ -0,0 +1,360 @@ +package net.lab1024.sa.admin.module.flow.service.impl; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import jakarta.annotation.Resource; +import lombok.RequiredArgsConstructor; +import net.lab1024.sa.admin.module.flow.domain.form.ApproveTaskInsForm; +import net.lab1024.sa.admin.module.flow.domain.form.CompleteTaskForm; +import net.lab1024.sa.admin.module.flow.domain.form.StartProcessForm; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowCopyVO; +import net.lab1024.sa.admin.module.flow.domain.vo.FlowTaskVO; +import net.lab1024.sa.admin.module.flow.domain.vo.StartProcessReturnVO; +import net.lab1024.sa.admin.module.flow.enums.BusinessStatusEnum; +import net.lab1024.sa.admin.module.flow.handler.FlowProcessEventHandler; +import net.lab1024.sa.admin.module.flow.mapper.WarmFlowMapper; +import net.lab1024.sa.admin.module.flow.service.FlowTaskService; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; +import net.lab1024.sa.base.common.exception.BusinessException; +import net.lab1024.sa.base.common.util.*; +import org.dromara.warm.flow.core.dto.FlowParams; +import org.dromara.warm.flow.core.entity.Definition; +import org.dromara.warm.flow.core.entity.HisTask; +import org.dromara.warm.flow.core.entity.Instance; +import org.dromara.warm.flow.core.entity.Task; +import org.dromara.warm.flow.core.enums.SkipType; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.service.InsService; +import org.dromara.warm.flow.core.service.TaskService; +import org.dromara.warm.flow.orm.entity.FlowHisTask; +import org.dromara.warm.flow.orm.entity.FlowInstance; +import org.dromara.warm.flow.orm.entity.FlowTask; +import org.dromara.warm.flow.orm.mapper.FlowHisTaskMapper; +import org.dromara.warm.flow.orm.mapper.FlowInstanceMapper; +import org.dromara.warm.flow.orm.mapper.FlowTaskMapper; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import static net.lab1024.sa.admin.module.flow.contstant.FlowConstant.*; + +/** + * 流程执行SERVICEIMPL + * + * @author WARM + * @since 2023/5/29 13:09 + */ +@Service +@RequiredArgsConstructor +public class FlowTaskServiceImpl implements FlowTaskService { + + @Resource + private WarmFlowMapper flowMapper; + @Resource + private TaskService taskService; + @Resource + private InsService insService; + @Resource + private DefService defService; + @Resource + private FlowInstanceMapper flowInstanceMapper; + @Resource + private FlowTaskMapper flowTaskMapper; + @Resource + private FlowProcessEventHandler flowProcessEventHandler; + @Resource + private EmployeeService employeeService; + @Autowired + private FlowHisTaskMapper flowHisTaskMapper; + + @Override + public IPage toDoPage(IPage page, Task task) { + return flowMapper.toDoPage(page,task); + } + + @Override + public IPage donePage(IPage page, HisTask hisTask) { + return flowMapper.donePage(page,hisTask); + } + + @Override + public IPage copyPage(IPage page, FlowTask flowTask) { + return flowMapper.copyPage(page,flowTask); + } + + /** + * 根据ID反显姓名 + * + * @param ids 需要反显姓名的用户ID + * @return {@link List} + * @author liangli + * @date 2024/8/21 17:11 + **/ + @Override + public List idReverseDisplayName(Long[] ids) { + if (Objects.isNull(ids) || ids.length == 0) { + return null; + } + return flowMapper.idReverseDisplayName(ids); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public StartProcessReturnVO startWorkFlow(StartProcessForm startProcessForm) { + String businessId = startProcessForm.getBusinessId(); + if (SmartStringUtil.isEmpty(businessId)) { + throw new BusinessException("启动工作流时必须包含业务ID"); + } + // 启动流程实例(提交申请) + Map variables = startProcessForm.getVariables(); + // 流程发起人 + long userId = SmartRequestUtil.getRequestUserId(); + variables.put(INITIATOR, String.valueOf(userId)); + // 业务id + variables.put(BUSINESS_ID, businessId); + variables.put(BUSINESS_TABLE,startProcessForm.getFlowCode()); + FlowInstance flowInstance = flowInstanceMapper.selectOne(new LambdaQueryWrapper<>(FlowInstance.class) + .eq(FlowInstance::getBusinessId, businessId)); + if (ObjectUtil.isNotNull(flowInstance)) { + BusinessStatusEnum.checkStartStatus(flowInstance.getFlowStatus()); + List taskList = taskService.list(new FlowTask().setInstanceId(flowInstance.getId())); + taskService.mergeVariable(flowInstance, variables); + insService.updateById(flowInstance); + StartProcessReturnVO vo = new StartProcessReturnVO(); + vo.setProcessInstanceId(taskList.get(0).getInstanceId()); + vo.setTaskId(taskList.get(0).getId()); + return vo; + } + FlowParams flowParams = new FlowParams(); + flowParams.flowCode(startProcessForm.getFlowCode()); + flowParams.variable(startProcessForm.getVariables()); +// flowParams.flowStatus(String.valueOf(FlowStatusEnum.PENDING_SUBMIT.getValue())); + Instance instance; + try { + instance = insService.start(businessId, flowParams); + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + //更新business表中状态 + String name = flowParams.getFlowCode(); + BaseMapper bizMapper = SpringUtils.getBean(flowParams.getFlowCode()+"Dao"); + if (ObjectUtil.isNotNull(bizMapper)) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + // 动态设置更新条件(假设字段名与实体属性对应) + updateWrapper.eq(name.toLowerCase() +"_id", instance.getBusinessId()) // 主键条件 + .set("instance_id", instance.getId()) + .set("node_name",instance.getNodeName())// 更新字段 + .set("flow_status", instance.getFlowStatus()); + bizMapper.update(null, updateWrapper); + } + // 申请人执行流程 + List taskList = taskService.list(new FlowTask().setInstanceId(instance.getId())); + if (taskList.size() > 1) { + throw new BusinessException("请检查流程第一个环节是否为申请人!"); + } + //自动提交申请人流程 + ApproveTaskInsForm approveTaskInsForm = new ApproveTaskInsForm(); + approveTaskInsForm.setInstanceId(instance.getId()); + approveTaskInsForm.setVariables(variables); + approveTaskByInstance( approveTaskInsForm); + //返回执行结果 + StartProcessReturnVO vo = new StartProcessReturnVO(); + vo.setProcessInstanceId(instance.getId()); + vo.setTaskId(taskList.get(0).getId()); + return vo; + } + + @Override + @Transactional(rollbackFor = Exception.class) + public boolean completeTask(CompleteTaskForm completeTaskForm) { + try { + // 获取任务ID并查询对应的流程任务和实例信息 + Long taskId = completeTaskForm.getTaskId(); + List messageType = completeTaskForm.getMessageType(); + String notice = completeTaskForm.getNotice(); + // 获取抄送人 + List flowCopyList = completeTaskForm.getFlowCopyList(); + FlowTask flowTask = flowTaskMapper.selectById(taskId); + if (ObjectUtil.isNull(flowTask)) { + throw new BusinessException("流程任务不存在或任务已审批!"); + } + Instance ins = insService.getById(flowTask.getInstanceId()); + // 获取流程定义信息 + Definition definition = defService.getById(flowTask.getDefinitionId()); + // 检查流程状态是否为草稿、已撤销或已退回状态,若是则执行流程提交监听 + if (BusinessStatusEnum.isDraftOrCancelOrBack(ins.getFlowStatus())) { + flowProcessEventHandler.processHandler(definition.getFlowCode(), ins.getBusinessId(), ins.getFlowStatus(), null, true); + } + // 构建流程参数,包括变量、跳转类型、消息、处理人、权限等信息 + FlowParams flowParams = new FlowParams(); + flowParams.skipType(SkipType.PASS.getKey()); + flowParams.message(completeTaskForm.getMessage()); + flowParams.hisTaskExt(completeTaskForm.getFileId()); + Map variables = completeTaskForm.getVariables(); + flowParams.variable(variables); + flowParams.flowCode(variables.get("flowCode").toString()); + // 执行任务跳转,并根据返回的处理人设置下一步处理人 + Instance instance = taskService.skip(taskId, flowParams); +// this.setHandler(instance, flowTask, flowCopyList); + + //设置下一环节处理人 +// setNextHandler(ins.getId()); + //更新business表中状态 + String name = flowParams.getFlowCode(); + BaseMapper bizMapper = SpringUtils.getBean(flowParams.getFlowCode()+"Dao"); + if (ObjectUtil.isNotNull(bizMapper)) { + UpdateWrapper updateWrapper = new UpdateWrapper<>(); + // 动态设置更新条件(假设字段名与实体属性对应) + updateWrapper.eq(name.toLowerCase() +"_id", instance.getBusinessId()) // 主键条件 + .set("node_name",instance.getNodeName())// 更新字段 + .set("flow_status", instance.getFlowStatus()); + bizMapper.update(null, updateWrapper); + } + return true; + } catch (Exception e) { + throw new BusinessException(e.getMessage()); + } + } + /** + * 按照实例id审批 + * + * @param approveTaskInsForm 流程审批实例审批 + */ + @Override + public boolean approveTaskByInstance(ApproveTaskInsForm approveTaskInsForm){ + List flowTaskList =selectByInstId(approveTaskInsForm.getInstanceId()); + CompleteTaskForm completeTaskForm = new CompleteTaskForm(); + SmartBeanUtil.copyProperties(approveTaskInsForm,completeTaskForm); + + if(flowTaskList.size()>0){ + completeTaskForm.setTaskId(flowTaskList.get(0).getId()); + } + return completeTask(completeTaskForm); + } + + /** + * 按照实例id查询任务 + * + * @param instanceId 流程实例id + */ + @Override + public List selectByInstId(Long instanceId) { + return flowTaskMapper.selectList(new LambdaQueryWrapper<>(FlowTask.class) + .eq(FlowTask::getInstanceId, instanceId)); + } + /** + * 按照任务id查询任务详情 + * + * @param taskId 流程实例id + */ + @Override + public FlowTaskVO getTaskDetailById(Long taskId){ + FlowTask flowTask = flowTaskMapper.selectById(taskId); + Definition definition = defService.getById(flowTask.getDefinitionId()); + Instance flowInstance = insService.getById(flowTask.getInstanceId()); + Map variable = flowInstance.getVariableMap(); + String flowCode = variable.get("flowCode").toString(); + String initiatorId = variable.get("initiator").toString(); + String initiator = employeeService.getById(Long.parseLong(initiatorId)).getActualName(); + + BaseMapper bizMapper = SpringUtils.getBean(flowCode+"Dao"); + Map businessForm = new HashMap<>(); + if (ObjectUtil.isNotNull(bizMapper)) { + Object businessEntity = bizMapper.selectById(flowInstance.getBusinessId()); + if (ObjectUtil.isNotNull(businessEntity)) { + // 将业务实体转换为Map + businessForm = BeanUtil.beanToMap(businessEntity); + } + } + // 暂时不获取表元数据,避免复杂的依赖问题 + JSONObject businessFormMetaData = new JSONObject(); + try { + String tableName = getTableNameByFlowCode(flowCode); + if (tableName != null) { + businessFormMetaData = SmartTableMetadataUtil.getTableMetadata(tableName); + } + } catch (Exception e) { + System.err.println("获取表元数据失败: " + e.getMessage()); + } + + FlowTaskVO flowTaskVO = new FlowTaskVO(); + SmartBeanUtil.copyProperties(flowTask,flowTaskVO); + flowTaskVO.setFlowCode(definition.getFlowCode()); + flowTaskVO.setFlowName(definition.getFlowName()); + flowTaskVO.setBusinessId(flowInstance.getBusinessId()); + flowTaskVO.setInitiator(initiator); + flowTaskVO.setBusinessFormMetaData(businessFormMetaData); + flowTaskVO.setBusinessForm( businessForm); + + return flowTaskVO; + } + + /** + * 按照任务id查询任务详情 + * + * @param taskId 流程实例id + */ + @Override + public FlowTaskVO getDoneTaskDetailById(Long taskId){ + FlowHisTask flowHisTask = flowHisTaskMapper.selectById(taskId); + Definition definition = defService.getById(flowHisTask.getDefinitionId()); + Instance flowInstance = insService.getById(flowHisTask.getInstanceId()); + Map variable = flowInstance.getVariableMap(); + String flowCode = variable.get("flowCode").toString(); + String initiatorId = variable.get("initiator").toString(); + String initiator = employeeService.getById(Long.parseLong(initiatorId)).getActualName(); + + BaseMapper bizMapper = SpringUtils.getBean(flowCode+"Dao"); + Map businessForm = new HashMap<>(); + if (ObjectUtil.isNotNull(bizMapper)) { + Object businessEntity = bizMapper.selectById(flowInstance.getBusinessId()); + if (ObjectUtil.isNotNull(businessEntity)) { + // 将业务实体转换为Map + businessForm = BeanUtil.beanToMap(businessEntity); + } + } + // 暂时不获取表元数据,避免复杂的依赖问题 + JSONObject businessFormMetaData = new JSONObject(); + try { + String tableName = getTableNameByFlowCode(flowCode); + if (tableName != null) { + businessFormMetaData = SmartTableMetadataUtil.getTableMetadata(tableName); + } + } catch (Exception e) { + System.err.println("获取表元数据失败: " + e.getMessage()); + } + + FlowTaskVO flowTaskVO = new FlowTaskVO(); + SmartBeanUtil.copyProperties(flowHisTask,flowTaskVO); + flowTaskVO.setFlowName(definition.getFlowName()); + flowTaskVO.setBusinessId(flowInstance.getBusinessId()); + flowTaskVO.setInitiator(initiator); + flowTaskVO.setBusinessFormMetaData(businessFormMetaData); + flowTaskVO.setBusinessForm( businessForm); + + return flowTaskVO; + } + + + /** + * 根据flowCode映射到对应的表名 + * @param flowCode 流程代码 + * @return 表名 + */ + private String getTableNameByFlowCode(String flowCode) { + return "t_"+flowCode; + + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/HandlerSelectServiceImpl.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/HandlerSelectServiceImpl.java new file mode 100644 index 0000000..603896d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/HandlerSelectServiceImpl.java @@ -0,0 +1,183 @@ +package net.lab1024.sa.admin.module.flow.service.impl; + +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.flow.enums.TaskAssigneeEnum; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentQueryForm; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.admin.module.system.employee.domain.form.EmployeeQueryForm; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleQueryForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import net.lab1024.sa.admin.module.system.role.service.RoleService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.util.SmartDateFormatterEnum; +import net.lab1024.sa.base.common.util.SmartLocalDateUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import org.dromara.warm.flow.core.utils.MathUtil; +import org.dromara.warm.flow.ui.dto.HandlerFunDto; +import org.dromara.warm.flow.ui.dto.HandlerQuery; +import org.dromara.warm.flow.ui.dto.TreeFunDto; +import org.dromara.warm.flow.ui.service.HandlerSelectService; +import org.dromara.warm.flow.ui.vo.HandlerSelectVo; +import org.springframework.stereotype.Component; + +import java.util.Arrays; +import java.util.List; + +/** + * 流程设计器-获取办理人权限设置列表接口实现类 + * + * @author warm + */ +@Component +public class HandlerSelectServiceImpl implements HandlerSelectService { + @Resource + private EmployeeService employeeService; + + @Resource + private RoleService roleService; + + @Resource + private DepartmentService departmentService; + + /** + * 获取办理人权限设置列表tabs页签,如:用户、角色和部门等,可以返回其中一种或者多种,按业务需求决定 + * + * @return tabs页签 + */ + @Override + public List getHandlerType() { + return Arrays.asList("用户", "角色", "部门"); + } + + /** + * 获取用户列表、角色列表、部门列表等,可以返回其中一种或者多种,按业务需求决定 + * + * @param query 查询参数 + * @return 结果 + */ + @Override + public HandlerSelectVo getHandlerSelect(HandlerQuery query) { + + if ("角色".equals(query.getHandlerType())) { + return getRole(query); + } + + if ("部门".equals(query.getHandlerType())) { + return getDept(query); + } + + if ("用户".equals(query.getHandlerType())) { + return getUser(query); + } + + return new HandlerSelectVo(); + } + + /** + * 获取角色列表 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + private HandlerSelectVo getRole(HandlerQuery query) { + RoleQueryForm queryForm = new RoleQueryForm(); + queryForm.setRoleCode(query.getHandlerCode()); + queryForm.setRoleName(query.getHandlerName()); + if(SmartStringUtil.isNotEmpty(query.getBeginTime())) + queryForm.setStartTime(SmartLocalDateUtil.parseDate(query.getBeginTime(), SmartDateFormatterEnum.YMD)); + if(SmartStringUtil.isNotEmpty(query.getEndTime())) + queryForm.setEndTime(SmartLocalDateUtil.parseDate(query.getEndTime(), SmartDateFormatterEnum.YMD)); + // 处理分页参数,避免空指针异常 + queryForm.setPageNum(query.getPageNum() != null ? (long)query.getPageNum() : 1L); + queryForm.setPageSize(query.getPageSize() != null ? (long)query.getPageSize() : 10L); + // 查询角色列表 + PageResult pageResult = roleService.queryPage(queryForm); + + // 业务系统数据,转成组件内部能够显示的数据, total是业务数据总数,用于分页显示 + HandlerFunDto handlerFunDto = new HandlerFunDto<>(pageResult.getList(), pageResult.getTotal()) + // 以下设置获取内置变量的Function + .setStorageId(role -> TaskAssigneeEnum.ROLE.getCode() + role.getRoleId()) // 前面拼接role: 是为了防止用户、角色的主键重复 + .setHandlerCode(RoleVO::getRoleCode) // 权限编码 + .setHandlerName(RoleVO::getRoleName) // 权限名称 + .setCreateTime(role -> SmartLocalDateUtil.format(role.getCreateTime(), SmartDateFormatterEnum.YMD)); + + return getHandlerSelectVo(handlerFunDto); + } + + /** + * 获取用户列表 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + private HandlerSelectVo getDept(HandlerQuery query) { + DepartmentQueryForm queryForm = new DepartmentQueryForm(); + queryForm.setName(query.getHandlerName()); + if(SmartStringUtil.isNotEmpty(query.getBeginTime())) + queryForm.setStartTime(SmartLocalDateUtil.parseDate(query.getBeginTime(), SmartDateFormatterEnum.YMD)); + if(SmartStringUtil.isNotEmpty(query.getEndTime())) + queryForm.setEndTime(SmartLocalDateUtil.parseDate(query.getEndTime(), SmartDateFormatterEnum.YMD)); + // 处理分页参数,避免空指针异常 + queryForm.setPageNum(query.getPageNum() != null ? (long)query.getPageNum() : 1L); + queryForm.setPageSize(query.getPageSize() != null ? (long)query.getPageSize() : 10L); + // 查询部门列表 + PageResult deptPage = departmentService.queryPage(queryForm); + // 业务系统数据,转成组件内部能够显示的数据, total是业务数据总数,用于分页显示 + HandlerFunDto handlerFunDto = new HandlerFunDto<>(deptPage.getList(), deptPage.getTotal()) + .setStorageId(dept ->TaskAssigneeEnum.DEPT.getCode() + dept.getDepartmentId()) // 前面拼接dept: 是为了防止用户、部门的主键重复 + .setHandlerName(DepartmentVO::getName) // 权限名称 + .setCreateTime(dept -> SmartLocalDateUtil.format(dept.getCreateTime(), SmartDateFormatterEnum.YMD)); + + return getHandlerSelectVo(handlerFunDto); + + } + + /** + * 获取用户列表, 同时构建左侧部门树状结构 + * + * @param query 查询条件 + * @return HandlerSelectVo + */ + private HandlerSelectVo getUser(HandlerQuery query) { + EmployeeQueryForm employeeQueryForm = new EmployeeQueryForm(); + if (SmartStringUtil.isNotEmpty(query.getHandlerCode())) + employeeQueryForm.setKeyword(query.getHandlerCode()); + else if (SmartStringUtil.isNotEmpty(query.getHandlerName())) + employeeQueryForm.setKeyword(query.getHandlerName()); + // 办理人用户选择列表,需要展示左侧树状部门,所以可能会通过部门id + if (MathUtil.isNumeric(query.getGroupId())) { + employeeQueryForm.setDepartmentId(Long.valueOf(query.getGroupId())); + } + if(SmartStringUtil.isNotEmpty(query.getBeginTime())) + employeeQueryForm.setStartTime(SmartLocalDateUtil.parseDate(query.getBeginTime(), SmartDateFormatterEnum.YMD)); + if(SmartStringUtil.isNotEmpty(query.getEndTime())) + employeeQueryForm.setEndTime(SmartLocalDateUtil.parseDate(query.getEndTime(), SmartDateFormatterEnum.YMD)); + // 处理分页参数,避免空指针异常 + employeeQueryForm.setPageNum(query.getPageNum() != null ? (long)query.getPageNum() : 1L); + employeeQueryForm.setPageSize(query.getPageSize() != null ? (long)query.getPageSize() : 10L); + // 查询用户列表 + PageResult employeeVOPageResult = employeeService.queryEmployeePage(employeeQueryForm); + + // 查询部门列表,构建树状结构 + List deptList = departmentService.listAll(); + + // 业务系统数据,转成组件内部能够显示的数据, total是业务数据总数,用于分页显示 + HandlerFunDto handlerFunDto = new HandlerFunDto<>(employeeVOPageResult.getList(), employeeVOPageResult.getTotal()) + .setStorageId(employee -> employee.getEmployeeId().toString()) + .setHandlerCode(EmployeeVO::getLoginName) // 权限编码 + .setHandlerName(EmployeeVO::getActualName) // 权限名称 + .setCreateTime(employee -> SmartLocalDateUtil.format(employee.getCreateTime(), SmartDateFormatterEnum.YMD_HMS)) + .setGroupName(employee -> employee.getDepartmentName() != null ? employee.getDepartmentName() : ""); + + // 业务系统机构,转成组件内部左侧树列表能够显示的数据 + TreeFunDto treeFunDto = new TreeFunDto<>(deptList) + .setId(dept -> dept.getDepartmentId().toString()) // 左侧树ID + .setName(DepartmentVO::getName) // 左侧树名称 + .setParentId(dept -> dept.getParentId().toString()); // 左侧树父级ID + + return getHandlerSelectVo(handlerFunDto, treeFunDto); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/HhDefServiceImpl.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/HhDefServiceImpl.java new file mode 100644 index 0000000..bb34c5b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/HhDefServiceImpl.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.admin.module.flow.service.impl; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.flow.adapter.WarmFlowAdapter; +import net.lab1024.sa.admin.module.flow.service.HhDefService; +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.base.common.util.SpringUtils; +import org.dromara.warm.flow.core.service.DefService; +import org.dromara.warm.flow.core.service.NodeService; +import org.dromara.warm.flow.core.service.SkipService; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * 流程定义serviceImpl + * + * @author warm + * @since 2023/5/29 13:09 + */ +@Service +public class HhDefServiceImpl implements HhDefService { + + @Resource + private DefService defService; + + @Resource + private NodeService nodeService; + + @Resource + private SkipService skipService; + + private static final List WARM_FLOW_ADAPTERS = new ArrayList<>(); + + /** + * 初始化方法 + */ + @PostConstruct + public void initMethod() { + Map beanNamesForType = SpringUtils.getBeanNamesForType(WarmFlowAdapter.class); + WARM_FLOW_ADAPTERS.addAll(beanNamesForType.values()); + } + + @Transactional(rollbackFor = Exception.class) + @Override + public Boolean interactiveType(WarmFlowInteractiveTypeVO warmFlowInteractiveTypeVo) { + Integer operatorType = warmFlowInteractiveTypeVo.getOperatorType(); + for (WarmFlowAdapter warmFlowAdapter : WARM_FLOW_ADAPTERS) { + if (warmFlowAdapter.isAdapter(operatorType)) { + return warmFlowAdapter.adapter(warmFlowInteractiveTypeVo); + } + } + return false; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/NodeExtServiceImpl.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/NodeExtServiceImpl.java new file mode 100644 index 0000000..7d7e2fb --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/flow/service/impl/NodeExtServiceImpl.java @@ -0,0 +1,136 @@ +package net.lab1024.sa.admin.module.flow.service.impl; + +import org.dromara.warm.flow.ui.service.NodeExtService; +import org.dromara.warm.flow.ui.vo.NodeExt; +import org.dromara.warm.flow.ui.vo.NodeExt.ChildNode; +import org.dromara.warm.flow.ui.vo.NodeExt.DictItem; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +/** + * 流程设计器-节点扩展属性 + * + * @author warm + */ +@Component +public class NodeExtServiceImpl implements NodeExtService { + + @Override + public List getNodeExt() { + List nodeExts = new ArrayList<>(); + +// // 第一个 NodeExt 对象 +// NodeExt nodeExt1 = new NodeExt(); +// nodeExt1.setCode("base"); +// nodeExt1.setDesc("基础设置扩展属性"); +// nodeExt1.setType(1); +// +// List childs1 = new ArrayList<>(); +// +// // 第一个 ChildNode 对象 +// ChildNode childNode1 = new ChildNode(); +// childNode1.setCode("base1"); +// childNode1.setLabel("输入框"); +// childNode1.setDesc("基础设置扩展属性1"); +// childNode1.setType(1); +// childNode1.setMust(false); +// childs1.add(childNode1); +// +// // 第二个 ChildNode 对象 +// ChildNode childNode2 = new ChildNode(); +// childNode2.setCode("base2"); +// childNode2.setLabel("文本域"); +// childNode2.setDesc("基础设置扩展属性2"); +// childNode2.setType(2); +// childNode2.setMust(false); +// childs1.add(childNode2); +// +// // 第三个 ChildNode 对象 +// ChildNode childNode3 = new ChildNode(); +// childNode3.setCode("base3"); +// childNode3.setLabel("下一步角色"); +// childNode3.setDesc("基础设置扩展属性3"); +// childNode3.setType(3); +// childNode3.setMust(false); +// +// List dictItems3 = new ArrayList<>(); +// dictItems3.add(new DictItem("普通角色", "common", true)); +// dictItems3.add(new DictItem("领导", "leader")); +// dictItems3.add(new DictItem("员工", "yuangong")); +// childNode3.setDict(dictItems3); +// childs1.add(childNode3); + +// // 第四个 ChildNode 对象 +// ChildNode childNode4 = new ChildNode(); +// childNode4.setCode("base4"); +// childNode4.setLabel("单选框"); +// childNode4.setDesc("基础设置扩展属性4"); +// childNode4.setType(4); +// childNode4.setMust(false); +// +// List dictItems4 = new ArrayList<>(); +// dictItems4.add(new DictItem("是否弹窗选人", "1", true)); +// dictItems4.add(new DictItem("是否能委托", "2", true)); +// dictItems4.add(new DictItem("是否能转办", "3")); +// dictItems4.add(new DictItem("是否能抄送", "4")); +// dictItems4.add(new DictItem("是否显示退回", "5")); +// dictItems4.add(new DictItem("是否能加签", "6")); +// dictItems4.add(new DictItem("是否能减签", "7")); +// childNode4.setDict(dictItems4); +// childs1.add(childNode4); +// +// nodeExt1.setChilds(childs1); +// nodeExts.add(nodeExt1); + + // 第二个 NodeExt 对象 + NodeExt nodeExt2 = new NodeExt(); + nodeExt2.setCode("new_tabs"); + nodeExt2.setName("按钮权限"); + nodeExt2.setDesc("按钮权限设置"); + nodeExt2.setType(2); + + List childs2 = new ArrayList<>(); + + // 第一个 ChildNode 对象 + ChildNode childNode5 = new ChildNode(); + childNode5.setCode("new_tabs1"); + childNode5.setLabel("复选框"); + childNode5.setDesc("按钮权限1"); + childNode5.setType(4); + childNode5.setMust(false); + childNode5.setMultiple(true); + + List dictItems5 = new ArrayList<>(); + dictItems5.add(new DictItem("是否弹窗选人", "1")); + dictItems5.add(new DictItem("是否能委托", "2")); + dictItems5.add(new DictItem("是否能转办", "3", true)); + dictItems5.add(new DictItem("是否能抄送", "4", true)); + dictItems5.add(new DictItem("是否显示退回", "5")); + dictItems5.add(new DictItem("是否能加签", "6")); + dictItems5.add(new DictItem("是否能减签", "7")); + childNode5.setDict(dictItems5); + childs2.add(childNode5); + + ChildNode childNode6 = new ChildNode(); + childNode6.setCode("new_tabs2"); + childNode6.setLabel("下拉选-多选"); + childNode6.setDesc("基础设置扩展属性3"); + childNode6.setType(3); + childNode6.setMust(false); + childNode6.setMultiple(true); + + List dictItems6 = new ArrayList<>(); + dictItems6.add(new DictItem("选项A", "1", true)); + dictItems6.add(new DictItem("选项B", "2")); + dictItems6.add(new DictItem("选项C", "3")); + childNode6.setDict(dictItems6); + childs2.add(childNode6); + + nodeExt2.setChilds(childs2); + nodeExts.add(nodeExt2); + + return nodeExts; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScope.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScope.java new file mode 100644 index 0000000..a75220e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScope.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.admin.module.system.datascope; + + +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeWhereInTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.strategy.AbstractDataScopeStrategy; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 数据范围 + * + * @Date 2022-03-18 20:59:17 + * @Author wzh + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface DataScope { + + DataScopeTypeEnum dataScopeType() ; + + DataScopeWhereInTypeEnum whereInType() default DataScopeWhereInTypeEnum.EMPLOYEE; + + /** + * DataScopeWhereInTypeEnum.CUSTOM_STRATEGY类型 才可使用joinSqlImplClazz属性 + */ + Class joinSqlImplClazz() default AbstractDataScopeStrategy.class; + + /** + * 多个参数已逗号分隔,本属性主要用于joinSqlImplClazz 实现类跟进参数进行不同的范围控制,如不使用CUSTOM_STRATEGY,可不做配置 + */ + String paramName() default ""; + /** + * + * 第几个where 条件 从0开始 + */ + int whereIndex() default 0; + + /** + * DataScopeWhereInTypeEnum为CUSTOM_STRATEGY类型时,此属性无效 + */ + String joinSql() default ""; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScopeController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScopeController.java new file mode 100644 index 0000000..dad539b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/DataScopeController.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.admin.module.system.datascope; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeAndViewTypeVO; +import net.lab1024.sa.admin.module.system.datascope.service.DataScopeService; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 查询支持的数据范围类型 + * + * @Date 2022-03-18 20:59:17 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_DATA_SCOPE) +public class DataScopeController { + + @Resource + private DataScopeService dataScopeService; + + @Operation(summary = "获取当前系统所配置的所有数据范围 @author 罗伊") + @GetMapping("/dataScope/list") + public ResponseDTO> dataScopeList() { + return dataScopeService.dataScopeList(); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/MyBatisPlugin.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/MyBatisPlugin.java new file mode 100644 index 0000000..f4baa4a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/MyBatisPlugin.java @@ -0,0 +1,183 @@ +package net.lab1024.sa.admin.module.system.datascope; + +import cn.hutool.core.util.StrUtil; +import com.google.common.collect.Maps; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeSqlConfig; +import net.lab1024.sa.admin.module.system.datascope.service.DataScopeSqlConfigService; +import net.lab1024.sa.base.common.domain.DataScopePlugin; +import org.apache.commons.lang3.StringUtils; +import org.apache.ibatis.mapping.*; +import org.apache.ibatis.plugin.Intercepts; +import org.apache.ibatis.plugin.Invocation; +import org.apache.ibatis.plugin.Plugin; +import org.apache.ibatis.plugin.Signature; +import org.apache.ibatis.session.ResultHandler; +import org.apache.ibatis.session.RowBounds; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.Map; +import java.util.Properties; + +/** + * mybaits sql 拦截 + * + * @Date 2022-03-18 20:59:17 + * @Author wzh + */ +@Intercepts({@Signature(type = org.apache.ibatis.executor.Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})}) +@Component +public class MyBatisPlugin extends DataScopePlugin { + + @Resource + private ApplicationContext applicationContext; + + @Override + public Object intercept(Invocation invocation) throws Throwable { + + MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0]; + Object parameter = invocation.getArgs()[1]; + + BoundSql boundSql = mappedStatement.getBoundSql(parameter); + String originalSql = boundSql.getSql().trim(); + String id = mappedStatement.getId(); + List methodStrList = StrUtil.split(id, "."); + String path = methodStrList.get(methodStrList.size() - 2) + "." + methodStrList.get(methodStrList.size() - 1); + DataScopeSqlConfigService dataScopeSqlConfigService = this.dataScopeSqlConfigService(); + if (dataScopeSqlConfigService == null) { + return invocation.proceed(); + } + DataScopeSqlConfig sqlConfigDTO = dataScopeSqlConfigService.getSqlConfig(path); + if (sqlConfigDTO != null) { + Map paramMap = this.getParamList(sqlConfigDTO.getParamName(), parameter); + BoundSql newBoundSql = copyFromBoundSql(mappedStatement, boundSql, this.joinSql(originalSql, paramMap, sqlConfigDTO)); + ParameterMap map = mappedStatement.getParameterMap(); + MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql), map); + invocation.getArgs()[0] = newMs; + } + + Object obj = invocation.proceed(); + return obj; + } + + + private Map getParamList(String paramName, Object parameter) { + Map paramMap = Maps.newHashMap(); + if (StringUtils.isEmpty(paramName)) { + return paramMap; + } + if (parameter == null) { + return paramMap; + } + if (parameter instanceof Map) { + String[] paramNameArray = paramName.split(","); + Map parameterMap = (Map) parameter; + for (String param : paramNameArray) { + if(parameterMap.containsKey(param)){ + paramMap.put(param, parameterMap.get(param)); + } + } + } + return paramMap; + } + + private String joinSql(String sql, Map paramMap, DataScopeSqlConfig sqlConfigDTO) { + if (null == sqlConfigDTO) { + return sql; + } + String appendSql = this.dataScopeSqlConfigService().getJoinSql(paramMap, sqlConfigDTO); + if (StringUtils.isEmpty(appendSql)) { + return sql; + } + Integer appendSqlWhereIndex = sqlConfigDTO.getWhereIndex(); + String where = "where"; + String order = "order by"; + String group = "group by"; + int whereIndex = StringUtils.ordinalIndexOf(sql.toLowerCase(), where, appendSqlWhereIndex + 1); + int orderIndex = sql.toLowerCase().indexOf(order); + int groupIndex = sql.toLowerCase().indexOf(group); + if (whereIndex > -1) { + String subSql = sql.substring(0, whereIndex + where.length() + 1); + subSql = subSql + " " + appendSql + " AND " + sql.substring(whereIndex + where.length() + 1); + return subSql; + } + + if (groupIndex > -1) { + String subSql = sql.substring(0, groupIndex); + subSql = subSql + " where " + appendSql + " " + sql.substring(groupIndex); + return subSql; + } + if (orderIndex > -1) { + String subSql = sql.substring(0, orderIndex); + subSql = subSql + " where " + appendSql + " " + sql.substring(orderIndex); + return subSql; + } + sql += " where " + appendSql; + return sql; + } + + public DataScopeSqlConfigService dataScopeSqlConfigService() { + return (DataScopeSqlConfigService) applicationContext.getBean("dataScopeSqlConfigService"); + } + + public class BoundSqlSqlSource implements SqlSource { + + BoundSql boundSql; + + public BoundSqlSqlSource(BoundSql boundSql) { + this.boundSql = boundSql; + } + + @Override + public BoundSql getBoundSql(Object parameterObject) { + return boundSql; + } + } + + /** + * 复制MappedStatement对象 + */ + private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource, ParameterMap parameterMap) { + + MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType()); + builder.resource(ms.getResource()); + builder.fetchSize(ms.getFetchSize()); + builder.statementType(ms.getStatementType()); + builder.keyGenerator(ms.getKeyGenerator()); + builder.timeout(ms.getTimeout()); + builder.parameterMap(parameterMap); + builder.resultMaps(ms.getResultMaps()); + builder.resultSetType(ms.getResultSetType()); + builder.cache(ms.getCache()); + builder.flushCacheRequired(ms.isFlushCacheRequired()); + builder.useCache(ms.isUseCache()); + return builder.build(); + } + + /** + * 复制BoundSql对象 + */ + private BoundSql copyFromBoundSql(MappedStatement ms, BoundSql boundSql, String sql) { + BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), sql, boundSql.getParameterMappings(), boundSql.getParameterObject()); + for (ParameterMapping mapping : boundSql.getParameterMappings()) { + String prop = mapping.getProperty(); + if (boundSql.hasAdditionalParameter(prop)) { + newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop)); + } + } + return newBoundSql; + } + + @Override + public Object plugin(Object arg0) { + return Plugin.wrap(arg0, this); + } + + @Override + public void setProperties(Properties arg0) { + + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeTypeEnum.java new file mode 100644 index 0000000..b750006 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeTypeEnum.java @@ -0,0 +1,53 @@ +package net.lab1024.sa.admin.module.system.datascope.constant; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 数据范围 类型 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +public enum DataScopeTypeEnum implements BaseEnum { + + /** + * 系统通知 + */ + NOTICE(1, 20, "系统通知", "系统通知数据范围"), + ; + + private final Integer value; + + private final Integer sort; + + private final String name; + + private final String desc; + + DataScopeTypeEnum(Integer value, Integer sort, String name, String desc) { + this.value = value; + this.sort = sort; + this.name = name; + this.desc = desc; + } + + @Override + public Integer getValue() { + return value; + } + + public Integer getSort() { + return sort; + } + + @Override + public String getDesc() { + return desc; + } + + public String getName() { + return name; + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeViewTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeViewTypeEnum.java new file mode 100644 index 0000000..bb9608f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeViewTypeEnum.java @@ -0,0 +1,62 @@ +package net.lab1024.sa.admin.module.system.datascope.constant; + + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + + +/** + * 数据可见范围类型 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +public enum DataScopeViewTypeEnum implements BaseEnum { + + /** + * 本人 + */ + ME(0, 0, "本人"), + + /** + * 部门 + */ + DEPARTMENT(1, 5, "本部门"), + + /** + * 本部门及下属子部门 + */ + DEPARTMENT_AND_SUB(2, 10, "本部门及下属子部门"), + + /** + * 全部 + */ + ALL(10, 100, "全部"); + + + + private final Integer value; + private final Integer level; + private final String desc; + + DataScopeViewTypeEnum(Integer value, Integer level, String desc) { + this.value = value; + this.level = level; + this.desc = desc; + } + + @Override + public Integer getValue() { + return value; + } + + public Integer getLevel() { + return level; + } + + @Override + public String getDesc() { + return desc; + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeWhereInTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeWhereInTypeEnum.java new file mode 100644 index 0000000..c1ca7b1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/constant/DataScopeWhereInTypeEnum.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.admin.module.system.datascope.constant; + + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 数据范围 sql where + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +public enum DataScopeWhereInTypeEnum implements BaseEnum { + + /** + * 以员工IN + */ + EMPLOYEE(0, "以员工IN"), + + /** + * 以部门IN + */ + DEPARTMENT(1, "以部门IN"), + + /** + * 自定义策略 + */ + CUSTOM_STRATEGY(2, "自定义策略"); + + private final Integer value; + private final String desc; + + DataScopeWhereInTypeEnum(Integer value, String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public Integer getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeAndViewTypeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeAndViewTypeVO.java new file mode 100644 index 0000000..3038d8e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeAndViewTypeVO.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.system.datascope.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 数据范围 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +@Data +public class DataScopeAndViewTypeVO { + + @Schema(description = "数据范围类型") + private Integer dataScopeType; + + @Schema(description = "数据范围名称") + private String dataScopeTypeName; + + @Schema(description = "描述") + private String dataScopeTypeDesc; + + @Schema(description = "顺序") + private Integer dataScopeTypeSort; + + @Schema(description = "可见范围列表") + private List viewTypeList; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeDTO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeDTO.java new file mode 100644 index 0000000..760cad0 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeDTO.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.admin.module.system.datascope.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +/** + * 数据范围 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +@Data +@Builder +public class DataScopeDTO { + + @Schema(description = "数据范围类型") + private Integer dataScopeType; + + @Schema(description = "数据范围名称") + private String dataScopeTypeName; + + @Schema(description = "描述") + private String dataScopeTypeDesc; + + @Schema(description = "顺序") + private Integer dataScopeTypeSort; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeSqlConfig.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeSqlConfig.java new file mode 100644 index 0000000..1ed7aa3 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeSqlConfig.java @@ -0,0 +1,38 @@ +package net.lab1024.sa.admin.module.system.datascope.domain; + +import lombok.Data; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeWhereInTypeEnum; + +/** + * 数据范围 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +@Data +public class DataScopeSqlConfig { + + /** + * 数据范围类型 + * {@link DataScopeTypeEnum} + */ + private DataScopeTypeEnum dataScopeType; + + /** + * join sql 具体实现类 + */ + private Class joinSqlImplClazz; + + private String joinSql; + + private Integer whereIndex; + + private String paramName; + + /** + * whereIn类型 + * {@link DataScopeWhereInTypeEnum} + */ + private DataScopeWhereInTypeEnum dataScopeWhereInType; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeViewTypeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeViewTypeVO.java new file mode 100644 index 0000000..ad567d6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/domain/DataScopeViewTypeVO.java @@ -0,0 +1,25 @@ +package net.lab1024.sa.admin.module.system.datascope.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +/** + * 数据可见范围 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +@Data +@Builder +public class DataScopeViewTypeVO { + + @Schema(description = "可见范围") + private Integer viewType; + + @Schema(description = "可见范围名称") + private String viewTypeName; + + @Schema(description = "级别,用于表示范围大小") + private Integer viewTypeLevel; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.java new file mode 100644 index 0000000..5824916 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeService.java @@ -0,0 +1,68 @@ +package net.lab1024.sa.admin.module.system.datascope.service; + +import com.google.common.collect.Lists; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeAndViewTypeVO; +import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeDTO; +import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeViewTypeVO; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.springframework.stereotype.Service; + +import java.util.Comparator; +import java.util.List; + +/** + * 数据范围 保存 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +@Service +public class DataScopeService { + + /** + * 获取所有可以进行数据范围配置的信息 + */ + public ResponseDTO> dataScopeList() { + List dataScopeList = this.getDataScopeType(); + List dataScopeAndTypeList = SmartBeanUtil.copyList(dataScopeList, DataScopeAndViewTypeVO.class); + List typeList = this.getViewType(); + dataScopeAndTypeList.forEach(e -> { + e.setViewTypeList(typeList); + }); + return ResponseDTO.ok(dataScopeAndTypeList); + } + + /** + * 获取当前系统存在的数据可见范围 + */ + public List getViewType() { + List viewTypeList = Lists.newArrayList(); + DataScopeViewTypeEnum[] enums = DataScopeViewTypeEnum.class.getEnumConstants(); + DataScopeViewTypeVO dataScopeViewTypeDTO; + for (DataScopeViewTypeEnum viewTypeEnum : enums) { + dataScopeViewTypeDTO = DataScopeViewTypeVO.builder().viewType(viewTypeEnum.getValue()).viewTypeLevel(viewTypeEnum.getLevel()).viewTypeName(viewTypeEnum.getDesc()).build(); + viewTypeList.add(dataScopeViewTypeDTO); + } + Comparator comparator = (h1, h2) -> h1.getViewTypeLevel().compareTo(h2.getViewTypeLevel()); + viewTypeList.sort(comparator); + return viewTypeList; + } + + public List getDataScopeType() { + List dataScopeTypeList = Lists.newArrayList(); + DataScopeTypeEnum[] enums = DataScopeTypeEnum.class.getEnumConstants(); + DataScopeDTO dataScopeDTO; + for (DataScopeTypeEnum typeEnum : enums) { + dataScopeDTO = + DataScopeDTO.builder().dataScopeType(typeEnum.getValue()).dataScopeTypeDesc(typeEnum.getDesc()).dataScopeTypeName(typeEnum.getName()).dataScopeTypeSort(typeEnum.getSort()).build(); + dataScopeTypeList.add(dataScopeDTO); + } + Comparator comparator = (h1, h2) -> h1.getDataScopeTypeSort().compareTo(h2.getDataScopeTypeSort()); + dataScopeTypeList.sort(comparator); + return dataScopeTypeList; + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeSqlConfigService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeSqlConfigService.java new file mode 100644 index 0000000..77d08cb --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeSqlConfigService.java @@ -0,0 +1,146 @@ +package net.lab1024.sa.admin.module.system.datascope.service; + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.AdminApplication; +import net.lab1024.sa.admin.module.system.datascope.DataScope; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeWhereInTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeSqlConfig; +import net.lab1024.sa.admin.module.system.datascope.strategy.AbstractDataScopeStrategy; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.reflections.Reflections; +import org.reflections.scanners.MethodAnnotationsScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * sql配置 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +@Slf4j +@Service +public class DataScopeSqlConfigService { + + /** + * 注解joinsql 参数 + */ + private static final String EMPLOYEE_PARAM = "#employeeIds"; + + private static final String DEPARTMENT_PARAM = "#departmentIds"; + + /** + * 用于拼接查看本人数据范围的 SQL + */ + private static final String CREATE_USER_ID_EQUALS = "create_user_id = "; + + private final ConcurrentHashMap dataScopeMethodMap = new ConcurrentHashMap<>(); + + @Resource + private DataScopeViewService dataScopeViewService; + + @Resource + private ApplicationContext applicationContext; + + + @PostConstruct + private void initDataScopeMethodMap() { + this.refreshDataScopeMethodMap(); + } + + /** + * 刷新 所有添加数据范围注解的接口方法配置 + */ + private Map refreshDataScopeMethodMap() { + Reflections reflections = new Reflections(new ConfigurationBuilder().setUrls(ClasspathHelper.forPackage(AdminApplication.COMPONENT_SCAN)).setScanners(new MethodAnnotationsScanner())); + Set methods = reflections.getMethodsAnnotatedWith(DataScope.class); + for (Method method : methods) { + DataScope dataScopeAnnotation = method.getAnnotation(DataScope.class); + if (dataScopeAnnotation != null) { + DataScopeSqlConfig configDTO = new DataScopeSqlConfig(); + configDTO.setDataScopeType(dataScopeAnnotation.dataScopeType()); + configDTO.setJoinSql(dataScopeAnnotation.joinSql()); + configDTO.setWhereIndex(dataScopeAnnotation.whereIndex()); + configDTO.setDataScopeWhereInType(dataScopeAnnotation.whereInType()); + configDTO.setParamName(dataScopeAnnotation.paramName()); + configDTO.setJoinSqlImplClazz(dataScopeAnnotation.joinSqlImplClazz()); + dataScopeMethodMap.put(method.getDeclaringClass().getSimpleName() + "." + method.getName(), configDTO); + } + } + return dataScopeMethodMap; + } + + /** + * 根据调用的方法获取,此方法的配置信息 + */ + public DataScopeSqlConfig getSqlConfig(String method) { + return this.dataScopeMethodMap.get(method); + } + + /** + * 组装需要拼接的sql + */ + public String getJoinSql(Map paramMap, DataScopeSqlConfig sqlConfigDTO) { + Long employeeId = SmartRequestUtil.getRequestUserId(); + if (employeeId == null) { + return ""; + } + + DataScopeTypeEnum dataScopeTypeEnum = sqlConfigDTO.getDataScopeType(); + DataScopeViewTypeEnum viewTypeEnum = dataScopeViewService.getEmployeeDataScopeViewType(dataScopeTypeEnum, employeeId); + + // 数据权限设置为仅本人可见时 直接返回 create_user_id = employeeId + if (DataScopeViewTypeEnum.ME == viewTypeEnum) { + return CREATE_USER_ID_EQUALS + employeeId; + } + + String joinSql = sqlConfigDTO.getJoinSql(); + + if (DataScopeWhereInTypeEnum.CUSTOM_STRATEGY == sqlConfigDTO.getDataScopeWhereInType()) { + Class strategyClass = sqlConfigDTO.getJoinSqlImplClazz(); + if (strategyClass == null) { + log.warn("data scope custom strategy class is null"); + return ""; + } + AbstractDataScopeStrategy powerStrategy = (AbstractDataScopeStrategy) applicationContext.getBean(sqlConfigDTO.getJoinSqlImplClazz()); + if (powerStrategy == null) { + log.warn("data scope custom strategy class:{} ,bean is null", sqlConfigDTO.getJoinSqlImplClazz()); + return ""; + } + return powerStrategy.getCondition(viewTypeEnum, paramMap, sqlConfigDTO); + } + if (DataScopeWhereInTypeEnum.EMPLOYEE == sqlConfigDTO.getDataScopeWhereInType()) { + List canViewEmployeeIds = dataScopeViewService.getCanViewEmployeeId(viewTypeEnum, employeeId); + if (CollectionUtils.isEmpty(canViewEmployeeIds)) { + return ""; + } + String employeeIds = StringUtils.join(canViewEmployeeIds, ","); + String sql = joinSql.replaceAll(EMPLOYEE_PARAM, employeeIds); + return sql; + } + if (DataScopeWhereInTypeEnum.DEPARTMENT == sqlConfigDTO.getDataScopeWhereInType()) { + List canViewDepartmentIds = dataScopeViewService.getCanViewDepartmentId(viewTypeEnum, employeeId); + if (CollectionUtils.isEmpty(canViewDepartmentIds)) { + return ""; + } + String departmentIds = StringUtils.join(canViewDepartmentIds, ","); + String sql = joinSql.replaceAll(DEPARTMENT_PARAM, departmentIds); + return sql; + } + return ""; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeViewService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeViewService.java new file mode 100644 index 0000000..0a602a3 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/service/DataScopeViewService.java @@ -0,0 +1,143 @@ +package net.lab1024.sa.admin.module.system.datascope.service; + +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.role.dao.RoleDataScopeDao; +import net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleDataScopeEntity; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 数据范围 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +@Service +public class DataScopeViewService { + + @Resource + private RoleEmployeeDao roleEmployeeDao; + + @Resource + private RoleDataScopeDao roleDataScopeDao; + + @Resource + private EmployeeDao employeeDao; + + @Resource + private DepartmentService departmentService; + + /** + * 获取某人可以查看的所有人员数据 + */ + public List getCanViewEmployeeId(DataScopeViewTypeEnum viewType, Long employeeId) { + if (DataScopeViewTypeEnum.ME == viewType) { + return this.getMeEmployeeIdList(employeeId); + } + if (DataScopeViewTypeEnum.DEPARTMENT == viewType) { + return this.getDepartmentEmployeeIdList(employeeId); + } + if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) { + return this.getDepartmentAndSubEmployeeIdList(employeeId); + } + // 可以查看所有员工数据 + return Lists.newArrayList(); + } + + /** + * 获取某人可以查看的所有部门数据 + */ + public List getCanViewDepartmentId(DataScopeViewTypeEnum viewType, Long employeeId) { + if (DataScopeViewTypeEnum.ME == viewType) { + // 数据可见范围类型为本人时 不可以查看任何部门数据 + return Lists.newArrayList(0L); + } + if (DataScopeViewTypeEnum.DEPARTMENT == viewType) { + return this.getMeDepartmentIdList(employeeId); + } + if (DataScopeViewTypeEnum.DEPARTMENT_AND_SUB == viewType) { + return this.getDepartmentAndSubIdList(employeeId); + } + // 可以查看所有部门数据 + return Lists.newArrayList(); + } + + public List getMeDepartmentIdList(Long employeeId) { + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + return Lists.newArrayList(employeeEntity.getDepartmentId()); + } + + public List getDepartmentAndSubIdList(Long employeeId) { + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + return departmentService.selfAndChildrenIdList(employeeEntity.getDepartmentId()); + } + + /** + * 根据员工id 获取各数据范围最大的可见范围 map + */ + public DataScopeViewTypeEnum getEmployeeDataScopeViewType(DataScopeTypeEnum dataScopeTypeEnum, Long employeeId) { + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + if (employeeEntity == null || employeeEntity.getEmployeeId() == null) { + return DataScopeViewTypeEnum.ME; + } + + // 如果是超级管理员 则可查看全部 + if (employeeEntity.getAdministratorFlag()) { + return DataScopeViewTypeEnum.ALL; + } + + List roleIdList = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId); + //未设置角色 默认本人 + if (CollectionUtils.isEmpty(roleIdList)) { + return DataScopeViewTypeEnum.ME; + } + //未设置角色数据范围 默认本人 + List dataScopeRoleList = roleDataScopeDao.listByRoleIdList(roleIdList); + if (CollectionUtils.isEmpty(dataScopeRoleList)) { + return DataScopeViewTypeEnum.ME; + } + Map> listMap = dataScopeRoleList.stream().collect(Collectors.groupingBy(RoleDataScopeEntity::getDataScopeType)); + List viewLevelList = listMap.getOrDefault(dataScopeTypeEnum.getValue(), Lists.newArrayList()); + if (CollectionUtils.isEmpty(viewLevelList)) { + return DataScopeViewTypeEnum.ME; + } + RoleDataScopeEntity maxLevel = viewLevelList.stream().max(Comparator.comparing(e -> SmartEnumUtil.getEnumByValue(e.getViewType(), DataScopeViewTypeEnum.class).getLevel())).get(); + return SmartEnumUtil.getEnumByValue(maxLevel.getViewType(), DataScopeViewTypeEnum.class); + } + + /** + * 获取本人相关 可查看员工id + */ + private List getMeEmployeeIdList(Long employeeId) { + return Lists.newArrayList(employeeId); + } + + /** + * 获取本部门相关 可查看员工id + */ + private List getDepartmentEmployeeIdList(Long employeeId) { + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + return employeeDao.getEmployeeIdByDepartmentId(employeeEntity.getDepartmentId(), false); + } + + /** + * 获取本部门及下属子部门相关 可查看员工id + */ + private List getDepartmentAndSubEmployeeIdList(Long employeeId) { + List allDepartmentIds = getDepartmentAndSubIdList(employeeId); + return employeeDao.getEmployeeIdByDepartmentIdList(allDepartmentIds, false); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/strategy/AbstractDataScopeStrategy.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/strategy/AbstractDataScopeStrategy.java new file mode 100644 index 0000000..1c740c7 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/datascope/strategy/AbstractDataScopeStrategy.java @@ -0,0 +1,20 @@ +package net.lab1024.sa.admin.module.system.datascope.strategy; + +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.domain.DataScopeSqlConfig; + +import java.util.Map; + +/** + * 数据范围策略 ,使用DataScopeWhereInTypeEnum.CUSTOM_STRATEGY类型,DataScope注解的joinSql属性无用 + * + * @Date 2020/11/28 20:59:17 + * @Author wzh + */ +public abstract class AbstractDataScopeStrategy { + + /** + * 获取joinsql 字符串 + */ + public abstract String getCondition(DataScopeViewTypeEnum viewTypeEnum, Map paramMap, DataScopeSqlConfig sqlConfigDTO); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/controller/DepartmentController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/controller/DepartmentController.java new file mode 100644 index 0000000..4913f10 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/controller/DepartmentController.java @@ -0,0 +1,65 @@ +package net.lab1024.sa.admin.module.system.department.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentAddForm; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentUpdateForm; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentTreeVO; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 部门 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_DEPARTMENT) +public class DepartmentController { + + @Resource + private DepartmentService departmentService; + + @Operation(summary = "查询部门树形列表 @author 卓大") + @GetMapping("/department/treeList") + public ResponseDTO> departmentTree() { + return departmentService.departmentTree(); + } + + @Operation(summary = "添加部门 @author 卓大") + @PostMapping("/department/add") + @SaCheckPermission("system:department:add") + public ResponseDTO addDepartment(@Valid @RequestBody DepartmentAddForm createDTO) { + return departmentService.addDepartment(createDTO); + } + + @Operation(summary = "更新部门 @author 卓大") + @PostMapping("/department/update") + @SaCheckPermission("system:department:update") + public ResponseDTO updateDepartment(@Valid @RequestBody DepartmentUpdateForm updateDTO) { + return departmentService.updateDepartment(updateDTO); + } + + @Operation(summary = "删除部门 @author 卓大") + @GetMapping("/department/delete/{departmentId}") + @SaCheckPermission("system:department:delete") + public ResponseDTO deleteDepartment(@PathVariable Long departmentId) { + return departmentService.deleteDepartment(departmentId); + } + + @Operation(summary = "查询部门列表 @author 卓大") + @GetMapping("/department/listAll") + public ResponseDTO> listAll() { + return ResponseDTO.ok(departmentService.listAll()); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.java new file mode 100644 index 0000000..2d4f8cb --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/dao/DepartmentDao.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.admin.module.system.department.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentQueryForm; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionQueryForm; +import net.lab1024.sa.admin.module.system.position.domain.vo.PositionVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 部门 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Mapper +public interface DepartmentDao extends BaseMapper { + + /** + * 根据部门id,查询此部门直接子部门的数量 + * + */ + Integer countSubDepartment(@Param("departmentId") Long departmentId); + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") DepartmentQueryForm queryForm); + + + /** + * 获取全部部门列表 + */ + List listAll(); + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/entity/DepartmentEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/entity/DepartmentEntity.java new file mode 100644 index 0000000..03d3d59 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/entity/DepartmentEntity.java @@ -0,0 +1,62 @@ +package net.lab1024.sa.admin.module.system.department.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.FieldStrategy; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 部门实体类 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Data +@TableName(value = "t_department") +public class DepartmentEntity { + + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long departmentId; + + /** + * 部门名称 + */ + private String name; + + /** + * 负责人员工 id + */ + @TableField(updateStrategy = FieldStrategy.IGNORED) + private Long managerId; + + /** + * 部门父级id + */ + private Long parentId; + + /** + * 排序 + */ + private Integer sort; + + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentAddForm.java new file mode 100644 index 0000000..bbdf584 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentAddForm.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.system.department.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 部门 添加表单 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Data +public class DepartmentAddForm { + + @Schema(description = "部门名称") + @Length(min = 1, max = 50, message = "请输入正确的部门名称(1-50个字符)") + @NotNull(message = "请输入正确的部门名称(1-50个字符)") + private String name; + + @Schema(description = "排序") + @NotNull(message = "排序值") + private Integer sort; + + @Schema(description = "部门负责人id") + private Long managerId; + + @Schema(description = "上级部门id (可选)") + private Long parentId; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentQueryForm.java new file mode 100644 index 0000000..38f4043 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentQueryForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.admin.module.system.department.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; +import java.util.List; + +@Data +public class DepartmentQueryForm extends PageParam { + + @Schema(description = "部门名称") + @Length(max = 20, message = "搜索词最多20字符") + private String name; + + @Schema(description = "开始时间") + private LocalDate startTime; + + @Schema(description = "结束时间") + private LocalDate endTime; + + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentUpdateForm.java new file mode 100644 index 0000000..07d9138 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/form/DepartmentUpdateForm.java @@ -0,0 +1,20 @@ +package net.lab1024.sa.admin.module.system.department.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 部门 更新表单 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Data +public class DepartmentUpdateForm extends DepartmentAddForm { + + @Schema(description = "部门id") + @NotNull(message = "部门id不能为空") + private Long departmentId; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentEmployeeTreeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentEmployeeTreeVO.java new file mode 100644 index 0000000..8c8be06 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentEmployeeTreeVO.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.admin.module.system.department.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; + +import java.util.List; + +/** + * 部门 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Data +public class DepartmentEmployeeTreeVO extends DepartmentVO { + + @Schema(description = "部门员工列表") + private List employees; + + @Schema(description = "子部门") + private List children; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentTreeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentTreeVO.java new file mode 100644 index 0000000..08e02c8 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentTreeVO.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.admin.module.system.department.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 部门 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Data +public class DepartmentTreeVO extends DepartmentVO { + + @Schema(description = "同级上一个元素id") + private Long preId; + + @Schema(description = "同级下一个元素id") + private Long nextId; + + @Schema(description = "子部门") + private List children; + + @Schema(description = "自己和所有递归子部门的id集合") + private List selfAndAllChildrenIdList; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentVO.java new file mode 100644 index 0000000..40e40fb --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/domain/vo/DepartmentVO.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.system.department.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 部门 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Data +public class DepartmentVO implements Serializable { + + private static final long serialVersionUID = 1L; + + @Schema(description = "部门id") + private Long departmentId; + + @Schema(description = "部门名称") + private String name; + + @Schema(description = "部门负责人姓名") + private String managerName; + + @Schema(description = "部门负责人id") + private Long managerId; + + @Schema(description = "父级部门id") + private Long parentId; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java new file mode 100644 index 0000000..3e3c3c5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/manager/DepartmentCacheManager.java @@ -0,0 +1,239 @@ +package net.lab1024.sa.admin.module.system.department.manager; + +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.constant.AdminCacheConst; +import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentTreeVO; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 部门 缓存相关 + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Slf4j +@Service +public class DepartmentCacheManager { + + @Resource + private DepartmentDao departmentDao; + + private void logClearInfo(String cache) { + log.info("clear " + cache); + } + + @CacheEvict(value = {AdminCacheConst.Department.DEPARTMENT_LIST_CACHE, AdminCacheConst.Department.DEPARTMENT_MAP_CACHE, AdminCacheConst.Department.DEPARTMENT_SELF_CHILDREN_CACHE, AdminCacheConst.Department.DEPARTMENT_TREE_CACHE, AdminCacheConst.Department.DEPARTMENT_PATH_CACHE,}, allEntries = true) + public void clearCache() { + logClearInfo(AdminCacheConst.Department.DEPARTMENT_LIST_CACHE); + } + + + /** + * 部门列表 + */ + @Cacheable(AdminCacheConst.Department.DEPARTMENT_LIST_CACHE) + public List getDepartmentList() { + return departmentDao.listAll(); + } + + /** + * 部门map + * + */ + @Cacheable(AdminCacheConst.Department.DEPARTMENT_MAP_CACHE) + public Map getDepartmentMap() { + return departmentDao.listAll().stream().collect(Collectors.toMap(DepartmentVO::getDepartmentId, Function.identity())); + } + + + /** + * 缓存部门树结构 + * + */ + @Cacheable(AdminCacheConst.Department.DEPARTMENT_TREE_CACHE) + public List getDepartmentTree() { + List departmentVOList = departmentDao.listAll(); + return this.buildTree(departmentVOList); + } + + /** + * 缓存某个部门的下级id列表 + * + */ + @Cacheable(AdminCacheConst.Department.DEPARTMENT_SELF_CHILDREN_CACHE) + public List getDepartmentSelfAndChildren(Long departmentId) { + List departmentVOList = departmentDao.listAll(); + return this.selfAndChildrenIdList(departmentId, departmentVOList); + } + + + /** + * 部门的路径名称 + * + */ + @Cacheable(AdminCacheConst.Department.DEPARTMENT_PATH_CACHE) + public Map getDepartmentPathMap() { + List departmentVOList = departmentDao.listAll(); + Map departmentMap = departmentVOList.stream().collect(Collectors.toMap(DepartmentVO::getDepartmentId, Function.identity())); + + Map pathNameMap = Maps.newHashMap(); + for (DepartmentVO departmentVO : departmentVOList) { + String pathName = this.buildDepartmentPath(departmentVO, departmentMap); + pathNameMap.put(departmentVO.getDepartmentId(), pathName); + } + + return pathNameMap; + } + + /** + * 构建父级考点路径 + */ + private String buildDepartmentPath(DepartmentVO departmentVO, Map departmentMap) { + if (Objects.equals(departmentVO.getParentId(), NumberUtils.LONG_ZERO)) { + return departmentVO.getName(); + } + //父节点 + DepartmentVO parentDepartment = departmentMap.get(departmentVO.getParentId()); + if (parentDepartment == null) { + return departmentVO.getName(); + } + String pathName = buildDepartmentPath(parentDepartment, departmentMap); + return pathName + "/" + departmentVO.getName(); + + } + // ---------------------- 构造树的一些方法 ------------------------------ + + /** + * 构建部门树结构 + * + */ + public List buildTree(List voList) { + if (CollectionUtils.isEmpty(voList)) { + return Lists.newArrayList(); + } + List rootList = voList.stream().filter(e -> e.getParentId() == null || Objects.equals(e.getParentId(), NumberUtils.LONG_ZERO)).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(rootList)) { + return Lists.newArrayList(); + } + List treeVOList = SmartBeanUtil.copyList(rootList, DepartmentTreeVO.class); + this.recursiveBuildTree(treeVOList, voList); + return treeVOList; + } + + /** + * 构建所有根节点的下级树形结构 + * 返回值为层序遍历结果 + * [由于departmentDao中listAll给出数据根据Sort降序 所以同一层中Sort值较大的优先遍历] + */ + private List recursiveBuildTree(List nodeList, List allDepartmentList) { + int nodeSize = nodeList.size(); + List childIdList = new ArrayList<>(); + for(int i = 0; i < nodeSize; i++) { + int preIndex = i - 1; + int nextIndex = i + 1; + DepartmentTreeVO node = nodeList.get(i); + if (preIndex > -1) { + node.setPreId(nodeList.get(preIndex).getDepartmentId()); + } + if (nextIndex < nodeSize) { + node.setNextId(nodeList.get(nextIndex).getDepartmentId()); + } + + List children = getChildren(node.getDepartmentId(), allDepartmentList); + + List tempChildIdList = new ArrayList<>(); + if (CollectionUtils.isNotEmpty(children)) { + node.setChildren(children); + tempChildIdList = this.recursiveBuildTree(children, allDepartmentList); + } + + if(CollectionUtils.isEmpty(node.getSelfAndAllChildrenIdList())) { + node.setSelfAndAllChildrenIdList( + new ArrayList<>() + ); + } + node.getSelfAndAllChildrenIdList().add(node.getDepartmentId()); + + if(CollectionUtils.isNotEmpty(tempChildIdList)) { + node.getSelfAndAllChildrenIdList().addAll(tempChildIdList); + childIdList.addAll(tempChildIdList); + } + + } + + // 保证本层遍历顺序 + for(int i = nodeSize - 1; i >= 0; i--) { + childIdList.add(0, nodeList.get(i).getDepartmentId()); + } + + return childIdList; + } + + + /** + * 获取子元素 + * + */ + private List getChildren(Long departmentId, List voList) { + List childrenEntityList = voList.stream().filter(e -> departmentId.equals(e.getParentId())).collect(Collectors.toList()); + if (CollectionUtils.isEmpty(childrenEntityList)) { + return Lists.newArrayList(); + } + return SmartBeanUtil.copyList(childrenEntityList, DepartmentTreeVO.class); + } + + + /** + * 通过部门id,获取当前以及下属部门 + * + */ + public List selfAndChildrenIdList(Long departmentId, List voList) { + List selfAndChildrenIdList = Lists.newArrayList(); + if (CollectionUtils.isEmpty(voList)) { + return selfAndChildrenIdList; + } + selfAndChildrenIdList.add(departmentId); + List children = this.getChildren(departmentId, voList); + if (CollectionUtils.isEmpty(children)) { + return selfAndChildrenIdList; + } + List childrenIdList = children.stream().map(DepartmentTreeVO::getDepartmentId).collect(Collectors.toList()); + selfAndChildrenIdList.addAll(childrenIdList); + for (Long childId : childrenIdList) { + this.selfAndChildrenRecursion(selfAndChildrenIdList, childId, voList); + } + return selfAndChildrenIdList; + } + + /** + * 递归查询 + */ + public void selfAndChildrenRecursion(List selfAndChildrenIdList, Long departmentId, List voList) { + List children = this.getChildren(departmentId, voList); + if (CollectionUtils.isEmpty(children)) { + return; + } + List childrenIdList = children.stream().map(DepartmentTreeVO::getDepartmentId).collect(Collectors.toList()); + selfAndChildrenIdList.addAll(childrenIdList); + for (Long childId : childrenIdList) { + this.selfAndChildrenRecursion(selfAndChildrenIdList, childId, voList); + } + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/service/DepartmentService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/service/DepartmentService.java new file mode 100644 index 0000000..75d155c --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/department/service/DepartmentService.java @@ -0,0 +1,206 @@ +package net.lab1024.sa.admin.module.system.department.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao; +import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentAddForm; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentQueryForm; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentUpdateForm; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentTreeVO; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.department.manager.DepartmentCacheManager; +import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionQueryForm; +import net.lab1024.sa.admin.module.system.position.domain.vo.PositionVO; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * 部门 service + * + * @Date 2022-01-12 20:37:48 + * @Author wzh + */ +@Service +public class DepartmentService { + + @Resource + private DepartmentDao departmentDao; + + @Resource + private EmployeeDao employeeDao; + + @Resource + private DepartmentCacheManager departmentCacheManager; + + // ---------------------------- 增加、修改、删除 ---------------------------- + + /** + * 新增添加部门 + * + */ + + public ResponseDTO addDepartment(DepartmentAddForm departmentAddForm) { + DepartmentEntity departmentEntity = SmartBeanUtil.copy(departmentAddForm, DepartmentEntity.class); + departmentDao.insert(departmentEntity); + this.clearCache(); + return ResponseDTO.ok(); + } + + + /** + * 更新部门信息 + * + */ + public ResponseDTO updateDepartment(DepartmentUpdateForm updateDTO) { + if (updateDTO.getParentId() == null) { + return ResponseDTO.userErrorParam("父级部门id不能为空"); + } + DepartmentEntity entity = departmentDao.selectById(updateDTO.getDepartmentId()); + if (entity == null) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + DepartmentEntity departmentEntity = SmartBeanUtil.copy(updateDTO, DepartmentEntity.class); + departmentEntity.setSort(updateDTO.getSort()); + departmentDao.updateById(departmentEntity); + this.clearCache(); + return ResponseDTO.ok(); + } + + /** + * 根据id删除部门 + * 1、需要判断当前部门是否有子部门,有子部门则不允许删除 + * 2、需要判断当前部门是否有员工,有员工则不能删除 + * + */ + public ResponseDTO deleteDepartment(Long departmentId) { + DepartmentEntity departmentEntity = departmentDao.selectById(departmentId); + if (null == departmentEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + // 是否有子级部门 + int subDepartmentNum = departmentDao.countSubDepartment(departmentId); + if (subDepartmentNum > 0) { + return ResponseDTO.userErrorParam("请先删除子级部门"); + } + + // 是否有未删除员工 + int employeeNum = employeeDao.countByDepartmentId(departmentId, Boolean.FALSE); + if (employeeNum > 0) { + return ResponseDTO.userErrorParam("请先删除部门员工"); + } + departmentDao.deleteById(departmentId); + // 清除缓存 + this.clearCache(); + return ResponseDTO.ok(); + } + + /** + * 清除自身以及下级的id列表缓存 + */ + private void clearCache() { + departmentCacheManager.clearCache(); + } + + // ---------------------------- 查询 ---------------------------- + + /** + * 分页查询 + * + * @param queryForm + * @return + */ + public PageResult queryPage(DepartmentQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = departmentDao.queryPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, list); + return pageResult; + } + + /** + * 获取部门树形结构 + */ + public ResponseDTO> departmentTree() { + List treeVOList = departmentCacheManager.getDepartmentTree(); + return ResponseDTO.ok(treeVOList); + } + + + /** + * 自身以及所有下级的部门id列表 + * + */ + public List selfAndChildrenIdList(Long departmentId) { + return departmentCacheManager.getDepartmentSelfAndChildren(departmentId); + } + + + /** + * 获取所有部门 + * + */ + public List listAll() { + return departmentCacheManager.getDepartmentList(); + } + + + /** + * 获取部门 + * + */ + public DepartmentVO getDepartmentById(Long departmentId) { + return departmentCacheManager.getDepartmentMap().get(departmentId); + } + + /** + * 获取部门路径:/公司/研发部/产品组 + */ + public String getDepartmentPath(Long departmentId) { + return departmentCacheManager.getDepartmentPathMap().get(departmentId); + } + + /** + * 查询全部父级部门(不包含自己) + * + */ + public List queryAllParentDepartment(Long departmentId) { + List list = new ArrayList<>(); + + Map departmentMap = departmentCacheManager.getDepartmentMap(); + DepartmentVO departmentVO = departmentMap.get(departmentId); + while (departmentVO != null) { + list.add(departmentVO); + departmentVO = departmentMap.get(departmentVO.getParentId()); + } + Collections.reverse(list); + return list; + } + + /** + * 查询全部父级部门(不包含自己) + * + */ + public List queryAllParentDepartmentIdList(Long departmentId) { + List list = new ArrayList<>(); + + Map departmentMap = departmentCacheManager.getDepartmentMap(); + DepartmentVO departmentVO = departmentMap.get(departmentId); + while (departmentVO != null) { + list.add(departmentVO.getDepartmentId()); + departmentVO = departmentMap.get(departmentVO.getParentId()); + } + Collections.reverse(list); + return list; + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/controller/EmployeeController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/controller/EmployeeController.java new file mode 100644 index 0000000..17bc211 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/controller/EmployeeController.java @@ -0,0 +1,126 @@ +package net.lab1024.sa.admin.module.system.employee.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.employee.domain.form.*; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiDecrypt; +import net.lab1024.sa.base.module.support.securityprotect.service.Level3ProtectConfigService; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 员工 + * + * @Date 2021-12-09 22:57:49 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_EMPLOYEE) +public class EmployeeController { + + @Resource + private EmployeeService employeeService; + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + @PostMapping("/employee/query") + @Operation(summary = "员工管理查询 @author 卓大") + public ResponseDTO> query(@Valid @RequestBody EmployeeQueryForm query) { + return employeeService.queryEmployee(query); + } + + @Operation(summary = "添加员工(返回添加员工的密码) @author 卓大") + @PostMapping("/employee/add") + @SaCheckPermission("system:employee:add") + public ResponseDTO addEmployee(@Valid @RequestBody EmployeeAddForm employeeAddForm) { + return employeeService.addEmployee(employeeAddForm); + } + + @Operation(summary = "更新员工 @author 卓大") + @PostMapping("/employee/update") + @SaCheckPermission("system:employee:update") + public ResponseDTO updateEmployee(@Valid @RequestBody EmployeeUpdateForm employeeUpdateForm) { + return employeeService.updateEmployee(employeeUpdateForm); + } + + @Operation(summary = "更新员工个人中心信息 @author 善逸") + @PostMapping("/employee/update/center") + public ResponseDTO updateCenter(@Valid @RequestBody EmployeeUpdateCenterForm updateCenterForm) { + updateCenterForm.setEmployeeId(SmartRequestUtil.getRequestUserId()); + return employeeService.updateCenter(updateCenterForm); + } + + @Operation(summary = "更新登录人头像 @author 善逸") + @PostMapping("/employee/update/avatar") + public ResponseDTO updateAvatar(@Valid @RequestBody EmployeeUpdateAvatarForm employeeUpdateAvatarForm) { + employeeUpdateAvatarForm.setEmployeeId(SmartRequestUtil.getRequestUserId()); + return employeeService.updateAvatar(employeeUpdateAvatarForm); + } + + @Operation(summary = "更新员工禁用/启用状态 @author 卓大") + @GetMapping("/employee/update/disabled/{employeeId}") + @SaCheckPermission("system:employee:disabled") + public ResponseDTO updateDisableFlag(@PathVariable Long employeeId) { + return employeeService.updateDisableFlag(employeeId); + } + + @Operation(summary = "批量删除员工 @author 卓大") + @PostMapping("/employee/update/batch/delete") + @SaCheckPermission("system:employee:delete") + public ResponseDTO batchUpdateDeleteFlag(@RequestBody List employeeIdList) { + return employeeService.batchUpdateDeleteFlag(employeeIdList); + } + + @Operation(summary = "批量调整员工部门 @author 卓大") + @PostMapping("/employee/update/batch/department") + @SaCheckPermission("system:employee:department:update") + public ResponseDTO batchUpdateDepartment(@Valid @RequestBody EmployeeBatchUpdateDepartmentForm batchUpdateDepartmentForm) { + return employeeService.batchUpdateDepartment(batchUpdateDepartmentForm); + } + + @Operation(summary = "修改密码 @author 卓大") + @PostMapping("/employee/update/password") + @ApiDecrypt + public ResponseDTO updatePassword(@Valid @RequestBody EmployeeUpdatePasswordForm updatePasswordForm) { + updatePasswordForm.setEmployeeId(SmartRequestUtil.getRequestUserId()); + return employeeService.updatePassword(SmartRequestUtil.getRequestUser(), updatePasswordForm); + } + + @Operation(summary = "获取密码复杂度 @author 卓大") + @GetMapping("/employee/getPasswordComplexityEnabled") + @ApiDecrypt + public ResponseDTO getPasswordComplexityEnabled() { + return ResponseDTO.ok(level3ProtectConfigService.isPasswordComplexityEnabled()); + } + + @Operation(summary = "重置员工密码 @author 卓大") + @GetMapping("/employee/update/password/reset/{employeeId}") + @SaCheckPermission("system:employee:password:reset") + public ResponseDTO resetPassword(@PathVariable Long employeeId) { + return employeeService.resetPassword(employeeId); + } + + @Operation(summary = "查询员工-根据部门id @author 卓大") + @GetMapping("/employee/getAllEmployeeByDepartmentId/{departmentId}") + public ResponseDTO> getAllEmployeeByDepartmentId(@PathVariable Long departmentId) { + return employeeService.getAllEmployeeByDepartmentId(departmentId); + } + + @Operation(summary = "查询所有员工 @author 卓大") + @GetMapping("/employee/queryAll") + public ResponseDTO> queryAllEmployee(@RequestParam(value = "disabledFlag", required = false) Boolean disabledFlag) { + return employeeService.queryAllEmployee(disabledFlag); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java new file mode 100644 index 0000000..5c9edc2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/dao/EmployeeDao.java @@ -0,0 +1,113 @@ +package net.lab1024.sa.admin.module.system.employee.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.core.metadata.IPage; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.employee.domain.form.EmployeeQueryForm; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; + +/** + * 员工 dao + * + * @Date 2021-12-09 22:57:49 + * @Author wzh + */ +@Mapper +public interface EmployeeDao extends BaseMapper { + /** + * 查询员工列表 + */ + List queryEmployee(Page page, @Param("queryForm") EmployeeQueryForm queryForm, @Param("departmentIdList") List departmentIdList); + + /** + * 查询员工 + */ + List selectEmployeeByDisabledAndDeleted(@Param("disabledFlag") Boolean disabledFlag, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 更新单个 + */ + void updateDisableFlag(@Param("employeeId") Long employeeId, @Param("disabledFlag") Boolean disabledFlag); + + /** + * 通过登录名查询 + */ + EmployeeEntity getByLoginName(@Param("loginName") String loginName, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 通过姓名查询 + */ + EmployeeEntity getByActualName(@Param("actualName") String actualName, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 通过手机号查询 + */ + EmployeeEntity getByPhone(@Param("phone") String phone, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 通过邮箱账号查询 + */ + EmployeeEntity getByEmail(@Param("email") String email, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 获取所有员工 + */ + List listAll(); + + /** + * 获取某个部门员工数 + */ + Integer countByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 获取一批员工 + */ + List getEmployeeByIds(@Param("employeeIds") Collection employeeIds); + + /** + * 查询单个员工信息 + */ + EmployeeVO getEmployeeById(@Param("employeeId") Long employeeId); + + /** + * 获取某个部门的员工 + */ + List selectByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 查询某些部门下用户名是xxx的员工 + */ + List selectByActualName(@Param("departmentIdList") List departmentIdList, @Param("actualName") String actualName, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 获取某批部门的员工Id + */ + List getEmployeeIdByDepartmentIdList(@Param("departmentIds") List departmentIds, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 获取所有 + */ + List getEmployeeId(@Param("leaveFlag") Boolean leaveFlag, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 获取某个部门的员工Id + */ + List getEmployeeIdByDepartmentId(@Param("departmentId") Long departmentId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 员工重置密码 + */ + Integer updatePassword(@Param("employeeId") Long employeeId, @Param("password") String password); + + Page selectUserPage(@Param("page") Page page, @Param("warmFlowInteractiveTypeVo") WarmFlowInteractiveTypeVO warmFlowInteractiveTypeVo); + + Page selectNotUserPage(@Param("page") Page page, @Param("warmFlowInteractiveTypeVo") WarmFlowInteractiveTypeVO warmFlowInteractiveTypeVo); +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/entity/EmployeeEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/entity/EmployeeEntity.java new file mode 100644 index 0000000..4ba6894 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/entity/EmployeeEntity.java @@ -0,0 +1,93 @@ +package net.lab1024.sa.admin.module.system.employee.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 员工 实体表 + * + * @Date 2021-12-09 22:57:49 + * @Author wzh + */ +@Data +@TableName("t_employee") +public class EmployeeEntity { + + @TableId(type = IdType.AUTO) + private Long employeeId; + + /** + * 登录账号 + */ + private String loginName; + + /** + * 登录密码 + */ + private String loginPwd; + + /** + * 员工名称 + */ + private String actualName; + + /** + * 头像 + */ + private String avatar; + + /** + * 性别 + */ + private Integer gender; + + /** + * 手机号码 + */ + private String phone; + + /** + * 邮箱 + */ + private String email; + + /** + * 部门id + */ + private Long departmentId; + + /** + * 职务级别ID + */ + private Long positionId; + + /** + * 是否为超级管理员: 0 不是,1是 + */ + private Boolean administratorFlag; + + /** + * 是否被禁用 0否1是 + */ + private Boolean disabledFlag; + + /** + * 是否删除0否 1是 + */ + private Boolean deletedFlag; + + /** + * 备注 + */ + private String remark; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeAddForm.java new file mode 100644 index 0000000..7826b2e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeAddForm.java @@ -0,0 +1,66 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.GenderEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.util.SmartVerificationUtil; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.hibernate.validator.constraints.Length; + +import java.util.List; + +/** + * 添加员工 + * + * @Date 2021-12-20 21:06:49 + * @Author wzh + */ +@Data +public class EmployeeAddForm { + + @Schema(description = "姓名") + @NotNull(message = "姓名不能为空") + @Length(max = 30, message = "姓名最多30字符") + private String actualName; + + @Schema(description = "登录账号") + @NotNull(message = "登录账号不能为空") + @Length(max = 30, message = "登录账号最多30字符") + private String loginName; + + @SchemaEnum(GenderEnum.class) + @CheckEnum(value = GenderEnum.class, message = "性别错误") + private Integer gender; + + @Schema(description = "部门id") + @NotNull(message = "部门id不能为空") + private Long departmentId; + + @Schema(description = "是否启用") + @NotNull(message = "是否被禁用不能为空") + private Boolean disabledFlag; + + @Schema(description = "手机号") + @NotNull(message = "手机号不能为空") + @Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确") + private String phone; + + @Schema(description = "邮箱账号") + @NotNull(message = "邮箱账号不能为空") + @Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱账号格式不正确") + private String email; + + @Schema(description = "职务级别ID") + private Long positionId; + + @Schema(description = "角色列表") + private List roleIdList; + + @Schema(description = "备注") + @Length(max = 200, message = "备注最多200字符") + private String remark; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeBatchUpdateDepartmentForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeBatchUpdateDepartmentForm.java new file mode 100644 index 0000000..5210558 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeBatchUpdateDepartmentForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +/** + * 员工更新部门 + * + * @Date 2021-12-20 21:06:49 + * @Author wzh + */ +@Data +public class EmployeeBatchUpdateDepartmentForm { + + @Schema(description = "员工id") + @NotEmpty(message = "员工id不能为空") + @Size(max = 99, message = "一次最多调整99个员工") + private List employeeIdList; + + @Schema(description = "部门ID") + @NotNull(message = "部门ID不能为空") + private Long departmentId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeQueryForm.java new file mode 100644 index 0000000..721f41d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeQueryForm.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; +import java.util.List; + +/** + * 员工列表 + * + * @Date 2021-12-20 21:06:49 + * @Author wzh + */ +@Data +public class EmployeeQueryForm extends PageParam { + + @Schema(description = "搜索词") + @Length(max = 20, message = "搜索词最多20字符") + private String keyword; + + @Schema(description = "部门id") + private Long departmentId; + + @Schema(description = "开始时间") + private LocalDate startTime; + + @Schema(description = "结束时间") + private LocalDate endTime; + + @Schema(description = "是否禁用") + private Boolean disabledFlag; + + @Schema(description = "员工id集合") + @Size(max = 99, message = "最多查询99个员工") + private List employeeIdList; + + @Schema(description = "删除标识", hidden = true) + private Boolean deletedFlag; + + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateAvatarForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateAvatarForm.java new file mode 100644 index 0000000..b31ae91 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateAvatarForm.java @@ -0,0 +1,22 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 修改登录人头像 + * + * @Date 2024年6月30日00:26:35 + * @Author wzh + */ +@Data +public class EmployeeUpdateAvatarForm { + + @Schema(hidden = true) + private Long employeeId; + + @Schema(description = "头像") + @NotBlank(message = "头像不能为空哦") + private String avatar; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateCenterForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateCenterForm.java new file mode 100644 index 0000000..3148b66 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateCenterForm.java @@ -0,0 +1,53 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.GenderEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.util.SmartVerificationUtil; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 更新员工个人中心信息 + * + * @Date 2021-12-20 21:06:49 + * @Author wzh + */ +@Data +public class EmployeeUpdateCenterForm { + + @Schema(hidden = true) + private Long employeeId; + + @Schema(description = "姓名") + @NotNull(message = "姓名不能为空") + @Length(max = 30, message = "姓名最多30字符") + private String actualName; + + @SchemaEnum(GenderEnum.class) + @CheckEnum(value = GenderEnum.class, message = "性别错误") + private Integer gender; + + @Schema(description = "手机号") + @NotNull(message = "手机号不能为空") + @Pattern(regexp = SmartVerificationUtil.PHONE_REGEXP, message = "手机号格式不正确") + private String phone; + + @Schema(description = "邮箱账号") + @NotNull(message = "邮箱账号不能为空") + @Pattern(regexp = SmartVerificationUtil.EMAIL, message = "邮箱账号格式不正确") + private String email; + + @Schema(description = "职务级别ID") + private Long positionId; + + @Schema(description = "头像") + private String avatar; + + @Schema(description = "备注") + @Length(max = 200, message = "备注最多200字符") + private String remark; +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateForm.java new file mode 100644 index 0000000..8ae56c5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 更新员工 + * + * @Date 2021-12-20 21:06:49 + * @Author wzh + */ +@Data +public class EmployeeUpdateForm extends EmployeeAddForm { + + @Schema(description = "员工id") + @NotNull(message = "员工id不能为空") + private Long employeeId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdatePasswordForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdatePasswordForm.java new file mode 100644 index 0000000..fb56dd6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdatePasswordForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.Pattern; +import lombok.Data; +import net.lab1024.sa.base.common.util.SmartVerificationUtil; + +/** + * 修改密码所需参数 + * + * @Date 2021-12-20 21:06:49 + * @Author wzh + */ +@Data +public class EmployeeUpdatePasswordForm { + + @Schema(hidden = true) + private Long employeeId; + + @Schema(description = "原密码") + @NotBlank(message = "原密码不能为空哦") + private String oldPassword; + + @Schema(description = "新密码") + @NotBlank(message = "新密码不能为空哦") + private String newPassword; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateRoleForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateRoleForm.java new file mode 100644 index 0000000..e87cd7e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/form/EmployeeUpdateRoleForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.admin.module.system.employee.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.util.List; + +/** + * 员工更新角色 + * + * @Date 2021-12-20 20:55:13 + * @Author wzh + */ +@Data +public class EmployeeUpdateRoleForm { + + @Schema(description = "员工id") + @NotNull(message = "员工id不能为空") + private Long employeeId; + + @Schema(description = "角色ids") + @Size(max = 99, message = "角色最多99") + private List roleIdList; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/vo/EmployeeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/vo/EmployeeVO.java new file mode 100644 index 0000000..cf374e1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/domain/vo/EmployeeVO.java @@ -0,0 +1,65 @@ +package net.lab1024.sa.admin.module.system.employee.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.GenderEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 员工信息 + * + * @Date 2021-12-21 23:05:56 + * @Author wzh + */ +@Data +public class EmployeeVO { + + @Schema(description = "主键id") + private Long employeeId; + + @Schema(description = "登录账号") + private String loginName; + + @SchemaEnum(GenderEnum.class) + private Integer gender; + + @Schema(description = "员工名称") + private String actualName; + + @Schema(description = "手机号码") + private String phone; + + @Schema(description = "部门id") + private Long departmentId; + + @Schema(description = "是否被禁用") + private Boolean disabledFlag; + + @Schema(description = "是否 超级管理员") + private Boolean administratorFlag; + + @Schema(description = "部门名称") + private String departmentName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "角色列表") + private List roleIdList; + + @Schema(description = "角色名称列表") + private List roleNameList; + + @Schema(description = "职务ID") + private Long positionId; + + @Schema(description = "职务名称") + private String positionName; + + @Schema(description = "邮箱") + private String email; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/manager/EmployeeManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/manager/EmployeeManager.java new file mode 100644 index 0000000..39af288 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/manager/EmployeeManager.java @@ -0,0 +1,83 @@ +package net.lab1024.sa.admin.module.system.employee.manager; + + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEmployeeEntity; +import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 员工 manager + * + * @Date 2021-12-29 21:52:46 + * @Author wzh + */ +@Service +public class EmployeeManager extends ServiceImpl { + + @Resource + private EmployeeDao employeeDao; + + @Resource + private RoleEmployeeService roleEmployeeService; + + @Resource + private RoleEmployeeDao roleEmployeeDao; + + /** + * 保存员工 + * + */ + @Transactional(rollbackFor = Throwable.class) + public void saveEmployee(EmployeeEntity employee, List roleIdList) { + // 保存员工 获得id + employeeDao.insert(employee); + + if (CollectionUtils.isNotEmpty(roleIdList)) { + List roleEmployeeList = roleIdList.stream().map(e -> new RoleEmployeeEntity(e, employee.getEmployeeId())).collect(Collectors.toList()); + roleEmployeeService.batchInsert(roleEmployeeList); + } + } + + /** + * 更新员工 + * + */ + @Transactional(rollbackFor = Throwable.class) + public void updateEmployee(EmployeeEntity employee, List roleIdList) { + // 保存员工 获得id + employeeDao.updateById(employee); + + // 若为空,则删除所有角色 + if (CollectionUtils.isEmpty(roleIdList)) { + roleEmployeeDao.deleteByEmployeeId(employee.getEmployeeId()); + return; + } + + List roleEmployeeList = roleIdList.stream().map(e -> new RoleEmployeeEntity(e, employee.getEmployeeId())).collect(Collectors.toList()); + this.updateEmployeeRole(employee.getEmployeeId(), roleEmployeeList); + } + + /** + * 更新员工角色 + */ + @Transactional(rollbackFor = Throwable.class) + public void updateEmployeeRole(Long employeeId, List roleEmployeeList) { + + roleEmployeeDao.deleteByEmployeeId(employeeId); + + if (CollectionUtils.isNotEmpty(roleEmployeeList)) { + roleEmployeeService.batchInsert(roleEmployeeList); + } + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/service/EmployeeService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/service/EmployeeService.java new file mode 100644 index 0000000..e9a01d6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/employee/service/EmployeeService.java @@ -0,0 +1,489 @@ +package net.lab1024.sa.admin.module.system.employee.service; + +import cn.dev33.satoken.stp.StpUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.flow.domain.vo.WarmFlowInteractiveTypeVO; +import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao; +import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.admin.module.system.employee.dao.EmployeeDao; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.employee.domain.form.*; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import net.lab1024.sa.admin.module.system.employee.manager.EmployeeManager; +import net.lab1024.sa.admin.module.system.login.service.LoginService; +import net.lab1024.sa.admin.module.system.position.dao.PositionDao; +import net.lab1024.sa.admin.module.system.position.domain.entity.PositionEntity; +import net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleEmployeeVO; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.securityprotect.service.SecurityPasswordService; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * 员工 service + * + * @Date 2021-12-29 21:52:46 + * @Author wzh + */ +@Service +public class EmployeeService { + + @Resource + private EmployeeDao employeeDao; + + @Resource + private DepartmentDao departmentDao; + + @Resource + private EmployeeManager employeeManager; + + @Resource + private RoleEmployeeDao roleEmployeeDao; + + @Resource + private DepartmentService departmentService; + + @Resource + private SecurityPasswordService securityPasswordService; + + @Resource + @Lazy + private LoginService loginService; + + @Resource + private PositionDao positionDao; + + public EmployeeEntity getById(Long employeeId) { + return employeeDao.selectById(employeeId); + } + + + /** + * 查询员工列表 + */ + public ResponseDTO> queryEmployee(EmployeeQueryForm employeeQueryForm) { + employeeQueryForm.setDeletedFlag(false); + Page pageParam = SmartPageUtil.convert2PageQuery(employeeQueryForm); + + List departmentIdList = new ArrayList<>(); + if (employeeQueryForm.getDepartmentId() != null) { + departmentIdList.addAll(departmentService.selfAndChildrenIdList(employeeQueryForm.getDepartmentId())); + } + + List employeeList = employeeDao.queryEmployee(pageParam, employeeQueryForm, departmentIdList); + if (CollectionUtils.isEmpty(employeeList)) { + PageResult pageResult = SmartPageUtil.convert2PageResult(pageParam, employeeList); + return ResponseDTO.ok(pageResult); + } + + // 查询员工角色 + List employeeIdList = employeeList.stream().map(EmployeeVO::getEmployeeId).collect(Collectors.toList()); + List roleEmployeeEntityList = employeeIdList.isEmpty() ? Collections.emptyList() : roleEmployeeDao.selectRoleByEmployeeIdList(employeeIdList); + Map> employeeRoleIdListMap = roleEmployeeEntityList.stream().collect(Collectors.groupingBy(RoleEmployeeVO::getEmployeeId, Collectors.mapping(RoleEmployeeVO::getRoleId, Collectors.toList()))); + Map> employeeRoleNameListMap = roleEmployeeEntityList.stream().collect(Collectors.groupingBy(RoleEmployeeVO::getEmployeeId, Collectors.mapping(RoleEmployeeVO::getRoleName, Collectors.toList()))); + + // 查询员工职位 + List positionIdList = employeeList.stream().map(EmployeeVO::getPositionId).filter(Objects::nonNull).collect(Collectors.toList()); + List positionEntityList = positionIdList.isEmpty() ? Collections.emptyList() : positionDao.selectBatchIds(positionIdList); + Map positionNameMap = positionEntityList.stream().collect(Collectors.toMap(PositionEntity::getPositionId, PositionEntity::getPositionName)); + + employeeList.forEach(e -> { + e.setRoleIdList(employeeRoleIdListMap.getOrDefault(e.getEmployeeId(), Lists.newArrayList())); + e.setRoleNameList(employeeRoleNameListMap.getOrDefault(e.getEmployeeId(), Lists.newArrayList())); + e.setDepartmentName(departmentService.getDepartmentPath(e.getDepartmentId())); + e.setPositionName(positionNameMap.get(e.getPositionId())); + }); + PageResult pageResult = SmartPageUtil.convert2PageResult(pageParam, employeeList); + return ResponseDTO.ok(pageResult); + } + + /** + * 查询员工列表 + */ + public PageResult queryEmployeePage(EmployeeQueryForm employeeQueryForm) { + employeeQueryForm.setDeletedFlag(false); + Page pageParam = SmartPageUtil.convert2PageQuery(employeeQueryForm); + + List departmentIdList = new ArrayList<>(); + if (employeeQueryForm.getDepartmentId() != null) { + departmentIdList.addAll(departmentService.selfAndChildrenIdList(employeeQueryForm.getDepartmentId())); + } + + List employeeList = employeeDao.queryEmployee(pageParam, employeeQueryForm, departmentIdList); + if (CollectionUtils.isEmpty(employeeList)) { + PageResult pageResult = SmartPageUtil.convert2PageResult(pageParam, employeeList); + return pageResult; + } + + // 查询员工角色 + List employeeIdList = employeeList.stream().map(EmployeeVO::getEmployeeId).collect(Collectors.toList()); + List roleEmployeeEntityList = employeeIdList.isEmpty() ? Collections.emptyList() : roleEmployeeDao.selectRoleByEmployeeIdList(employeeIdList); + Map> employeeRoleIdListMap = roleEmployeeEntityList.stream().collect(Collectors.groupingBy(RoleEmployeeVO::getEmployeeId, Collectors.mapping(RoleEmployeeVO::getRoleId, Collectors.toList()))); + Map> employeeRoleNameListMap = roleEmployeeEntityList.stream().collect(Collectors.groupingBy(RoleEmployeeVO::getEmployeeId, Collectors.mapping(RoleEmployeeVO::getRoleName, Collectors.toList()))); + + // 查询员工职位 + List positionIdList = employeeList.stream().map(EmployeeVO::getPositionId).filter(Objects::nonNull).collect(Collectors.toList()); + List positionEntityList = positionIdList.isEmpty() ? Collections.emptyList() : positionDao.selectBatchIds(positionIdList); + Map positionNameMap = positionEntityList.stream().collect(Collectors.toMap(PositionEntity::getPositionId, PositionEntity::getPositionName)); + + employeeList.forEach(e -> { + e.setRoleIdList(employeeRoleIdListMap.getOrDefault(e.getEmployeeId(), Lists.newArrayList())); + e.setRoleNameList(employeeRoleNameListMap.getOrDefault(e.getEmployeeId(), Lists.newArrayList())); + e.setDepartmentName(departmentService.getDepartmentPath(e.getDepartmentId())); + e.setPositionName(positionNameMap.get(e.getPositionId())); + }); + PageResult pageResult = SmartPageUtil.convert2PageResult(pageParam, employeeList); + return pageResult; + } + + /** + * 新增员工 + */ + public synchronized ResponseDTO addEmployee(EmployeeAddForm employeeAddForm) { + // 校验登录名是否重复 + EmployeeEntity employeeEntity = employeeDao.getByLoginName(employeeAddForm.getLoginName(), null); + if (null != employeeEntity) { + return ResponseDTO.userErrorParam("登录名重复"); + } + // 校验电话是否存在 + employeeEntity = employeeDao.getByPhone(employeeAddForm.getPhone(), null); + if (null != employeeEntity) { + return ResponseDTO.userErrorParam("手机号已存在"); + } + // 部门是否存在 + Long departmentId = employeeAddForm.getDepartmentId(); + DepartmentEntity department = departmentDao.selectById(departmentId); + if (department == null) { + return ResponseDTO.userErrorParam("部门不存在"); + } + + EmployeeEntity entity = SmartBeanUtil.copy(employeeAddForm, EmployeeEntity.class); + + // 设置密码 默认密码 + String password = securityPasswordService.randomPassword(); + entity.setLoginPwd(SecurityPasswordService.getEncryptPwd(password)); + + // 保存数据 + entity.setDeletedFlag(Boolean.FALSE); + employeeManager.saveEmployee(entity, employeeAddForm.getRoleIdList()); + + return ResponseDTO.ok(password); + } + + /** + * 更新员工 + */ + public synchronized ResponseDTO updateEmployee(EmployeeUpdateForm employeeUpdateForm) { + + Long employeeId = employeeUpdateForm.getEmployeeId(); + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + if (null == employeeEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + // 部门是否存在 + Long departmentId = employeeUpdateForm.getDepartmentId(); + DepartmentEntity departmentEntity = departmentDao.selectById(departmentId); + if (departmentEntity == null) { + return ResponseDTO.userErrorParam("部门不存在"); + } + + // 检查唯一性 + ResponseDTO checkResponse = checkUniqueness(employeeId, employeeUpdateForm.getLoginName(), employeeUpdateForm.getPhone(), employeeUpdateForm.getEmail()); + if (!checkResponse.getOk()) { + return checkResponse; + } + + EmployeeEntity entity = SmartBeanUtil.copy(employeeUpdateForm, EmployeeEntity.class); + // 不更新密码 + entity.setLoginPwd(null); + + // 更新数据 + employeeManager.updateEmployee(entity, employeeUpdateForm.getRoleIdList()); + + // 清除员工缓存 + loginService.clearLoginEmployeeCache(employeeId); + + return ResponseDTO.ok(); + } + + /** + * 更新员工个人中心信息 + */ + public ResponseDTO updateCenter(EmployeeUpdateCenterForm updateCenterForm) { + + Long employeeId = updateCenterForm.getEmployeeId(); + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + if (null == employeeEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + // 检查唯一性 登录账号不能修改则不需要检查 + ResponseDTO checkResponse = checkUniqueness(employeeId, "", updateCenterForm.getPhone(), updateCenterForm.getEmail()); + if (!checkResponse.getOk()) { + return checkResponse; + } + + EmployeeEntity employee = SmartBeanUtil.copy(updateCenterForm, EmployeeEntity.class); + // 不更新密码 + employee.setLoginPwd(null); + + // 更新数据 + employeeDao.updateById(employee); + + // 清除员工缓存 + loginService.clearLoginEmployeeCache(employeeId); + + return ResponseDTO.ok(); + } + + /** + * 检查唯一性 + */ + private ResponseDTO checkUniqueness(Long employeeId, String loginName, String phone, String email) { + EmployeeEntity existEntity = employeeDao.getByLoginName(loginName, null); + if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) { + return ResponseDTO.userErrorParam("登录名重复"); + } + + existEntity = employeeDao.getByPhone(phone, null); + if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) { + return ResponseDTO.userErrorParam("手机号已存在"); + } + + existEntity = employeeDao.getByEmail(email, null); + if (null != existEntity && !Objects.equals(existEntity.getEmployeeId(), employeeId)) { + return ResponseDTO.userErrorParam("邮箱账号已存在"); + } + + return ResponseDTO.ok(); + } + + /** + * 更新登录人头像 + * + * @param employeeUpdateAvatarForm + * @return + */ + public ResponseDTO updateAvatar(EmployeeUpdateAvatarForm employeeUpdateAvatarForm) { + Long employeeId = employeeUpdateAvatarForm.getEmployeeId(); + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + if (employeeEntity == null) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + // 更新头像 + EmployeeEntity updateEntity = new EmployeeEntity(); + updateEntity.setEmployeeId(employeeId); + updateEntity.setAvatar(employeeUpdateAvatarForm.getAvatar()); + employeeDao.updateById(updateEntity); + + // 清除员工缓存 + loginService.clearLoginEmployeeCache(employeeId); + return ResponseDTO.ok(); + } + + /** + * 更新禁用/启用状态 + */ + public ResponseDTO updateDisableFlag(Long employeeId) { + if (null == employeeId) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + if (null == employeeEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + employeeDao.updateDisableFlag(employeeId, !employeeEntity.getDisabledFlag()); + + if (employeeEntity.getDisabledFlag()) { + // 强制退出登录 + StpUtil.logout(UserTypeEnum.ADMIN_EMPLOYEE.getValue() + StringConst.COLON + employeeId); + } + + return ResponseDTO.ok(); + } + + /** + * 批量删除员工 + */ + public ResponseDTO batchUpdateDeleteFlag(List employeeIdList) { + if (CollectionUtils.isEmpty(employeeIdList)) { + return ResponseDTO.ok(); + } + List employeeEntityList = employeeManager.listByIds(employeeIdList); + if (CollectionUtils.isEmpty(employeeEntityList)) { + return ResponseDTO.ok(); + } + // 更新删除 + List deleteList = employeeIdList.stream().map(e -> { + EmployeeEntity updateEmployee = new EmployeeEntity(); + updateEmployee.setEmployeeId(e); + updateEmployee.setDeletedFlag(true); + return updateEmployee; + }).collect(Collectors.toList()); + employeeManager.updateBatchById(deleteList); + + for (Long employeeId : employeeIdList) { + // 强制退出登录 + StpUtil.logout(UserTypeEnum.ADMIN_EMPLOYEE.getValue() + StringConst.COLON + employeeId); + } + return ResponseDTO.ok(); + } + + + /** + * 批量更新部门 + */ + public ResponseDTO batchUpdateDepartment(EmployeeBatchUpdateDepartmentForm batchUpdateDepartmentForm) { + List employeeIdList = batchUpdateDepartmentForm.getEmployeeIdList(); + List employeeEntityList = employeeDao.selectBatchIds(employeeIdList); + if (employeeIdList.size() != employeeEntityList.size()) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + // 更新 + List updateList = employeeIdList.stream().map(e -> { + EmployeeEntity updateEmployee = new EmployeeEntity(); + updateEmployee.setEmployeeId(e); + updateEmployee.setDepartmentId(batchUpdateDepartmentForm.getDepartmentId()); + return updateEmployee; + }).collect(Collectors.toList()); + employeeManager.updateBatchById(updateList); + + return ResponseDTO.ok(); + } + + + /** + * 更新密码 + */ + @Transactional(rollbackFor = Throwable.class) + public ResponseDTO updatePassword(RequestUser requestUser, EmployeeUpdatePasswordForm updatePasswordForm) { + Long employeeId = updatePasswordForm.getEmployeeId(); + EmployeeEntity employeeEntity = employeeDao.selectById(employeeId); + if (employeeEntity == null) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + // 校验原始密码 + if (!SecurityPasswordService.matchesPwd(updatePasswordForm.getOldPassword(),employeeEntity.getLoginPwd()) ) { + return ResponseDTO.userErrorParam("原密码有误,请重新输入"); + } + + // 新旧密码相同 + if (Objects.equals(updatePasswordForm.getOldPassword(), updatePasswordForm.getNewPassword()) ){ + return ResponseDTO.userErrorParam("新密码与原始密码相同,请重新输入"); + } + + // 校验密码复杂度 + ResponseDTO validatePassComplexity = securityPasswordService.validatePasswordComplexity(updatePasswordForm.getNewPassword()); + if (!validatePassComplexity.getOk()) { + return validatePassComplexity; + } + + // 根据三级等保规则,校验密码是否重复 + ResponseDTO passwordRepeatTimes = securityPasswordService.validatePasswordRepeatTimes(requestUser, updatePasswordForm.getNewPassword()); + if (!passwordRepeatTimes.getOk()) { + return ResponseDTO.error(passwordRepeatTimes); + } + + + // 更新密码 + String newEncryptPassword = SecurityPasswordService.getEncryptPwd(updatePasswordForm.getNewPassword()); + EmployeeEntity updateEntity = new EmployeeEntity(); + updateEntity.setEmployeeId(employeeId); + updateEntity.setLoginPwd(newEncryptPassword); + employeeDao.updateById(updateEntity); + + // 保存修改密码密码记录 + securityPasswordService.saveUserChangePasswordLog(requestUser, newEncryptPassword, employeeEntity.getLoginPwd()); + + return ResponseDTO.ok(); + } + + /** + * 获取某个部门的员工信息 + */ + public ResponseDTO> getAllEmployeeByDepartmentId(Long departmentId) { + List employeeEntityList = employeeDao.selectByDepartmentId(departmentId, Boolean.FALSE); + + if (CollectionUtils.isEmpty(employeeEntityList)) { + return ResponseDTO.ok(Collections.emptyList()); + } + + DepartmentVO department = departmentService.getDepartmentById(departmentId); + + List voList = employeeEntityList.stream().map(e -> { + EmployeeVO employeeVO = SmartBeanUtil.copy(e, EmployeeVO.class); + if (department != null) { + employeeVO.setDepartmentName(department.getName()); + } + return employeeVO; + }).collect(Collectors.toList()); + return ResponseDTO.ok(voList); + } + + + /** + * 重置密码 + */ + public ResponseDTO resetPassword(Long employeeId) { + String password = securityPasswordService.randomPassword(); + employeeDao.updatePassword(employeeId, SecurityPasswordService.getEncryptPwd(password)); + return ResponseDTO.ok(password); + } + + + /** + * 查询全部员工 + */ + public ResponseDTO> queryAllEmployee(Boolean disabledFlag) { + List employeeList = employeeDao.selectEmployeeByDisabledAndDeleted(disabledFlag, Boolean.FALSE); + return ResponseDTO.ok(employeeList); + } + + /** + * 根据登录名获取员工 + */ + public EmployeeEntity getByLoginName(String loginName) { + return employeeDao.getByLoginName(loginName, false); + } + + /** + * 根据条件分页查询不等于用户列表的所有用户 + * + * @param warmFlowInteractiveTypeVo 用户编号集合 + * @return 用户信息集合信息 + */ + public Page selectNotUserList(Page page, WarmFlowInteractiveTypeVO warmFlowInteractiveTypeVo){ + return employeeDao.selectNotUserPage(page, warmFlowInteractiveTypeVo); + } + + /** + * 根据条件分页查询不等于用户列表的所有用户 + * + * @param warmFlowInteractiveTypeVo 用户编号集合 + * @return 用户信息集合信息 + */ + public Page selectUserList(Page page, WarmFlowInteractiveTypeVO warmFlowInteractiveTypeVo){ + return employeeDao.selectUserPage(page, warmFlowInteractiveTypeVo); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/controller/LoginController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/controller/LoginController.java new file mode 100644 index 0000000..5cd9017 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/controller/LoginController.java @@ -0,0 +1,86 @@ +package net.lab1024.sa.admin.module.system.login.controller; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.extra.servlet.JakartaServletUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.login.domain.LoginForm; +import net.lab1024.sa.admin.module.system.login.domain.LoginResultVO; +import net.lab1024.sa.admin.module.system.login.service.LoginService; +import net.lab1024.sa.admin.util.AdminRequestUtil; +import net.lab1024.sa.base.common.annoation.NoNeedLogin; +import net.lab1024.sa.base.common.constant.RequestHeaderConst; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.module.support.captcha.domain.CaptchaVO; +import net.lab1024.sa.base.module.support.securityprotect.service.Level3ProtectConfigService; +import org.springframework.web.bind.annotation.*; + +/** + * 员工登录 + * + * @Date 2021-12-15 21:05:46 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_LOGIN) +public class LoginController { + + @Resource + private LoginService loginService; + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + @NoNeedLogin + @PostMapping("/login") + @Operation(summary = "登录 @author 卓大") + public ResponseDTO login(@Valid @RequestBody LoginForm loginForm, HttpServletRequest request) { + String ip = JakartaServletUtil.getClientIP(request); + String userAgent = JakartaServletUtil.getHeaderIgnoreCase(request, RequestHeaderConst.USER_AGENT); + return loginService.login(loginForm, ip, userAgent); + } + + @GetMapping("/login/getLoginInfo") + @Operation(summary = "获取登录结果信息 @author 卓大") + public ResponseDTO getLoginInfo() { + String tokenValue = StpUtil.getTokenValue(); + LoginResultVO loginResult = loginService.getLoginResult(AdminRequestUtil.getRequestUser(), tokenValue); + loginResult.setToken(tokenValue); + return ResponseDTO.ok(loginResult); + } + + @Operation(summary = "退出登陆 @author 卓大") + @GetMapping("/login/logout") + public ResponseDTO logout() { + return loginService.logout(SmartRequestUtil.getRequestUser()); + } + + @Operation(summary = "获取验证码 @author 卓大") + @GetMapping("/login/getCaptcha") + @NoNeedLogin + public ResponseDTO getCaptcha() { + return loginService.getCaptcha(); + } + + @NoNeedLogin + @GetMapping("/login/sendEmailCode/{loginName}") + @Operation(summary = "获取邮箱登录验证码 @author 卓大") + public ResponseDTO sendEmailCode(@PathVariable String loginName) { + return loginService.sendEmailCode(loginName); + } + + + @NoNeedLogin + @GetMapping("/login/getTwoFactorLoginFlag") + @Operation(summary = "获取双因子登录标识 @author 卓大") + public ResponseDTO getTwoFactorLoginFlag() { + // 双因子登录 + boolean twoFactorLoginEnabled = level3ProtectConfigService.isTwoFactorLoginEnabled(); + return ResponseDTO.ok(twoFactorLoginEnabled); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/LoginForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/LoginForm.java new file mode 100644 index 0000000..d452638 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/LoginForm.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.system.login.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.constant.LoginDeviceEnum; +import net.lab1024.sa.base.module.support.captcha.domain.CaptchaForm; +import org.hibernate.validator.constraints.Length; + +/** + * 员工登录 + * + * @Date 2021-12-19 11:49:45 + * @Author wzh + */ +@Data +public class LoginForm extends CaptchaForm { + + @Schema(description = "登录账号") + @NotBlank(message = "登录账号不能为空") + @Length(max = 30, message = "登录账号最多30字符") + private String loginName; + + @Schema(description = "密码") + @NotBlank(message = "密码不能为空") + private String password; + + @SchemaEnum(desc = "登录终端", value = LoginDeviceEnum.class) + @CheckEnum(value = LoginDeviceEnum.class, required = true, message = "此终端不允许登录") + private Integer loginDevice; + + @Schema(description = "邮箱验证码") + private String emailCode; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/LoginResultVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/LoginResultVO.java new file mode 100644 index 0000000..0f6c0c1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/LoginResultVO.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.admin.module.system.login.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; +import net.minidev.json.annotate.JsonIgnore; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 登录结果信息 + * + * @Date 2021-12-19 11:49:45 + * @Author wzh + */ +@Data +public class LoginResultVO extends RequestEmployee { + + @Schema(description = "token") + private String token; + + @Schema(description = "菜单列表") + private List menuList; + + @Schema(description = "是否需要修改密码") + private Boolean needUpdatePwdFlag; + + @Schema(description = "上次登录ip") + private String lastLoginIp; + + @Schema(description = "上次登录ip地区") + private String lastLoginIpRegion; + + @Schema(description = "上次登录user-agent") + private String lastLoginUserAgent; + + @Schema(description = "上次登录时间") + private LocalDateTime lastLoginTime; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/RequestEmployee.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/RequestEmployee.java new file mode 100644 index 0000000..eba4712 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/domain/RequestEmployee.java @@ -0,0 +1,89 @@ +package net.lab1024.sa.admin.module.system.login.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.enumeration.GenderEnum; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +/** + * 请求员工登录信息 + * + * @Date 2021/8/4 21:15 + * @Author wzh + */ +@Data +public class RequestEmployee implements RequestUser { + + @Schema(description = "员工id") + private Long employeeId; + + @SchemaEnum(UserTypeEnum.class) + private UserTypeEnum userType; + + @Schema(description = "登录账号") + private String loginName; + + @Schema(description = "员工名称") + private String actualName; + + @Schema(description = "头像") + private String avatar; + + @SchemaEnum(GenderEnum.class) + private Integer gender; + + @Schema(description = "手机号码") + private String phone; + + @Schema(description = "部门id") + private Long departmentId; + + @Schema(description = "部门名称") + private String departmentName; + + @Schema(description = "职务级别ID") + private Long positionId; + + @Schema(description = "邮箱") + private String email; + + @Schema(description = "是否禁用") + private Boolean disabledFlag; + + @Schema(description = "是否为超管") + private Boolean administratorFlag; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "请求ip") + private String ip; + + @Schema(description = "请求user-agent") + private String userAgent; + + @Schema(description = "角色名称汇总(逗号分隔)") + private String roleNames; + + @Override + public Long getUserId() { + return employeeId; + } + + @Override + public String getUserName() { + return actualName; + } + + @Override + public String getLoginAccount() { + return loginName; + } + + @Override + public String getRoleNames() { + return roleNames; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/service/LoginService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/service/LoginService.java new file mode 100644 index 0000000..c78b1c4 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/login/service/LoginService.java @@ -0,0 +1,599 @@ +package net.lab1024.sa.admin.module.system.login.service; + +import cn.dev33.satoken.stp.StpInterface; +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.lang.UUID; +import cn.hutool.core.util.NumberUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.extra.servlet.JakartaServletUtil; +import com.googlecode.concurrentlinkedhashmap.ConcurrentLinkedHashMap; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.department.service.DepartmentService; +import net.lab1024.sa.admin.module.system.employee.domain.entity.EmployeeEntity; +import net.lab1024.sa.admin.module.system.employee.service.EmployeeService; +import net.lab1024.sa.admin.module.system.login.domain.LoginForm; +import net.lab1024.sa.admin.module.system.login.domain.LoginResultVO; +import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; +import net.lab1024.sa.admin.module.system.role.service.RoleMenuService; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.constant.RequestHeaderConst; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.UserPermission; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.common.util.SmartIpUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.constant.LoginDeviceEnum; +import net.lab1024.sa.base.constant.RedisKeyConst; +import net.lab1024.sa.base.module.support.apiencrypt.service.ApiEncryptService; +import net.lab1024.sa.base.module.support.captcha.CaptchaService; +import net.lab1024.sa.base.module.support.captcha.domain.CaptchaVO; +import net.lab1024.sa.base.module.support.config.ConfigKeyEnum; +import net.lab1024.sa.base.module.support.config.ConfigService; +import net.lab1024.sa.base.module.support.file.service.IFileStorageService; +import net.lab1024.sa.base.module.support.loginlog.LoginLogResultEnum; +import net.lab1024.sa.base.module.support.loginlog.LoginLogService; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogEntity; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogVO; +import net.lab1024.sa.base.module.support.mail.MailService; +import net.lab1024.sa.base.module.support.mail.constant.MailTemplateCodeEnum; +import net.lab1024.sa.base.module.support.redis.RedisService; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailEntity; +import net.lab1024.sa.base.module.support.securityprotect.service.*; +import org.apache.commons.lang3.BooleanUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.*; +import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; + +/** + * 登录 + * + * @Date 2021-12-01 22:56:34 + * @Author wzh + */ +@Slf4j +@Service +public class LoginService implements StpInterface { + + /** + * 万能密码的 sa token loginId 前缀 + */ + private static final String SUPER_PASSWORD_LOGIN_ID_PREFIX = "S"; + + /** + * 最大在线缓存人数 + */ + private static final long CACHE_MAX_ONLINE_PERSON_COUNT = 1000L; + + /** + * 登录信息二级缓存 + */ + private final ConcurrentMap loginEmployeeCache = new ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(CACHE_MAX_ONLINE_PERSON_COUNT).build(); + + + /** + * 权限 缓存 + */ + private final ConcurrentMap permissionCache = new ConcurrentLinkedHashMap.Builder().maximumWeightedCapacity(CACHE_MAX_ONLINE_PERSON_COUNT).build(); + + @Resource + private EmployeeService employeeService; + + @Resource + private DepartmentService departmentService; + + @Resource + private CaptchaService captchaService; + + @Resource + private ConfigService configService; + + @Resource + private LoginLogService loginLogService; + + @Resource + private RoleEmployeeService roleEmployeeService; + + @Resource + private RoleMenuService roleMenuService; + + @Resource + private SecurityLoginService securityLoginService; + + @Resource + private SecurityPasswordService protectPasswordService; + + @Resource + private IFileStorageService fileStorageService; + + @Resource + private ApiEncryptService apiEncryptService; + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + @Resource + private MailService mailService; + + @Resource + private RedisService redisService; + + /** + * 获取验证码 + */ + public ResponseDTO getCaptcha() { + return ResponseDTO.ok(captchaService.generateCaptcha()); + } + + /** + * 员工登陆 + * + * @return 返回用户登录信息 + */ + public ResponseDTO login(LoginForm loginForm, String ip, String userAgent) { + + LoginDeviceEnum loginDeviceEnum = SmartEnumUtil.getEnumByValue(loginForm.getLoginDevice(), LoginDeviceEnum.class); + if (loginDeviceEnum == null) { + return ResponseDTO.userErrorParam("登录设备暂不支持!"); + } + + // 校验 图形验证码 + ResponseDTO checkCaptcha = captchaService.checkCaptcha(loginForm); + if (!checkCaptcha.getOk()) { + return ResponseDTO.error(UserErrorCode.PARAM_ERROR, checkCaptcha.getMsg()); + } + + // 验证登录名 + EmployeeEntity employeeEntity = employeeService.getByLoginName(loginForm.getLoginName()); + if (null == employeeEntity) { + return ResponseDTO.userErrorParam("登录名或密码错误!"); + } + + // 验证账号状态 + if (employeeEntity.getDeletedFlag()) { + saveLoginLog(employeeEntity, ip, userAgent, "账号已删除", LoginLogResultEnum.LOGIN_FAIL, loginDeviceEnum); + return ResponseDTO.userErrorParam("您的账号已被删除,请联系工作人员!"); + } + + if (employeeEntity.getDisabledFlag()) { + saveLoginLog(employeeEntity, ip, userAgent, "账号已禁用", LoginLogResultEnum.LOGIN_FAIL, loginDeviceEnum); + return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!"); + } + + // 解密前端加密的密码 + String requestPassword = apiEncryptService.decrypt(loginForm.getPassword()); + + // 验证密码 是否为万能密码 + String superPassword = configService.getConfigValue(ConfigKeyEnum.SUPER_PASSWORD); + boolean superPasswordFlag = superPassword.equals(requestPassword); + + // 校验双因子登录 + ResponseDTO validateEmailCode = validateEmailCode(loginForm, employeeEntity, superPasswordFlag); + if (!validateEmailCode.getOk()) { + return ResponseDTO.error(validateEmailCode); + } + + // 万能密码特殊操作 + if (superPasswordFlag) { + + // 对于万能密码:受限制sa token 要求loginId唯一,万能密码只能插入一段uuid + String saTokenLoginId = SUPER_PASSWORD_LOGIN_ID_PREFIX + StringConst.COLON + UUID.randomUUID().toString().replace("-", "") + StringConst.COLON + employeeEntity.getEmployeeId(); + // 万能密码登录只能登录30分钟 + StpUtil.login(saTokenLoginId, 1800); + + } else { + + // 按照等保登录要求,进行登录失败次数校验 + ResponseDTO loginFailEntityResponseDTO = securityLoginService.checkLogin(employeeEntity.getEmployeeId(), UserTypeEnum.ADMIN_EMPLOYEE); + if (!loginFailEntityResponseDTO.getOk()) { + return ResponseDTO.error(loginFailEntityResponseDTO); + } + + // 密码错误 + if (!SecurityPasswordService.matchesPwd(requestPassword, employeeEntity.getLoginPwd())) { + // 记录登录失败 + saveLoginLog(employeeEntity, ip, userAgent, "密码错误", LoginLogResultEnum.LOGIN_FAIL, loginDeviceEnum); + // 记录等级保护次数 + String msg = securityLoginService.recordLoginFail(employeeEntity.getEmployeeId(), UserTypeEnum.ADMIN_EMPLOYEE, employeeEntity.getLoginName(), loginFailEntityResponseDTO.getData()); + return msg == null ? ResponseDTO.userErrorParam("登录名或密码错误!") : ResponseDTO.error(UserErrorCode.LOGIN_FAIL_WILL_LOCK, msg); + } + + String saTokenLoginId = UserTypeEnum.ADMIN_EMPLOYEE.getValue() + StringConst.COLON + employeeEntity.getEmployeeId(); + + // 登录 + StpUtil.login(saTokenLoginId, String.valueOf(loginDeviceEnum.getDesc())); + + // 移除邮箱验证码 + deleteEmailCode(employeeEntity.getEmployeeId()); + } + + // 获取员工信息 + RequestEmployee requestEmployee = loadLoginInfo(employeeEntity); + + // 放入缓存 + loginEmployeeCache.put(employeeEntity.getEmployeeId(), requestEmployee); + + // 移除登录失败 + securityLoginService.removeLoginFail(employeeEntity.getEmployeeId(), UserTypeEnum.ADMIN_EMPLOYEE); + + // 获取登录结果信息 + String token = StpUtil.getTokenValue(); + LoginResultVO loginResultVO = getLoginResult(requestEmployee, token); + + //保存登录记录 + saveLoginLog(employeeEntity, ip, userAgent, superPasswordFlag ? "万能密码登录" : StringConst.EMPTY, LoginLogResultEnum.LOGIN_SUCCESS, loginDeviceEnum); + + // 设置 token + loginResultVO.setToken(token); + + // 清除权限缓存 + permissionCache.remove(employeeEntity.getEmployeeId()); + + return ResponseDTO.ok(loginResultVO); + } + + + /** + * 获取登录结果信息 + */ + public LoginResultVO getLoginResult(RequestEmployee requestEmployee, String token) { + + // 基础信息 + LoginResultVO loginResultVO = SmartBeanUtil.copy(requestEmployee, LoginResultVO.class); + + // 前端菜单和功能点清单 + List roleList = roleEmployeeService.getRoleIdList(requestEmployee.getEmployeeId()); + List menuAndPointsList = roleMenuService.getMenuList(roleList.stream().map(RoleVO::getRoleId).collect(Collectors.toList()), requestEmployee.getAdministratorFlag()); + loginResultVO.setMenuList(menuAndPointsList); + + // 更新下后端权限缓存 + UserPermission userPermission = getUserPermission(requestEmployee.getUserId()); + permissionCache.put(requestEmployee.getUserId(), userPermission); + + // 上次登录信息 + LoginLogVO loginLogVO = loginLogService.queryLastByUserId(requestEmployee.getEmployeeId(), UserTypeEnum.ADMIN_EMPLOYEE, LoginLogResultEnum.LOGIN_SUCCESS); + if (loginLogVO != null) { + loginResultVO.setLastLoginIp(loginLogVO.getLoginIp()); + loginResultVO.setLastLoginIpRegion(loginLogVO.getLoginIpRegion()); + loginResultVO.setLastLoginTime(loginLogVO.getCreateTime()); + loginResultVO.setLastLoginUserAgent(loginLogVO.getUserAgent()); + } + + // 是否需要强制修改密码 + boolean needChangePasswordFlag = protectPasswordService.checkNeedChangePassword(requestEmployee.getUserType().getValue(), requestEmployee.getUserId()); + loginResultVO.setNeedUpdatePwdFlag(needChangePasswordFlag); + + // 万能密码登录,则不需要设置强制修改密码 + String loginIdByToken = (String) StpUtil.getLoginIdByToken(token); + if (loginIdByToken != null && loginIdByToken.startsWith(SUPER_PASSWORD_LOGIN_ID_PREFIX)) { + loginResultVO.setNeedUpdatePwdFlag(false); + } + + return loginResultVO; + } + + + /** + * 获取登录的用户信息 + */ + private RequestEmployee loadLoginInfo(EmployeeEntity employeeEntity) { + + // 基础信息 + RequestEmployee requestEmployee = SmartBeanUtil.copy(employeeEntity, RequestEmployee.class); + requestEmployee.setUserType(UserTypeEnum.ADMIN_EMPLOYEE); + + // 部门信息 + DepartmentVO department = departmentService.getDepartmentById(employeeEntity.getDepartmentId()); + requestEmployee.setDepartmentName(null == department ? StringConst.EMPTY : department.getName()); + + // 角色名称(操作日志审计展示) + List roleList = roleEmployeeService.getRoleIdList(employeeEntity.getEmployeeId()); + if (roleList != null && !roleList.isEmpty()) { + String roleNames = roleList.stream().map(RoleVO::getRoleName).filter(Objects::nonNull).collect(Collectors.joining(",")); + requestEmployee.setRoleNames(roleNames); + } else { + requestEmployee.setRoleNames(StringConst.EMPTY); + } + + // 头像信息 + String avatar = employeeEntity.getAvatar(); + if (StringUtils.isNotBlank(avatar)) { + ResponseDTO getFileUrl = fileStorageService.getFileUrl(avatar); + if (BooleanUtils.isTrue(getFileUrl.getOk())) { + requestEmployee.setAvatar(getFileUrl.getData()); + } + } + + return requestEmployee; + } + + + /** + * 根据登陆token 获取员请求工信息 + */ + public RequestEmployee getLoginEmployee(String loginId, HttpServletRequest request) { + if (loginId == null) { + return null; + } + + Long requestEmployeeId = getEmployeeIdByLoginId(loginId); + if (requestEmployeeId == null) { + return null; + } + + RequestEmployee requestEmployee = loginEmployeeCache.get(requestEmployeeId); + if (requestEmployee == null) { + // 员工基本信息 + EmployeeEntity employeeEntity = employeeService.getById(requestEmployeeId); + if (employeeEntity == null) { + return null; + } + + requestEmployee = this.loadLoginInfo(employeeEntity); + loginEmployeeCache.put(requestEmployeeId, requestEmployee); + } + + // 更新请求ip和user agent + requestEmployee.setUserAgent(JakartaServletUtil.getHeaderIgnoreCase(request, RequestHeaderConst.USER_AGENT)); + requestEmployee.setIp(JakartaServletUtil.getClientIP(request)); + + return requestEmployee; + } + + /** + * 根据 loginId 获取 员工id + */ + Long getEmployeeIdByLoginId(String loginId) { + + if (loginId == null) { + return null; + } + + try { + // 如果是 万能密码 登录的用户 + String employeeIdStr = null; + if (loginId.startsWith(SUPER_PASSWORD_LOGIN_ID_PREFIX)) { + employeeIdStr = loginId.split(StringConst.COLON)[2]; + } else { + employeeIdStr = loginId.substring(2); + } + + return Long.parseLong(employeeIdStr); + } catch (Exception e) { + log.error("loginId parse error , loginId : {}", loginId, e); + return null; + } + } + + + /** + * 退出登录 + */ + public ResponseDTO logout(RequestUser requestUser) { + + // sa token 登出 + StpUtil.logout(); + + // 清空登录信息缓存 + loginEmployeeCache.remove(requestUser.getUserId()); + + //保存登出日志 + LoginLogEntity loginEntity = LoginLogEntity.builder() + .userId(requestUser.getUserId()) + .userType(requestUser.getUserType().getValue()) + .userName(requestUser.getUserName()) + .userAgent(requestUser.getUserAgent()) + .loginIp(requestUser.getIp()) + .loginIpRegion(SmartIpUtil.getRegion(requestUser.getIp())) + .loginResult(LoginLogResultEnum.LOGIN_OUT.getValue()) + .createTime(LocalDateTime.now()) + .build(); + loginLogService.log(loginEntity); + + return ResponseDTO.ok(); + } + + /** + * 清除员工登录缓存 + */ + public void clearLoginEmployeeCache(Long employeeId) { + // 清空登录信息缓存 + loginEmployeeCache.remove(employeeId); + } + + /** + * 保存登录日志 + */ + private void saveLoginLog(EmployeeEntity employeeEntity, String ip, String userAgent, String remark, LoginLogResultEnum result, LoginDeviceEnum loginDeviceEnum) { + LoginLogEntity loginEntity = LoginLogEntity.builder() + .userId(employeeEntity.getEmployeeId()) + .userType(UserTypeEnum.ADMIN_EMPLOYEE.getValue()) + .userName(employeeEntity.getActualName()) + .userAgent(userAgent) + .loginIp(ip) + .loginIpRegion(SmartIpUtil.getRegion(ip)) + .remark(remark) + .loginDevice(loginDeviceEnum.getDesc()) + .loginResult(result.getValue()) + .createTime(LocalDateTime.now()) + .build(); + loginLogService.log(loginEntity); + } + + + @Override + public List getPermissionList(Object loginId, String loginType) { + Long employeeId = this.getEmployeeIdByLoginId((String) loginId); + if (employeeId == null) { + return Collections.emptyList(); + } + + UserPermission userPermission = permissionCache.get(employeeId); + if (userPermission == null) { + userPermission = getUserPermission(employeeId); + permissionCache.put(employeeId, userPermission); + } + + return userPermission.getPermissionList(); + } + + @Override + public List getRoleList(Object loginId, String loginType) { + Long employeeId = this.getEmployeeIdByLoginId((String) loginId); + if (employeeId == null) { + return Collections.emptyList(); + } + + UserPermission userPermission = permissionCache.get(employeeId); + if (userPermission == null) { + userPermission = getUserPermission(employeeId); + permissionCache.put(employeeId, userPermission); + } + return userPermission.getRoleList(); + } + + /** + * 获取用户的权限(包含 角色列表、权限列表) + */ + private UserPermission getUserPermission(Long employeeId) { + + UserPermission userPermission = new UserPermission(); + userPermission.setPermissionList(new ArrayList<>()); + userPermission.setRoleList(new ArrayList<>()); + + // 角色列表 + List roleList = roleEmployeeService.getRoleIdList(employeeId); + userPermission.getRoleList().addAll(roleList.stream().map(RoleVO::getRoleCode).collect(Collectors.toSet())); + + // 前端菜单和功能点清单 + EmployeeEntity employeeEntity = employeeService.getById(employeeId); + + List menuAndPointsList = roleMenuService.getMenuList(roleList.stream().map(RoleVO::getRoleId).collect(Collectors.toList()), employeeEntity.getAdministratorFlag()); + + // 权限列表 + HashSet permissionSet = new HashSet<>(); + for (MenuVO menu : menuAndPointsList) { + if (menu.getPermsType() == null) { + continue; + } + + String perms = menu.getApiPerms(); + if (StringUtils.isEmpty(perms)) { + continue; + } + //接口权限 + String[] split = perms.split(","); + permissionSet.addAll(Arrays.asList(split)); + } + userPermission.getPermissionList().addAll(permissionSet); + + return userPermission; + } + + /** + * 发送 邮箱 验证码 + */ + public ResponseDTO sendEmailCode(String loginName) { + + // 开启双因子登录 + if (!level3ProtectConfigService.isTwoFactorLoginEnabled()) { + return ResponseDTO.userErrorParam("无需使用邮箱验证码"); + } + + // 验证登录名 + EmployeeEntity employeeEntity = employeeService.getByLoginName(loginName); + if (null == employeeEntity) { + return ResponseDTO.ok(); + } + + // 验证账号状态 + if (employeeEntity.getDeletedFlag()) { + return ResponseDTO.userErrorParam("您的账号已被删除,请联系工作人员!"); + } + + if (employeeEntity.getDisabledFlag()) { + return ResponseDTO.userErrorParam("您的账号已被禁用,请联系工作人员!"); + } + + String mail = employeeEntity.getEmail(); + if (SmartStringUtil.isBlank(mail)) { + return ResponseDTO.userErrorParam("您暂未配置邮箱地址,请联系管理员配置邮箱"); + } + + // 校验验证码发送时间,60秒内不能重复发生 + String redisVerificationCodeKey = redisService.generateRedisKey(RedisKeyConst.Support.LOGIN_VERIFICATION_CODE, UserTypeEnum.ADMIN_EMPLOYEE.getValue() + RedisKeyConst.SEPARATOR + employeeEntity.getEmployeeId()); + String emailCode = redisService.get(redisVerificationCodeKey); + long sendCodeTimeMills = -1; + if (!SmartStringUtil.isEmpty(emailCode)) { + sendCodeTimeMills = NumberUtil.parseLong(emailCode.split(StringConst.UNDERLINE)[1]); + } + + if (System.currentTimeMillis() - sendCodeTimeMills < 60 * 1000) { + return ResponseDTO.userErrorParam("邮箱验证码已发送,一分钟内请勿重复发送"); + } + + //生成验证码 + long currentTimeMillis = System.currentTimeMillis(); + String verificationCode = RandomUtil.randomNumbers(4); + redisService.set(redisVerificationCodeKey, verificationCode + StringConst.UNDERLINE + currentTimeMillis, 300); + + // 发送邮件验证码 + HashMap mailParams = new HashMap<>(); + mailParams.put("code", verificationCode); + return mailService.sendMail(MailTemplateCodeEnum.LOGIN_VERIFICATION_CODE, mailParams, Collections.singletonList(employeeEntity.getEmail())); + } + + + /** + * 校验邮箱验证码 + */ + private ResponseDTO validateEmailCode(LoginForm loginForm, EmployeeEntity employeeEntity, boolean superPasswordFlag) { + // 万能密码则不校验 + if (superPasswordFlag) { + return ResponseDTO.ok(); + } + + // 未开启双因子登录 + if (!level3ProtectConfigService.isTwoFactorLoginEnabled()) { + return ResponseDTO.ok(); + } + + if (SmartStringUtil.isEmpty(loginForm.getEmailCode())) { + return ResponseDTO.userErrorParam("请输入邮箱验证码"); + } + + // 校验验证码 + String redisVerificationCodeKey = redisService.generateRedisKey(RedisKeyConst.Support.LOGIN_VERIFICATION_CODE, UserTypeEnum.ADMIN_EMPLOYEE.getValue() + RedisKeyConst.SEPARATOR + employeeEntity.getEmployeeId()); + String emailCode = redisService.get(redisVerificationCodeKey); + if (SmartStringUtil.isEmpty(emailCode)) { + return ResponseDTO.userErrorParam("邮箱验证码已失效,请重新发送"); + } + + if (!emailCode.split(StringConst.UNDERLINE)[0].equals(loginForm.getEmailCode().trim())) { + return ResponseDTO.userErrorParam("邮箱验证码错误,请重新填写"); + } + + return ResponseDTO.ok(); + } + + /** + * 移除邮箱验证码 + */ + private void deleteEmailCode(Long employeeId) { + String redisVerificationCodeKey = redisService.generateRedisKey(RedisKeyConst.Support.LOGIN_VERIFICATION_CODE, UserTypeEnum.ADMIN_EMPLOYEE.getValue() + RedisKeyConst.SEPARATOR + employeeId); + redisService.delete(redisVerificationCodeKey); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuPermsTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuPermsTypeEnum.java new file mode 100644 index 0000000..757392c --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuPermsTypeEnum.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.admin.module.system.menu.constant; + + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 权限类型 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +public enum MenuPermsTypeEnum implements BaseEnum { + /** + * sa-token + */ + SA_TOKEN(1, "Sa-Token模式"), + + ; + + private final Integer value; + + private final String desc; + + + MenuPermsTypeEnum(Integer value, String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public Integer getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuTypeEnum.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuTypeEnum.java new file mode 100644 index 0000000..e0f0d41 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/constant/MenuTypeEnum.java @@ -0,0 +1,45 @@ +package net.lab1024.sa.admin.module.system.menu.constant; + + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 菜单类型枚举 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +public enum MenuTypeEnum implements BaseEnum { + /** + * 目录 + */ + CATALOG(1, "目录"), + /** + * 菜单 + */ + MENU(2, "菜单"), + /** + * 功能点 + */ + POINTS(3, "功能点"); + + private final Integer value; + + private final String desc; + + + MenuTypeEnum(Integer value, String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public Integer getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/controller/MenuController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/controller/MenuController.java new file mode 100644 index 0000000..99f7ac1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/controller/MenuController.java @@ -0,0 +1,80 @@ +package net.lab1024.sa.admin.module.system.menu.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.menu.domain.form.MenuAddForm; +import net.lab1024.sa.admin.module.system.menu.domain.form.MenuUpdateForm; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuTreeVO; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; +import net.lab1024.sa.admin.module.system.menu.service.MenuService; +import net.lab1024.sa.base.common.domain.RequestUrlVO; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 菜单 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_MENU) +public class MenuController { + + @Resource + private MenuService menuService; + + @Operation(summary = "添加菜单 @author 卓大") + @PostMapping("/menu/add") + @SaCheckPermission("system:menu:add") + public ResponseDTO addMenu(@RequestBody @Valid MenuAddForm menuAddForm) { + menuAddForm.setCreateUserId(SmartRequestUtil.getRequestUserId()); + return menuService.addMenu(menuAddForm); + } + + @Operation(summary = "更新菜单 @author 卓大") + @PostMapping("/menu/update") + @SaCheckPermission("system:menu:update") + public ResponseDTO updateMenu(@RequestBody @Valid MenuUpdateForm menuUpdateForm) { + menuUpdateForm.setUpdateUserId(SmartRequestUtil.getRequestUserId()); + return menuService.updateMenu(menuUpdateForm); + } + + @Operation(summary = "批量删除菜单 @author 卓大") + @GetMapping("/menu/batchDelete") + @SaCheckPermission("system:menu:batchDelete") + public ResponseDTO batchDeleteMenu(@RequestParam("menuIdList") List menuIdList) { + return menuService.batchDeleteMenu(menuIdList, SmartRequestUtil.getRequestUserId()); + } + + @Operation(summary = "查询菜单列表 @author 卓大") + @GetMapping("/menu/query") + public ResponseDTO> queryMenuList() { + return ResponseDTO.ok(menuService.queryMenuList(null)); + } + + @Operation(summary = "查询菜单详情 @author 卓大") + @GetMapping("/menu/detail/{menuId}") + public ResponseDTO getMenuDetail(@PathVariable Long menuId) { + return menuService.getMenuDetail(menuId); + } + + @Operation(summary = "查询菜单树 @author 卓大") + @GetMapping("/menu/tree") + public ResponseDTO> queryMenuTree(@RequestParam("onlyMenu") Boolean onlyMenu) { + return menuService.queryMenuTree(onlyMenu); + } + + @Operation(summary = "获取所有请求路径 @author 卓大") + @GetMapping("/menu/auth/url") + public ResponseDTO> getAuthUrl() { + return menuService.getAuthUrl(); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/dao/MenuDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/dao/MenuDao.java new file mode 100644 index 0000000..441c0ea --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/dao/MenuDao.java @@ -0,0 +1,93 @@ +package net.lab1024.sa.admin.module.system.menu.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; +import net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; + +import java.util.List; + +/** + * 菜单 dao + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Mapper +public interface MenuDao extends BaseMapper { + + /** + * 根据名称查询同一级下的菜单 + * + * @param menuName 菜单名 + * @param parentId 父级id + * @param deletedFlag 是否删除 + */ + MenuEntity getByMenuName(@Param("menuName") String menuName, @Param("parentId") Long parentId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 根据前端权限字符串查询菜单 + * + * @param webPerms 前端权限字符串 + * @param deletedFlag 是否删除 + */ + MenuEntity getByWebPerms(@Param("webPerms") String webPerms, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 根据菜单ID删除菜单(逻辑删除) + * + * @param menuIdList 菜单id集合 + * @param updateUserId 操作人id + * @param deletedFlag 是否删除 + */ + void deleteByMenuIdList(@Param("menuIdList") List menuIdList, @Param("updateUserId") Long updateUserId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 查询菜单列表 + * + * @param deletedFlag 是否删除 + * @param disabledFlag 是否禁用 + * @param menuTypeList 菜单类型集合 + */ + List queryMenuList(@Param("deletedFlag") Boolean deletedFlag, @Param("disabledFlag") Boolean disabledFlag, @Param("menuTypeList") List menuTypeList); + + + /** + * 根据菜单ID 查询功能点列表 + * + * @param menuId 菜单id + * @param menuType 菜单类型 + * @param deletedFlag 删除标记 + */ + List getPointListByMenuId(@Param("menuId") Long menuId, @Param("menuType") Integer menuType, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 根据员工ID查询菜单列表 + * + * @param deletedFlag 是否删除 + * @param disabledFlag 禁用标识 + * @param employeeId 员工id + */ + List queryMenuByEmployeeId(@Param("deletedFlag") Boolean deletedFlag, + @Param("disabledFlag") Boolean disabledFlag, + @Param("employeeId") Long employeeId); + + /** + * 根据菜单类型查询 + * + * @param menuType 菜单类型 + * @param deletedFlag 删除 + * @param disabledFlag 禁用 + */ + List queryMenuByType(@Param("menuType") Integer menuType, + @Param("deletedFlag") Boolean deletedFlag, + @Param("disabledFlag") Boolean disabledFlag); + + /** + * 查询孩子id + * + */ + List selectMenuIdByParentIdList(@Param("menuIdList") List menuIdList); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/entity/MenuEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/entity/MenuEntity.java new file mode 100644 index 0000000..cbccc3f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/entity/MenuEntity.java @@ -0,0 +1,133 @@ +package net.lab1024.sa.admin.module.system.menu.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.admin.module.system.menu.constant.MenuTypeEnum; + +import java.time.LocalDateTime; + +/** + * 菜单 表 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +@TableName(value = "t_menu") +public class MenuEntity { + + /** + * 菜单ID + */ + @TableId(type = IdType.AUTO) + private Long menuId; + + /** + * 菜单名称 + */ + private String menuName; + + /** + * 类型 + * + * @see MenuTypeEnum + */ + private Integer menuType; + + /** + * 父菜单ID + */ + private Long parentId; + + /** + * 显示顺序 + */ + private Integer sort; + + /** + * 路由地址 + */ + private String path; + + /** + * 组件路径 + */ + private String component; + + /** + * 是否为外链 + */ + private Boolean frameFlag; + + /** + * 外链地址 + */ + private String frameUrl; + + /** + * 是否缓存 + */ + private Boolean cacheFlag; + + /** + * 显示状态 + */ + private Boolean visibleFlag; + + /** + * 禁用状态 + */ + private Boolean disabledFlag; + + /** + * 后端权限字符串 + */ + private String apiPerms; + + /** + * 权限类型 + */ + private Integer permsType; + + /** + * 前端权限字符串 + */ + private String webPerms; + + /** + * 菜单图标 + */ + private String icon; + + /** + * 功能点关联菜单ID + */ + private Long contextMenuId; + + /** + * 删除状态 + */ + private Boolean deletedFlag; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 创建人 + */ + private Long createUserId; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 更新人 + */ + private Long updateUserId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuAddForm.java new file mode 100644 index 0000000..534dda3 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuAddForm.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.admin.module.system.menu.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 菜单 添加表单 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +public class MenuAddForm extends MenuBaseForm { + + @Schema(hidden = true) + private Long createUserId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuBaseForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuBaseForm.java new file mode 100644 index 0000000..33a84b4 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuBaseForm.java @@ -0,0 +1,78 @@ +package net.lab1024.sa.admin.module.system.menu.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.admin.module.system.menu.constant.MenuPermsTypeEnum; +import net.lab1024.sa.admin.module.system.menu.constant.MenuTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 菜单基础 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +public class MenuBaseForm { + + @Schema(description = "菜单名称") + @NotBlank(message = "菜单名称不能为空") + @Length(max = 30, message = "菜单名称最多30个字符") + private String menuName; + + @SchemaEnum(value = MenuTypeEnum.class, desc = "类型") + @CheckEnum(value = MenuTypeEnum.class, message = "类型错误") + private Integer menuType; + + @Schema(description = "父菜单ID 无上级可传0") + @NotNull(message = "父菜单ID不能为空") + private Long parentId; + + @Schema(description = "显示顺序") + private Integer sort; + + @Schema(description = "路由地址") + private String path; + + @Schema(description = "组件路径") + private String component; + + @Schema(description = "是否为外链") + @NotNull(message = "是否为外链不能为空") + private Boolean frameFlag; + + @Schema(description = "外链地址") + private String frameUrl; + + @Schema(description = "是否缓存") + @NotNull(message = "是否缓存不能为空") + private Boolean cacheFlag; + + @Schema(description = "显示状态") + @NotNull(message = "显示状态不能为空") + private Boolean visibleFlag; + + @Schema(description = "禁用状态") + @NotNull(message = "禁用状态不能为空") + private Boolean disabledFlag; + + @SchemaEnum(value = MenuPermsTypeEnum.class, desc = "权限类型 ") + @CheckEnum(value = MenuPermsTypeEnum.class, message = "权限类型") + private Integer permsType; + + @Schema(description = "前端权限字符串") + private String webPerms; + + @Schema(description = "后端端权限字符串") + private String apiPerms; + + @Schema(description = "菜单图标") + private String icon; + + @Schema(description = "功能点关联菜单ID") + private Long contextMenuId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuPointsOperateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuPointsOperateForm.java new file mode 100644 index 0000000..e8c1ae6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuPointsOperateForm.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.admin.module.system.menu.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.util.List; + +/** + * 菜单功能点操作Form + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +public class MenuPointsOperateForm { + + @Schema(description = "菜单ID") + private Long menuId; + + @Schema(description = "功能点名称") + @NotBlank(message = "功能点不能为空") + @Length(max = 30, message = "功能点最多30个字符") + private String menuName; + + @Schema(description = "禁用状态") + @NotNull(message = "禁用状态不能为空") + private Boolean disabledFlag; + + @Schema(description = "后端接口权限集合") + private List apiPermsList; + + @Schema(description = "权限字符串") + private String webPerms; + + @Schema(description = "功能点关联菜单ID") + private Long contextMenuId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuUpdateForm.java new file mode 100644 index 0000000..c384406 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/form/MenuUpdateForm.java @@ -0,0 +1,22 @@ +package net.lab1024.sa.admin.module.system.menu.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 菜单 更新Form + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +public class MenuUpdateForm extends MenuBaseForm { + + @Schema(description = "菜单ID") + @NotNull(message = "菜单ID不能为空") + private Long menuId; + + @Schema(hidden = true) + private Long updateUserId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuSimpleTreeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuSimpleTreeVO.java new file mode 100644 index 0000000..52d981b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuSimpleTreeVO.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.admin.module.system.menu.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 简易的菜单VO + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +public class MenuSimpleTreeVO { + + @Schema(description = "菜单ID") + private Long menuId; + + @Schema(description = "菜单名称") + private String menuName; + + @Schema(description = "功能点关联菜单ID") + private Long contextMenuId; + + @Schema(description = "父级菜单ID") + private Long parentId; + + @Schema(description = "菜单类型") + private Integer menuType; + + @Schema(description = "子菜单") + private List children; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuTreeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuTreeVO.java new file mode 100644 index 0000000..77ac54e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuTreeVO.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.system.menu.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 菜单 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +public class MenuTreeVO extends MenuVO{ + + @Schema(description = "菜单子集") + private List children; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuVO.java new file mode 100644 index 0000000..028a31b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/domain/vo/MenuVO.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.system.menu.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.system.menu.domain.form.MenuBaseForm; + +import java.time.LocalDateTime; + +/** + * 菜单 + * + * @Date 2022-03-06 22:04:37 + * @Author wzh + */ +@Data +public class MenuVO extends MenuBaseForm { + + @Schema(description = "菜单ID") + private Long menuId; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "创建人") + private Long createUserId; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @Schema(description = "更新人") + private Long updateUserId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuService.java new file mode 100644 index 0000000..5dd3e02 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/menu/service/MenuService.java @@ -0,0 +1,229 @@ +package net.lab1024.sa.admin.module.system.menu.service; + +import cn.hutool.core.collection.CollectionUtil; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.menu.constant.MenuTypeEnum; +import net.lab1024.sa.admin.module.system.menu.dao.MenuDao; +import net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity; +import net.lab1024.sa.admin.module.system.menu.domain.form.MenuAddForm; +import net.lab1024.sa.admin.module.system.menu.domain.form.MenuBaseForm; +import net.lab1024.sa.admin.module.system.menu.domain.form.MenuUpdateForm; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuTreeVO; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; +import net.lab1024.sa.base.common.code.SystemErrorCode; +import net.lab1024.sa.base.common.domain.RequestUrlVO; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 菜单 + * + * @Date 2022-03-08 22:15:09 + * @Author wzh + */ +@Service +public class MenuService { + + @Resource + private MenuDao menuDao; + + @Resource + private List authUrl; + + /** + * 添加菜单 + * + */ + public synchronized ResponseDTO addMenu(MenuAddForm menuAddForm) { + // 校验菜单名称 + if (this.validateMenuName(menuAddForm)) { + return ResponseDTO.userErrorParam("菜单名称已存在"); + } + // 校验前端权限字符串 + if (this.validateWebPerms(menuAddForm)) { + return ResponseDTO.userErrorParam("前端权限字符串已存在"); + } + MenuEntity menuEntity = SmartBeanUtil.copy(menuAddForm, MenuEntity.class); + menuDao.insert(menuEntity); + return ResponseDTO.ok(); + } + + /** + * 更新菜单 + * + */ + public synchronized ResponseDTO updateMenu(MenuUpdateForm menuUpdateForm) { + //校验菜单是否存在 + MenuEntity selectMenu = menuDao.selectById(menuUpdateForm.getMenuId()); + if (selectMenu == null) { + return ResponseDTO.userErrorParam("菜单不存在"); + } + if (selectMenu.getDeletedFlag()) { + return ResponseDTO.userErrorParam("菜单已被删除"); + } + //校验菜单名称 + if (this.validateMenuName(menuUpdateForm)) { + return ResponseDTO.userErrorParam("菜单名称已存在"); + } + // 校验前端权限字符串 + if (this.validateWebPerms(menuUpdateForm)) { + return ResponseDTO.userErrorParam("前端权限字符串已存在"); + } + if (menuUpdateForm.getMenuId().equals(menuUpdateForm.getParentId())) { + return ResponseDTO.userErrorParam("上级菜单不能为自己"); + } + MenuEntity menuEntity = SmartBeanUtil.copy(menuUpdateForm, MenuEntity.class); + menuDao.updateById(menuEntity); + return ResponseDTO.ok(); + } + + + /** + * 批量删除菜单 + * + */ + public synchronized ResponseDTO batchDeleteMenu(List menuIdList, Long employeeId) { + if (CollectionUtils.isEmpty(menuIdList)) { + return ResponseDTO.userErrorParam("所选菜单不能为空"); + } + menuDao.deleteByMenuIdList(menuIdList, employeeId, Boolean.TRUE); + //孩子节点也需要删除 + this.recursiveDeleteChildren(menuIdList, employeeId); + return ResponseDTO.ok(); + } + + private void recursiveDeleteChildren(List menuIdList, Long employeeId) { + List childrenMenuIdList = menuDao.selectMenuIdByParentIdList(menuIdList); + if (CollectionUtil.isEmpty(childrenMenuIdList)) { + return; + } + menuDao.deleteByMenuIdList(childrenMenuIdList, employeeId, Boolean.TRUE); + recursiveDeleteChildren(childrenMenuIdList, employeeId); + } + + /** + * 校验菜单名称 + * + */ + public Boolean validateMenuName(T menuDTO) { + MenuEntity menu = menuDao.getByMenuName(menuDTO.getMenuName(), menuDTO.getParentId(), Boolean.FALSE); + if (menuDTO instanceof MenuAddForm) { + return menu != null; + } + if (menuDTO instanceof MenuUpdateForm) { + Long menuId = ((MenuUpdateForm) menuDTO).getMenuId(); + return menu != null && menu.getMenuId().longValue() != menuId.longValue(); + } + return true; + } + + /** + * 校验前端权限字符串 + * + * @return true 重复 false 未重复 + */ + public Boolean validateWebPerms(T menuDTO) { + MenuEntity menu = menuDao.getByWebPerms(menuDTO.getWebPerms(), Boolean.FALSE); + if (menuDTO instanceof MenuAddForm) { + return menu != null; + } + if (menuDTO instanceof MenuUpdateForm) { + Long menuId = ((MenuUpdateForm) menuDTO).getMenuId(); + return menu != null && menu.getMenuId().longValue() != menuId.longValue(); + } + return true; + } + + /** + * 查询菜单列表 + * + */ + public List queryMenuList(Boolean disabledFlag) { + List menuVOList = menuDao.queryMenuList(Boolean.FALSE, disabledFlag, null); + //根据ParentId进行分组 + Map> parentMap = menuVOList.stream().collect(Collectors.groupingBy(MenuVO::getParentId, Collectors.toList())); + return this.filterNoParentMenu(parentMap, NumberUtils.LONG_ZERO); + } + + /** + * 过滤没有上级菜单的菜单列表 + * + */ + private List filterNoParentMenu(Map> parentMap, Long parentId) { + // 获取本级菜单树List + List res = parentMap.getOrDefault(parentId, Lists.newArrayList()); + List childMenu = Lists.newArrayList(); + // 循环遍历下级菜单 + res.forEach(e -> { + List menuList = this.filterNoParentMenu(parentMap, e.getMenuId()); + childMenu.addAll(menuList); + }); + res.addAll(childMenu); + return res; + } + + /** + * 查询菜单树 + * + * @param onlyMenu 不查询功能点 + */ + public ResponseDTO> queryMenuTree(Boolean onlyMenu) { + List menuTypeList = Lists.newArrayList(); + if (onlyMenu) { + menuTypeList = Lists.newArrayList(MenuTypeEnum.CATALOG.getValue(), MenuTypeEnum.MENU.getValue()); + } + List menuVOList = menuDao.queryMenuList(Boolean.FALSE, null, menuTypeList); + //根据ParentId进行分组 + Map> parentMap = menuVOList.stream().collect(Collectors.groupingBy(MenuVO::getParentId, Collectors.toList())); + List menuTreeVOList = this.buildMenuTree(parentMap, NumberUtils.LONG_ZERO); + return ResponseDTO.ok(menuTreeVOList); + } + + /** + * 构建菜单树 + * + */ + List buildMenuTree(Map> parentMap, Long parentId) { + // 获取本级菜单树List + List res = parentMap.getOrDefault(parentId, Lists.newArrayList()).stream() + .map(e -> SmartBeanUtil.copy(e, MenuTreeVO.class)).collect(Collectors.toList()); + // 循环遍历下级菜单 + res.forEach(e -> { + e.setChildren(this.buildMenuTree(parentMap, e.getMenuId())); + }); + return res; + } + + /** + * 查询菜单详情 + * + */ + public ResponseDTO getMenuDetail(Long menuId) { + //校验菜单是否存在 + MenuEntity selectMenu = menuDao.selectById(menuId); + if (selectMenu == null) { + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, "菜单不存在"); + } + if (selectMenu.getDeletedFlag()) { + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, "菜单已被删除"); + } + MenuVO menuVO = SmartBeanUtil.copy(selectMenu, MenuVO.class); + return ResponseDTO.ok(menuVO); + } + + /** + * 获取系统所有请求路径 + */ + public ResponseDTO> getAuthUrl() { + return ResponseDTO.ok(authUrl); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/message/AdminMessageController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/message/AdminMessageController.java new file mode 100644 index 0000000..40922e2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/message/AdminMessageController.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.admin.module.system.message; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.ValidateList; +import net.lab1024.sa.base.module.support.message.domain.MessageQueryForm; +import net.lab1024.sa.base.module.support.message.domain.MessageSendForm; +import net.lab1024.sa.base.module.support.message.domain.MessageVO; +import net.lab1024.sa.base.module.support.message.service.MessageService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + + +/** + * 后管 消息路由 + * + * @author: 卓大 + * @date: 2025/04/09 20:55 + */ +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_MESSAGE) +@RestController +public class AdminMessageController { + + @Autowired + private MessageService messageService; + + @Operation(summary = "通知消息-新建 @author 卓大") + @PostMapping("/message/sendMessages") + @SaCheckPermission("system:message:send") + public ResponseDTO sendMessages(@RequestBody @Valid ValidateList messageList) { + messageService.sendMessage(messageList); + return ResponseDTO.ok(); + } + + @Operation(summary = "通知消息-分页查询 @author 卓大") + @PostMapping("/message/query") + @SaCheckPermission("system:message:query") + public ResponseDTO> query(@RequestBody @Valid MessageQueryForm queryForm) { + return ResponseDTO.ok(messageService.query(queryForm)); + } + + @Operation(summary = "通知消息-删除 @author 卓大") + @GetMapping("/message/delete/{messageId}") + @SaCheckPermission("system:message:delete") + public ResponseDTO delete(@PathVariable Long messageId) { + return messageService.delete(messageId); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/controller/PositionController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/controller/PositionController.java new file mode 100644 index 0000000..de8f25d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/controller/PositionController.java @@ -0,0 +1,70 @@ +package net.lab1024.sa.admin.module.system.position.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionAddForm; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionQueryForm; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionUpdateForm; +import net.lab1024.sa.admin.module.system.position.domain.vo.PositionVO; +import net.lab1024.sa.admin.module.system.position.service.PositionService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.ValidateList; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 职务表 Controller + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_POSITION) +public class PositionController { + + @Resource + private PositionService positionService; + + @Operation(summary = "分页查询") + @PostMapping("/position/queryPage") + public ResponseDTO> queryPage(@RequestBody @Valid PositionQueryForm queryForm) { + return ResponseDTO.ok(positionService.queryPage(queryForm)); + } + + @Operation(summary = "添加") + @PostMapping("/position/add") + public ResponseDTO add(@RequestBody @Valid PositionAddForm addForm) { + return positionService.add(addForm); + } + + @Operation(summary = "更新") + @PostMapping("/position/update") + public ResponseDTO update(@RequestBody @Valid PositionUpdateForm updateForm) { + return positionService.update(updateForm); + } + + @Operation(summary = "批量删除") + @PostMapping("/position/batchDelete") + public ResponseDTO batchDelete(@RequestBody ValidateList idList) { + return positionService.batchDelete(idList); + } + + @Operation(summary = "单个删除") + @GetMapping("/position/delete/{positionId}") + public ResponseDTO batchDelete(@PathVariable Long positionId) { + return positionService.delete(positionId); + } + + + @Operation(summary = "不分页查询") + @GetMapping("/position/queryList") + public ResponseDTO> queryList() { + return ResponseDTO.ok(positionService.queryList()); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/dao/PositionDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/dao/PositionDao.java new file mode 100644 index 0000000..c5fcee2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/dao/PositionDao.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.admin.module.system.position.dao; + +import java.util.List; +import net.lab1024.sa.admin.module.system.position.domain.entity.PositionEntity; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionQueryForm; +import net.lab1024.sa.admin.module.system.position.domain.vo.PositionVO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +/** + * 职务表 Dao + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Mapper +public interface PositionDao extends BaseMapper { + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") PositionQueryForm queryForm); + + + /** + * 查询 + * @param deletedFlag + * @return + */ + List queryList(@Param("deletedFlag") Boolean deletedFlag); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/entity/PositionEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/entity/PositionEntity.java new file mode 100644 index 0000000..167e695 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/entity/PositionEntity.java @@ -0,0 +1,60 @@ +package net.lab1024.sa.admin.module.system.position.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; + +import java.time.LocalDateTime; + +import lombok.Data; + +/** + * 职务表 实体类 + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Data +@TableName("t_position") +public class PositionEntity { + + /** + * 职务ID + */ + @TableId(type = IdType.AUTO) + private Long positionId; + + /** + * 职务名称 + */ + private String positionName; + + /** + * 职级 + */ + private String level; + + /** + * 排序 + */ + private Integer sort; + + /** + * 备注 + */ + private String remark; + + private Boolean deletedFlag; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionAddForm.java new file mode 100644 index 0000000..a56702d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionAddForm.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.system.position.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 职务表 新建表单 + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Data +public class PositionAddForm { + + @Schema(description = "职务名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "职务名称 不能为空") + private String positionName; + + @Schema(description = "职级") + private String level; + + @Schema(description = "排序") + @NotNull(message = "排序不能为空") + private Integer sort; + + @Schema(description = "备注") + private String remark; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionQueryForm.java new file mode 100644 index 0000000..0d4a8c9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionQueryForm.java @@ -0,0 +1,22 @@ +package net.lab1024.sa.admin.module.system.position.domain.form; + +import net.lab1024.sa.base.common.domain.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 职务表 分页查询表单 + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Data +public class PositionQueryForm extends PageParam{ + + @Schema(description = "关键字查询") + private String keywords; + + @Schema(hidden = true) + private Boolean deletedFlag; +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionUpdateForm.java new file mode 100644 index 0000000..e338f76 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/form/PositionUpdateForm.java @@ -0,0 +1,21 @@ +package net.lab1024.sa.admin.module.system.position.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 职务表 更新表单 + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Data +public class PositionUpdateForm extends PositionAddForm { + + @Schema(description = "职务ID", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "职务ID 不能为空") + private Long positionId; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/vo/PositionVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/vo/PositionVO.java new file mode 100644 index 0000000..9ddd7f9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/domain/vo/PositionVO.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.admin.module.system.position.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * 职务表 列表VO + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Data +public class PositionVO { + + + @Schema(description = "职务ID") + private Long positionId; + + @Schema(description = "职务名称") + private String positionName; + + @Schema(description = "职级") + private String level; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/manager/PositionManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/manager/PositionManager.java new file mode 100644 index 0000000..6db7c16 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/manager/PositionManager.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.system.position.manager; + +import net.lab1024.sa.admin.module.system.position.dao.PositionDao; +import net.lab1024.sa.admin.module.system.position.domain.entity.PositionEntity; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + * 职务表 Manager + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ +@Service +public class PositionManager extends ServiceImpl { + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/service/PositionService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/service/PositionService.java new file mode 100644 index 0000000..7c5b53e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/position/service/PositionService.java @@ -0,0 +1,104 @@ +package net.lab1024.sa.admin.module.system.position.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.position.dao.PositionDao; +import net.lab1024.sa.admin.module.system.position.domain.entity.PositionEntity; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionAddForm; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionQueryForm; +import net.lab1024.sa.admin.module.system.position.domain.form.PositionUpdateForm; +import net.lab1024.sa.admin.module.system.position.domain.vo.PositionVO; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 职务表 Service + * + * @Author wzh + * @Date 2024-06-23 23:31:38 + */ + +@Service +public class PositionService { + + @Resource + private PositionDao positionDao; + + /** + * 分页查询 + * + * @param queryForm + * @return + */ + public PageResult queryPage(PositionQueryForm queryForm) { + queryForm.setDeletedFlag(Boolean.FALSE); + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = positionDao.queryPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, list); + return pageResult; + } + + /** + * 添加 + */ + public ResponseDTO add(PositionAddForm addForm) { + PositionEntity positionEntity = SmartBeanUtil.copy(addForm, PositionEntity.class); + positionDao.insert(positionEntity); + return ResponseDTO.ok(); + } + + /** + * 更新 + * + * @param updateForm + * @return + */ + public ResponseDTO update(PositionUpdateForm updateForm) { + PositionEntity positionEntity = SmartBeanUtil.copy(updateForm, PositionEntity.class); + positionDao.updateById(positionEntity); + return ResponseDTO.ok(); + } + + /** + * 批量删除 + * + * @param idList + * @return + */ + public ResponseDTO batchDelete(List idList) { + if (CollectionUtils.isEmpty(idList)){ + return ResponseDTO.ok(); + } + + positionDao.deleteBatchIds(idList); + return ResponseDTO.ok(); + } + + /** + * 单个删除 + */ + public ResponseDTO delete(Long positionId) { + if (null == positionId){ + return ResponseDTO.ok(); + } + + positionDao.deleteById(positionId); + return ResponseDTO.ok(); + } + + /** + * 分页查询 + * + * @return + */ + public List queryList() { + List list = positionDao.queryList(Boolean.FALSE); + return list; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleController.java new file mode 100644 index 0000000..70011ae --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleController.java @@ -0,0 +1,64 @@ +package net.lab1024.sa.admin.module.system.role.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleAddForm; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import net.lab1024.sa.admin.module.system.role.service.RoleService; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 角色 + * + * @Date 2021-12-14 19:40:28 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_ROLE) +public class RoleController { + + @Resource + private RoleService roleService; + + @Operation(summary = "添加角色 @author 卓大") + @PostMapping("/role/add") + @SaCheckPermission("system:role:add") + public ResponseDTO addRole(@Valid @RequestBody RoleAddForm roleAddForm) { + return roleService.addRole(roleAddForm); + } + + @Operation(summary = "删除角色 @author 卓大") + @GetMapping("/role/delete/{roleId}") + @SaCheckPermission("system:role:delete") + public ResponseDTO deleteRole(@PathVariable Long roleId) { + return roleService.deleteRole(roleId); + } + + @Operation(summary = "更新角色 @author 卓大") + @PostMapping("/role/update") + @SaCheckPermission("system:role:update") + public ResponseDTO updateRole(@Valid @RequestBody RoleUpdateForm roleUpdateDTO) { + return roleService.updateRole(roleUpdateDTO); + } + + @Operation(summary = "获取角色数据 @author 卓大") + @GetMapping("/role/get/{roleId}") + public ResponseDTO getRole(@PathVariable("roleId") Long roleId) { + return roleService.getRoleById(roleId); + } + + @Operation(summary = "获取所有角色 @author 卓大") + @GetMapping("/role/getAll") + public ResponseDTO> getAllRole() { + return roleService.getAllRole(); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleDataScopeController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleDataScopeController.java new file mode 100644 index 0000000..28bca46 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleDataScopeController.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.system.role.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleDataScopeUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleDataScopeVO; +import net.lab1024.sa.admin.module.system.role.service.RoleDataScopeService; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 角色的数据权限配置 + * + * @Date 2022-02-26 22:09:59 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_ROLE_DATA_SCOPE) +public class RoleDataScopeController { + + @Resource + private RoleDataScopeService roleDataScopeService; + + @Operation(summary = "获取某角色所设置的数据范围 @author 卓大") + @GetMapping("/role/dataScope/getRoleDataScopeList/{roleId}") + public ResponseDTO> dataScopeListByRole(@PathVariable Long roleId) { + return roleDataScopeService.getRoleDataScopeList(roleId); + } + + @Operation(summary = "批量设置某角色数据范围 @author 卓大") + @PostMapping("/role/dataScope/updateRoleDataScopeList") + @SaCheckPermission("system:role:dataScope:update") + public ResponseDTO updateRoleDataScopeList(@RequestBody @Valid RoleDataScopeUpdateForm roleDataScopeUpdateForm) { + return roleDataScopeService.updateRoleDataScopeList(roleDataScopeUpdateForm); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleEmployeeController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleEmployeeController.java new file mode 100644 index 0000000..41fae56 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleEmployeeController.java @@ -0,0 +1,71 @@ +package net.lab1024.sa.admin.module.system.role.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleEmployeeQueryForm; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleEmployeeUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleSelectedVO; +import net.lab1024.sa.admin.module.system.role.service.RoleEmployeeService; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 角色的员工 + * + * @Date 2022-02-26 22:09:59 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_ROLE_EMPLOYEE) +public class RoleEmployeeController { + + @Resource + private RoleEmployeeService roleEmployeeService; + + @Operation(summary = "查询某个角色下的员工列表 @author 卓大") + @PostMapping("/role/employee/queryEmployee") + public ResponseDTO> queryEmployee(@Valid @RequestBody RoleEmployeeQueryForm roleEmployeeQueryForm) { + return roleEmployeeService.queryEmployee(roleEmployeeQueryForm); + } + + @Operation(summary = "获取某个角色下的所有员工列表(无分页) @author 卓大") + @GetMapping("/role/employee/getAllEmployeeByRoleId/{roleId}") + public ResponseDTO> listAllEmployeeRoleId(@PathVariable Long roleId) { + return ResponseDTO.ok(roleEmployeeService.getAllEmployeeByRoleId(roleId)); + } + + @Operation(summary = "从角色成员列表中移除员工 @author 卓大") + @GetMapping("/role/employee/removeEmployee") + @SaCheckPermission("system:role:employee:delete") + public ResponseDTO removeEmployee(Long employeeId, Long roleId) { + return roleEmployeeService.removeRoleEmployee(employeeId, roleId); + } + + @Operation(summary = "从角色成员列表中批量移除员工 @author 卓大") + @PostMapping("/role/employee/batchRemoveRoleEmployee") + @SaCheckPermission("system:role:employee:batch:delete") + public ResponseDTO batchRemoveEmployee(@Valid @RequestBody RoleEmployeeUpdateForm updateForm) { + return roleEmployeeService.batchRemoveRoleEmployee(updateForm); + } + + @Operation(summary = "角色成员列表中批量添加员工 @author 卓大") + @PostMapping("/role/employee/batchAddRoleEmployee") + @SaCheckPermission("system:role:employee:add") + public ResponseDTO addEmployeeList(@Valid @RequestBody RoleEmployeeUpdateForm addForm) { + return roleEmployeeService.batchAddRoleEmployee(addForm); + } + + @Operation(summary = "获取员工所有选中的角色和所有角色 @author 卓大") + @GetMapping("/role/employee/getRoles/{employeeId}") + public ResponseDTO> getRoleByEmployeeId(@PathVariable Long employeeId) { + return ResponseDTO.ok(roleEmployeeService.getRoleInfoListByEmployeeId(employeeId)); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleMenuController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleMenuController.java new file mode 100644 index 0000000..3f08708 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/controller/RoleMenuController.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.admin.module.system.role.controller; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.admin.constant.AdminSwaggerTagConst; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleMenuUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleMenuTreeVO; +import net.lab1024.sa.admin.module.system.role.service.RoleMenuService; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.web.bind.annotation.*; + +/** + * 角色的菜单 + * + * @Date 2022-02-26 21:34:01 + * @Author wzh + */ +@RestController +@Tag(name = AdminSwaggerTagConst.System.SYSTEM_ROLE_MENU) +public class RoleMenuController { + + @Resource + private RoleMenuService roleMenuService; + + @Operation(summary = "更新角色权限 @author 卓大") + @PostMapping("/role/menu/updateRoleMenu") + @SaCheckPermission("system:role:menu:update") + public ResponseDTO updateRoleMenu(@Valid @RequestBody RoleMenuUpdateForm updateDTO) { + return roleMenuService.updateRoleMenu(updateDTO); + } + + @Operation(summary = "获取角色关联菜单权限 @author 卓大") + @GetMapping("/role/menu/getRoleSelectedMenu/{roleId}") + public ResponseDTO getRoleSelectedMenu(@PathVariable Long roleId) { + return roleMenuService.getRoleSelectedMenu(roleId); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleDao.java new file mode 100644 index 0000000..46fcafa --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleDao.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.system.role.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentQueryForm; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleQueryForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEntity; + +import java.util.List; + +/** + * 角色 dao + * + * @Date 2022-02-26 21:34:01 + * @Author wzh + */ +@Mapper +public interface RoleDao extends BaseMapper { + + /** + * 根据角色名称查询 + */ + RoleEntity getByRoleName(@Param("roleName") String roleName); + + /** + * 根据角色编码 + */ + RoleEntity getByRoleCode(@Param("roleCode") String roleCode); + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") RoleQueryForm queryForm); + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleDataScopeDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleDataScopeDao.java new file mode 100644 index 0000000..2541426 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleDataScopeDao.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.admin.module.system.role.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleDataScopeEntity; + +import java.util.List; + + +/** + * 角色 数据权限 dao + * + * @Date 2022-02-26 21:34:01 + * @Author wzh + */ +@Mapper +public interface RoleDataScopeDao extends BaseMapper { + + /** + * 获取某个角色的设置信息 + */ + List listByRoleId(@Param("roleId") Long roleId); + + /** + * 获取某批角色的所有数据范围配置信息 + */ + List listByRoleIdList(@Param("roleIdList") List roleIdList); + + /** + * 删除某个角色的设置信息 + */ + void deleteByRoleId(@Param("roleId") Long roleId); + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleEmployeeDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleEmployeeDao.java new file mode 100644 index 0000000..75795d2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleEmployeeDao.java @@ -0,0 +1,85 @@ +package net.lab1024.sa.admin.module.system.role.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEmployeeEntity; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleEmployeeQueryForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleEmployeeVO; + +import java.util.List; +import java.util.Set; + + +/** + * 角色 员工 dao + * + * @Date 2022-03-07 18:54:42 + * @Author wzh + */ +@Mapper +public interface RoleEmployeeDao extends BaseMapper { + + /** + * 根据员工id 查询所有的角色 + */ + List selectRoleByEmployeeId(@Param("employeeId") Long employeeId); + + /** + * 根据员工id 查询所有的角色io集合 + */ + List selectRoleIdByEmployeeId(@Param("employeeId") Long employeeId); + + /** + * 根据员工id 查询所有的角色 + */ + List selectRoleIdByEmployeeIdList(@Param("employeeIdList") List employeeIdList); + + /** + * 根据员工id 查询所有的角色 + */ + List selectRoleByEmployeeIdList(@Param("employeeIdList") List employeeIdList); + + /** + * 查询角色下的人员id + */ + Set selectEmployeeIdByRoleIdList(@Param("roleIdList") List roleIdList); + + /** + * + */ + List selectRoleEmployeeByName(Page page, @Param("queryForm") RoleEmployeeQueryForm roleEmployeeQueryForm); + + /** + * + */ + List selectEmployeeByRoleId(@Param("roleId") Long roleId); + /** + * 根据员工信息删除 + */ + void deleteByEmployeeId(@Param("employeeId") Long employeeId); + + /** + * 删除某个角色的所有关系 + */ + void deleteByRoleId(@Param("roleId")Long roleId); + + /** + * 根据员工和 角色删除关系 + */ + void deleteByEmployeeIdRoleId(@Param("employeeId") Long employeeId,@Param("roleId")Long roleId); + + /** + * 批量删除某个角色下的某批用户的关联关系 + */ + void batchDeleteEmployeeRole(@Param("roleId") Long roleId, @Param("employeeIds") Set employeeIds); + + /** + * 判断某个角色下是否存在用户 + */ + Integer existsByRoleId(@Param("roleId") Long roleId); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleMenuDao.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleMenuDao.java new file mode 100644 index 0000000..ae20fca --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/dao/RoleMenuDao.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.admin.module.system.role.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleMenuEntity; + +import java.util.List; + +/** + * 角色 菜单 dao + * + * @Date 2022-03-07 18:54:42 + * @Author wzh + */ +@Mapper +public interface RoleMenuDao extends BaseMapper { + + /** + * 根据角色ID删除菜单权限 + * + */ + void deleteByRoleId(@Param("roleId") Long roleId); + + /** + * 根据角色ID查询选择的菜单权限 + * + */ + List queryMenuIdByRoleId(@Param("roleId") Long roleId); + + /** + * 根据角色ID集合查询选择的菜单权限 + * + */ + List selectMenuListByRoleIdList(@Param("roleIdList") List roleIdList, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 查询所有的菜单角色 + * + */ + List queryAllRoleMenu(); +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleDataScopeEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleDataScopeEntity.java new file mode 100644 index 0000000..e32a127 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleDataScopeEntity.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.admin.module.system.role.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeTypeEnum; +import net.lab1024.sa.admin.module.system.datascope.constant.DataScopeViewTypeEnum; + +import java.time.LocalDateTime; + +/** + * 数据范围与角色关系 + * + * @Date 2022-03-07 18:54:42 + * @Author wzh + */ +@Data +@TableName("t_role_data_scope") +public class RoleDataScopeEntity { + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long id; + /** + * 数据范围id + * {@link DataScopeTypeEnum} + */ + private Integer dataScopeType; + /** + * 数据范围类型 + * {@link DataScopeViewTypeEnum} + */ + private Integer viewType; + /** + * 角色id + */ + private Long roleId; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleEmployeeEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleEmployeeEntity.java new file mode 100644 index 0000000..0975105 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleEmployeeEntity.java @@ -0,0 +1,38 @@ +package net.lab1024.sa.admin.module.system.role.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 角色 员工关系 + * + * @Date 2022-03-07 18:54:42 + * @Author wzh + */ +@Data +@TableName("t_role_employee") +public class RoleEmployeeEntity { + + @TableId(type = IdType.AUTO) + private Long id; + + private Long roleId; + + private Long employeeId; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; + + public RoleEmployeeEntity() { + } + + public RoleEmployeeEntity(Long roleId, Long employeeId) { + this.roleId = roleId; + this.employeeId = employeeId; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleEntity.java new file mode 100644 index 0000000..67d24a7 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleEntity.java @@ -0,0 +1,49 @@ +package net.lab1024.sa.admin.module.system.role.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 角色 + * + * @Date 2022-03-07 18:54:42 + * @Author wzh + */ +@Data +@TableName("t_role") +public class RoleEntity { + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long roleId; + + /** + * 角色名称 + */ + private String roleName; + + /** + * 角色编码 + */ + private String roleCode; + + /** + * 角色备注 + */ + private String remark; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleMenuEntity.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleMenuEntity.java new file mode 100644 index 0000000..b47f0c9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/entity/RoleMenuEntity.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.admin.module.system.role.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 角色 菜单 + * + * @Date 2022-03-16 23:00:57 + * @Author wzh + */ +@Data +@TableName("t_role_menu") +public class RoleMenuEntity { + + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long roleMenuId; + + /** + * 角色 id + */ + private Long roleId; + + /** + * 菜单 id + */ + private Long menuId; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleAddForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleAddForm.java new file mode 100644 index 0000000..2bfdc1a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleAddForm.java @@ -0,0 +1,38 @@ +package net.lab1024.sa.admin.module.system.role.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 角色 添加表单 + * + * @Date 2022-02-26 19:09:42 + * @Author wzh + */ +@Data +public class RoleAddForm { + + /** + * 角色名称 + */ + @Schema(description = "角色名称") + @NotNull(message = "角色名称不能为空") + @Length(min = 1, max = 20, message = "角色名称(1-20)个字符") + private String roleName; + + @Schema(description = "角色编码") + @NotNull(message = "角色编码 不能为空") + @Length(min = 1, max = 20, message = "角色编码(1-20)个字符") + private String roleCode; + + /** + * 角色描述 + */ + @Schema(description = "角色描述") + @Length(max = 255, message = "角色描述最多255个字符") + private String remark; + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleDataScopeUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleDataScopeUpdateForm.java new file mode 100644 index 0000000..157ead1 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleDataScopeUpdateForm.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.admin.module.system.role.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +/** + * 角色的数据范围更新 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleDataScopeUpdateForm { + + @Schema(description = "角色id") + @NotNull(message = "角色id不能为空") + private Long roleId; + + @Schema(description = "设置信息") + @Valid + private List dataScopeItemList; + + + @Data + public static class RoleUpdateDataScopeListFormItem { + + @Schema(description = "数据范围类型") + @NotNull(message = "数据范围类型不能为空") + private Integer dataScopeType; + + @Schema(description = "可见范围") + @NotNull(message = "可见范围不能为空") + private Integer viewType; + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleEmployeeQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleEmployeeQueryForm.java new file mode 100644 index 0000000..009bcfd --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleEmployeeQueryForm.java @@ -0,0 +1,21 @@ +package net.lab1024.sa.admin.module.system.role.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +/** + * 角色的员工查询 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleEmployeeQueryForm extends PageParam { + + @Schema(description = "关键字") + private String keywords; + + @Schema(description = "角色id") + private String roleId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleEmployeeUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleEmployeeUpdateForm.java new file mode 100644 index 0000000..b835953 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleEmployeeUpdateForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.admin.module.system.role.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; +import java.util.Set; + +/** + * 角色的员工更新 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleEmployeeUpdateForm { + + @Schema(description = "角色id") + @NotNull(message = "角色id不能为空") + protected Long roleId; + + @Schema(description = "员工id集合") + @NotEmpty(message = "员工id不能为空") + protected Set employeeIdList; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleMenuUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleMenuUpdateForm.java new file mode 100644 index 0000000..08a7b56 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleMenuUpdateForm.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.system.role.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +/** + * 角色的菜单更新 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleMenuUpdateForm { + + /** + * 角色id + */ + @Schema(description = "角色id") + @NotNull(message = "角色id不能为空") + private Long roleId; + + /** + * 菜单ID 集合 + */ + @Schema(description = "菜单ID集合") + @NotNull(message = "菜单ID不能为空") + private List menuIdList; + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleQueryForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleQueryForm.java new file mode 100644 index 0000000..458d4c7 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleQueryForm.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.admin.module.system.role.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +import java.time.LocalDate; + +/** + * 角色 查询 + * + * @Date 2022-02-26 19:09:42 + * @Author wzh + */ +@Data +public class RoleQueryForm extends PageParam { + + @Schema(description = "角色code") + private String roleCode; + + @Schema(description = "角色名称") + private String roleName; + + @Schema(description = "角色id") + private String roleId; + + @Schema(description = "开始时间") + private LocalDate startTime; + + @Schema(description = "结束时间") + private LocalDate endTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleUpdateForm.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleUpdateForm.java new file mode 100644 index 0000000..7e7646f --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/form/RoleUpdateForm.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.admin.module.system.role.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 角色更新修改 + * + * @Date 2022-02-26 19:09:42 + * @Author wzh + */ +@Data +public class RoleUpdateForm extends RoleAddForm { + + /** + * 角色id + */ + @Schema(description = "角色id") + @NotNull(message = "角色id不能为空") + protected Long roleId; + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleDataScopeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleDataScopeVO.java new file mode 100644 index 0000000..ac931c6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleDataScopeVO.java @@ -0,0 +1,20 @@ +package net.lab1024.sa.admin.module.system.role.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 角色的数据范围 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleDataScopeVO { + + @Schema(description = "数据范围id") + private Integer dataScopeType; + + @Schema(description = "可见范围") + private Integer viewType; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleEmployeeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleEmployeeVO.java new file mode 100644 index 0000000..012c613 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleEmployeeVO.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.admin.module.system.role.domain.vo; + +import lombok.Data; + +/** + * 角色的员工 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleEmployeeVO { + + private Long roleId; + + private Long employeeId; + + private String roleName; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleMenuTreeVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleMenuTreeVO.java new file mode 100644 index 0000000..09b278d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleMenuTreeVO.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.admin.module.system.role.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuSimpleTreeVO; + +import java.util.List; + +/** + * 角色菜单树 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleMenuTreeVO { + + @Schema(description = "角色ID") + private Long roleId; + + @Schema(description = "菜单列表") + private List menuTreeList; + + @Schema(description = "选中的菜单ID") + private List selectedMenuId; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleSelectedVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleSelectedVO.java new file mode 100644 index 0000000..50d0211 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleSelectedVO.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.admin.module.system.role.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 选择角色 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleSelectedVO extends RoleVO { + + @Schema(description = "角色名称") + private Boolean selected; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleVO.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleVO.java new file mode 100644 index 0000000..144eaeb --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/domain/vo/RoleVO.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.admin.module.system.role.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 角色 + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Data +public class RoleVO { + + @Schema(description = "角色ID") + private Long roleId; + + @Schema(description = "角色名称") + private String roleName; + + @Schema(description = "角色编码") + private String roleCode; + + @Schema(description = "角色备注") + private String remark; + + /** + * 创建时间 + */ + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleDataScopeManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleDataScopeManager.java new file mode 100644 index 0000000..7052b4c --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleDataScopeManager.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.admin.module.system.role.manager; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.lab1024.sa.admin.module.system.role.dao.RoleDataScopeDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleDataScopeEntity; +import org.springframework.stereotype.Service; + +/** + * 角色 数据范围 manager + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Service +public class RoleDataScopeManager extends ServiceImpl { + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleEmployeeManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleEmployeeManager.java new file mode 100644 index 0000000..1aa0d8d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleEmployeeManager.java @@ -0,0 +1,21 @@ +package net.lab1024.sa.admin.module.system.role.manager; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEmployeeEntity; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 角色员工 manager + * + * @Date 2022-04-08 21:53:04 + * @Author wzh + */ +@Service +public class RoleEmployeeManager extends ServiceImpl { + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleMenuManager.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleMenuManager.java new file mode 100644 index 0000000..ad0dd6c --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/manager/RoleMenuManager.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.admin.module.system.role.manager; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.role.dao.RoleMenuDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleMenuEntity; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 角色-菜单 manager + * + * @Date 2022-04-09 19:05:49 + * @Author wzh + */ +@Service +public class RoleMenuManager extends ServiceImpl { + + @Resource + private RoleMenuDao roleMenuDao; + + /** + * 更新角色权限 + * + */ + @Transactional(rollbackFor = Exception.class) + public void updateRoleMenu(Long roleId, List roleMenuEntityList) { + // 根据角色ID删除菜单权限 + roleMenuDao.deleteByRoleId(roleId); + // 批量添加菜单权限 + saveBatch(roleMenuEntityList); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleDataScopeService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleDataScopeService.java new file mode 100644 index 0000000..9b747cc --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleDataScopeService.java @@ -0,0 +1,60 @@ +package net.lab1024.sa.admin.module.system.role.service; + +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleDataScopeEntity; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleDataScopeUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleDataScopeVO; +import net.lab1024.sa.admin.module.system.role.manager.RoleDataScopeManager; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.CollectionUtils; + +import java.util.List; + +/** + * 角色-数据范围 + * + * @Date 2021-10-22 23:17:47 + * @Author wzh + */ +@Service +public class RoleDataScopeService { + + @Resource + private RoleDataScopeManager roleDataScopeManager; + + + /** + * 获取某个角色的数据范围设置信息 + * + */ + public ResponseDTO> getRoleDataScopeList(Long roleId) { + List roleDataScopeEntityList = roleDataScopeManager.getBaseMapper().listByRoleId(roleId); + if (CollectionUtils.isEmpty(roleDataScopeEntityList)) { + return ResponseDTO.ok(Lists.newArrayList()); + } + List roleDataScopeList = SmartBeanUtil.copyList(roleDataScopeEntityList, RoleDataScopeVO.class); + return ResponseDTO.ok(roleDataScopeList); + } + + /** + * 批量设置某个角色的数据范围设置信息 + * + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO updateRoleDataScopeList(RoleDataScopeUpdateForm roleDataScopeUpdateForm) { + List batchSetList = roleDataScopeUpdateForm.getDataScopeItemList(); + if (CollectionUtils.isEmpty(batchSetList)) { + return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "缺少配置信息"); + } + List roleDataScopeEntityList = SmartBeanUtil.copyList(batchSetList, RoleDataScopeEntity.class); + roleDataScopeEntityList.forEach(e -> e.setRoleId(roleDataScopeUpdateForm.getRoleId())); + roleDataScopeManager.getBaseMapper().deleteByRoleId(roleDataScopeUpdateForm.getRoleId()); + roleDataScopeManager.saveBatch(roleDataScopeEntityList); + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleEmployeeService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleEmployeeService.java new file mode 100644 index 0000000..0435b6c --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleEmployeeService.java @@ -0,0 +1,152 @@ +package net.lab1024.sa.admin.module.system.role.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.department.dao.DepartmentDao; +import net.lab1024.sa.admin.module.system.department.domain.entity.DepartmentEntity; +import net.lab1024.sa.admin.module.system.employee.domain.vo.EmployeeVO; +import net.lab1024.sa.admin.module.system.role.dao.RoleDao; +import net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEmployeeEntity; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEntity; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleEmployeeQueryForm; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleEmployeeUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleSelectedVO; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import net.lab1024.sa.admin.module.system.role.manager.RoleEmployeeManager; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 角色-员工 + * + * @Date 2021-10-22 23:17:47 + * @Author wzh + */ +@Service +public class RoleEmployeeService { + + @Resource + private RoleEmployeeDao roleEmployeeDao; + @Resource + private RoleDao roleDao; + @Resource + private DepartmentDao departmentDao; + @Resource + private RoleEmployeeManager roleEmployeeManager; + + + /** + * 批量插入 + * + */ + public void batchInsert(List roleEmployeeList) { + roleEmployeeManager.saveBatch(roleEmployeeList); + } + + /** + * 通过角色id,分页获取成员员工列表 + * + */ + public ResponseDTO> queryEmployee(RoleEmployeeQueryForm roleEmployeeQueryForm) { + Page page = SmartPageUtil.convert2PageQuery(roleEmployeeQueryForm); + List employeeList = roleEmployeeDao.selectRoleEmployeeByName(page, roleEmployeeQueryForm) + .stream() + .filter(Objects::nonNull) + .collect(Collectors.toList()); + List departmentIdList = employeeList.stream().filter(e -> e != null && e.getDepartmentId() != null).map(EmployeeVO::getDepartmentId).collect(Collectors.toList()); + if (CollectionUtils.isNotEmpty(departmentIdList)) { + List departmentEntities = departmentDao.selectBatchIds(departmentIdList); + Map departmentIdNameMap = departmentEntities.stream().collect(Collectors.toMap(DepartmentEntity::getDepartmentId, DepartmentEntity::getName)); + employeeList.forEach(e -> { + e.setDepartmentName(departmentIdNameMap.getOrDefault(e.getDepartmentId(), StringConst.EMPTY)); + }); + } + PageResult pageResult = SmartPageUtil.convert2PageResult(page, employeeList, EmployeeVO.class); + return ResponseDTO.ok(pageResult); + } + + public List getAllEmployeeByRoleId(Long roleId) { + return roleEmployeeDao.selectEmployeeByRoleId(roleId); + } + + /** + * 移除员工角色 + * + */ + public ResponseDTO removeRoleEmployee(Long employeeId, Long roleId) { + if (null == employeeId || null == roleId) { + return ResponseDTO.userErrorParam(); + } + roleEmployeeDao.deleteByEmployeeIdRoleId(employeeId, roleId); + return ResponseDTO.ok(); + } + + /** + * 批量删除角色的成员员工 + * + */ + public ResponseDTO batchRemoveRoleEmployee(RoleEmployeeUpdateForm roleEmployeeUpdateForm) { + roleEmployeeDao.batchDeleteEmployeeRole(roleEmployeeUpdateForm.getRoleId(), roleEmployeeUpdateForm.getEmployeeIdList()); + return ResponseDTO.ok(); + } + + /** + * 批量添加角色的成员员工 + * + */ + public ResponseDTO batchAddRoleEmployee(RoleEmployeeUpdateForm roleEmployeeUpdateForm) { + Long roleId = roleEmployeeUpdateForm.getRoleId(); + + // 已选择的员工id列表 + Set selectedEmployeeIdList = roleEmployeeUpdateForm.getEmployeeIdList(); + // 数据库里已有的员工id列表 + Set dbEmployeeIdList = roleEmployeeDao.selectEmployeeIdByRoleIdList(Lists.newArrayList(roleId)); + // 从已选择的员工id列表里 过滤数据库里不存在的 即需要添加的员工 id + Set addEmployeeIdList = selectedEmployeeIdList.stream().filter(id -> !dbEmployeeIdList.contains(id)).collect(Collectors.toSet()); + + // 添加角色员工 + if (CollectionUtils.isNotEmpty(addEmployeeIdList)) { + List roleEmployeeList = addEmployeeIdList.stream() + .map(employeeId -> new RoleEmployeeEntity(roleId, employeeId)) + .collect(Collectors.toList()); + roleEmployeeManager.saveBatch(roleEmployeeList); + } + return ResponseDTO.ok(); + } + + /** + * 通过员工id获取员工角色 + * + */ + public List getRoleInfoListByEmployeeId(Long employeeId) { + List roleIds = roleEmployeeDao.selectRoleIdByEmployeeId(employeeId); + List roleList = roleDao.selectList(null); + List result = SmartBeanUtil.copyList(roleList, RoleSelectedVO.class); + result.stream().forEach(item -> item.setSelected(roleIds.contains(item.getRoleId()))); + return result; + } + + /** + * 根据员工id 查询角色id集合 + * + */ + public List getRoleIdList(Long employeeId) { + return roleEmployeeDao.selectRoleByEmployeeId(employeeId); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleMenuService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleMenuService.java new file mode 100644 index 0000000..547de6d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleMenuService.java @@ -0,0 +1,120 @@ +package net.lab1024.sa.admin.module.system.role.service; + +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.menu.dao.MenuDao; +import net.lab1024.sa.admin.module.system.menu.domain.entity.MenuEntity; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuSimpleTreeVO; +import net.lab1024.sa.admin.module.system.menu.domain.vo.MenuVO; +import net.lab1024.sa.admin.module.system.role.dao.RoleDao; +import net.lab1024.sa.admin.module.system.role.dao.RoleMenuDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEntity; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleMenuEntity; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleMenuUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleMenuTreeVO; +import net.lab1024.sa.admin.module.system.role.manager.RoleMenuManager; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.math.NumberUtils; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * 角色-菜单 + * + * @Date 2021-10-22 23:17:47 + * @Author wzh + */ +@Service +public class RoleMenuService { + + @Resource + private RoleDao roleDao; + @Resource + private RoleMenuDao roleMenuDao; + @Resource + private RoleMenuManager roleMenuManager; + @Resource + private MenuDao menuDao; + + /** + * 更新角色权限 + * + */ + public ResponseDTO updateRoleMenu(RoleMenuUpdateForm roleMenuUpdateForm) { + //查询角色是否存在 + Long roleId = roleMenuUpdateForm.getRoleId(); + RoleEntity roleEntity = roleDao.selectById(roleId); + if (null == roleEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + List roleMenuEntityList = Lists.newArrayList(); + RoleMenuEntity roleMenuEntity; + for (Long menuId : roleMenuUpdateForm.getMenuIdList()) { + roleMenuEntity = new RoleMenuEntity(); + roleMenuEntity.setRoleId(roleId); + roleMenuEntity.setMenuId(menuId); + roleMenuEntityList.add(roleMenuEntity); + } + roleMenuManager.updateRoleMenu(roleMenuUpdateForm.getRoleId(), roleMenuEntityList); + return ResponseDTO.ok(); + } + + /** + * 根据角色id集合,查询其所有的菜单权限 + * + */ + public List getMenuList(List roleIdList, Boolean administratorFlag) { + //管理员返回所有菜单 + if(administratorFlag){ + List menuEntityList = roleMenuDao.selectMenuListByRoleIdList(Lists.newArrayList(), false); + return SmartBeanUtil.copyList(menuEntityList, MenuVO.class); + } + //非管理员 无角色 返回空菜单 + if (CollectionUtils.isEmpty(roleIdList)) { + return new ArrayList<>(); + } + List menuEntityList = roleMenuDao.selectMenuListByRoleIdList(roleIdList, false); + return SmartBeanUtil.copyList(menuEntityList, MenuVO.class); + } + + + /** + * 获取角色关联菜单权限 + * + */ + public ResponseDTO getRoleSelectedMenu(Long roleId) { + RoleMenuTreeVO res = new RoleMenuTreeVO(); + res.setRoleId(roleId); + //查询角色ID选择的菜单权限 + List selectedMenuId = roleMenuDao.queryMenuIdByRoleId(roleId); + res.setSelectedMenuId(selectedMenuId); + //查询菜单权限 + List menuVOList = menuDao.queryMenuList(Boolean.FALSE, Boolean.FALSE, null); + Map> parentMap = menuVOList.stream().collect(Collectors.groupingBy(MenuVO::getParentId, Collectors.toList())); + List menuTreeList = this.buildMenuTree(parentMap, NumberUtils.LONG_ZERO); + res.setMenuTreeList(menuTreeList); + return ResponseDTO.ok(res); + } + + /** + * 构建菜单树 + * + */ + private List buildMenuTree(Map> parentMap, Long parentId) { + // 获取本级菜单树List + List res = parentMap.getOrDefault(parentId, Lists.newArrayList()).stream() + .map(e -> SmartBeanUtil.copy(e, MenuSimpleTreeVO.class)).collect(Collectors.toList()); + // 循环遍历下级菜单 + res.forEach(e -> { + e.setChildren(this.buildMenuTree(parentMap, e.getMenuId())); + }); + return res; + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleService.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleService.java new file mode 100644 index 0000000..cf65b99 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/role/service/RoleService.java @@ -0,0 +1,139 @@ +package net.lab1024.sa.admin.module.system.role.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.admin.module.system.department.domain.form.DepartmentQueryForm; +import net.lab1024.sa.admin.module.system.department.domain.vo.DepartmentVO; +import net.lab1024.sa.admin.module.system.role.dao.RoleDao; +import net.lab1024.sa.admin.module.system.role.dao.RoleEmployeeDao; +import net.lab1024.sa.admin.module.system.role.dao.RoleMenuDao; +import net.lab1024.sa.admin.module.system.role.domain.entity.RoleEntity; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleAddForm; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleQueryForm; +import net.lab1024.sa.admin.module.system.role.domain.form.RoleUpdateForm; +import net.lab1024.sa.admin.module.system.role.domain.vo.RoleVO; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 角色 + * + * @Date 2021-08-16 20:19:22 + * @Author wzh + */ +@Service +public class RoleService { + + @Resource + private RoleDao roleDao; + + @Resource + private RoleMenuDao roleMenuDao; + + @Resource + private RoleEmployeeDao roleEmployeeDao; + + /** + * 分页查询 + * + * @param queryForm + * @return + */ + public PageResult queryPage(RoleQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = roleDao.queryPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, list); + return pageResult; + } + + /** + * 新增添加角色 + */ + public ResponseDTO addRole(RoleAddForm roleAddForm) { + RoleEntity existRoleEntity = roleDao.getByRoleName(roleAddForm.getRoleName()); + if (null != existRoleEntity) { + return ResponseDTO.userErrorParam("角色名称重复"); + } + + existRoleEntity = roleDao.getByRoleCode(roleAddForm.getRoleCode()); + if (null != existRoleEntity) { + return ResponseDTO.userErrorParam("角色编码重复,重复的角色为:" + existRoleEntity.getRoleName()); + } + + RoleEntity roleEntity = SmartBeanUtil.copy(roleAddForm, RoleEntity.class); + roleDao.insert(roleEntity); + return ResponseDTO.ok(); + } + + /** + * 根据角色id 删除 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO deleteRole(Long roleId) { + RoleEntity roleEntity = roleDao.selectById(roleId); + if (null == roleEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + // 当没有员工绑定这个角色时才可以删除 + Integer exists = roleEmployeeDao.existsByRoleId(roleId); + if (exists != null) { + return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, "该角色下存在员工,无法删除"); + } + roleDao.deleteById(roleId); + roleMenuDao.deleteByRoleId(roleId); + roleEmployeeDao.deleteByRoleId(roleId); + return ResponseDTO.ok(); + } + + /** + * 更新角色 + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO updateRole(RoleUpdateForm roleUpdateForm) { + if (null == roleDao.selectById(roleUpdateForm.getRoleId())) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + RoleEntity existRoleEntity = roleDao.getByRoleName(roleUpdateForm.getRoleName()); + if (null != existRoleEntity && !existRoleEntity.getRoleId().equals(roleUpdateForm.getRoleId())) { + return ResponseDTO.userErrorParam("角色名称重复"); + } + + existRoleEntity = roleDao.getByRoleCode(roleUpdateForm.getRoleCode()); + if (null != existRoleEntity && !existRoleEntity.getRoleId().equals(roleUpdateForm.getRoleId())) { + return ResponseDTO.userErrorParam("角色编码重复,重复的角色为:" + existRoleEntity.getRoleName()); + } + + RoleEntity roleEntity = SmartBeanUtil.copy(roleUpdateForm, RoleEntity.class); + roleDao.updateById(roleEntity); + return ResponseDTO.ok(); + } + + /** + * 根据id获取角色数据 + */ + public ResponseDTO getRoleById(Long roleId) { + RoleEntity roleEntity = roleDao.selectById(roleId); + if (null == roleEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + RoleVO role = SmartBeanUtil.copy(roleEntity, RoleVO.class); + return ResponseDTO.ok(role); + } + + /** + * 获取所有角色列表 + */ + public ResponseDTO> getAllRole() { + List roleEntityList = roleDao.selectList(null); + List roleList = SmartBeanUtil.copyList(roleEntityList, RoleVO.class); + return ResponseDTO.ok(roleList); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminApiEncryptController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminApiEncryptController.java new file mode 100644 index 0000000..9eb0d5a --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminApiEncryptController.java @@ -0,0 +1,78 @@ +package net.lab1024.sa.admin.module.system.support; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.ValidateList; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiDecrypt; +import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiEncrypt; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * + * api 加密 + * + * @Date 2023/10/21 09:21:20 + * @Author wzh + */ + +@RestController +@Tag(name = SwaggerTagConst.Support.PROTECT) +public class AdminApiEncryptController extends SupportBaseController { + + + @ApiDecrypt + @PostMapping("/apiEncrypt/testRequestEncrypt") + @Operation(summary = "测试 请求加密") + public ResponseDTO testRequestEncrypt(@RequestBody @Valid JweForm form) { + return ResponseDTO.ok(form); + } + + @ApiEncrypt + @PostMapping("/apiEncrypt/testResponseEncrypt") + @Operation(summary = "测试 返回加密") + public ResponseDTO testResponseEncrypt(@RequestBody @Valid JweForm form) { + return ResponseDTO.ok(form); + } + + @ApiDecrypt + @ApiEncrypt + @PostMapping("/apiEncrypt/testDecryptAndEncrypt") + @Operation(summary = "测试 请求参数加密和解密、返回数据加密和解密") + public ResponseDTO testDecryptAndEncrypt(@RequestBody @Valid JweForm form) { + return ResponseDTO.ok(form); + } + + @ApiDecrypt + @ApiEncrypt + @PostMapping("/apiEncrypt/testArray") + @Operation(summary = "测试 数组加密和解密") + public ResponseDTO> testArray(@RequestBody @Valid ValidateList list) { + return ResponseDTO.ok(list); + } + + + @Data + public static class JweForm { + + @NotBlank(message = "姓名 不能为空") + String name; + + @NotNull + @Min(value = 1) + Integer age; + + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminCacheController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminCacheController.java new file mode 100644 index 0000000..1d6397e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminCacheController.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.cache.CacheService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +/** + * 缓存 + * + * @Date 2021/10/11 20:07 + * @Author wzh + */ +@RestController +@Tag(name = SwaggerTagConst.Support.CACHE) +public class AdminCacheController extends SupportBaseController { + + @Resource + private CacheService cacheService; + + @Operation(summary = "获取所有缓存 @author 罗伊") + @GetMapping("/cache/names") + @SaCheckPermission("support:cache:keys") + public ResponseDTO> cacheNames() { + return ResponseDTO.ok(cacheService.cacheNames()); + } + + @Operation(summary = "移除某个缓存 @author 罗伊") + @GetMapping("/cache/remove/{cacheName}") + @SaCheckPermission("support:cache:delete") + public ResponseDTO removeCache(@PathVariable String cacheName) { + cacheService.removeCache(cacheName); + return ResponseDTO.ok(); + } + + @Operation(summary = "获取某个缓存的所有key @author 罗伊") + @GetMapping("/cache/keys/{cacheName}") + @SaCheckPermission("support:cache:keys") + public ResponseDTO> cacheKeys(@PathVariable String cacheName) { + return ResponseDTO.ok(cacheService.cacheKey(cacheName)); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminChangeLogController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminChangeLogController.java new file mode 100644 index 0000000..559383e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminChangeLogController.java @@ -0,0 +1,58 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.ValidateList; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.changelog.domain.form.ChangeLogAddForm; +import net.lab1024.sa.base.module.support.changelog.domain.form.ChangeLogUpdateForm; +import net.lab1024.sa.base.module.support.changelog.service.ChangeLogService; +import org.springframework.web.bind.annotation.*; + +/** + * 系统更新日志 Controller + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@RestController +@Tag(name = SwaggerTagConst.Support.CHANGE_LOG) +public class AdminChangeLogController extends SupportBaseController { + + @Resource + private ChangeLogService changeLogService; + + @Operation(summary = "添加 @author 卓大") + @PostMapping("/changeLog/add") + @SaCheckPermission("support:changeLog:add") + public ResponseDTO add(@RequestBody @Valid ChangeLogAddForm addForm) { + return changeLogService.add(addForm); + } + + @Operation(summary = "更新 @author 卓大") + @PostMapping("/changeLog/update") + @SaCheckPermission("support:changeLog:update") + public ResponseDTO update(@RequestBody @Valid ChangeLogUpdateForm updateForm) { + return changeLogService.update(updateForm); + } + + @Operation(summary = "批量删除 @author 卓大") + @PostMapping("/changeLog/batchDelete") + @SaCheckPermission("support:changeLog:batchDelete") + public ResponseDTO batchDelete(@RequestBody ValidateList idList) { + return changeLogService.batchDelete(idList); + } + + @Operation(summary = "单个删除 @author 卓大") + @GetMapping("/changeLog/delete/{changeLogId}") + @SaCheckPermission("support:changeLog:delete") + public ResponseDTO batchDelete(@PathVariable Long changeLogId) { + return changeLogService.delete(changeLogId); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminConfigController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminConfigController.java new file mode 100644 index 0000000..62aa6af --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminConfigController.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.config.ConfigService; +import net.lab1024.sa.base.module.support.config.domain.ConfigAddForm; +import net.lab1024.sa.base.module.support.config.domain.ConfigQueryForm; +import net.lab1024.sa.base.module.support.config.domain.ConfigUpdateForm; +import net.lab1024.sa.base.module.support.config.domain.ConfigVO; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 配置 + * + * @Date 2022-03-14 20:46:27 + * @Author wzh + */ +@Tag(name = SwaggerTagConst.Support.CONFIG) +@RestController +public class AdminConfigController extends SupportBaseController { + + @Resource + private ConfigService configService; + + @Operation(summary = "分页查询系统配置 @author 卓大") + @PostMapping("/config/query") + @SaCheckPermission("support:config:query") + public ResponseDTO> queryConfigPage(@RequestBody @Valid ConfigQueryForm queryForm) { + return configService.queryConfigPage(queryForm); + } + + @Operation(summary = "添加配置参数 @author 卓大") + @PostMapping("/config/add") + @SaCheckPermission("support:config:add") + public ResponseDTO addConfig(@RequestBody @Valid ConfigAddForm configAddForm) { + return configService.add(configAddForm); + } + + @Operation(summary = "修改配置参数 @author 卓大") + @PostMapping("/config/update") + @SaCheckPermission("support:config:update") + public ResponseDTO updateConfig(@RequestBody @Valid ConfigUpdateForm updateForm) { + return configService.updateConfig(updateForm); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminDataMaskingDemoController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminDataMaskingDemoController.java new file mode 100644 index 0000000..1c08a2b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminDataMaskingDemoController.java @@ -0,0 +1,85 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.hutool.core.util.RandomUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import lombok.Data; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.datamasking.DataMasking; +import net.lab1024.sa.base.module.support.datamasking.DataMaskingTypeEnum; +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.List; + +/** + * 数据脱敏demo + * + * @Date 2024/08/01 22:07:27 + * @Author wzh + */ + +@RestController +@Tag(name = SwaggerTagConst.Support.DATA_MASKING) +public class AdminDataMaskingDemoController extends SupportBaseController { + + @Operation(summary = "数据脱敏demo @author 1024创新实验室-主任-卓大") + @GetMapping("/dataMasking/demo/query") + public ResponseDTO> query() { + + List list = new ArrayList<>(); + for (int i = 0; i < RandomUtil.randomInt(10,16); i++) { + DataVO data = new DataVO(); + data.setUserId(RandomUtil.randomLong(1328479238, 83274298347982L)); + data.setPhone("1" + RandomUtil.randomNumbers(10)); + data.setIdCard("410" + RandomUtil.randomNumbers(3) + RandomUtil.randomInt(1980, 2010) + RandomUtil.randomInt(10, 12) + RandomUtil.randomInt(10, 30) + RandomUtil.randomNumbers(4)); + data.setAddress(RandomUtil.randomBoolean() ? "河南省洛阳市洛龙区一零二四大街1024号" : "河南省郑州市高新区六边形大街六边形大楼"); + data.setPassword(RandomUtil.randomString(10)); + data.setEmail(RandomUtil.randomString(RandomUtil.randomInt(6, 10)) + "@" + RandomUtil.randomString(2) + ".com"); + data.setCarLicense("豫" + RandomStringUtils.randomAlphabetic(1).toUpperCase()+" " + RandomStringUtils.randomAlphanumeric(5).toUpperCase()); + data.setBankCard("6225" + RandomStringUtils.randomNumeric(14)); + data.setOther(RandomStringUtils.randomAlphanumeric(1, 12)); + list.add(data); + } + + return ResponseDTO.ok(list); + } + + + @Data + public static class DataVO { + + @DataMasking(DataMaskingTypeEnum.USER_ID) + private Long userId; + + @DataMasking(DataMaskingTypeEnum.PHONE) + private String phone; + + @DataMasking(DataMaskingTypeEnum.ID_CARD) + private String idCard; + + @DataMasking(DataMaskingTypeEnum.ADDRESS) + private String address; + + @DataMasking(DataMaskingTypeEnum.PASSWORD) + private String password; + + @DataMasking(DataMaskingTypeEnum.EMAIL) + private String email; + + @DataMasking(DataMaskingTypeEnum.CAR_LICENSE) + private String carLicense; + + @DataMasking(DataMaskingTypeEnum.BANK_CARD) + private String bankCard; + + @DataMasking + private String other; + + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminDictController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminDictController.java new file mode 100644 index 0000000..51c67a6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminDictController.java @@ -0,0 +1,142 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.ValidateList; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.dict.domain.form.*; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictDataVO; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictVO; +import net.lab1024.sa.base.module.support.dict.service.DictService; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 数据字典 Controller + * + * @Date 2025-03-25 22:25:04 + * @Author wzh + */ +@Tag(name = SwaggerTagConst.Support.DICT) +@RestController +public class AdminDictController extends SupportBaseController { + + @Resource + private DictService dictService; + + // ------------------- 获取全部数据 ------------------- + + @Operation(summary = "获取全部数据(供前端缓存使用) @author 1024创新实验室-主任-卓大") + @GetMapping("/dict/getAllDictData") + public ResponseDTO> getAll() { + return ResponseDTO.ok(dictService.getAll()); + } + + @Operation(summary = "获取所有字典code @author 1024创新实验室-主任-卓大") + @GetMapping("/dict/getAllDict") + public ResponseDTO> getAllDict() { + return ResponseDTO.ok(dictService.getAllDict()); + } + + // ------------------- 字典 ------------------- + + @Operation(summary = "分页查询 @author 1024创新实验室-主任-卓大") + @PostMapping("/dict/queryPage") + @SaCheckPermission("support:dict:query") + public ResponseDTO> queryPage(@RequestBody @Valid DictQueryForm queryForm) { + return ResponseDTO.ok(dictService.queryPage(queryForm)); + } + + @Operation(summary = "添加 @author 1024创新实验室-主任-卓大") + @PostMapping("/dict/add") + @SaCheckPermission("support:dict:add") + public ResponseDTO add(@RequestBody @Valid DictAddForm addForm) { + return dictService.add(addForm); + } + + @Operation(summary = "更新 @author 1024创新实验室-主任-卓大") + @PostMapping("/dict/update") + @SaCheckPermission("support:dict:update") + public ResponseDTO update(@RequestBody @Valid DictUpdateForm updateForm) { + return dictService.update(updateForm); + } + + @Operation(summary = "启用/禁用 @author 1024创新实验室-主任-卓大") + @GetMapping("/dict/updateDisabled/{dictId}") + @SaCheckPermission("support:dict:updateDisabled") + public ResponseDTO updateDisabled(@PathVariable Long dictId) { + return dictService.updateDisabled(dictId); + } + + @Operation(summary = "批量删除 @author 1024创新实验室-主任-卓大") + @PostMapping("/dict/batchDelete") + @SaCheckPermission("support:dict:delete") + public ResponseDTO batchDelete(@RequestBody ValidateList idList) { + return dictService.batchDelete(idList); + } + + @Operation(summary = "单个删除 @author 1024创新实验室-主任-卓大") + @GetMapping("/dict/delete/{dictId}") + @SaCheckPermission("support:dict:delete") + public ResponseDTO delete(@PathVariable Long dictId) { + return dictService.delete(dictId); + } + + // ------------------- 字典数据 ------------------- + + @Operation(summary = "字典数据 分页查询 @author 1024创新实验室-主任-卓大") + @GetMapping("/dict/dictData/queryDictData/{dictId}") + @SaCheckPermission("support:dictData:query") + public ResponseDTO> queryDictData(@PathVariable Long dictId) { + return ResponseDTO.ok(dictService.queryDictData(dictId)); + } + + @GetMapping("/dict/value/list/{dictCode}") + @SaCheckPermission("support:dictData:query") + public ResponseDTO> queryDictData(@PathVariable String dictCode) { + return ResponseDTO.ok(dictService.queryDictDataByCode(dictCode)); + } + + @Operation(summary = "字典数据 启用/禁用 @author 1024创新实验室-主任-卓大") + @GetMapping("/dict/dictData/updateDisabled/{dictDataId}") + @SaCheckPermission("support:dictData:updateDisabled") + public ResponseDTO updateDictDataDisabled(@PathVariable Long dictDataId) { + return dictService.updateDictDataDisabled(dictDataId); + } + + @Operation(summary = "字典数据 添加 @author 1024创新实验室-主任-卓大") + @PostMapping("/dict/dictData/add") + @SaCheckPermission("support:dictData:add") + public ResponseDTO addDictData(@RequestBody @Valid DictDataAddForm addForm) { + return dictService.addDictData(addForm); + } + + @Operation(summary = "字典数据 更新 @author 1024创新实验室-主任-卓大") + @PostMapping("/dict/dictData/update") + @SaCheckPermission("support:dictData:update") + public ResponseDTO updateDictData(@RequestBody @Valid DictDataUpdateForm updateForm) { + return dictService.updateDictData(updateForm); + } + + @Operation(summary = "字典数据 批量删除 @author 1024创新实验室-主任-卓大") + @PostMapping("/dict/dictData/batchDelete") + @SaCheckPermission("support:dictData:delete") + public ResponseDTO batchDeleteDictData(@RequestBody ValidateList idList) { + return dictService.batchDeleteDictData(idList); + } + + @Operation(summary = "字典数据 单个删除 @author 1024创新实验室-主任-卓大") + @GetMapping("/dict/dictData/delete/{dictDataId}") + @SaCheckPermission("support:dictData:delete") + public ResponseDTO deleteDictData(@PathVariable Long dictDataId) { + return dictService.deleteDictData(dictDataId); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminFileController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminFileController.java new file mode 100644 index 0000000..f0380cd --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminFileController.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.file.domain.form.FileQueryForm; +import net.lab1024.sa.base.module.support.file.domain.vo.FileVO; +import net.lab1024.sa.base.module.support.file.service.FileService; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 文件服务 + * + * @Date 2019年10月11日 15:34:47 + * @Author wzh + */ +@RestController +@Tag(name = SwaggerTagConst.Support.FILE) +public class AdminFileController extends SupportBaseController { + + @Resource + private FileService fileService; + + @Operation(summary = "分页查询 @author 1024创新实验室-主任-卓大") + @PostMapping("/file/queryPage") + @SaCheckPermission("support:file:query") + public ResponseDTO> queryPage(@RequestBody @Valid FileQueryForm queryForm) { + return ResponseDTO.ok(fileService.queryPage(queryForm)); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminHeartBeatController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminHeartBeatController.java new file mode 100644 index 0000000..99d052b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminHeartBeatController.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.admin.module.system.support; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.heartbeat.HeartBeatService; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordQueryForm; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordVO; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 心跳记录 + * + * @Date 2022-01-09 20:57:24 + * @Author wzh + */ +@Tag(name = SwaggerTagConst.Support.HEART_BEAT) +@RestController +public class AdminHeartBeatController extends SupportBaseController { + + @Resource + private HeartBeatService heartBeatService; + + @PostMapping("/heartBeat/query") + @Operation(summary = "查询心跳记录 @author 卓大") + public ResponseDTO> query(@RequestBody @Valid HeartBeatRecordQueryForm pageParam) { + return heartBeatService.pageQuery(pageParam); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminHelpDocController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminHelpDocController.java new file mode 100644 index 0000000..5e6b776 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminHelpDocController.java @@ -0,0 +1,101 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.*; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocDetailVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocVO; +import net.lab1024.sa.base.module.support.helpdoc.service.HelpDocCatalogService; +import net.lab1024.sa.base.module.support.helpdoc.service.HelpDocService; +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 帮助文档 + * + * @Date 2022-08-20 23:11:42 + * @Author wzh + */ +@Tag(name = SwaggerTagConst.Support.HELP_DOC) +@RestController +public class AdminHelpDocController extends SupportBaseController { + + @Resource + private HelpDocService helpDocService; + + @Resource + private HelpDocCatalogService helpDocCatalogService; + + // --------------------- 帮助文档 【目录管理】 ------------------------- + + + @Operation(summary = "帮助文档目录-添加 @author 卓大") + @PostMapping("/helpDoc/helpDocCatalog/add") + public ResponseDTO addHelpDocCatalog(@RequestBody @Valid HelpDocCatalogAddForm helpDocCatalogAddForm) { + return helpDocCatalogService.add(helpDocCatalogAddForm); + } + + @Operation(summary = "帮助文档目录-更新 @author 卓大") + @PostMapping("/helpDoc/helpDocCatalog/update") + public ResponseDTO updateHelpDocCatalog(@RequestBody @Valid HelpDocCatalogUpdateForm helpDocCatalogUpdateForm) { + return helpDocCatalogService.update(helpDocCatalogUpdateForm); + } + + @Operation(summary = "帮助文档目录-删除 @author 卓大") + @GetMapping("/helpDoc/helpDocCatalog/delete/{helpDocCatalogId}") + public ResponseDTO deleteHelpDocCatalog(@PathVariable Long helpDocCatalogId) { + return helpDocCatalogService.delete(helpDocCatalogId); + } + + // --------------------- 帮助文档 【管理:增、删、查、改】------------------------- + + @Operation(summary = "【管理】帮助文档-分页查询 @author 卓大") + @PostMapping("/helpDoc/query") + @SaCheckPermission("support:helpDoc:query") + public ResponseDTO> query(@RequestBody @Valid HelpDocQueryForm queryForm) { + return ResponseDTO.ok(helpDocService.query(queryForm)); + } + + @Operation(summary = "【管理】帮助文档-获取详情 @author 卓大") + @GetMapping("/helpDoc/getDetail/{helpDocId}") + @SaCheckPermission("support:helpDoc:add") + public ResponseDTO getDetail(@PathVariable Long helpDocId) { + return ResponseDTO.ok(helpDocService.getDetail(helpDocId)); + } + + @Operation(summary = "【管理】帮助文档-添加 @author 卓大") + @PostMapping("/helpDoc/add") + @RepeatSubmit + public ResponseDTO add(@RequestBody @Valid HelpDocAddForm addForm) { + return helpDocService.add(addForm); + } + + @Operation(summary = "【管理】帮助文档-更新 @author 卓大") + @PostMapping("/helpDoc/update") + @RepeatSubmit + public ResponseDTO update(@RequestBody @Valid HelpDocUpdateForm updateForm) { + return helpDocService.update(updateForm); + } + + @Operation(summary = "【管理】帮助文档-删除 @author 卓大") + @GetMapping("/helpDoc/delete/{helpDocId}") + public ResponseDTO delete(@PathVariable Long helpDocId) { + return helpDocService.delete(helpDocId); + } + + @Operation(summary = "【管理】帮助文档-根据关联id查询 @author 卓大") + @GetMapping("/helpDoc/queryHelpDocByRelationId/{relationId}") + public ResponseDTO> queryHelpDocByRelationId(@PathVariable Long relationId) { + return ResponseDTO.ok(helpDocService.queryHelpDocByRelationId(relationId)); + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminLoginLogController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminLoginLogController.java new file mode 100644 index 0000000..af32703 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminLoginLogController.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.loginlog.LoginLogService; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogQueryForm; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogVO; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 登录日志 + * + * @Date 2022/07/22 19:46:23 + * @Author wzh + */ +@RestController +@Tag(name = SwaggerTagConst.Support.LOGIN_LOG) +public class AdminLoginLogController extends SupportBaseController { + + @Resource + private LoginLogService loginLogService; + + @Operation(summary = "分页查询 @author 卓大") + @PostMapping("/loginLog/page/query") + @SaCheckPermission("support:loginLog:query") + public ResponseDTO> queryByPage(@RequestBody LoginLogQueryForm queryForm) { + return loginLogService.queryByPage(queryForm); + } + + @Operation(summary = "分页查询当前登录人信息 @author 善逸") + @PostMapping("/loginLog/page/query/login") + public ResponseDTO> queryByPageLogin(@RequestBody LoginLogQueryForm queryForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + queryForm.setUserId(requestUser.getUserId()); + queryForm.setUserType(requestUser.getUserType().getValue()); + return loginLogService.queryByPage(queryForm); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminOperateLogController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminOperateLogController.java new file mode 100644 index 0000000..f306212 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminOperateLogController.java @@ -0,0 +1,63 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.operatelog.OperateLogService; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogQueryForm; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogVO; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 操作日志 + * + * @Date 2021-12-08 20:48:52 + * @Author wzh + */ +@RestController +@Tag(name = SwaggerTagConst.Support.OPERATE_LOG) +public class AdminOperateLogController extends SupportBaseController { + + @Resource + private OperateLogService operateLogService; + + @Operation(summary = "分页查询 @author 罗伊") + @PostMapping("/operateLog/page/query") + @SaCheckPermission("support:operateLog:query") + public ResponseDTO> queryByPage(@RequestBody OperateLogQueryForm queryForm) { + return operateLogService.queryByPage(queryForm); + } + + @Operation(summary = "详情 @author 罗伊") + @GetMapping("/operateLog/detail/{operateLogId}") + @SaCheckPermission("support:operateLog:detail") + public ResponseDTO detail(@PathVariable Long operateLogId) { + return operateLogService.detail(operateLogId); + } + + @Operation(summary = "操作模块下拉(去重)") + @GetMapping("/operateLog/module/list") + @SaCheckPermission("support:operateLog:query") + public ResponseDTO> moduleList() { + return operateLogService.queryModuleList(); + } + + @Operation(summary = "分页查询当前登录人信息 @author 善逸") + @PostMapping("/operateLog/page/query/login") + public ResponseDTO> queryByPageLogin(@RequestBody OperateLogQueryForm queryForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + queryForm.setOperateUserId(requestUser.getUserId()); + queryForm.setOperateUserType(requestUser.getUserType().getValue()); + return operateLogService.queryByPage(queryForm); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminProtectController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminProtectController.java new file mode 100644 index 0000000..3d41dc2 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminProtectController.java @@ -0,0 +1,70 @@ +package net.lab1024.sa.admin.module.system.support; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.ValidateList; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.config.ConfigKeyEnum; +import net.lab1024.sa.base.module.support.config.ConfigService; +import net.lab1024.sa.base.module.support.securityprotect.domain.Level3ProtectConfigForm; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailQueryForm; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailVO; +import net.lab1024.sa.base.module.support.securityprotect.service.Level3ProtectConfigService; +import net.lab1024.sa.base.module.support.securityprotect.service.SecurityLoginService; +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; + +/** + * + * 网络安全 + * + * @Date 2023/10/17 19:07:27 + * @Author wzh + */ + +@RestController +@Tag(name = SwaggerTagConst.Support.PROTECT) +public class AdminProtectController extends SupportBaseController { + + @Resource + private SecurityLoginService securityLoginService; + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + @Resource + private ConfigService configService; + + + @Operation(summary = "分页查询 @author 1024创新实验室-主任-卓大") + @PostMapping("/protect/loginFail/queryPage") + public ResponseDTO> queryPage(@RequestBody @Valid LoginFailQueryForm queryForm) { + return ResponseDTO.ok(securityLoginService.queryPage(queryForm)); + } + + + @Operation(summary = "批量删除 @author 1024创新实验室-主任-卓大") + @PostMapping("/protect/loginFail/batchDelete") + public ResponseDTO batchDelete(@RequestBody ValidateList idList) { + return securityLoginService.batchDelete(idList); + } + + @Operation(summary = "更新三级等保配置 @author 1024创新实验室-主任-卓大") + @PostMapping("/protect/level3protect/updateConfig") + public ResponseDTO updateConfig(@RequestBody @Valid Level3ProtectConfigForm configForm) { + return level3ProtectConfigService.updateLevel3Config(configForm); + } + + @Operation(summary = "查询 三级等保配置 @author 1024创新实验室-主任-卓大") + @GetMapping("/protect/level3protect/getConfig") + public ResponseDTO getConfig() { + return ResponseDTO.ok(configService.getConfigValue(ConfigKeyEnum.LEVEL3_PROTECT_CONFIG)); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminReloadController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminReloadController.java new file mode 100644 index 0000000..c3ffbc6 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminReloadController.java @@ -0,0 +1,51 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.reload.ReloadService; +import net.lab1024.sa.base.module.support.reload.domain.ReloadForm; +import net.lab1024.sa.base.module.support.reload.domain.ReloadItemVO; +import net.lab1024.sa.base.module.support.reload.domain.ReloadResultVO; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * reload (内存热加载、钩子等) + * + * @Date 2015-03-02 19:11:52 + * @Author wzh + */ +@RestController +@Tag(name = SwaggerTagConst.Support.RELOAD) +public class AdminReloadController extends SupportBaseController { + + @Resource + private ReloadService reloadService; + + @Operation(summary = "查询reload列表 @author 开云") + @GetMapping("/reload/query") + public ResponseDTO> query() { + return reloadService.query(); + } + + @Operation(summary = "获取reload result @author 开云") + @GetMapping("/reload/result/{tag}") + @SaCheckPermission("support:reload:result") + public ResponseDTO> queryReloadResult(@PathVariable("tag") String tag) { + return reloadService.queryReloadItemResult(tag); + } + + @Operation(summary = "通过tag更新标识 @author 开云") + @PostMapping("/reload/update") + @SaCheckPermission("support:reload:update") + public ResponseDTO updateByTag(@RequestBody @Valid ReloadForm reloadForm) { + return reloadService.updateByTag(reloadForm); + } +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminSerialNumberController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminSerialNumberController.java new file mode 100644 index 0000000..d5c4915 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminSerialNumberController.java @@ -0,0 +1,71 @@ +package net.lab1024.sa.admin.module.system.support; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberIdEnum; +import net.lab1024.sa.base.module.support.serialnumber.dao.SerialNumberDao; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberEntity; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberGenerateForm; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberRecordEntity; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberRecordQueryForm; +import net.lab1024.sa.base.module.support.serialnumber.service.SerialNumberRecordService; +import net.lab1024.sa.base.module.support.serialnumber.service.SerialNumberService; +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 java.util.List; + +/** + * 单据序列号 + * + * @Date 2022-03-25 21:46:07 + * @Author wzh + */ +@Tag(name = SwaggerTagConst.Support.SERIAL_NUMBER) +@RestController +public class AdminSerialNumberController extends SupportBaseController { + + @Resource + private SerialNumberDao serialNumberDao; + + @Resource + private SerialNumberService serialNumberService; + + @Resource + private SerialNumberRecordService serialNumberRecordService; + + @Operation(summary = "生成单号 @author 卓大") + @PostMapping("/serialNumber/generate") + @SaCheckPermission("support:serialNumber:generate") + public ResponseDTO> generate(@RequestBody @Valid SerialNumberGenerateForm generateForm) { + SerialNumberIdEnum serialNumberIdEnum = SmartEnumUtil.getEnumByValue(generateForm.getSerialNumberId(), SerialNumberIdEnum.class); + if (null == serialNumberIdEnum) { + return ResponseDTO.userErrorParam("SerialNumberId,不存在" + generateForm.getSerialNumberId()); + } + return ResponseDTO.ok(serialNumberService.generate(serialNumberIdEnum, generateForm.getCount())); + } + + @Operation(summary = "获取所有单号定义 @author 卓大") + @GetMapping("/serialNumber/all") + public ResponseDTO> getAll() { + return ResponseDTO.ok(serialNumberDao.selectList(null)); + } + + @Operation(summary = "获取生成记录 @author 卓大") + @PostMapping("/serialNumber/queryRecord") + @SaCheckPermission("support:serialNumber:record") + public ResponseDTO> queryRecord(@RequestBody @Valid SerialNumberRecordQueryForm queryForm) { + return ResponseDTO.ok(serialNumberRecordService.query(queryForm)); + } + +} diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminSmartJobController.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminSmartJobController.java new file mode 100644 index 0000000..02e5cea --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/module/system/support/AdminSmartJobController.java @@ -0,0 +1,94 @@ +package net.lab1024.sa.admin.module.system.support; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.job.api.SmartJobService; +import net.lab1024.sa.base.module.support.job.api.domain.*; +import net.lab1024.sa.base.module.support.job.config.SmartJobAutoConfiguration; +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.web.bind.annotation.*; + +/** + * 定时任务 管理接口 + * + * @author huke + * @date 2024/6/17 20:41 + */ +@Tag(name = SwaggerTagConst.Support.JOB) +@RestController +@ConditionalOnBean(SmartJobAutoConfiguration.class) +public class AdminSmartJobController extends SupportBaseController { + + @Autowired + private SmartJobService jobService; + + @Operation(summary = "定时任务-立即执行 @huke") + @PostMapping("/job/execute") + @RepeatSubmit + public ResponseDTO execute(@RequestBody @Valid SmartJobExecuteForm executeForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + executeForm.setUpdateName(requestUser.getUserName()); + return jobService.execute(executeForm); + } + + @Operation(summary = "定时任务-查询详情 @huke") + @GetMapping("/job/{jobId}") + public ResponseDTO queryJobInfo(@PathVariable Integer jobId) { + return jobService.queryJobInfo(jobId); + } + + @Operation(summary = "定时任务-分页查询 @huke") + @PostMapping("/job/query") + public ResponseDTO> queryJob(@RequestBody @Valid SmartJobQueryForm queryForm) { + return jobService.queryJob(queryForm); + } + + @Operation(summary = "定时任务-添加任务 @huke") + @PostMapping("/job/add") + @RepeatSubmit + public ResponseDTO addJob(@RequestBody @Valid SmartJobAddForm addForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + addForm.setUpdateName(requestUser.getUserName()); + return jobService.addJob(addForm); + } + + @Operation(summary = "定时任务-更新-任务信息 @huke") + @PostMapping("/job/update") + @RepeatSubmit + public ResponseDTO updateJob(@RequestBody @Valid SmartJobUpdateForm updateForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + updateForm.setUpdateName(requestUser.getUserName()); + return jobService.updateJob(updateForm); + } + + @Operation(summary = "定时任务-更新-开启状态 @huke") + @PostMapping("/job/update/enabled") + @RepeatSubmit + public ResponseDTO updateJobEnabled(@RequestBody @Valid SmartJobEnabledUpdateForm updateForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + updateForm.setUpdateName(requestUser.getUserName()); + return jobService.updateJobEnabled(updateForm); + } + + @Operation(summary = "定时任务-删除 @zhuoda") + @GetMapping("/job/delete") + @RepeatSubmit + public ResponseDTO deleteJob(@RequestParam Integer jobId) { + return jobService.deleteJob(jobId, SmartRequestUtil.getRequestUser()); + } + + @Operation(summary = "定时任务-执行记录-分页查询 @huke") + @PostMapping("/job/log/query") + public ResponseDTO> queryJobLog(@RequestBody @Valid SmartJobLogQueryForm queryForm) { + return jobService.queryJobLog(queryForm); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/AdminRequestUtil.java b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/AdminRequestUtil.java new file mode 100644 index 0000000..04569ac --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/java/net/lab1024/sa/admin/util/AdminRequestUtil.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.admin.util; + +import net.lab1024.sa.admin.module.system.login.domain.RequestEmployee; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.util.SmartRequestUtil; + +/** + * admin 端的请求工具类 + * + * @Date 2023/7/28 19:39:21 + * @Author wzh + */ +public final class AdminRequestUtil { + + + public static RequestEmployee getRequestUser() { + return (RequestEmployee) SmartRequestUtil.getRequestUser(); + } + + public static Long getRequestUserId() { + RequestUser requestUser = getRequestUser(); + return null == requestUser ? null : requestUser.getUserId(); + } + + +} diff --git a/smart-flow-api/sa-admin/src/main/resources/dev/application.yaml b/smart-flow-api/sa-admin/src/main/resources/dev/application.yaml new file mode 100644 index 0000000..ac17553 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/dev/application.yaml @@ -0,0 +1,27 @@ +############################################################################################################# +# # +# 为了减少重复配置,本配置文件为此sa-admin的独有配置,更多配置请查看 sa-base 项目中的 sa-base.yaml 通用配置文件。 # +# 其中此文件中配置可以覆盖 sa-base.yaml 中的通用配置,具体实现类请看类:YamlProcessor.java # +# # +############################################################################################################# + +# 项目配置: 名称、日志目录 +project: + name: sa-admin + log-directory: ./logs/${project.name}/${spring.profiles.active} + +# 项目端口和url根路径 +server: + port: 1024 + servlet: + context-path: / + +management: + health: + mail: + enabled: false + +# 环境 +spring: + profiles: + active: '@profiles.active@' \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/dev/log4j2-spring.xml b/smart-flow-api/sa-admin/src/main/resources/dev/log4j2-spring.xml new file mode 100644 index 0000000..14e3eea --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/dev/log4j2-spring.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/dev/spy.properties b/smart-flow-api/sa-admin/src/main/resources/dev/spy.properties new file mode 100644 index 0000000..667e1ea --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/dev/spy.properties @@ -0,0 +1,18 @@ +#相关的包 +modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory +# 日志格式 +logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger +#日志输出到控制台 +appender=com.p6spy.engine.spy.appender.StdoutLogger +# 设置 p6spy driver 代理 +deregisterdrivers=true +# 取消JDBC URL前缀 +useprefix=true +# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset. +excludecategories=info,debug,result,commit,resultset +# 日期格式 +dateformat=yyyy-MM-dd HH:mm:ss +# 开启慢sql +outagedetection=true +# 慢SQL记录标准(单位秒) +outagedetectioninterval=2 \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/category/CategoryMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/category/CategoryMapper.xml new file mode 100644 index 0000000..908509c --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/category/CategoryMapper.xml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/goods/GoodsMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/goods/GoodsMapper.xml new file mode 100644 index 0000000..967966e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/goods/GoodsMapper.xml @@ -0,0 +1,41 @@ + + + + + update t_goods + set deleted_flag = #{deletedFlag} + WHERE goods_id IN + + #{item} + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/bank/BankMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/bank/BankMapper.xml new file mode 100644 index 0000000..3d00f12 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/bank/BankMapper.xml @@ -0,0 +1,58 @@ + + + + + UPDATE t_oa_bank + SET deleted_flag = #{deletedFlag} + WHERE bank_id = #{bankId} + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/enterprise/EnterpriseEmployeeMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/enterprise/EnterpriseEmployeeMapper.xml new file mode 100644 index 0000000..fe80bd5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/enterprise/EnterpriseEmployeeMapper.xml @@ -0,0 +1,94 @@ + + + + + + delete from t_oa_enterprise_employee where enterprise_id = #{enterpriseId} and employee_id in + + #{item} + + + + + delete from t_oa_enterprise_employee where employee_id = #{employeeId} + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/enterprise/EnterpriseMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/enterprise/EnterpriseMapper.xml new file mode 100644 index 0000000..2dfa2e5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/enterprise/EnterpriseMapper.xml @@ -0,0 +1,93 @@ + + + + + UPDATE t_oa_enterprise + SET deleted_flag = #{deletedFlag} + WHERE enterprise_id = #{enterpriseId} + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/invoice/InvoiceMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/invoice/InvoiceMapper.xml new file mode 100644 index 0000000..c6dbdd9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/invoice/InvoiceMapper.xml @@ -0,0 +1,57 @@ + + + + + UPDATE t_oa_invoice + SET deleted_flag = #{deletedFlag} + WHERE invoice_id = #{invoiceId} + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/leave/LeaveMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/leave/LeaveMapper.xml new file mode 100644 index 0000000..cafe30d --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/leave/LeaveMapper.xml @@ -0,0 +1,57 @@ + + + + + + + t_leave.leave_id, + t_leave.type, + t_leave.reason, + t_leave.start_time, + t_leave.end_time, + t_leave.day, + t_leave.instance_id, + t_leave.node_code, + t_leave.node_name, + t_leave.node_type, + t_leave.flow_status, + t_leave.create_user_id, + t_leave.create_time, + t_leave.update_time, + t_leave.deleted_flag + + + + + + + diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/notice/NoticeMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/notice/NoticeMapper.xml new file mode 100644 index 0000000..8683cc9 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/business/oa/notice/NoticeMapper.xml @@ -0,0 +1,265 @@ + + + + + + + t_notice.notice_id, + t_notice.notice_type_id, + t_notice.title, + t_notice.all_visible_flag, + t_notice.scheduled_publish_flag, + t_notice.publish_time, + t_notice.content_text, + t_notice.content_html, + t_notice.attachment, + t_notice.page_view_count, + t_notice.user_view_count, + t_notice.source, + t_notice.author, + t_notice.document_number, + t_notice.instance_id, + t_notice.node_name, + t_notice.flow_status, + t_notice.deleted_flag, + t_notice.create_user_id, + t_notice.update_time, + t_notice.create_time + + + + + + insert into t_notice_visible_range + (notice_id, data_type, data_id) + values + + ( #{noticeId} , #{item.dataType}, #{item.dataId} ) + + + + delete + from t_notice_visible_range + where notice_id = #{noticeId} + + + + + + + update t_notice + set deleted_flag = true + where notice_id = #{noticeId} + + + + + + + + + + + + + + insert into t_notice_view_record (notice_id, employee_id, first_ip, first_user_agent, page_view_count) + values (#{noticeId}, #{employeeId}, #{ip}, #{userAgent}, #{pageViewCount}) + + + update t_notice_view_record + set page_view_count = page_view_count + 1, + last_ip = #{ip}, + last_user_agent = #{userAgent} + where notice_id = #{noticeId} + and employee_id = #{employeeId} + + + update t_notice + set page_view_count = page_view_count + #{pageViewCountIncrement}, + user_view_count = user_view_count + #{userViewCountIncrement} + where notice_id = #{noticeId} + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/flow/WarmFLowMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/flow/WarmFLowMapper.xml new file mode 100644 index 0000000..d477ea3 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/flow/WarmFLowMapper.xml @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/PositionMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/PositionMapper.xml new file mode 100644 index 0000000..d211b06 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/PositionMapper.xml @@ -0,0 +1,25 @@ + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/department/DepartmentMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/department/DepartmentMapper.xml new file mode 100644 index 0000000..b145877 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/department/DepartmentMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/employee/EmployeeMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/employee/EmployeeMapper.xml new file mode 100644 index 0000000..9d11110 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/employee/EmployeeMapper.xml @@ -0,0 +1,301 @@ + + + + + + + + UPDATE t_employee + SET disabled_flag = #{disabledFlag} + WHERE employee_id = #{employeeId} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + UPDATE t_employee + SET login_pwd = #{password} + WHERE employee_id = #{employeeId} + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/menu/MenuMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/menu/MenuMapper.xml new file mode 100644 index 0000000..68fbede --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/menu/MenuMapper.xml @@ -0,0 +1,78 @@ + + + + + + + + update t_menu + set deleted_flag = #{deletedFlag}, + update_user_id = #{updateUserId} + where menu_id = #{item} + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleDataScopeMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleDataScopeMapper.xml new file mode 100644 index 0000000..b9f5bcf --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleDataScopeMapper.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + DELETE FROM t_role_data_scope + WHERE role_id = #{roleId} + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleEmployeeMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleEmployeeMapper.xml new file mode 100644 index 0000000..0de8188 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleEmployeeMapper.xml @@ -0,0 +1,149 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + DELETE + FROM t_role_employee + WHERE employee_id = #{employeeId} + + + + + DELETE + FROM t_role_employee + WHERE role_id = #{roleId} + + + + DELETE + FROM t_role_employee + WHERE role_id = #{roleId} + and employee_id = #{employeeId} + + + + + DELETE FROM t_role_employee + WHERE role_id = #{roleId} and employee_id in + + #{item} + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleMapper.xml new file mode 100644 index 0000000..b26ba0e --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleMenuMapper.xml b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleMenuMapper.xml new file mode 100644 index 0000000..448fa58 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/mapper/system/role/RoleMenuMapper.xml @@ -0,0 +1,39 @@ + + + + + delete + from t_role_menu + where role_id = #{roleId} + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/pre/application.yaml b/smart-flow-api/sa-admin/src/main/resources/pre/application.yaml new file mode 100644 index 0000000..a56dcc5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/pre/application.yaml @@ -0,0 +1,22 @@ +############################################################################################################# +# # +# 为了减少重复配置,本配置文件为此sa-admin的独有配置,更多配置请查看 sa-base 项目中的 sa-base.yaml 通用配置文件。 # +# 其中此文件中配置可以覆盖 sa-base.yaml 中的通用配置,具体实现类请看类:YamlProcessor.java # +# # +############################################################################################################# + +# 项目配置: 名称、日志目录 +project: + name: sa-admin + log-directory: /home/logs/smart_admin_v3/${project.name}/${spring.profiles.active} + +# 项目端口和url根路径 +server: + port: 1024 + servlet: + context-path: / + +# 环境 +spring: + profiles: + active: '@profiles.active@' \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/pre/log4j2-spring.xml b/smart-flow-api/sa-admin/src/main/resources/pre/log4j2-spring.xml new file mode 100644 index 0000000..d03ceca --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/pre/log4j2-spring.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/prod/application.yaml b/smart-flow-api/sa-admin/src/main/resources/prod/application.yaml new file mode 100644 index 0000000..a56dcc5 --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/prod/application.yaml @@ -0,0 +1,22 @@ +############################################################################################################# +# # +# 为了减少重复配置,本配置文件为此sa-admin的独有配置,更多配置请查看 sa-base 项目中的 sa-base.yaml 通用配置文件。 # +# 其中此文件中配置可以覆盖 sa-base.yaml 中的通用配置,具体实现类请看类:YamlProcessor.java # +# # +############################################################################################################# + +# 项目配置: 名称、日志目录 +project: + name: sa-admin + log-directory: /home/logs/smart_admin_v3/${project.name}/${spring.profiles.active} + +# 项目端口和url根路径 +server: + port: 1024 + servlet: + context-path: / + +# 环境 +spring: + profiles: + active: '@profiles.active@' \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/prod/log4j2-spring.xml b/smart-flow-api/sa-admin/src/main/resources/prod/log4j2-spring.xml new file mode 100644 index 0000000..e0b752b --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/prod/log4j2-spring.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/test/application.yaml b/smart-flow-api/sa-admin/src/main/resources/test/application.yaml new file mode 100644 index 0000000..6ca92cf --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/test/application.yaml @@ -0,0 +1,22 @@ +############################################################################################################# +# # +# 为了减少重复配置,本配置文件为此sa-admin的独有配置,更多配置请查看 sa-base 项目中的 sa-base.yaml 通用配置文件。 # +# 其中此文件中配置可以覆盖 sa-base.yaml 中的通用配置,具体实现类请看类:YamlProcessor.java # +# # +############################################################################################################# + +# 项目配置: 名称、日志目录 +project: + name: sa-admin + log-directory: /home/project/smartadmin/test/log + +# 项目端口和url根路径 +server: + port: 11024 + servlet: + context-path: / + +# 环境 +spring: + profiles: + active: '@profiles.active@' \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/test/log4j2-spring.xml b/smart-flow-api/sa-admin/src/main/resources/test/log4j2-spring.xml new file mode 100644 index 0000000..d03ceca --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/test/log4j2-spring.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/main/resources/test/spy.properties b/smart-flow-api/sa-admin/src/main/resources/test/spy.properties new file mode 100644 index 0000000..667e1ea --- /dev/null +++ b/smart-flow-api/sa-admin/src/main/resources/test/spy.properties @@ -0,0 +1,18 @@ +#相关的包 +modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory +# 日志格式 +logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger +#日志输出到控制台 +appender=com.p6spy.engine.spy.appender.StdoutLogger +# 设置 p6spy driver 代理 +deregisterdrivers=true +# 取消JDBC URL前缀 +useprefix=true +# 配置记录 Log 例外,可去掉的结果集有error,info,batch,debug,statement,commit,rollback,result,resultset. +excludecategories=info,debug,result,commit,resultset +# 日期格式 +dateformat=yyyy-MM-dd HH:mm:ss +# 开启慢sql +outagedetection=true +# 慢SQL记录标准(单位秒) +outagedetectioninterval=2 \ No newline at end of file diff --git a/smart-flow-api/sa-admin/src/test/java/net/lab1024/sa/admin/AdminApplicationTest.java b/smart-flow-api/sa-admin/src/test/java/net/lab1024/sa/admin/AdminApplicationTest.java new file mode 100644 index 0000000..0d8d423 --- /dev/null +++ b/smart-flow-api/sa-admin/src/test/java/net/lab1024/sa/admin/AdminApplicationTest.java @@ -0,0 +1,25 @@ +package net.lab1024.sa.admin; + +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.extension.ExtendWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +public class AdminApplicationTest { + + @BeforeEach + public void before() { + System.out.println("----------------------- 测试开始 -----------------------"); + + } + + @AfterEach + public void after() { + System.out.println("----------------------- 测试结束 -----------------------"); + } + +} + diff --git a/smart-flow-api/sa-base/lib/.gitignore b/smart-flow-api/sa-base/lib/.gitignore new file mode 100644 index 0000000..c8a0b1b --- /dev/null +++ b/smart-flow-api/sa-base/lib/.gitignore @@ -0,0 +1,2 @@ +# 厂商 JDBC 勿入库;本地复制 Kingbase 驱动后命名为 kingbase8.jar +*.jar diff --git a/smart-flow-api/sa-base/lib/README.txt b/smart-flow-api/sa-base/lib/README.txt new file mode 100644 index 0000000..9424ac4 --- /dev/null +++ b/smart-flow-api/sa-base/lib/README.txt @@ -0,0 +1,10 @@ +Kingbase JDBC(必做,否则启动报 ClassNotFoundException: com.kingbase8.Driver) + +1. 从人大金仓安装目录找到 JDBC 驱动 jar(常见名含 kingbase8)。 +2. 在本目录保存为固定文件名: + + kingbase8.jar + +3. IDEA:Maven Reload,然后重新编译 / 启动 sa-admin。 + +也可运行项目根 scripts/install-kingbase8-to-local-m2.sh 后,将同一 jar 再复制为本目录的 kingbase8.jar。 diff --git a/smart-flow-api/sa-base/pom.xml b/smart-flow-api/sa-base/pom.xml new file mode 100644 index 0000000..9b78325 --- /dev/null +++ b/smart-flow-api/sa-base/pom.xml @@ -0,0 +1,298 @@ + + 4.0.0 + + net.lab1024 + sa-parent + 3.0.1 + ../pom.xml + + + sa-base + 3.0.1 + + sa-base + sa-base project + + + + + org.springframework.boot + spring-boot-starter-aop + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.boot + spring-boot-starter-data-redis + + + org.springframework.boot + spring-boot-starter + + + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-logging + + + + + + org.springframework.security + spring-security-crypto + + + + + cn.dev33 + sa-token-spring-boot3-starter + + + + cn.dev33 + sa-token-redis-jackson + + + + + + org.springframework.boot + spring-boot-starter-log4j2 + + + + org.springframework.boot + spring-boot-starter-validation + + + + org.springframework.boot + spring-boot-starter-test + + + + com.mysql + mysql-connector-j + + + + com.github.ben-manes.caffeine + caffeine + + + error_prone_annotations + com.google.errorprone + + + + + + org.projectlombok + lombok + + + + org.apache.commons + commons-pool2 + + + + org.apache.commons + commons-text + + + + com.baomidou + mybatis-plus-spring-boot3-starter + + + + p6spy + p6spy + + + + com.github.xiaoymin + knife4j-openapi3-jakarta-spring-boot-starter + + + + com.squareup.okhttp3 + okhttp + + + + com.alibaba + fastjson + + + + com.alibaba + druid-spring-boot-3-starter + + + + com.google.guava + guava + + + + com.googlecode.concurrentlinkedhashmap + concurrentlinkedhashmap-lru + + + + org.reflections + reflections + + + + com.amazonaws + aws-java-sdk-s3 + + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-collections4 + + + + commons-io + commons-io + + + + org.apache.commons + commons-compress + + + + cn.hutool + hutool-all + + + + io.jsonwebtoken + jjwt + + + + com.auth0 + jwks-rsa + + + + org.apache.velocity + velocity-engine-core + + + + org.apache.velocity.tools + velocity-tools-generic + + + + org.lionsoul + ip2region + + + + org.bouncycastle + bcprov-jdk18on + + + + cn.idev.excel + fastexcel + + + logback-classic + ch.qos.logback + + + + + + org.apache.poi + poi + + + + org.apache.poi + poi-ooxml + + + + org.apache.poi + poi-scratchpad + + + + org.apache.poi + ooxml-schemas + + + + com.fasterxml.jackson.datatype + jackson-datatype-jsr310 + + + + net.1024lab + smartdb + ${smartdb.version} + + + + org.redisson + redisson-spring-boot-starter + + + + org.yaml + snakeyaml + + + + org.springframework.boot + spring-boot-starter-mail + + + + org.jsoup + jsoup + + + + org.freemarker + freemarker + + + + org.apache.tika + tika-core + + + + cn.com.kingbase + kingbase8 + + + + + diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/annoation/NoNeedLogin.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/annoation/NoNeedLogin.java new file mode 100644 index 0000000..54f54e9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/annoation/NoNeedLogin.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.common.annoation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 不需要登录注解 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface NoNeedLogin { +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCode.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCode.java new file mode 100644 index 0000000..009275f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCode.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.base.common.code; + +/** + * 错误码
+ * 一共分为三种: 1)系统错误、2)用户级别错误、3)未预期到的错误 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ +public interface ErrorCode { + + /** + * 系统等级 + */ + String LEVEL_SYSTEM = "system"; + + /** + * 用户等级 + */ + String LEVEL_USER = "user"; + + /** + * 未预期到的等级 + */ + String LEVEL_UNEXPECTED = "unexpected"; + + /** + * 错误码 + */ + int getCode(); + + /** + * 错误消息 + * + */ + String getMsg(); + + /** + * 错误等级 + */ + String getLevel(); + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCodeRangeContainer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCodeRangeContainer.java new file mode 100644 index 0000000..c2343f7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCodeRangeContainer.java @@ -0,0 +1,108 @@ +package net.lab1024.sa.base.common.code; + +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 错误码 注册容器 + * + * @Date 2021/09/27 22:09 + * @Author wzh + */ +class ErrorCodeRangeContainer { + + /** + * 所有的错误码均大于10000 + */ + static final int MIN_START_CODE = 10000; + + static final Map, ImmutablePair> CODE_RANGE_MAP = new ConcurrentHashMap<>(); + + /** + * 用于统计数量 + */ + static int errorCounter = 0; + + /** + * 注册状态码 + * 校验是否重复 是否越界 + * + */ + static void register(Class clazz, int start, int end) { + String simpleName = clazz.getSimpleName(); + if (!clazz.isEnum()) { + throw new ExceptionInInitializerError(String.format("<> error: %s not Enum class !", simpleName)); + } + if (start > end) { + throw new ExceptionInInitializerError(String.format("<> error: %s start must be less than the end !", simpleName)); + } + + if (start <= MIN_START_CODE) { + throw new ExceptionInInitializerError(String.format("<> error: %s start must be more than %s !", simpleName, MIN_START_CODE)); + } + + // 校验是否重复注册 + boolean containsKey = CODE_RANGE_MAP.containsKey(clazz); + if (containsKey) { + throw new ExceptionInInitializerError(String.format("<> error: Enum %s already exist !", simpleName)); + } + + // 校验 开始结束值 是否越界 + CODE_RANGE_MAP.forEach((k, v) -> { + if (isExistOtherRange(start, end, v)) { + throw new IllegalArgumentException(String.format("<> error: %s[%d,%d] has intersection with class:%s[%d,%d]", simpleName, start, end, + k.getSimpleName(), v.getLeft(), v.getRight())); + } + }); + + // 循环校验code并存储 + List codeList = Stream.of(clazz.getEnumConstants()).map(codeEnum -> { + int code = codeEnum.getCode(); + if (code < start || code > end) { + throw new IllegalArgumentException(String.format("<> error: %s[%d,%d] code %d out of range", simpleName, start, end, code)); + } + return code; + }).collect(Collectors.toList()); + + // 校验code是否重复 + List distinctCodeList = codeList.stream().distinct().collect(Collectors.toList()); + Collection subtract = CollectionUtils.subtract(codeList, distinctCodeList); + if (CollectionUtils.isNotEmpty(subtract)) { + throw new IllegalArgumentException(String.format("<> error: %s code %s is repeat!", simpleName, subtract)); + } + + CODE_RANGE_MAP.put(clazz, ImmutablePair.of(start, end)); + // 统计 + errorCounter = errorCounter + distinctCodeList.size(); + } + + /** + * 是否存在于其他范围 + */ + private static boolean isExistOtherRange(int start, int end, ImmutablePair range) { + if (start >= range.getLeft() && start <= range.getRight()) { + return true; + } + + if (end >= range.getLeft() && end <= range.getRight()) { + return true; + } + + return false; + } + + /** + * 进行初始化 + */ + static int initialize() { + return errorCounter; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCodeRegister.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCodeRegister.java new file mode 100644 index 0000000..59f719c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/ErrorCodeRegister.java @@ -0,0 +1,38 @@ +package net.lab1024.sa.base.common.code; + +import static net.lab1024.sa.base.common.code.ErrorCodeRangeContainer.register; + +/** + * 注册code状态码
+ * ps:为什么要在此处不那么优雅的手动注册? + * 主要是为了能统一、清晰、浏览当前定义的所有状态码 + * 方便后续维护 + * + * @Date 2021/09/27 23:09 + * @Author wzh + */ +public class ErrorCodeRegister { + + static { + + // 系统 错误码 + register(SystemErrorCode.class, 10001, 20000); + + // 意外 错误码 + register(UnexpectedErrorCode.class, 20001, 30000); + + // 用户 通用错误码 + register(UserErrorCode.class, 30001, 40000); + + } + + + public static int initialize() { + return ErrorCodeRangeContainer.initialize(); + } + + public static void main(String[] args) { + ErrorCodeRegister.initialize(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/SystemErrorCode.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/SystemErrorCode.java new file mode 100644 index 0000000..b55b4d9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/SystemErrorCode.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.common.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 系统错误状态码(此类返回码应该高度重视) + * + * @Date 2021/10/24 20:09 + * @Author wzh + */ +@Getter +@AllArgsConstructor +public enum SystemErrorCode implements ErrorCode { + + /** + * 系统错误 + */ + SYSTEM_ERROR(10001, "系统似乎出现了点小问题"), + + ; + + private final int code; + + private final String msg; + + private final String level; + + SystemErrorCode(int code, String msg) { + this.code = code; + this.msg = msg; + this.level = LEVEL_SYSTEM; + } + +} + diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/UnexpectedErrorCode.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/UnexpectedErrorCode.java new file mode 100644 index 0000000..1ff3f95 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/UnexpectedErrorCode.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.common.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 未预期的错误码(即发生了不可能发生的事情,此类返回码应该高度重视) + * + * @Date 2021/09/27 22:10:46 + * @Author wzh + */ +@Getter +@AllArgsConstructor +public enum UnexpectedErrorCode implements ErrorCode { + + /** + * 业务错误 + */ + BUSINESS_HANDING(20001, "呃~ 业务繁忙,请稍后重试"), + + /** + * id错误 + */ + PAY_ORDER_ID_ERROR(20002, "付款单id发生了异常,请联系技术人员排查"), + + ; + + private final int code; + + private final String msg; + + private final String level; + + UnexpectedErrorCode(int code, String msg) { + this.code = code; + this.msg = msg; + this.level = LEVEL_UNEXPECTED; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/UserErrorCode.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/UserErrorCode.java new file mode 100644 index 0000000..d00a38c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/code/UserErrorCode.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.common.code; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 用户级别的错误码(用户引起的错误返回码,可以不用关注) + * + * @Date 2021/09/21 22:12:27 + * @Author wzh + */ +@Getter +@AllArgsConstructor +public enum UserErrorCode implements ErrorCode { + + PARAM_ERROR(30001, "参数错误"), + + DATA_NOT_EXIST(30002, "左翻右翻,数据竟然找不到了~"), + + ALREADY_EXIST(30003, "数据已存在了呀~"), + + REPEAT_SUBMIT(30004, "亲~您操作的太快了,请稍等下再操作~"), + + NO_PERMISSION(30005, "对不起,您没有权限访问此内容哦~"), + + DEVELOPING(30006, "系統正在紧急开发中,敬请期待~"), + + LOGIN_STATE_INVALID(30007, "您还未登录或登录失效,请重新登录!"), + + USER_STATUS_ERROR(30008, "用户状态异常"), + + FORM_REPEAT_SUBMIT(30009, "请勿重复提交"), + + LOGIN_FAIL_LOCK(30010, "登录连续失败已经被锁定,无法登录"), + LOGIN_FAIL_WILL_LOCK(30011, "登录连续失败将会锁定提醒"), + + LOGIN_ACTIVE_TIMEOUT(30012, "长时间未操作系统,需要重新登录"); + + private final int code; + + private final String msg; + + private final String level; + + UserErrorCode(int code, String msg) { + this.code = code; + this.msg = msg; + this.level = LEVEL_USER; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/constant/RequestHeaderConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/constant/RequestHeaderConst.java new file mode 100644 index 0000000..15392dd --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/constant/RequestHeaderConst.java @@ -0,0 +1,15 @@ +package net.lab1024.sa.base.common.constant; + +/** + * 请求消息头常量 + * + * @Date 2022-05-15 20:46:27 + * @Author wzh + */ +public class RequestHeaderConst { + + public static final String TOKEN = "Authorization"; + + public static final String USER_AGENT = "user-agent"; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/constant/StringConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/constant/StringConst.java new file mode 100644 index 0000000..13a39dc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/constant/StringConst.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.common.constant; + +/** + * 字符串常量 + * + * @Date 2021-10-14 23:16:47 + * @Author wzh + */ +public class StringConst { + + /** + * 全局通用分隔符 + */ + public static final String SEPARATOR = ","; + + /** + * 全局通用分隔符 下划线 + */ + public static final String UNDERLINE = "_"; + + /** + * 全局通用 横杠 + */ + public static final String HORIZONTAL = "-"; + + /** + * 全局通用分隔符 + */ + public static final Character SEPARATOR_CHAR = ','; + + /** + * 全局通用分隔符 斜杠 + */ + public static final String SEPARATOR_SLASH = "/"; + + /** + * 空字符串 + */ + public static final String EMPTY = ""; + + /** + * 全局通用 冒号 + */ + public static final String COLON = ":"; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/controller/SupportBaseController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/controller/SupportBaseController.java new file mode 100644 index 0000000..ff61ab5 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/controller/SupportBaseController.java @@ -0,0 +1,14 @@ +package net.lab1024.sa.base.common.controller; + +import net.lab1024.sa.base.constant.SwaggerTagConst; +import org.springframework.web.bind.annotation.RequestMapping; + +/** + * 支撑类业务路由基类 + * + * @Date 2022-04-24 20:43:55 + * @Author wzh + */ +@RequestMapping(SwaggerTagConst.Support.URL_PREFIX) +public class SupportBaseController { +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/DataScopePlugin.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/DataScopePlugin.java new file mode 100644 index 0000000..a7bce39 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/DataScopePlugin.java @@ -0,0 +1,12 @@ +package net.lab1024.sa.base.common.domain; + +import org.apache.ibatis.plugin.Interceptor; + +/** + * 数据范围 插件 + * + * @Date 2021-11-15 17:20:04 + * @Author wzh + */ +public abstract class DataScopePlugin implements Interceptor { +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/PageParam.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/PageParam.java new file mode 100644 index 0000000..fa185e2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/PageParam.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.base.common.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +import java.util.List; + +/** + * 分页基础参数 + * + * @Date 2020/04/28 16:19 + * @Author wzh + */ +@Data +public class PageParam { + + @Schema(description = "页码(不能为空)", example = "1") + @NotNull(message = "分页参数不能为空") + private Long pageNum; + + @Schema(description = "每页数量(不能为空)", example = "10") + @NotNull(message = "每页数量不能为空") + @Max(value = 500, message = "每页最大为500") + private Long pageSize; + + @Schema(description = "是否查询总条数") + protected Boolean searchCount; + + @Schema(description = "排序字段集合") + @Size(max = 10, message = "排序字段最多10") + @Valid + private List sortItemList; + + /** + * 排序DTO类 + */ + @Data + public static class SortItem { + + @Schema(description = "true正序|false倒序") + @NotNull(message = "排序规则不能为空") + private Boolean isAsc; + + @Schema(description = "排序字段") + @NotBlank(message = "排序字段不能为空") + @Length(max = 30, message = "排序字段最多30") + private String column; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/PageResult.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/PageResult.java new file mode 100644 index 0000000..823c200 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/PageResult.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.common.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.List; + +/** + * 分页返回对象 + * + * @Date 2020/04/28 16:19 + * @Author wzh + */ +@Data +public class PageResult { + + /** + * 当前页 + */ + @Schema(description = "当前页") + private Long pageNum; + + /** + * 每页的数量 + */ + @Schema(description = "每页的数量") + private Long pageSize; + + /** + * 总记录数 + */ + @Schema(description = "总记录数") + private Long total; + + /** + * 总页数 + */ + @Schema(description = "总页数") + private Long pages; + + /** + * 结果集 + */ + @Schema(description = "结果集") + private List list; + + @Schema(description = "是否为空") + private Boolean emptyFlag; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/RequestUrlVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/RequestUrlVO.java new file mode 100644 index 0000000..fef3ec9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/RequestUrlVO.java @@ -0,0 +1,23 @@ +package net.lab1024.sa.base.common.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 请求url返回对象 + * + * @Date 2021/9/1 20:15 + * @Author wzh + */ +@Data +public class RequestUrlVO { + + @Schema(description = "注释说明") + private String comment; + + @Schema(description = "controller.method") + private String name; + + @Schema(description = "url") + private String url; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/RequestUser.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/RequestUser.java new file mode 100644 index 0000000..d5cfb3c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/RequestUser.java @@ -0,0 +1,60 @@ +package net.lab1024.sa.base.common.domain; + +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; + +/** + * 请求用户 + * + * @Date 2021-12-21 19:55:07 + * @Author wzh + */ +public interface RequestUser { + + /** + * 请求用户id + * + * @return + */ + Long getUserId(); + + /** + * 请求用户名称 + * + * @return + */ + String getUserName(); + + /** + * 获取用户类型 + */ + UserTypeEnum getUserType(); + + /** + * 获取请求的IP + * + * @return + */ + String getIp(); + + /** + * 获取请求 user-agent + * + * @return + */ + String getUserAgent(); + + /** + * 登录账号(管理端员工为 loginName;未实现则返回 null) + */ + default String getLoginAccount() { + return null; + } + + /** + * 角色名称汇总(逗号分隔;未实现则返回 null) + */ + default String getRoleNames() { + return null; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ResponseDTO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ResponseDTO.java new file mode 100644 index 0000000..c4e3640 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ResponseDTO.java @@ -0,0 +1,118 @@ +package net.lab1024.sa.base.common.domain; + + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.code.ErrorCode; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.enumeration.DataTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import org.apache.commons.lang3.StringUtils; + +/** + * 请求返回对象 + * + * @Date 2021-10-31 21:06:11 + * @Author wzh + */ +@Data +@Schema +public class ResponseDTO { + + public static final int OK_CODE = 0; + + public static final String OK_MSG = "操作成功"; + + @Schema(description = "返回码") + private Integer code; + + @Schema(description = "级别") + private String level; + + private String msg; + + private Boolean ok; + + @Schema(description = "返回数据") + private T data; + + @SchemaEnum(value = DataTypeEnum.class,desc = "数据类型") + private Integer dataType; + + public ResponseDTO(Integer code, String level, boolean ok, String msg, T data) { + this.code = code; + this.level = level; + this.ok = ok; + this.msg = msg; + this.data = data; + this.dataType = DataTypeEnum.NORMAL.getValue(); + } + + public ResponseDTO(Integer code, String level, boolean ok, String msg) { + this.code = code; + this.level = level; + this.ok = ok; + this.msg = msg; + this.dataType = DataTypeEnum.NORMAL.getValue(); + } + + public ResponseDTO(ErrorCode errorCode, boolean ok, String msg, T data) { + this.code = errorCode.getCode(); + this.level = errorCode.getLevel(); + this.ok = ok; + if (StringUtils.isNotBlank(msg)) { + this.msg = msg; + } else { + this.msg = errorCode.getMsg(); + } + this.data = data; + this.dataType = DataTypeEnum.NORMAL.getValue(); + } + + public static ResponseDTO ok() { + return new ResponseDTO<>(OK_CODE, null, true, OK_MSG, null); + } + + public static ResponseDTO ok(T data) { + return new ResponseDTO<>(OK_CODE, null, true, OK_MSG, data); + } + + public static ResponseDTO okMsg(String msg) { + return new ResponseDTO<>(OK_CODE, null, true, msg, null); + } + + // -------------------------------------------- 最常用的 用户参数 错误码 -------------------------------------------- + + public static ResponseDTO userErrorParam() { + return new ResponseDTO<>(UserErrorCode.PARAM_ERROR, false, null, null); + } + + + public static ResponseDTO userErrorParam(String msg) { + return new ResponseDTO<>(UserErrorCode.PARAM_ERROR, false, msg, null); + } + + // -------------------------------------------- 错误码 -------------------------------------------- + + public static ResponseDTO error(ErrorCode errorCode) { + return new ResponseDTO<>(errorCode, false, null, null); + } + + public static ResponseDTO error(ErrorCode errorCode, boolean ok) { + return new ResponseDTO<>(errorCode, ok, null, null); + } + + public static ResponseDTO error(ResponseDTO responseDTO) { + return new ResponseDTO<>(responseDTO.getCode(), responseDTO.getLevel(), responseDTO.getOk(), responseDTO.getMsg(), null); + } + + public static ResponseDTO error(ErrorCode errorCode, String msg) { + return new ResponseDTO<>(errorCode, false, msg, null); + } + + public static ResponseDTO errorData(ErrorCode errorCode, T data) { + return new ResponseDTO<>(errorCode, false, null, data); + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/SystemEnvironment.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/SystemEnvironment.java new file mode 100644 index 0000000..232fc49 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/SystemEnvironment.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.base.common.domain; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum; + +/** + * 系统环境 + * + * @Date 2021/8/13 21:06:11 + * @Author wzh + */ +@AllArgsConstructor +@Getter +public class SystemEnvironment { + + /** + * 是否位生产环境 + */ + private boolean isProd; + + /** + * 项目名称 + */ + private String projectName; + + /** + * 当前环境 + */ + private SystemEnvironmentEnum currentEnvironment; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/UserPermission.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/UserPermission.java new file mode 100644 index 0000000..52b7c87 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/UserPermission.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.common.domain; + +import lombok.Data; + +import java.util.List; + +/** + * sa-token 所需的权限信息 + * + * @Date 2023/8/26 15:23:10 + * @Author wzh + */ + +@Data +public class UserPermission { + + /** + * 权限列表 + */ + private List permissionList; + + /** + * 角色列表 + */ + private List roleList; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ValidateData.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ValidateData.java new file mode 100644 index 0000000..17628d0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ValidateData.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.common.domain; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 校验数据是否为空的包装类 + * + * @Date 2020/10/16 21:06:11 + * @Author wzh + */ +@Data +public class ValidateData { + + @NotNull(message = "数据不能为空哦") + private T data; +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ValidateList.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ValidateList.java new file mode 100644 index 0000000..bdf413a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/domain/ValidateList.java @@ -0,0 +1,151 @@ +package net.lab1024.sa.base.common.domain; + +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; + +import java.util.*; + +/** + * 校验集合是否为空的包装类 + * + * @Date 2020-02-03 17:37 + * @Author wzh + */ +public class ValidateList implements List { + + @Valid + @NotEmpty(message = "数据长度不能为空哦") + private List list; + + public ValidateList() { + this.list = new ArrayList<>(); + } + + public ValidateList(List list) { + this.list = list; + } + + public List getList() { + return list; + } + + public void setList(List list) { + this.list = list; + } + + @Override + public int size() { + return list.size(); + } + + @Override + public boolean isEmpty() { + return list.isEmpty(); + } + + @Override + public boolean contains(Object o) { + return list.contains(o); + } + + @Override + public Iterator iterator() { + return list.iterator(); + } + + @Override + public Object[] toArray() { + return list.toArray(); + } + + @Override + public T[] toArray(T[] a) { + return list.toArray(a); + } + + @Override + public boolean add(E e) { + return list.add(e); + } + + @Override + public boolean remove(Object o) { + return list.remove(o); + } + + @Override + public boolean containsAll(Collection c) { + return list.containsAll(c); + } + + @Override + public boolean addAll(Collection c) { + return list.addAll(c); + } + + @Override + public boolean addAll(int index, Collection c) { + return list.addAll(index, c); + } + + @Override + public boolean removeAll(Collection c) { + return list.removeAll(c); + } + + @Override + public boolean retainAll(Collection c) { + return list.retainAll(c); + } + + @Override + public void clear() { + list.clear(); + } + + @Override + public E get(int index) { + return list.get(index); + } + + @Override + public E set(int index, E element) { + return list.set(index, element); + } + + @Override + public void add(int index, E element) { + list.add(index, element); + } + + @Override + public E remove(int index) { + return list.remove(index); + } + + @Override + public int indexOf(Object o) { + return list.indexOf(o); + } + + @Override + public int lastIndexOf(Object o) { + return list.lastIndexOf(o); + } + + @Override + public ListIterator listIterator() { + return list.listIterator(); + } + + @Override + public ListIterator listIterator(int index) { + return list.listIterator(index); + } + + @Override + public List subList(int fromIndex, int toIndex) { + return list.subList(fromIndex, toIndex); + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/BaseEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/BaseEnum.java new file mode 100644 index 0000000..31b9079 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/BaseEnum.java @@ -0,0 +1,96 @@ +package net.lab1024.sa.base.common.enumeration; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONAware; +import com.alibaba.fastjson.JSONObject; +import com.google.common.base.CaseFormat; +import lombok.Data; + +import java.util.LinkedHashMap; +import java.util.Objects; + +/** + * 枚举类接口 + * + * @Date 2018-07-17 21:22:12 + * @Author wzh + */ +public interface BaseEnum { + + /** + * 获取枚举类的值 + * + * @return + */ + Object getValue(); + + /** + * 获取枚举类的说明 + * + * @return String + */ + String getDesc(); + + /** + * 比较参数是否与枚举类的value相同 + * + * @param value + * @return boolean + */ + default boolean equalsValue(Object value) { + return Objects.equals(getValue(), value); + } + + /** + * 比较枚举类是否相同 + * + * @param baseEnum + * @return boolean + */ + default boolean equals(BaseEnum baseEnum) { + return Objects.equals(getValue(), baseEnum.getValue()) && Objects.equals(getDesc(), baseEnum.getDesc()); + } + + /** + * 返回枚举类的说明 + * + * @param clazz 枚举类类对象 + * @return + */ + static String getInfo(Class clazz) { + BaseEnum[] enums = clazz.getEnumConstants(); + LinkedHashMap json = new LinkedHashMap<>(enums.length); + for (BaseEnum e : enums) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("value", new DeletedQuotationAware(e.getValue())); + jsonObject.put("desc", new DeletedQuotationAware(e.getDesc())); + json.put(e.toString(), jsonObject); + } + + String enumJson = JSON.toJSONString(json, true); + enumJson = enumJson.replaceAll("\"", ""); + enumJson = enumJson.replaceAll("\t", "  "); + enumJson = enumJson.replaceAll("\n", "
"); + String prefix = "
export const " + CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, clazz.getSimpleName() + " =
"); + return prefix + enumJson + "
"; + } + + @Data + class DeletedQuotationAware implements JSONAware { + + private String value; + + public DeletedQuotationAware(Object value) { + if (value instanceof String) { + this.value = "'" + value + "'"; + } else { + this.value = value.toString(); + } + } + + @Override + public String toJSONString() { + return value; + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/DataTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/DataTypeEnum.java new file mode 100644 index 0000000..267e4f3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/DataTypeEnum.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.base.common.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * @Date 2023/10/25 09:47:13 + * @Author wzh + */ + +@Getter +@AllArgsConstructor +public enum DataTypeEnum implements BaseEnum { + + /** + *普通数据 + */ + NORMAL(1, "普通数据"), + + /** + * 加密数据 + */ + ENCRYPT(10, "加密数据"), + ; + private final Integer value; + + private final String desc; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/GenderEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/GenderEnum.java new file mode 100644 index 0000000..9d33b50 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/GenderEnum.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.common.enumeration; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 性别枚举类 + * + * @Date 2019/09/24 16:50 + * @Author wzh + */ +@AllArgsConstructor +@Getter +public enum GenderEnum implements BaseEnum { + + /** + * 0 未知 + */ + UNKNOWN(0, "未知"), + + /** + * 男 1 奇数为阳 + */ + MAN(1, "男"), + + /** + * 女 2 偶数为阴 + */ + WOMAN(2, "女"); + + private final Integer value; + + private final String desc; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/SystemEnvironmentEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/SystemEnvironmentEnum.java new file mode 100644 index 0000000..54f06af --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/SystemEnvironmentEnum.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.base.common.enumeration; + + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 系统环境枚举类 + * + * @Date 2020-10-15 22:45:04 + * @Author wzh + */ +@AllArgsConstructor +@Getter +public enum SystemEnvironmentEnum implements BaseEnum { + /** + * dev + */ + DEV(SystemEnvironmentNameConst.DEV, "开发环境"), + + /** + * test + */ + TEST(SystemEnvironmentNameConst.TEST, "测试环境"), + + /** + * pre + */ + PRE(SystemEnvironmentNameConst.PRE, "预发布环境"), + + /** + * prod + */ + PROD(SystemEnvironmentNameConst.PROD, "生产环境"); + + private final String value; + + private final String desc; + + public static final class SystemEnvironmentNameConst { + public static final String DEV = "dev"; + public static final String TEST = "test"; + public static final String PRE = "pre"; + public static final String PROD = "prod"; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/UserTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/UserTypeEnum.java new file mode 100644 index 0000000..67a1716 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/enumeration/UserTypeEnum.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.common.enumeration; + +/** + * 用户类型 + * + * @Date 2022/10/19 21:46:24 + * @Author wzh + */ +public enum UserTypeEnum implements BaseEnum { + + /** + * 管理端 员工用户 + */ + ADMIN_EMPLOYEE(1, "员工"); + + private Integer type; + + private String desc; + + UserTypeEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + @Override + public Integer getValue() { + return type; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/exception/BusinessException.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/exception/BusinessException.java new file mode 100644 index 0000000..a1b3c94 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/exception/BusinessException.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.base.common.exception; + +import net.lab1024.sa.base.common.code.ErrorCode; + +/** + * 业务逻辑异常,全局异常拦截后统一返回ResponseCodeConst.SYSTEM_ERROR + * + * @Date 2020/8/25 21:57 + * @Author wzh + */ +public class BusinessException extends RuntimeException { + + public BusinessException() { + } + + public BusinessException(ErrorCode errorCode) { + super(errorCode.getMsg()); + } + + public BusinessException(String message) { + super(message); + } + + public BusinessException(String message, Throwable cause) { + super(message, cause); + } + + public BusinessException(Throwable cause) { + super(cause); + } + + public BusinessException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/DictDataDeserializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/DictDataDeserializer.java new file mode 100644 index 0000000..4f8de5f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/DictDataDeserializer.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.common.json.deserializer; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import lombok.extern.slf4j.Slf4j; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * 字典反序列化 + * + * @Date 2022-08-12 22:17:53 + * @Author wzh + */ +@Slf4j +public class DictDataDeserializer extends JsonDeserializer { + + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { + List list = new ArrayList<>(); + ObjectCodec objectCodec = jsonParser.getCodec(); + JsonNode listOrObjectNode = objectCodec.readTree(jsonParser); + String deserialize = ""; + try { + if (listOrObjectNode.isArray()) { + for (JsonNode node : listOrObjectNode) { + list.add(node.asText()); + } + } else { + list.add(listOrObjectNode.asText()); + } + deserialize = String.join(",", list); + } catch (Exception e) { + log.error(e.getMessage(), e); + deserialize = listOrObjectNode.asText(); + } + return deserialize; + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/FileKeyVoDeserializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/FileKeyVoDeserializer.java new file mode 100644 index 0000000..4746783 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/FileKeyVoDeserializer.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.common.json.deserializer; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.ObjectCodec; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; +import com.fasterxml.jackson.databind.JsonNode; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.file.domain.vo.FileVO; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 文件key反序列化
+ * 由于前端接收到的是序列化过的字段, 这边入库需要进行反序列化操作比较方便处理 + * + * @Date 2022-11-24 17:15:23 + * @Author wzh + */ +@Slf4j +public class FileKeyVoDeserializer extends JsonDeserializer { + + @Override + public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + List list = new ArrayList<>(); + ObjectCodec objectCodec = jsonParser.getCodec(); + JsonNode listOrObjectNode = objectCodec.readTree(jsonParser); + String deserialize = ""; + try { + if (listOrObjectNode.isArray()) { + for (JsonNode node : listOrObjectNode) { + list.add(objectCodec.treeToValue(node, FileVO.class)); + } + } else { + list.add(objectCodec.treeToValue(listOrObjectNode, FileVO.class)); + } + deserialize = list.stream().map(FileVO::getFileKey).collect(Collectors.joining(",")); + } catch (Exception e) { + log.error(e.getMessage(), e); + deserialize = listOrObjectNode.asText(); + } + return deserialize; + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/LongJsonDeserializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/LongJsonDeserializer.java new file mode 100644 index 0000000..d7d951b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/deserializer/LongJsonDeserializer.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.common.json.deserializer; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +import java.io.IOException; + +/** + * Long类型序列化 + * + * @Date 2020-06-02 22:55:07 + * @Author wzh + */ +public class LongJsonDeserializer extends JsonDeserializer { + + @Override + public Long deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { + String value = jsonParser.getText(); + try { + return value == null ? null : Long.parseLong(value); + } catch (NumberFormatException e) { + return null; + } + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/BigDecimalNullZeroSerializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/BigDecimalNullZeroSerializer.java new file mode 100644 index 0000000..251c48a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/BigDecimalNullZeroSerializer.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.base.common.json.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; +import java.math.BigDecimal; + +/** + * 数字序列化 + * + * @Date 2020/8/20 21:04 + * @Author wzh + */ +public class BigDecimalNullZeroSerializer extends JsonSerializer { + + @Override + public void serialize(BigDecimal value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (value == null) { + jsonGenerator.writeNumber(BigDecimal.ZERO); + return; + } + jsonGenerator.writeNumber(value); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/DataMaskingSerializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/DataMaskingSerializer.java new file mode 100644 index 0000000..ffe7c84 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/DataMaskingSerializer.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.base.common.json.serializer; + +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 net.lab1024.sa.base.module.support.datamasking.DataMasking; +import net.lab1024.sa.base.module.support.datamasking.DataMaskingTypeEnum; +import net.lab1024.sa.base.module.support.datamasking.SmartDataMaskingUtil; +import org.apache.commons.lang3.ObjectUtils; + +import java.io.IOException; + +/** + * 脱敏序列化 + * + * @author 罗伊 + * @description: + * @date 2024/7/21 4:39 下午 + */ +public class DataMaskingSerializer extends JsonSerializer implements ContextualSerializer { + + private DataMaskingTypeEnum typeEnum; + + @Override + public void serialize(Object value, JsonGenerator jsonGenerator, SerializerProvider serializers) throws IOException { + + if (ObjectUtils.isEmpty(value)) { + jsonGenerator.writeObject(value); + return; + } + + if (typeEnum == null) { + jsonGenerator.writeObject(SmartDataMaskingUtil.dataMasking(String.valueOf(value))); + return; + } + + jsonGenerator.writeObject(SmartDataMaskingUtil.dataMasking(value, typeEnum)); + } + + @Override + public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { + // 判断beanProperty是不是空 + if (null == property) { + return prov.findNullValueSerializer(property); + } + + DataMasking annotation = property.getAnnotation(DataMasking.class); + if (null == annotation) { + return prov.findValueSerializer(property.getType(), property); + } + + typeEnum = annotation.value(); + return this; + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/FileKeySerializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/FileKeySerializer.java new file mode 100644 index 0000000..d48cf69 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/FileKeySerializer.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.common.json.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.module.support.file.service.FileService; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; + +/** + * 文件key进行序列化对象 + * + * @Date 2020/8/15 22:06 + * @Author wzh + */ +public class FileKeySerializer extends JsonSerializer { + + @Resource + private FileService fileService; + + + @Override + public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (StringUtils.isEmpty(value)) { + jsonGenerator.writeString(value); + return; + } + if (fileService == null) { + jsonGenerator.writeString(value); + return; + } + ResponseDTO responseDTO = fileService.getFileUrl(value); + if (responseDTO.getOk()) { + jsonGenerator.writeString(responseDTO.getData()); + return; + } + jsonGenerator.writeString(value); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/FileKeyVoSerializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/FileKeyVoSerializer.java new file mode 100644 index 0000000..328e974 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/FileKeyVoSerializer.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.base.common.json.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.module.support.file.domain.vo.FileVO; +import net.lab1024.sa.base.module.support.file.service.FileService; +import org.apache.commons.lang3.StringUtils; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +/** + * 文件key进行序列化对象 + * + * @Date 2020/8/15 22:06 + * @Author wzh + */ +public class FileKeyVoSerializer extends JsonSerializer { + + @Resource + private FileService fileService; + + + @Override + public void serialize(String value, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { + if (StringUtils.isEmpty(value)) { + jsonGenerator.writeObject(Lists.newArrayList()); + return; + } + if(fileService == null){ + jsonGenerator.writeString(value); + return; + } + String[] fileKeyArray = value.split(","); + List fileKeyList = Arrays.asList(fileKeyArray); + List fileKeyVOList = fileService.getFileList(fileKeyList); + jsonGenerator.writeObject(fileKeyVOList); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java new file mode 100644 index 0000000..01bc6f4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/LongJsonSerializer.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.common.json.serializer; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +import java.io.IOException; + +/** + * Long类型序列化 + * + * @Date 2020-06-02 22:55:07 + * @Author wzh + */ +public class LongJsonSerializer extends JsonSerializer { + + public static final LongJsonSerializer INSTANCE = new LongJsonSerializer(); + + @Override + public void serialize(Long value, JsonGenerator gen, SerializerProvider serializerProvider) throws IOException, JsonProcessingException { + if (null == value) { + gen.writeNull(); + return; + } + // js中最大安全整数16位 Number.MAX_SAFE_INTEGER + String longStr = String.valueOf(value); + if (longStr.length() > 16) { + gen.writeString(longStr); + } else { + gen.writeNumber(value); + } + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/enumeration/EnumSerialize.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/enumeration/EnumSerialize.java new file mode 100644 index 0000000..ace962b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/enumeration/EnumSerialize.java @@ -0,0 +1,25 @@ +package net.lab1024.sa.base.common.json.serializer.enumeration; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 枚举类 序列化 注解 + * + * @author huke + * @date 2024年6月29日 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonSerialize(using = EnumSerializer.class, nullsUsing = EnumSerializer.class) +public @interface EnumSerialize { + + Class value(); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/enumeration/EnumSerializer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/enumeration/EnumSerializer.java new file mode 100644 index 0000000..9cd2324 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/json/serializer/enumeration/EnumSerializer.java @@ -0,0 +1,53 @@ +package net.lab1024.sa.base.common.json.serializer.enumeration; + +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 net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.enumeration.BaseEnum; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; + +import java.io.IOException; +import java.util.stream.Collectors; + +/** + * 枚举 序列化 + * + * @author huke + * @date 2024年6月29日 + */ +public class EnumSerializer extends JsonSerializer implements ContextualSerializer { + + private Class enumClazz; + + @Override + public void serialize(Object value, JsonGenerator gen, SerializerProvider serializers) throws IOException { + gen.writeObject(value); + String fieldName = gen.getOutputContext().getCurrentName() + "Desc"; + Object desc; + // 多个枚举类 逗号分割 + if (value instanceof String && String.valueOf(value).contains(StringConst.SEPARATOR)) { + desc = SmartStringUtil.splitConvertToIntList(String.valueOf(value), StringConst.SEPARATOR) + .stream().map(e -> SmartEnumUtil.getEnumDescByValue(e, enumClazz)).collect(Collectors.toList()); + + } else { + BaseEnum anEnum = SmartEnumUtil.getEnumByValue(value, enumClazz); + desc = null != anEnum ? anEnum.getDesc() : null; + } + gen.writeObjectField(fieldName, desc); + } + + @Override + public JsonSerializer createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException { + EnumSerialize annotation = property.getAnnotation(EnumSerialize.class); + if (null == annotation) { + return prov.findValueSerializer(property.getType(), property); + } + enumClazz = annotation.value(); + return this; + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SchemaEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SchemaEnum.java new file mode 100644 index 0000000..24e17b6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SchemaEnum.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.common.swagger; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 枚举类字段属性的 自定义 swagger 注解 + * + * @Date 2019/05/16 23:18 + * @Author wzh + */ +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface SchemaEnum { + + /** + * 枚举类对象 + * + */ + Class value(); + + String example() default ""; + + boolean hidden() default false; + + boolean required() default true; + + String dataType() default ""; + + String desc() default ""; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SchemaEnumPropertyCustomizer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SchemaEnumPropertyCustomizer.java new file mode 100644 index 0000000..3fa597a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SchemaEnumPropertyCustomizer.java @@ -0,0 +1,49 @@ +package net.lab1024.sa.base.common.swagger; + +import io.swagger.v3.core.converter.AnnotatedType; +import io.swagger.v3.oas.models.media.Schema; +import net.lab1024.sa.base.common.enumeration.BaseEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import org.springdoc.core.customizers.PropertyCustomizer; +import org.springframework.stereotype.Component; + +import java.lang.annotation.Annotation; + +/** + * + * 自定义枚举类文档 + * + * @Date 2023/12/25 23:28:51 + * @Author wzh + */ +@Component +public class SchemaEnumPropertyCustomizer implements PropertyCustomizer { + + @Override + public Schema customize(Schema schema, AnnotatedType type) { + if (type.getCtxAnnotations() == null) { + return schema; + } + + StringBuilder description = new StringBuilder(); + for (Annotation ctxAnnotation : type.getCtxAnnotations()) { + if (ctxAnnotation.annotationType().equals(CheckEnum.class) && ((CheckEnum) ctxAnnotation).required()) { + description.append("【必填】"); + } + } + + for (Annotation ctxAnnotation : type.getCtxAnnotations()) { + if (ctxAnnotation.annotationType().equals(SchemaEnum.class)) { + description.append(((SchemaEnum) ctxAnnotation).desc()); + Class clazz = ((SchemaEnum) ctxAnnotation).value(); + description.append(BaseEnum.getInfo(clazz)); + } + } + + if (description.length() > 0) { + schema.setDescription(description.toString()); + } + return schema; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SmartOperationCustomizer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SmartOperationCustomizer.java new file mode 100644 index 0000000..b29e645 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/swagger/SmartOperationCustomizer.java @@ -0,0 +1,111 @@ +package net.lab1024.sa.base.common.swagger; + +import cn.dev33.satoken.annotation.SaCheckPermission; +import cn.dev33.satoken.annotation.SaCheckRole; +import cn.dev33.satoken.annotation.SaMode; +import io.swagger.v3.oas.models.Operation; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiDecrypt; +import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiEncrypt; +import org.springdoc.core.customizers.OperationCustomizer; +import org.springframework.web.method.HandlerMethod; + +import java.util.ArrayList; +import java.util.List; + +/** + * 权限、接口加解密等 + * + * @Date 2023/12/26 13:47:39 + * @Author wzh + */ + +public class SmartOperationCustomizer implements OperationCustomizer { + + @Override + public Operation customize(Operation operation, HandlerMethod handlerMethod) { + + List noteList = new ArrayList<>(); + + // 请求参数加密 + List encryptBuilderList = new ArrayList<>(); + + if (handlerMethod.getMethodAnnotation(ApiDecrypt.class) != null || + handlerMethod.getBeanType().getAnnotation(ApiDecrypt.class) != null) { + encryptBuilderList.add("【请求参数加密】"); + } + + if (handlerMethod.getMethodAnnotation(ApiEncrypt.class) != null || + handlerMethod.getBeanType().getAnnotation(ApiEncrypt.class) != null) { + encryptBuilderList.add("【返回结果加密】"); + } + + if (!encryptBuilderList.isEmpty()) { + noteList.add("
接口安全:" + SmartStringUtil.join(",", encryptBuilderList) + ""); + } + + // 权限 + noteList.addAll(getPermission(handlerMethod)); + + // 更新 + operation.setDescription(SmartStringUtil.join("
", noteList)); + + return operation; + } + + + private List getPermission(HandlerMethod handlerMethod) { + List values = new ArrayList<>(); + + StringBuilder permissionStringBuilder = new StringBuilder(); + SaCheckPermission classPermissions = handlerMethod.getBeanType().getAnnotation(SaCheckPermission.class); + if (classPermissions != null) { + permissionStringBuilder.append(""); + permissionStringBuilder.append("类:").append(getAnnotationNote(classPermissions.value(), classPermissions.mode())); + permissionStringBuilder.append("
"); + } + + SaCheckPermission methodPermission = handlerMethod.getMethodAnnotation(SaCheckPermission.class); + if (methodPermission != null) { + permissionStringBuilder.append(""); + permissionStringBuilder.append("方法:").append(getAnnotationNote(methodPermission.value(), methodPermission.mode())); + permissionStringBuilder.append("
"); + } + + if (permissionStringBuilder.length() > 0) { + permissionStringBuilder.insert(0, "权限校验:
"); + values.add(permissionStringBuilder.toString()); + } + + + StringBuilder roleStringBuilder = new StringBuilder(); + SaCheckRole classCheckRole = handlerMethod.getBeanType().getAnnotation(SaCheckRole.class); + if (classCheckRole != null) { + roleStringBuilder.append(""); + roleStringBuilder.append("类:").append(getAnnotationNote(classCheckRole.value(), classCheckRole.mode())); + roleStringBuilder.append("
"); + } + + SaCheckPermission methodCheckRole = handlerMethod.getMethodAnnotation(SaCheckPermission.class); + if (methodCheckRole != null) { + roleStringBuilder.append(""); + roleStringBuilder.append("方法:").append(getAnnotationNote(methodCheckRole.value(), methodCheckRole.mode())); + roleStringBuilder.append("
"); + } + + if (roleStringBuilder.length() > 0) { + roleStringBuilder.insert(0, "角色校验:
"); + values.add(roleStringBuilder.toString()); + } + + return values; + } + + private String getAnnotationNote(String[] values, SaMode mode) { + if (mode.equals(SaMode.AND)) { + return String.join(" 且 ", values); + } else { + return String.join(" 或 ", values); + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartBeanUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartBeanUtil.java new file mode 100644 index 0000000..c3e8d9f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartBeanUtil.java @@ -0,0 +1,91 @@ +package net.lab1024.sa.base.common.util; + +import jakarta.validation.ConstraintViolation; +import jakarta.validation.Validation; +import jakarta.validation.Validator; +import org.springframework.beans.BeanUtils; + +import java.util.Collections; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * bean相关工具类 + * + * @Date 2018-01-15 10:48:23 + * @Author wzh + */ +public class SmartBeanUtil { + + /** + * 验证器 + */ + private static final Validator VALIDATOR = Validation.buildDefaultValidatorFactory().getValidator(); + + /** + * 复制bean的属性 + * + * @param source 源 要复制的对象 + * @param target 目标 复制到此对象 + */ + public static void copyProperties(Object source, Object target) { + BeanUtils.copyProperties(source, target); + } + + /** + * 复制对象 + * + * @param source 源 要复制的对象 + * @param target 目标 复制到此对象 + * @param + * @return + */ + public static T copy(Object source, Class target) { + if (source == null || target == null) { + return null; + } + try { + T newInstance = target.newInstance(); + BeanUtils.copyProperties(source, newInstance); + return newInstance; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + /** + * 复制list + * + * @param source + * @param target + * @param + * @param + * @return + */ + public static List copyList(List source, Class target) { + if (null == source || source.isEmpty()) { + return Collections.emptyList(); + } + return source.stream().map(e -> copy(e, target)).collect(Collectors.toList()); + } + + /** + * 手动验证对象 Model的属性 + * 需要配合 hibernate-validator 校验注解 + * + * @param t + * @return String 返回null代表验证通过,否则返回错误的信息 + */ + public static String verify(T t) { + // 获取验证结果 + Set> validate = VALIDATOR.validate(t); + if (validate.isEmpty()) { + // 验证通过 + return null; + } + // 返回错误信息 + List messageList = validate.stream().map(ConstraintViolation::getMessage).collect(Collectors.toList()); + return messageList.toString(); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartBigDecimalUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartBigDecimalUtil.java new file mode 100644 index 0000000..68b7262 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartBigDecimalUtil.java @@ -0,0 +1,244 @@ +package net.lab1024.sa.base.common.util; + +import java.math.BigDecimal; +import java.math.RoundingMode; + +/** + * BigDecimal 工具类 + * + * @Date 2018/01/17 13:54 + * @Author wzh + */ +public class SmartBigDecimalUtil { + + /** + * 金额 保留小数点 2 + */ + public static final int AMOUNT_DECIMAL_POINT = 2; + + public static final BigDecimal ONE_HUNDRED = new BigDecimal("100"); + + /** + * 金额相关计算方法:四舍五入 保留2位小数点 + */ + public static class Amount { + + public static BigDecimal add(BigDecimal num1, BigDecimal num2) { + return setScale(num1.add(num2), AMOUNT_DECIMAL_POINT); + } + + public static BigDecimal multiply(BigDecimal num1, BigDecimal num2) { + return setScale(num1.multiply(num2), AMOUNT_DECIMAL_POINT); + } + + public static BigDecimal subtract(BigDecimal num1, BigDecimal num2) { + return setScale(num1.subtract(num2), AMOUNT_DECIMAL_POINT); + } + + public static BigDecimal divide(BigDecimal num1, BigDecimal num2) { + return setScale(num1.divide(num2, RoundingMode.HALF_UP), AMOUNT_DECIMAL_POINT); + } + } + + + /** + * BigDecimal 加法 num1 + num2 + * 未做非空校验 + * + * @param num1 + * @param num2 + * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT + * @return BigDecimal + */ + public static BigDecimal add(BigDecimal num1, BigDecimal num2, int point) { + return setScale(num1.add(num2), point); + } + + /** + * 累加 + * + * @param point + * @param array + * @return + */ + public static BigDecimal add(int point, BigDecimal... array) { + BigDecimal res = new BigDecimal(0); + for (BigDecimal item : array) { + if (item == null) { + res = res.add(BigDecimal.ZERO); + } else { + res = res.add(item); + } + } + return setScale(res, point); + } + + /** + * BigDecimal 乘法 num1 x num2 + * 未做非空校验 + * + * @param num1 + * @param num2 + * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT + * @return BigDecimal + */ + public static BigDecimal multiply(BigDecimal num1, BigDecimal num2, int point) { + return setScale(num1.multiply(num2), point); + } + + /** + * BigDecimal 减法 num1 - num2 + * 未做非空校验 + * + * @param num1 + * @param num2 + * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT + * @return BigDecimal + */ + public static BigDecimal subtract(BigDecimal num1, BigDecimal num2, int point) { + return setScale(num1.subtract(num2), point); + } + + /** + * BigDecimal 除法 num1/num2 + * 未做非空校验 + * + * @param num1 + * @param num2 + * @param point 请使用BigDecimalUtils.PRICE_DECIMAL_POINT | BigDecimalUtils.WEIGHT_DECIMAL_POINT + * @return BigDecimal + */ + public static BigDecimal divide(BigDecimal num1, BigDecimal num2, int point) { + return num1.divide(num2, point, RoundingMode.HALF_UP); + } + + /** + * 设置小数点类型为 四舍五入 + * + * @param num + * @param point + * @return BigDecimal + */ + public static BigDecimal setScale(BigDecimal num, int point) { + return num.setScale(point, RoundingMode.HALF_UP); + } + + /** + * 比较 num1 是否大于 num2 + * + * @param num1 + * @param num2 + * @return boolean + */ + public static boolean isGreaterThan(BigDecimal num1, BigDecimal num2) { + return num1.compareTo(num2) > 0; + } + + /** + * 比较 num1 是否大于等于 num2 + * + * @param num1 + * @param num2 + * @return boolean + */ + public static boolean isGreaterOrEqual(BigDecimal num1, BigDecimal num2) { + return isGreaterThan(num1, num2) || equals(num1, num2); + } + + /** + * 比较 num1 是否小于 num2 + * + * @param num1 + * @param num2 + * @return boolean + */ + public static boolean isLessThan(BigDecimal num1, BigDecimal num2) { + return num1.compareTo(num2) < 0; + } + + /** + * 比较 num1 是否小于等于 num2 + * + * @param num1 + * @param num2 + * @return boolean + */ + public static boolean isLessOrEqual(BigDecimal num1, BigDecimal num2) { + return isLessThan(num1, num2) || equals(num1, num2); + } + + /** + * 比较 num1 是否等于 num2 + * + * @param num1 + * @param num2 + * @return + */ + public static boolean equals(BigDecimal num1, BigDecimal num2) { + return num1.compareTo(num2) == 0; + } + + /** + * 计算 num1 / num2 的百分比 + * + * @param num1 + * @param num2 + * @param point 保留几位小数 + * @return String + */ + public static BigDecimal percent(Integer num1, Integer num2, int point) { + if (num1 == null || num2 == null) { + return BigDecimal.ZERO; + } + if (num2.equals(0)) { + return BigDecimal.ZERO; + } + return percent(new BigDecimal(num1), new BigDecimal(num2), point); + } + + /** + * 计算 num1 / num2 的百分比 + * + * @param num1 + * @param num2 + * @param point 保留几位小数 + * @return String + */ + public static BigDecimal percent(BigDecimal num1, BigDecimal num2, int point) { + if (num1 == null || num2 == null) { + return BigDecimal.ZERO; + } + if (equals(BigDecimal.ZERO, num2)) { + return BigDecimal.ZERO; + } + BigDecimal percent = num1.divide(num2, point + 2, RoundingMode.HALF_UP); + return percent.multiply(ONE_HUNDRED).setScale(point); + } + + /** + * 比较 num1,num2 返回最大的值 + * + * @param num1 + * @param num2 + * @return BigDecimal + */ + public static BigDecimal max(BigDecimal num1, BigDecimal num2) { + return num1.compareTo(num2) > 0 ? num1 : num2; + } + + /** + * 比较 num1,num2 返回最小的值 + * + * @param num1 + * @param num2 + * @return BigDecimal + */ + public static BigDecimal min(BigDecimal num1, BigDecimal num2) { + return num1.compareTo(num2) < 0 ? num1 : num2; + } + + public static void main(String[] args) { + System.out.println(percent(new BigDecimal("3"), new BigDecimal("11"), 2)); + System.out.println(percent(new BigDecimal("8"), new BigDecimal("11"), 2)); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartDateFormatterEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartDateFormatterEnum.java new file mode 100644 index 0000000..41377bb --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartDateFormatterEnum.java @@ -0,0 +1,76 @@ +package net.lab1024.sa.base.common.util; + + +import java.time.format.DateTimeFormatter; + +/** + * @Date 2023/12/5 21:26:25 + * @Author wzh + */ +public enum SmartDateFormatterEnum { + /** + * 日期格式 :年月日 yyyy-MM-dd + * 例:2021-10-15 + */ + YMD(DateTimeFormatter.ofPattern("yyyy-MM-dd")), + + /** + * 日期格式 :年月日 时分 yyyy-MM-dd HH:mm + * 例:2021-10-15 10:15 + */ + YMD_HM(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm")), + + /** + * 日期格式 :年月日 时分秒 yyyy-MM-dd HH:mm:ss + * 例:2021-10-15 10:15:00 + */ + YMD_HMS(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")), + + /** + * 日期格式 :年月 yyyy-MM + * 例:2021-10 + */ + YM(DateTimeFormatter.ofPattern("yyyy-MM")), + + /** + * 日期格式:年月 MM-dd + * 例:10-15 + */ + MD(DateTimeFormatter.ofPattern("MM-dd")), + + /** + * 日期格式:年月 MM月dd日 + * 例:10月15日 + */ + CHINESE_MD(DateTimeFormatter.ofPattern("MM月dd日")), + + /** + * 日期格式 : yyyyMMddHHmmss + * 例:20091225091010 + */ + YMDHMS(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")), + + /** + * 日期格式 :时分秒 HH:mm:ss + * 例:10:15:00 + */ + HMS(DateTimeFormatter.ofPattern("HH:mm:ss")), + + /** + * 日期格式 :时分 HH:mm + * 例:10:15 + */ + HM(DateTimeFormatter.ofPattern("HH:mm")) + + ; + + private final DateTimeFormatter formatter; + + SmartDateFormatterEnum(DateTimeFormatter formatter) { + this.formatter = formatter; + } + + public DateTimeFormatter getFormatter() { + return formatter; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartEnumUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartEnumUtil.java new file mode 100644 index 0000000..46ce7a7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartEnumUtil.java @@ -0,0 +1,162 @@ +package net.lab1024.sa.base.common.util; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.util.Collection; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +import java.util.function.BiConsumer; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 枚举工具类 + * + * @Date 2017/10/10 18:17 + * @Author wzh + */ +public class SmartEnumUtil { + + /** + * 校验参数与枚举类比较是否合法 + * + * @param value 参数 + * @param enumClass 枚举类必须实现BaseEnum接口 + * @return boolean + * @Author 胡克 + */ + public static boolean checkEnum(Object value, Class enumClass) { + if (null == value) { + return false; + } + return Stream.of(enumClass.getEnumConstants()).anyMatch(e -> e.equalsValue(value)); + } + + /** + * 创建一个具有唯一array值的数组,每个值不包含在其他给定的数组中。 + * + * @param enumClass + * @param exclude + * @param + * @return + */ + public static List differenceValueList(Class enumClass, T... exclude) { + HashSet valueSet = new HashSet<>(); + if (exclude != null) { + valueSet.addAll(Stream.of(exclude).map(BaseEnum::getValue).collect(Collectors.toSet())); + } + + return Stream.of(enumClass.getEnumConstants()) + .filter(e -> !valueSet.contains(e.getValue())) + .map(BaseEnum::getValue) + .collect(Collectors.toList()); + } + + /** + * 获取枚举类的说明 value : info 的形式 + * + * @param enumClass + * @return String + */ + public static String getEnumDesc(Class enumClass) { + BaseEnum[] enums = enumClass.getEnumConstants(); + // value : info 的形式 + StringBuilder sb = new StringBuilder(); + for (BaseEnum baseEnum : enums) { + sb.append(baseEnum.getValue()).append(":").append(baseEnum.getDesc()).append(","); + } + return sb.toString(); + } + + /** + * 获取与参数相匹配的枚举类实例的 说明 + * + * @param value 参数 + * @param enumClass 枚举类必须实现BaseEnum接口 + * @return String 如无匹配枚举则返回null + */ + public static String getEnumDescByValue(Object value, Class enumClass) { + if (null == value) { + return null; + } + return Stream.of(enumClass.getEnumConstants()) + .filter(e -> e.equalsValue(value)) + .findFirst() + .map(BaseEnum::getDesc) + .orElse(null); + } + + public static String getEnumDescByValueList(Collection values, Class enumClass) { + if (CollectionUtils.isEmpty(values)) { + return ""; + } + return Stream.of(enumClass.getEnumConstants()).filter(e -> values.contains(e.getValue())).map(BaseEnum::getDesc).collect(Collectors.joining(",")); + } + + /** + * 根据参数获取枚举类的实例 + * + * @param value 参数 + * @param enumClass 枚举类必须实现BaseEnum接口 + * @return BaseEnum 无匹配值返回null + * @Author 胡克 + */ + public static T getEnumByValue(Object value, Class enumClass) { + if (null == value) { + return null; + } + return Stream.of(enumClass.getEnumConstants()) + .filter(e -> e.equalsValue(value)) + .findFirst() + .orElse(null); + } + + /** + * 根据实例描述与获取枚举类的实例 + * + * @param desc 参数描述 + * @param enumClass 枚举类必须实现BaseEnum接口 + * @return BaseEnum 无匹配值返回null + * @Author 胡克 + */ + public static T getEnumByDesc(String desc, Class enumClass) { + return Stream.of(enumClass.getEnumConstants()) + .filter(e -> Objects.equals(e.getDesc(), desc)) + .findFirst() + .orElse(null); + } + + + public static T getEnumByName(String name, Class enumClass) { + return Stream.of(enumClass.getEnumConstants()) + .filter(e -> StringUtils.equalsIgnoreCase(e.toString(), name)) + .findFirst() + .orElse(null); + } + + + /** + * 根据lambda getter/setter 注入 + * + * @param list + * @param getter + * @param setter + * @param enumClass + * @param + */ + public static void inject(List list, Function getter, BiConsumer setter, Class enumClass) { + if (list == null || list.isEmpty()) { + return; + } + for (T t : list) { + Integer enumValue = getter.apply(t); + if (enumValue != null) { + setter.accept(t, getEnumDescByValue(enumValue, enumClass)); + } + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartExcelUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartExcelUtil.java new file mode 100644 index 0000000..f31fa98 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartExcelUtil.java @@ -0,0 +1,223 @@ +package net.lab1024.sa.base.common.util; + +import cn.idev.excel.FastExcel; +import cn.idev.excel.write.handler.SheetWriteHandler; +import cn.idev.excel.write.metadata.holder.WriteSheetHolder; +import cn.idev.excel.write.metadata.holder.WriteWorkbookHolder; +import jakarta.servlet.http.HttpServletResponse; +import lombok.Data; +import lombok.extern.slf4j.Slf4j; +import org.apache.poi.openxml4j.opc.PackagePartName; +import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.openxml4j.opc.TargetMode; +import org.apache.poi.xssf.usermodel.XSSFPictureData; +import org.apache.poi.xssf.usermodel.XSSFRelation; +import org.apache.poi.xssf.usermodel.XSSFSheet; +import org.apache.poi.xssf.usermodel.XSSFWorkbook; + +import javax.imageio.ImageIO; +import javax.swing.*; +import java.awt.*; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Collection; + +/** + * + * excel 工具类 + * + * @Date 2024/4/22 22:49:07 + * @Author wzh + */ +public final class SmartExcelUtil { + + /** + * 通用单sheet导出 + */ + public static void exportExcel(HttpServletResponse response, String fileName, String sheetName, Class head,Collection data) throws IOException { + // 设置下载消息头 + SmartResponseUtil.setDownloadFileHeader(response, fileName, null); + // 下载 + FastExcel.write(response.getOutputStream(), head) + .autoCloseStream(Boolean.FALSE) + .sheet(sheetName) + .doWrite(data); + } + + /** + * 通用单 sheet水印 导出 + */ + public static void exportExcelWithWatermark(HttpServletResponse response, String fileName, String sheetName, Class head,Collection data, String watermarkString) throws IOException { + // 设置下载消息头 + SmartResponseUtil.setDownloadFileHeader(response, fileName, null); + // 水印 + Watermark watermark = new Watermark(watermarkString); + // 一定要inMemory + FastExcel.write(response.getOutputStream(), head) + .inMemory(true) + .sheet(sheetName) + .registerWriteHandler(new CustomWaterMarkHandler(watermark)) + .doWrite(data); + } + + + @Slf4j + private static class CustomWaterMarkHandler implements SheetWriteHandler { + + private final Watermark watermark; + + public CustomWaterMarkHandler(Watermark watermark) { + this.watermark = watermark; + } + + @Override + public void afterSheetCreate(WriteWorkbookHolder writeWorkbookHolder, WriteSheetHolder writeSheetHolder) { + BufferedImage bufferedImage = createWatermarkImage(); + XSSFWorkbook workbook = (XSSFWorkbook) writeSheetHolder.getParentWriteWorkbookHolder().getWorkbook(); + try { + // 添加水印的具体操作 + addWatermarkToSheet(workbook, bufferedImage); + } catch (Exception e) { + log.error("添加水印出错:", e); + } + + } + + /** + * 创建水印图片 + * + * @return + */ + private BufferedImage createWatermarkImage() { + // 获取水印相关参数 + Font font = watermark.getFont(); + int width = watermark.getWidth(); + int height = watermark.getHeight(); + Color color = watermark.getColor(); + String text = watermark.getContent(); + + // 创建带有透明背景的 BufferedImage + BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB); + Graphics2D g = image.createGraphics(); + + // 设置画笔字体、平滑、颜色 + g.setFont(font); + g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); + g.setColor(color); + + // 计算水印位置和角度 + int y = watermark.getYAxis(); + int x = watermark.getXAxis(); + AffineTransform transform = AffineTransform.getRotateInstance(Math.toRadians(-watermark.getAngle()), 0, y); + g.setTransform(transform); + // 绘制水印文字 + g.drawString(text, x, y); + + // 释放资源 + g.dispose(); + + return image; + } + + private void addWatermarkToSheet(XSSFWorkbook workbook, BufferedImage watermarkImage) { + try (ByteArrayOutputStream os = new ByteArrayOutputStream()) { + ImageIO.write(watermarkImage, "png", os); + int pictureIdx = workbook.addPicture(os.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG); + XSSFPictureData pictureData = workbook.getAllPictures().get(pictureIdx); + for (int i = 0; i < workbook.getNumberOfSheets(); i++) { + // 获取每个Sheet表 + XSSFSheet sheet = workbook.getSheetAt(i); + PackagePartName ppn = pictureData.getPackagePart().getPartName(); + String relType = XSSFRelation.IMAGES.getRelation(); + PackageRelationship pr = sheet.getPackagePart().addRelationship(ppn, TargetMode.INTERNAL, relType, null); + sheet.getCTWorksheet().addNewPicture().setId(pr.getId()); + } + } catch (Exception e) { + // 处理ImageIO.write可能抛出的异常 + log.error("添加水印图片时发生错误", e); + } + } + } + + @Data + private static class Watermark { + + public Watermark(String content) { + this.content = content; + init(); + } + + public Watermark(String content, Color color, Font font, double angle) { + this.content = content; + this.color = color; + this.font = font; + this.angle = angle; + init(); + } + + /** + * 根据水印内容长度自适应水印图片大小,简单的三角函数 + */ + private void init() { + FontMetrics fontMetrics = new JLabel().getFontMetrics(this.font); + int stringWidth = fontMetrics.stringWidth(this.content); + int charWidth = fontMetrics.charWidth('A'); + this.width = (int) Math.abs(stringWidth * Math.cos(Math.toRadians(this.angle))) + 5 * charWidth; + this.height = (int) Math.abs(stringWidth * Math.sin(Math.toRadians(this.angle))) + 5 * charWidth; + this.yAxis = this.height; + this.xAxis = charWidth; + } + + /** + * 水印内容 + */ + private String content; + + /** + * 画笔颜色 + */ + private Color color = new Color(239,239,239); + + /** + * 字体样式 + */ + private Font font = new Font("Microsoft YaHei", Font.BOLD, 26); + + /** + * 水印宽度 + */ + private int width; + + /** + * 水印高度 + */ + private int height; + + /** + * 倾斜角度,非弧度制 + */ + private double angle = 25; + + /** + * 字体的y轴位置 + */ + private int yAxis = 50; + + /** + * 字体的X轴位置 + */ + private int xAxis; + + /** + * 水平倾斜度 + */ + private double shearX = 0.1; + + /** + * 垂直倾斜度 + */ + private double shearY = -0.26; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartIpUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartIpUtil.java new file mode 100644 index 0000000..0db96ed --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartIpUtil.java @@ -0,0 +1,120 @@ +package net.lab1024.sa.base.common.util; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.constant.StringConst; +import org.lionsoul.ip2region.xdb.Searcher; + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; + +/** + * IP工具类 + * + * @Date 2023/9/14 15:35:11 + * @Author wzh + */ +@Slf4j +public class SmartIpUtil { + + private static Searcher IP_SEARCHER; + + /** + * 初始化数据 + * + * @param filePath + */ + public static void init(String filePath) { + + try { + byte[] cBuff = Searcher.loadContentFromFile(filePath); + IP_SEARCHER = Searcher.newWithBuffer(cBuff); + + } catch (Throwable e) { + log.error("初始化ip2region.xdb文件失败,报错信息:[{}]", e.getMessage(), e); + throw new RuntimeException("系统异常!"); + } + } + + + /** + * 自定义解析ip地址 + * + * @param ipStr ipStr + * @return 返回结果例 [河南省, 洛阳市, 洛龙区] + */ + public static List getRegionList(String ipStr) { + List regionList = new ArrayList<>(); + try { + if (SmartStringUtil.isEmpty(ipStr)) { + return regionList; + } + ipStr = ipStr.trim(); + String region = IP_SEARCHER.search(ipStr); + String[] split = region.split("\\|"); + regionList.addAll(Arrays.asList(split)); + } catch (Exception e) { + log.error("解析ip地址出错", e); + } + return regionList; + } + + /** + * 自定义解析ip地址 + * + * @param ipStr ipStr + * @return 返回结果例 河南省|洛阳市|洛龙区 + */ + public static String getRegion(String ipStr) { + try { + if (SmartStringUtil.isEmpty(ipStr)) { + return StringConst.EMPTY; + } + ipStr = ipStr.trim(); + return IP_SEARCHER.search(ipStr); + } catch (Exception e) { + log.error("解析ip地址出错", e); + return StringConst.EMPTY; + } + } + + /** + * 获取本机第一个ip + * + * @return + */ + public static String getLocalFirstIp() { + List list = getLocalIp(); + return list.size() > 0 ? list.get(0) : null; + } + + /** + * 获取本机ip + * + * @return + */ + public static List getLocalIp() { + List ipList = new ArrayList<>(); + try { + Enumeration networkInterfaces = NetworkInterface.getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) { + NetworkInterface networkInterface = networkInterfaces.nextElement(); + Enumeration inetAddresses = networkInterface.getInetAddresses(); + while (inetAddresses.hasMoreElements()) { + InetAddress inetAddress = inetAddresses.nextElement(); + // 排除回环地址和IPv6地址 + if (!inetAddress.isLoopbackAddress() && !inetAddress.getHostAddress().contains(StringConst.COLON)) { + ipList.add(inetAddress.getHostAddress()); + } + } + } + } catch (SocketException e) { + e.printStackTrace(); + } + return ipList; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartLocalDateUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartLocalDateUtil.java new file mode 100644 index 0000000..288a844 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartLocalDateUtil.java @@ -0,0 +1,121 @@ +package net.lab1024.sa.base.common.util; + +import java.time.*; +import java.time.format.TextStyle; +import java.time.temporal.ChronoUnit; +import java.util.Date; +import java.util.Locale; + + +/** + * @Date 2023/12/5 22:25:43 + * @Author wzh + */ +public class SmartLocalDateUtil { + + + /** + * 格式化 LocalDateTime 返回对应格式字符串 + * + * @param time + * @param formatterEnum {@link SmartDateFormatterEnum} + * @return + */ + public static String format(LocalDateTime time, SmartDateFormatterEnum formatterEnum) { + return time.format(formatterEnum.getFormatter()); + } + + /** + * 格式化 LocalDate返回对应格式字符串 + * + * @param date + * @param formatterEnum {@link SmartDateFormatterEnum} + * @return + */ + public static String format(LocalDate date, SmartDateFormatterEnum formatterEnum) { + return date.format(formatterEnum.getFormatter()); + } + + /** + * 解析时间字符串 返回LocalDateTime + * + * @param time + * @param formatterEnum {@link SmartDateFormatterEnum} + * @return + */ + public static LocalDateTime parse(String time, SmartDateFormatterEnum formatterEnum) { + return LocalDateTime.parse(time, formatterEnum.getFormatter()); + } + + /** + * 解析时间字符串 返回 LocalDate + * + * @param time + * @param formatterEnum {@link SmartDateFormatterEnum} + * @return + */ + public static LocalDate parseDate(String time, SmartDateFormatterEnum formatterEnum) { + return LocalDate.parse(time, formatterEnum.getFormatter()); + } + + /** + * 获取指定日期时间戳 + * + * @param time + * @return + */ + public static Long getTimestamp(LocalDateTime time) { + return time.toInstant(ZoneOffset.ofHours(8)).toEpochMilli(); + } + + /** + * 获取当前时间戳(秒) + * + * @return + */ + public static long nowSecond() { + return System.currentTimeMillis() / 1000; + } + + /** + * 将时间格式化为 星期几,例:星期一 ... 星期日 + * + * @param localDate + * @return + */ + public static String formatToChineseWeek(LocalDate localDate) { + return localDate.getDayOfWeek().getDisplayName(TextStyle.FULL, Locale.CHINESE); + } + + /** + * 将时间格式化为 周几,例:周一 ... 周日 + * + * @param localDate + * @return + */ + public static String formatToChineseWeekZhou(LocalDate localDate) { + return formatToChineseWeek(localDate).replace("星期", "周"); + } + + public static LocalDateTime toLocalDateTime(Date date) { + return Instant.ofEpochMilli(date.getTime()).atZone(ZoneId.systemDefault()).toLocalDateTime(); + } + + /** + * 获取当天剩余时间 单位 + * + * @param unit 时间单位 + * @return + */ + public static Long getDayBalanceTime(ChronoUnit unit) { + LocalDateTime now = LocalDateTime.now(); + return Duration.between(now, now.plusDays(1L).with(LocalTime.MIN)).get(unit); + } + + public static void main(String[] args) { + System.out.println(SmartLocalDateUtil.format(LocalDateTime.now(), SmartDateFormatterEnum.YMD_HMS)); + System.out.println(SmartLocalDateUtil.format(LocalDateTime.now(), SmartDateFormatterEnum.YMD_HM)); + System.out.println(SmartLocalDateUtil.parse("2021-10-15 10:10:00", SmartDateFormatterEnum.YMD_HMS)); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartPageUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartPageUtil.java new file mode 100644 index 0000000..fb7092d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartPageUtil.java @@ -0,0 +1,119 @@ +package net.lab1024.sa.base.common.util; + +import com.baomidou.mybatisplus.core.metadata.OrderItem; +import com.baomidou.mybatisplus.core.toolkit.sql.SqlInjectionUtils; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.exception.BusinessException; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.ArrayList; +import java.util.List; + +/** + * 分页工具类 + * + * @Date 2020-04-23 20:51:40 + * @Author wzh + */ +@Slf4j +public class SmartPageUtil { + + /** + * 转换为查询参数 + */ + public static Page convert2PageQuery(PageParam pageParam) { + Page page = new Page<>(pageParam.getPageNum(), pageParam.getPageSize()); + + if (pageParam.getSearchCount() != null) { + page.setSearchCount(pageParam.getSearchCount()); + } + + List sortItemList = pageParam.getSortItemList(); + if (CollectionUtils.isEmpty(sortItemList)) { + return page; + } + + // 设置排序字段并检测是否含有sql注入 + List orderItemList = new ArrayList<>(); + for (PageParam.SortItem sortItem : sortItemList) { + + if (SmartStringUtil.isEmpty(sortItem.getColumn())) { + continue; + } + + if (SqlInjectionUtils.check(sortItem.getColumn())) { + log.error("《存在SQL注入:》 : {}", sortItem.getColumn()); + throw new BusinessException("存在SQL注入风险,请联系技术工作人员!"); + } + + OrderItem orderItem = new OrderItem(); + orderItem.setColumn(sortItem.getColumn()); + orderItem.setAsc(sortItem.getIsAsc()); + orderItemList.add(orderItem); + } + page.setOrders(orderItemList); + return page; + } + + /** + * 转换为 PageResult 对象 + */ + public static PageResult convert2PageResult(Page page, List sourceList, Class targetClazz) { + return convert2PageResult(page, SmartBeanUtil.copyList(sourceList, targetClazz)); + } + + /** + * 转换为 PageResult 对象 + */ + public static PageResult convert2PageResult(Page page, List sourceList) { + PageResult pageResult = new PageResult<>(); + pageResult.setPageNum(page.getCurrent()); + pageResult.setPageSize(page.getSize()); + pageResult.setTotal(page.getTotal()); + pageResult.setPages(page.getPages()); + pageResult.setList(sourceList); + pageResult.setEmptyFlag(CollectionUtils.isEmpty(sourceList)); + return pageResult; + } + + /** + * 转换分页结果对象 + */ + public static PageResult convert2PageResult(PageResult pageResult, Class targetClazz) { + PageResult newPageResult = new PageResult<>(); + newPageResult.setPageNum(pageResult.getPageNum()); + newPageResult.setPageSize(pageResult.getPageSize()); + newPageResult.setTotal(pageResult.getTotal()); + newPageResult.setPages(pageResult.getPages()); + newPageResult.setEmptyFlag(pageResult.getEmptyFlag()); + newPageResult.setList(SmartBeanUtil.copyList(pageResult.getList(), targetClazz)); + return newPageResult; + } + + public static PageResult subListPage(Integer pageNum, Integer pageSize, List list) { + PageResult pageRet = new PageResult(); + //总条数 + int count = list.size(); + int pages = count % pageSize == 0 ? count / pageSize : (count / pageSize + 1); + int fromIndex = (pageNum - 1) * pageSize; + int toIndex = Math.min(pageNum * pageSize, count); + + if (pageNum > pages) { + pageRet.setList(Lists.newLinkedList()); + pageRet.setPageNum(pageNum.longValue()); + pageRet.setPages((long) pages); + pageRet.setTotal((long) count); + return pageRet; + } + List pageList = list.subList(fromIndex, toIndex); + pageRet.setList(pageList); + pageRet.setPageNum(pageNum.longValue()); + pageRet.setPages((long) pages); + pageRet.setTotal((long) count); + return pageRet; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartRequestUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartRequestUtil.java new file mode 100644 index 0000000..f5cd922 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartRequestUtil.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.common.util; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.RequestUser; + +/** + * 请求用户 工具类 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +@Slf4j +public class SmartRequestUtil { + + private static final ThreadLocal REQUEST_THREAD_LOCAL = new ThreadLocal<>(); + + public static void setRequestUser(RequestUser requestUser) { + REQUEST_THREAD_LOCAL.set(requestUser); + } + + public static RequestUser getRequestUser() { + return REQUEST_THREAD_LOCAL.get(); + } + + public static Long getRequestUserId() { + RequestUser requestUser = getRequestUser(); + return null == requestUser ? null : requestUser.getUserId(); + } + + + public static void remove() { + REQUEST_THREAD_LOCAL.remove(); + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartResponseUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartResponseUtil.java new file mode 100644 index 0000000..7d8ee45 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartResponseUtil.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.base.common.util; + +import com.alibaba.fastjson.JSON; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.http.MediaTypeFactory; + +import java.io.IOException; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; + +import static cn.hutool.core.util.CharsetUtil.UTF_8; + +/** + * 返回工具栏 + * + * @Date 2023/11/25 18:51:32 + * @Author wzh + */ + +@Slf4j +public class SmartResponseUtil { + + public static void write(HttpServletResponse response, ResponseDTO responseDTO) { + // 重置response + response.setContentType(MediaType.APPLICATION_JSON_VALUE); + response.setCharacterEncoding(UTF_8); + + try { + response.getWriter().write(JSON.toJSONString(responseDTO)); + response.flushBuffer(); + } catch (IOException ex) { + log.error(ex.getMessage(), ex); + throw new RuntimeException(ex); + } + } + + public static void setDownloadFileHeader(HttpServletResponse response, String fileName) { + setDownloadFileHeader(response, fileName, null); + } + + public static void setDownloadFileHeader(HttpServletResponse response, String fileName, Long fileSize) { + response.setCharacterEncoding(UTF_8); + if (fileSize != null) { + response.setHeader(HttpHeaders.CONTENT_LENGTH, String.valueOf(fileSize)); + } + + if (SmartStringUtil.isNotEmpty(fileName)) { + response.setHeader(HttpHeaders.CONTENT_TYPE, MediaTypeFactory.getMediaType(fileName).orElse(MediaType.APPLICATION_OCTET_STREAM) + ";charset=utf-8"); + response.setHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment;filename=" + URLEncoder.encode(fileName, StandardCharsets.UTF_8).replaceAll("\\+", "%20")); + response.setHeader(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, HttpHeaders.CONTENT_DISPOSITION); + } + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartStringUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartStringUtil.java new file mode 100644 index 0000000..236f922 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartStringUtil.java @@ -0,0 +1,439 @@ +package net.lab1024.sa.base.common.util; + + +import cn.hutool.core.util.StrUtil; + +import java.util.*; + +/** + * 独有的字符串工具类 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ +public class SmartStringUtil extends StrUtil { + + /** 空字符串 */ + private static final String NULLSTR = ""; + public static final String SEPARATOR = ","; + + public static final String SLASH = "/"; + + // ===============split ======================= + + public static Set splitConvertToSet(String str, String split) { + if (isEmpty(str)) { + return new HashSet(); + } + String[] splitArr = str.split(split); + HashSet set = new HashSet(splitArr.length); + Collections.addAll(set, splitArr); + return set; + } + + public static List splitConvertToList(String str, String split) { + if (isEmpty(str)) { + return new ArrayList(); + } + String[] splitArr = str.split(split); + ArrayList list = new ArrayList(splitArr.length); + list.addAll(Arrays.asList(splitArr)); + return list; + } + + // ===============split Integer======================= + + public static List splitConvertToIntList(String str, String split, int defaultVal) { + if (isEmpty(str)) { + return new ArrayList(); + } + String[] strArr = str.split(split); + List list = new ArrayList(strArr.length); + for (int i = 0; i < strArr.length; i++) { + try { + int parseInt = Integer.parseInt(strArr[i]); + list.add(parseInt); + } catch (NumberFormatException e) { + list.add(defaultVal); + continue; + } + } + return list; + } + + public static Set splitConvertToIntSet(String str, String split, int defaultVal) { + if (isEmpty(str)) { + return new HashSet(); + } + String[] strArr = str.split(split); + HashSet set = new HashSet(strArr.length); + for (int i = 0; i < strArr.length; i++) { + try { + int parseInt = Integer.parseInt(strArr[i]); + set.add(parseInt); + } catch (NumberFormatException e) { + set.add(defaultVal); + continue; + } + } + return set; + } + + public static Set splitConvertToIntSet(String str, String split) { + return splitConvertToIntSet(str, split, 0); + } + + public static List splitConvertToIntList(String str, String split) { + return splitConvertToIntList(str, split, 0); + } + + public static int[] splitConvertToIntArray(String str, String split, int defaultVal) { + if (isEmpty(str)) { + return new int[0]; + } + String[] strArr = str.split(split); + int[] result = new int[strArr.length]; + for (int i = 0; i < strArr.length; i++) { + try { + result[i] = Integer.parseInt(strArr[i]); + } catch (NumberFormatException e) { + result[i] = defaultVal; + continue; + } + } + return result; + } + + public static int[] splitConvertToIntArray(String str, String split) { + return splitConvertToIntArray(str, split, 0); + } + + // ===============split 2 Long======================= + + public static List splitConvertToLongList(String str, String split, long defaultVal) { + if (isEmpty(str)) { + return new ArrayList(); + } + String[] strArr = str.split(split); + List list = new ArrayList(strArr.length); + for (int i = 0; i < strArr.length; i++) { + try { + long parseLong = Long.parseLong(strArr[i]); + list.add(parseLong); + } catch (NumberFormatException e) { + list.add(defaultVal); + continue; + } + } + return list; + } + + public static List splitConvertToLongList(String str, String split) { + return splitConvertToLongList(str, split, 0L); + } + + public static long[] splitConvertToLongArray(String str, String split, long defaultVal) { + if (isEmpty(str)) { + return new long[0]; + } + String[] strArr = str.split(split); + long[] result = new long[strArr.length]; + for (int i = 0; i < strArr.length; i++) { + try { + result[i] = Long.parseLong(strArr[i]); + } catch (NumberFormatException e) { + result[i] = defaultVal; + continue; + } + } + return result; + } + + public static long[] splitConvertToLongArray(String str, String split) { + return splitConvertToLongArray(str, split, 0L); + } + + // ===============split convert byte======================= + + public static List splitConvertToByteList(String str, String split, byte defaultVal) { + if (isEmpty(str)) { + return new ArrayList(); + } + String[] strArr = str.split(split); + List list = new ArrayList(strArr.length); + for (int i = 0; i < strArr.length; i++) { + try { + byte parseByte = Byte.parseByte(strArr[i]); + list.add(parseByte); + } catch (NumberFormatException e) { + list.add(defaultVal); + continue; + } + } + return list; + } + + public static List splitConvertToByteList(String str, String split) { + return splitConvertToByteList(str, split, (byte) 0); + } + + public static byte[] splitConvertToByteArray(String str, String split, byte defaultVal) { + if (isEmpty(str)) { + return new byte[0]; + } + String[] strArr = str.split(split); + byte[] result = new byte[strArr.length]; + for (int i = 0; i < strArr.length; i++) { + try { + result[i] = Byte.parseByte(strArr[i]); + } catch (NumberFormatException e) { + result[i] = defaultVal; + continue; + } + } + return result; + } + + public static byte[] splitConvertToByteArray(String str, String split) { + return splitConvertToByteArray(str, split, (byte) 0); + } + + // ===============split convert double======================= + + public static List splitConvertToDoubleList(String str, String split, double defaultVal) { + if (isEmpty(str)) { + return new ArrayList(); + } + String[] strArr = str.split(split); + List list = new ArrayList(strArr.length); + for (int i = 0; i < strArr.length; i++) { + try { + double parseByte = Double.parseDouble(strArr[i]); + list.add(parseByte); + } catch (NumberFormatException e) { + list.add(defaultVal); + continue; + } + } + return list; + } + + public static List splitConvertToDoubleList(String str, String split) { + return splitConvertToDoubleList(str, split, 0); + } + + public static double[] splitConvertToDoubleArray(String str, String split, double defaultVal) { + if (isEmpty(str)) { + return new double[0]; + } + String[] strArr = str.split(split); + double[] result = new double[strArr.length]; + for (int i = 0; i < strArr.length; i++) { + try { + result[i] = Double.parseDouble(strArr[i]); + } catch (NumberFormatException e) { + result[i] = defaultVal; + continue; + } + } + return result; + } + + public static double[] splitConvertToDoubleArray(String str, String split) { + return splitConvertToDoubleArray(str, split, 0); + } + + // ===============split convert float======================= + + public static List splitConvertToFloatList(String str, String split, float defaultVal) { + if (isEmpty(str)) { + return new ArrayList(); + } + String[] strArr = str.split(split); + List list = new ArrayList(strArr.length); + for (int i = 0; i < strArr.length; i++) { + try { + float parseByte = Float.parseFloat(strArr[i]); + list.add(parseByte); + } catch (NumberFormatException e) { + list.add(defaultVal); + continue; + } + } + return list; + } + + public static List splitConvertToFloatList(String str, String split) { + return splitConvertToFloatList(str, split, 0f); + } + + public static float[] splitConvertToFloatArray(String str, String split, float defaultVal) { + if (isEmpty(str)) { + return new float[0]; + } + String[] strArr = str.split(split); + float[] result = new float[strArr.length]; + for (int i = 0; i < strArr.length; i++) { + try { + result[i] = Float.parseFloat(strArr[i]); + } catch (NumberFormatException e) { + result[i] = defaultVal; + continue; + } + } + return result; + } + + public static float[] splitConvertToFloatArray(String str, String split) { + return splitConvertToFloatArray(str, split, 0f); + } + + + public static String upperCaseFirstChar(String str) { + if (str != null && !str.isEmpty()) { + char firstChar = str.charAt(0); + if (Character.isUpperCase(firstChar)) { + return str; + } else { + char[] values = str.toCharArray(); + values[0] = Character.toUpperCase(firstChar); + return new String(values); + } + } else { + return str; + } + } + + public static String replace(String content, int begin, int end, String newStr) { + if (begin < content.length() && begin >= 0) { + if (end <= content.length() && end >= 0) { + if (begin > end) { + return content; + } else { + StringBuilder starStr = new StringBuilder(); + + for (int i = begin; i < end; ++i) { + starStr.append(newStr); + } + + return content.substring(0, begin) + starStr + content.substring(end); + } + } else { + return content; + } + } else { + return content; + } + } + + /** + * * 判断一个Collection是否为空, 包含List,Set,Queue + * + * @param coll 要判断的Collection + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Collection coll) + { + return isNull(coll) || coll.isEmpty(); + } + + /** + * * 判断一个Collection是否非空,包含List,Set,Queue + * + * @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); + } + + /** + * * 判断一个Map是否为空 + * + * @param map 要判断的Map + * @return true:为空 false:非空 + */ + public static boolean isEmpty(Map map) + { + return isNull(map) || map.isEmpty(); + } + + /** + * * 判断一个Map是否为空 + * + * @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); + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartTableMetadataUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartTableMetadataUtil.java new file mode 100644 index 0000000..3fe6904 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartTableMetadataUtil.java @@ -0,0 +1,215 @@ +package net.lab1024.sa.base.common.util; + +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; +import com.baomidou.mybatisplus.core.metadata.TableFieldInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfo; +import com.baomidou.mybatisplus.core.metadata.TableInfoHelper; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +import javax.sql.DataSource; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.ResultSet; +import java.util.HashMap; +import java.util.Map; + +@Component +public class SmartTableMetadataUtil { + + @Resource + private DataSource dataSource; // 注入的数据源 + + private static DataSource staticDataSource; // 静态变量保存数据源 + + @PostConstruct + public void init() { + staticDataSource = this.dataSource; + } + + + /** + * 根据实体类获取表元数据 + * @param entityClass 实体类Class对象 + * @return JSON格式的表元数据 + */ + public static JSONObject getTableMetadata(Class entityClass) throws Exception { + TableInfo tableInfo = TableInfoHelper.getTableInfo(entityClass); + if (tableInfo == null) { + throw new RuntimeException("实体类未配置MyBatis-Plus注解"); + } + return getTableMetadataByTableInfo(tableInfo); + } + + /** + * 根据表名获取表元数据 + * @param tableName 数据库表名 + * @return JSON格式的表元数据 + */ + public static JSONObject getTableMetadata(String tableName) throws Exception { + if (staticDataSource == null) { + throw new RuntimeException("数据源未初始化"); + } + return getTableMetadataByTableName(tableName); + } + + /** + * 根据TableInfo获取表元数据(内部方法) + * @param tableInfo MyBatis-Plus表信息 + * @return JSON格式的表元数据 + */ + private static JSONObject getTableMetadataByTableInfo(TableInfo tableInfo) throws Exception { + String tableName = tableInfo.getTableName(); + + // 1. 获取表注释 + String tableComment = getTableCommentFromDB(tableName); + JSONObject tableJson = new JSONObject(); + tableJson.set("englishName", tableName); + tableJson.set("chineseName", tableComment); + + // 2. 获取字段注释 + Map fieldComments = getFieldCommentsFromDB(tableName); + JSONArray columns = new JSONArray(); + for (TableFieldInfo field : tableInfo.getFieldList()) { + JSONObject column = new JSONObject(); + String columnName = field.getColumn(); + column.set("englishName", columnName); + column.set("chineseName", fieldComments.getOrDefault(columnName, "无注释")); + column.set("javaType", field.getPropertyType().getSimpleName()); + columns.add(column); + } + + // 3. 构建结果 + JSONObject result = new JSONObject(); + result.set("table", tableJson); + result.set("columns", columns); + return result; + } + + /** + * 根据表名获取表元数据(内部方法) + * @param tableName 数据库表名 + * @return JSON格式的表元数据 + */ + private static JSONObject getTableMetadataByTableName(String tableName) throws Exception { + // 1. 获取表注释 + String tableComment = getTableCommentFromDB(tableName); + JSONObject tableJson = new JSONObject(); + tableJson.set("englishName", tableName); + tableJson.set("chineseName", tableComment); + + // 2. 获取字段信息和注释 + Map fieldComments = getFieldCommentsFromDB(tableName); + Map fieldTypes = getFieldTypesFromDB(tableName); + + JSONArray columns = new JSONArray(); + for (Map.Entry entry : fieldComments.entrySet()) { + String columnName = entry.getKey(); + String comment = entry.getValue(); + String sqlType = fieldTypes.getOrDefault(columnName, "VARCHAR"); + + JSONObject column = new JSONObject(); + column.set("englishName", columnName); + column.set("chineseName", comment); + column.set("sqlType", sqlType); + column.set("javaType", sqlTypeToJavaType(sqlType)); + columns.add(column); + } + + // 3. 构建结果 + JSONObject result = new JSONObject(); + result.set("table", tableJson); + result.set("columns", columns); + return result; + } + + // 从数据库获取表注释(基于JDBC元数据) + private static String getTableCommentFromDB(String tableName) throws Exception { + try (Connection conn = staticDataSource.getConnection()) { + DatabaseMetaData metaData = conn.getMetaData(); + try (ResultSet rs = metaData.getTables(null, null, tableName, new String[]{"TABLE"})) { + if (rs.next()) return rs.getString("REMARKS"); + } + } + return tableName; + } + + // 批量获取字段注释 + private static Map getFieldCommentsFromDB(String tableName) throws Exception { + Map comments = new HashMap<>(); + try (Connection conn = staticDataSource.getConnection()) { + DatabaseMetaData metaData = conn.getMetaData(); + try (ResultSet rs = metaData.getColumns(null, null, tableName, null)) { + while (rs.next()) { + String columnName = rs.getString("COLUMN_NAME"); + String remark = rs.getString("REMARKS"); + comments.put(columnName, remark != null ? remark : "无注释"); + } + } + } + return comments; + } + + // 批量获取字段类型 + private static Map getFieldTypesFromDB(String tableName) throws Exception { + Map types = new HashMap<>(); + try (Connection conn = staticDataSource.getConnection()) { + DatabaseMetaData metaData = conn.getMetaData(); + try (ResultSet rs = metaData.getColumns(null, null, tableName, null)) { + while (rs.next()) { + String columnName = rs.getString("COLUMN_NAME"); + String typeName = rs.getString("TYPE_NAME"); + int columnSize = rs.getInt("COLUMN_SIZE"); + int decimalDigits = rs.getInt("DECIMAL_DIGITS"); + + // 构建完整的类型信息 + String fullType = typeName; + if (columnSize > 0) { + if (decimalDigits > 0) { + fullType = typeName + "(" + columnSize + "," + decimalDigits + ")"; + } else { + fullType = typeName + "(" + columnSize + ")"; + } + } + types.put(columnName, fullType); + } + } + } + return types; + } + + // SQL类型转Java类型 + private static String sqlTypeToJavaType(String sqlType) { + if (sqlType == null) return "String"; + + String upperType = sqlType.toUpperCase(); + if (upperType.startsWith("VARCHAR") || upperType.startsWith("CHAR") || + upperType.startsWith("TEXT") || upperType.startsWith("LONGTEXT")) { + return "String"; + } else if (upperType.startsWith("INT") || upperType.startsWith("TINYINT") || + upperType.startsWith("SMALLINT") || upperType.startsWith("MEDIUMINT")) { + return "Integer"; + } else if (upperType.startsWith("BIGINT")) { + return "Long"; + } else if (upperType.startsWith("DECIMAL") || upperType.startsWith("NUMERIC")) { + return "BigDecimal"; + } else if (upperType.startsWith("FLOAT")) { + return "Float"; + } else if (upperType.startsWith("DOUBLE")) { + return "Double"; + } else if (upperType.startsWith("DATE")) { + return "Date"; + } else if (upperType.startsWith("DATETIME") || upperType.startsWith("TIMESTAMP")) { + return "Date"; + } else if (upperType.startsWith("TIME")) { + return "Time"; + } else if (upperType.startsWith("BOOLEAN") || upperType.startsWith("BIT")) { + return "Boolean"; + } else { + return "String"; + } + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartVerificationUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartVerificationUtil.java new file mode 100644 index 0000000..539e480 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SmartVerificationUtil.java @@ -0,0 +1,95 @@ +package net.lab1024.sa.base.common.util; + +import java.util.regex.Pattern; + +/** + * 验证工具类 + * + * @Date 2017/11/06 10:54 + * @Author wzh + */ +public class SmartVerificationUtil { + + /** + * 手机号码验证规则 + */ + public static final String PHONE_REGEXP = "^1[0-9]{10}"; + + /** + * 固定号码验证规则 + */ + public static final String FIXED_PHONE_REGEXP = "^0\\d{2,3}-[1-9]\\d{6,7}$"; + + /** + * 密码正则校验 + */ + public static final String PWD_REGEXP = "^[A-Za-z0-9.]{6,15}$"; + + /** + * 车牌号 + */ + public static final String CAR_NUMBER = + "([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼]{1}(([A-HJ-Z]{1}[A-HJ-NP-Z0-9]{5})|([A-HJ-Z]{1}(([DF]{1}[A-HJ-NP-Z0-9]{1}[0-9]{4})|([0-9]{5}[DF]{1})))|" + "([A-HJ-Z" + "]{1}[A-D0-9]{1}[0-9]{3}警)))|" + + "([0-9]{6}使)|((([沪粤川云桂鄂陕蒙藏黑辽渝]{1}A)|鲁B|闽D|蒙E|蒙H)[0-9]{4}领)|(WJ[京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼·•]{1}[0-9]{4}[TDSHBXJ0-9]{1})|" + "([VKHBSLJNGCE]{1}[A-DJ-PR" + "-TVY]{1}[0-9]{5})"; + + /** + * 日期年月日校验 yyyy-MM-dd HH:mm:ss + */ + public static final String DATE_TIME = "^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9" + + "]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"; + + /** + * 日期校验 yyyy-MM-dd + */ + public static final String DATE = "(([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))" + + "|(02-(0[1-9]|[1][0-9]|2[0-8])))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29)" + "([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9" + + "][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|(" + "(([0-9]{2})(0[48]|[2468][048]|[13579][26])|(" + "(0[48" + "]|[2468][048]|[3579][26])00))-02-29)"; + + public static final String DATE_TIME_HM = "^((([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})-(((0[13578]|1[02])-(0[1-9]|[12][0-9]|3[01]))|((0[469]|11)-(0[1-9]|[12][0-9]|30))|(02-(0[1-9]|[1][0-9]|2[0-8]))))|((([0-9]{2})(0[48]|[2468][048]|[13579][26])|((0[48]|[2468][048]|[3579][26])00))-02-29))\\s+([0-1]?[0-9]|2[0-3]):([0-5][0-9])$"; + + /** + * 年月校验 例: 2019-10 + */ + public static final String YEAR_MONTH = "^\\d{4}-((0([1-9]))|(1(0|1|2)))$"; + + /** + * 时间区间验证 10:23-19:00 + */ + public static final String TIME_SECTION = "^(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9])-(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9])$"; + + /** + * 时间验证 10:23 + */ + public static final String TIME = "^(0[0-9]|1[0-9]|2[0-3]):(0[0-9]|[1-5][0-9])$"; + + /** + * 身份证号 + */ + public static final String ID_CARD = "(^\\d{15}$)|(^\\d{18}$)|(^\\d{17}(\\d|X|x)$)"; + + /** + * URL + */ + public static final String URL = "[a-zA-z]+://[^\\s]*"; + + /** + * 邮箱 + */ + public static final String EMAIL = "[\\w!#$%&'*+/=?^_`{|}~-]+(?:\\.[\\w!#$%&'*+/=?^_`{|}~-]+)*@(?:[\\w](?:[\\w-]*[\\w])?\\.)+[\\w](?:[\\w-]*[\\w])?"; + + /** + * 整数 + */ + public static final String INTEGER = "^-?[1-9]\\d*$"; + + /** + * 小数 + */ + public static final String DOUBLE = "^-?[1-9]\\d*\\.\\d*|0\\.\\d*[1-9]\\d*$"; + + + public static void main(String[] args) { + boolean matches = Pattern.matches(INTEGER, "1"); + System.out.println(matches); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SpringUtils.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SpringUtils.java new file mode 100644 index 0000000..cbc0fb7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/util/SpringUtils.java @@ -0,0 +1,174 @@ +package net.lab1024.sa.base.common.util; + +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 java.util.Map; + +/** + * spring工具类 方便在非spring管理环境中获取bean + * + * @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; + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + /** + * 获取对象 + * + * @param name + * @return Object 一个以所给名字注册的bean的实例 + * @throws BeansException + * + */ + @SuppressWarnings("unchecked") + public static T getBean(String name) throws BeansException + { + return (T) beanFactory.getBean(name); + } + + /** + * 获取类型为requiredType的对象 + * + * @param clz + * @return + * @throws BeansException + * + */ + public static T getBean(Class 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定义是一个singleton还是一个prototype。 如果与给定名字相应的bean定义没有被找到,将会抛出一个异常(NoSuchBeanDefinitionException) + * + * @param name + * @return boolean + * @throws NoSuchBeanDefinitionException + * + */ + public static boolean isSingleton(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.isSingleton(name); + } + + /** + * @param name + * @return Class 注册对象的类型 + * @throws NoSuchBeanDefinitionException + * + */ + public static Class getType(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getType(name); + } + + /** + * 如果给定的bean名字在bean定义中有别名,则返回这些别名 + * + * @param name + * @return + * @throws NoSuchBeanDefinitionException + * + */ + public static String[] getAliases(String name) throws NoSuchBeanDefinitionException + { + return beanFactory.getAliases(name); + } + + /** + * 获取aop代理对象 + * + * @param invoker + * @return + */ + @SuppressWarnings("unchecked") + public static T getAopProxy(T invoker) + { + return (T) AopContext.currentProxy(); + } + + /** + * 获取当前的环境配置,无配置返回null + * + * @return 当前的环境配置 + */ + public static String[] getActiveProfiles() + { + return applicationContext.getEnvironment().getActiveProfiles(); + } + + /** + * 获取当前的环境配置,当有多个环境配置时,只获取第一个 + * + * @return 当前的环境配置 + */ + public static String getActiveProfile() + { + final String[] activeProfiles = getActiveProfiles(); + return SmartStringUtil.isNotEmpty(activeProfiles) ? activeProfiles[0] : null; + } + + /** + * 获取配置文件中的值 + * + * @param key 配置文件的key + * @return 当前的配置文件的值 + * + */ + public static String getRequiredProperty(String key) + { + return applicationContext.getEnvironment().getRequiredProperty(key); + } + + /** + * 获取clazz类型所有的实现类,key为类名 + * + * @param clazz 类类型 + * @param T + * @return 所有实现类 + */ + public static Map getBeanNamesForType(Class clazz) { + return beanFactory.getBeansOfType(clazz); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/validator/enumeration/CheckEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/validator/enumeration/CheckEnum.java new file mode 100644 index 0000000..85d8dc9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/validator/enumeration/CheckEnum.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.base.common.validator.enumeration; + + +import jakarta.validation.Constraint; +import jakarta.validation.Payload; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 自定义的属性校验注解,为了方便与校验属性的值是否为合法的枚举值 + * + * @Date 2017/11/11 15:31 + * @Author wzh + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@Constraint(validatedBy = EnumValidator.class)// 自定义验证的处理类 +public @interface CheckEnum { + + /** + * 默认的错误提示信息 + * + * @return String + */ + String message(); + + /** + * 枚举类对象 必须实现BaseEnum接口 + * + */ + Class value(); + + /** + * 是否必须 + * + * @return boolean + */ + boolean required() default false; + + //下面这两个属性必须添加 :不然会报错 + Class[] groups() default {}; + + Class[] payload() default {}; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/validator/enumeration/EnumValidator.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/validator/enumeration/EnumValidator.java new file mode 100644 index 0000000..af84df4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/common/validator/enumeration/EnumValidator.java @@ -0,0 +1,70 @@ +package net.lab1024.sa.base.common.validator.enumeration; + + +import jakarta.validation.ConstraintValidator; +import jakarta.validation.ConstraintValidatorContext; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * 枚举类校验器 + * + * @Date 2017/11/11 15:34 + * @Author wzh + */ +public class EnumValidator implements ConstraintValidator { + + /** + * 枚举类实例集合 + */ + private List enumValList; + + /** + * 是否必须 + */ + private boolean required; + + @Override + public void initialize(CheckEnum constraintAnnotation) { + // 获取注解传入的枚举类对象 + required = constraintAnnotation.required(); + Class enumClass = constraintAnnotation.value(); + enumValList = Stream.of(enumClass.getEnumConstants()).map(BaseEnum::getValue).collect(Collectors.toList()); + } + + @Override + public boolean isValid(Object value, ConstraintValidatorContext constraintValidatorContext) { + // 判断是否必须 + if (null == value) { + return !required; + } + + if (value instanceof List) { + // 如果为 List 集合数据 + return this.checkList((List) value); + } + + // 校验是否为合法的枚举值 + return enumValList.contains(value); + } + + /** + * 校验集合类型 + * + */ + private boolean checkList(List list) { + if (required && list.isEmpty()) { + // 必须的情况下 list 不能为空 + return false; + } + // 校验是否重复 + long count = list.stream().distinct().count(); + if (count != list.size()) { + return false; + } + return enumValList.containsAll(list); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/AsyncConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/AsyncConfig.java new file mode 100644 index 0000000..323cdb0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/AsyncConfig.java @@ -0,0 +1,68 @@ +package net.lab1024.sa.base.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.task.AsyncTaskExecutor; +import org.springframework.scheduling.annotation.AsyncConfigurer; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; + +import java.lang.reflect.Method; +import java.util.Arrays; + +/** + * 异步调用线程配置 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ +@Slf4j +@Configuration +public class AsyncConfig { + + /** + * 线程池 配置bean名称 + */ + public static final String ASYNC_EXECUTOR_THREAD_NAME = "smart-async-executor"; + + /** + * 配置线程池 + * + * @return + */ + @Bean(name = ASYNC_EXECUTOR_THREAD_NAME) + public AsyncTaskExecutor executor() { + int processors = Runtime.getRuntime().availableProcessors(); + int threadCount = Math.max(1, processors - 1); + ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor(); + // 核心线程数量 + taskExecutor.setCorePoolSize(threadCount); + // 最大线程数量 + taskExecutor.setMaxPoolSize(threadCount); + taskExecutor.setThreadNamePrefix(ASYNC_EXECUTOR_THREAD_NAME); + taskExecutor.initialize(); + return taskExecutor; + } + + /** + * spring 异步任务 异常配置 + */ + @Configuration + public static class AsyncExceptionConfig implements AsyncConfigurer { + @Override + public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() { + return new AsyncExceptionHandler(); + } + } + + /** + * 自定义异常处理 + */ + public static class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler { + @Override + public void handleUncaughtException(Throwable throwable, Method method, Object... objects) { + log.error("异步任务发生异常:{}, 参数:{}, ", method.getDeclaringClass().getSimpleName() + "." + method.getName(), Arrays.toString(objects), throwable); + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/CacheConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/CacheConfig.java new file mode 100644 index 0000000..bf6de16 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/CacheConfig.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.base.config; + +import net.lab1024.sa.base.module.support.cache.CacheService; +import net.lab1024.sa.base.module.support.cache.CaffeineCacheServiceImpl; +import net.lab1024.sa.base.module.support.cache.RedisCacheServiceImpl; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 缓存配置 + * + * @author zhoumingfa + * @date 2025/03/28 + */ +@Configuration +public class CacheConfig { + + private static final String REDIS_CACHE = "redis"; + private static final String CAFFEINE_CACHE = "caffeine"; + + + @Bean + @ConditionalOnProperty(prefix = "spring.cache", name = {"type"}, havingValue = REDIS_CACHE) + public CacheService redisCacheService() { + return new RedisCacheServiceImpl(); + } + + @Bean + @ConditionalOnProperty(prefix = "spring.cache", name = {"type"}, havingValue = CAFFEINE_CACHE) + public CacheService caffeineCacheService() { + return new CaffeineCacheServiceImpl(); + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/CorsFilterConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/CorsFilterConfig.java new file mode 100644 index 0000000..c05d15a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/CorsFilterConfig.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.cors.CorsConfiguration; +import org.springframework.web.cors.UrlBasedCorsConfigurationSource; +import org.springframework.web.filter.CorsFilter; + +/** + * 跨域配置 + * + * @Date 2021/11/15 20:38 + * @Author wzh + */ +@Configuration +@Conditional(SystemEnvironmentConfig.class) +public class CorsFilterConfig { + + @Value("${access-control-allow-origin}") + private String accessControlAllowOrigin; + + /** + * 跨域配置 + */ + @Bean + public CorsFilter corsFilter () { + UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); + CorsConfiguration config = new CorsConfiguration(); + config.setAllowCredentials(true); + // 设置访问源地址 + config.addAllowedOriginPattern(accessControlAllowOrigin); + // 设置访问源请求头 + config.addAllowedHeader("*"); + // 设置访问源请求方法 + config.addAllowedMethod("*"); + // 对接口配置跨域设置 + source.registerCorsConfiguration("/**", config); + return new CorsFilter(source); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/DataSourceConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/DataSourceConfig.java new file mode 100644 index 0000000..1af7ede --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/DataSourceConfig.java @@ -0,0 +1,205 @@ +package net.lab1024.sa.base.config; + +import com.alibaba.druid.filter.Filter; +import com.alibaba.druid.filter.stat.StatFilter; +import com.alibaba.druid.pool.DruidDataSource; +import com.alibaba.druid.support.jakarta.StatViewServlet; +import com.alibaba.druid.support.jakarta.WebStatFilter; +import com.alibaba.druid.support.spring.stat.DruidStatInterceptor; +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.core.config.GlobalConfig; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.DataScopePlugin; +import net.lab1024.sa.base.handler.MybatisPlusFillHandler; +import org.apache.ibatis.plugin.Interceptor; +import org.apache.ibatis.session.SqlSessionFactory; +import org.springframework.aop.support.DefaultPointcutAdvisor; +import org.springframework.aop.support.JdkRegexpMethodPointcut; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.boot.web.servlet.ServletRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; + +import javax.sql.DataSource; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 数据源配置 + * + * @Date 2017-11-28 15:21:10 + * @Author wzh + */ +@Slf4j +@Configuration +public class DataSourceConfig { + + @Value("${spring.datasource.driver-class-name}") + String driver; + + @Value("${spring.datasource.url}") + String url; + + @Value("${spring.datasource.username}") + String username; + + @Value("${spring.datasource.password}") + String password; + + @Value("${spring.datasource.initial-size}") + int initialSize; + + @Value("${spring.datasource.min-idle}") + int minIdle; + + @Value("${spring.datasource.max-active}") + int maxActive; + + @Value("${spring.datasource.max-wait}") + long maxWait; + + @Value("${spring.datasource.time-between-eviction-runs-millis}") + long timeBetweenEvictionRunsMillis; + + @Value("${spring.datasource.min-evictable-idle-time-millis}") + long minEvictableIdleTimeMillis; + + @Value("${spring.datasource.filters}") + String filters; + + @Value("${spring.datasource.druid.username}") + String druidUserName; + + @Value("${spring.datasource.druid.password}") + String druidPassword; + + @Value("${spring.datasource.druid.login.enabled}") + boolean druidLoginEnable; + + @Value("${spring.datasource.druid.method.pointcut}") + String methodPointcut; + + @jakarta.annotation.Resource + private MybatisPlusInterceptor paginationInterceptor; + + @jakarta.annotation.Resource + private DataScopePlugin dataScopePlugin; + + @Bean + @Primary + public DataSource druidDataSource() { + DruidDataSource druidDataSource = new DruidDataSource(); + // 根据驱动类名自动设置数据库类型,兼容 MySQL、人大金仓等数据库 + if (driver.contains("kingbase")) { + druidDataSource.setDbType(DbType.KINGBASE_ES.getDb()); + } else if (driver.contains("mysql")) { + druidDataSource.setDbType(DbType.MYSQL.getDb()); + } else { + druidDataSource.setDbType(DbType.MYSQL.getDb()); + } + druidDataSource.setDriverClassName(driver); + druidDataSource.setUrl(url); + druidDataSource.setUsername(username); + druidDataSource.setPassword(password); + druidDataSource.setInitialSize(initialSize); + druidDataSource.setMinIdle(minIdle); + druidDataSource.setMaxActive(maxActive); + druidDataSource.setMaxWait(maxWait); + druidDataSource.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis); + druidDataSource.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis); + druidDataSource.setValidationQuery("SELECT 1"); + try { + druidDataSource.setFilters(filters); + ArrayList arrayList = new ArrayList<>(); + StatFilter statFilter = new StatFilter(); + statFilter.setMergeSql(true); + statFilter.setSlowSqlMillis(1000); + statFilter.setLogSlowSql(true); + arrayList.add(statFilter); + druidDataSource.setProxyFilters(arrayList); + druidDataSource.init(); + } catch (SQLException e) { + log.error("初始化数据源出错", e); + } + + return druidDataSource; + } + + @Bean + public SqlSessionFactory sqlSessionFactory() throws Exception { + MybatisSqlSessionFactoryBean factoryBean = new MybatisSqlSessionFactoryBean(); + factoryBean.setDataSource(druidDataSource()); + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + Resource[] resources = resolver.getResources("classpath*:/mapper/**/*.xml"); + factoryBean.setMapperLocations(resources); + + // 设置 MyBatis-Plus 分页插件 注意此处myBatisPlugin一定要放在后面 + List pluginsList = new ArrayList<>(); + pluginsList.add(paginationInterceptor); + if (dataScopePlugin != null) { + pluginsList.add(dataScopePlugin); + } + factoryBean.setPlugins(pluginsList.toArray(new Interceptor[0])); + // 添加字段自动填充处理 + factoryBean.setGlobalConfig(new GlobalConfig().setBanner(false).setMetaObjectHandler(new MybatisPlusFillHandler())); + + return factoryBean.getObject(); + } + + /** + * 非正式环境 才加载 + * + * @return + */ + @Conditional(SystemEnvironmentConfig.class) + @Bean + public ServletRegistrationBean druidServlet() { + ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean<>(); + servletRegistrationBean.setServlet(new StatViewServlet()); + servletRegistrationBean.addUrlMappings("/druid/*"); + Map initParameters = new HashMap(); + //不设置用户名密码可以直接通过druid/index.html访问 + if (druidLoginEnable) { + initParameters.put("loginUsername", druidUserName); + initParameters.put("loginPassword", druidPassword); + } + initParameters.put("resetEnable", "false"); + servletRegistrationBean.setInitParameters(initParameters); + return servletRegistrationBean; + } + + @Bean + public FilterRegistrationBean filterRegistrationBean() { + FilterRegistrationBean filterRegistrationBean = new FilterRegistrationBean(); + filterRegistrationBean.setFilter(new WebStatFilter()); + filterRegistrationBean.addUrlPatterns("/*"); + filterRegistrationBean.addInitParameter("exclusions", "*.js,*.gif,*.jpg,*.png,*.css,*.ico,/*"); + return filterRegistrationBean; + } + + @Bean + public JdkRegexpMethodPointcut jdkRegexpMethodPointcut() { + JdkRegexpMethodPointcut jdkRegexpMethodPointcut = new JdkRegexpMethodPointcut(); + jdkRegexpMethodPointcut.setPatterns(methodPointcut); + return jdkRegexpMethodPointcut; + } + + @Bean + public DefaultPointcutAdvisor defaultPointcutAdvisor() { + DefaultPointcutAdvisor pointcutAdvisor = new DefaultPointcutAdvisor(); + pointcutAdvisor.setPointcut(jdkRegexpMethodPointcut()); + pointcutAdvisor.setAdvice(new DruidStatInterceptor()); + return pointcutAdvisor; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java new file mode 100644 index 0000000..f52aa90 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/FileConfig.java @@ -0,0 +1,101 @@ +package net.lab1024.sa.base.config; + +import com.amazonaws.ClientConfiguration; +import com.amazonaws.Protocol; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.auth.BasicAWSCredentials; +import com.amazonaws.client.builder.AwsClientBuilder; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import lombok.Data; +import net.lab1024.sa.base.module.support.file.service.FileStorageCloudServiceImpl; +import net.lab1024.sa.base.module.support.file.service.FileStorageLocalServiceImpl; +import net.lab1024.sa.base.module.support.file.service.IFileStorageService; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +/** + * 文件上传 配置 + * + * @Date 2019-09-02 23:21:10 + * @Author wzh + */ +@Data +@Configuration +public class FileConfig implements WebMvcConfigurer { + + private static final String MODE_CLOUD = "cloud"; + + private static final String MODE_LOCAL = "local"; + + @Value("${file.storage.cloud.region}") + private String region; + + @Value("${file.storage.cloud.endpoint}") + private String endpoint; + + @Value("${file.storage.cloud.bucket-name}") + private String bucketName; + + @Value("${file.storage.cloud.access-key}") + private String accessKey; + + @Value("${file.storage.cloud.secret-key}") + private String secretKey; + + @Value("${file.storage.cloud.private-url-expire-seconds}") + private Long privateUrlExpireSeconds; + + @Value("${file.storage.cloud.url-prefix}") + private String urlPrefix; + + @Value("${file.storage.local.upload-path}") + private String uploadPath; + + @Value("${file.storage.mode}") + private String mode; + + /** + * 初始化 云oss client 配置 + * + * @return + */ + @Bean + @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) + public AmazonS3 initAmazonS3() { + ClientConfiguration clientConfig = new ClientConfiguration(); + clientConfig.setProtocol(Protocol.HTTPS); + return AmazonS3ClientBuilder.standard() + .withCredentials(new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey))) + .withClientConfiguration(clientConfig) + .withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(endpoint, region)) + .withPathStyleAccessEnabled(false) + .withChunkedEncodingDisabled(true) + .build(); + } + + @Bean + @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_CLOUD) + public IFileStorageService initCloudFileService() { + return new FileStorageCloudServiceImpl(); + } + + @Bean + @ConditionalOnProperty(prefix = "file.storage", name = {"mode"}, havingValue = MODE_LOCAL) + public IFileStorageService initLocalFileService() { + return new FileStorageLocalServiceImpl(); + } + + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + if (MODE_LOCAL.equals(mode)) { + String path = uploadPath.endsWith("/") ? uploadPath : uploadPath + "/"; + registry.addResourceHandler(FileStorageLocalServiceImpl.UPLOAD_MAPPING + "/**").addResourceLocations("file:" + path); + } + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/HeartBeatConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/HeartBeatConfig.java new file mode 100644 index 0000000..1b500a9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/HeartBeatConfig.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.config; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.module.support.heartbeat.core.HeartBeatManager; +import net.lab1024.sa.base.module.support.heartbeat.core.IHeartBeatRecordHandler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 心跳配置 + * + * @Date 2018/10/9 18:47 + * @Author wzh + */ +@Configuration +public class HeartBeatConfig { + + /** + * 间隔时间 + */ + @Value("${heart-beat.interval-seconds}") + private Long intervalSeconds; + + @Resource + private IHeartBeatRecordHandler heartBeatRecordHandler; + + @Bean + public HeartBeatManager heartBeatManager() { + return new HeartBeatManager(intervalSeconds * 1000L, heartBeatRecordHandler); + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java new file mode 100644 index 0000000..99ca242 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/JsonConfig.java @@ -0,0 +1,87 @@ +package net.lab1024.sa.base.config; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import net.lab1024.sa.base.common.json.serializer.LongJsonSerializer; +import org.apache.commons.lang3.StringUtils; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.converter.Converter; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeParseException; + +/** + * json 序列化配置 + * + * @Date 2017-11-28 15:21:10 + * @Author wzh + */ +@Configuration +public class JsonConfig { + + @Bean + public Jackson2ObjectMapperBuilderCustomizer customizer() { + return builder -> { + builder.deserializers(new LocalDateDeserializer(DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter())); + builder.deserializers(new LocalDateTimeDeserializer(DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter())); + builder.serializers(new LocalDateSerializer(DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter())); + builder.serializers(new LocalDateTimeSerializer(DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter())); + builder.serializerByType(Long.class, LongJsonSerializer.INSTANCE); + }; + } + + + /** + * string 转为 LocalDateTime 配置类 + * + * @author 卓大 + */ + @Configuration + public static class StringToLocalDateTime implements Converter { + + @Override + public LocalDateTime convert(String str) { + if (StringUtils.isBlank(str)) { + return null; + } + LocalDateTime localDateTime; + try { + localDateTime = LocalDateTimeUtil.parse(str, DatePattern.NORM_DATETIME_FORMAT.getDateTimeFormatter()); + } catch (DateTimeParseException e) { + throw new RuntimeException("请输入正确的日期格式:yyyy-MM-dd HH:mm:ss"); + } + return localDateTime; + } + } + + + /** + * string 转为 LocalDate 配置类 + * + * @author 卓大 + */ + @Configuration + public static class StringToLocalDate implements Converter { + + @Override + public LocalDate convert(String str) { + if (StringUtils.isBlank(str)) { + return null; + } + LocalDate localDate; + try { + localDate = LocalDateTimeUtil.parseDate(str, DatePattern.NORM_DATE_FORMAT.getDateTimeFormatter()); + } catch (DateTimeParseException e) { + throw new RuntimeException("请输入正确的日期格式:yyyy-MM-dd"); + } + return localDate; + } + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/MybatisDatabaseIdProviderConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/MybatisDatabaseIdProviderConfig.java new file mode 100644 index 0000000..f80aa14 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/MybatisDatabaseIdProviderConfig.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.config; + +import org.apache.ibatis.mapping.DatabaseIdProvider; +import org.apache.ibatis.mapping.VendorDatabaseIdProvider; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Properties; + +/** + * MyBatis 数据库方言识别(用于 mapper.xml 的 databaseId) + * + * 适配:MySQL / KingbaseES(V9) / PostgreSQL + */ +@Configuration +public class MybatisDatabaseIdProviderConfig { + + @Bean + public DatabaseIdProvider databaseIdProvider() { + VendorDatabaseIdProvider provider = new VendorDatabaseIdProvider(); + Properties p = new Properties(); + // MySQL + p.setProperty("MySQL", "mysql"); + p.setProperty("MySQL 8", "mysql"); + // KingbaseES(人大金仓) + p.setProperty("KingbaseES", "kingbase"); + p.setProperty("Kingbase", "kingbase"); + // PostgreSQL + p.setProperty("PostgreSQL", "postgres"); + provider.setProperties(p); + return provider; + } +} + diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/MybatisPlusConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/MybatisPlusConfig.java new file mode 100644 index 0000000..a8e72ca --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/MybatisPlusConfig.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.base.config; + +import com.baomidou.mybatisplus.annotation.DbType; +import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; +import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * mp 插件 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ +@EnableTransactionManagement +@Configuration +public class MybatisPlusConfig { + + /** + * 分页插件 + */ + @Bean + public MybatisPlusInterceptor paginationInterceptor() { + MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); + // 兼容国产化环境(人大金仓 KingbaseES 属于 PostgreSQL 体系) + // 不指定 DbType,让 MP 根据 JDBC 元信息自动识别数据库类型(MySQL/KingbaseES/PG 等) + interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); + return interceptor; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RedisConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RedisConfig.java new file mode 100644 index 0000000..68b3e83 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RedisConfig.java @@ -0,0 +1,82 @@ +package net.lab1024.sa.base.config; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.jsontype.impl.LaissezFaireSubTypeValidator; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import jakarta.annotation.Resource; +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.*; +import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +/** + * redis配置 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ +@Configuration +public class RedisConfig { + + @Resource + private RedisConnectionFactory factory; + + @Bean + public RedisTemplate redisTemplate() { + Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class); + ObjectMapper om = new ObjectMapper(); + om.registerModule(new JavaTimeModule()) + .configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, false) + .configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false) + .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false) + .configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, false) + .setSerializationInclusion(JsonInclude.Include.NON_NULL); + + om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY); + // enableDefaultTyping 官方已弃用 所以改为 activateDefaultTyping + om.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL); + jackson2JsonRedisSerializer.setObjectMapper(om); + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(factory); + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(jackson2JsonRedisSerializer); + template.setHashKeySerializer(jackson2JsonRedisSerializer); + template.setHashValueSerializer(jackson2JsonRedisSerializer); + template.setDefaultSerializer(new StringRedisSerializer()); + template.afterPropertiesSet(); + return template; + } + + @Bean + public HashOperations hashOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForHash(); + } + + @Bean + public ValueOperations valueOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForValue(); + } + + @Bean + public ListOperations listOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForList(); + } + + @Bean + public SetOperations setOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForSet(); + } + + @Bean + public ZSetOperations zSetOperations(RedisTemplate redisTemplate) { + return redisTemplate.opsForZSet(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RepeatSubmitConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RepeatSubmitConfig.java new file mode 100644 index 0000000..4148dcb --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RepeatSubmitConfig.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.config; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.module.support.repeatsubmit.RepeatSubmitAspect; +import net.lab1024.sa.base.module.support.repeatsubmit.ticket.RepeatSubmitRedisTicket; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.ValueOperations; + +/** + * 重复提交配置 + * + * @Date 2021/10/9 18:47 + * @Author wzh + */ +@Configuration +public class RepeatSubmitConfig { + + @Resource + private ValueOperations valueOperations; + + @Bean + public RepeatSubmitAspect repeatSubmitAspect() { + RepeatSubmitRedisTicket caffeineTicket = new RepeatSubmitRedisTicket(valueOperations, this::ticket); + return new RepeatSubmitAspect(caffeineTicket); + } + + /** + * 获取指明某个用户的凭证 + */ + private String ticket(String servletPath) { + Long userId = SmartRequestUtil.getRequestUserId(); + if (null == userId) { + return StringConst.EMPTY; + } + return servletPath + "_" + userId; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RestTemplateConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RestTemplateConfig.java new file mode 100644 index 0000000..e007ac3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/RestTemplateConfig.java @@ -0,0 +1,127 @@ +package net.lab1024.sa.base.config; + +import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; +import okhttp3.ConnectionPool; +import okhttp3.OkHttpClient; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.MediaType; +import org.springframework.http.client.OkHttp3ClientHttpRequestFactory; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.StringHttpMessageConverter; +import org.springframework.web.client.RestTemplate; + +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; +import java.nio.charset.StandardCharsets; +import java.security.KeyManagementException; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * http请求配置 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +@Configuration +public class RestTemplateConfig { + + @Value("${http.pool.max-total}") + private Integer maxTotal; + + @Value("${http.pool.connect-timeout}") + private Integer connectTimeout; + + @Value("${http.pool.read-timeout}") + private Integer readTimeout; + + @Value("${http.pool.write-timeout}") + private Integer writeTimeout; + + @Value("${http.pool.keep-alive}") + private Integer keepAlive; + + @Bean + public RestTemplate restTemplate() { + RestTemplate restTemplate = new RestTemplate(); + restTemplate.setRequestFactory(this.clientHttpRequestFactory()); + List> messageConverterList = restTemplate.getMessageConverters(); + messageConverterList.add(0, new StringHttpMessageConverter(StandardCharsets.UTF_8)); + messageConverterList.addAll(this.converters()); + return restTemplate; + } + + public List> converters() { + List> converters = new ArrayList<>(); + HttpMessageConverter converter = new StringHttpMessageConverter(StandardCharsets.UTF_8); + FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); + List fastMediaTypes = new ArrayList<>(); + fastMediaTypes.add(MediaType.APPLICATION_FORM_URLENCODED); + fastMediaTypes.add(MediaType.APPLICATION_JSON); + fastConverter.setSupportedMediaTypes(fastMediaTypes); + converters.add(converter); + converters.add(fastConverter); + return converters; + } + + + public OkHttp3ClientHttpRequestFactory clientHttpRequestFactory() { + return new OkHttp3ClientHttpRequestFactory(httpClientBuilder()); + } + + public OkHttpClient httpClientBuilder() { + return new OkHttpClient.Builder() + .retryOnConnectionFailure(true) + .connectionPool(this.pool()) + .connectTimeout(connectTimeout, TimeUnit.MILLISECONDS) + .readTimeout(readTimeout, TimeUnit.MILLISECONDS) + .writeTimeout(writeTimeout, TimeUnit.MILLISECONDS) + .build(); + } + + public ConnectionPool pool() { + return new ConnectionPool(maxTotal, keepAlive, TimeUnit.MILLISECONDS); + } + + + @Bean + public X509TrustManager x509TrustManager() { + return new X509TrustManager() { + @Override + public void checkClientTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + } + + @Override + public void checkServerTrusted(X509Certificate[] x509Certificates, String s) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + }; + } + + @Bean + public SSLSocketFactory sslSocketFactory() { + try { + //信任任何链接 + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, new TrustManager[]{x509TrustManager()}, new SecureRandom()); + return sslContext.getSocketFactory(); + } catch (NoSuchAlgorithmException | KeyManagementException e) { + e.printStackTrace(); + } + return null; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/ScheduleConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/ScheduleConfig.java new file mode 100644 index 0000000..128cc2f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/ScheduleConfig.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.base.config; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Configuration; +import org.springframework.scheduling.annotation.SchedulingConfigurer; +import org.springframework.scheduling.config.ScheduledTaskRegistrar; +import org.springframework.scheduling.config.Task; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 定时任务调度 配置 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +@Slf4j +@Configuration +public class ScheduleConfig implements SchedulingConfigurer { + + private ScheduledTaskRegistrar taskRegistrar; + + @Override + public void configureTasks(ScheduledTaskRegistrar taskRegistrar) { + this.taskRegistrar = taskRegistrar; + } + + public String destroy() { + List taskList = new ArrayList<>(); + taskList.addAll(taskRegistrar.getCronTaskList()); + taskList.addAll(taskRegistrar.getTriggerTaskList()); + taskList.addAll(taskRegistrar.getFixedDelayTaskList()); + taskList.addAll(taskRegistrar.getFixedRateTaskList()); + + taskRegistrar.destroy(); + + List taskNameList = taskList.stream().map(Task::toString).collect(Collectors.toList()); + return "已关闭 @Scheduled定时任务:" + taskNameList.size() + "个!"; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/SwaggerConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/SwaggerConfig.java new file mode 100644 index 0000000..6163c20 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/SwaggerConfig.java @@ -0,0 +1,129 @@ +package net.lab1024.sa.base.config; + +import com.google.common.collect.Lists; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Contact; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.constant.RequestHeaderConst; +import net.lab1024.sa.base.common.swagger.SmartOperationCustomizer; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import org.apache.commons.lang3.StringUtils; +import org.springdoc.core.customizers.OpenApiBuilderCustomizer; +import org.springdoc.core.customizers.ServerBaseUrlCustomizer; +import org.springdoc.core.models.GroupedOpenApi; +import org.springdoc.core.properties.SpringDocConfigProperties; +import org.springdoc.core.providers.JavadocProvider; +import org.springdoc.core.service.OpenAPIService; +import org.springdoc.core.service.SecurityService; +import org.springdoc.core.utils.PropertyResolverUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Conditional; +import org.springframework.context.annotation.Configuration; + +import java.util.List; +import java.util.Optional; + +/** + * springdoc-openapi 配置 + * nginx配置前缀时如果需要访问【/swagger-ui/index.html】需添加额外nginx配置 + * location /v3/api-docs/ { + * proxy_pass http://127.0.0.1:1024/v3/api-docs/; + * } + * @Date 2020-03-25 22:54:46 + * @Author wzh + */ +@Slf4j +@Configuration +@Conditional(SystemEnvironmentConfig.class) +public class SwaggerConfig { + /** + * 用于解决/swagger-ui/index.html页面ServersUrl 测试环境部署错误问题 + */ + @Value("${springdoc.swagger-ui.server-base-url}") + private String serverBaseUrl; + + public static final String[] SWAGGER_WHITELIST = { + "/swagger-ui/**", + "/swagger-ui/index.html", + "/swagger-ui.html", + "/swagger-ui.html/**", + "/v3/api-docs", + "/v3/api-docs/**", + "/doc.html", + }; + + @Bean + public OpenAPI api() { + return new OpenAPI() + .components(components()) + .info(new Info() + .title("SmartFlow 3.X 接口文档") + .contact(new Contact().name("lovefawn")) + .version("v3.X") + ) + .addSecurityItem(new SecurityRequirement().addList(RequestHeaderConst.TOKEN)); + } + + private Components components() { + return new Components() + .addSecuritySchemes(RequestHeaderConst.TOKEN, new SecurityScheme().scheme("Bearer").description("请输入token,格式为[Bearer xxxxxxxx]").type(SecurityScheme.Type.APIKEY).in(SecurityScheme.In.HEADER).name(RequestHeaderConst.TOKEN)); + } + + @Bean + public GroupedOpenApi businessApi() { + return GroupedOpenApi.builder() + .group("业务接口") + .pathsToMatch("/**") + .pathsToExclude(SwaggerTagConst.Support.URL_PREFIX + "/**") + .addOperationCustomizer(new SmartOperationCustomizer()) + .build(); + + } + + @Bean + public GroupedOpenApi supportApi() { + return GroupedOpenApi.builder() + .group("支撑接口(Support)") + .pathsToMatch(SwaggerTagConst.Support.URL_PREFIX + "/**") + .addOperationCustomizer(new SmartOperationCustomizer()) + .build(); + } + + /** + * 以下代码可以用于设置 /swagger-ui/index.html 的serverBaseUrl + * 如果使用knife4j则不需要 + * @param openAPI + * @param securityParser + * @param springDocConfigProperties + * @param propertyResolverUtils + * @param openApiBuilderCustomizers + * @param serverBaseUrlCustomizers + * @param javadocProvider + * @return + */ + @Bean + public OpenAPIService openApiBuilder(Optional openAPI, + SecurityService securityParser, + SpringDocConfigProperties springDocConfigProperties, + PropertyResolverUtils propertyResolverUtils, + Optional> openApiBuilderCustomizers, + Optional> serverBaseUrlCustomizers, + Optional javadocProvider) { + List list = Lists.newArrayList(new ServerBaseUrlCustomizer() { + @Override + public String customize(String baseUrl) { + if (StringUtils.isNotBlank(serverBaseUrl)) { + return serverBaseUrl; + } + return baseUrl; + } + }); + return new OpenAPIService(openAPI, securityParser, springDocConfigProperties, + propertyResolverUtils, openApiBuilderCustomizers, Optional.of(list), javadocProvider); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/SystemEnvironmentConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/SystemEnvironmentConfig.java new file mode 100644 index 0000000..7cb49b0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/SystemEnvironmentConfig.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.config; + +import net.lab1024.sa.base.common.domain.SystemEnvironment; +import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.type.AnnotatedTypeMetadata; + +/** + * 系统环境 + * + * @Date 2021/08/13 18:56 + * @Author wzh + */ +@Configuration +public class SystemEnvironmentConfig implements Condition { + + @Value("${spring.profiles.active}") + private String systemEnvironment; + + @Value("${project.name}") + private String projectName; + + /** + * 判断是否开启swagger + */ + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { + return isDevOrTest(conditionContext); + } + + /** + * 是否为:开发环境和 测试环境 + */ + private boolean isDevOrTest(ConditionContext conditionContext) { + String property = conditionContext.getEnvironment().getProperty("spring.profiles.active"); + return StringUtils.isNotBlank(property) && (SystemEnvironmentEnum.TEST.equalsValue(property) || SystemEnvironmentEnum.DEV.equalsValue(property)); + } + + @Bean("systemEnvironment") + public SystemEnvironment initEnvironment() { + SystemEnvironmentEnum currentEnvironment = SmartEnumUtil.getEnumByValue(systemEnvironment, SystemEnvironmentEnum.class); + if (currentEnvironment == null) { + throw new ExceptionInInitializerError("无法获取当前环境!请在 application.yaml 配置参数:spring.profiles.active"); + } + if (StringUtils.isBlank(projectName)) { + throw new ExceptionInInitializerError("无法获取当前项目名称!请在 application.yaml 配置参数:project.name"); + } + return new SystemEnvironment(currentEnvironment == SystemEnvironmentEnum.PROD, projectName, currentEnvironment); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/TokenConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/TokenConfig.java new file mode 100644 index 0000000..b8878e6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/TokenConfig.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.base.config; + +import cn.dev33.satoken.config.SaTokenConfig; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.module.support.securityprotect.service.Level3ProtectConfigService; +import org.springframework.context.annotation.Configuration; + +/** + * + * 三级等保配置初始化后最低活跃频率全局配置 + * + * @Date 2024/11/24 + * @Author wzh + */ + +@Configuration +public class TokenConfig { + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + // 此配置会覆盖 sa-base.yaml 中的配置 + @Resource + public void configSaToken(SaTokenConfig config) { + + config.setActiveTimeout(level3ProtectConfigService.getLoginActiveTimeoutSeconds()); + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/UrlConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/UrlConfig.java new file mode 100644 index 0000000..7c69e4b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/UrlConfig.java @@ -0,0 +1,139 @@ +package net.lab1024.sa.base.config; + +import cn.dev33.satoken.annotation.SaIgnore; +import cn.hutool.core.util.StrUtil; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import io.swagger.v3.oas.annotations.Operation; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.annoation.NoNeedLogin; +import net.lab1024.sa.base.common.domain.RequestUrlVO; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.condition.PathPatternsRequestCondition; +import org.springframework.web.servlet.mvc.method.RequestMappingInfo; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +import java.lang.reflect.Method; +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * url配置 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +@Configuration +@Slf4j +public class UrlConfig { + + @Resource + private RequestMappingHandlerMapping requestMappingHandlerMapping; + + /** + * 获取每个方法的请求路径 + */ + @Bean + public Map> methodUrlMap() { + Map> methodUrlMap = Maps.newHashMap(); + //获取url与类和方法的对应信息 + Map map = requestMappingHandlerMapping.getHandlerMethods(); + for (Map.Entry entry : map.entrySet()) { + RequestMappingInfo requestMappingInfo = entry.getKey(); + PathPatternsRequestCondition pathPatternsCondition = requestMappingInfo.getPathPatternsCondition(); + if(pathPatternsCondition == null){ + continue; + } + + Set urls = pathPatternsCondition.getPatternValues(); + if (CollectionUtils.isEmpty(urls)) { + continue; + } + HandlerMethod handlerMethod = entry.getValue(); + methodUrlMap.put(handlerMethod.getMethod(), urls); + } + return methodUrlMap; + } + + /** + * 需要进行url权限校验的方法 + * + * @param methodUrlMap + * @return + */ + @Bean + public List authUrl(Map> methodUrlMap) { + List authUrlList = Lists.newArrayList(); + for (Map.Entry> entry : methodUrlMap.entrySet()) { + Method method = entry.getKey(); + // 忽略权限 + SaIgnore ignore = method.getAnnotation(SaIgnore.class); + if (null != ignore) { + continue; + } + NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class); + if (null != noNeedLogin) { + continue; + } + Set urlSet = entry.getValue(); + List requestUrlList = this.buildRequestUrl(method, urlSet); + authUrlList.addAll(requestUrlList); + } + return authUrlList; + } + + private List buildRequestUrl(Method method, Set urlSet) { + List requestUrlList = Lists.newArrayList(); + if (CollectionUtils.isEmpty(urlSet)) { + return requestUrlList; + } + //url对应的方法名称 + String className = method.getDeclaringClass().getName(); + String methodName = method.getName(); + List list = StrUtil.split(className, "."); + String controllerName = list.get(list.size() - 1); + String name = controllerName + "." + methodName; + //swagger 说明信息 + String methodComment = null; + Operation apiOperation = method.getAnnotation(Operation.class); + if (apiOperation != null) { + methodComment = apiOperation.summary(); + } + for (String url : urlSet) { + RequestUrlVO requestUrlVO = new RequestUrlVO(); + requestUrlVO.setUrl(url); + requestUrlVO.setName(name); + requestUrlVO.setComment(methodComment); + requestUrlList.add(requestUrlVO); + } + return requestUrlList; + } + + + /** + * 获取无需登录可以匿名访问的url信息 + * + * @return + */ + @Bean + public List noNeedLoginUrlList(Map> methodUrlMap) { + List noNeedLoginUrlList = Lists.newArrayList(); + for (Map.Entry> entry : methodUrlMap.entrySet()) { + Method method = entry.getKey(); + NoNeedLogin noNeedLogin = method.getAnnotation(NoNeedLogin.class); + if (null == noNeedLogin) { + continue; + } + noNeedLoginUrlList.addAll(entry.getValue()); + } + log.info("不需要登录的URL:{}", noNeedLoginUrlList); + return noNeedLoginUrlList; + } + + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/YamlProcessor.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/YamlProcessor.java new file mode 100644 index 0000000..fcb44bd --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/config/YamlProcessor.java @@ -0,0 +1,62 @@ +package net.lab1024.sa.base.config; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.env.EnvironmentPostProcessor; +import org.springframework.boot.env.YamlPropertySourceLoader; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.env.MutablePropertySources; +import org.springframework.core.env.PropertySource; +import org.springframework.core.io.Resource; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; + +import java.io.IOException; +import java.util.List; + +/** + * yaml 读取配置 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +@Configuration +@Slf4j +@Order(value = 0) +public class YamlProcessor implements EnvironmentPostProcessor { + + private final YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); + + @Override + public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { + + String filePath = environment.getProperty("project.log-path"); + if (SmartStringUtil.isNotEmpty(filePath)) { + System.setProperty("project.log-path", filePath); + } + + MutablePropertySources propertySources = environment.getPropertySources(); + this.loadProperty(propertySources); + } + + private void loadProperty(MutablePropertySources propertySources) { + PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(); + try { + Resource[] resources = resolver.getResources("classpath*:sa-*.yaml"); + if (resources.length < 1) { + return; + } + for (Resource resource : resources) { + log.info("初始化系统配置:{}", resource.getFilename()); + List> load = loader.load(resource.getFilename(), resource); + load.forEach(propertySources::addLast); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/CacheKeyConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/CacheKeyConst.java new file mode 100644 index 0000000..41b54dc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/CacheKeyConst.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.constant; + +/** + * 缓存key常量 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +public class CacheKeyConst { + + public static class Dict { + + public static final String DICT_DATA = "dict_data_cache"; + + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/LoginDeviceEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/LoginDeviceEnum.java new file mode 100644 index 0000000..4674893 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/LoginDeviceEnum.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.constant; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 登录设备类型 + * + * @Date 2021-11-29 19:48:35 + * @Author wzh + */ +public enum LoginDeviceEnum implements BaseEnum { + + PC(1, "电脑端"), + + ANDROID(2, "安卓"), + + APPLE(3, "苹果"), + + H5(4, "H5"), + + WEIXIN_MP(5, "微信小程序"); + + LoginDeviceEnum(Integer value, String desc) { + this.value = value; + this.desc = desc; + } + + private Integer value; + private String desc; + + @Override + public Integer getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/RedisKeyConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/RedisKeyConst.java new file mode 100644 index 0000000..2ad0f26 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/RedisKeyConst.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.base.constant; + +/** + * redis key 常量类 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +public class RedisKeyConst { + + public static final String SEPARATOR = ":"; + + public static class Support { + + public static final String FILE_PRIVATE_VO = "file:private:"; + + public static final String SERIAL_NUMBER_LAST_INFO = "serial-number:last-info"; + + public static final String SERIAL_NUMBER = "serial-number:"; + + public static final String CAPTCHA = "captcha:"; + + public static final String LOGIN_VERIFICATION_CODE = "login:verification-code:"; + + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/ReloadConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/ReloadConst.java new file mode 100644 index 0000000..294d646 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/ReloadConst.java @@ -0,0 +1,15 @@ +package net.lab1024.sa.base.constant; + +/** + * reload 项目 + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +public class ReloadConst { + + public static final String CONFIG_RELOAD = "system_config"; + + public static final String CACHE_SERVICE = "cache_service"; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/SwaggerTagConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/SwaggerTagConst.java new file mode 100644 index 0000000..df8af99 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/constant/SwaggerTagConst.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.constant; + +/** + * swagger + * + * @Date 2022-05-30 21:22:12 + * @Author wzh + */ +public class SwaggerTagConst { + + public static class Support { + + public static final String URL_PREFIX = "/support"; + + public static final String CACHE = "业务支撑-缓存"; + + public static final String CAPTCHA = "业务支撑-验证码"; + + public static final String OPERATE_LOG = "业务支撑-用户操作记录"; + + public static final String LOGIN_LOG = "业务支撑-登录日志"; + + public static final String RELOAD = "业务支撑-reload"; + + public static final String SERIAL_NUMBER = "业务支撑-id生成器"; + + public static final String HEART_BEAT = "业务支撑-服务心跳"; + + public static final String FILE = "业务支撑-文件服务"; + + public static final String CONFIG = "业务支撑-系统参数"; + + public static final String DATA_TRACER = "业务支撑-数据变动记录"; + + public static final String DICT = "业务支撑-数据字典"; + + public static final String CODE_GENERATOR = "业务支撑-代码生成"; + + public static final String CHANGE_LOG = "业务支撑-更新日志"; + + public static final String HELP_DOC = "业务支撑-帮助文档"; + + public static final String FEEDBACK = "业务支撑-意见反馈"; + + public static final String TABLE_COLUMN = "业务支撑-列自定义"; + + public static final String PROTECT = "业务支撑-网络安全"; + + public static final String DATA_MASKING = "业务支撑-数据脱敏"; + + public static final String JOB = "业务支撑-定时任务"; + + public static final String MESSAGE = "业务支撑-消息"; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/handler/GlobalExceptionHandler.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/handler/GlobalExceptionHandler.java new file mode 100644 index 0000000..4a1b081 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/handler/GlobalExceptionHandler.java @@ -0,0 +1,127 @@ +package net.lab1024.sa.base.handler; + +import cn.dev33.satoken.exception.NotPermissionException; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.code.SystemErrorCode; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.SystemEnvironment; +import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum; +import net.lab1024.sa.base.common.exception.BusinessException; +import org.springframework.beans.TypeMismatchException; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.validation.BindException; +import org.springframework.validation.FieldError; +import org.springframework.web.bind.MethodArgumentNotValidException; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.context.request.RequestAttributes; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 全局异常拦截 + * + * @Date 2020/8/25 21:57 + * @Author wzh + */ +@Slf4j +@ControllerAdvice +public class GlobalExceptionHandler { + + @Resource + private SystemEnvironment systemEnvironment; + + /** + * json 格式错误 缺少请求体 + */ + @ResponseBody + @ExceptionHandler({HttpMessageNotReadableException.class}) + public ResponseDTO jsonFormatExceptionHandler(Exception e) { + if (!systemEnvironment.isProd()) { + log.error("全局JSON格式错误异常,URL:{}", getCurrentRequestUrl(), e); + } + return ResponseDTO.error(UserErrorCode.PARAM_ERROR, "参数JSON格式错误"); + } + + /** + * json 格式错误 缺少请求体 + */ + @ResponseBody + @ExceptionHandler({TypeMismatchException.class, BindException.class}) + public ResponseDTO paramExceptionHandler(Exception e) { + if (e instanceof BindException) { + if (e instanceof MethodArgumentNotValidException) { + List fieldErrors = ((MethodArgumentNotValidException) e).getBindingResult().getFieldErrors(); + List msgList = fieldErrors.stream().map(FieldError::getDefaultMessage).collect(Collectors.toList()); + return ResponseDTO.error(UserErrorCode.PARAM_ERROR, String.join(",", msgList)); + } + + List fieldErrors = ((BindException) e).getFieldErrors(); + List error = fieldErrors.stream().map(field -> field.getField() + ":" + field.getRejectedValue()).collect(Collectors.toList()); + String errorMsg = UserErrorCode.PARAM_ERROR.getMsg() + ":" + error; + return ResponseDTO.error(UserErrorCode.PARAM_ERROR, errorMsg); + } + return ResponseDTO.error(UserErrorCode.PARAM_ERROR); + } + + /** + * sa-token 权限异常处理 + * + * @param e 权限异常 + * @return 错误结果 + */ + @ResponseBody + @ExceptionHandler(NotPermissionException.class) + public ResponseDTO permissionException(NotPermissionException e) { + // 开发环境 方便调试 + if (SystemEnvironmentEnum.PROD != systemEnvironment.getCurrentEnvironment()) { + return ResponseDTO.error(UserErrorCode.NO_PERMISSION, e.getMessage()); + } + return ResponseDTO.error(UserErrorCode.NO_PERMISSION); + } + + + /** + * 业务异常 + */ + @ResponseBody + @ExceptionHandler(BusinessException.class) + public ResponseDTO businessExceptionHandler(BusinessException e) { + if (!systemEnvironment.isProd()) { + log.error("全局业务异常,URL:{}", getCurrentRequestUrl(), e); + } + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, e.getMessage()); + } + + /** + * 其他全部异常 + * + * @param e 全局异常 + * @return 错误结果 + */ + @ResponseBody + @ExceptionHandler(Throwable.class) + public ResponseDTO errorHandler(Throwable e) { + log.error("捕获全局异常,URL:{}", getCurrentRequestUrl(), e); + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, systemEnvironment.isProd() ? null : e.toString()); + } + + /** + * 获取当前请求url + */ + private String getCurrentRequestUrl() { + RequestAttributes request = RequestContextHolder.getRequestAttributes(); + if (null == request) { + return null; + } + ServletRequestAttributes servletRequest = (ServletRequestAttributes) request; + return servletRequest.getRequest().getRequestURI(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/handler/MybatisPlusFillHandler.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/handler/MybatisPlusFillHandler.java new file mode 100644 index 0000000..e991ba6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/handler/MybatisPlusFillHandler.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.base.handler; + +import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; +import lombok.extern.slf4j.Slf4j; +import org.apache.ibatis.reflection.MetaObject; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.Date; + +/** + * Mybatis Plus 插入或者更新时指定字段设置值 + * + * @author zhoumingfa + */ +@Component +@Slf4j +public class MybatisPlusFillHandler implements MetaObjectHandler { + public static final String CREATE_TIME = "createTime"; + public static final String UPDATE_TIME = "updateTime"; + + @Override + public void insertFill(MetaObject metaObject) { + fillTimeField(metaObject, CREATE_TIME); + fillTimeField(metaObject, UPDATE_TIME); + } + + @Override + public void updateFill(MetaObject metaObject) { + fillTimeField(metaObject, UPDATE_TIME); + } + + /** + * 动态处理时间字段类型(兼容 LocalDateTime 和 Date) + */ + private void fillTimeField(MetaObject metaObject, String fieldName) { + if (metaObject.hasSetter(fieldName)) { + Class fieldType = metaObject.getGetterType(fieldName); + Object value = null; + + if (fieldType == LocalDateTime.class) { + value = LocalDateTime.now(); + } else if (fieldType == Date.class) { + // 将 LocalDateTime 转换为 Date + value = Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()); + } + + if (value != null) { + this.fillStrategy(metaObject, fieldName, value); + } + } + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/Ip2RegionListener.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/Ip2RegionListener.java new file mode 100644 index 0000000..a961520 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/Ip2RegionListener.java @@ -0,0 +1,77 @@ +package net.lab1024.sa.base.listener; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.util.SmartIpUtil; +import org.apache.commons.io.FileUtils; +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.boot.context.logging.LoggingApplicationListener; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.ConfigurableEnvironment; +import org.springframework.core.io.ClassPathResource; + +import java.io.File; +import java.io.IOException; + +/** + * 初初始化ip工具类 + * + * @Date 2023-09-03 23:45:26 + * @Author wzh + */ +@Order(value = LoggingApplicationListener.DEFAULT_ORDER) +@Slf4j +public class Ip2RegionListener implements ApplicationListener { + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) { + + } + +// private static final String IP_FILE_NAME = "ip2region.xdb"; +// +// private static final String LOG_DIRECTORY = "project.log-directory"; +// +// @Override +// public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) { +// +// ConfigurableEnvironment environment = applicationEvent.getEnvironment(); +// String logDirectoryPath = environment.getProperty(LOG_DIRECTORY); +// if (logDirectoryPath == null) { +// throw new ExceptionInInitializerError("环境变量为空:" + LOG_DIRECTORY); +// } +// System.setProperty(LOG_DIRECTORY, logDirectoryPath); +// +// // 1、从jar中的ip2region.xdb文件复制到服务器目录中 +// File logDirectoryFile = new File(logDirectoryPath); +// if (!logDirectoryFile.exists()) { +// logDirectoryFile.mkdirs(); +// } +// +// String tempFilePath = null; +// if (logDirectoryPath.endsWith("/")) { +// tempFilePath = logDirectoryPath + IP_FILE_NAME; +// } else { +// tempFilePath = logDirectoryPath + "/" + IP_FILE_NAME; +// } +// +// File tempFile = new File(tempFilePath); +// try { +// FileUtils.copyInputStreamToFile(new ClassPathResource(IP_FILE_NAME).getInputStream(), tempFile); +// +// // 2、初始化 +// SmartIpUtil.init(tempFilePath); +// +// +// } catch (IOException e) { +// log.error("无法复制ip数据文件 ip2region.xdb", e); +// throw new ExceptionInInitializerError("无法复制ip数据文件"); +// } finally { +// if (tempFile.exists()) { +// tempFile.delete(); +// } +// } +// +// } + + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/LogVariableListener.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/LogVariableListener.java new file mode 100644 index 0000000..ea869b1 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/LogVariableListener.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.base.listener; + +import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; +import org.springframework.boot.context.logging.LoggingApplicationListener; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.ConfigurableEnvironment; + +/** + * 将application.yam l中的日志路径变量:project.log-path注入到 log4j2.xml + * + * @Date 2023-09-03 23:45:26 + * @Author wzh + */ +@Order(value = LoggingApplicationListener.DEFAULT_ORDER - 1) +public class LogVariableListener implements ApplicationListener { + + private static final String LOG_DIRECTORY = "project.log-directory"; + + @Override + public void onApplicationEvent(ApplicationEnvironmentPreparedEvent applicationEvent) { + + ConfigurableEnvironment environment = applicationEvent.getEnvironment(); + String filePath = environment.getProperty(LOG_DIRECTORY); + if (filePath != null) { + System.setProperty(LOG_DIRECTORY, filePath); + } + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/WebServerListener.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/WebServerListener.java new file mode 100644 index 0000000..3438aa2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/listener/WebServerListener.java @@ -0,0 +1,92 @@ +package net.lab1024.sa.base.listener; + +import cn.hutool.core.net.NetUtil; +import cn.hutool.core.util.URLUtil; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.code.ErrorCodeRegister; +import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.context.WebServerApplicationContext; +import org.springframework.boot.web.context.WebServerInitializedEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.core.annotation.Order; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +/** + * 启动监听器 + * + * @Date 2021-12-23 23:45:26 + * @Author wzh + */ +@Slf4j +@Component +@Order(value = 1024) +public class WebServerListener implements ApplicationListener { + + @Value("${reload.interval-seconds}") + private Integer intervalSeconds; + + @Override + public void onApplicationEvent(WebServerInitializedEvent webServerInitializedEvent) { + WebServerApplicationContext context = webServerInitializedEvent.getApplicationContext(); + // 初始化reload + initReload(context); + // 项目信息 + showProjectMessage(webServerInitializedEvent); + } + + /** + * 显示项目信息 + */ + private void showProjectMessage(WebServerInitializedEvent webServerInitializedEvent) { + WebServerApplicationContext context = webServerInitializedEvent.getApplicationContext(); + Environment env = context.getEnvironment(); + + //获取服务信息 + String ip = NetUtil.getLocalhost().getHostAddress(); + Integer port = webServerInitializedEvent.getWebServer().getPort(); + String contextPath = env.getProperty("server.servlet.context-path"); + if (contextPath == null) { + contextPath = ""; + } + String profile = env.getProperty("spring.profiles.active"); + SystemEnvironmentEnum environmentEnum = SmartEnumUtil.getEnumByValue(profile, SystemEnvironmentEnum.class); + String projectName = env.getProperty("project.name"); + //拼接服务地址 + String title = String.format("-------------【%s】 服务已成功启动 (%s started successfully)-------------", projectName, projectName); + + // 初始化状态码 + int codeCount = ErrorCodeRegister.initialize(); + String localhostUrl = URLUtil.normalize(String.format("http://localhost:%d%s", port, contextPath), false, true); + String externalUrl = URLUtil.normalize(String.format("http://%s:%d%s", ip, port, contextPath), false, true); + String swaggerUrl = URLUtil.normalize(String.format("http://localhost:%d%s/swagger-ui/index.html", port, contextPath), false, true); + String knife4jUrl = URLUtil.normalize(String.format("http://localhost:%d%s/doc.html", port, contextPath), false, true); + log.warn("\n{}\n" + + "\t当前启动环境:\t{} , {}" + + "\n\t返回码初始化:\t完成{}个返回码初始化" + + "\n\t服务本机地址:\t{}" + + "\n\t服务外网地址:\t{}" + + "\n\tSwagger地址:\t{}" + + "\n\tknife4j地址:\t{}" + + "\n-------------------------------------------------------------------------------------\n", + title, profile, environmentEnum.getDesc(), codeCount, localhostUrl, externalUrl, swaggerUrl, knife4jUrl); + } + + /** + * 初始化reload + */ + private void initReload(WebServerApplicationContext applicationContext) { +// 将applicationContext转换为ConfigurableApplicationContext +// ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) applicationContext; +// +// +// //获取BeanFactory +// DefaultListableBeanFactory defaultListableBeanFactory = (DefaultListableBeanFactory) configurableApplicationContext.getAutowireCapableBeanFactory(); +// +// //动态注册bean +// SmartReloadManager reloadManager = new SmartReloadManager(applicationContext.getBean(ReloadCommand.class), intervalSeconds); +// defaultListableBeanFactory.registerSingleton("smartReloadManager", reloadManager); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/advice/DecryptRequestAdvice.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/advice/DecryptRequestAdvice.java new file mode 100644 index 0000000..5ee528e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/advice/DecryptRequestAdvice.java @@ -0,0 +1,92 @@ +package net.lab1024.sa.base.module.support.apiencrypt.advice; + +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiDecrypt; +import net.lab1024.sa.base.module.support.apiencrypt.domain.ApiEncryptForm; +import net.lab1024.sa.base.module.support.apiencrypt.service.ApiEncryptService; +import org.apache.commons.io.IOUtils; +import org.springframework.core.MethodParameter; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.RequestBodyAdviceAdapter; + +import java.io.InputStream; +import java.lang.reflect.Type; + +/** + * 解密 + * + * @Date 2023/10/21 11:41:46 + * @Author wzh + */ + +@Slf4j +@ControllerAdvice +public class DecryptRequestAdvice extends RequestBodyAdviceAdapter { + + private static final String ENCODING = "UTF-8"; + + @Resource + private ApiEncryptService apiEncryptService; + + @Resource + private ObjectMapper objectMapper; + + @Override + public boolean supports(MethodParameter methodParameter, Type targetType, Class> converterType) { + return methodParameter.hasMethodAnnotation(ApiDecrypt.class) || methodParameter.hasParameterAnnotation(ApiDecrypt.class) || methodParameter.getContainingClass().isAnnotationPresent(ApiDecrypt.class); + } + + @Override + public HttpInputMessage beforeBodyRead(HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { + try { + String bodyStr = IOUtils.toString(inputMessage.getBody(), ENCODING); + ApiEncryptForm apiEncryptForm = objectMapper.readValue(bodyStr, ApiEncryptForm.class); + if (SmartStringUtil.isEmpty(apiEncryptForm.getEncryptData())) { + return inputMessage; + } + String decrypt = apiEncryptService.decrypt(apiEncryptForm.getEncryptData()); + return new DecryptHttpInputMessage(inputMessage.getHeaders(), IOUtils.toInputStream(decrypt, ENCODING)); + } catch (Exception e) { + log.error("", e); + return inputMessage; + } + } + + @Override + public Object afterBodyRead(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { + return body; + } + + @Override + public Object handleEmptyBody(Object body, HttpInputMessage inputMessage, MethodParameter parameter, Type targetType, Class> converterType) { + return body; + } + + static class DecryptHttpInputMessage implements HttpInputMessage { + private final HttpHeaders headers; + + private final InputStream body; + + public DecryptHttpInputMessage(HttpHeaders headers, InputStream body) { + this.headers = headers; + this.body = body; + } + + @Override + public InputStream getBody() { + return body; + } + + @Override + public HttpHeaders getHeaders() { + return headers; + } + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/advice/EncryptResponseAdvice.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/advice/EncryptResponseAdvice.java new file mode 100644 index 0000000..f4f6c03 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/advice/EncryptResponseAdvice.java @@ -0,0 +1,60 @@ +package net.lab1024.sa.base.module.support.apiencrypt.advice; + +import com.alibaba.fastjson.JSON; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.enumeration.DataTypeEnum; +import net.lab1024.sa.base.module.support.apiencrypt.annotation.ApiEncrypt; +import net.lab1024.sa.base.module.support.apiencrypt.service.ApiEncryptService; +import org.springframework.core.MethodParameter; +import org.springframework.http.MediaType; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.server.ServerHttpRequest; +import org.springframework.http.server.ServerHttpResponse; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; + +/** + * 加密 + * + * @Date 2023/10/24 09:52:58 + * @Author wzh + */ + + +@Slf4j +@ControllerAdvice +public class EncryptResponseAdvice implements ResponseBodyAdvice> { + + @Resource + private ApiEncryptService apiEncryptService; + + @Resource + private ObjectMapper objectMapper; + + @Override + public boolean supports(MethodParameter returnType, Class> converterType) { + return returnType.hasMethodAnnotation(ApiEncrypt.class) || returnType.getContainingClass().isAnnotationPresent(ApiEncrypt.class); + } + + @Override + public ResponseDTO beforeBodyWrite(ResponseDTO body, MethodParameter returnType, MediaType selectedContentType, Class> selectedConverterType, ServerHttpRequest request, ServerHttpResponse response) { + if (body == null || body.getData() == null) { + return body; + } + + try { + String encrypt = apiEncryptService.encrypt(objectMapper.writeValueAsString(body.getData())); + body.setData(encrypt); + body.setDataType(DataTypeEnum.ENCRYPT.getValue()); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + return body; + } +} + + diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/annotation/ApiDecrypt.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/annotation/ApiDecrypt.java new file mode 100644 index 0000000..2e6ead8 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/annotation/ApiDecrypt.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.module.support.apiencrypt.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 解密注解 + * + * @Date 2023/10/21 11:41:46 + * @Author wzh + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface ApiDecrypt { +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/annotation/ApiEncrypt.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/annotation/ApiEncrypt.java new file mode 100644 index 0000000..f34770b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/annotation/ApiEncrypt.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.module.support.apiencrypt.annotation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 加密注解 + * + * @Date 2023/10/21 11:41:46 + * @Author wzh + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +public @interface ApiEncrypt { +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/domain/ApiEncryptForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/domain/ApiEncryptForm.java new file mode 100644 index 0000000..7bb7be3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/domain/ApiEncryptForm.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.module.support.apiencrypt.domain; + +import lombok.Data; + +/** + * 加密数据的表单 + * + * @Date 2023/10/21 11:41:46 + * @Author wzh + */ + + +@Data +public class ApiEncryptForm { + + private String encryptData; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptService.java new file mode 100644 index 0000000..198690e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptService.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.apiencrypt.service; + +/** + * 接口加密、解密 Service + * + * @Date 2023/10/21 11:41:46 + * @Author wzh + */ + +public interface ApiEncryptService { + + /** + * 解密 + * @param data + * @return + */ + String decrypt(String data); + + /** + * 加密 + * + * @param data + * @return + */ + String encrypt(String data); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptServiceAesImpl.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptServiceAesImpl.java new file mode 100644 index 0000000..545a278 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptServiceAesImpl.java @@ -0,0 +1,111 @@ +package net.lab1024.sa.base.module.support.apiencrypt.service; + +import cn.hutool.crypto.symmetric.AES; +import cn.hutool.crypto.symmetric.SM4; +import com.alibaba.fastjson.JSON; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.constant.StringConst; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.springframework.stereotype.Service; + +import java.io.UnsupportedEncodingException; +import java.security.Security; +import java.util.Base64; + +/** + * AES 加密和解密 + * 1、AES加密算法支持三种密钥长度:128位、192位和256位,这里选择128位 + * 2、AES 要求秘钥为 128bit,转化字节为 16个字节; + * 3、js前端使用 UCS-2 或者 UTF-16 编码,字母、数字、特殊符号等 占用1个字节; + * 4、所以:秘钥Key 组成为:字母、数字、特殊符号 一共16个即可 + * + * @Date 2023/10/21 11:41:46 + * @Author wzh + */ + +@Slf4j +public class ApiEncryptServiceAesImpl implements ApiEncryptService { + + private static final String CHARSET = "UTF-8"; + + private static final String AES_KEY = "1024lab__1024lab"; + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + @Override + public String encrypt(String data) { + try { + // AES 加密 并转为 base64 + AES aes = new AES(hexToBytes(stringToHex(AES_KEY))); + return aes.encryptBase64(data); + + + } catch (Exception e) { + log.error(e.getMessage(), e); + return StringConst.EMPTY; + } + } + + @Override + public String decrypt(String data) { + try { + // 第一步: Base64 解码 + byte[] base64Decode = Base64.getDecoder().decode(data); + + // 第二步: AES 解密 + AES aes = new AES(hexToBytes(stringToHex(AES_KEY))); + byte[] decryptedBytes = aes.decrypt(base64Decode); + return new String(decryptedBytes, CHARSET); + + } catch (Exception e) { + log.error(e.getMessage(), e); + return StringConst.EMPTY; + } + } + + /** + * 16 进制串转字节数组 + * + * @param hex 16进制字符串 + * @return byte数组 + */ + public static byte[] hexToBytes(String hex) { + int length = hex.length(); + byte[] result; + if (length % 2 == 1) { + length++; + result = new byte[(length / 2)]; + hex = "0" + hex; + } else { + result = new byte[(length / 2)]; + } + int j = 0; + for (int i = 0; i < length; i += 2) { + result[j] = hexToByte(hex.substring(i, i + 2)); + j++; + } + return result; + } + + public static String stringToHex(String input) { + char[] chars = input.toCharArray(); + StringBuilder hex = new StringBuilder(); + for (char c : chars) { + hex.append(Integer.toHexString((int) c)); + } + return hex.toString(); + } + + /** + * 16 进制字符转字节 + * + * @param hex 16进制字符 0x00到0xFF + * @return byte + */ + private static byte hexToByte(String hex) { + return (byte) Integer.parseInt(hex, 16); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptServiceSmImpl.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptServiceSmImpl.java new file mode 100644 index 0000000..26fb0e1 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/apiencrypt/service/ApiEncryptServiceSmImpl.java @@ -0,0 +1,115 @@ +package net.lab1024.sa.base.module.support.apiencrypt.service; + +import cn.hutool.crypto.symmetric.SM4; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.constant.StringConst; +import org.bouncycastle.jce.provider.BouncyCastleProvider; +import org.springframework.stereotype.Service; + +import java.security.Security; +import java.util.Base64; + +/** + * 国产 SM4 加密 和 解密 + * 1、国密SM4 要求秘钥为 128bit,转化字节为 16个字节; + * 2、js前端使用 UCS-2 或者 UTF-16 编码,字母、数字、特殊符号等 占用1个字节; + * 3、java中 每个 字母数字 也是占用1个字节; + * 4、所以:前端和后端的 秘钥Key 组成为:字母、数字、特殊符号 一共16个即可 + * + * @Date 2023/10/21 11:41:46 + * @Author wzh + */ + +@Slf4j +@Service +public class ApiEncryptServiceSmImpl implements ApiEncryptService { + + private static final String CHARSET = "UTF-8"; + private static final String SM4_KEY = "1024lab__1024lab"; + + static { + Security.addProvider(new BouncyCastleProvider()); + } + + + @Override + public String encrypt(String data) { + try { + + // 第一步: SM4 加密 + SM4 sm4 = new SM4(hexToBytes(stringToHex(SM4_KEY))); + String encryptHex = sm4.encryptHex(data); + + // 第二步: Base64 编码 + return new String(Base64.getEncoder().encode(encryptHex.getBytes(CHARSET)), CHARSET); + + } catch (Exception e) { + log.error(e.getMessage(), e); + return StringConst.EMPTY; + } + } + + + @Override + public String decrypt(String data) { + try { + + // 第一步: Base64 解码 + byte[] base64Decode = Base64.getDecoder().decode(data); + + // 第二步: SM4 解密 + SM4 sm4 = new SM4(hexToBytes(stringToHex(SM4_KEY))); + return sm4.decryptStr(new String(base64Decode)); + + } catch (Exception e) { + log.error(e.getMessage(), e); + return StringConst.EMPTY; + } + } + + + public static String stringToHex(String input) { + char[] chars = input.toCharArray(); + StringBuilder hex = new StringBuilder(); + for (char c : chars) { + hex.append(Integer.toHexString((int) c)); + } + return hex.toString(); + } + + + /** + * 16 进制串转字节数组 + * + * @param hex 16进制字符串 + * @return byte数组 + */ + public static byte[] hexToBytes(String hex) { + int length = hex.length(); + byte[] result; + if (length % 2 == 1) { + length++; + result = new byte[(length / 2)]; + hex = "0" + hex; + } else { + result = new byte[(length / 2)]; + } + int j = 0; + for (int i = 0; i < length; i += 2) { + result[j] = hexToByte(hex.substring(i, i + 2)); + j++; + } + return result; + } + + /** + * 16 进制字符转字节 + * + * @param hex 16进制字符 0x00到0xFF + * @return byte + */ + private static byte hexToByte(String hex) { + return (byte) Integer.parseInt(hex, 16); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/CacheService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/CacheService.java new file mode 100644 index 0000000..3d49f9d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/CacheService.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.module.support.cache; + +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.constant.ReloadConst; +import net.lab1024.sa.base.module.support.reload.core.annoation.SmartReload; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.cache.caffeine.CaffeineCacheManager; +import org.springframework.stereotype.Service; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * 缓存服务 + * + * @Date 2021/10/11 20:07 + * @Author wzh + */ +@Service +public interface CacheService { + + /** + * 获取所有缓存名称 + */ + List cacheNames(); + + /** + * 某个缓存下的所有 key + */ + List cacheKey(String cacheName); + + /** + * 移除某个 key + */ + void removeCache(String cacheName); + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/CaffeineCacheServiceImpl.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/CaffeineCacheServiceImpl.java new file mode 100644 index 0000000..087b537 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/CaffeineCacheServiceImpl.java @@ -0,0 +1,68 @@ +package net.lab1024.sa.base.module.support.cache; + +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.constant.ReloadConst; +import net.lab1024.sa.base.module.support.reload.core.annoation.SmartReload; +import org.springframework.cache.caffeine.CaffeineCache; +import org.springframework.cache.caffeine.CaffeineCacheManager; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * caffeine 缓存实现 + * + * @Date 2021/10/11 20:07 + * @Author wzh + */ +public class CaffeineCacheServiceImpl implements CacheService { + + @Resource + private CaffeineCacheManager caffeineCacheManager; + + /** + * 获取所有缓存名称 + */ + @Override + public List cacheNames() { + return Lists.newArrayList(caffeineCacheManager.getCacheNames()); + } + + /** + * 某个缓存下的所有 key + */ + @Override + public List cacheKey(String cacheName) { + CaffeineCache cache = (CaffeineCache) caffeineCacheManager.getCache(cacheName); + if (cache == null) { + return Lists.newArrayList(); + } + Set cacheKey = cache.getNativeCache().asMap().keySet(); + return cacheKey.stream().map(e -> e.toString()).collect(Collectors.toList()); + } + + /** + * 移除某个 key + */ + @Override + public void removeCache(String cacheName) { + CaffeineCache cache = (CaffeineCache) caffeineCacheManager.getCache(cacheName); + if (cache != null) { + cache.clear(); + } + } + + @SmartReload(ReloadConst.CACHE_SERVICE) + public void clearAllCache() { + Collection cacheNames = caffeineCacheManager.getCacheNames(); + for (String name : cacheNames) { + CaffeineCache cache = (CaffeineCache) caffeineCacheManager.getCache(name); + if (cache != null) { + cache.clear(); + } + } + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/RedisCacheServiceImpl.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/RedisCacheServiceImpl.java new file mode 100644 index 0000000..5e04fcc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/cache/RedisCacheServiceImpl.java @@ -0,0 +1,86 @@ +package net.lab1024.sa.base.module.support.cache; + +import cn.hutool.core.util.StrUtil; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.constant.ReloadConst; +import net.lab1024.sa.base.module.support.reload.core.annoation.SmartReload; +import org.springframework.data.redis.cache.RedisCache; +import org.springframework.data.redis.cache.RedisCacheManager; +import org.springframework.data.redis.connection.RedisConnection; +import org.springframework.data.redis.connection.RedisConnectionFactory; + +import java.util.Collection; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +/** + * redis 缓存实现 + * + * @author zhoumingfa + * @date 2025/3/28 + */ +public class RedisCacheServiceImpl implements CacheService { + + @Resource + private RedisCacheManager redisCacheManager; + + @Resource + private RedisConnectionFactory redisConnectionFactory; + + /** + * 获取所有缓存名称 + */ + @Override + public List cacheNames() { + return Lists.newArrayList(redisCacheManager.getCacheNames()); + } + + /** + * 某个缓存下的所有 key + */ + @Override + public List cacheKey(String cacheName) { + RedisCache cache = (RedisCache) redisCacheManager.getCache(cacheName); + if (cache == null) { + return Lists.newArrayList(); + } + // 获取 Redis 连接 + RedisConnection connection = redisConnectionFactory.getConnection(); + // 根据指定的 key 模式获取所有匹配的键 + Set keys = connection.keyCommands().keys((cacheName + ":*").getBytes()); + + if (keys != null) { + return keys.stream().map(key -> { + String redisKey = StrUtil.str(key, "utf-8"); + // 从 Redis 键中提取出最后一个冒号后面的字符串作为真正的键 + return redisKey.substring(redisKey.lastIndexOf(":") + 1); + }).collect(Collectors.toList()); + } + connection.close(); + return Lists.newArrayList(cacheName); + } + + /** + * 移除某个 key + */ + @Override + public void removeCache(String cacheName) { + RedisCache cache = (RedisCache) redisCacheManager.getCache(cacheName); + if (cache != null) { + cache.clear(); + } + } + + @SmartReload(ReloadConst.CACHE_SERVICE) + public void clearAllCache() { + Collection cacheNames = redisCacheManager.getCacheNames(); + for (String name : cacheNames) { + RedisCache cache = (RedisCache) redisCacheManager.getCache(name); + if (cache != null) { + cache.clear(); + } + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/CaptchaController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/CaptchaController.java new file mode 100644 index 0000000..b5ee9b2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/CaptchaController.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.base.module.support.captcha; + + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.captcha.domain.CaptchaVO; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 图形验证码业务 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ +@Tag(name = SwaggerTagConst.Support.CAPTCHA) +@RestController +public class CaptchaController extends SupportBaseController { + + @Resource + private CaptchaService captchaService; + + @Operation(summary = "获取图形验证码 ") + @GetMapping("/captcha") + public ResponseDTO generateCaptcha() { + return ResponseDTO.ok(captchaService.generateCaptcha()); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/CaptchaService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/CaptchaService.java new file mode 100644 index 0000000..500704e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/CaptchaService.java @@ -0,0 +1,108 @@ +package net.lab1024.sa.base.module.support.captcha; + +import cn.hutool.captcha.CaptchaUtil; +import cn.hutool.captcha.LineCaptcha; +import cn.hutool.core.img.ImgUtil; +import cn.hutool.core.util.RandomUtil; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.SystemEnvironment; +import net.lab1024.sa.base.constant.RedisKeyConst; +import net.lab1024.sa.base.module.support.captcha.domain.CaptchaForm; +import net.lab1024.sa.base.module.support.captcha.domain.CaptchaVO; +import net.lab1024.sa.base.module.support.redis.RedisService; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; + +import java.awt.*; +import java.util.Objects; +import java.util.UUID; + +/** + * 图形验证码 服务 + * + * @Date 2021/8/31 20:52 + * @Author wzh + */ +@Slf4j +@Service +public class CaptchaService { + + /** + * 过期时间:65秒 + */ + private static final long EXPIRE_SECOND = 65L; + + @Resource + private SystemEnvironment systemEnvironment; + + @Resource + private RedisService redisService; + + /** + * 生成图形验证码 + * 默认 1 分钟有效期 + */ + public CaptchaVO generateCaptcha() { + + //生成四位验证码 + String captchaText = RandomUtil.randomNumbers(4); + + //定义图形验证码的长、宽、验证码位数、干扰线数量 + LineCaptcha lineCaptcha = CaptchaUtil.createLineCaptcha(125, 43, 4, 80); + + //设置背景颜色 + lineCaptcha.setBackground(new Color(230, 244, 255)); + + //生成图片 + Image image = lineCaptcha.createImage(captchaText); + + //转为base64 + String base64Code = ImgUtil.toBase64(image, "jpg"); + + /* + * 返回验证码对象 + * 图片 base64格式 + */ + // uuid 唯一标识 + String uuid = UUID.randomUUID().toString().replace("-", StringConst.EMPTY); + + CaptchaVO captchaVO = new CaptchaVO(); + captchaVO.setCaptchaUuid(uuid); + captchaVO.setCaptchaBase64Image("data:image/png;base64," + base64Code); + captchaVO.setExpireSeconds(EXPIRE_SECOND); + if (!systemEnvironment.isProd()) { + captchaVO.setCaptchaText(captchaText); + } + String redisCaptchaKey = redisService.generateRedisKey(RedisKeyConst.Support.CAPTCHA, uuid); + redisService.set(redisCaptchaKey, captchaText, EXPIRE_SECOND); + return captchaVO; + } + + /** + * 校验图形验证码 + */ + public ResponseDTO checkCaptcha(CaptchaForm captchaForm) { + if (StringUtils.isBlank(captchaForm.getCaptchaUuid()) || StringUtils.isBlank(captchaForm.getCaptchaCode())) { + return ResponseDTO.userErrorParam("请输入正确验证码"); + } + /* + * 1、校验redis里的验证码 + * 2、校验成功后,删除redis + */ + String redisCaptchaKey = redisService.generateRedisKey(RedisKeyConst.Support.CAPTCHA, captchaForm.getCaptchaUuid()); + String redisCaptchaCode = redisService.get(redisCaptchaKey); + if (StringUtils.isBlank(redisCaptchaCode)) { + return ResponseDTO.userErrorParam("验证码已过期,请刷新重试"); + } + if (!Objects.equals(redisCaptchaCode, captchaForm.getCaptchaCode())) { + return ResponseDTO.userErrorParam("验证码错误,请输入正确的验证码"); + } + // 删除已使用的验证码 + redisService.delete(redisCaptchaKey); + return ResponseDTO.ok(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/domain/CaptchaForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/domain/CaptchaForm.java new file mode 100644 index 0000000..e87dff3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/domain/CaptchaForm.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.base.module.support.captcha.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 图形验证码 表单 + * + * @Date 2021-09-02 20:21:10 + * @Author wzh + */ + +@Data +public class CaptchaForm { + + @Schema(description = "验证码") + @NotBlank(message = "验证码不能为空") + private String captchaCode; + + @Schema(description = "验证码uuid标识") + @NotBlank(message = "验证码uuid标识不能为空") + private String captchaUuid; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/domain/CaptchaVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/domain/CaptchaVO.java new file mode 100644 index 0000000..6db1ef2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/captcha/domain/CaptchaVO.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.base.module.support.captcha.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 图形验证码 VO + * + * @Date 2021/8/31 20:52 + * @Author wzh + */ +@Data +public class CaptchaVO { + + @Schema(description = "验证码唯一标识") + private String captchaUuid; + + @Schema(description = "验证码图片内容-生产环境无效") + private String captchaText; + + @Schema(description = "验证码Base64图片") + private String captchaBase64Image; + + @Schema(description = "过期时间(秒)") + private Long expireSeconds; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/constant/ChangeLogTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/constant/ChangeLogTypeEnum.java new file mode 100644 index 0000000..6331371 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/constant/ChangeLogTypeEnum.java @@ -0,0 +1,38 @@ +package net.lab1024.sa.base.module.support.changelog.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复] + * + * @Author wzh + * @Date 2022-09-26T14:53:50 + */ + +@AllArgsConstructor +@Getter +public enum ChangeLogTypeEnum implements BaseEnum { + + /** + * 重大更新 + */ + MAJOR_UPDATE(1, "重大更新"), + + /** + * 功能更新 + */ + FUNCTION_UPDATE(2, "功能更新"), + + /** + * Bug修复 + */ + BUG_FIX(3, "Bug修复"), + + ; + + private final Integer value; + + private final String desc; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/controller/ChangeLogController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/controller/ChangeLogController.java new file mode 100644 index 0000000..8aac145 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/controller/ChangeLogController.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.module.support.changelog.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.changelog.domain.form.ChangeLogQueryForm; +import net.lab1024.sa.base.module.support.changelog.domain.vo.ChangeLogVO; +import net.lab1024.sa.base.module.support.changelog.service.ChangeLogService; +import org.springframework.web.bind.annotation.*; + +/** + * 系统更新日志 Controller + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@RestController +@Tag(name = SwaggerTagConst.Support.CHANGE_LOG) +public class ChangeLogController extends SupportBaseController { + + @Resource + private ChangeLogService changeLogService; + + @Operation(summary = "分页查询 @author 卓大") + @PostMapping("/changeLog/queryPage") + public ResponseDTO> queryPage(@RequestBody @Valid ChangeLogQueryForm queryForm) { + return ResponseDTO.ok(changeLogService.queryPage(queryForm)); + } + + + @Operation(summary = "变更内容详情 @author 卓大") + @GetMapping("/changeLog/getDetail/{changeLogId}") + public ResponseDTO getDetail(@PathVariable Long changeLogId) { + return ResponseDTO.ok(changeLogService.getById(changeLogId)); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/dao/ChangeLogDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/dao/ChangeLogDao.java new file mode 100644 index 0000000..4c3384e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/dao/ChangeLogDao.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.base.module.support.changelog.dao; + +import java.util.List; + +import net.lab1024.sa.base.module.support.changelog.domain.form.ChangeLogQueryForm; +import net.lab1024.sa.base.module.support.changelog.domain.vo.ChangeLogVO; +import net.lab1024.sa.base.module.support.changelog.domain.entity.ChangeLogEntity; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +/** + * 系统更新日志 Dao + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@Mapper +public interface ChangeLogDao extends BaseMapper { + + /** + * 分页 查询 + * + */ + List queryPage(Page page, @Param("queryForm") ChangeLogQueryForm queryForm); + + /** + * 根据版本查询 ChangeLog + * + */ + ChangeLogEntity selectByVersion(@Param("version") String version); + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/entity/ChangeLogEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/entity/ChangeLogEntity.java new file mode 100644 index 0000000..e4730b3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/entity/ChangeLogEntity.java @@ -0,0 +1,67 @@ +package net.lab1024.sa.base.module.support.changelog.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.time.LocalDate; +import java.time.LocalDateTime; +import lombok.Data; + +/** + * 系统更新日志 + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@Data +@TableName("t_change_log") +public class ChangeLogEntity { + + /** + * 更新日志id + */ + @TableId(type = IdType.AUTO) + private Long changeLogId; + + /** + * 版本 + */ + private String version; + + /** + * 更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复] + */ + private Integer type; + + /** + * 发布人 + */ + private String publishAuthor; + + /** + * 发布日期 + */ + private LocalDate publicDate; + + /** + * 更新内容 + */ + private String content; + + /** + * 跳转链接 + */ + private String link; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogAddForm.java new file mode 100644 index 0000000..0d8093b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogAddForm.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.module.support.changelog.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.changelog.constant.ChangeLogTypeEnum; + +import java.time.LocalDate; + +/** + * 系统更新日志 新建表单 + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@Data +public class ChangeLogAddForm { + + @Schema(description = "版本", required = true) + @NotBlank(message = "版本 不能为空") + private String version; + + @SchemaEnum(value = ChangeLogTypeEnum.class, desc = "更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复]") + @CheckEnum(value = ChangeLogTypeEnum.class, message = "更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复] 错误", required = true) + private Integer type; + + @Schema(description = "发布人", required = true) + @NotBlank(message = "发布人 不能为空") + private String publishAuthor; + + @Schema(description = "发布日期", required = true) + @NotNull(message = "发布日期 不能为空") + private LocalDate publicDate; + + @Schema(description = "更新内容", required = true) + @NotBlank(message = "更新内容 不能为空") + private String content; + + @Schema(description = "跳转链接") + private String link; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogQueryForm.java new file mode 100644 index 0000000..57171bb --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogQueryForm.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.base.module.support.changelog.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.changelog.constant.ChangeLogTypeEnum; + +import java.time.LocalDate; + +/** + * 系统更新日志 查询 + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@Data +public class ChangeLogQueryForm extends PageParam{ + + @SchemaEnum(value = ChangeLogTypeEnum.class, desc = "更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复]") + @CheckEnum(value = ChangeLogTypeEnum.class, message = "更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复] 错误") + private Integer type; + + @Schema(description = "关键字") + private String keyword; + + @Schema(description = "发布日期") + private LocalDate publicDateBegin; + + @Schema(description = "发布日期") + private LocalDate publicDateEnd; + + @Schema(description = "创建时间") + private LocalDate createTime; + + @Schema(description = "跳转链接") + private String link; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogUpdateForm.java new file mode 100644 index 0000000..e442b5f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/form/ChangeLogUpdateForm.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.module.support.changelog.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.changelog.constant.ChangeLogTypeEnum; + +import java.time.LocalDate; + +/** + * 系统更新日志 更新表单 + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@Data +public class ChangeLogUpdateForm { + + @Schema(description = "更新日志id", required = true) + @NotNull(message = "更新日志id 不能为空") + private Long changeLogId; + + @Schema(description = "版本", required = true) + @NotBlank(message = "版本 不能为空") + private String version; + + @SchemaEnum(value = ChangeLogTypeEnum.class, desc = "更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复]") + @CheckEnum(value = ChangeLogTypeEnum.class, message = "更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复] 错误", required = true) + private Integer type; + + @Schema(description = "发布人", required = true) + @NotBlank(message = "发布人 不能为空") + private String publishAuthor; + + @Schema(description = "发布日期", required = true) + @NotNull(message = "发布日期 不能为空") + private LocalDate publicDate; + + @Schema(description = "更新内容", required = true) + @NotBlank(message = "更新内容 不能为空") + private String content; + + @Schema(description = "跳转链接") + private String link; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/vo/ChangeLogVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/vo/ChangeLogVO.java new file mode 100644 index 0000000..844619e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/domain/vo/ChangeLogVO.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.base.module.support.changelog.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.changelog.constant.ChangeLogTypeEnum; + +/** + * 系统更新日志 列表VO + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@Data +public class ChangeLogVO { + + private Long changeLogId; + + @Schema(description = "版本") + private String version; + + @SchemaEnum(value = ChangeLogTypeEnum.class, desc = "更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复]") + private Integer type; + + @Schema(description = "发布人") + private String publishAuthor; + + @Schema(description = "发布日期") + private LocalDate publicDate; + + @Schema(description = "更新内容") + private String content; + + @Schema(description = "跳转链接") + private String link; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/service/ChangeLogService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/service/ChangeLogService.java new file mode 100644 index 0000000..b385217 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/changelog/service/ChangeLogService.java @@ -0,0 +1,96 @@ +package net.lab1024.sa.base.module.support.changelog.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.changelog.dao.ChangeLogDao; +import net.lab1024.sa.base.module.support.changelog.domain.entity.ChangeLogEntity; +import net.lab1024.sa.base.module.support.changelog.domain.form.ChangeLogAddForm; +import net.lab1024.sa.base.module.support.changelog.domain.form.ChangeLogQueryForm; +import net.lab1024.sa.base.module.support.changelog.domain.form.ChangeLogUpdateForm; +import net.lab1024.sa.base.module.support.changelog.domain.vo.ChangeLogVO; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 系统更新日志 Service + * + * @Author wzh + * @Date 2022-09-26 14:53:50 + */ + +@Service +public class ChangeLogService { + + @Resource + private ChangeLogDao changeLogDao; + + /** + * 分页查询 + */ + public PageResult queryPage(ChangeLogQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = changeLogDao.queryPage(page, queryForm); + return SmartPageUtil.convert2PageResult(page, list); + } + + /** + * 添加 + */ + public synchronized ResponseDTO add(ChangeLogAddForm addForm) { + ChangeLogEntity existVersion = changeLogDao.selectByVersion(addForm.getVersion()); + if (existVersion != null) { + return ResponseDTO.userErrorParam("此版本已经存在"); + } + + ChangeLogEntity changeLogEntity = SmartBeanUtil.copy(addForm, ChangeLogEntity.class); + changeLogDao.insert(changeLogEntity); + return ResponseDTO.ok(); + } + + /** + * 更新 + */ + public synchronized ResponseDTO update(ChangeLogUpdateForm updateForm) { + ChangeLogEntity existVersion = changeLogDao.selectByVersion(updateForm.getVersion()); + if (existVersion != null && !updateForm.getChangeLogId().equals(existVersion.getChangeLogId())) { + return ResponseDTO.userErrorParam("此版本已经存在"); + } + ChangeLogEntity changeLogEntity = SmartBeanUtil.copy(updateForm, ChangeLogEntity.class); + changeLogDao.updateById(changeLogEntity); + return ResponseDTO.ok(); + } + + /** + * 批量删除 + */ + public synchronized ResponseDTO batchDelete(List idList) { + if (CollectionUtils.isEmpty(idList)) { + return ResponseDTO.ok(); + } + + changeLogDao.deleteBatchIds(idList); + return ResponseDTO.ok(); + } + + /** + * 单个删除 + */ + public synchronized ResponseDTO delete(Long changeLogId) { + if (null == changeLogId) { + return ResponseDTO.ok(); + } + + changeLogDao.deleteById(changeLogId); + return ResponseDTO.ok(); + } + + public ChangeLogVO getById(Long changeLogId) { + return SmartBeanUtil.copy(changeLogDao.selectById(changeLogId), ChangeLogVO.class); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeDeleteEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeDeleteEnum.java new file mode 100644 index 0000000..d5f5218 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeDeleteEnum.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.base.module.support.codegenerator.constant; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 删除类型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ +public enum CodeDeleteEnum implements BaseEnum { + + SINGLE("Single", "单个删除"), + BATCH("Batch", "批量删除"), + SINGLE_AND_BATCH("SingleAndBatch", "单个和批量删除"); + + private String value; + + private String desc; + + CodeDeleteEnum(String value, String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeFrontComponentEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeFrontComponentEnum.java new file mode 100644 index 0000000..3f77531 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeFrontComponentEnum.java @@ -0,0 +1,49 @@ +package net.lab1024.sa.base.module.support.codegenerator.constant; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 前端组件类型 + * + * @Date 2022-06-30 20:15:38 + * @Author wzh + */ +public enum CodeFrontComponentEnum implements BaseEnum { + + INPUT("Input", "输入框"), + + INPUT_NUMBER("InputNumber", "数字输入框"), + + TEXTAREA("Textarea", " 文本"), + + BOOLEAN_SELECT("BooleanSelect", "布尔下拉框"), + + ENUM_SELECT("SmartEnumSelect", "枚举下拉"), + + DICT_SELECT("DictSelect", "字典下拉"), + + DATE("Date", "日期选择"), + + DATE_TIME("DateTime", "时间选择"), + + FILE_UPLOAD("FileUpload", "文件上传"); + + private String value; + + private String desc; + + CodeFrontComponentEnum(String value, String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public String getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeGeneratorConstant.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeGeneratorConstant.java new file mode 100644 index 0000000..08d0659 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeGeneratorConstant.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.codegenerator.constant; + +/** + * 常量 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ +public class CodeGeneratorConstant { + + /** + * 主键 + */ + public final static String PRIMARY_KEY = "PRI"; + + /** + * 自增 + */ + public final static String AUTO_INCREMENT = "auto_increment"; + + /** + * 默认逻辑删除字段名称 + */ + public static String DELETED_FLAG = "deleted_flag"; + + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeGeneratorPageTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeGeneratorPageTypeEnum.java new file mode 100644 index 0000000..cf1d2c9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeGeneratorPageTypeEnum.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.base.module.support.codegenerator.constant; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 页面类型 + * + * @Date 2022-06-29 19:11:22 + * @Author wzh + */ +public enum CodeGeneratorPageTypeEnum implements BaseEnum { + + MODAL("modal", "弹窗"), + DRAWER("drawer", "抽屉"), + PAGE("page", "新页面"); + + private String value; + + private String desc; + + CodeGeneratorPageTypeEnum(String value, String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeQueryFieldQueryTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeQueryFieldQueryTypeEnum.java new file mode 100644 index 0000000..f0941c1 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/constant/CodeQueryFieldQueryTypeEnum.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.module.support.codegenerator.constant; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 查询条件类型 + * + * @Date 2022-06-29 20:23:46 + * @Author wzh + */ +public enum CodeQueryFieldQueryTypeEnum implements BaseEnum { + + LIKE("Like", "模糊查询"), + EQUAL("Equal", "等于"), + DATE_RANGE("DateRange", "日期范围"), + DATE("Date", "指定日期"), + ENUM("Enum", "枚举"), + + DICT("Dict", "字典"), + ; + + private String value; + + private String desc; + + CodeQueryFieldQueryTypeEnum(String value, String desc) { + this.value = value; + this.desc = desc; + } + + @Override + public Object getValue() { + return value; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/controller/CodeGeneratorController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/controller/CodeGeneratorController.java new file mode 100644 index 0000000..515d71a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/controller/CodeGeneratorController.java @@ -0,0 +1,94 @@ +package net.lab1024.sa.base.module.support.codegenerator.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartResponseUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorPreviewForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.TableQueryForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableColumnVO; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableConfigVO; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableVO; +import net.lab1024.sa.base.module.support.codegenerator.service.CodeGeneratorService; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +/** + * 代码生成 + * + * @Date 2022-06-29 20:23:46 + * @Author wzh + */ +@Tag(name = SwaggerTagConst.Support.CODE_GENERATOR) +@Controller +public class CodeGeneratorController extends SupportBaseController { + + @Resource + private CodeGeneratorService codeGeneratorService; + + // ------------------- 查询 ------------------- + + @Operation(summary = "获取表的列 @author 卓大") + @GetMapping("/codeGenerator/table/getTableColumns/{table}") + @ResponseBody + public ResponseDTO> getTableColumns(@PathVariable String table) { + return ResponseDTO.ok(codeGeneratorService.getTableColumns(table)); + } + + @Operation(summary = "查询数据库的表 @author 卓大") + @PostMapping("/codeGenerator/table/queryTableList") + @ResponseBody + public ResponseDTO> queryTableList(@RequestBody @Valid TableQueryForm tableQueryForm) { + return ResponseDTO.ok(codeGeneratorService.queryTableList(tableQueryForm)); + } + + // ------------------- 配置 ------------------- + + @Operation(summary = "获取表的配置信息 @author 卓大") + @GetMapping("/codeGenerator/table/getConfig/{table}") + @ResponseBody + public ResponseDTO getTableConfig(@PathVariable String table) { + return ResponseDTO.ok(codeGeneratorService.getTableConfig(table)); + } + + @Operation(summary = "更新配置信息 @author 卓大") + @PostMapping("/codeGenerator/table/updateConfig") + @ResponseBody + public ResponseDTO updateConfig(@RequestBody @Valid CodeGeneratorConfigForm form) { + return codeGeneratorService.updateConfig(form); + } + + // ------------------- 生成 ------------------- + + @Operation(summary = "代码预览 @author 卓大") + @PostMapping("/codeGenerator/code/preview") + @ResponseBody + public ResponseDTO preview(@RequestBody @Valid CodeGeneratorPreviewForm form) { + return codeGeneratorService.preview(form); + } + + @Operation(summary = "代码下载 @author 卓大") + @GetMapping(value = "/codeGenerator/code/download/{tableName}", produces = "application/octet-stream") + public void download(@PathVariable String tableName, HttpServletResponse response) throws IOException { + + ResponseDTO download = codeGeneratorService.download(tableName); + + if (download.getOk()) { + SmartResponseUtil.setDownloadFileHeader(response, tableName + "_code.zip", (long) download.getData().length); + response.getOutputStream().write(download.getData()); + } else { + SmartResponseUtil.write(response, download); + } + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorConfigDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorConfigDao.java new file mode 100644 index 0000000..c6482bc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorConfigDao.java @@ -0,0 +1,16 @@ +package net.lab1024.sa.base.module.support.codegenerator.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.codegenerator.domain.entity.CodeGeneratorConfigEntity; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +/** + * 表的 代码生成配置 Dao + * @Date 2022-09-23 20:15:38 + * @Author wzh + */ +@Mapper +public interface CodeGeneratorConfigDao extends BaseMapper { + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorDao.java new file mode 100644 index 0000000..97adba2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/dao/CodeGeneratorDao.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.base.module.support.codegenerator.dao; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.TableQueryForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableColumnVO; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ +@Mapper +public interface CodeGeneratorDao { + + /** + * 分页查询表 + */ + List queryTableList(Page page, @Param("queryForm") TableQueryForm queryForm); + + /** + * 查询表是否存在 + * + * @param tableName + * @return + */ + long countByTableName(@Param("tableName") String tableName); + + + /** + * 查询表列信息 + * + * @param tableName + * @return + */ + List selectTableColumn(@Param("tableName") String tableName); +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/entity/CodeGeneratorConfigEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/entity/CodeGeneratorConfigEntity.java new file mode 100644 index 0000000..87850c6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/entity/CodeGeneratorConfigEntity.java @@ -0,0 +1,70 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 代码生成-配置 + * + * @Date 2022/6/23 21:59:22 + * @Author wzh + */ +@Data +@TableName("t_code_generator_config") +public class CodeGeneratorConfigEntity { + + /** + * 表名 + */ + @TableId(type = IdType.NONE) + private String tableName; + + /** + * 基础命名信息 + */ + private String basic; + + /** + * 字段列表 + */ + private String fields; + + /** + * 增加、修改 信息 + */ + private String insertAndUpdate; + + /** + * 删除 信息 + */ + private String deleteInfo; + + /** + * 查询字段 + */ + private String queryFields; + + /** + * 列表字段 + */ + private String tableFields; + + /** + * 详情 + */ + private String detail; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/CodeGeneratorConfigForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/CodeGeneratorConfigForm.java new file mode 100644 index 0000000..f434b53 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/CodeGeneratorConfigForm.java @@ -0,0 +1,60 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.*; + +import java.util.List; + +/** + * 代码生成 配置信息表单 + * + * @Date 2022-06-29 20:23:46 + * @Author wzh + */ + +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class CodeGeneratorConfigForm { + + @NotBlank(message = "表名 不能为空") + @Schema(description = "表名") + private String tableName; + + @Valid + @NotNull(message = "基础信息不能为空") + @Schema(description = "基础信息") + private CodeBasic basic; + + @Valid + @NotNull(message = "字段信息不能为空") + @Schema(description = "字段信息") + private List fields; + + @Valid + @NotNull(message = "增加、修改 信息 不能为空") + @Schema(description = "增加、修改 信息") + private CodeInsertAndUpdate insertAndUpdate; + + @Valid + @NotNull(message = "删除 信息 不能为空") + @Schema(description = "删除 信息") + private CodeDelete deleteInfo; + + @Valid + @Schema(description = "查询字段") + private List queryFields; + + @Valid + @Schema(description = "列表字段") + private List tableFields; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/CodeGeneratorPreviewForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/CodeGeneratorPreviewForm.java new file mode 100644 index 0000000..ad8838e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/CodeGeneratorPreviewForm.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 代码生成 预览 表单 + * + * @Date 2022/6/23 23:20:46 + * @Author wzh + */ +@Data +public class CodeGeneratorPreviewForm { + + @NotBlank(message = "模板文件 不能为空") + @Schema(description = "模板文件") + private String templateFile; + + @NotBlank(message = "表名 不能为空") + @Schema(description = "表名") + private String tableName; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/TableQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/TableQueryForm.java new file mode 100644 index 0000000..8dc9b4c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/form/TableQueryForm.java @@ -0,0 +1,20 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + + +/** + * 查询表数据 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ +@Data +public class TableQueryForm extends PageParam { + + @Schema(description = "表名关键字") + private String tableNameKeywords; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeBasic.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeBasic.java new file mode 100644 index 0000000..f5ac9dd --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeBasic.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 代码生成 基础数据 模型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Data +public class CodeBasic { + + @Schema(description = "业务名称") + @NotBlank(message = "1.基础命名 基础命名 不能为空") + private String moduleName; + + @Schema(description = "java包名") + @NotBlank(message = "1.基础命名 java包名 不能为空") + private String javaPackageName; + + @Schema(description = "注释") + @NotBlank(message = "1.基础命名 注释 不能为空") + private String description; + + @Schema(description = "前端作者") + @NotBlank(message = "1.基础命名 前端作者 不能为空") + private String frontAuthor; + + @Schema(description = "前端时间") + @NotNull(message = "1.基础命名 前端时间 不能为空") + private LocalDateTime frontDate; + + @Schema(description = "后端作者") + @NotBlank(message = "1.基础命名 后端作者 不能为空") + private String backendAuthor; + + @Schema(description = "后端时间") + @NotNull(message = "1.基础命名 后端时间 不能为空") + private LocalDateTime backendDate; + + @Schema(description = "版权信息") + @NotNull(message = "1.基础命名 版权信息 不能为空") + private String copyright; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeDelete.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeDelete.java new file mode 100644 index 0000000..c51defd --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeDelete.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeDeleteEnum; + +/** + * 代码生成 删除 模型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Data +public class CodeDelete { + + @Schema(description = "是否支持删除 ") + @NotNull(message = "4.删除 是否支持删除 不能为空") + private Boolean isSupportDelete; + + @Schema(description = "是否为物理删除") + @NotNull(message = "4.删除 是否为物理删除 不能为空") + private Boolean isPhysicallyDeleted; + + @Schema(description = "删除类型") + @NotBlank(message = "4.删除 删除类型 不能为空") + @SchemaEnum(CodeDeleteEnum.class) + @CheckEnum(value = CodeDeleteEnum.class, message = "删除 删除类型 枚举值错误") + private String deleteEnum; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeField.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeField.java new file mode 100644 index 0000000..0b08a98 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeField.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 代码生成 基础字段 模型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Data +public class CodeField { + + @Schema(description = "列") + @NotBlank(message = " 2.字段列表 列名 不能为空") + private String columnName; + + @Schema(description = "列备注") + private String columnComment; + + @Schema(description = "字段名词") + @NotBlank(message = "2.字段列表 字段名词 不能为空") + private String label; + + @Schema(description = "字段命名") + @NotBlank(message = "2.字段列表 字段命名 不能为空") + private String fieldName; + + @Schema(description = "java类型") + @NotBlank(message = "2.字段列表 java类型 不能为空") + private String javaType; + + @Schema(description = "js类型") + @NotBlank(message = "2.字段列表 js类型 不能为空") + private String jsType; + + @Schema(description = "字典key") + private String dict; + + @Schema(description = "枚举名称") + private String enumName; + + @Schema(description = "主键") + @NotNull(message = "2.字段列表 主键 不能为空") + private Boolean primaryKeyFlag; + + @Schema(description = "自增") + @NotNull(message = "2.字段列表 自增 不能为空") + private Boolean autoIncreaseFlag; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeInsertAndUpdate.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeInsertAndUpdate.java new file mode 100644 index 0000000..0121c67 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeInsertAndUpdate.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeGeneratorPageTypeEnum; + +import java.util.List; + +/** + * 代码生成 增加、修改 模型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Data +public class CodeInsertAndUpdate { + + @NotNull(message = "3.增加、修改 是否支持增加、修改 不能为空") + private Boolean isSupportInsertAndUpdate; + + @SchemaEnum(CodeGeneratorPageTypeEnum.class) + @CheckEnum(value = CodeGeneratorPageTypeEnum.class, message = "3.增加、修改 增加、修改 页面类型 枚举值错误") + private String pageType; + + @Schema(description = "宽度") + private String width; + + @NotNull(message = "3.增加、修改 每行字段数量 不能为空") + @Schema(description = "每行字段数量") + private Integer countPerLine; + + @Schema(description = "字段列表") + private List fieldList; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeInsertAndUpdateField.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeInsertAndUpdateField.java new file mode 100644 index 0000000..a081f88 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeInsertAndUpdateField.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeFrontComponentEnum; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeGeneratorPageTypeEnum; + +/** + * 代码生成 增加、修改的字段 模型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Data +public class CodeInsertAndUpdateField { + + @NotBlank(message = "3.增加、修改 列名 不能为空") + @Schema(description = "列名") + private String columnName; + + @NotNull(message = "3.增加、修改 必须 不能为空") + @Schema(description = "必须") + private Boolean requiredFlag; + + @NotNull(message = "3.增加、修改 插入标识 不能为空") + @Schema(description = "插入标识") + private Boolean insertFlag; + + @NotNull(message = "3.增加、修改 更新标识 不能为空") + @Schema(description = "更新标识") + private Boolean updateFlag; + + @SchemaEnum(value = CodeFrontComponentEnum.class) + @CheckEnum(value = CodeFrontComponentEnum.class, message = "3.增加、修改 组件类型 枚举值错误", required = true) + private String frontComponent; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeQueryField.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeQueryField.java new file mode 100644 index 0000000..f83f710 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeQueryField.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeQueryFieldQueryTypeEnum; + +import java.util.List; + +/** + * 代码生成 查询条件 模型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Data +public class CodeQueryField { + + @NotBlank(message = "5、查询条件 条件名称 不能为空") + @Schema(description = "条件名称") + private String label; + + @NotBlank(message = "5、查询条件 字段名 不能为空") + @Schema(description = "字段名") + private String fieldName; + + @SchemaEnum(CodeQueryFieldQueryTypeEnum.class) + @CheckEnum(value = CodeQueryFieldQueryTypeEnum.class, message = "5、查询条件 查询条件 查询类型 枚举值错误") + private String queryTypeEnum; + + @NotEmpty(message = "5、查询条件 列 不能为空") + @Schema(description = "列") + private List columnNameList; + + @NotBlank(message = "5、查询条件 宽度 不能为空") + @Schema(description = "宽度") + private String width; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeTableField.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeTableField.java new file mode 100644 index 0000000..2a730c4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/model/CodeTableField.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.module.support.codegenerator.domain.model; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 代码生成 列表表格 模型 + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Data +public class CodeTableField { + + @NotBlank(message = "6、列表 列名 不能为空") + @Schema(description = "列名") + private String columnName; + + @NotBlank(message = "6、列表 字段名词 不能为空") + @Schema(description = "字段名词") + private String label; + + @NotBlank(message = "6、列表 字段命名 不能为空") + @Schema(description = "字段命名") + private String fieldName; + + @NotNull(message = "6、列表 列表显示 不能为空") + @Schema(description = "列表显示") + private Boolean showFlag; + + @Schema(description = "宽度") + private Integer width; + + @NotNull(message = "6、列表 自动省略标识 不能为空") + @Schema(description = "自动省略标识") + private Boolean ellipsisFlag; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableColumnVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableColumnVO.java new file mode 100644 index 0000000..8f6308f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableColumnVO.java @@ -0,0 +1,39 @@ + +package net.lab1024.sa.base.module.support.codegenerator.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 列 + * + * @Date 2022/9/21 21:07:58 + * @Author wzh + */ + +@Data +public class TableColumnVO { + + @Schema(description = "列名") + private String columnName; + + @Schema(description = "列描述") + private String columnComment; + + @Schema(description = "columnKey") + private String columnKey; + + @Schema(description = "extra") + private String extra; + + @Schema(description = "是否为空") + private String isNullable; + + @Schema(description = "数据类型varchar") + private String dataType; + + @Schema(description = "列类型varchar(50)") + private String columnType; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableConfigVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableConfigVO.java new file mode 100644 index 0000000..35cb18a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableConfigVO.java @@ -0,0 +1,37 @@ + +package net.lab1024.sa.base.module.support.codegenerator.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.*; + +import java.util.List; + +/** + * 表的配置信息 + * + * @Date 2022/9/21 21:07:58 + * @Author wzh + */ + +@Data +public class TableConfigVO { + + @Schema(description = "基础命名信息") + private CodeBasic basic; + + @Schema(description = "字段列") + private List fields; + + @Schema(description = "增加、修改 信息") + private CodeInsertAndUpdate insertAndUpdate; + + @Schema(description = "删除 信息") + private CodeDelete deleteInfo; + + @Schema(description = "查询字段") + private List queryFields; + + @Schema(description = "列表字段") + private List tableFields; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableVO.java new file mode 100644 index 0000000..083962b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/domain/vo/TableVO.java @@ -0,0 +1,34 @@ + +package net.lab1024.sa.base.module.support.codegenerator.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 表信息 + * + * @Date 2022/9/21 18:07:58 + * @Author wzh + */ + +@Data +public class TableVO { + + @Schema(description = "表名") + private String tableName; + + @Schema(description = "表备注") + private String tableComment; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @Schema(description = "配置时间") + private LocalDateTime configTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorService.java new file mode 100644 index 0000000..e495bb7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorService.java @@ -0,0 +1,225 @@ +package net.lab1024.sa.base.module.support.codegenerator.service; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeGeneratorConstant; +import net.lab1024.sa.base.module.support.codegenerator.dao.CodeGeneratorConfigDao; +import net.lab1024.sa.base.module.support.codegenerator.dao.CodeGeneratorDao; +import net.lab1024.sa.base.module.support.codegenerator.domain.entity.CodeGeneratorConfigEntity; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorPreviewForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.TableQueryForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.*; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableColumnVO; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableConfigVO; +import net.lab1024.sa.base.module.support.codegenerator.domain.vo.TableVO; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.io.ByteArrayOutputStream; +import java.util.List; +import java.util.Optional; + +/** + * 代码生成器 Service + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ +@Slf4j +@Service +public class CodeGeneratorService { + + @Resource + private CodeGeneratorDao codeGeneratorDao; + + @Resource + private CodeGeneratorConfigDao codeGeneratorConfigDao; + + @Resource + private CodeGeneratorTemplateService codeGeneratorTemplateService; + + + /** + * 列信息 + * + * @param tableName + * @return + */ + public List getTableColumns(String tableName) { + return codeGeneratorDao.selectTableColumn(tableName); + } + + + /** + * 查询数据库表数据 + * + * @param tableQueryForm + * @return + */ + public PageResult queryTableList(TableQueryForm tableQueryForm) { + Page page = SmartPageUtil.convert2PageQuery(tableQueryForm); + List tableVOList = codeGeneratorDao.queryTableList(page, tableQueryForm); + return SmartPageUtil.convert2PageResult(page, tableVOList); + } + + /** + * 获取 表的 配置信息 + * + * @param table + * @return + */ + public TableConfigVO getTableConfig(String table) { + + TableConfigVO config = new TableConfigVO(); + + CodeGeneratorConfigEntity codeGeneratorConfigEntity = codeGeneratorConfigDao.selectById(table); + if (codeGeneratorConfigEntity == null) { + return config; + } + + if (SmartStringUtil.isNotEmpty(codeGeneratorConfigEntity.getBasic())) { + CodeBasic basic = JSON.parseObject(codeGeneratorConfigEntity.getBasic(), CodeBasic.class); + config.setBasic(basic); + } + + if (SmartStringUtil.isNotEmpty(codeGeneratorConfigEntity.getFields())) { + List fields = JSONArray.parseArray(codeGeneratorConfigEntity.getFields(), CodeField.class); + config.setFields(fields); + } + + if (SmartStringUtil.isNotEmpty(codeGeneratorConfigEntity.getInsertAndUpdate())) { + CodeInsertAndUpdate insertAndUpdate = JSON.parseObject(codeGeneratorConfigEntity.getInsertAndUpdate(), CodeInsertAndUpdate.class); + config.setInsertAndUpdate(insertAndUpdate); + } + + if (SmartStringUtil.isNotEmpty(codeGeneratorConfigEntity.getDeleteInfo())) { + CodeDelete deleteInfo = JSON.parseObject(codeGeneratorConfigEntity.getDeleteInfo(), CodeDelete.class); + config.setDeleteInfo(deleteInfo); + } + + if (SmartStringUtil.isNotEmpty(codeGeneratorConfigEntity.getQueryFields())) { + List queryFields = JSONArray.parseArray(codeGeneratorConfigEntity.getQueryFields(), CodeQueryField.class); + config.setQueryFields(queryFields); + } + + if (SmartStringUtil.isNotEmpty(codeGeneratorConfigEntity.getTableFields())) { + List tableFields = JSONArray.parseArray(codeGeneratorConfigEntity.getTableFields(), CodeTableField.class); + config.setTableFields(tableFields); + } + + return config; + } + + /** + * 更新配置 + * + * @param form + * @return + */ + public synchronized ResponseDTO updateConfig(CodeGeneratorConfigForm form) { + long existCount = codeGeneratorDao.countByTableName(form.getTableName()); + if (existCount == 0) { + return ResponseDTO.userErrorParam("表不存在,请联系后端查看下数据库"); + } + + CodeGeneratorConfigEntity codeGeneratorConfigEntity = codeGeneratorConfigDao.selectById(form.getTableName()); + boolean updateFlag = true; + if (codeGeneratorConfigEntity == null) { + codeGeneratorConfigEntity = new CodeGeneratorConfigEntity(); + updateFlag = false; + } + + // 校验假删,必须有 deleted_flag 字段 + List tableColumns = getTableColumns(form.getTableName()); + if (null != form.getDeleteInfo() && form.getDeleteInfo().getIsSupportDelete() && !form.getDeleteInfo().getIsPhysicallyDeleted()) { + Optional any = tableColumns.stream().filter(e -> e.getColumnName().equals(CodeGeneratorConstant.DELETED_FLAG)).findAny(); + if (!any.isPresent()) { + return ResponseDTO.userErrorParam("表结构中没有假删字段:" + CodeGeneratorConstant.DELETED_FLAG + ",请仔细排查"); + } + } + + // 校验表必须有主键 + if(!tableColumns.stream().filter( e -> "PRI".equalsIgnoreCase(e.getColumnKey())).findAny().isPresent()){ + return ResponseDTO.userErrorParam("表必须有主键,请联系后端查看下数据库表结构"); + } + + codeGeneratorConfigEntity.setTableName(form.getTableName()); + codeGeneratorConfigEntity.setBasic(JSON.toJSONString(form.getBasic())); + codeGeneratorConfigEntity.setFields(JSONArray.toJSONString(form.getFields())); + codeGeneratorConfigEntity.setInsertAndUpdate(JSON.toJSONString(form.getInsertAndUpdate())); + codeGeneratorConfigEntity.setDeleteInfo(JSON.toJSONString(form.getDeleteInfo())); + codeGeneratorConfigEntity.setQueryFields(JSONArray.toJSONString(form.getQueryFields())); + codeGeneratorConfigEntity.setTableFields(JSONArray.toJSONString(form.getTableFields())); + + if (updateFlag) { + codeGeneratorConfigDao.updateById(codeGeneratorConfigEntity); + } else { + codeGeneratorConfigDao.insert(codeGeneratorConfigEntity); + } + return ResponseDTO.ok(); + } + + /** + * 预览 + * + * @param form + * @return + */ + public ResponseDTO preview(CodeGeneratorPreviewForm form) { + long existCount = codeGeneratorDao.countByTableName(form.getTableName()); + if (existCount == 0) { + return ResponseDTO.userErrorParam("表不存在,请联系后端查看下数据库"); + } + + CodeGeneratorConfigEntity codeGeneratorConfigEntity = codeGeneratorConfigDao.selectById(form.getTableName()); + if (codeGeneratorConfigEntity == null) { + return ResponseDTO.userErrorParam("配置信息不存在,请先进行配置"); + } + + List columns = getTableColumns(form.getTableName()); + if (CollectionUtils.isEmpty(columns)) { + return ResponseDTO.userErrorParam("表没有列信息无法生成"); + } + + String result = codeGeneratorTemplateService.generate(form.getTableName(), form.getTemplateFile(), codeGeneratorConfigEntity); + return ResponseDTO.ok(result); + + } + + /** + * 下载代码 + * @param tableName + * @return + */ + public ResponseDTO download(String tableName) { + if (SmartStringUtil.isBlank(tableName)) { + return ResponseDTO.userErrorParam("表名不能为空"); + } + + long existCount = codeGeneratorDao.countByTableName(tableName); + if (existCount == 0) { + return ResponseDTO.userErrorParam("表不存在,请联系后端查看下数据库"); + } + + CodeGeneratorConfigEntity codeGeneratorConfigEntity = codeGeneratorConfigDao.selectById(tableName); + if (codeGeneratorConfigEntity == null) { + return ResponseDTO.userErrorParam("配置信息不存在,请先进行配置"); + } + + List columns = getTableColumns(tableName); + if (CollectionUtils.isEmpty(columns)) { + return ResponseDTO.userErrorParam("表没有列信息无法生成"); + } + ByteArrayOutputStream out = new ByteArrayOutputStream(); + codeGeneratorTemplateService.zipGeneratedFiles(out, tableName, codeGeneratorConfigEntity); + return ResponseDTO.ok(out.toByteArray()); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorTemplateService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorTemplateService.java new file mode 100644 index 0000000..74998c9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/CodeGeneratorTemplateService.java @@ -0,0 +1,236 @@ +package net.lab1024.sa.base.module.support.codegenerator.service; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.util.ZipUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.google.common.base.CaseFormat; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.domain.entity.CodeGeneratorConfigEntity; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.*; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.*; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.domain.*; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.front.ApiVariableService; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.front.ConstVariableService; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.front.FormVariableService; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.front.ListVariableService; +import net.lab1024.sa.base.module.support.codegenerator.util.CodeGeneratorTool; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.velocity.Template; +import org.apache.velocity.app.Velocity; +import org.apache.velocity.app.VelocityEngine; +import org.apache.velocity.tools.ToolContext; +import org.apache.velocity.tools.ToolManager; +import org.springframework.stereotype.Service; + +import java.io.File; +import java.io.OutputStream; +import java.io.StringWriter; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.*; +import java.util.stream.Collectors; + +/** + * 代码生成器 模板 Service + * + * @Date 2022-06-30 22:15:38 + * @Author wzh + */ + +@Service +@Slf4j +public class CodeGeneratorTemplateService { + + + private Map map = new HashMap<>(); + + @PostConstruct + public void init() { + // 后端 + map.put("java/domain/entity/Entity.java", new EntityVariableService()); + map.put("java/domain/form/AddForm.java", new AddFormVariableService()); + map.put("java/domain/form/UpdateForm.java", new UpdateFormVariableService()); + map.put("java/domain/form/QueryForm.java", new QueryFormVariableService()); + map.put("java/domain/vo/VO.java", new VOVariableService()); + map.put("java/controller/Controller.java", new ControllerVariableService()); + map.put("java/service/Service.java", new ServiceVariableService()); + map.put("java/manager/Manager.java", new ManagerVariableService()); + map.put("java/dao/Dao.java", new DaoVariableService()); + map.put("java/mapper/Mapper.xml", new MapperVariableService()); + // 菜单 SQL + map.put("java/sql/Menu.sql", new MenuVariableService()); + // 前端 + map.put("js/api.js", new ApiVariableService()); + map.put("js/const.js", new ConstVariableService()); + map.put("js/list.vue", new ListVariableService()); + map.put("js/form.vue", new FormVariableService()); + } + + public void zipGeneratedFiles(OutputStream outputStream, String tableName, CodeGeneratorConfigEntity codeGeneratorConfigEntity) { + String uuid = UUID.randomUUID().toString(); + File dir = new File(uuid); + + // 1、生产文件 + CodeBasic basic = JSON.parseObject(codeGeneratorConfigEntity.getBasic(), CodeBasic.class); + String moduleName = basic.getModuleName(); + + for (Map.Entry entry : map.entrySet()) { + try { + String templateFile = entry.getKey(); + String upperCamel = new CodeGeneratorTool().lowerCamel2UpperCamel(moduleName); + String lowerHyphen = new CodeGeneratorTool().lowerCamel2LowerHyphen(moduleName); + String[] templateSplit = templateFile.split("/"); + String fileName = templateFile.startsWith("java") ? upperCamel + templateSplit[templateSplit.length - 1] : lowerHyphen + "-" + templateSplit[templateSplit.length - 1]; + String fullPathFileName = templateFile.replaceAll(templateSplit[templateSplit.length - 1], fileName); + fullPathFileName = fullPathFileName.replaceAll("java/", "java/" + basic.getModuleName().toLowerCase() + "/"); + fullPathFileName = fullPathFileName.replaceAll("js/", "js/" + lowerHyphen + "/"); + + String fileContent = generate(tableName, templateFile, codeGeneratorConfigEntity); + File file = new File(uuid + "/" + fullPathFileName); + file.getParentFile().mkdirs(); + FileUtil.appendUtf8String(fileContent, file); + } catch (IORuntimeException e) { + log.error(e.getMessage(), e); + } + } + + // 2、后端的枚举文件 + List fields = JSONArray.parseArray(codeGeneratorConfigEntity.getFields(), CodeField.class); + if (CollectionUtils.isNotEmpty(fields)) { + List enumFiledList = fields.stream().filter(e -> SmartStringUtil.isNotBlank(e.getEnumName())).collect(Collectors.toList()); + for (CodeField codeField : enumFiledList) { + Map variablesMap = new HashMap<>(); + + String enumName = CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, codeField.getEnumName()); + if (!enumName.endsWith("Enum")) { + enumName = enumName + "Enum"; + } + variablesMap.put("enumName", enumName); + variablesMap.put("enumDesc", codeField.getColumnComment()); + variablesMap.put("enumJavaType", codeField.getJavaType()); + variablesMap.put("basic", basic); + variablesMap.put("packageName", basic.getJavaPackageName() + ".constant"); + + String fileContent = render("code-generator-template/java/constant/enum.java.vm", variablesMap); + File file = new File(uuid + "/java/" + basic.getModuleName().toLowerCase() + "/constant/" + enumName + ".java"); + file.getParentFile().mkdirs(); + FileUtil.appendUtf8String(fileContent, file); + } + } + + + ZipUtil.zip(outputStream, StandardCharsets.UTF_8, false, null, dir); + + FileUtil.del(dir); + + } + + + public String generate(String tableName, String file, CodeGeneratorConfigEntity codeGeneratorConfigEntity) { + + // -------------------- 1 校验不支持的代码生成,比如增加、删除等 -------------------- + + String finalFile = file; + Optional optional = map.keySet().stream().filter(e -> e.contains(finalFile)).findFirst(); + if (!optional.isPresent()) { + return "不存在此模板!"; + } + + file = optional.get(); + CodeGenerateBaseVariableService codeGenerateBaseVariableService = map.get(file); + if (codeGenerateBaseVariableService == null) { + return "代码生成Service不存在,请检查相关代码!"; + } + + CodeBasic basic = JSON.parseObject(codeGeneratorConfigEntity.getBasic(), CodeBasic.class); + List fields = JSONArray.parseArray(codeGeneratorConfigEntity.getFields(), CodeField.class); + CodeInsertAndUpdate insertAndUpdate = JSON.parseObject(codeGeneratorConfigEntity.getInsertAndUpdate(), CodeInsertAndUpdate.class); + CodeDelete deleteInfo = JSON.parseObject(codeGeneratorConfigEntity.getDeleteInfo(), CodeDelete.class); + List queryFields = JSONArray.parseArray(codeGeneratorConfigEntity.getQueryFields(), CodeQueryField.class); + List tableFields = JSONArray.parseArray(codeGeneratorConfigEntity.getTableFields(), CodeTableField.class); + tableFields.forEach(e -> e.setWidth(e.getWidth() == null ? 0 : e.getWidth())); + + CodeGeneratorConfigForm form = CodeGeneratorConfigForm.builder().basic(basic).fields(fields).insertAndUpdate(insertAndUpdate).deleteInfo(deleteInfo).queryFields(queryFields).tableFields(tableFields).deleteInfo(deleteInfo).build(); + form.setTableName(tableName); + if (!codeGenerateBaseVariableService.isSupport(form)) { + return "业务不需要此功能,故没有生成代码;"; + } + + // -------------------- 2 通用模板的变量 -------------------- + Map variablesMap = new HashMap<>(); + + + Map basicMap = BeanUtil.beanToMap(basic); + basicMap.put("frontDate", DateUtil.formatLocalDateTime(basic.getFrontDate())); + basicMap.put("backendDate", DateUtil.formatLocalDateTime(basic.getBackendDate())); + + variablesMap.put("basic", basicMap); + variablesMap.put("fields", fields); + variablesMap.put("insertAndUpdate", insertAndUpdate); + variablesMap.put("deleteInfo", deleteInfo); + variablesMap.put("queryFields", queryFields); + variablesMap.put("tableFields", tableFields); + variablesMap.put("tableName", tableName); + + //名词的大写开头和小写开头 + HashMap names = new HashMap<>(); + names.put("lowerCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_CAMEL, basic.getModuleName())); + names.put("upperCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL, basic.getModuleName())); + names.put("lowerHyphenCamel", CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, basic.getModuleName())); + variablesMap.put("name", names); + + //主键字段名称和java类型 + CodeField primaryKeycodeField = fields.stream().filter(e -> e.getPrimaryKeyFlag()).findFirst().get(); + if (primaryKeycodeField != null) { + variablesMap.put("primaryKeyJavaType", primaryKeycodeField.getJavaType()); + variablesMap.put("primaryKeyFieldName", primaryKeycodeField.getFieldName()); + variablesMap.put("primaryKeyColumnName", primaryKeycodeField.getColumnName()); + } + + // -------------------- 3、针对此 模板 的特殊变量 -------------------- + + Map specialVariables = codeGenerateBaseVariableService.getInjectVariablesMap(form); + variablesMap.putAll(specialVariables); + + // -------------------- 4、模板 生成代码 -------------------- + + return render("code-generator-template/" + file + ".vm", variablesMap); + } + + /** + * 渲染 + * + * @param templateFile + * @param variablesMap + * @return + */ + private String render(String templateFile, Map variablesMap) { + VelocityEngine engine = new VelocityEngine(); + engine.setProperty(Velocity.FILE_RESOURCE_LOADER_CACHE, true); + engine.setProperty(Velocity.INPUT_ENCODING, "UTF-8"); + engine.setProperty("resource.loader.file.class", "org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader"); + engine.init(); + Template template = engine.getTemplate(templateFile); + + //加载tools.xml配置文件 + ToolManager toolManager = new ToolManager(); + toolManager.configure("code-generator-template/tools.xml"); + + //注入变量 + ToolContext context = toolManager.createContext(); + context.putAll(variablesMap); + + StringWriter sw = new StringWriter(); + template.merge(context, sw); + return sw.toString(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/CodeGenerateBaseVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/CodeGenerateBaseVariableService.java new file mode 100644 index 0000000..5c7e2d9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/CodeGenerateBaseVariableService.java @@ -0,0 +1,148 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable; + +import com.google.common.base.CaseFormat; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeFrontComponentEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdate; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.*; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * @Date 2022/9/29 17:20:41 + * @Author wzh + */ +public abstract class CodeGenerateBaseVariableService { + + public abstract Map getInjectVariablesMap(CodeGeneratorConfigForm form); + + /** + * 是否支持 : + * 1、增加、修改 + * 2、删除 + * + * @param form + * @return + */ + public abstract boolean isSupport(CodeGeneratorConfigForm form); + + /** + * 获取所有javabean的 import 包名 + * + * @param form + * @return + */ + public List getJavaBeanImportClass(CodeGeneratorConfigForm form) { + String upperCamelName = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_CAMEL, form.getBasic().getModuleName()); + ArrayList list = new ArrayList<>(); + + list.add("import " + form.getBasic().getJavaPackageName() + ".domain.entity." + upperCamelName + "Entity;"); + + list.add("import " + form.getBasic().getJavaPackageName() + ".domain.form." + upperCamelName + "AddForm;"); + list.add("import " + form.getBasic().getJavaPackageName() + ".domain.form." + upperCamelName + "UpdateForm;"); + list.add("import " + form.getBasic().getJavaPackageName() + ".domain.form." + upperCamelName + "QueryForm;"); + + list.add("import " + form.getBasic().getJavaPackageName() + ".domain.vo." + upperCamelName + "VO;"); + return list; + } + + + /** + * 根据列名查找 CodeField + */ + public CodeField getCodeFieldByColumnName(String columnName, CodeGeneratorConfigForm form) { + List fields = form.getFields(); + if (CollectionUtils.isEmpty(fields)) { + return null; + } + + return fields.stream().filter(e -> SmartStringUtil.equals(columnName, e.getColumnName())).findFirst().orElse(null); + } + + + /** + * 是否为文件上传字段 + */ + protected boolean isFile(String columnName, CodeGeneratorConfigForm form) { + CodeInsertAndUpdate insertAndUpdate = form.getInsertAndUpdate(); + if (insertAndUpdate == null) { + return false; + } + + List fieldList = insertAndUpdate.getFieldList(); + if (CollectionUtils.isEmpty(fieldList)) { + return false; + } + + Optional first = fieldList.stream().filter(e -> columnName.equals(e.getColumnName())).findFirst(); + if (!first.isPresent()) { + return false; + } + + CodeInsertAndUpdateField field = first.get(); + return CodeFrontComponentEnum.FILE_UPLOAD.equalsValue(field.getFrontComponent()); + } + + /** + * 是否为 字典 + */ + protected boolean isDict(String columnName, CodeGeneratorConfigForm form) { + CodeField codeField = getCodeField(columnName, form); + return codeField != null && codeField.getDict() != null; + } + + /** + * 是否为 枚举 + */ + protected boolean isEnum(String columnName, CodeGeneratorConfigForm form) { + CodeField codeField = getCodeField(columnName, form); + return codeField != null && codeField.getEnumName() != null; + } + + private CodeField getCodeField(String columnName, CodeGeneratorConfigForm form) { + List fields = form.getFields(); + if (CollectionUtils.isEmpty(fields)) { + return null; + } + + return fields.stream().filter(e -> columnName.equals(e.getColumnName())).findFirst().orElse(null); + } + + /** + * 获取字段集合 + * + * @param form + * @return + */ + protected Map getFieldMap(CodeGeneratorConfigForm form) { + List fields = form.getFields(); + if (fields == null) { + return new HashMap<>(); + } + + return fields.stream().collect(Collectors.toMap(CodeField::getColumnName, Function.identity())); + } + + /** + * 获取java类型 + * + * @return + */ + protected String getJavaPackageName(String javaType) { + if ("BigDecimal".equals(javaType)) { + return "import java.math.BigDecimal;"; + } else if ("LocalDate".equals(javaType)) { + return "import java.time.LocalDate;"; + } else if ("LocalDateTime".equals(javaType)) { + return "import java.time.LocalDateTime;"; + } else { + return null; + } + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ControllerVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ControllerVariableService.java new file mode 100644 index 0000000..239f041 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ControllerVariableService.java @@ -0,0 +1,75 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend; + +import com.google.common.base.CaseFormat; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeDeleteEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class ControllerVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + List updateFieldList = form.getInsertAndUpdate().getFieldList().stream().filter(e -> Boolean.TRUE.equals(e.getInsertFlag())).collect(Collectors.toList()); + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".controller"); + + List packageList = getPackageList(updateFieldList, form); + variablesMap.put("importPackageList", packageList); + + return variablesMap; + } + + + public List getPackageList(List fields, CodeGeneratorConfigForm form) { + if (CollectionUtils.isEmpty(fields)) { + return new ArrayList<>(); + } + + HashSet packageSet = new HashSet<>(); + + //1、javabean相关的包 + packageSet.addAll(getJavaBeanImportClass(form).stream().filter(e -> !e.contains("Entity;")).collect(Collectors.toList())); + + //2、其他包 + if (form.getDeleteInfo().getIsSupportDelete()) { + + CodeDeleteEnum codeDeleteEnum = SmartEnumUtil.getEnumByValue(form.getDeleteInfo().getDeleteEnum(), CodeDeleteEnum.class); + if (codeDeleteEnum == CodeDeleteEnum.BATCH || codeDeleteEnum == CodeDeleteEnum.SINGLE_AND_BATCH) { + //2、批量删除的话,要导入ValidateList + packageSet.add("import net.lab1024.sa.base.common.domain.ValidateList;"); + } + + if (codeDeleteEnum == CodeDeleteEnum.SINGLE || codeDeleteEnum == CodeDeleteEnum.SINGLE_AND_BATCH) { + //3、单个删除的话,要导入 @PathVariable + packageSet.add("import org.springframework.web.bind.annotation.PathVariable;"); + packageSet.add("import org.springframework.web.bind.annotation.GetMapping;"); + } + } + + packageSet.add("import " + form.getBasic().getJavaPackageName() + ".service." + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, form.getBasic().getModuleName()) + "Service;"); + + // 排序一下 + ArrayList packageList = new ArrayList<>(packageSet); + Collections.sort(packageList); + return packageList; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/DaoVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/DaoVariableService.java new file mode 100644 index 0000000..32b1791 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/DaoVariableService.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend; + +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class DaoVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + List updateFieldList = form.getInsertAndUpdate().getFieldList().stream().filter(e -> Boolean.TRUE.equals(e.getInsertFlag())).collect(Collectors.toList()); + List packageList = getPackageList(updateFieldList, form); + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".dao" ); + variablesMap.put("importPackageList", packageList); + + return variablesMap; + } + + + public List getPackageList(List fields, CodeGeneratorConfigForm form) { + if (CollectionUtils.isEmpty(fields)) { + return new ArrayList<>(); + } + + HashSet packageSet = new HashSet<>(); + + //1、javabean相关的包 + packageSet.addAll(getJavaBeanImportClass(form).stream().filter( e-> e.contains("QueryForm;") || e.contains("VO;")|| e.contains("Entity;")).collect(Collectors.toList())); + + //2、util + packageSet.add("import java.util.List;"); + + //3、 排序一下 + ArrayList packageList = new ArrayList<>(packageSet); + Collections.sort(packageList); + return packageList; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ManagerVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ManagerVariableService.java new file mode 100644 index 0000000..ed1ef5b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ManagerVariableService.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend; + +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class ManagerVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + List updateFieldList = form.getInsertAndUpdate().getFieldList().stream().filter(e -> Boolean.TRUE.equals(e.getInsertFlag())).collect(Collectors.toList()); + List packageList = getPackageList(updateFieldList, form); + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".manager" ); + variablesMap.put("importPackageList", packageList); + + return variablesMap; + } + + + public List getPackageList(List fields, CodeGeneratorConfigForm form) { + if (CollectionUtils.isEmpty(fields)) { + return new ArrayList<>(); + } + + HashSet packageList = new HashSet<>(); + + //1、javabean相关的包 + packageList.addAll(getJavaBeanImportClass(form).stream().filter(e -> e.contains("Entity;")).collect(Collectors.toList())); + + //2、dao + packageList.add("import " + form.getBasic().getJavaPackageName() + ".dao."+ form.getBasic().getModuleName() + "Dao;" ); + return new ArrayList<>(packageList); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/MenuVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/MenuVariableService.java new file mode 100644 index 0000000..17ab19f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/MenuVariableService.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend; + +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; + +import java.util.HashMap; +import java.util.Map; + +/** + * 目前暂时没用到 这是一个空实现 + * + * @author zhoumingfa + * @date 2024/8/13 + */ +public class MenuVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + return new HashMap<>(2); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ServiceVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ServiceVariableService.java new file mode 100644 index 0000000..2908934 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/ServiceVariableService.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend; + +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class ServiceVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + List updateFieldList = form.getInsertAndUpdate().getFieldList().stream().filter(e -> Boolean.TRUE.equals(e.getInsertFlag())).collect(Collectors.toList()); + List packageList = getPackageList(updateFieldList, form); + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".service" ); + variablesMap.put("importPackageList", packageList); + + return variablesMap; + } + + + public List getPackageList(List fields, CodeGeneratorConfigForm form) { + if (CollectionUtils.isEmpty(fields)) { + return new ArrayList<>(); + } + + HashSet packageSet = new HashSet<>(); + + //1、javabean相关的包 + packageSet.addAll(getJavaBeanImportClass(form)); + + //2、dao + packageSet.add("import " + form.getBasic().getJavaPackageName() + ".dao."+ form.getBasic().getModuleName() + "Dao;" ); + + //3、util list + packageSet.add("import java.util.List;"); + + //3、 排序一下 + ArrayList packageList = new ArrayList<>(packageSet); + Collections.sort(packageList); + return packageList; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/AddFormVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/AddFormVariableService.java new file mode 100644 index 0000000..d47c9f9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/AddFormVariableService.java @@ -0,0 +1,128 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.domain; + +import cn.hutool.core.bean.BeanUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeFrontComponentEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdate; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class AddFormVariableService extends CodeGenerateBaseVariableService { + + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + CodeInsertAndUpdate insertAndUpdate = form.getInsertAndUpdate(); + return insertAndUpdate != null && insertAndUpdate.getIsSupportInsertAndUpdate() != null && insertAndUpdate.getIsSupportInsertAndUpdate(); + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + List updateFieldList = form.getInsertAndUpdate().getFieldList().stream().filter(e -> Boolean.TRUE.equals(e.getInsertFlag())).collect(Collectors.toList()); + ImmutablePair, List>> packageListAndFields = getPackageListAndFields(updateFieldList, form); + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".domain.form"); + variablesMap.put("importPackageList", packageListAndFields.getLeft()); + variablesMap.put("fields", packageListAndFields.getRight()); + + return variablesMap; + } + + + public ImmutablePair, List>> getPackageListAndFields(List fields, CodeGeneratorConfigForm form) { + if (CollectionUtils.isEmpty(fields)) { + return ImmutablePair.of(new ArrayList<>(), new ArrayList<>()); + } + + Map fieldMap = getFieldMap(form); + HashSet packageList = new HashSet<>(); + + + /** + * 1、LocalDate、LocalDateTime、BigDecimal 类型的包名 + * 2、排序 + */ + + List> finalFieldList = new ArrayList<>(); + + for (CodeInsertAndUpdateField field : fields) { + CodeField codeField = fieldMap.get(field.getColumnName()); + if (codeField == null) { + continue; + } + + // CodeField 和 InsertAndUpdateField 合并 + Map finalFieldMap = BeanUtil.beanToMap(field); + finalFieldMap.putAll(BeanUtil.beanToMap(codeField)); + + // 枚举 + if (SmartStringUtil.isNotEmpty(codeField.getEnumName())) { + packageList.add("import net.lab1024.sa.base.common.swagger.SchemaEnum;"); + packageList.add("import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;"); + packageList.add("import " + form.getBasic().getJavaPackageName() + ".constant." + codeField.getEnumName() + ";"); + + //enum check + String checkEnumPrefix = "@CheckEnum(value = " + codeField.getEnumName() + ".class, message = \"" + codeField.getLabel() + " 错误\""; + String checkEnum = checkEnumPrefix + (field.getRequiredFlag() ? ", required = true)" : ")"); + + finalFieldMap.put("apiModelProperty", "@SchemaEnum(value = " + codeField.getEnumName() + ".class, desc = \"" + codeField.getLabel() + "\")"); + finalFieldMap.put("checkEnum", checkEnum); + finalFieldMap.put("isEnum", true); + + } else { + String prefix = "@Schema(description = \"" + codeField.getLabel() + "\""; + String apiModelProperty = prefix + (field.getRequiredFlag() ? ", requiredMode = Schema.RequiredMode.REQUIRED)" : ")"); + finalFieldMap.put("apiModelProperty", apiModelProperty); + + packageList.add("import io.swagger.v3.oas.annotations.media.Schema;"); + + if (Boolean.TRUE.equals(field.getRequiredFlag())) { + String notEmptyPrefix = "String".equals(codeField.getJavaType()) ? "@NotBlank" : "@NotNull"; + finalFieldMap.put("notEmpty", "\n " + notEmptyPrefix + "(message = \"" + codeField.getLabel() + " 不能为空\")"); + packageList.add("String".equals(codeField.getJavaType()) ? "import jakarta.validation.constraints.NotBlank;" + : "import jakarta.validation.constraints.NotNull;"); + } + } + + //字典 + if (SmartStringUtil.isNotEmpty(codeField.getDict())) { + finalFieldMap.put("dict", "\n @JsonDeserialize(using = DictValueVoDeserializer.class)"); + packageList.add("import com.fasterxml.jackson.databind.annotation.JsonDeserialize;"); + packageList.add("import net.lab1024.sa.base.common.json.deserializer.DictValueVoDeserializer;"); + } + + //文件上传 + if (CodeFrontComponentEnum.FILE_UPLOAD.equalsValue(field.getFrontComponent())) { + finalFieldMap.put("file", "\n @JsonDeserialize(using = FileKeyVoDeserializer.class)"); + packageList.add("import com.fasterxml.jackson.databind.annotation.JsonDeserialize;"); + packageList.add("import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;"); + } + + packageList.add(getJavaPackageName(codeField.getJavaType())); + finalFieldList.add(finalFieldMap); + } + + + // lombok + packageList.add("import lombok.Data;"); + + List packageNameList = packageList.stream().filter(Objects::nonNull).collect(Collectors.toList()); + Collections.sort(packageNameList); + return ImmutablePair.of(packageNameList, finalFieldList); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/EntityVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/EntityVariableService.java new file mode 100644 index 0000000..4ae9f87 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/EntityVariableService.java @@ -0,0 +1,77 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.domain; + +import com.google.common.collect.Lists; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class EntityVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".domain.entity"); + variablesMap.put("importPackageList", getImportPackageList(form.getFields())); + + + return variablesMap; + } + + + public List getImportPackageList(List fields) { + if (CollectionUtils.isEmpty(fields)) { + return Lists.newArrayList(); + } + + /** + * 1、LocalDate、LocalDateTime、BigDecimal 类型的包名 + * 2、排序 + */ + List result = fields.stream().map(e -> getJavaPackageName(e.getJavaType())).filter(Objects::nonNull).distinct().collect(Collectors.toList()); + + // lombok + result.add("import lombok.Data;"); + + // mybatis plus + result.add("import com.baomidou.mybatisplus.annotation.TableName;"); + + // 自动填充注解 + boolean existCreateAndUpdate = fields.stream().anyMatch(e -> "create_time".equals(e.getColumnName()) || "update_time".equals(e.getColumnName())); + if (existCreateAndUpdate) { + result.add("import com.baomidou.mybatisplus.annotation.FieldFill;"); + result.add("import com.baomidou.mybatisplus.annotation.TableField;"); + } + + //主键 + boolean isExistPrimaryKey = fields.stream().anyMatch(e -> e.getPrimaryKeyFlag() != null && e.getPrimaryKeyFlag()); + if (isExistPrimaryKey) { + result.add("import com.baomidou.mybatisplus.annotation.TableId;"); + } + + //自增 + boolean isExistAutoIncrease = fields.stream().anyMatch(e -> e.getAutoIncreaseFlag() != null && e.getAutoIncreaseFlag()); + if (isExistAutoIncrease) { + result.add("import com.baomidou.mybatisplus.annotation.IdType;"); + } + + Collections.sort(result); + return result; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/MapperVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/MapperVariableService.java new file mode 100644 index 0000000..922d21b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/MapperVariableService.java @@ -0,0 +1,85 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.domain; + +import cn.hutool.core.bean.BeanUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeQueryFieldQueryTypeEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeQueryField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class MapperVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + List> finalQueryFiledList = new ArrayList<>(); + for (CodeQueryField queryField : form.getQueryFields()) { + Map fieldMap = BeanUtil.beanToMap(queryField); + finalQueryFiledList.add(fieldMap); + + //模糊查询 + if (CodeQueryFieldQueryTypeEnum.LIKE.getValue().equals(queryField.getQueryTypeEnum())) { + StringBuilder stringBuilder = new StringBuilder(); + List columnNameList = queryField.getColumnNameList(); + if (columnNameList.size() == 1) { + // AND INSTR(t_notice.title,#{query.keywords}) + stringBuilder.append("AND INSTR(") + .append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(0)) + .append(",#{queryForm.") + .append(queryField.getFieldName()) + .append("})"); + } else { + for (int i = 0; i < columnNameList.size(); i++) { + if (i == 0) { + stringBuilder.append("AND (\n INSTR(") + .append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(i)) + .append(",#{queryForm.") + .append(queryField.getFieldName()) + .append("})"); + } else { + // OR INSTR(t_notice.author,#{query.keywords}) + stringBuilder.append("\n OR INSTR(") + .append(form.getTableName()).append(".").append(queryField.getColumnNameList().get(i)) + .append(",#{queryForm.") + .append(queryField.getFieldName()) + .append("})"); + } + } + stringBuilder.append("\n )"); + } + fieldMap.put("likeStr", stringBuilder.toString()); + } else if (CodeQueryFieldQueryTypeEnum.DICT.equalsValue(queryField.getQueryTypeEnum())) { + String stringBuilder = "AND INSTR(" + + form.getTableName() + "." + queryField.getColumnNameList().get(0) + + ",#{queryForm." + + queryField.getFieldName() + + "})"; + fieldMap.put("likeStr", stringBuilder); + } + else { + fieldMap.put("columnName", queryField.getColumnNameList().get(0)); + } + } + + variablesMap.put("queryFields", finalQueryFiledList); + variablesMap.put("daoClassName", form.getBasic().getJavaPackageName() + ".dao." + form.getBasic().getModuleName() + "Dao"); + return variablesMap; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/QueryFormVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/QueryFormVariableService.java new file mode 100644 index 0000000..aebd8ce --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/QueryFormVariableService.java @@ -0,0 +1,126 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.domain; + +import cn.hutool.core.bean.BeanUtil; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeQueryFieldQueryTypeEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeQueryField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class QueryFormVariableService extends CodeGenerateBaseVariableService { + + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + ImmutablePair, List>> packageListAndFields = getPackageListAndFields(form); + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".domain.form"); + variablesMap.put("importPackageList", packageListAndFields.getLeft()); + variablesMap.put("fields", packageListAndFields.getRight()); + return variablesMap; + } + + + public ImmutablePair, List>> getPackageListAndFields(CodeGeneratorConfigForm form) { + + List fields = form.getQueryFields(); + + HashSet packageList = new HashSet<>(); + + /** + * 1、LocalDate、LocalDateTime、BigDecimal 类型的包名 + * 2、排序 + */ + + List> finalFieldList = new ArrayList<>(); + + for (CodeQueryField field : fields) { + + // CodeField 和 InsertAndUpdateField 合并 + Map finalFieldMap = BeanUtil.beanToMap(field); + finalFieldMap.putAll(BeanUtil.beanToMap(field)); + + String queryTypeEnumStr = field.getQueryTypeEnum(); + CodeQueryFieldQueryTypeEnum queryTypeEnum = SmartEnumUtil.getEnumByValue(queryTypeEnumStr, CodeQueryFieldQueryTypeEnum.class); + if (queryTypeEnum == null) { + continue; + } + + String apiModelProperty = "@Schema(description = \"" + field.getLabel() + "\")"; + finalFieldMap.put("apiModelProperty", apiModelProperty); + packageList.add("import io.swagger.v3.oas.annotations.media.Schema;"); + + CodeField codeField = null; + + switch (queryTypeEnum) { + case EQUAL: + codeField = getCodeFieldByColumnName(field.getColumnNameList().get(0), form); + if (codeField == null) { + finalFieldMap.put("javaType", "String"); + } else { + finalFieldMap.put("javaType", codeField.getJavaType()); + } + break; + case DATE_RANGE: + case DATE: + packageList.add("import java.time.LocalDate;"); + finalFieldMap.put("javaType", "LocalDate"); + break; + case ENUM: + codeField = getCodeFieldByColumnName(field.getColumnNameList().get(0), form); + if (codeField == null) { + continue; + } + + packageList.add("import net.lab1024.sa.base.common.swagger.SchemaEnum;"); + packageList.add("import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;"); + packageList.add("import " + form.getBasic().getJavaPackageName() + ".constant." + codeField.getEnumName() + ";"); + + //enum check + String checkEnum = "@CheckEnum(value = " + codeField.getEnumName() + ".class, message = \"" + codeField.getLabel() + " 错误\")"; + finalFieldMap.put("apiModelProperty", "@SchemaEnum(value = " + codeField.getEnumName() + ".class, desc = \"" + codeField.getLabel() + "\")"); + finalFieldMap.put("checkEnum", checkEnum); + finalFieldMap.put("isEnum", true); + + finalFieldMap.put("javaType", codeField.getJavaType()); + break; + case DICT: + codeField = getCodeFieldByColumnName(field.getColumnNameList().get(0), form); + if (SmartStringUtil.isNotEmpty(codeField.getDict())) { + finalFieldMap.put("dict", "\n @JsonDeserialize(using = DictValueVoDeserializer.class)"); + packageList.add("import com.fasterxml.jackson.databind.annotation.JsonDeserialize;"); + packageList.add("import net.lab1024.sa.base.common.json.deserializer.DictValueVoDeserializer;"); + } + finalFieldMap.put("javaType", "String"); + default: + finalFieldMap.put("javaType", "String"); + } + + finalFieldList.add(finalFieldMap); + } + + // lombok + packageList.add("import lombok.Data;"); + packageList.add("import lombok.EqualsAndHashCode;"); + + List packageNameList = packageList.stream().filter(Objects::nonNull).sorted().collect(Collectors.toList()); + return ImmutablePair.of(packageNameList, finalFieldList); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/UpdateFormVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/UpdateFormVariableService.java new file mode 100644 index 0000000..a5089da --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/UpdateFormVariableService.java @@ -0,0 +1,143 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.domain; + +import cn.hutool.core.bean.BeanUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeFrontComponentEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdate; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class UpdateFormVariableService extends CodeGenerateBaseVariableService { + + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + CodeInsertAndUpdate insertAndUpdate = form.getInsertAndUpdate(); + return insertAndUpdate != null && insertAndUpdate.getIsSupportInsertAndUpdate() != null && insertAndUpdate.getIsSupportInsertAndUpdate(); + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + Map fieldMap = getFieldMap(form); + List updateFieldList = form.getInsertAndUpdate().getFieldList().stream().filter(e -> { + boolean isUpdate = Boolean.TRUE.equals(e.getUpdateFlag()); + CodeField codeField = fieldMap.get(e.getColumnName()); + if (codeField == null) { + return false; + } + + if (Boolean.TRUE.equals(codeField.getPrimaryKeyFlag())) { + e.setRequiredFlag(true); + } + + return isUpdate || Boolean.TRUE.equals(codeField.getPrimaryKeyFlag()); + } + + ).collect(Collectors.toList()); + + ImmutablePair, List>> packageListAndFields = getPackageListAndFields(updateFieldList, form); + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".domain.form"); + variablesMap.put("importPackageList", packageListAndFields.getLeft()); + variablesMap.put("fields", packageListAndFields.getRight()); + + return variablesMap; + } + + public ImmutablePair, List>> getPackageListAndFields(List fields, CodeGeneratorConfigForm form) { + if (CollectionUtils.isEmpty(fields)) { + return ImmutablePair.of(new ArrayList<>(), new ArrayList<>()); + } + + Map fieldMap = getFieldMap(form); + HashSet packageList = new HashSet<>(); + + + /** + * 1、LocalDate、LocalDateTime、BigDecimal 类型的包名 + * 2、排序 + */ + + List> finalFieldList = new ArrayList<>(); + + for (CodeInsertAndUpdateField field : fields) { + CodeField codeField = fieldMap.get(field.getColumnName()); + if (codeField == null) { + continue; + } + + // CodeField 和 InsertAndUpdateField 合并 + Map finalFieldMap = BeanUtil.beanToMap(field); + finalFieldMap.putAll(BeanUtil.beanToMap(codeField)); + + // 枚举 + if (SmartStringUtil.isNotEmpty(codeField.getEnumName())) { + packageList.add("import net.lab1024.sa.base.common.swagger.SchemaEnum;"); + packageList.add("import net.lab1024.sa.base.common.validator.enumeration.CheckEnum;"); + packageList.add("import " + form.getBasic().getJavaPackageName() + ".constant." + codeField.getEnumName() + ";"); + + //enum check + String checkEnumPrefix = "@CheckEnum(value = " + codeField.getEnumName() + ".class, message = \"" + codeField.getLabel() + " 错误\""; + String checkEnum = checkEnumPrefix + (field.getRequiredFlag() ? ", required = true)" : ")"); + + finalFieldMap.put("apiModelProperty", "@SchemaEnum(value = " + codeField.getEnumName() + ".class, desc = \"" + codeField.getLabel() + "\")"); + finalFieldMap.put("checkEnum", checkEnum); + finalFieldMap.put("isEnum", true); + + } else { + String prefix = "@Schema(description = \"" + codeField.getLabel() + "\""; + String apiModelProperty = prefix + (field.getRequiredFlag() ? ", requiredMode = Schema.RequiredMode.REQUIRED)" : ")"); + finalFieldMap.put("apiModelProperty", apiModelProperty); + + packageList.add("import io.swagger.v3.oas.annotations.media.Schema;"); + + if (Boolean.TRUE.equals(field.getRequiredFlag())) { + String notEmptyPrefix = "String".equals(codeField.getJavaType()) ? "@NotBlank" : "@NotNull"; + finalFieldMap.put("notEmpty", "\n " + notEmptyPrefix + "(message = \"" + codeField.getLabel() + " 不能为空\")"); + packageList.add("String".equals(codeField.getJavaType()) ? "import jakarta.validation.constraints.NotBlank;" : "import jakarta.validation.constraints.NotNull;"); + } + } + + + //字典 + if (SmartStringUtil.isNotEmpty(codeField.getDict())) { + finalFieldMap.put("dict", "\n @JsonDeserialize(using = DictValueVoDeserializer.class)"); + packageList.add("import com.fasterxml.jackson.databind.annotation.JsonDeserialize;"); + packageList.add("import net.lab1024.sa.base.common.json.deserializer.DictValueVoDeserializer;"); + } + + //文件上传 + if (CodeFrontComponentEnum.FILE_UPLOAD.equalsValue(field.getFrontComponent())) { + finalFieldMap.put("file", "\n @JsonDeserialize(using = FileKeyVoDeserializer.class)"); + packageList.add("import com.fasterxml.jackson.databind.annotation.JsonDeserialize;"); + packageList.add("import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer;"); + } + + packageList.add(getJavaPackageName(codeField.getJavaType())); + finalFieldList.add(finalFieldMap); + } + + + // lombok + packageList.add("import lombok.Data;"); + + List packageNameList = packageList.stream().filter(Objects::nonNull).collect(Collectors.toList()); + Collections.sort(packageNameList); + return ImmutablePair.of(packageNameList, finalFieldList); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/VOVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/VOVariableService.java new file mode 100644 index 0000000..4fe381c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/backend/domain/VOVariableService.java @@ -0,0 +1,104 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.backend.domain; + +import cn.hutool.core.bean.BeanUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeTableField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.tuple.ImmutablePair; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class VOVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + Map fieldMap = getFieldMap(form); + List updateFieldList = form.getTableFields().stream().filter(e -> Boolean.TRUE.equals(e.getShowFlag())).collect(Collectors.toList()); + + ImmutablePair, List>> packageListAndFields = getPackageListAndFields(updateFieldList, form); + + variablesMap.put("packageName", form.getBasic().getJavaPackageName() + ".domain.vo"); + variablesMap.put("importPackageList", packageListAndFields.getLeft()); + variablesMap.put("fields", packageListAndFields.getRight()); + + return variablesMap; + } + + public ImmutablePair, List>> getPackageListAndFields(List fields, CodeGeneratorConfigForm form) { + if (CollectionUtils.isEmpty(fields)) { + return ImmutablePair.of(new ArrayList<>(), new ArrayList<>()); + } + + Map fieldMap = getFieldMap(form); + HashSet packageList = new HashSet<>(); + + + /** + * 1、LocalDate、LocalDateTime、BigDecimal 类型的包名 + * 2、排序 + */ + + List> finalFieldList = new ArrayList<>(); + + for (CodeTableField field : fields) { + CodeField codeField = fieldMap.get(field.getColumnName()); + if (codeField == null) { + continue; + } + + // CodeField 和 CodeTableField 合并 + Map finalFieldMap = BeanUtil.beanToMap(field); + finalFieldMap.putAll(BeanUtil.beanToMap(codeField)); + + // 枚举 + if (SmartStringUtil.isNotEmpty(codeField.getEnumName())) { + packageList.add("import net.lab1024.sa.base.common.swagger.SchemaEnum;"); + packageList.add("import " + form.getBasic().getJavaPackageName() + ".constant." + codeField.getEnumName() + ";"); + + finalFieldMap.put("apiModelProperty", "@SchemaEnum(value = " + codeField.getEnumName() + ".class, desc = \"" + codeField.getLabel() + "\")"); + finalFieldMap.put("isEnum", true); + + } else { + String apiModelProperty = "@Schema(description = \"" + codeField.getLabel() + "\")"; + finalFieldMap.put("apiModelProperty", apiModelProperty); + + packageList.add("import io.swagger.v3.oas.annotations.media.Schema;"); + } + + //文件上传 + if (isFile(field.getColumnName(), form)) { + finalFieldMap.put("file", "\n @JsonSerialize(using = FileKeyVoSerializer.class)"); + packageList.add("import com.fasterxml.jackson.databind.annotation.JsonSerialize;"); + packageList.add("import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer;"); + } + + packageList.add(getJavaPackageName(codeField.getJavaType())); + finalFieldList.add(finalFieldMap); + } + + + // lombok + packageList.add("import lombok.Data;"); + + List packageNameList = packageList.stream().filter(Objects::nonNull).collect(Collectors.toList()); + Collections.sort(packageNameList); + return ImmutablePair.of(packageNameList, finalFieldList); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ApiVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ApiVariableService.java new file mode 100644 index 0000000..98f678d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ApiVariableService.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.front; + +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; + +import java.util.*; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class ApiVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + return variablesMap; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ConstVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ConstVariableService.java new file mode 100644 index 0000000..5b50647 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ConstVariableService.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.front; + +import cn.hutool.core.bean.BeanUtil; +import com.google.common.base.CaseFormat; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class ConstVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + List> enumList = new ArrayList<>(); + List enumFiledList = form.getFields().stream().filter(e -> SmartStringUtil.isNotBlank(e.getEnumName())).collect(Collectors.toList()); + for (CodeField codeField : enumFiledList) { + Map beanToMap = BeanUtil.beanToMap(codeField); + String upperUnderscoreEnum = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, codeField.getEnumName()); + beanToMap.put("upperUnderscoreEnum", upperUnderscoreEnum); + enumList.add(beanToMap); + } + variablesMap.put("enumList", enumList); + return variablesMap; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/FormVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/FormVariableService.java new file mode 100644 index 0000000..0a8498a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/FormVariableService.java @@ -0,0 +1,81 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.front; + +import cn.hutool.core.bean.BeanUtil; +import com.google.common.base.CaseFormat; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeFrontComponentEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; + +import java.util.*; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class FormVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + List> fieldsVariableList = new ArrayList<>(); + List fieldList = form.getInsertAndUpdate().getFieldList(); + + HashSet frontImportSet = new HashSet<>(); + + for (CodeInsertAndUpdateField field : fieldList) { + // 不存在 添加 和 更新 + if (!(field.getInsertFlag() || field.getUpdateFlag())) { + continue; + } + + Map objectMap = BeanUtil.beanToMap(field); + + CodeField codeField = getCodeFieldByColumnName(field.getColumnName(), form); + if (codeField == null) { + continue; + } + objectMap.put("label", codeField.getLabel()); + objectMap.put("fieldName", codeField.getFieldName()); + objectMap.put("dict", codeField.getDict()); + + if (SmartStringUtil.isNotBlank(codeField.getEnumName())) { + String upperUnderscoreEnum = CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, codeField.getEnumName()); + objectMap.put("upperUnderscoreEnum", upperUnderscoreEnum); + } + + fieldsVariableList.add(objectMap); + + if (CodeFrontComponentEnum.ENUM_SELECT.equalsValue(field.getFrontComponent())) { + frontImportSet.add("import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';"); + } + + if (CodeFrontComponentEnum.BOOLEAN_SELECT.equalsValue(field.getFrontComponent())) { + frontImportSet.add("import BooleanSelect from '/@/components/framework/boolean-select/index.vue';"); + } + + if (CodeFrontComponentEnum.DICT_SELECT.equalsValue(field.getFrontComponent())) { + frontImportSet.add("import DictSelect from '/@/components/support/dict-select/index.vue';"); + frontImportSet.add("import { DICT_CODE_ENUM } from '/@/constants/support/dict-const.js';"); + } + + if (CodeFrontComponentEnum.FILE_UPLOAD.equalsValue(field.getFrontComponent())) { + frontImportSet.add("import { FILE_FOLDER_TYPE_ENUM } from '/@/constants/support/file-const';"); + frontImportSet.add("import FileUpload from '/@/components/support/file-upload/index.vue';"); + } + } + + variablesMap.put("formFields", fieldsVariableList); + variablesMap.put("frontImportList", new ArrayList<>(frontImportSet)); + + return variablesMap; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ListVariableService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ListVariableService.java new file mode 100644 index 0000000..630771c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/service/variable/front/ListVariableService.java @@ -0,0 +1,103 @@ +package net.lab1024.sa.base.module.support.codegenerator.service.variable.front; + +import cn.hutool.core.bean.BeanUtil; +import com.google.common.base.CaseFormat; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeFrontComponentEnum; +import net.lab1024.sa.base.module.support.codegenerator.constant.CodeQueryFieldQueryTypeEnum; +import net.lab1024.sa.base.module.support.codegenerator.domain.form.CodeGeneratorConfigForm; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeInsertAndUpdateField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeQueryField; +import net.lab1024.sa.base.module.support.codegenerator.domain.model.CodeTableField; +import net.lab1024.sa.base.module.support.codegenerator.service.variable.CodeGenerateBaseVariableService; + +import java.util.*; + +/** + * @Author wzh + * @Date 2022/9/29 17:20:41 + */ + +public class ListVariableService extends CodeGenerateBaseVariableService { + + @Override + public boolean isSupport(CodeGeneratorConfigForm form) { + return true; + } + + @Override + public Map getInjectVariablesMap(CodeGeneratorConfigForm form) { + Map variablesMap = new HashMap<>(); + + + HashSet frontImportSet = new HashSet<>(); + frontImportSet.add("import " + CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, form.getBasic().getModuleName()) + "Form from './" + CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_HYPHEN, form.getBasic().getModuleName()) + "-form.vue';"); + + // 查询参数 + List> queryVariable = new ArrayList<>(); + List queryFields = form.getQueryFields(); + + for (CodeQueryField queryField : queryFields) { + Map objectMap = BeanUtil.beanToMap(queryField); + + CodeField codeField = getCodeFieldByColumnName(queryField.getColumnNameList().get(0), form); + + if (CodeQueryFieldQueryTypeEnum.ENUM.equalsValue(queryField.getQueryTypeEnum())) { + objectMap.put("frontEnumName", codeField.getEnumName()); + frontImportSet.add("import SmartEnumSelect from '/@/components/framework/smart-enum-select/index.vue';"); + } + + if (CodeQueryFieldQueryTypeEnum.DICT.equalsValue(queryField.getQueryTypeEnum())) { + objectMap.put("dict", codeField.getDict()); + frontImportSet.add("import DictSelect from '/@/components/support/dict-select/index.vue';"); + } + + if (CodeQueryFieldQueryTypeEnum.DATE_RANGE.equalsValue(queryField.getQueryTypeEnum())) { + frontImportSet.add("import { defaultTimeRanges } from '/@/lib/default-time-ranges';"); + } + queryVariable.add(objectMap); + } + + // 表格列表 + List> listVariable = new ArrayList<>(); + // 过滤掉不显示的字段 + List tableFields = form.getTableFields().stream().filter(CodeTableField::getShowFlag).toList(); + + for (CodeTableField tableField : tableFields) { + Map objectMap = BeanUtil.beanToMap(tableField); + objectMap.put("fieldName", tableField.getFieldName()); + + CodeField codeField = getCodeFieldByColumnName(tableField.getColumnName(), form); + if (codeField == null) { + continue; + } + + // 是否存在字典 + if (SmartStringUtil.isNotBlank(codeField.getDict())) { + objectMap.put("dict", codeField.getDict()); + frontImportSet.add("import { DICT_CODE_ENUM } from '/@/constants/support/dict-const.js';"); + frontImportSet.add("import DictLabel from '/@/components/support/dict-label/index.vue';"); + } + + CodeInsertAndUpdateField codeInsertAndUpdateField = form.getInsertAndUpdate().getFieldList().stream().filter(e -> SmartStringUtil.equals(tableField.getColumnName(), e.getColumnName())).findFirst().orElse(null); + if (codeInsertAndUpdateField == null) { + continue; + } + + // 是否存在上传组件 + if (CodeFrontComponentEnum.FILE_UPLOAD.equalsValue(codeInsertAndUpdateField.getFrontComponent())) { + objectMap.put("frontComponent", codeInsertAndUpdateField.getFrontComponent()); + frontImportSet.add("import FilePreview from '/@/components/support/file-preview/index.vue';"); + } + + listVariable.add(objectMap); + } + + variablesMap.put("queryFields", queryVariable); + variablesMap.put("listFields", listVariable); + variablesMap.put("frontImportList", new ArrayList<>(frontImportSet)); + + return variablesMap; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/util/CodeGeneratorTool.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/util/CodeGeneratorTool.java new file mode 100644 index 0000000..4532e19 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/codegenerator/util/CodeGeneratorTool.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.module.support.codegenerator.util; + +import com.google.common.base.CaseFormat; +import net.lab1024.sa.base.common.constant.StringConst; + +/** + * 代码生成 velocity 工具类 + * + * @Author wzh + * @Date 2022/9/30 19:02:17 + */ + +public class CodeGeneratorTool { + + /** + * 小写驼峰,转为大写驼峰 + */ + public String lowerCamel2UpperCamel(String str) { + if (str == null) { + return StringConst.EMPTY; + } + return CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_CAMEL, str); + } + + /** + * 小写驼峰,转为小写中划线 + */ + public String lowerCamel2LowerHyphen(String str) { + if (str == null) { + return StringConst.EMPTY; + } + return CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_HYPHEN, str); + } + + + /** + * 去掉 注释 枚举类型 + */ + public String removeEnumDesc(String str) { + if (str == null) { + return StringConst.EMPTY; + } + + int index = str.indexOf("["); + if (index == -1) { + index = str.indexOf("【"); + } + + if (index == -1) { + return str; + } + + return str.substring(0, index - 1); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigController.java new file mode 100644 index 0000000..f0636ea --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigController.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.base.module.support.config; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.config.domain.ConfigVO; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * 配置 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Tag(name = SwaggerTagConst.Support.CONFIG) +@RestController +public class ConfigController extends SupportBaseController { + + @Resource + private ConfigService configService; + + @Operation(summary = "查询配置详情 @author 卓大") + @GetMapping("/config/queryByKey") + public ResponseDTO queryByKey(@RequestParam String configKey) { + return ResponseDTO.ok(configService.getConfig(configKey)); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigDao.java new file mode 100644 index 0000000..b155fad --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigDao.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.base.module.support.config; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.config.domain.ConfigEntity; +import net.lab1024.sa.base.module.support.config.domain.ConfigQueryForm; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 系统参数配置 t_config Dao层 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Mapper +public interface ConfigDao extends BaseMapper { + + /** + * 分页查询系统配置 + * + */ + List queryByPage(Page page, @Param("query") ConfigQueryForm queryForm); + + /** + * 根据key查询获取数据 + * + */ + ConfigEntity selectByKey(String key); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigKeyEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigKeyEnum.java new file mode 100644 index 0000000..036cb18 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigKeyEnum.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.module.support.config; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 系统配置常量类 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Getter +@AllArgsConstructor +public enum ConfigKeyEnum implements BaseEnum { + + /** + * 万能密码 + */ + SUPER_PASSWORD("super_password", "万能密码"), + + LEVEL3_PROTECT_CONFIG("level3_protect_config", "三级等保配置"), + ; + + private final String value; + + private final String desc; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigService.java new file mode 100644 index 0000000..e8f9c35 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/ConfigService.java @@ -0,0 +1,184 @@ +package net.lab1024.sa.base.module.support.config; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.constant.ReloadConst; +import net.lab1024.sa.base.module.support.config.domain.*; +import net.lab1024.sa.base.module.support.reload.core.annoation.SmartReload; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 系统配置业务类 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Slf4j +@Service +public class ConfigService { + + /** + * 一个简单的系统配置缓存 + */ + private final ConcurrentHashMap CONFIG_CACHE = new ConcurrentHashMap<>(); + + @Resource + private ConfigDao configDao; + + @SmartReload(ReloadConst.CONFIG_RELOAD) + public void configReload(String param) { + this.loadConfigCache(); + } + + /** + * 初始化系统设置缓存 + */ + @PostConstruct + private void loadConfigCache() { + CONFIG_CACHE.clear(); + List entityList = configDao.selectList(null); + if (CollectionUtils.isEmpty(entityList)) { + return; + } + entityList.forEach(entity -> this.CONFIG_CACHE.put(entity.getConfigKey().toLowerCase(), entity)); + log.info("################# 系统配置缓存初始化完毕:{} ###################", CONFIG_CACHE.size()); + } + + /** + * 刷新系统设置缓存 + */ + private void refreshConfigCache(Long configId) { + // 重新查询 加入缓存 + ConfigEntity configEntity = configDao.selectById(configId); + if (null == configEntity) { + return; + } + this.CONFIG_CACHE.put(configEntity.getConfigKey().toLowerCase(), configEntity); + } + + /** + * 分页查询系统配置 + * + */ + public ResponseDTO> queryConfigPage(ConfigQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List entityList = configDao.queryByPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, entityList, ConfigVO.class); + return ResponseDTO.ok(pageResult); + } + + /** + * 查询配置缓存 + * + */ + public ConfigVO getConfig(ConfigKeyEnum configKey) { + return this.getConfig(configKey.getValue()); + } + + /** + * 查询配置缓存 + * + */ + public ConfigVO getConfig(String configKey) { + if (StrUtil.isBlank(configKey)) { + return null; + } + ConfigEntity entity = this.CONFIG_CACHE.get(configKey.toLowerCase()); + return SmartBeanUtil.copy(entity, ConfigVO.class); + } + + /** + * 查询配置缓存参数 + * + */ + public String getConfigValue(ConfigKeyEnum configKey) { + ConfigVO config = this.getConfig(configKey); + return config == null ? null : config.getConfigValue(); + } + + /** + * 根据参数key查询 并转换为对象 + * + */ + public T getConfigValue2Obj(ConfigKeyEnum configKey, Class clazz) { + String configValue = this.getConfigValue(configKey); + return JSON.parseObject(configValue, clazz); + } + + /** + * 添加系统配置 + * + */ + public ResponseDTO add(ConfigAddForm configAddForm) { + ConfigEntity entity = configDao.selectByKey(configAddForm.getConfigKey()); + if (null != entity) { + return ResponseDTO.error(UserErrorCode.ALREADY_EXIST); + } + entity = SmartBeanUtil.copy(configAddForm, ConfigEntity.class); + configDao.insert(entity); + + // 刷新缓存 + this.refreshConfigCache(entity.getConfigId()); + return ResponseDTO.ok(); + } + + /** + * 更新系统配置 + * + */ + public ResponseDTO updateConfig(ConfigUpdateForm updateDTO) { + Long configId = updateDTO.getConfigId(); + ConfigEntity entity = configDao.selectById(configId); + if (null == entity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + ConfigEntity alreadyEntity = configDao.selectByKey(updateDTO.getConfigKey()); + if (null != alreadyEntity && !Objects.equals(configId, alreadyEntity.getConfigId())) { + return ResponseDTO.error(UserErrorCode.ALREADY_EXIST, "config key 已存在"); + } + + // 更新数据 + entity = SmartBeanUtil.copy(updateDTO, ConfigEntity.class); + configDao.updateById(entity); + + // 刷新缓存 + this.refreshConfigCache(configId); + return ResponseDTO.ok(); + } + + /** + * 更新系统配置 + * + */ + public ResponseDTO updateValueByKey(ConfigKeyEnum key, String value) { + ConfigVO config = this.getConfig(key); + if (null == config) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + // 更新数据 + Long configId = config.getConfigId(); + ConfigEntity entity = new ConfigEntity(); + entity.setConfigId(configId); + entity.setConfigValue(value); + configDao.updateById(entity); + + // 刷新缓存 + this.refreshConfigCache(configId); + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigAddForm.java new file mode 100644 index 0000000..375ff4d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigAddForm.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.base.module.support.config.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 添加配置表单 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Data +public class ConfigAddForm { + + @Schema(description = "参数key") + @NotBlank(message = "参数key不能为空") + @Length(max = 255, message = "参数key最多255个字符") + private String configKey; + + @Schema(description = "参数的值") + @NotBlank(message = "参数的值不能为空") + @Length(max = 60000, message = "参数的值最多60000个字符") + private String configValue; + + @Schema(description = "参数名称") + @NotBlank(message = "参数名称不能为空") + @Length(max = 255, message = "参数名称最多255个字符") + private String configName; + + @Schema(description = "备注") + @Length(max = 255, message = "备注最多255个字符") + private String remark; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigEntity.java new file mode 100644 index 0000000..5545f33 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigEntity.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.module.support.config.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 系统配置参数 实体类 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Data +@TableName("t_config") +public class ConfigEntity { + + @TableId(type = IdType.AUTO) + private Long configId; + + /** + * 参数key + */ + private String configKey; + + /** + * 参数的值 + */ + private String configValue; + + /** + * 参数名称 + */ + private String configName; + + /** + * 备注 + */ + private String remark; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigQueryForm.java new file mode 100644 index 0000000..4862c13 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigQueryForm.java @@ -0,0 +1,20 @@ +package net.lab1024.sa.base.module.support.config.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +/** + * 分页查询 系统配置 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Data +public class ConfigQueryForm extends PageParam { + + @Schema(description = "参数KEY") + @Length(max = 50, message = "参数Key最多50字符") + private String configKey; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigUpdateForm.java new file mode 100644 index 0000000..28bef4d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.base.module.support.config.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 配置更新表单 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Data +public class ConfigUpdateForm extends ConfigAddForm { + + @Schema(description = "configId") + @NotNull(message = "configId不能为空") + private Long configId; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigVO.java new file mode 100644 index 0000000..1325ac4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/config/domain/ConfigVO.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.module.support.config.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 配置信息 + * + * @Author wzh + * @Date 2022-03-14 20:46:27 + */ +@Data +public class ConfigVO { + @Schema(description = "主键") + private Long configId; + + @Schema(description = "参数key") + private String configKey; + + @Schema(description = "参数的值") + private String configValue; + + @Schema(description = "参数名称") + private String configName; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "上次修改时间") + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/DataMasking.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/DataMasking.java new file mode 100644 index 0000000..c3847d7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/DataMasking.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.datamasking; + +import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import net.lab1024.sa.base.common.json.serializer.DataMaskingSerializer; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 脱敏注解 + * + * @author 罗伊 + * @description: + * @date 2024/7/21 4:39 下午 + */ +@Target(ElementType.FIELD) +@Retention(RetentionPolicy.RUNTIME) +@JacksonAnnotationsInside +@JsonSerialize(using = DataMaskingSerializer.class, nullsUsing = DataMaskingSerializer.class) +public @interface DataMasking { + + DataMaskingTypeEnum value() default DataMaskingTypeEnum.COMMON; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/DataMaskingTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/DataMaskingTypeEnum.java new file mode 100644 index 0000000..b925aa7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/DataMaskingTypeEnum.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.base.module.support.datamasking; + +import cn.hutool.core.util.DesensitizedUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 脱敏数据类型 + * + * @Author wzh + * @Date 2024/8/1 + */ + +@AllArgsConstructor +@Getter +public enum DataMaskingTypeEnum { + + COMMON(null, "通用"), + PHONE(DesensitizedUtil.DesensitizedType.MOBILE_PHONE, "手机号"), + CHINESE_NAME(DesensitizedUtil.DesensitizedType.CHINESE_NAME, "中文名"), + ID_CARD(DesensitizedUtil.DesensitizedType.ID_CARD, "身份证号"), + FIXED_PHONE(DesensitizedUtil.DesensitizedType.FIXED_PHONE, "座机号"), + ADDRESS(DesensitizedUtil.DesensitizedType.ADDRESS, "地址"), + EMAIL(DesensitizedUtil.DesensitizedType.EMAIL, "电子邮件"), + PASSWORD(DesensitizedUtil.DesensitizedType.PASSWORD, "密码"), + CAR_LICENSE(DesensitizedUtil.DesensitizedType.CAR_LICENSE, "中国大陆车牌"), + BANK_CARD(DesensitizedUtil.DesensitizedType.BANK_CARD, "银行卡"), + USER_ID(DesensitizedUtil.DesensitizedType.USER_ID, "用户id"); + + + + private DesensitizedUtil.DesensitizedType type; + + private String desc; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/SmartDataMaskingUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/SmartDataMaskingUtil.java new file mode 100644 index 0000000..6144039 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datamasking/SmartDataMaskingUtil.java @@ -0,0 +1,213 @@ +package net.lab1024.sa.base.module.support.datamasking; + +import cn.hutool.core.util.DesensitizedUtil; +import cn.hutool.core.util.StrUtil; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; + +import java.beans.IntrospectionException; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 脱敏工具类 + * + * @Author wzh + * @Date 2024-07-23 21:38:52 + */ +public class SmartDataMaskingUtil { + + /** + * 类 加注解字段缓存 + */ + private static final ConcurrentHashMap, List> fieldMap = new ConcurrentHashMap<>(); + + public static String dataMasking(String value) { + if (StringUtils.isBlank(value)) { + return value; + } + + if (value.length() < 4) { + return StrUtil.hide(value, 0, value.length()); + } + + int valueLength = value.length(); + int startHideIndex = getHideStartIndex(valueLength); + int endHideIndex = getHideEndIndex(valueLength); + return StrUtil.hide(value, startHideIndex, endHideIndex); + } + + public static Object dataMasking(Object value, DataMaskingTypeEnum dataType) { + + if (value == null) { + return null; + } + + if (dataType == null) { + return dataMasking(String.valueOf(value)); + } + + switch (dataType) { + case PHONE: + return DesensitizedUtil.mobilePhone(String.valueOf(value)); + case CHINESE_NAME: + return DesensitizedUtil.chineseName(String.valueOf(value)); + case ID_CARD: + return DesensitizedUtil.idCardNum(String.valueOf(value), 6, 2); + case FIXED_PHONE: + return DesensitizedUtil.fixedPhone(String.valueOf(value)); + case ADDRESS: + return StrUtil.hide(String.valueOf(value), 6, String.valueOf(value).length() - 1); + case EMAIL: + return DesensitizedUtil.email(String.valueOf(value)); + case PASSWORD: + return DesensitizedUtil.password(String.valueOf(value)); + case CAR_LICENSE: + return DesensitizedUtil.carLicense(String.valueOf(value)); + case BANK_CARD: + return DesensitizedUtil.bankCard(String.valueOf(value)); + case USER_ID: + return DesensitizedUtil.userId(); + default: + return dataMasking(String.valueOf(value)); + } + } + + /** + * 批量脱敏 + */ + public static void dataMasking(Collection objectList) throws IntrospectionException, InvocationTargetException, IllegalAccessException { + if (CollectionUtils.isEmpty(objectList)) { + return; + } + + for (T object : objectList) { + dataMasking(object); + } + } + + + /** + * 单个脱敏 + */ + public static void dataMasking(T object) throws IntrospectionException, InvocationTargetException, IllegalAccessException { + Class tClass = object.getClass(); + List fieldList = getField(object); + for (Field field : fieldList) { + field.setAccessible(true); + String fieldValue = ""; + try { + PropertyDescriptor pd = new PropertyDescriptor(field.getName(), tClass); + Method getMethod = pd.getReadMethod(); + Object value = getMethod.invoke(object); + if (value != null) { + fieldValue = value.toString(); + } + } catch (Exception e) { + throw new RuntimeException(e); + } + if (StringUtils.isBlank(fieldValue)) { + continue; + } + int valueLength = fieldValue.length(); + int startHideIndex = getHideStartIndex(valueLength); + int endHideIndex = getHideEndIndex(valueLength); + try { + field.set(object, StrUtil.hide(fieldValue, startHideIndex, endHideIndex)); + } catch (Exception e1) { + throw new RuntimeException(e1); + } + } + } + + private static int getHideStartIndex(int totalLength) { + if (totalLength <= 4) { + return 1; + } else if (totalLength <= 6) { + return 1; + } else if (totalLength <= 10) { + return 2; + } else if (totalLength <= 18) { + return 3; + } else if (totalLength <= 27) { + return 5; + } else if (totalLength <= 34) { + return 7; + } else if (totalLength <= 41) { + return 9; + } else { + return 15; + } + } + + private static int getHideEndIndex(int totalLength) { + if (totalLength <= 4) { + return totalLength - 1; + } else if (totalLength <= 6) { + return totalLength - 2; + } else if (totalLength <= 10) { + return totalLength - 2; + } else if (totalLength <= 18) { + return totalLength - 4; + } else if (totalLength <= 27) { + return totalLength - 6; + } else if (totalLength <= 34) { + return totalLength - 8; + } else if (totalLength <= 41) { + return totalLength - 10; + } else { + return totalLength - 16; + } + } + + + public static List getField(Object object) throws IntrospectionException { + // 从缓存中查询 + Class tClass = object.getClass(); + List fieldList = fieldMap.get(tClass); + if (null != fieldList) { + return fieldList; + } + + // 这一段递归代码 是为了 从父类中获取属性 + Class tempClass = tClass; + fieldList = new ArrayList<>(); + while (tempClass != null) { + Field[] declaredFields = tempClass.getDeclaredFields(); + for (Field field : declaredFields) { + boolean stringField = false; + try { + PropertyDescriptor pd = new PropertyDescriptor(field.getName(), tClass); + Method getMethod = pd.getReadMethod(); + Type returnType = getMethod.getGenericReturnType(); + stringField = "java.lang.String".equals(returnType.getTypeName()); + } catch (Exception e) { + throw new RuntimeException(e); + } + if (field.isAnnotationPresent(DataMasking.class) && stringField) { + field.setAccessible(true); + fieldList.add(field); + } + } + tempClass = tempClass.getSuperclass(); + } + fieldMap.put(tClass, fieldList); + return fieldList; + } + + public static void main(String[] args) { + System.out.println(dataMasking("a", null)); + System.out.println(dataMasking("ab", null)); + System.out.println(dataMasking("abc", null)); + System.out.println(dataMasking("abcd", null)); + System.out.println(dataMasking("abcde", null)); + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldBigDecimal.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldBigDecimal.java new file mode 100644 index 0000000..f282a66 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldBigDecimal.java @@ -0,0 +1,18 @@ +package net.lab1024.sa.base.module.support.datatracer.annoation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 数据变动字段注解 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface DataTracerFieldBigDecimal { + int scale() default 2; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldDict.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldDict.java new file mode 100644 index 0000000..e5f11cc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldDict.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.base.module.support.datatracer.annoation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 字典的字段 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface DataTracerFieldDict { + + String dictCode(); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldEnum.java new file mode 100644 index 0000000..1bfc153 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldEnum.java @@ -0,0 +1,22 @@ +package net.lab1024.sa.base.module.support.datatracer.annoation; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 字段枚举 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface DataTracerFieldEnum { + + Class enumClass() default BaseEnum.class; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldLabel.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldLabel.java new file mode 100644 index 0000000..20cd74e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldLabel.java @@ -0,0 +1,23 @@ +package net.lab1024.sa.base.module.support.datatracer.annoation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 字段标签 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface DataTracerFieldLabel { + /** + * 本属性的注释信息 + * @return + */ + String value() default ""; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldSql.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldSql.java new file mode 100644 index 0000000..8e48f3a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/annoation/DataTracerFieldSql.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.base.module.support.datatracer.annoation; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 支持查询sql + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.FIELD) +public @interface DataTracerFieldSql { + + /** + * 关联字段名称 + * @return + */ + String relateColumn() default "id"; + + /** + * 关联显示的字段 + * @return + */ + String relateDisplayColumn() default ""; + /** + * 是否关联字段查询Mapper + * @return + */ + Class relateMapper() default BaseMapper.class; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/constant/DataTracerConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/constant/DataTracerConst.java new file mode 100644 index 0000000..b16306e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/constant/DataTracerConst.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.base.module.support.datatracer.constant; + +/** + * 常量 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +public class DataTracerConst { + + public static final String TAB = " "; + + public static final String SPLIT_LINE = "-----------------------------"; + + public static final String BLANK = " "; + public static final String SPLIT = ": "; + public static final String HTML_BR = "
"; + + public static final String INSERT = "新增"; + + public static final String DELETE = "删除"; + + public static final String UPDATE = "修改"; +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/constant/DataTracerTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/constant/DataTracerTypeEnum.java new file mode 100644 index 0000000..d25d410 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/constant/DataTracerTypeEnum.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.base.module.support.datatracer.constant; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 数据业务类型 + * + * @Author wzh + * @Date 2022-07-23 19:38:52- + */ +@AllArgsConstructor +@Getter +public enum DataTracerTypeEnum implements BaseEnum { + + /** + * 商品 + */ + GOODS(1, "商品"), + + /** + *通知公告 + */ + OA_NOTICE(2, "OA-通知公告"), + + /** + * 企业信息 + */ + OA_ENTERPRISE(3, "OA-企业信息"), + + /** + *通知公告 + */ + OA_LEAVE(4, "OA-请假申请"), + + ; + + private final Integer value; + + private final String desc; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/controller/DataTracerController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/controller/DataTracerController.java new file mode 100644 index 0000000..4690793 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/controller/DataTracerController.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.module.support.datatracer.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.datatracer.domain.form.DataTracerQueryForm; +import net.lab1024.sa.base.module.support.datatracer.domain.vo.DataTracerVO; +import net.lab1024.sa.base.module.support.datatracer.service.DataTracerService; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 数据变动记录 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Tag(name = SwaggerTagConst.Support.DATA_TRACER) +@RestController +public class DataTracerController extends SupportBaseController { + + @Resource + private DataTracerService dataTracerService; + + @Operation(summary = "分页查询业务操作日志 - @author 卓大") + @PostMapping("/dataTracer/query") + public ResponseDTO> query(@Valid @RequestBody DataTracerQueryForm queryForm) { + return dataTracerService.query(queryForm); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/dao/DataTracerDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/dao/DataTracerDao.java new file mode 100644 index 0000000..0a55b63 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/dao/DataTracerDao.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.datatracer.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.datatracer.domain.entity.DataTracerEntity; +import net.lab1024.sa.base.module.support.datatracer.domain.form.DataTracerQueryForm; +import net.lab1024.sa.base.module.support.datatracer.domain.vo.DataTracerVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * dao: t_data_tracker + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Mapper +public interface DataTracerDao extends BaseMapper { + + /** + * 操作记录查询 + * + */ + List selectRecord(@Param("dataId") Long dataId, @Param("dataType") Integer dataType); + + /** + * 分页查询 + * + */ + List query(Page page, @Param("query") DataTracerQueryForm queryForm); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/bo/DataTracerContentBO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/bo/DataTracerContentBO.java new file mode 100644 index 0000000..9f47abf --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/bo/DataTracerContentBO.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.module.support.datatracer.domain.bo; + +import lombok.Data; + +import java.lang.reflect.Field; + +/** + * 变动内容 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Data +public class DataTracerContentBO { + + /** + * 变动字段 + */ + private Field field; + + /** + * 变动字段的值 + */ + private Object fieldValue; + + /** + * 变动字段描述 + */ + private String fieldDesc; + + /** + * 变动内容 + */ + private String fieldContent; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/entity/DataTracerEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/entity/DataTracerEntity.java new file mode 100644 index 0000000..23c4c61 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/entity/DataTracerEntity.java @@ -0,0 +1,92 @@ +package net.lab1024.sa.base.module.support.datatracer.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; + +import java.time.LocalDateTime; + +/** + * 数据记录 实体 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Data +@TableName("t_data_tracer") +public class DataTracerEntity { + + @TableId(type = IdType.AUTO) + private Long dataTracerId; + /** + * 数据id + */ + private Long dataId; + /** + * 业务类型 + * {@link DataTracerTypeEnum} + */ + private Integer type; + + /** + * 内容 + */ + private String content; + + /** + * diff 差异:旧的数据 + */ + private String diffOld; + + /** + * 差异:新的数据 + */ + private String diffNew; + + /** + * 扩展字段 + */ + private String extraData; + + /** + * 用户 + */ + private Long userId; + + /** + * 用户类型 + */ + private Integer userType; + + /** + * 用户名 + */ + private String userName; + + /** + * 请求ip + */ + private String ip; + + /** + * 请求ip地区 + */ + private String ipRegion; + + /** + * 请求头 + */ + private String userAgent; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/form/DataTracerForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/form/DataTracerForm.java new file mode 100644 index 0000000..f1cfaa3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/form/DataTracerForm.java @@ -0,0 +1,51 @@ +package net.lab1024.sa.base.module.support.datatracer.domain.form; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; + +/** + * 数据变动表单 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class DataTracerForm { + + /** + * 业务id + */ + private Long dataId; + + /** + * 业务类型 + */ + private DataTracerTypeEnum type; + + /** + * 操作内容 + */ + private String content; + + /** + * diff 差异:旧的数据 + */ + private String diffOld; + + /** + * 差异:新的数据 + */ + private String diffNew; + + /** + * 扩展字段 + */ + private String extraData; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/form/DataTracerQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/form/DataTracerQueryForm.java new file mode 100644 index 0000000..9243cdc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/form/DataTracerQueryForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.module.support.datatracer.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; + +/** + * 查询表单 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Data +public class DataTracerQueryForm extends PageParam { + + @SchemaEnum(DataTracerTypeEnum.class) + private Integer type; + + @Schema(description = "业务id") + @NotNull(message = "业务id不能为空") + private Long dataId; + + @Schema(description = "关键字") + private String keywords; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/vo/DataTracerVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/vo/DataTracerVO.java new file mode 100644 index 0000000..bd6cc27 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/domain/vo/DataTracerVO.java @@ -0,0 +1,62 @@ +package net.lab1024.sa.base.module.support.datatracer.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; + +import java.time.LocalDateTime; + +/** + * 变动记录 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Data +public class DataTracerVO { + + @Schema(description = "日志id") + private Long dataTracerId; + + @Schema(description = "单据id") + private Long dataId; + + @SchemaEnum(value = DataTracerTypeEnum.class, desc = "业务类型") + private Integer type; + + @Schema(description = "操作内容") + private String content; + + @Schema(description = "diff 差异:旧的数据") + private String diffOld; + + @Schema(description = "差异:新的数据") + private String diffNew; + + @Schema(description = "扩展字段") + private String extraData; + + @Schema(description = "操作人") + private Long userId; + + @SchemaEnum(value = UserTypeEnum.class, desc = "用户类型") + private Integer userType; + + @Schema(description = "操作人名称") + private String userName; + + @Schema(description = "userAgent") + private String userAgent; + + @Schema(description = "ip") + private String ip; + + @Schema(description = "ip地区") + private String ipRegion; + + @Schema(description = "操作时间") + private LocalDateTime createTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/manager/DataTracerManger.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/manager/DataTracerManger.java new file mode 100644 index 0000000..4a32082 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/manager/DataTracerManger.java @@ -0,0 +1,16 @@ +package net.lab1024.sa.base.module.support.datatracer.manager; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.lab1024.sa.base.module.support.datatracer.dao.DataTracerDao; +import net.lab1024.sa.base.module.support.datatracer.domain.entity.DataTracerEntity; +import org.springframework.stereotype.Service; + +/** + * manager层 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Service +public class DataTracerManger extends ServiceImpl { +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/service/DataTracerChangeContentService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/service/DataTracerChangeContentService.java new file mode 100644 index 0000000..432096f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/service/DataTracerChangeContentService.java @@ -0,0 +1,454 @@ +package net.lab1024.sa.base.module.support.datatracer.service; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.json.JSONUtil; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.google.common.base.CaseFormat; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.util.SmartBigDecimalUtil; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.datatracer.annoation.*; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst; +import net.lab1024.sa.base.module.support.datatracer.domain.bo.DataTracerContentBO; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictDataVO; +import net.lab1024.sa.base.module.support.dict.service.DictService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.context.ApplicationContext; +import org.springframework.stereotype.Service; + +import java.beans.PropertyDescriptor; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.math.BigDecimal; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 数据变更内容 + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Slf4j +@Service +public class DataTracerChangeContentService { + + @Resource + private ApplicationContext applicationContext; + @Resource + private DictService dictService; + /** + * 字段描述缓存 + */ + private final ConcurrentHashMap fieldDescCacheMap = new ConcurrentHashMap<>(); + + /** + * 类 加注解字段缓存 + */ + private final ConcurrentHashMap, List> fieldMap = new ConcurrentHashMap<>(); + + /** + * 数据批量对比 + * + * @param oldObjectList 原始对象列表 + * @param newObjectList 新的对象列表 + * @param Class类型 + * @return 变更内容 + */ + public String getChangeContent(List oldObjectList, List newObjectList) { + boolean valid = this.valid(oldObjectList, newObjectList); + if (!valid) { + return ""; + } + String operateType = this.getOperateType(oldObjectList, newObjectList); + String operateContent = ""; + if (DataTracerConst.INSERT.equals(operateType) || DataTracerConst.DELETE.equals(operateType)) { + operateContent = this.getObjectListContent(newObjectList); + if (StringUtils.isEmpty(operateContent)) { + return ""; + } + return operateType + ":" + operateContent; + } + if (DataTracerConst.UPDATE.equals(operateType)) { + return this.getUpdateContentList(oldObjectList, newObjectList); + } + return operateContent; + } + + + /** + * 解析多个对象的变更,删除,新增 + * oldObject 为空 ,newObject 不为空 为新增 + * oldObject 不为空 ,newObject 不空 为删除 + * 都不为空为编辑 + * + * @param oldObject 原始对象 + * @param newObject 新对象 + * @return 变更内容 + */ + public String getChangeContent(Object oldObject, Object newObject) { + boolean valid = this.valid(oldObject, newObject); + if (!valid) { + return ""; + } + String operateType = this.getOperateType(oldObject, newObject); + String operateContent = ""; + if (DataTracerConst.INSERT.equals(operateType) || DataTracerConst.DELETE.equals(operateType)) { + operateContent = this.getAddDeleteContent(newObject); + } + if (DataTracerConst.UPDATE.equals(operateType)) { + operateContent = this.getUpdateContent(oldObject, newObject); + } + if (StringUtils.isEmpty(operateContent)) { + return ""; + } + return operateContent; + } + + /** + * 解析单个bean的内容 + * + * @param object 普通对象 + * @return 单个内容 + */ + public String getChangeContent(Object object) { + return this.getAddDeleteContent(object); + } + + // ---------------------------- 以下 是 私有private 方法 ---------------------------- + + /** + * 获取新增或删除操作内容 + * + * @param object 新增或删除的对象 + */ + private String getAddDeleteContent(Object object) { + List fields = this.getField(object); + Map beanParseMap = this.fieldParse(object, fields); + return this.getAddDeleteContent(beanParseMap); + } + + /** + * 单个对象变动内容 + * + * @param oldObjectList 旧的对象列表 + * @param newObjectList 新的对象列表 + * @return 拼接后的内容 + */ + private String getUpdateContentList(List oldObjectList, List newObjectList) { + String oldContent = this.getObjectListContent(oldObjectList); + String newContent = this.getObjectListContent(newObjectList); + if (oldContent.equals(newContent)) { + return ""; + } + if (StringUtils.isEmpty(oldContent) && StringUtils.isEmpty(newContent)) { + return ""; + } + return "【原数据】:
" + oldContent + "
" + "【新数据】:
" + newContent; + } + + /** + * 获取一个对象的内容信息 + * + * @param objectList 对象列表 + * @param 类型 + * @return 内容 + */ + private String getObjectListContent(List objectList) { + if (CollectionUtils.isEmpty(objectList)) { + return ""; + } + List fields = this.getField(objectList.get(0)); + List contentList = Lists.newArrayList(); + for (Object objItem : objectList) { + Map beanParseMap = this.fieldParse(objItem, fields); + contentList.add(this.getAddDeleteContent(beanParseMap)); + } + return StringUtils.join(contentList, "
"); + } + + private String getAddDeleteContent(Map beanParseMap) { + List contentList = new ArrayList<>(); + for (Entry entry : beanParseMap.entrySet()) { + DataTracerContentBO dataTracerContentBO = entry.getValue(); + boolean jsonFlag = JSONUtil.isTypeJSON(dataTracerContentBO.getFieldContent()); + String filedDesc = dataTracerContentBO.getFieldDesc(); + if (jsonFlag) { + contentList.add(filedDesc + "(请进入详情查看)"); + } else { + contentList.add(dataTracerContentBO.getFieldDesc() + ":" + dataTracerContentBO.getFieldContent()); + } + } + String operateContent = StringUtils.join(contentList, "
"); + if (StringUtils.isEmpty(operateContent)) { + return ""; + } + return operateContent; + } + + + /** + * 获取更新操作内容 + * + * @param oldObject 原始对象 + * @param newObject 新对象 + * @return + */ + private String getUpdateContent(T oldObject, T newObject) { + List fields = this.getField(oldObject); + List contentList = new ArrayList<>(); + Map oldBeanParseMap = this.fieldParse(oldObject, fields); + Map newBeanParseMap = this.fieldParse(newObject, fields); + //oldBeanParseMap与newBeanParseMap size一定相同 + for (Entry entry : oldBeanParseMap.entrySet()) { + String fieldName = entry.getKey(); + // 新旧对象内容 + DataTracerContentBO oldContentBO = entry.getValue(); + DataTracerContentBO newContentBO = newBeanParseMap.get(fieldName); + // fieldContent + String oldContent = oldContentBO == null || oldContentBO.getFieldContent() == null ? "" : oldContentBO.getFieldContent(); + String newContent = newContentBO == null || newContentBO.getFieldContent() == null ? "" : newContentBO.getFieldContent(); + + if (oldContent.equals(newContent)) { + continue; + } + String fieldDesc = oldContentBO.getFieldDesc(); + boolean jsonFlag = JSONUtil.isTypeJSON(oldContent) || JSONUtil.isTypeJSON(newContent); + if (jsonFlag) { + String content = fieldDesc + "【进入详情查看】"; + contentList.add(content); + continue; + } + String content = fieldDesc + ":" + "由【" + oldContent + "】变更为【" + newContent + "】"; + contentList.add(content); + } + if (CollectionUtils.isEmpty(contentList)) { + return ""; + } + String operateContent = StringUtils.join(contentList, "
"); + if (StringUtils.isEmpty(operateContent)) { + return ""; + } + return operateContent; + } + + + /** + * 接bean对象 + * + * @param object 对象 + * @param fields 字段 + * @return + */ + private Map fieldParse(Object object, List fields) { + if (fields == null || fields.isEmpty()) { + return new HashMap<>(); + } + //对象解析结果 + Map objectParse = new HashMap<>(16); + for (Field field : fields) { + field.setAccessible(true); + String desc = this.getFieldDesc(field); + if (StringUtils.isEmpty(desc)) { + continue; + } + DataTracerContentBO dataTracerContentBO = this.getFieldValue(field, object); + if (dataTracerContentBO != null) { + dataTracerContentBO.setFieldDesc(desc); + objectParse.put(field.getName(), dataTracerContentBO); + } + } + return objectParse; + } + + /** + * 获取字段值 + */ + private DataTracerContentBO getFieldValue(Field field, Object object) { + Object fieldValue = ""; + Class clazz = object.getClass(); + try { + PropertyDescriptor pd = new PropertyDescriptor(field.getName(), clazz); + Method get = pd.getReadMethod(); + fieldValue = get.invoke(object); + } catch (Exception e) { + log.error("bean operate log: reflect field value error " + field.getName()); + return null; + } + if (fieldValue == null) { + return null; + } + + String fieldContent = ""; + DataTracerFieldEnum dataTracerFieldEnum = field.getAnnotation(DataTracerFieldEnum.class); + DataTracerFieldSql dataTracerFieldSql = field.getAnnotation(DataTracerFieldSql.class); + DataTracerFieldDict dataTracerFieldDict = field.getAnnotation(DataTracerFieldDict.class); + if (dataTracerFieldEnum != null) { + if (fieldValue instanceof Collection) { + fieldContent = SmartEnumUtil.getEnumDescByValueList((Collection) fieldValue, dataTracerFieldEnum.enumClass()); + } else { + fieldContent = SmartEnumUtil.getEnumDescByValue(fieldValue, dataTracerFieldEnum.enumClass()); + } + } else if (dataTracerFieldDict != null) { + DictDataVO dictData = dictService.getDictData(dataTracerFieldDict.dictCode(), fieldValue.toString()); + fieldContent = dictData == null ? fieldValue.toString() : dictData.getDataLabel(); + } else if (dataTracerFieldSql != null) { + fieldContent = this.getRelateDisplayValue(fieldValue, dataTracerFieldSql); + } else if (fieldValue instanceof Date) { + fieldContent = DateUtil.formatDateTime((Date) fieldValue); + } else if (fieldValue instanceof LocalDateTime) { + fieldContent = LocalDateTimeUtil.formatNormal((LocalDateTime) fieldValue); + } else if (fieldValue instanceof LocalDate) { + fieldContent = LocalDateTimeUtil.formatNormal((LocalDate) fieldValue); + } else if (fieldValue instanceof BigDecimal) { + DataTracerFieldBigDecimal dataTracerFieldBigDecimal = field.getAnnotation(DataTracerFieldBigDecimal.class); + if (dataTracerFieldBigDecimal != null) { + BigDecimal value = SmartBigDecimalUtil.setScale((BigDecimal) fieldValue, dataTracerFieldBigDecimal.scale()); + fieldContent = value.toString(); + } + } else { + fieldContent = JSON.toJSONString(fieldValue); + } + DataTracerContentBO dataTracerContentBO = new DataTracerContentBO(); + dataTracerContentBO.setField(field); + dataTracerContentBO.setFieldValue(fieldValue); + dataTracerContentBO.setFieldContent(fieldContent); + return dataTracerContentBO; + } + + /** + * 获取关联字段的显示值 + */ + private String getRelateDisplayValue(Object fieldValue, DataTracerFieldSql dataTracerFieldSql) { + Class relateMapper = dataTracerFieldSql.relateMapper(); + BaseMapper mapper = applicationContext.getBean(relateMapper); + if (mapper == null) { + return ""; + } + String relateFieldValue = fieldValue.toString(); + QueryWrapper qw = new QueryWrapper(); + qw.select(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, dataTracerFieldSql.relateDisplayColumn())); + qw.in(CaseFormat.UPPER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, dataTracerFieldSql.relateColumn()), relateFieldValue); + List displayValue = mapper.selectObjs(qw); + if (CollectionUtils.isEmpty(displayValue)) { + return ""; + } + return SmartStringUtil.join(",", displayValue); + } + + /** + * 获取字段描述信息 优先 OperateField 没得话swagger判断 + */ + private String getFieldDesc(Field field) { + // 根据字段名称 从缓存中查询 + String fieldName = field.toGenericString(); + String desc = fieldDescCacheMap.get(fieldName); + if (null != desc) { + return desc; + } + DataTracerFieldLabel operateField = field.getAnnotation(DataTracerFieldLabel.class); + if (operateField != null) { + return operateField.value(); + } + fieldDescCacheMap.put(fieldName, desc); + return desc; + } + + /** + * 获取操作类型 + */ + private String getOperateType(Object oldObject, Object newObject) { + if (oldObject == null && newObject != null) { + return DataTracerConst.INSERT; + } + if (oldObject != null && newObject == null) { + return DataTracerConst.DELETE; + } + return DataTracerConst.UPDATE; + } + + /** + * 校验是否进行比对 + */ + private boolean valid(Object oldObject, Object newObject) { + if (oldObject == null && newObject == null) { + return false; + } + if (oldObject == null) { + return true; + } + if (newObject == null) { + return true; + } + String oldClass = oldObject.getClass().getName(); + String newClass = newObject.getClass().getName(); + return oldClass.equals(newClass); + } + + + /** + * 校验 + */ + private boolean valid(List oldObjectList, List newObjectList) { + if (CollectionUtils.isEmpty(oldObjectList) && CollectionUtils.isEmpty(newObjectList)) { + return false; + } + if (CollectionUtils.isEmpty(oldObjectList) && CollectionUtils.isNotEmpty(newObjectList)) { + return true; + } + if (CollectionUtils.isNotEmpty(oldObjectList) && CollectionUtils.isEmpty(newObjectList)) { + return true; + } + if (CollectionUtils.isNotEmpty(oldObjectList) && CollectionUtils.isNotEmpty(newObjectList)) { + T oldObject = oldObjectList.get(0); + T newObject = newObjectList.get(0); + String oldClass = oldObject.getClass().getName(); + String newClass = newObject.getClass().getName(); + return oldClass.equals(newClass); + } + return true; + } + + /** + * 查询 包含 file key 注解的字段 + * 使用缓存 + */ + private List getField(Object obj) { + // 从缓存中查询 + Class tClass = obj.getClass(); + List fieldList = fieldMap.get(tClass); + if (null != fieldList) { + return fieldList; + } + + // 这一段递归代码 是为了 从父类中获取属性 + Class tempClass = tClass; + fieldList = new ArrayList<>(); + while (tempClass != null) { + Field[] declaredFields = tempClass.getDeclaredFields(); + for (Field field : declaredFields) { + // 过虑出有注解字段 + if (!field.isAnnotationPresent(DataTracerFieldLabel.class)) { + continue; + } + field.setAccessible(true); + fieldList.add(field); + } + tempClass = tempClass.getSuperclass(); + } + fieldMap.put(tClass, fieldList); + return fieldList; + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/service/DataTracerService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/service/DataTracerService.java new file mode 100644 index 0000000..aa20805 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/datatracer/service/DataTracerService.java @@ -0,0 +1,224 @@ +package net.lab1024.sa.base.module.support.datatracer.service; + + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartIpUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerConst; +import net.lab1024.sa.base.module.support.datatracer.constant.DataTracerTypeEnum; +import net.lab1024.sa.base.module.support.datatracer.dao.DataTracerDao; +import net.lab1024.sa.base.module.support.datatracer.domain.entity.DataTracerEntity; +import net.lab1024.sa.base.module.support.datatracer.domain.form.DataTracerForm; +import net.lab1024.sa.base.module.support.datatracer.domain.form.DataTracerQueryForm; +import net.lab1024.sa.base.module.support.datatracer.domain.vo.DataTracerVO; +import net.lab1024.sa.base.module.support.datatracer.manager.DataTracerManger; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据变动记录 Service + * + * @Author wzh + * @Date 2022-07-23 19:38:52 + */ +@Slf4j +@Service +public class DataTracerService { + + @Resource + private DataTracerDao dataTracerDao; + + @Resource + private DataTracerManger dataTracerManger; + + @Resource + private DataTracerChangeContentService dataTracerChangeContentService; + + /** + * 获取变更内容 + * + * @param object + * @return + */ + public String getChangeContent(Object object) { + return dataTracerChangeContentService.getChangeContent(object); + } + + /** + * 获取变更内容 + */ + public String getChangeContent(Object oldObject, Object newObject) { + return dataTracerChangeContentService.getChangeContent(oldObject, newObject); + } + + + /** + * 获取变更内容 + */ + public String getChangeContent(List oldObjectList, List newObjectList) { + return dataTracerChangeContentService.getChangeContent(oldObjectList, newObjectList); + } + + + /** + * 保存【修改】数据变动记录 + * + * @param dataId + * @param type + */ + public void update(Long dataId, DataTracerTypeEnum type, Object oldObject, Object newObject) { + DataTracerForm form = DataTracerForm.builder() + .dataId(dataId) + .type(type) + .content(dataTracerChangeContentService.getChangeContent(oldObject, newObject)) + .build(); + this.addTrace(form); + } + + + /** + * 保存【新增】数据变动记录 + * + * @param dataId + * @param type + */ + public void insert(Long dataId, DataTracerTypeEnum type) { + DataTracerForm form = DataTracerForm.builder().dataId(dataId).type(type).content(DataTracerConst.INSERT).build(); + this.addTrace(form); + } + + /** + * 保存【删除】数据变动记录 + * + * @param dataId + * @param type + */ + public void delete(Long dataId, DataTracerTypeEnum type) { + DataTracerForm form = DataTracerForm.builder().dataId(dataId).type(type).content(DataTracerConst.DELETE).build(); + this.addTrace(form); + } + + /** + * 保存【删除】数据变动记录 + * + * @param dataId + * @param type + */ + public void delete(Long dataId, DataTracerTypeEnum type, Object object) { + DataTracerForm form = DataTracerForm.builder().dataId(dataId).type(type).content(DataTracerConst.DELETE).build(); + this.addTrace(form); + } + + /** + * 保存【批量删除】数据变动记录 + * + * @param dataIdList + * @param type + */ + public void batchDelete(List dataIdList, DataTracerTypeEnum type) { + if (CollectionUtils.isEmpty(dataIdList)) { + return; + } + + this.addTraceList(dataIdList.stream().map(e -> DataTracerForm.builder() + .dataId(e) + .type(type) + .content(DataTracerConst.DELETE) + .build()) + .collect(Collectors.toList()) + ); + } + + /** + * 保存数据变动记录 + * + * @param dataId + * @param type + * @param content + */ + public void addTrace(Long dataId, DataTracerTypeEnum type, String content) { + DataTracerForm form = DataTracerForm.builder().dataId(dataId).type(type).content(content).build(); + this.addTrace(form); + } + + /** + * 保存数据变动记录 + */ + public void addTrace(DataTracerForm tracerForm) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + this.addTrace(tracerForm, requestUser); + } + + + /** + * 保存数据变动记录 + */ + public void addTrace(DataTracerForm tracerForm, RequestUser requestUser) { + DataTracerEntity tracerEntity = SmartBeanUtil.copy(tracerForm, DataTracerEntity.class); + tracerEntity.setType(tracerForm.getType().getValue()); + if (requestUser != null) { + tracerEntity.setIp(requestUser.getIp()); + tracerEntity.setIpRegion(SmartIpUtil.getRegion(requestUser.getIp())); + tracerEntity.setUserAgent(requestUser.getUserAgent()); + tracerEntity.setUserId(requestUser.getUserId()); + tracerEntity.setUserType(requestUser.getUserType().getValue()); + tracerEntity.setUserName(requestUser.getUserName()); + } + dataTracerManger.save(tracerEntity); + } + + /** + * 批量保存数据变动记录 + */ + public void addTraceList(List tracerFormList) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + this.addTraceList(tracerFormList, requestUser); + } + + /** + * 批量保存数据变动记录 + */ + public void addTraceList(List tracerFormList, RequestUser requestUser) { + if (CollectionUtils.isEmpty(tracerFormList)) { + return; + } + + List tracerEntityList = tracerFormList.stream().map(e -> { + DataTracerEntity tracerEntity = SmartBeanUtil.copy(e, DataTracerEntity.class); + tracerEntity.setType(e.getType().getValue()); + tracerEntity.setIp(requestUser.getIp()); + tracerEntity.setIpRegion(SmartIpUtil.getRegion(requestUser.getIp())); + tracerEntity.setUserAgent(requestUser.getUserAgent()); + tracerEntity.setUserId(requestUser.getUserId()); + tracerEntity.setUserType(requestUser.getUserType().getValue()); + tracerEntity.setUserName(requestUser.getUserName()); + return tracerEntity; + }).collect(Collectors.toList()); + dataTracerManger.saveBatch(tracerEntityList); + } + + + /** + * 分页查询 + * + * @param queryForm + * @return + */ + public ResponseDTO> query(DataTracerQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = dataTracerDao.query(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, list); + return ResponseDTO.ok(pageResult); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/dao/DictDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/dao/DictDao.java new file mode 100644 index 0000000..0fa4984 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/dao/DictDao.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.base.module.support.dict.dao; + +import java.util.List; + +import net.lab1024.sa.base.module.support.dict.domain.entity.DictEntity; +import net.lab1024.sa.base.module.support.dict.domain.form.DictQueryForm; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictVO; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +/** + * 数据字典 Dao + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Mapper +@Component +public interface DictDao extends BaseMapper { + + /** + * 分页 查询 + */ + List queryPage(Page page, @Param("queryForm") DictQueryForm queryForm); + + /** + * 根据 dictCode 去查询 + */ + DictEntity selectByCode(@Param("code") String code); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/dao/DictDataDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/dao/DictDataDao.java new file mode 100644 index 0000000..c0994f9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/dao/DictDataDao.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.base.module.support.dict.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.dict.domain.entity.DictDataEntity; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictDataVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; + +/** + * 字典数据表 Dao + * + * @Author wzh + * @Date 2025-03-25 23:12:59 + */ + +@Mapper +@Component +public interface DictDataDao extends BaseMapper { + + List queryByDictId(@Param("dictId") Long dictId); + + List selectByDictDataIds(@Param("dictDataIdList") Collection dictDataIds); + + DictDataEntity selectByDictIdAndValue(@Param("dictId") Long dictId, @Param("dataValue") String dataValue); + + List getAll(); + + List queryDictDataByCode(@Param("dictCode")String dictCode); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java new file mode 100644 index 0000000..34b8397 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictDataEntity.java @@ -0,0 +1,67 @@ +package net.lab1024.sa.base.module.support.dict.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 字典数据表 实体类 + * + * @Author wzh + * @Date 2025-03-25 23:12:59 + */ + +@Data +@TableName("t_dict_data") +public class DictDataEntity { + + /** + * 字典数据id + */ + @TableId(type = IdType.AUTO) + private Long dictDataId; + + /** + * 字典id + */ + private Long dictId; + + /** + * 字典项值 + */ + private String dataValue; + + /** + * 字典项显示名称 + */ + private String dataLabel; + + /** + * 备注 + */ + private String remark; + + /** + * 排序(越大越靠前) + */ + private Integer sortOrder; + + /** + * 禁用状态 + */ + private Boolean disabledFlag; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictEntity.java new file mode 100644 index 0000000..a04a042 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/entity/DictEntity.java @@ -0,0 +1,57 @@ +package net.lab1024.sa.base.module.support.dict.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 数据字典 实体类 + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Data +@TableName("t_dict") +public class DictEntity { + + /** + * 字典id + */ + @TableId(type = IdType.AUTO) + private Long dictId; + + /** + * 字典名字 + */ + private String dictName; + + /** + * 字典编码 + */ + private String dictCode; + + /** + * 字典备注 + */ + private String remark; + + /** + * 禁用状态 + */ + private Boolean disabledFlag; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictAddForm.java new file mode 100644 index 0000000..95726a7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictAddForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.module.support.dict.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * 数据字典 新建表单 + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Data +public class DictAddForm { + + @Schema(description = "字典名字", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "字典名字 不能为空") + private String dictName; + + @Schema(description = "字典编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "字典编码 不能为空") + private String dictCode; + + @Schema(description = "字典备注") + private String remark; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java new file mode 100644 index 0000000..cfc1f66 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataAddForm.java @@ -0,0 +1,37 @@ +package net.lab1024.sa.base.module.support.dict.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 字典数据表 新建表单 + * + * @Author wzh + * @Date 2025-03-25 23:12:59 + */ + +@Data +public class DictDataAddForm { + + @Schema(description = "字典id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "字典id 不能为空") + private Long dictId; + + @Schema(description = "字典项值", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "字典项值 不能为空") + private String dataValue; + + @Schema(description = "字典项显示名称", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "字典项显示名称 不能为空") + private String dataLabel; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序(越大越靠前)", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "排序(越大越靠前) 不能为空") + private Integer sortOrder; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataUpdateForm.java new file mode 100644 index 0000000..77c43c7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictDataUpdateForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.dict.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + + +/** + * 字典数据表 更新表单 + * + * @Author wzh + * @Date 2025-03-25 23:12:59 + */ + +@Data +public class DictDataUpdateForm extends DictDataAddForm { + + @Schema(description = "字典数据id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "字典数据id 不能为空") + private Long dictDataId; + + @Schema(description = "字典数据编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "字典数据编码 不能为空") + private String dictCode; + + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictQueryForm.java new file mode 100644 index 0000000..728035c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictQueryForm.java @@ -0,0 +1,25 @@ +package net.lab1024.sa.base.module.support.dict.domain.form; + +import net.lab1024.sa.base.common.domain.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 数据字典 分页查询表单 + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Data +@EqualsAndHashCode(callSuper = false) +public class DictQueryForm extends PageParam { + + @Schema(description = "关键字") + private String keywords; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictUpdateForm.java new file mode 100644 index 0000000..1edd622 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/form/DictUpdateForm.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.base.module.support.dict.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 数据字典 更新表单 + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Data +public class DictUpdateForm { + + @Schema(description = "字典id", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "字典id 不能为空") + private Long dictId; + + @Schema(description = "字典名字", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "字典名字 不能为空") + private String dictName; + + @Schema(description = "字典编码", requiredMode = Schema.RequiredMode.REQUIRED) + @NotBlank(message = "字典编码 不能为空") + private String dictCode; + + @Schema(description = "字典备注") + private String remark; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java new file mode 100644 index 0000000..308dacb --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictDataVO.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.base.module.support.dict.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 字典数据表 列表VO + * + * @Author wzh + * @Date 2025-03-25 23:12:59 + */ + +@Data +public class DictDataVO { + + @Schema(description = "字典数据id") + private Long dictDataId; + + @Schema(description = "字典id") + private Long dictId; + + @Schema(description = "字典编码") + private String dictCode; + + @Schema(description = "字典项值") + private String dataValue; + + @Schema(description = "字典项显示名称") + private String dataLabel; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序(越大越靠前)") + private Integer sortOrder; + + @Schema(description = "禁用状态") + private Boolean disabledFlag; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictVO.java new file mode 100644 index 0000000..4584d48 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/domain/vo/DictVO.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.module.support.dict.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; + +import java.time.LocalDateTime; + +import lombok.Data; + +/** + * 数据字典 列表VO + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Data +public class DictVO { + + @Schema(description = "字典id") + private Long dictId; + + @Schema(description = "字典名字") + private String dictName; + + @Schema(description = "字典编码") + private String dictCode; + + @Schema(description = "字典备注") + private String remark; + + @Schema(description = "禁用状态") + private Integer disabledFlag; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/manager/DictManager.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/manager/DictManager.java new file mode 100644 index 0000000..7b87861 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/manager/DictManager.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.module.support.dict.manager; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.constant.CacheKeyConst; +import net.lab1024.sa.base.module.support.dict.dao.DictDao; +import net.lab1024.sa.base.module.support.dict.dao.DictDataDao; +import net.lab1024.sa.base.module.support.dict.domain.entity.DictDataEntity; +import net.lab1024.sa.base.module.support.dict.domain.entity.DictEntity; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictDataVO; +import org.springframework.cache.annotation.Cacheable; +import org.springframework.stereotype.Service; + + +/** + * 数据字典 缓存 + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Service +public class DictManager { + + @Resource + private DictDao dictDao; + + @Resource + private DictDataDao dictDataDao; + + + /** + * 获取字典 + */ + @Cacheable(value = CacheKeyConst.Dict.DICT_DATA, key = "#dictCode + '_' + #dataValue") + public DictDataVO getDictData(String dictCode, String dataValue) { + DictEntity dictEntity = dictDao.selectByCode(dictCode); + if (dictEntity == null) { + return null; + } + + DictDataEntity dictDataEntity = dictDataDao.selectByDictIdAndValue(dictEntity.getDictId(), dataValue); + return SmartBeanUtil.copy(dictDataEntity, DictDataVO.class); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/service/DictService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/service/DictService.java new file mode 100644 index 0000000..8762b0b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/dict/service/DictService.java @@ -0,0 +1,277 @@ +package net.lab1024.sa.base.module.support.dict.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.constant.CacheKeyConst; +import net.lab1024.sa.base.module.support.dict.dao.DictDao; +import net.lab1024.sa.base.module.support.dict.dao.DictDataDao; +import net.lab1024.sa.base.module.support.dict.domain.entity.DictDataEntity; +import net.lab1024.sa.base.module.support.dict.domain.entity.DictEntity; +import net.lab1024.sa.base.module.support.dict.domain.form.*; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictDataVO; +import net.lab1024.sa.base.module.support.dict.domain.vo.DictVO; +import net.lab1024.sa.base.module.support.dict.manager.DictManager; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.cache.Cache; +import org.springframework.cache.CacheManager; +import org.springframework.cache.annotation.CacheEvict; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * 数据字典 Service + * + * @Author wzh + * @Date 2025-03-25 22:25:04 + */ + +@Service +public class DictService { + + @Resource + private DictDao dictDao; + + @Resource + private DictDataDao dictDataDao; + + @Resource + private CacheManager cacheManager; + + @Resource + private DictManager dictManager; + + /** + * 获取全部数据 + */ + public List getAll() { + return dictDataDao.getAll(); + } + + /** + * 获取所有字典 + */ + public List getAllDict() { + List dictEntityList = dictDao.selectList(null).stream().filter(e -> !e.getDisabledFlag()).collect(Collectors.toList()); + return SmartBeanUtil.copyList(dictEntityList, DictVO.class); + } + + /** + * 分页查询 + */ + public PageResult queryPage(DictQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = dictDao.queryPage(page, queryForm); + return SmartPageUtil.convert2PageResult(page, list); + } + + /** + * 添加 + */ + public synchronized ResponseDTO add(DictAddForm addForm) { + DictEntity existDictCode = dictDao.selectByCode(addForm.getDictCode()); + if (null != existDictCode) { + return ResponseDTO.userErrorParam("数据字典编码已经存在!"); + } + + DictEntity dictEntity = SmartBeanUtil.copy(addForm, DictEntity.class); + dictDao.insert(dictEntity); + return ResponseDTO.ok(); + } + + /** + * 禁用 启用 + */ + public ResponseDTO updateDisabled(Long dictId) { + DictEntity dictEntity = dictDao.selectById(dictId); + if (dictEntity == null) { + return ResponseDTO.userErrorParam("数据不存在"); + } + + dictEntity.setDisabledFlag(!dictEntity.getDisabledFlag()); + dictDao.updateById(dictEntity); + return ResponseDTO.ok(); + } + + /** + * 更新 + */ + @CacheEvict(CacheKeyConst.Dict.DICT_DATA) + public synchronized ResponseDTO update(DictUpdateForm updateForm) { + DictEntity existDictCode = dictDao.selectByCode(updateForm.getDictCode()); + if (null != existDictCode && !existDictCode.getDictId().equals(updateForm.getDictId())) { + return ResponseDTO.userErrorParam("数据字典编码已经存在!"); + } + + DictEntity dictEntity = SmartBeanUtil.copy(updateForm, DictEntity.class); + dictDao.updateById(dictEntity); + return ResponseDTO.ok(); + } + + /** + * 批量删除 + */ + @CacheEvict(CacheKeyConst.Dict.DICT_DATA) + public synchronized ResponseDTO batchDelete(List idList) { + if (CollectionUtils.isEmpty(idList)) { + return ResponseDTO.ok(); + } + + dictDao.deleteBatchIds(idList); + return ResponseDTO.ok(); + } + + /** + * 单个删除 + */ + @CacheEvict(CacheKeyConst.Dict.DICT_DATA) + public synchronized ResponseDTO delete(Long dictId) { + if (null == dictId) { + return ResponseDTO.ok(); + } + + dictDao.deleteById(dictId); + return ResponseDTO.ok(); + } + + + // -------------- 字典数据 -------------------- + + /** + * 分页查询 + */ + public List queryDictData(Long dictId) { + return dictDataDao.queryByDictId(dictId); + } + + /** + * 获取字典 + */ + + public DictDataVO getDictData(String dictCode, String dataValue) { + return dictManager.getDictData(dictCode, dataValue); + } + + /** + * 获取字典Label + */ + public String getDictDataLabel(String dictCode, String dataValue) { + DictDataVO dictData = getDictData(dictCode, dataValue); + return dictData == null ? "" : dictData.getDataLabel(); + } + + /** + * 添加 + */ + public synchronized ResponseDTO addDictData(DictDataAddForm addForm) { + + addForm.setDataValue(SmartStringUtil.trim(addForm.getDataValue())); + + DictEntity dictEntity = dictDao.selectById(addForm.getDictId()); + if (null == dictEntity) { + return ResponseDTO.userErrorParam("数据字典不存在"); + } + + DictDataEntity existData = dictDataDao.selectByDictIdAndValue(addForm.getDictId(), addForm.getDataValue()); + if (null != existData) { + return ResponseDTO.userErrorParam("已存在相同value的数据"); + } + + DictDataEntity dictDataEntity = SmartBeanUtil.copy(addForm, DictDataEntity.class); + dictDataDao.insert(dictDataEntity); + return ResponseDTO.ok(); + } + + /** + * 更新 + */ + @CacheEvict(value = CacheKeyConst.Dict.DICT_DATA, key = "#updateForm.dictCode + '_' + #updateForm.dataValue") + public synchronized ResponseDTO updateDictData(DictDataUpdateForm updateForm) { + + updateForm.setDataValue(SmartStringUtil.trim(updateForm.getDataValue())); + + DictEntity dictEntity = dictDao.selectById(updateForm.getDictId()); + if (null == dictEntity) { + return ResponseDTO.userErrorParam("数据字典不存在"); + } + + DictDataEntity existData = dictDataDao.selectByDictIdAndValue(updateForm.getDictId(), updateForm.getDataValue()); + if (null != existData && !existData.getDictDataId().equals(updateForm.getDictDataId())) { + return ResponseDTO.userErrorParam("已存在相同value的数据"); + } + + DictDataEntity dictDataEntity = SmartBeanUtil.copy(updateForm, DictDataEntity.class); + dictDataDao.updateById(dictDataEntity); + return ResponseDTO.ok(); + } + + /** + * 批量删除 + */ + public synchronized ResponseDTO batchDeleteDictData(List idList) { + if (CollectionUtils.isEmpty(idList)) { + return ResponseDTO.ok(); + } + // 清除缓存 + clearDictDataCache(idList); + // 删除 + dictDataDao.deleteBatchIds(idList); + return ResponseDTO.ok(); + } + + /** + * 单个删除 + */ + public synchronized ResponseDTO deleteDictData(Long dictDataId) { + if (null == dictDataId) { + return ResponseDTO.ok(); + } + // 清除缓存 + clearDictDataCache(Collections.singletonList(dictDataId)); + // 删除 + dictDataDao.deleteById(dictDataId); + return ResponseDTO.ok(); + } + + + /** + * 清空字典数据缓存 + */ + private void clearDictDataCache(List idList) { + List dictDataList = dictDataDao.selectByDictDataIds(idList); + Cache cache = cacheManager.getCache(CacheKeyConst.Dict.DICT_DATA); + if (cache == null) { + return; + } + + for (DictDataVO dictDataVO : dictDataList) { + cache.evict(dictDataVO.getDictCode() + "_" + dictDataVO.getDataValue()); + } + } + + + /** + * 更新启用/禁用 + */ + public synchronized ResponseDTO updateDictDataDisabled(Long dictDataId) { + DictDataEntity dictDataEntity = dictDataDao.selectById(dictDataId); + if (dictDataEntity == null) { + return ResponseDTO.userErrorParam("数据不存在"); + } + + dictDataEntity.setDisabledFlag(!dictDataEntity.getDisabledFlag()); + dictDataDao.updateById(dictDataEntity); + return ResponseDTO.ok(); + } + + public List queryDictDataByCode(String dictCode) { + return dictDataDao.queryDictDataByCode(dictCode); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/controller/FeedbackController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/controller/FeedbackController.java new file mode 100644 index 0000000..f83ff7e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/controller/FeedbackController.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.base.module.support.feedback.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackAddForm; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackQueryForm; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackVO; +import net.lab1024.sa.base.module.support.feedback.service.FeedbackService; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; + +/** + * 意见反馈 + * + * @Author wzh + * @Date 2022-08-11 20:48:09 + */ +@Slf4j +@Tag(name = SwaggerTagConst.Support.FEEDBACK) +@RestController +public class FeedbackController extends SupportBaseController { + + @Resource + private FeedbackService feedbackService; + + @Operation(summary = "意见反馈-分页查询 @author 开云") + @PostMapping("/feedback/query") + public ResponseDTO> query(@RequestBody @Valid FeedbackQueryForm queryForm) { + return feedbackService.query(queryForm); + } + + @Operation(summary = "意见反馈-新增 @author 开云") + @PostMapping("/feedback/add") + public ResponseDTO add(@RequestBody @Valid FeedbackAddForm addForm) { + RequestUser employee = SmartRequestUtil.getRequestUser(); + return feedbackService.add(addForm, employee); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/dao/FeedbackDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/dao/FeedbackDao.java new file mode 100644 index 0000000..083bc00 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/dao/FeedbackDao.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.feedback.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackEntity; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackQueryForm; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 意见反馈 dao + * + * @Author wzh + * @Date 2022-08-11 20:48:09 + */ +@Mapper +public interface FeedbackDao extends BaseMapper { + + /** + * 分页查询 + */ + List queryPage(Page page, @Param("query") FeedbackQueryForm query); +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackAddForm.java new file mode 100644 index 0000000..e6cd76a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackAddForm.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.base.module.support.feedback.domain; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer; +import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer; + +/** + * 意见反馈 添加表单 + * + * @Author wzh + * @Date 2022-08-11 20:48:09 + */ +@Data +public class FeedbackAddForm { + + @Schema(description = "反馈内容") + @NotBlank(message = "反馈内容不能为空") + private String feedbackContent; + + @Schema(description = "反馈图片") + @JsonSerialize(using = FileKeyVoSerializer.class) + @JsonDeserialize(using = FileKeyVoDeserializer.class) + private String feedbackAttachment; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackEntity.java new file mode 100644 index 0000000..136dae9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackEntity.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.base.module.support.feedback.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 意见反馈 表 + * + * @Author wzh + * @Date 2022-08-11 20:48:09 + */ +@Data +@TableName("t_feedback") +public class FeedbackEntity { + /** + * 主键 + */ + @TableId(type = IdType.AUTO) + private Long feedbackId; + + /** + * 反馈内容 + */ + private String feedbackContent; + + /** + * 反馈附件 + */ + private String feedbackAttachment; + + /** + * 创建人id + */ + private Long userId; + + /** + * 用户类型 + */ + private Integer userType; + + /** + * 创建人姓名 + */ + private String userName; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackQueryForm.java new file mode 100644 index 0000000..62648c4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackQueryForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.module.support.feedback.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; + +/** + * 意见反馈 查询 + * + * @Author wzh + * @Date 2022-08-11 20:48:09 + */ +@Data +public class FeedbackQueryForm extends PageParam { + + @Schema(description = "搜索词") + @Length(max = 25, message = "搜索词最多25字符") + private String searchWord; + + @Schema(description = "开始时间", example = "2021-02-14") + private LocalDate startDate; + + @Schema(description = "截止时间", example = "2022-10-15") + private LocalDate endDate; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackVO.java new file mode 100644 index 0000000..f8f7489 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/domain/FeedbackVO.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.base.module.support.feedback.domain; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer; +import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +import java.time.LocalDateTime; + +/** + * 意见反馈 返回对象 + * + * @Author wzh + * @Date 2022-08-11 20:48:09 + */ +@Data +public class FeedbackVO { + + @Schema(description = "主键") + private Long feedbackId; + + @Schema(description = "反馈内容") + private String feedbackContent; + + @Schema(description = "反馈图片") + @JsonSerialize(using = FileKeyVoSerializer.class) + @JsonDeserialize(using = FileKeyVoDeserializer.class) + private String feedbackAttachment; + + @Schema(description = "创建人id") + private Long userId; + + @Schema(description = "创建人姓名") + private String userName; + + @SchemaEnum(value = UserTypeEnum.class, desc = "创建人类型") + private Integer userType; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/service/FeedbackService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/service/FeedbackService.java new file mode 100644 index 0000000..88fafcb --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/feedback/service/FeedbackService.java @@ -0,0 +1,57 @@ +package net.lab1024.sa.base.module.support.feedback.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.feedback.dao.FeedbackDao; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackAddForm; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackEntity; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackQueryForm; +import net.lab1024.sa.base.module.support.feedback.domain.FeedbackVO; +import org.springframework.stereotype.Service; + +import java.util.List; + + +/** + * 意见反馈 + * + * @Author wzh + * @Date 2022-08-11 20:48:09 + */ +@Service +public class FeedbackService { + + @Resource + private FeedbackDao feedbackDao; + + /** + * 分页查询 + * + */ + public ResponseDTO> query(FeedbackQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = feedbackDao.queryPage(page, queryForm); + PageResult pageResultDTO = SmartPageUtil.convert2PageResult(page, list); + if (pageResultDTO.getEmptyFlag()) { + return ResponseDTO.ok(pageResultDTO); + } + return ResponseDTO.ok(pageResultDTO); + } + + /** + * 新建 + */ + public ResponseDTO add(FeedbackAddForm addForm, RequestUser requestUser) { + FeedbackEntity feedback = SmartBeanUtil.copy(addForm, FeedbackEntity.class); + feedback.setUserType(requestUser.getUserType().getValue()); + feedback.setUserId(requestUser.getUserId()); + feedback.setUserName(requestUser.getUserName()); + feedbackDao.insert(feedback); + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java new file mode 100644 index 0000000..424ca57 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/constant/FileFolderTypeEnum.java @@ -0,0 +1,55 @@ +package net.lab1024.sa.base.module.support.file.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 文件服务 文件夹位置类型枚举类 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@AllArgsConstructor +@Getter +public enum FileFolderTypeEnum implements BaseEnum { + + /** + * 通用 + */ + COMMON(1, FileFolderTypeEnum.FOLDER_PUBLIC + "/common/", "通用"), + + /** + * 公告 + */ + NOTICE(2, FileFolderTypeEnum.FOLDER_PUBLIC + "/notice/", "公告"), + + /** + * 帮助中心 + */ + HELP_DOC(3, FileFolderTypeEnum.FOLDER_PUBLIC + "/help-doc/", "帮助中心"), + + /** + * 意见反馈 + */ + FEEDBACK(4, FileFolderTypeEnum.FOLDER_PUBLIC + "/feedback/", "意见反馈"), + + ; + + /** + * 公用读取文件夹 public + */ + public static final String FOLDER_PUBLIC = "public"; + + /** + * 私有读取文件夹 private, 私有文件夹会设置 只读权限,并且 文件url 拥有过期时间 + */ + public static final String FOLDER_PRIVATE = "private"; + + private final Integer value; + + private final String folder; + + private final String desc; +} + diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/controller/FileController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/controller/FileController.java new file mode 100644 index 0000000..0b31457 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/controller/FileController.java @@ -0,0 +1,70 @@ +package net.lab1024.sa.base.module.support.file.controller; + +import cn.hutool.extra.servlet.JakartaServletUtil; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import net.lab1024.sa.base.common.constant.RequestHeaderConst; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.common.util.SmartResponseUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.file.domain.vo.FileDownloadVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileUploadVO; +import net.lab1024.sa.base.module.support.file.service.FileService; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +/** + * 文件服务 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@RestController +@Tag(name = SwaggerTagConst.Support.FILE) +public class FileController extends SupportBaseController { + + @Resource + private FileService fileService; + + + @Operation(summary = "文件上传 ") + @PostMapping("/file/upload") + public ResponseDTO upload(@RequestParam MultipartFile file, @RequestParam Integer folder) { + RequestUser requestUser = SmartRequestUtil.getRequestUser(); + return fileService.fileUpload(file, folder, requestUser); + } + + @Operation(summary = "获取文件URL:根据fileKey ") + @GetMapping("/file/getFileUrl") + public ResponseDTO getUrl(@RequestParam String fileKey) { + return fileService.getFileUrl(fileKey); + } + + @Operation(summary = "下载文件流(根据fileKey) ") + @GetMapping("/file/downLoad") + public void downLoad(@RequestParam String fileKey, HttpServletRequest request, HttpServletResponse response) throws IOException { + String userAgent = JakartaServletUtil.getHeaderIgnoreCase(request, RequestHeaderConst.USER_AGENT); + ResponseDTO downloadFileResult = fileService.getDownloadFile(fileKey, userAgent); + if (!downloadFileResult.getOk()) { + SmartResponseUtil.write(response, downloadFileResult); + return; + } + // 下载文件信息 + FileDownloadVO fileDownloadVO = downloadFileResult.getData(); + // 设置下载消息头 + SmartResponseUtil.setDownloadFileHeader(response, fileDownloadVO.getMetadata().getFileName(), fileDownloadVO.getMetadata().getFileSize()); + // 下载 + response.getOutputStream().write(fileDownloadVO.getData()); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/dao/FileDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/dao/FileDao.java new file mode 100644 index 0000000..e658b43 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/dao/FileDao.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.base.module.support.file.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.file.domain.vo.FileVO; +import net.lab1024.sa.base.module.support.file.domain.entity.FileEntity; +import net.lab1024.sa.base.module.support.file.domain.form.FileQueryForm; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.Collection; +import java.util.List; + +/** + * 文件服务 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Mapper +public interface FileDao extends BaseMapper { + + /** + * 文件key单个查询 + * + * @param fileKey + * @return + */ + FileVO getByFileKey(@Param("fileKey") String fileKey); + + + /** + * 批量获取 + */ + List selectByFileKeyList(@Param("fileKeyList") Collection fileKeyList); + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") FileQueryForm queryForm); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/entity/FileEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/entity/FileEntity.java new file mode 100644 index 0000000..ec56cec --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/entity/FileEntity.java @@ -0,0 +1,70 @@ +package net.lab1024.sa.base.module.support.file.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 文件服务 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Data +@TableName(value = "t_file") +public class FileEntity { + + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long fileId; + + /** + * 文件夹类型 + */ + private Integer folderType; + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件大小 + */ + private Long fileSize; + + /** + * 文件key,用于文件下载 + */ + private String fileKey; + + /** + * 文件类型 + */ + private String fileType; + + /** + * 创建人,即上传人 + */ + private Long creatorId; + + /** + * 用户类型 + */ + private Integer creatorUserType; + + /** + * 创建人 姓名 + */ + private String creatorName; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} + diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/form/FileQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/form/FileQueryForm.java new file mode 100644 index 0000000..edd74ee --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/form/FileQueryForm.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.base.module.support.file.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.file.constant.FileFolderTypeEnum; + +import java.time.LocalDate; + +/** + * 文件信息查询 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Data +public class FileQueryForm extends PageParam { + + @SchemaEnum(value = FileFolderTypeEnum.class, desc = "文件夹类型") + @CheckEnum(value = FileFolderTypeEnum.class, message = "文件夹类型 错误") + private Integer folderType; + + @Schema(description = "文件名词") + private String fileName; + + @Schema(description = "文件Key") + private String fileKey; + + @Schema(description = "文件类型") + private String fileType; + + @Schema(description = "创建人") + private String creatorName; + + @Schema(description = "创建时间") + private LocalDate createTimeBegin; + + @Schema(description = "创建时间") + private LocalDate createTimeEnd; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/form/FileUrlUploadForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/form/FileUrlUploadForm.java new file mode 100644 index 0000000..47ac4d0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/form/FileUrlUploadForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.file.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.file.constant.FileFolderTypeEnum; + +/** + * url上传文件 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Data +public class FileUrlUploadForm { + + @SchemaEnum(value = FileFolderTypeEnum.class, desc = "业务类型") + @CheckEnum(value = FileFolderTypeEnum.class, required = true, message = "业务类型错误") + private Integer folder; + + @Schema(description = "文件url") + @NotBlank(message = "文件url不能为空") + private String fileUrl; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileDownloadVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileDownloadVO.java new file mode 100644 index 0000000..3b27c97 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileDownloadVO.java @@ -0,0 +1,25 @@ +package net.lab1024.sa.base.module.support.file.domain.vo; + +import lombok.Data; + +/** + * 文件下载 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Data +public class FileDownloadVO { + + /** + * 文件字节数据 + */ + private byte[] data; + + /** + * 文件元数据 + */ + private FileMetadataVO metadata; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileMetadataVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileMetadataVO.java new file mode 100644 index 0000000..62f6797 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileMetadataVO.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.module.support.file.domain.vo; + +import lombok.Data; + +/** + * 文件元数据 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Data +public class FileMetadataVO { + + /** + * 文件名称 + */ + private String fileName; + + /** + * 文件大小/字节 + */ + private Long fileSize; + + /** + * 文件格式 + */ + private String fileFormat; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileUploadVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileUploadVO.java new file mode 100644 index 0000000..ca26fc9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileUploadVO.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.base.module.support.file.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 文件信息 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Data +public class FileUploadVO { + + @Schema(description = "文件id") + private Long fileId; + + @Schema(description = "文件名称") + private String fileName; + + @Schema(description = "fileUrl") + private String fileUrl; + + @Schema(description = "fileKey") + private String fileKey; + + @Schema(description = "文件大小") + private Long fileSize; + + @Schema(description = "文件类型") + private String fileType; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileVO.java new file mode 100644 index 0000000..d5591c8 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/domain/vo/FileVO.java @@ -0,0 +1,53 @@ +package net.lab1024.sa.base.module.support.file.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.file.constant.FileFolderTypeEnum; + +import java.time.LocalDateTime; + +/** + * 文件信息 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Data +public class FileVO { + + @Schema(description = "主键") + private Long fileId; + + @Schema(description = "存储文件夹类型") + @SchemaEnum(FileFolderTypeEnum.class) + private Integer folderType; + + @Schema(description = "文件名称") + private String fileName; + + @Schema(description = "文件大小") + private Integer fileSize; + + @Schema(description = "文件类型") + private String fileType; + + @Schema(description = "文件路径") + private String fileKey; + + @Schema(description = "上传人") + private Long creatorId; + + @Schema(description = "上传人") + private String creatorName; + + @SchemaEnum(value = UserTypeEnum.class, desc = "创建人类型") + private Integer creatorUserType; + + @Schema(description = "文件展示url") + private String fileUrl; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileService.java new file mode 100644 index 0000000..544367e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileService.java @@ -0,0 +1,206 @@ +package net.lab1024.sa.base.module.support.file.service; + +import cn.hutool.core.util.StrUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.file.constant.FileFolderTypeEnum; +import net.lab1024.sa.base.module.support.file.dao.FileDao; +import net.lab1024.sa.base.module.support.file.domain.entity.FileEntity; +import net.lab1024.sa.base.module.support.file.domain.form.FileQueryForm; +import net.lab1024.sa.base.module.support.file.domain.vo.FileDownloadVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileUploadVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileVO; +import net.lab1024.sa.base.module.support.redis.RedisService; +import net.lab1024.sa.base.module.support.securityprotect.service.SecurityFileService; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 文件服务 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Service +public class FileService { + + /** + * 文件名最大长度 + */ + private static final int FILE_NAME_MAX_LENGTH = 100; + + @Resource + private IFileStorageService fileStorageService; + + @Resource + private FileDao fileDao; + + @Resource + private RedisService redisService; + + @Resource + private SecurityFileService securityFileService; + + /** + * 文件上传服务 + * + * @param file + * @param folderType 文件夹类型 + * @return + */ + public ResponseDTO fileUpload(MultipartFile file, Integer folderType, RequestUser requestUser) { + FileFolderTypeEnum folderTypeEnum = SmartEnumUtil.getEnumByValue(folderType, FileFolderTypeEnum.class); + if (null == folderTypeEnum) { + return ResponseDTO.userErrorParam("文件夹错误"); + } + + if (null == file || file.getSize() == 0) { + return ResponseDTO.userErrorParam("上传文件不能为空"); + } + + // 校验文件名称 + String originalFilename = file.getOriginalFilename(); + if (StringUtils.isBlank(originalFilename)) { + return ResponseDTO.userErrorParam("上传文件名称不能为空"); + } + + if (originalFilename.length() > FILE_NAME_MAX_LENGTH) { + return ResponseDTO.userErrorParam("文件名称最大长度为:" + FILE_NAME_MAX_LENGTH); + } + + // 校验文件大小以及安全性 + ResponseDTO validateFile = securityFileService.checkFile(file); + if (!validateFile.getOk()) { + return ResponseDTO.error(validateFile); + } + + // 进行上传 + ResponseDTO response = fileStorageService.upload(file, folderTypeEnum.getFolder()); + if (!response.getOk()) { + return response; + } + + // 上传成功 保存记录数据库 + FileUploadVO uploadVO = response.getData(); + FileEntity fileEntity = new FileEntity(); + fileEntity.setFolderType(folderTypeEnum.getValue()); + fileEntity.setFileName(originalFilename); + fileEntity.setFileSize(file.getSize()); + fileEntity.setFileKey(uploadVO.getFileKey()); + fileEntity.setFileType(uploadVO.getFileType()); + fileEntity.setCreatorId(requestUser == null ? null : requestUser.getUserId()); + fileEntity.setCreatorName(requestUser == null ? null : requestUser.getUserName()); + fileEntity.setCreatorUserType(requestUser == null ? null : requestUser.getUserType().getValue()); + fileDao.insert(fileEntity); + + // 将fileId 返回给前端 + uploadVO.setFileId(fileEntity.getFileId()); + + return response; + } + + /** + * 批量获取文件信息 + * + * @param fileKeyList + * @return + */ + public List getFileList(List fileKeyList) { + if (CollectionUtils.isEmpty(fileKeyList)) { + return Lists.newArrayList(); + } + + // 查询数据库,并获取 file url + HashSet fileKeySet = new HashSet<>(fileKeyList); + Map fileMap = fileDao.selectByFileKeyList(fileKeySet) + .stream().collect(Collectors.toMap(FileVO::getFileKey, Function.identity())); + + for (FileVO fileVO : fileMap.values()) { + ResponseDTO fileUrlResponse = fileStorageService.getFileUrl(fileVO.getFileKey()); + if (fileUrlResponse.getOk()) { + fileVO.setFileUrl(fileUrlResponse.getData()); + } + } + + // 返回结果 + List result = Lists.newArrayListWithCapacity(fileKeyList.size()); + for (String fileKey : fileKeyList) { + FileVO fileVO = fileMap.get(fileKey); + if (fileVO != null) { + result.add(fileVO); + } + } + + return result; + } + + + /** + * 根据文件绝对路径 获取文件URL + * 支持单个 key 逗号分隔的形式 + * + * @param fileKeys + * @return + */ + public ResponseDTO getFileUrl(String fileKeys) { + if (StringUtils.isBlank(fileKeys)) { + return ResponseDTO.error(UserErrorCode.PARAM_ERROR); + } + + List fileKeyArray = StrUtil.split(fileKeys, StringConst.SEPARATOR); + List fileUrlList = Lists.newArrayListWithCapacity(fileKeyArray.size()); + for (String fileKey : fileKeyArray) { + ResponseDTO fileUrlResponse = fileStorageService.getFileUrl(fileKey); + if (fileUrlResponse.getOk()) { + fileUrlList.add(fileUrlResponse.getData()); + } + } + return ResponseDTO.ok(SmartStringUtil.join(StringConst.SEPARATOR, fileUrlList)); + } + + + /** + * 根据文件服务类型 和 FileKey 下载文件 + */ + public ResponseDTO getDownloadFile(String fileKey, String userAgent) { + FileVO fileVO = fileDao.getByFileKey(fileKey); + if (fileVO == null) { + return ResponseDTO.userErrorParam("文件不存在"); + } + + // 根据文件服务类 获取对应文件服务 查询 url + ResponseDTO download = fileStorageService.download(fileKey); + if (download.getOk()) { + download.getData().getMetadata().setFileName(fileVO.getFileName()); + } + return download; + } + + /** + * 分页查询 + */ + public PageResult queryPage(FileQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = fileDao.queryPage(page, queryForm); + return SmartPageUtil.convert2PageResult(page, list); + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java new file mode 100644 index 0000000..bcdfe21 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageCloudServiceImpl.java @@ -0,0 +1,243 @@ +package net.lab1024.sa.base.module.support.file.service; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.CannedAccessControlList; +import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.S3Object; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.code.SystemErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.config.FileConfig; +import net.lab1024.sa.base.constant.RedisKeyConst; +import net.lab1024.sa.base.module.support.file.constant.FileFolderTypeEnum; +import net.lab1024.sa.base.module.support.file.dao.FileDao; +import net.lab1024.sa.base.module.support.file.domain.vo.FileDownloadVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileMetadataVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileUploadVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileVO; +import net.lab1024.sa.base.module.support.redis.RedisService; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.StandardCharsets; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * 云计算 实现 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Slf4j +public class FileStorageCloudServiceImpl implements IFileStorageService { + + /** + * 自定义元数据 文件名称 + */ + private static final String USER_METADATA_FILE_NAME = "file-name"; + + /** + * 自定义元数据 文件格式 + */ + private static final String USER_METADATA_FILE_FORMAT = "file-format"; + + /** + * 自定义元数据 文件大小 + */ + private static final String USER_METADATA_FILE_SIZE = "file-size"; + + @Resource + private AmazonS3 amazonS3; + + @Resource + private FileConfig cloudConfig; + + @Resource + private RedisService redisService; + + @Resource + private FileDao fileDao; + + @Override + public ResponseDTO upload(MultipartFile file, String path) { + // 设置文件 key + String originalFileName = file.getOriginalFilename(); + if (SmartStringUtil.isEmpty(originalFileName)) { + return ResponseDTO.userErrorParam("上传文件名为空"); + } + + String fileType = FilenameUtils.getExtension(originalFileName); + String uuid = UUID.randomUUID().toString().replaceAll("-", ""); + String time = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_FORMATTER); + String fileKey = path + uuid + "_" + time+ "." + fileType; + + // 文件名称 URL 编码 + String urlEncoderFilename; + try { + urlEncoderFilename = URLEncoder.encode(originalFileName, StandardCharsets.UTF_8.name()); + } catch (UnsupportedEncodingException e) { + log.error("文件上传服务URL ENCODE-发生异常:", e); + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, "上传失败"); + } + ObjectMetadata meta = new ObjectMetadata(); + meta.setContentEncoding(StandardCharsets.UTF_8.name()); + meta.setContentDisposition("attachment;filename=" + urlEncoderFilename); + Map userMetadata = new HashMap<>(10); + userMetadata.put(USER_METADATA_FILE_NAME, urlEncoderFilename); + userMetadata.put(USER_METADATA_FILE_FORMAT, fileType); + userMetadata.put(USER_METADATA_FILE_SIZE, String.valueOf(file.getSize())); + meta.setUserMetadata(userMetadata); + meta.setContentLength(file.getSize()); + meta.setContentType(this.getContentType(fileType)); + try { + amazonS3.putObject(cloudConfig.getBucketName(), fileKey, file.getInputStream(), meta); + } catch (IOException e) { + log.error("文件上传-发生异常:", e); + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, "上传失败"); + } + // 根据文件路径获取并设置访问权限 + CannedAccessControlList acl = this.getACL(path); + amazonS3.setObjectAcl(cloudConfig.getBucketName(), fileKey, acl); + // 返回上传结果 + FileUploadVO uploadVO = new FileUploadVO(); + uploadVO.setFileName(originalFileName); + uploadVO.setFileType(fileType); + // 根据 访问权限 返回不同的 URL + String url = cloudConfig.getUrlPrefix() + fileKey; + if (CannedAccessControlList.Private.equals(acl)) { + // 获取临时访问的URL + url = this.getFileUrl(fileKey).getData(); + } + uploadVO.setFileUrl(url); + uploadVO.setFileKey(fileKey); + uploadVO.setFileSize(file.getSize()); + return ResponseDTO.ok(uploadVO); + } + + /** + * 获取文件url + * + * @param fileKey + * @return + */ + @Override + public ResponseDTO getFileUrl(String fileKey) { + if (StringUtils.isBlank(fileKey)) { + return ResponseDTO.userErrorParam("文件不存在,key为空"); + } + + if (!fileKey.startsWith(FileFolderTypeEnum.FOLDER_PRIVATE)) { + // 不是私有的 都公共读 + return ResponseDTO.ok(cloudConfig.getUrlPrefix() + fileKey); + } + + // 如果是私有的,则规定时间内可以访问,超过规定时间,则连接失效 + + String fileRedisKey = RedisKeyConst.Support.FILE_PRIVATE_VO + fileKey; + FileVO fileVO = redisService.getObject(fileRedisKey, FileVO.class); + if (fileVO == null) { + fileVO = fileDao.getByFileKey(fileKey); + if (fileVO == null) { + return ResponseDTO.userErrorParam("文件不存在"); + } + + Date expiration = new Date(System.currentTimeMillis() + cloudConfig.getPrivateUrlExpireSeconds() * 1000L); + URL url = amazonS3.generatePresignedUrl(cloudConfig.getBucketName(), fileKey, expiration); + fileVO.setFileUrl(url.toString()); + redisService.set(fileRedisKey, fileVO, cloudConfig.getPrivateUrlExpireSeconds() - 5); + } + + return ResponseDTO.ok(fileVO.getFileUrl()); + } + + + /** + * 流式下载(名称为原文件) + */ + @Override + public ResponseDTO download(String key) { + //获取oss对象 + S3Object s3Object = amazonS3.getObject(cloudConfig.getBucketName(), key); + // 获取文件 meta + ObjectMetadata metadata = s3Object.getObjectMetadata(); + Map userMetadata = metadata.getUserMetadata(); + FileMetadataVO metadataDTO = null; + if (MapUtils.isNotEmpty(userMetadata)) { + metadataDTO = new FileMetadataVO(); + metadataDTO.setFileFormat(userMetadata.get(USER_METADATA_FILE_FORMAT)); + metadataDTO.setFileName(userMetadata.get(USER_METADATA_FILE_NAME)); + String fileSizeStr = userMetadata.get(USER_METADATA_FILE_SIZE); + Long fileSize = StringUtils.isBlank(fileSizeStr) ? null : Long.valueOf(fileSizeStr); + metadataDTO.setFileSize(fileSize); + } + + // 获得输入流 + InputStream objectContent = s3Object.getObjectContent(); + try { + // 输入流转换为字节流 + byte[] buffer = FileCopyUtils.copyToByteArray(objectContent); + + FileDownloadVO fileDownloadVO = new FileDownloadVO(); + fileDownloadVO.setData(buffer); + fileDownloadVO.setMetadata(metadataDTO); + return ResponseDTO.ok(fileDownloadVO); + } catch (IOException e) { + log.error("文件下载-发生异常:", e); + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, "下载失败"); + } finally { + try { + // 关闭输入流 + objectContent.close(); + s3Object.close(); + } catch (IOException e) { + log.error("文件下载-发生异常:", e); + } + } + } + + /** + * 根据文件夹路径 返回对应的访问权限 + * + * @param fileKey + * @return + */ + private CannedAccessControlList getACL(String fileKey) { + // 公用读 + if (fileKey.contains(FileFolderTypeEnum.FOLDER_PUBLIC)) { + return CannedAccessControlList.PublicRead; + } + // 其他默认私有读写 + return CannedAccessControlList.Private; + } + + /** + * 单个删除文件 + * 根据 file key 删除文件 + * ps:不能删除fileKey不为空的文件夹 + * + * @param fileKey 文件or文件夹 + * @return + */ + @Override + public ResponseDTO delete(String fileKey) { + amazonS3.deleteObject(cloudConfig.getBucketName(), fileKey); + return ResponseDTO.ok(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageLocalServiceImpl.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageLocalServiceImpl.java new file mode 100644 index 0000000..9f55d07 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/FileStorageLocalServiceImpl.java @@ -0,0 +1,190 @@ +package net.lab1024.sa.base.module.support.file.service; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.net.NetUtil; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.code.SystemErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.file.domain.vo.FileDownloadVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileMetadataVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileUploadVO; +import org.apache.commons.io.FileUtils; +import org.apache.commons.io.FilenameUtils; +import org.apache.commons.lang3.StringUtils; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.util.FileCopyUtils; +import org.springframework.web.multipart.MultipartFile; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.util.UUID; + +/** + * 本地存储 实现 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +@Slf4j +public class FileStorageLocalServiceImpl implements IFileStorageService { + + + public static final String UPLOAD_MAPPING = "/upload"; + + @Value("${file.storage.local.upload-path}") + private String uploadPath; + + @Value("${file.storage.local.url-prefix}") + private String urlPrefix; + + @Value("${server.servlet.context-path}") + private String contextPath; + + @Value("${server.port}") + private String port; + + @PostConstruct + public void initUrlPrefix() { + if (SmartStringUtil.isNotEmpty(urlPrefix)) { + return; + } + + String localhostIp = NetUtil.getLocalhostStr(); + String finalContextPath = contextPath.startsWith("/") ? contextPath : "/" + contextPath; + if (finalContextPath.endsWith("/")) { + finalContextPath = finalContextPath.substring(0, finalContextPath.length() - 1); + } + urlPrefix = "http://" + localhostIp + ":" + port + finalContextPath + UPLOAD_MAPPING; + urlPrefix = urlPrefix.endsWith("/") ? urlPrefix : urlPrefix + "/"; + } + + @Override + public ResponseDTO upload(MultipartFile multipartFile, String path) { + if (null == multipartFile) { + return ResponseDTO.userErrorParam("上传文件不能为空"); + } + String filePath = uploadPath + path; + File directory = new File(filePath); + if (!directory.exists()) { + // 目录不存在,新建 + directory.mkdirs(); + } + if (!path.endsWith("/")) { + path = path + "/"; + } + FileUploadVO fileUploadVO = new FileUploadVO(); + //原文件名 + String originalFileName = multipartFile.getOriginalFilename(); + //新文件名 + String uuid = UUID.randomUUID().toString().replaceAll("-", ""); + String time = LocalDateTimeUtil.format(LocalDateTime.now(), DatePattern.PURE_DATETIME_FORMATTER); + String newFileName = uuid + "_" + time; + String fileType = FilenameUtils.getExtension(originalFileName); + if (SmartStringUtil.isNotEmpty(fileType)) { + newFileName = newFileName + "." + fileType; + } + //生成文件key + String fileKey = path + newFileName; + //创建文件 + File fileTemp = new File(new File(filePath + newFileName).getAbsolutePath()); + try { + multipartFile.transferTo(fileTemp); + fileUploadVO.setFileUrl(this.generateFileUrl(fileKey)); + fileUploadVO.setFileName(newFileName); + fileUploadVO.setFileKey(fileKey); + fileUploadVO.setFileSize(multipartFile.getSize()); + fileUploadVO.setFileType(FilenameUtils.getExtension(originalFileName)); + } catch (IOException e) { + if (fileTemp.exists() && fileTemp.isFile()) { + fileTemp.delete(); + } + log.error("", e); + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, "上传失败"); + } + return ResponseDTO.ok(fileUploadVO); + } + + /** + * 生成fileUrl地址 + * + * @param filePath + * @return + */ + public String generateFileUrl(String filePath) { + return urlPrefix + filePath; + } + + /** + * 获取文件Url + * + * @param fileKey + * @return + */ + @Override + public ResponseDTO getFileUrl(String fileKey) { + if (StringUtils.isBlank(fileKey)) { + return ResponseDTO.userErrorParam("文件不存在,key为空"); + } + + String fileUrl = this.generateFileUrl(fileKey); + return ResponseDTO.ok(fileUrl); + } + + /** + * 文件下载 + * + * @param fileKey + * @return + */ + @Override + public ResponseDTO download(String fileKey) { + String filePath = uploadPath + fileKey; + File localFile = new File(filePath); + InputStream in = null; + try { + in = Files.newInputStream(localFile.toPath()); + // 输入流转换为字节流 + byte[] buffer = FileCopyUtils.copyToByteArray(in); + FileDownloadVO fileDownloadVO = new FileDownloadVO(); + fileDownloadVO.setData(buffer); + + FileMetadataVO fileMetadataDTO = new FileMetadataVO(); + fileMetadataDTO.setFileName(localFile.getName()); + fileMetadataDTO.setFileSize(localFile.length()); + fileMetadataDTO.setFileFormat(FilenameUtils.getExtension(localFile.getName())); + fileDownloadVO.setMetadata(fileMetadataDTO); + + return ResponseDTO.ok(fileDownloadVO); + } catch (IOException e) { + log.error("文件下载-发生异常:", e); + return ResponseDTO.error(SystemErrorCode.SYSTEM_ERROR, "文件下载失败"); + } finally { + try { + // 关闭输入流 + if (in != null) { + in.close(); + } + } catch (IOException e) { + log.error("文件下载-发生异常:", e); + } + } + } + + @Override + public ResponseDTO delete(String fileKey) { + String filePath = uploadPath + fileKey; + File localFile = new File(filePath); + try { + FileUtils.forceDelete(localFile); + } catch (IOException e) { + log.error("删除本地文件失败:{}", filePath, e); + } + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/IFileStorageService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/IFileStorageService.java new file mode 100644 index 0000000..e4de218 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/file/service/IFileStorageService.java @@ -0,0 +1,96 @@ +package net.lab1024.sa.base.module.support.file.service; + +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileDownloadVO; +import net.lab1024.sa.base.module.support.file.domain.vo.FileUploadVO; +import org.springframework.web.multipart.MultipartFile; + +/** + * 接口 + * + * @Author wzh + * @Date 2019年10月11日 15:34:47 + */ +public interface IFileStorageService { + + /** + * 文件上传 + * + * @param file + * @param path + * @return + */ + ResponseDTO upload(MultipartFile file, String path); + + /** + * 获取文件url + * + * @param fileKey + * @return + */ + ResponseDTO getFileUrl(String fileKey); + + + /** + * 流式下载(名称为原文件) + * + * @param key + * @return + */ + ResponseDTO download(String key); + + /** + * 单个删除文件 + * 根据文件key删除 + * + * @param fileKey + * @return + */ + ResponseDTO delete(String fileKey); + + + /** + * 获取文件类型 + * + * @param fileExt + * @return + */ + default String getContentType(String fileExt) { + // 文件的后缀名 + if ("bmp".equalsIgnoreCase(fileExt)) { + return "image/bmp"; + } + if ("gif".equalsIgnoreCase(fileExt)) { + return "image/gif"; + } + if ("jpeg".equalsIgnoreCase(fileExt) || "jpg".equalsIgnoreCase(fileExt)) { + return "image/jpeg"; + } + if ("png".equalsIgnoreCase(fileExt)) { + return "image/png"; + } + if ("html".equalsIgnoreCase(fileExt)) { + return "text/html"; + } + if ("txt".equalsIgnoreCase(fileExt)) { + return "text/plain"; + } + if ("vsd".equalsIgnoreCase(fileExt)) { + return "application/vnd.visio"; + } + if ("ppt".equalsIgnoreCase(fileExt) || "pptx".equalsIgnoreCase(fileExt)) { + return "application/vnd.ms-powerpoint"; + } + if ("doc".equalsIgnoreCase(fileExt) || "docx".equalsIgnoreCase(fileExt)) { + return "application/msword"; + } + if ("pdf".equalsIgnoreCase(fileExt)) { + return "application/pdf"; + } + if ("xml".equalsIgnoreCase(fileExt)) { + return "text/xml"; + } + return ""; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordDao.java new file mode 100644 index 0000000..2a8dab0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordDao.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.module.support.heartbeat; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordEntity; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordQueryForm; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 心跳记录 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +@Mapper +public interface HeartBeatRecordDao extends BaseMapper { + + /** + * 更新心跳日志 + * + * @param id + * @param heartBeatTime + */ + void updateHeartBeatTimeById(@Param("id") Long id, @Param("heartBeatTime") LocalDateTime heartBeatTime); + + /** + * 查询心跳日志 + * + * @param heartBeatRecordEntity + * @return + */ + HeartBeatRecordEntity query(HeartBeatRecordEntity heartBeatRecordEntity); + + /** + * 分页查询 + * @param heartBeatRecordQueryForm + * @return + */ + List pageQuery(Page page, @Param("query") HeartBeatRecordQueryForm heartBeatRecordQueryForm); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordHandler.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordHandler.java new file mode 100644 index 0000000..0e968b1 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatRecordHandler.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.base.module.support.heartbeat; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.module.support.heartbeat.core.HeartBeatRecord; +import net.lab1024.sa.base.module.support.heartbeat.core.IHeartBeatRecordHandler; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordEntity; +import org.springframework.stereotype.Service; + +/** + * 心跳记录 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +@Slf4j +@Service +public class HeartBeatRecordHandler implements IHeartBeatRecordHandler { + + @Resource + private HeartBeatRecordDao heartBeatRecordDao; + + /** + * 心跳日志处理方法 + * @param heartBeatRecord + */ + @Override + public void handler(HeartBeatRecord heartBeatRecord) { + HeartBeatRecordEntity heartBeatRecordEntity = SmartBeanUtil.copy(heartBeatRecord, HeartBeatRecordEntity.class); + HeartBeatRecordEntity heartBeatRecordOld = heartBeatRecordDao.query(heartBeatRecordEntity); + if (heartBeatRecordOld == null) { + heartBeatRecordDao.insert(heartBeatRecordEntity); + } else { + heartBeatRecordDao.updateHeartBeatTimeById(heartBeatRecordOld.getHeartBeatRecordId(), heartBeatRecordEntity.getHeartBeatTime()); + } + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatService.java new file mode 100644 index 0000000..7f8a0b3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/HeartBeatService.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.heartbeat; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordQueryForm; +import net.lab1024.sa.base.module.support.heartbeat.domain.HeartBeatRecordVO; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 心跳记录 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +@Slf4j +@Service +public class HeartBeatService { + + @Resource + private HeartBeatRecordDao heartBeatRecordDao; + + public ResponseDTO> pageQuery(HeartBeatRecordQueryForm pageParam) { + Page pageQueryInfo = SmartPageUtil.convert2PageQuery(pageParam); + List recordVOList = heartBeatRecordDao.pageQuery(pageQueryInfo,pageParam); + PageResult pageResult = SmartPageUtil.convert2PageResult(pageQueryInfo, recordVOList); + return ResponseDTO.ok(pageResult); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatManager.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatManager.java new file mode 100644 index 0000000..463924c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatManager.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.module.support.heartbeat.core; + +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * 心跳核心调度管理器 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +public class HeartBeatManager { + + private static final String THREAD_NAME_PREFIX = "smart-heart-beat"; + private static final int THREAD_COUNT = 1; + private static final long INITIAL_DELAY = 60 * 1000L; + + private ScheduledThreadPoolExecutor threadPoolExecutor; + + /** + * 服务状态持久化处理类 + */ + private IHeartBeatRecordHandler heartBeatRecordHandler; + + /** + * 调度配置信息 + */ + private long intervalMilliseconds; + + /** + * @param intervalMilliseconds 间隔执行时间(毫秒) + */ + public HeartBeatManager(Long intervalMilliseconds, + IHeartBeatRecordHandler heartBeatRecordHandler) { + this.intervalMilliseconds = intervalMilliseconds; + this.heartBeatRecordHandler = heartBeatRecordHandler; + //使用守护线程去处理 + this.threadPoolExecutor = new ScheduledThreadPoolExecutor(THREAD_COUNT, r -> { + Thread t = new Thread(r, THREAD_NAME_PREFIX); + if (!t.isDaemon()) { + t.setDaemon(true); + } + return t; + }); + // 开始心跳 + this.beginHeartBeat(); + } + + /** + * 开启心跳 + */ + private void beginHeartBeat() { + HeartBeatRunnable heartBeatRunnable = new HeartBeatRunnable(heartBeatRecordHandler); + threadPoolExecutor.scheduleWithFixedDelay(heartBeatRunnable, INITIAL_DELAY, intervalMilliseconds, TimeUnit.MILLISECONDS); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatRecord.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatRecord.java new file mode 100644 index 0000000..c0de8b2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatRecord.java @@ -0,0 +1,38 @@ +package net.lab1024.sa.base.module.support.heartbeat.core; + +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 心跳记录日志 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +@Data +public class HeartBeatRecord { + + /** + * 项目名字 + */ + private String projectPath; + /** + * 服务器ip + */ + private String serverIp; + /** + * 进程号 + */ + private Integer processNo; + /** + * 进程开启时间 + */ + private LocalDateTime processStartTime; + /** + * 心跳当前时间 + */ + private LocalDateTime heartBeatTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatRunnable.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatRunnable.java new file mode 100644 index 0000000..6e051a7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/HeartBeatRunnable.java @@ -0,0 +1,68 @@ +package net.lab1024.sa.base.module.support.heartbeat.core; + +import cn.hutool.core.net.NetUtil; +import org.apache.commons.lang3.StringUtils; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.util.ArrayList; +import java.util.List; + +/** + * 心跳线程 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +public class HeartBeatRunnable implements Runnable { + + /** + * 项目路径 + */ + private String projectPath; + /** + * 服务器ip(多网卡) + */ + private List serverIps; + /** + * 进程号 + */ + private Integer processNo; + /** + * 进程开启时间 + */ + private LocalDateTime processStartTime; + + private IHeartBeatRecordHandler recordHandler; + + public HeartBeatRunnable(IHeartBeatRecordHandler recordHandler) { + this.recordHandler = recordHandler; + this.initServerInfo(); + } + + /** + * 初始化心跳相关信息 + */ + private void initServerInfo(){ + RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean(); + this.projectPath = System.getProperty("user.dir"); + this.serverIps = new ArrayList<>(NetUtil.localIpv4s()); + this.processNo = Integer.valueOf(runtimeMXBean.getName().split("@")[0]).intValue(); + this.processStartTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(runtimeMXBean.getStartTime()), ZoneId.systemDefault()); + } + + + @Override + public void run() { + HeartBeatRecord heartBeatRecord = new HeartBeatRecord(); + heartBeatRecord.setProjectPath(this.projectPath); + heartBeatRecord.setServerIp(StringUtils.join(this.serverIps, ";")); + heartBeatRecord.setProcessNo(this.processNo); + heartBeatRecord.setProcessStartTime(this.processStartTime); + heartBeatRecord.setHeartBeatTime(LocalDateTime.now()); + recordHandler.handler(heartBeatRecord); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/IHeartBeatRecordHandler.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/IHeartBeatRecordHandler.java new file mode 100644 index 0000000..e0a7e9f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/core/IHeartBeatRecordHandler.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.module.support.heartbeat.core; + +/** + * 心跳处理接口 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +public interface IHeartBeatRecordHandler { + + /** + * 心跳日志处理方法 + * + * @param heartBeatRecord + */ + void handler(HeartBeatRecord heartBeatRecord); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordEntity.java new file mode 100644 index 0000000..76e7c6c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordEntity.java @@ -0,0 +1,49 @@ +package net.lab1024.sa.base.module.support.heartbeat.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +/** + * 心跳记录 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +@Data +@TableName(value = "t_heart_beat_record") +public class HeartBeatRecordEntity implements Serializable { + + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long heartBeatRecordId; + + /** + * 项目名字 + */ + private String projectPath; + /** + * 服务器ip + */ + private String serverIp; + /** + * 进程号 + */ + private Integer processNo; + /** + * 进程开启时间 + */ + private LocalDateTime processStartTime; + /** + * 心跳当前时间 + */ + private LocalDateTime heartBeatTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordQueryForm.java new file mode 100644 index 0000000..8e4d2b6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordQueryForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.heartbeat.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +import java.time.LocalDate; + +/** + * 心跳记录 查询 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +@Data +public class HeartBeatRecordQueryForm extends PageParam { + + @Schema(description = "关键字") + private String keywords; + + @Schema(description = "开始日期") + private LocalDate startDate; + + @Schema(description = "结束日期") + private LocalDate endDate; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordVO.java new file mode 100644 index 0000000..2743c15 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/heartbeat/domain/HeartBeatRecordVO.java @@ -0,0 +1,35 @@ +package net.lab1024.sa.base.module.support.heartbeat.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.util.Date; + +/** + * 心跳记录 + * + * @Author wzh + * @Date 2022-01-09 20:57:24 + */ +@Data +public class HeartBeatRecordVO { + + private Integer heartBeatRecordId; + + @Schema(description = "项目路径") + private String projectPath; + + @Schema(description = "服务器ip") + private String serverIp; + + @Schema(description = "进程号") + private Integer processNo; + + @Schema(description = "进程开启时间") + private Date processStartTime; + + @Schema(description = "心跳当前时间") + private Date heartBeatTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/controller/HelpDocController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/controller/HelpDocController.java new file mode 100644 index 0000000..bd112f9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/controller/HelpDocController.java @@ -0,0 +1,74 @@ +package net.lab1024.sa.base.module.support.helpdoc.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocViewRecordQueryForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocCatalogVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocDetailVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocViewRecordVO; +import net.lab1024.sa.base.module.support.helpdoc.service.HelpDocCatalogService; +import net.lab1024.sa.base.module.support.helpdoc.service.HelpDocUserService; +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +/** + * 帮助文档 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Tag(name = SwaggerTagConst.Support.HELP_DOC) +@RestController +public class HelpDocController extends SupportBaseController { + + @Resource + private HelpDocCatalogService helpDocCatalogService; + + @Resource + private HelpDocUserService helpDocUserService; + + // --------------------- 帮助文档 【目录】 ------------------------- + + @Operation(summary = "帮助文档目录-获取全部 @author 卓大") + @GetMapping("/helpDoc/helpDocCatalog/getAll") + public ResponseDTO> getAll() { + return ResponseDTO.ok(helpDocCatalogService.getAll()); + } + + // --------------------- 帮助文档 【用户】------------------------- + + @Operation(summary = "【用户】帮助文档-查看详情 @author 卓大") + @GetMapping("/helpDoc/user/view/{helpDocId}") + @RepeatSubmit + public ResponseDTO view(@PathVariable Long helpDocId, HttpServletRequest request) { + return helpDocUserService.view( + SmartRequestUtil.getRequestUser(), + helpDocId); + } + + @Operation(summary = "【用户】帮助文档-查询全部 @author 卓大") + @GetMapping("/helpDoc/user/queryAllHelpDocList") + @RepeatSubmit + public ResponseDTO> queryAllHelpDocList() { + return helpDocUserService.queryAllHelpDocList(); + } + + + @Operation(summary = "【用户】帮助文档-查询 查看记录 @author 卓大") + @PostMapping("/helpDoc/user/queryViewRecord") + @RepeatSubmit + public ResponseDTO> queryViewRecord(@RequestBody @Valid HelpDocViewRecordQueryForm helpDocViewRecordQueryForm) { + return ResponseDTO.ok(helpDocUserService.queryViewRecord(helpDocViewRecordQueryForm)); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocCatalogDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocCatalogDao.java new file mode 100644 index 0000000..e2e11e5 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocCatalogDao.java @@ -0,0 +1,17 @@ +package net.lab1024.sa.base.module.support.helpdoc.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.helpdoc.domain.entity.HelpDocCatalogEntity; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +/** + * 帮助文档目录 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Mapper +public interface HelpDocCatalogDao extends BaseMapper { + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocDao.java new file mode 100644 index 0000000..1ffcc38 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/dao/HelpDocDao.java @@ -0,0 +1,133 @@ +package net.lab1024.sa.base.module.support.helpdoc.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.helpdoc.domain.entity.HelpDocEntity; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocQueryForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocRelationForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocViewRecordQueryForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocRelationVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocViewRecordVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 帮助文档 dao + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Mapper +public interface HelpDocDao extends BaseMapper { + + // ================================= 帮助文档【主表 t_help_doc 】 ================================= + + + /** + * 查询 全部相关文档 + * + * @return + */ + List queryAllHelpDocList(); + + /** + * 后管分页查询帮助文档 + * + * @param page + * @param queryForm + * @return + */ + List query(Page page, @Param("query") HelpDocQueryForm queryForm); + + + /** + * 更新 阅读量 + * @param helpDocId + * @param userViewCountIncrease + * @param pageViewCountIncrease + */ + void updateViewCount(@Param("helpDocId")Long helpDocId, @Param("userViewCountIncrease")Integer userViewCountIncrease,@Param("pageViewCountIncrease") Integer pageViewCountIncrease); + + + /** + * 根据目录,查询文档 + * + * @param helpDocCatalogId + * @return + */ + List queryHelpDocByCatalogId( @Param("helpDocCatalogId") Long helpDocCatalogId); + + /** + * 根据关联文档id,查询文档 + * + * @param relationId + * @return + */ + List queryHelpDocByRelationId( @Param("relationId") Long relationId); + + // ================================= 关联项目 【子表 t_help_doc_relation 】 ================================= + + /** + * 保存 关联 + * + * @param helpDocId + * @param relationList + */ + void insertRelation(@Param("helpDocId") Long helpDocId, @Param("relationList") List relationList); + + /** + * 删除关联 + * + * @param helpDocId + */ + void deleteRelation(@Param("helpDocId") Long helpDocId); + + /** + * 查询关联 + * + * @param helpDocId + */ + List queryRelationByHelpDoc(@Param("helpDocId") Long helpDocId); + + // ================================= 查看记录【子表 t_help_doc_view_record】 ================================= + + /** + * 查询某个用户的指定文档的阅读量 + * @param helpDocId + * @param userId + * @return + */ + long viewRecordCount(@Param("helpDocId")Long helpDocId, @Param("userId")Long userId); + + /** + * 查询帮助文档的 查看记录 + * @param page + * @param helpDocViewRecordQueryForm + * @return + */ + List queryViewRecordList(Page page, @Param("queryForm") HelpDocViewRecordQueryForm helpDocViewRecordQueryForm); + + /** + * 保存查看记录 + * @param helpDocId + * @param userId + * @param userName + * @param ip + * @param userAgent + */ + void insertViewRecord(@Param("helpDocId") Long helpDocId, @Param("userId") Long userId, @Param("userName") String userName, @Param("ip") String ip, @Param("userAgent") String userAgent,@Param("pageViewCount") Integer pageViewCount); + + /** + * 更新查看记录 + * @param helpDocId + * @param userId + * @param ip + * @param userAgent + */ + void updateViewRecord(@Param("helpDocId")Long helpDocId, @Param("userId")Long userId,@Param("ip") String ip, @Param("userAgent")String userAgent); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/entity/HelpDocCatalogEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/entity/HelpDocCatalogEntity.java new file mode 100644 index 0000000..3bea152 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/entity/HelpDocCatalogEntity.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * 帮助文档的 类型 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +@TableName("t_help_doc_catalog") +@NoArgsConstructor +@AllArgsConstructor +@Builder +public class HelpDocCatalogEntity { + + @TableId(type = IdType.AUTO) + private Long helpDocCatalogId; + + /** + * 名称 + */ + private String name; + + /** + * 父id + */ + private Long parentId; + + /** + * 排序 + */ + @TableField("`sort`") + private Integer sort; + + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/entity/HelpDocEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/entity/HelpDocEntity.java new file mode 100644 index 0000000..7ffc14c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/entity/HelpDocEntity.java @@ -0,0 +1,74 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.entity; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 帮助文档 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +@TableName("t_help_doc") +public class HelpDocEntity { + + @TableId(type = IdType.AUTO) + private Long helpDocId; + + /** + * 类型 + */ + private Long helpDocCatalogId; + + /** + * 标题 + */ + private String title; + + /** + * 内容 纯文本 + */ + private String contentText; + + /** + * 内容 html + */ + private String contentHtml; + + /** + * 附件 + * 多个英文逗号分隔 + */ + private String attachment; + + /** + * 排序 + */ + @TableField("`sort`") + private Integer sort; + + /** + * 页面浏览量 + */ + private Integer pageViewCount; + + /** + * 用户浏览量 + */ + private Integer userViewCount; + + /** + * 作者 + */ + private String author; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocAddForm.java new file mode 100644 index 0000000..6789cfd --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocAddForm.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.form; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.json.deserializer.FileKeyVoDeserializer; +import org.hibernate.validator.constraints.Length; + +import java.util.List; + +/** + * 帮助文档 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocAddForm { + + @Schema(description = "标题") + @NotBlank(message = "标题不能为空") + @Length(max = 200, message = "标题最多200字符") + private String title; + + @Schema(description = "分类") + @NotNull(message = "分类不能为空") + private Long helpDocCatalogId; + + @Schema(description = "纯文本内容") + @NotNull(message = "文本内容不能为空") + private String contentText; + + @Schema(description = "html内容") + @NotNull(message = "html内容不能为空") + private String contentHtml; + + @Schema(description = "附件,多个英文逗号分隔|可选") + @Length(max = 1000, message = "最多1000字符") + @JsonDeserialize(using = FileKeyVoDeserializer.class) + private String attachment; + + @Schema(description = "排序") + @NotNull(message = "排序不能为空") + private Integer sort; + + @Schema(description = "关联的集合") + private List relationList; + + @Schema(description = "作者") + @NotBlank(message = "作者不能为空") + private String author; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocCatalogAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocCatalogAddForm.java new file mode 100644 index 0000000..c171a01 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocCatalogAddForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 帮助文档 目录 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocCatalogAddForm { + + @Schema(description = "名称") + @NotBlank(message = "名称不能为空") + @Length(max = 200, message = "名称最多200字符") + private String name; + + @Schema(description = "父级") + private Long parentId; + + @Schema(description = "排序") + private Integer sort; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocCatalogUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocCatalogUpdateForm.java new file mode 100644 index 0000000..a54da48 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocCatalogUpdateForm.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 帮助文档 目录 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocCatalogUpdateForm extends HelpDocCatalogAddForm { + + @Schema(description = "id") + @NotNull(message = "id") + private Long helpDocCatalogId; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocQueryForm.java new file mode 100644 index 0000000..a0e9b5a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocQueryForm.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +import java.time.LocalDate; + +/** + * 帮助文档 分页查询 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocQueryForm extends PageParam { + + @Schema(description = "分类") + private Long helpDocCatalogId; + + @Schema(description = "标题") + private String keywords; + + @Schema(description = "创建-开始时间") + private LocalDate createTimeBegin; + + @Schema(description = "创建-截止时间") + private LocalDate createTimeEnd; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocRelationForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocRelationForm.java new file mode 100644 index 0000000..d3bde32 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocRelationForm.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 帮助文档 关联项目 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocRelationForm { + + @Schema(description = "关联名称") + @NotBlank(message = "关联名称不能为空") + private String relationName; + + @Schema(description = "关联id") + @NotNull(message = "关联id不能为空") + private Long relationId; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocUpdateForm.java new file mode 100644 index 0000000..51ca19c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocUpdateForm.java @@ -0,0 +1,20 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 更新 帮助文档 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocUpdateForm extends HelpDocAddForm { + + @Schema(description = "id") + @NotNull(message = "通知id不能为空") + private Long helpDocId; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocViewRecordQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocViewRecordQueryForm.java new file mode 100644 index 0000000..29fc7a0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/form/HelpDocViewRecordQueryForm.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.form; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +/** + * 查阅记录 查询 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocViewRecordQueryForm extends PageParam { + + @Schema(description = "帮助文档id") + @NotNull(message = "帮助文档id不能为空") + private Long helpDocId; + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "关键字") + private String keywords; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocCatalogVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocCatalogVO.java new file mode 100644 index 0000000..31ba477 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocCatalogVO.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 帮助文档的 目录 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocCatalogVO { + + @Schema(description = "帮助文档目录id") + private Long helpDocCatalogId; + + @Schema(description = "帮助文档目录-名称") + private String name; + + @Schema(description = "帮助文档目录-父级id") + private Long parentId; + + @Schema(description = "帮助文档目录-排序") + private Integer sort; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocDetailVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocDetailVO.java new file mode 100644 index 0000000..55756ea --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocDetailVO.java @@ -0,0 +1,62 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.vo; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; +import net.lab1024.sa.base.common.json.serializer.FileKeyVoSerializer; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 帮助文档 详情 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocDetailVO { + + @Schema(description = "id") + private Long helpDocId; + + @Schema(description = "标题") + private String title; + + @Schema(description = "分类") + private Long helpDocCatalogId; + + @Schema(description = "分类名称") + private Long helpDocCatalogName; + + @Schema(description = "纯文本内容") + private String contentText; + + @Schema(description = "html内容") + private String contentHtml; + + @Schema(description = "附件") + @JsonSerialize(using = FileKeyVoSerializer.class) + private String attachment; + + @Schema(description = "作者") + @NotBlank(message = "作者不能为空") + private String author; + + @Schema(description = "页面浏览量") + private Integer pageViewCount; + + @Schema(description = "用户浏览量") + private Integer userViewCount; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @Schema(description = "关联项目") + private List relationList; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocRecordVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocRecordVO.java new file mode 100644 index 0000000..b63ff7b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocRecordVO.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 帮助文档 - 浏览记录 VO + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocRecordVO { + + @Schema(description = "员工ID") + private Long employeeId; + + @Schema(description = "员工姓名") + private String employeeName; + + @Schema(description = "员工部门名称") + private String departmentName; + + @Schema(description = "查看次数") + private Integer pageViewCount; + + @Schema(description = "首次ip") + private String firstIp; + + @Schema(description = "首次用户设备等标识") + private String firstUserAgent; + + @Schema(description = "首次查看时间") + private LocalDateTime createTime; + + @Schema(description = "最后一次 ip") + private String lastIp; + + @Schema(description = "最后一次 用户设备等标识") + private String lastUserAgent; + + @Schema(description = "最后一次查看时间") + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocRelationVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocRelationVO.java new file mode 100644 index 0000000..56f3fdc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocRelationVO.java @@ -0,0 +1,20 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 帮助文档 关联项目 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocRelationVO { + + @Schema(description = "关联名称") + private String relationName; + + @Schema(description = "关联id") + private Long relationId; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocVO.java new file mode 100644 index 0000000..9eb9ee2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocVO.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 帮助文档 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocVO { + + @Schema(description = "id") + private Long helpDocId; + + @Schema(description = "标题") + private String title; + + @Schema(description = "分类") + private Long helpDocCatalogId; + + @Schema(description = "分类名称") + private String helpDocCatalogName; + + @Schema(description = "作者") + private String author; + + @Schema(description = "排序") + private Integer sort; + + @Schema(description = "页面浏览量") + private Integer pageViewCount; + + @Schema(description = "用户浏览量") + private Integer userViewCount; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocViewRecordVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocViewRecordVO.java new file mode 100644 index 0000000..aef202f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/domain/vo/HelpDocViewRecordVO.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.base.module.support.helpdoc.domain.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 帮助文档 - 浏览记录 VO + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Data +public class HelpDocViewRecordVO { + + @Schema(description = "ID") + private Long userId; + + @Schema(description = "姓名") + private String userName; + + @Schema(description = "查看次数") + private Integer pageViewCount; + + @Schema(description = "首次ip") + private String firstIp; + + @Schema(description = "首次用户设备等标识") + private String firstUserAgent; + + @Schema(description = "首次查看时间") + private LocalDateTime createTime; + + @Schema(description = "最后一次 ip") + private String lastIp; + + @Schema(description = "最后一次 用户设备等标识") + private String lastUserAgent; + + @Schema(description = "最后一次查看时间") + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/manager/HelpDocManager.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/manager/HelpDocManager.java new file mode 100644 index 0000000..12bc5d8 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/manager/HelpDocManager.java @@ -0,0 +1,57 @@ +package net.lab1024.sa.base.module.support.helpdoc.manager; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.module.support.helpdoc.dao.HelpDocDao; +import net.lab1024.sa.base.module.support.helpdoc.domain.entity.HelpDocEntity; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocRelationForm; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 帮助文档 manager + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Service +public class HelpDocManager { + + @Resource + private HelpDocDao helpDocDao; + + /** + * 保存 + * + * @param helpDocEntity + * @param relationList + */ + @Transactional(rollbackFor = Throwable.class) + public void save(HelpDocEntity helpDocEntity, List relationList) { + helpDocDao.insert(helpDocEntity); + Long helpDocId = helpDocEntity.getHelpDocId(); + // 保存关联 + if (CollectionUtils.isNotEmpty(relationList)) { + helpDocDao.insertRelation(helpDocId, relationList); + } + } + + /** + * 更新 + * + * @param helpDocEntity + * @param relationList + */ + @Transactional(rollbackFor = Throwable.class) + public void update(HelpDocEntity helpDocEntity, List relationList) { + helpDocDao.updateById(helpDocEntity); + Long helpDocId = helpDocEntity.getHelpDocId(); + // 保存关联 + if (CollectionUtils.isNotEmpty(relationList)) { + helpDocDao.deleteRelation(helpDocId); + helpDocDao.insertRelation(helpDocId, relationList); + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocCatalogService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocCatalogService.java new file mode 100644 index 0000000..c88630f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocCatalogService.java @@ -0,0 +1,112 @@ +package net.lab1024.sa.base.module.support.helpdoc.service; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.module.support.helpdoc.dao.HelpDocCatalogDao; +import net.lab1024.sa.base.module.support.helpdoc.dao.HelpDocDao; +import net.lab1024.sa.base.module.support.helpdoc.domain.entity.HelpDocCatalogEntity; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocCatalogAddForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocCatalogUpdateForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocCatalogVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocVO; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * 帮助文档 目录 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Service +public class HelpDocCatalogService { + + @Resource + private HelpDocCatalogDao helpDocCatalogDao; + + @Resource + private HelpDocDao helpDocDao; + + /** + * 查询全部目录 + * + * @return + */ + public List getAll() { + return SmartBeanUtil.copyList(helpDocCatalogDao.selectList(null), HelpDocCatalogVO.class); + } + + /** + * 添加目录 + * + * @param helpDocCatalogAddForm + * @return + */ + public synchronized ResponseDTO add(HelpDocCatalogAddForm helpDocCatalogAddForm) { + List helpDocCatalogList = getAll(); + Optional exist = helpDocCatalogList.stream().filter(e -> helpDocCatalogAddForm.getName().equals(e.getName())).findFirst(); + if (exist.isPresent()) { + return ResponseDTO.userErrorParam("存在相同名称的目录了"); + } + + helpDocCatalogDao.insert(SmartBeanUtil.copy(helpDocCatalogAddForm, HelpDocCatalogEntity.class)); + return ResponseDTO.ok(); + } + + /** + * 更新目录 + * + * @param updateForm + * @return + */ + public synchronized ResponseDTO update(HelpDocCatalogUpdateForm updateForm) { + HelpDocCatalogEntity helpDocCatalogEntity = helpDocCatalogDao.selectById(updateForm.getHelpDocCatalogId()); + if (helpDocCatalogEntity == null) { + return ResponseDTO.userErrorParam("目录不存在"); + } + + List helpDocCatalogList = getAll(); + Optional exist = helpDocCatalogList.stream().filter(e -> updateForm.getName().equals(e.getName())).findFirst(); + if (exist.isPresent() && !exist.get().getHelpDocCatalogId().equals(updateForm.getHelpDocCatalogId())) { + return ResponseDTO.userErrorParam("存在相同名称的目录了"); + } + helpDocCatalogDao.updateById(SmartBeanUtil.copy(updateForm, HelpDocCatalogEntity.class)); + return ResponseDTO.ok(); + } + + /** + * 删除目录(如果有子目录、或者有帮助文档,则不能删除) + * + * @param helpDocCatalogId + * @return + */ + public synchronized ResponseDTO delete(Long helpDocCatalogId) { + if (helpDocCatalogId == null) { + return ResponseDTO.ok(); + } + + HelpDocCatalogEntity helpDocCatalogEntity = helpDocCatalogDao.selectById(helpDocCatalogId); + if (helpDocCatalogEntity == null) { + return ResponseDTO.userErrorParam("目录不存在"); + } + + //如果有子目录,则不能删除 + Optional existOptional = getAll().stream().filter(e -> helpDocCatalogId.equals(e.getParentId())).findFirst(); + if (existOptional.isPresent()) { + return ResponseDTO.userErrorParam("存在子目录:" + existOptional.get().getName()); + } + + //查询是否有帮助文档 + List helpDocVOList = helpDocDao.queryHelpDocByCatalogId(helpDocCatalogId); + if (CollectionUtils.isNotEmpty(helpDocVOList)) { + return ResponseDTO.userErrorParam("目录下存在文档,不能删除"); + } + helpDocCatalogDao.deleteById(helpDocCatalogId); + return ResponseDTO.ok(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocService.java new file mode 100644 index 0000000..4dd241d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocService.java @@ -0,0 +1,117 @@ +package net.lab1024.sa.base.module.support.helpdoc.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.helpdoc.dao.HelpDocDao; +import net.lab1024.sa.base.module.support.helpdoc.domain.entity.HelpDocEntity; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocAddForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocQueryForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocUpdateForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocDetailVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocVO; +import net.lab1024.sa.base.module.support.helpdoc.manager.HelpDocManager; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 后台管理业务 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Service +public class HelpDocService { + + @Resource + private HelpDocDao helpDocDao; + + @Resource + private HelpDocManager helpDaoManager; + + + /** + * 查询 帮助文档 + * + * @param queryForm + * @return + */ + public PageResult query(HelpDocQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = helpDocDao.query(page, queryForm); + return SmartPageUtil.convert2PageResult(page, list); + } + + /** + * 添加 + * + * @param addForm + * @return + */ + public ResponseDTO add(HelpDocAddForm addForm) { + HelpDocEntity helpDaoEntity = SmartBeanUtil.copy(addForm, HelpDocEntity.class); + helpDaoManager.save(helpDaoEntity, addForm.getRelationList()); + return ResponseDTO.ok(); + } + + + /** + * 更新 + * + * @param updateForm + * @return + */ + public ResponseDTO update(HelpDocUpdateForm updateForm) { + // 更新 + HelpDocEntity helpDaoEntity = SmartBeanUtil.copy(updateForm, HelpDocEntity.class); + helpDaoManager.update(helpDaoEntity, updateForm.getRelationList()); + return ResponseDTO.ok(); + } + + + /** + * 删除 + * + * @param helpDocId + * @return + */ + @Transactional(rollbackFor = Exception.class) + public ResponseDTO delete(Long helpDocId) { + HelpDocEntity helpDaoEntity = helpDocDao.selectById(helpDocId); + if (helpDaoEntity != null) { + helpDocDao.deleteById(helpDocId); + helpDocDao.deleteRelation(helpDocId); + } + return ResponseDTO.ok(); + } + + /** + * 获取详情 + * + * @param helpDocId + * @return + */ + public HelpDocDetailVO getDetail(Long helpDocId) { + HelpDocEntity helpDaoEntity = helpDocDao.selectById(helpDocId); + HelpDocDetailVO detail = SmartBeanUtil.copy(helpDaoEntity, HelpDocDetailVO.class); + if (detail != null) { + detail.setRelationList(helpDocDao.queryRelationByHelpDoc(helpDocId)); + } + return detail; + } + + /** + * 获取详情 + * + * @param relationId + * @return + */ + public List queryHelpDocByRelationId(Long relationId) { + return helpDocDao.queryHelpDocByRelationId(relationId); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocUserService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocUserService.java new file mode 100644 index 0000000..d7043f9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/helpdoc/service/HelpDocUserService.java @@ -0,0 +1,82 @@ +package net.lab1024.sa.base.module.support.helpdoc.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.helpdoc.dao.HelpDocDao; +import net.lab1024.sa.base.module.support.helpdoc.domain.entity.HelpDocEntity; +import net.lab1024.sa.base.module.support.helpdoc.domain.form.HelpDocViewRecordQueryForm; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocDetailVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocVO; +import net.lab1024.sa.base.module.support.helpdoc.domain.vo.HelpDocViewRecordVO; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 用户查看 帮助文档 + * + * @Author wzh + * @Date 2022-08-20 23:11:42 + */ +@Service +public class HelpDocUserService { + + @Resource + private HelpDocDao helpDocDao; + + + /** + * 查询全部 帮助文档 + * + * @return + */ + public ResponseDTO> queryAllHelpDocList() { + return ResponseDTO.ok(helpDocDao.queryAllHelpDocList()); + } + + + /** + * 查询我的 待查看的 帮助文档清单 + * + * @return + */ + public ResponseDTO view(RequestUser requestUser, Long helpDocId) { + HelpDocEntity helpDocEntity = helpDocDao.selectById(helpDocId); + if (helpDocEntity == null) { + return ResponseDTO.userErrorParam("帮助文档不存在"); + } + + HelpDocDetailVO helpDocDetailVO = SmartBeanUtil.copy(helpDocEntity, HelpDocDetailVO.class); + long viewCount = helpDocDao.viewRecordCount(helpDocId, requestUser.getUserId()); + if (viewCount == 0) { + helpDocDao.insertViewRecord(helpDocId, requestUser.getUserId(), requestUser.getUserName(), requestUser.getIp(), requestUser.getUserAgent(), 1); + helpDocDao.updateViewCount(helpDocId, 1, 1); + helpDocDetailVO.setPageViewCount(helpDocDetailVO.getPageViewCount() + 1); + helpDocDetailVO.setUserViewCount(helpDocDetailVO.getUserViewCount() + 1); + } else { + helpDocDao.updateViewRecord(helpDocId, requestUser.getUserId(), requestUser.getIp(), requestUser.getUserAgent()); + helpDocDao.updateViewCount(helpDocId, 0, 1); + helpDocDetailVO.setPageViewCount(helpDocDetailVO.getPageViewCount() + 1); + } + + return ResponseDTO.ok(helpDocDetailVO); + } + + + /** + * 分页查询 查看记录 + * + * @param helpDocViewRecordQueryForm + * @return + */ + public PageResult queryViewRecord(HelpDocViewRecordQueryForm helpDocViewRecordQueryForm) { + Page page = SmartPageUtil.convert2PageQuery(helpDocViewRecordQueryForm); + List noticeViewRecordVOS = helpDocDao.queryViewRecordList(page, helpDocViewRecordQueryForm); + return SmartPageUtil.convert2PageResult(page, noticeViewRecordVOS); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/SmartJobClientManager.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/SmartJobClientManager.java new file mode 100644 index 0000000..6c61dd2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/SmartJobClientManager.java @@ -0,0 +1,164 @@ +package net.lab1024.sa.base.module.support.job.api; + +import cn.hutool.core.util.IdUtil; +import com.google.common.collect.Lists; +import jakarta.annotation.PreDestroy; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.job.api.domain.SmartJobMsg; +import net.lab1024.sa.base.module.support.job.config.SmartJobAutoConfiguration; +import net.lab1024.sa.base.module.support.job.core.SmartJob; +import net.lab1024.sa.base.module.support.job.core.SmartJobExecutor; +import net.lab1024.sa.base.module.support.job.core.SmartJobLauncher; +import net.lab1024.sa.base.module.support.job.repository.SmartJobRepository; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobEntity; +import org.redisson.api.RLock; +import org.redisson.api.RTopic; +import org.redisson.api.RedissonClient; +import org.redisson.api.listener.MessageListener; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.concurrent.TimeUnit; + +/** + * smart job 执行端管理 + * 分布式系统之间 用发布/订阅消息的形式 来管理多个job + * + * @author huke + * @date 2024/6/22 20:31 + */ +@ConditionalOnBean(SmartJobAutoConfiguration.class) +@Slf4j +@Service +public class SmartJobClientManager { + + private final SmartJobLauncher jobLauncher; + + private final SmartJobRepository jobRepository; + + private final List jobInterfaceList; + + private static final String EXECUTE_LOCK = "smart-job-lock-msg-execute-"; + + private static final String TOPIC = "smart-job-instance"; + + private final RedissonClient redissonClient; + + private final RTopic topic; + + private final SmartJobMsgListener jobMsgListener; + + public SmartJobClientManager(SmartJobLauncher jobLauncher, + SmartJobRepository jobRepository, + List jobInterfaceList, + RedissonClient redissonClient) { + this.jobLauncher = jobLauncher; + this.jobRepository = jobRepository; + this.jobInterfaceList = jobInterfaceList; + this.redissonClient = redissonClient; + + // 添加监听器 + this.topic = redissonClient.getTopic(TOPIC); + this.jobMsgListener = new SmartJobMsgListener(); + topic.addListener(SmartJobMsg.class, jobMsgListener); + log.info("==== SmartJob ==== client-manager init"); + } + + /** + * 发布消息 + */ + public void publishToClient(SmartJobMsg msgDTO) { + msgDTO.setMsgId(IdUtil.fastSimpleUUID()); + topic.publish(msgDTO); + } + + /** + * 处理消息 + */ + private class SmartJobMsgListener implements MessageListener { + + @Override + public void onMessage(CharSequence channel, SmartJobMsg msg) { + log.info("==== SmartJob ==== on-message :{}", msg); + // 判断消息类型 业务简单就直接判断 复杂的话可以策略模式 + SmartJobMsg.MsgTypeEnum msgType = msg.getMsgType(); + // 更新任务 + if (SmartJobMsg.MsgTypeEnum.UPDATE_JOB == msgType) { + updateJob(msg.getJobId()); + } + // 执行任务 + if (SmartJobMsg.MsgTypeEnum.EXECUTE_JOB == msgType) { + executeJob(msg); + } + } + } + + /** + * 获取任务执行类 + * + * @param jobClass + * @return + */ + private Optional queryJobImpl(String jobClass) { + return jobInterfaceList.stream().filter(e -> Objects.equals(e.getClassName(), jobClass)).findFirst(); + } + + /** + * 更新任务 + * + * @param jobId + */ + private void updateJob(Integer jobId) { + SmartJobEntity jobEntity = jobRepository.getJobDao().selectById(jobId); + if (null == jobEntity) { + return; + } + jobLauncher.startOrRefreshJob(Lists.newArrayList(jobEntity)); + } + + /** + * 立即执行任务 + * + * @param msg + */ + private void executeJob(SmartJobMsg msg) { + Integer jobId = msg.getJobId(); + SmartJobEntity jobEntity = jobRepository.getJobDao().selectById(jobId); + if (null == jobEntity) { + return; + } + // 获取定时任务实现类 + Optional optional = this.queryJobImpl(jobEntity.getJobClass()); + if (!optional.isPresent()) { + return; + } + + // 获取执行锁 无需主动释放 + RLock rLock = redissonClient.getLock(EXECUTE_LOCK + msg.getMsgId()); + try { + boolean getLock = rLock.tryLock(0, 20, TimeUnit.SECONDS); + if (!getLock) { + return; + } + } catch (InterruptedException e) { + log.error("==== SmartJob ==== msg execute err:", e); + return; + } + + // 通过执行器 执行任务 + jobEntity.setParam(msg.getParam()); + SmartJobExecutor jobExecutor = new SmartJobExecutor(jobEntity, jobRepository, optional.get(), redissonClient); + jobExecutor.execute(msg.getUpdateName()); + } + + + @PreDestroy + public void destroy() { + topic.removeListener(jobMsgListener); + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/SmartJobService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/SmartJobService.java new file mode 100644 index 0000000..836f42f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/SmartJobService.java @@ -0,0 +1,296 @@ +package net.lab1024.sa.base.module.support.job.api; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.job.api.domain.*; +import net.lab1024.sa.base.module.support.job.config.SmartJobAutoConfiguration; +import net.lab1024.sa.base.module.support.job.constant.SmartJobTriggerTypeEnum; +import net.lab1024.sa.base.module.support.job.constant.SmartJobUtil; +import net.lab1024.sa.base.module.support.job.repository.SmartJobDao; +import net.lab1024.sa.base.module.support.job.repository.SmartJobLogDao; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobEntity; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobLogEntity; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.stream.Collectors; + +/** + * 定时任务 接口业务管理 + * 如果不需要通过接口管理定时任务 可以删除此类 + * + * @author huke + * @date 2024/6/17 20:41 + */ +@ConditionalOnBean(SmartJobAutoConfiguration.class) +@Service +public class SmartJobService { + + @Resource + private SmartJobDao jobDao; + + @Resource + private SmartJobLogDao jobLogDao; + + @Resource + private SmartJobClientManager jobClientManager; + + /** + * 查询 定时任务详情 + * + * @param jobId + * @return + */ + public ResponseDTO queryJobInfo(Integer jobId) { + SmartJobEntity jobEntity = jobDao.selectById(jobId); + if (null == jobEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + SmartJobVO jobVO = SmartBeanUtil.copy(jobEntity, SmartJobVO.class); + // 处理设置job详情 + this.handleJobInfo(Lists.newArrayList(jobVO)); + return ResponseDTO.ok(jobVO); + } + + /** + * 分页查询 定时任务 + * + * @param queryForm + * @return + */ + public ResponseDTO> queryJob(SmartJobQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List jobList = jobDao.query(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, jobList); + // 处理设置job详情 + this.handleJobInfo(jobList); + return ResponseDTO.ok(pageResult); + } + + /** + * 处理设置 任务信息 + * + * @param jobList + */ + private void handleJobInfo(List jobList) { + if (CollectionUtils.isEmpty(jobList)) { + return; + } + // 查询最后一次执行记录 + List logIdList = jobList.stream().map(SmartJobVO::getLastExecuteLogId).filter(Objects::nonNull).collect(Collectors.toList()); + Map lastLogMap = Collections.emptyMap(); + if (CollectionUtils.isNotEmpty(logIdList)) { + lastLogMap = jobLogDao.selectBatchIds(logIdList) + .stream() + .collect(Collectors.toMap(SmartJobLogEntity::getLogId, e -> SmartBeanUtil.copy(e, SmartJobLogVO.class))); + } + + // 循环处理任务信息 + for (SmartJobVO jobVO : jobList) { + // 设置最后一次执行记录 + Long lastExecuteLogId = jobVO.getLastExecuteLogId(); + if (null != lastExecuteLogId) { + jobVO.setLastJobLog(lastLogMap.get(lastExecuteLogId)); + } + // 计算未来5次执行时间 + if (jobVO.getEnabledFlag()) { + List nextTimeList = SmartJobUtil.queryNextTimeFromNow(jobVO.getTriggerType(), jobVO.getTriggerValue(), jobVO.getLastExecuteTime(), 5); + jobVO.setNextJobExecuteTimeList(nextTimeList); + } + } + } + + /** + * 分页查询 定时任务-执行记录 + * + * @param queryForm + * @return + */ + public ResponseDTO> queryJobLog(SmartJobLogQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List jobList = jobLogDao.query(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, jobList); + return ResponseDTO.ok(pageResult); + } + + /** + * 添加定时任务 + * + * @param addForm + * @return + */ + public synchronized ResponseDTO addJob(SmartJobAddForm addForm) { + // 校验参数 + ResponseDTO checkRes = this.checkParam(addForm); + if (!checkRes.getOk()) { + return checkRes; + } + + // 校验重复的执行类 + SmartJobEntity existJobClass = jobDao.selectByJobClass(addForm.getJobClass()); + if (null != existJobClass && !existJobClass.getDeletedFlag()) { + return ResponseDTO.userErrorParam("已经存在相同的执行类"); + } + + // 添加数据 + SmartJobEntity jobEntity = SmartBeanUtil.copy(addForm, SmartJobEntity.class); + jobDao.insert(jobEntity); + + // 更新执行端 + SmartJobMsg jobMsg = new SmartJobMsg(); + jobMsg.setJobId(jobEntity.getJobId()); + jobMsg.setMsgType(SmartJobMsg.MsgTypeEnum.UPDATE_JOB); + jobMsg.setUpdateName(addForm.getUpdateName()); + jobClientManager.publishToClient(jobMsg); + return ResponseDTO.ok(); + } + + /** + * 更新定时任务 + * + * @param updateForm + * @return + */ + public synchronized ResponseDTO updateJob(SmartJobUpdateForm updateForm) { + // 校验参数 + Integer jobId = updateForm.getJobId(); + SmartJobEntity jobEntity = jobDao.selectById(jobId); + if (null == jobEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + ResponseDTO checkRes = this.checkParam(updateForm); + if (!checkRes.getOk()) { + return checkRes; + } + + // 校验重复的执行类 + SmartJobEntity existJobClass = jobDao.selectByJobClass(updateForm.getJobClass()); + if (null != existJobClass && !existJobClass.getDeletedFlag() && !existJobClass.getJobId().equals(jobId)) { + return ResponseDTO.userErrorParam("已经存在相同的执行类"); + } + + // 更新数据 + jobEntity = SmartBeanUtil.copy(updateForm, SmartJobEntity.class); + jobDao.updateById(jobEntity); + + // 更新执行端 + SmartJobMsg jobMsg = new SmartJobMsg(); + jobMsg.setJobId(jobId); + jobMsg.setMsgType(SmartJobMsg.MsgTypeEnum.UPDATE_JOB); + jobMsg.setUpdateName(updateForm.getUpdateName()); + jobClientManager.publishToClient(jobMsg); + return ResponseDTO.ok(); + } + + /** + * 校验参数 + * 如需其他校验,请自行添加校验逻辑 + * + * @param addForm + * @return + */ + private ResponseDTO checkParam(SmartJobAddForm addForm) { + // 校验触发时间配置 + String triggerType = addForm.getTriggerType(); + String triggerValue = addForm.getTriggerValue(); + if (SmartJobTriggerTypeEnum.CRON.equalsValue(triggerType) && !SmartJobUtil.checkCron(triggerValue)) { + return ResponseDTO.userErrorParam("cron表达式错误"); + } + if (SmartJobTriggerTypeEnum.FIXED_DELAY.equalsValue(triggerType) && !SmartJobUtil.checkFixedDelay(triggerValue)) { + return ResponseDTO.userErrorParam("固定间隔配置错误:必须是大于0的整数"); + } + // 校验job class + return SmartJobUtil.checkJobClass(addForm.getJobClass()); + } + + /** + * 更新定时任务-是否开启 + * + * @param updateForm + * @return + */ + public ResponseDTO updateJobEnabled(SmartJobEnabledUpdateForm updateForm) { + Integer jobId = updateForm.getJobId(); + SmartJobEntity jobEntity = jobDao.selectById(jobId); + if (null == jobEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + Boolean enabledFlag = updateForm.getEnabledFlag(); + if (Objects.equals(enabledFlag, jobEntity.getEnabledFlag())) { + return ResponseDTO.ok(); + } + // 更新数据 + jobEntity = new SmartJobEntity(); + jobEntity.setJobId(jobId); + jobEntity.setEnabledFlag(enabledFlag); + jobEntity.setUpdateName(updateForm.getUpdateName()); + jobDao.updateById(jobEntity); + + // 更新执行端 + SmartJobMsg jobMsg = new SmartJobMsg(); + jobMsg.setJobId(jobId); + jobMsg.setMsgType(SmartJobMsg.MsgTypeEnum.UPDATE_JOB); + jobMsg.setUpdateName(updateForm.getUpdateName()); + jobClientManager.publishToClient(jobMsg); + return ResponseDTO.ok(); + } + + /** + * 执行定时任务 + * 忽略任务的开启状态,立即执行一次 + * + * @param executeForm + * @return + */ + public ResponseDTO execute(SmartJobExecuteForm executeForm) { + Integer jobId = executeForm.getJobId(); + SmartJobEntity jobEntity = jobDao.selectById(jobId); + if (null == jobEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + + // 更新执行端 + SmartJobMsg jobMsg = new SmartJobMsg(); + jobMsg.setJobId(jobId); + jobMsg.setParam(executeForm.getParam()); + jobMsg.setMsgType(SmartJobMsg.MsgTypeEnum.EXECUTE_JOB); + jobMsg.setUpdateName(executeForm.getUpdateName()); + jobClientManager.publishToClient(jobMsg); + return ResponseDTO.ok(); + } + + /** + * 移除定时任务 + * 物理删除 + * + * @return + * @author huke + */ + public synchronized ResponseDTO deleteJob(Integer jobId, RequestUser requestUser) { + // 删除任务 + jobDao.updateDeletedFlag(jobId, Boolean.TRUE); + + // 更新执行端 + SmartJobMsg jobMsg = new SmartJobMsg(); + jobMsg.setJobId(jobId); + jobMsg.setMsgType(SmartJobMsg.MsgTypeEnum.UPDATE_JOB); + jobMsg.setUpdateName(requestUser.getUserName()); + jobClientManager.publishToClient(jobMsg); + return ResponseDTO.ok(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobAddForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobAddForm.java new file mode 100644 index 0000000..0ca70f1 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobAddForm.java @@ -0,0 +1,58 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.job.constant.SmartJobTriggerTypeEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 定时任务 添加 + * + * @author huke + * @date 2024/12/19 19:30 + */ +@Data +public class SmartJobAddForm { + + @Schema(description = "任务名称") + @NotBlank(message = "任务名称不能为空") + @Length(max = 100, message = "任务名称最多100字符") + private String jobName; + + @Schema(description = "任务执行类") + @NotBlank(message = "任务执行类不能为空") + @Length(max = 200, message = "任务执行类最多200字符") + private String jobClass; + + @SchemaEnum(desc = "触发类型", value = SmartJobTriggerTypeEnum.class) + @CheckEnum(value = SmartJobTriggerTypeEnum.class, required = true, message = "触发类型错误") + private String triggerType; + + @Schema(description = "触发配置") + @NotBlank(message = "触发配置不能为空") + @Length(max = 100, message = "触发配置最多100字符") + private String triggerValue; + + @Schema(description = "定时任务参数|可选") + @Length(max = 1000, message = "定时任务参数最多1000字符") + private String param; + + @Schema(description = "是否开启") + @NotNull(message = "是否开启不能为空") + private Boolean enabledFlag; + + @Schema(description = "备注") + @Length(max = 250, message = "任务备注最多250字符") + private String remark; + + @NotNull(message = "排序不能为空") + @Schema(description = "排序") + private Integer sort; + + @Schema(hidden = true) + private String updateName; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobEnabledUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobEnabledUpdateForm.java new file mode 100644 index 0000000..11de070 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobEnabledUpdateForm.java @@ -0,0 +1,26 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 定时任务-更新-开启状态 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Data +public class SmartJobEnabledUpdateForm { + + @Schema(description = "任务id") + @NotNull(message = "任务id不能为空") + private Integer jobId; + + @Schema(description = "是否启用") + @NotNull(message = "是否启用不能为空") + private Boolean enabledFlag; + + @Schema(hidden = true) + private String updateName; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobExecuteForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobExecuteForm.java new file mode 100644 index 0000000..81f4cb2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobExecuteForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.hibernate.validator.constraints.Length; + +/** + * 定时任务-手动执行 + * + * @author huke + * @date 2024/6/18 20:30 + */ +@Data +public class SmartJobExecuteForm { + + @Schema(description = "任务id") + @NotNull(message = "任务id不能为空") + private Integer jobId; + + @Schema(description = "定时任务参数|可选") + @Length(max = 2000, message = "定时任务参数最多2000字符") + private String param; + + @Schema(hidden = true) + private String updateName; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobLogQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobLogQueryForm.java new file mode 100644 index 0000000..f405e7d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobLogQueryForm.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; + +/** + * 定时任务-执行记录 分页查询 + * + * @author huke + * @date 2024/6/17 20:50 + */ +@Data +public class SmartJobLogQueryForm extends PageParam { + + @Schema(description = "搜索词|可选") + @Length(max = 50, message = "搜索词最多50字符") + private String searchWord; + + @Schema(description = "任务id|可选") + private Integer jobId; + + @Schema(description = "是否成功|可选") + private Boolean successFlag; + + @Schema(description = "开始时间|可选", example = "2024-06-06") + private LocalDate startTime; + + @Schema(description = "截止时间|可选", example = "2025-10-15") + private LocalDate endTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobLogVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobLogVO.java new file mode 100644 index 0000000..dc60cb7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobLogVO.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 定时任务-执行记录 vo + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Data +public class SmartJobLogVO { + + @Schema(description = "logId") + private Long logId; + + @Schema(description = "任务id") + private Integer jobId; + + @Schema(description = "任务名称") + private String jobName; + + @Schema(description = "定时任务参数|可选") + private String param; + + @Schema(description = "执行结果是否成功") + private Boolean successFlag; + + @Schema(description = "开始执行时间") + private LocalDateTime executeStartTime; + + @Schema(description = "执行时长-毫秒") + private Long executeTimeMillis; + + @Schema(description = "执行结果描述") + private String executeResult; + + @Schema(description = "执行结束时间") + private LocalDateTime executeEndTime; + + @Schema(description = "ip") + private String ip; + + @Schema(description = "进程id") + private String processId; + + @Schema(description = "程序目录") + private String programPath; + + private String createName; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobMsg.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobMsg.java new file mode 100644 index 0000000..c7cba95 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobMsg.java @@ -0,0 +1,59 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 定时任务 发布/订阅消息对象 + * + * @author huke + * @date 2024/6/20 21:10 + */ +@Data +public class SmartJobMsg { + + /** + * 消息id 无需设置 + */ + private String msgId; + + /** + * 任务id + */ + private Integer jobId; + + /** + * 任务参数 + */ + private String param; + + /** + * 消息类型 + */ + private MsgTypeEnum msgType; + + /** + * 更新人 + */ + private String updateName; + + @Getter + @AllArgsConstructor + public enum MsgTypeEnum implements BaseEnum { + + /** + * 1 更新任务 + */ + UPDATE_JOB(1, "更新任务"), + + EXECUTE_JOB(2, "执行任务"), + + ; + + private final Integer value; + + private final String desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobQueryForm.java new file mode 100644 index 0000000..39a56c7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobQueryForm.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.job.constant.SmartJobTriggerTypeEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 定时任务 分页查询 + * + * @author huke + * @date 2024/6/17 20:50 + */ +@Data +public class SmartJobQueryForm extends PageParam { + + @Schema(description = "搜索词|可选") + @Length(max = 50, message = "搜索词最多50字符") + private String searchWord; + + @SchemaEnum(desc = "触发类型", value = SmartJobTriggerTypeEnum.class) + @CheckEnum(value = SmartJobTriggerTypeEnum.class, message = "触发类型错误") + private String triggerType; + + @Schema(description = "是否启用|可选") + private Boolean enabledFlag; + + @Schema(description = "是否删除|可选") + private Boolean deletedFlag; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobUpdateForm.java new file mode 100644 index 0000000..860b4a9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobUpdateForm.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.job.constant.SmartJobTriggerTypeEnum; +import org.hibernate.validator.constraints.Length; + +/** + * 定时任务 更新 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Data +public class SmartJobUpdateForm extends SmartJobAddForm { + + @Schema(description = "任务id") + @NotNull(message = "任务id不能为空") + private Integer jobId; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobVO.java new file mode 100644 index 0000000..d83d98b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/api/domain/SmartJobVO.java @@ -0,0 +1,66 @@ +package net.lab1024.sa.base.module.support.job.api.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.json.serializer.enumeration.EnumSerialize; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.job.constant.SmartJobTriggerTypeEnum; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 定时任务 vo + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Data +public class SmartJobVO { + + @Schema(description = "任务id") + private Integer jobId; + + @Schema(description = "任务名称") + private String jobName; + + @Schema(description = "执行类") + private String jobClass; + + @SchemaEnum(desc = "触发类型", value = SmartJobTriggerTypeEnum.class) + @EnumSerialize(SmartJobTriggerTypeEnum.class) + private String triggerType; + + @Schema(description = "触发配置") + private String triggerValue; + + @Schema(description = "定时任务参数|可选") + private String param; + + @Schema(description = "是否启用") + private Boolean enabledFlag; + + @Schema(description = "最后一执行时间") + private LocalDateTime lastExecuteTime; + + @Schema(description = "最后一次执行记录id") + private Long lastExecuteLogId; + + @Schema(description = "备注") + private String remark; + + @Schema(description = "排序") + private Integer sort; + + private String updateName; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; + + @Schema(description = "上次执行记录") + private SmartJobLogVO lastJobLog; + + @Schema(description = "未来N次任务执行时间") + private List nextJobExecuteTimeList; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/config/SmartJobAutoConfiguration.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/config/SmartJobAutoConfiguration.java new file mode 100644 index 0000000..25ad872 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/config/SmartJobAutoConfiguration.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.base.module.support.job.config; + +import net.lab1024.sa.base.module.support.job.core.SmartJob; +import net.lab1024.sa.base.module.support.job.core.SmartJobLauncher; +import net.lab1024.sa.base.module.support.job.repository.SmartJobRepository; +import org.redisson.api.RedissonClient; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.List; + +/** + * 定时任务 配置 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Configuration +@EnableConfigurationProperties(SmartJobConfig.class) +@ConditionalOnProperty( + prefix = SmartJobConfig.CONFIG_PREFIX, + name = "enabled", + havingValue = "true" +) +public class SmartJobAutoConfiguration { + + private final SmartJobConfig jobConfig; + + private final SmartJobRepository jobRepository; + + private final List jobInterfaceList; + + public SmartJobAutoConfiguration(SmartJobConfig jobConfig, + SmartJobRepository jobRepository, + List jobInterfaceList) { + this.jobConfig = jobConfig; + this.jobRepository = jobRepository; + this.jobInterfaceList = jobInterfaceList; + } + + /** + * 定时任务启动器 + * + * @return + */ + @Bean + public SmartJobLauncher initJobLauncher(RedissonClient redissonClient) { + return new SmartJobLauncher(jobConfig, jobRepository, jobInterfaceList, redissonClient); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/config/SmartJobConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/config/SmartJobConfig.java new file mode 100644 index 0000000..d2bee0d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/config/SmartJobConfig.java @@ -0,0 +1,39 @@ +package net.lab1024.sa.base.module.support.job.config; + + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; + +/** + * smart job 配置 + * 与配置文件参数对应 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@ConfigurationProperties(prefix = SmartJobConfig.CONFIG_PREFIX) +@Data +public class SmartJobConfig { + + public static final String CONFIG_PREFIX = "smart.job"; + + /** + * 任务执行核心线程数 偶数 默认2 + */ + private Integer corePoolSize = 2; + + /** + * 任务延迟初始化 默认30秒 + */ + private Integer initDelay = 30; + + /** + * 数据库配置检测-开关 默认开启 + */ + private Boolean dbRefreshEnabled = true; + + /** + * 数据库配置检测-执行间隔 默认120秒 + */ + private Integer dbRefreshInterval = 120; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobConst.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobConst.java new file mode 100644 index 0000000..4409ad3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobConst.java @@ -0,0 +1,22 @@ +package net.lab1024.sa.base.module.support.job.constant; + +/** + * smart job 常量 + * + * @author huke + * @date 2024/6/19 20:25 + */ +public class SmartJobConst { + + public static final String SYSTEM_NAME = "system"; + + public static final String LOGO = " _____ __ __ __ \n" + + " / ___/____ ___ ____ ______/ /_ / /___ / /_ \n" + + " \\__ \\/ __ `__ \\/ __ `/ ___/ __/ __ / / __ \\/ __ \\\n" + + " ___/ / / / / / / /_/ / / / /_ / /_/ / /_/ / /_/ /\n" + + "/____/_/ /_/ /_/\\__,_/_/ \\__/ \\____/\\____/_.___/ \n" + + "-->任务执行线程池:%s\n" + + "-->任务初始化延迟:%s秒\n" + + "-->数据库配置检测:%s\n\n"; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobTriggerTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobTriggerTypeEnum.java new file mode 100644 index 0000000..c2368c6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobTriggerTypeEnum.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.base.module.support.job.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * job 任务触发类型 枚举类 + * + * @author huke + * @date 2024年6月29日 + **/ +@AllArgsConstructor +@Getter +public enum SmartJobTriggerTypeEnum implements BaseEnum { + + /** + * 1 cron表达式 + */ + CRON("cron", "cron表达式"), + + FIXED_DELAY("fixed_delay", "固定间隔"), + + ; + + private final String value; + + private final String desc; +} + diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobUtil.java new file mode 100644 index 0000000..ac21b3d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/constant/SmartJobUtil.java @@ -0,0 +1,210 @@ +package net.lab1024.sa.base.module.support.job.constant; + +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.module.support.job.core.SmartJob; +import org.springframework.scheduling.support.CronExpression; + +import java.lang.management.ManagementFactory; +import java.lang.management.RuntimeMXBean; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * smart job util + * + * @author huke + * @date 2024/6/18 20:00 + */ +public class SmartJobUtil { + + private SmartJobUtil() { + } + + /** + * 校验cron表达式 是否合法 + * + * @param cron + * @return + */ + public static boolean checkCron(String cron) { + return CronExpression.isValidExpression(cron); + } + + /** + * 校验固定间隔 值是否合法 + * + * @param val + * @return + */ + public static boolean checkFixedDelay(String val) { + int intVal; + try { + intVal = Integer.parseInt(val); + } catch (NumberFormatException e) { + return false; + } + return intVal > 0; + } + + /** + * 打印一些展示信息到控制台 + * 环保绿 + * + * @param info + */ + public static void printInfo(String info) { + System.out.printf("\033[32;1m %s \033[0m", info); + } + + /** + * 查询未来N次执行时间 从最后一次时间时间 开始计算 + * + * @param triggerType + * @param triggerVal + * @param lastExecuteTime + * @param num + * @return + */ + public static List queryNextTimeFromLast(String triggerType, + String triggerVal, + LocalDateTime lastExecuteTime, + int num) { + List nextTimeList = null; + if (SmartJobTriggerTypeEnum.CRON.equalsValue(triggerType)) { + nextTimeList = SmartJobUtil.queryNextTime(triggerVal, lastExecuteTime, num); + } else if (SmartJobTriggerTypeEnum.FIXED_DELAY.equalsValue(triggerType)) { + nextTimeList = SmartJobUtil.queryNextTime(getFixedDelayVal(triggerVal), lastExecuteTime, num); + } + return nextTimeList; + } + + /** + * 查询未来N次执行时间 从当前时间 开始计算 + * + * @param triggerType + * @param triggerVal + * @param lastExecuteTime + * @param num + * @return + */ + public static List queryNextTimeFromNow(String triggerType, + String triggerVal, + LocalDateTime lastExecuteTime, + int num) { + LocalDateTime nowTime = LocalDateTime.now(); + List nextTimeList = null; + if (SmartJobTriggerTypeEnum.CRON.equalsValue(triggerType)) { + nextTimeList = SmartJobUtil.queryNextTime(triggerVal, nowTime, num); + } else if (SmartJobTriggerTypeEnum.FIXED_DELAY.equalsValue(triggerType)) { + Integer fixedDelay = getFixedDelayVal(triggerVal); + LocalDateTime startTime = null == lastExecuteTime || lastExecuteTime.plusSeconds(fixedDelay).isBefore(nowTime) + ? nowTime : lastExecuteTime; + nextTimeList = SmartJobUtil.queryNextTime(fixedDelay, startTime, num); + } + return nextTimeList; + } + + /** + * 根据cron表达式 计算N次执行时间 + * + * @param cron + * @param startTime + * @param num + * @return + */ + public static List queryNextTime(String cron, LocalDateTime startTime, int num) { + if (null == startTime) { + return Collections.emptyList(); + } + CronExpression parse = CronExpression.parse(cron); + List timeList = new ArrayList<>(num); + for (int i = 0; i < num; i++) { + startTime = parse.next(startTime); + timeList.add(startTime); + } + return timeList; + } + + /** + * 根据 固定间隔 计算N次执行时间 + * + * @param fixDelaySecond + * @param startTime + * @param num + * @return + */ + public static List queryNextTime(Integer fixDelaySecond, LocalDateTime startTime, int num) { + if (null == startTime) { + return Collections.emptyList(); + } + List timeList = new ArrayList<>(num); + for (int i = 0; i < num; i++) { + startTime = startTime.plusSeconds(fixDelaySecond); + timeList.add(startTime); + } + return timeList; + } + + /** + * 获取固定间隔时间 + * + * @param val + * @return + */ + public static Integer getFixedDelayVal(String val) { + return Integer.parseInt(val); + } + + /** + * 获取当前 Java 应用程序的工作目录 + * + * @return + */ + public static String getProgramPath() { + return System.getProperty("user.dir"); + } + + /** + * 获取当前 Java 应用程序的进程id + * + * @return + */ + public static String getProcessId() { + RuntimeMXBean runtime = ManagementFactory.getRuntimeMXBean(); + return runtime.getName().split("@")[0]; + } + + + /** + * 根据className 判断job class + */ + public static ResponseDTO checkJobClass(String className) { + try { + Class aClass = Class.forName(className); + // 判断是否实现了 SmartJob + if (!SmartJob.class.isAssignableFrom(aClass)) { + return ResponseDTO.userErrorParam(className + " 执行类没有实现 SmartJob 接口"); + } + } catch (ClassNotFoundException e) { + return ResponseDTO.userErrorParam("没有在代码中发现执行类:" + className); + } + return ResponseDTO.ok(); + } + + + public static void main(String[] args) { + LocalDateTime startTime = LocalDateTime.now(); + List timeList = SmartJobUtil.queryNextTime("5 * * * * *", startTime, 3); + System.out.println(timeList); + + timeList = SmartJobUtil.queryNextTime(10, startTime, 3); + System.out.println(timeList); + + System.out.println("project path ->" + getProgramPath()); + System.out.println("project process id ->" + getProcessId()); + ResponseDTO res = checkJobClass("net.lab1024.sa.base.module.support.job.sample.SmartJobSample1"); + System.out.println(res.getMsg()); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJob.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJob.java new file mode 100644 index 0000000..7549642 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJob.java @@ -0,0 +1,28 @@ +package net.lab1024.sa.base.module.support.job.core; + +/** + * 定时任务 执行接口 + * + * @author huke + * @date 2024/6/17 21:30 + */ +public interface SmartJob { + + /** + * 默认方法 + * 获取当前任务类名 + * + * @return + */ + default String getClassName() { + return this.getClass().getName(); + } + + /** + * 执行定时任务 + * + * @param param 可选参数 任务不需要时不用管 + * @return 可null, 自行组织语言描述执行结果,例如:本次处理数据N条 等 + */ + String run(String param); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobExecutor.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobExecutor.java new file mode 100644 index 0000000..721410a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobExecutor.java @@ -0,0 +1,168 @@ +package net.lab1024.sa.base.module.support.job.core; + +import cn.hutool.core.exceptions.ExceptionUtil; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.util.SmartIpUtil; +import net.lab1024.sa.base.module.support.job.constant.SmartJobConst; +import net.lab1024.sa.base.module.support.job.constant.SmartJobUtil; +import net.lab1024.sa.base.module.support.job.repository.SmartJobRepository; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobEntity; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobLogEntity; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.util.StopWatch; + +import java.time.LocalDateTime; +import java.time.temporal.ChronoUnit; +import java.util.concurrent.TimeUnit; + +/** + * 定时任务 执行器 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Slf4j +public class SmartJobExecutor implements Runnable { + + private final SmartJobEntity jobEntity; + + private final SmartJobRepository jobRepository; + + private final SmartJob jobInterface; + + private final RedissonClient redissonClient; + + private static final String EXECUTE_LOCK = "smart-job-lock-execute-"; + + public SmartJobExecutor(SmartJobEntity jobEntity, + SmartJobRepository jobRepository, + SmartJob jobInterface, + RedissonClient redissonClient) { + this.jobEntity = jobEntity; + this.jobRepository = jobRepository; + this.jobInterface = jobInterface; + this.redissonClient = redissonClient; + } + + /** + * 系统线程执行 + */ + @Override + public void run() { + // 获取当前任务执行锁 最多持有30s自动释放 + Integer jobId = jobEntity.getJobId(); + RLock rLock = redissonClient.getLock(EXECUTE_LOCK + jobId); + try { + boolean lock = rLock.tryLock(0, 30, TimeUnit.SECONDS); + if (!lock) { + return; + } + // 查询上次执行时间 校验执行间隔 + SmartJobEntity dbJobEntity = jobRepository.getJobDao().selectById(jobId); + if (null == dbJobEntity) { + return; + } + LocalDateTime lastExecuteTime = dbJobEntity.getLastExecuteTime(); + if (null != lastExecuteTime) { + LocalDateTime nextTime = SmartJobUtil.queryNextTimeFromLast(jobEntity.getTriggerType(), jobEntity.getTriggerValue(), lastExecuteTime, 1).get(0); + if (LocalDateTime.now().isBefore(nextTime)) { + return; + } + } + // 执行任务 + SmartJobLogEntity logEntity = this.execute(SmartJobConst.SYSTEM_NAME); + log.info("==== SmartJob ==== execute job->{},time-millis->{}ms", jobEntity.getJobName(), logEntity.getExecuteTimeMillis()); + } catch (Throwable t) { + log.error("==== SmartJob ==== execute err:", t); + } finally { + if (rLock.isHeldByCurrentThread()) { + rLock.unlock(); + } + } + } + + /** + * 执行任务 + * + * @param executorName + */ + public SmartJobLogEntity execute(String executorName) { + // 保存执行记录 + LocalDateTime startTime = LocalDateTime.now(); + Long logId = this.saveLogBeforeExecute(jobEntity, executorName, startTime); + + // 执行计时 + StopWatch stopWatch = new StopWatch(); + stopWatch.start(); + + // 执行任务 + boolean successFlag = true; + String executeResult; + try { + executeResult = jobInterface.run(jobEntity.getParam()); + stopWatch.stop(); + } catch (Throwable t) { + stopWatch.stop(); + successFlag = false; + // ps:异常信息不大于数据库字段长度限制 + executeResult = ExceptionUtil.stacktraceToString(t, 1800); + log.error("==== SmartJob ==== execute err:", t); + } + + // 更新执行记录 + SmartJobLogEntity logEntity = new SmartJobLogEntity(); + logEntity.setLogId(logId); + logEntity.setSuccessFlag(successFlag); + long totalTimeMillis = stopWatch.getTotalTimeMillis(); + logEntity.setExecuteTimeMillis(totalTimeMillis); + logEntity.setExecuteEndTime(startTime.plus(totalTimeMillis, ChronoUnit.MILLIS)); + logEntity.setExecuteResult(executeResult); + jobRepository.getJobLogDao().updateById(logEntity); + return logEntity; + } + + /** + * 执行前 保存执行记录 + * + * @param jobEntity + * @param executorName + * @param executeTime + * @return 返回执行记录id + */ + private Long saveLogBeforeExecute(SmartJobEntity jobEntity, + String executorName, + LocalDateTime executeTime) { + Integer jobId = jobEntity.getJobId(); + // 保存执行记录 + SmartJobLogEntity logEntity = new SmartJobLogEntity(); + logEntity.setJobId(jobId); + logEntity.setJobName(jobEntity.getJobName()); + logEntity.setParam(jobEntity.getParam()); + logEntity.setSuccessFlag(true); + // 执行开始时间 + logEntity.setExecuteStartTime(executeTime); + logEntity.setExecuteEndTime(executeTime); + logEntity.setExecuteTimeMillis(0L); + logEntity.setCreateName(executorName); + logEntity.setIp(SmartIpUtil.getLocalFirstIp()); + logEntity.setProcessId(SmartJobUtil.getProcessId()); + logEntity.setProgramPath(SmartJobUtil.getProgramPath()); + + // 更新最后执行时间 + SmartJobEntity updateJobEntity = new SmartJobEntity(); + updateJobEntity.setJobId(jobId); + updateJobEntity.setLastExecuteTime(executeTime); + jobRepository.saveLog(logEntity, updateJobEntity); + return logEntity.getLogId(); + } + + /** + * 查询 当前任务信息 + * + * @return + */ + public SmartJobEntity getJob() { + return jobEntity; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobLauncher.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobLauncher.java new file mode 100644 index 0000000..04dd72e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobLauncher.java @@ -0,0 +1,153 @@ +package net.lab1024.sa.base.module.support.job.core; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import jakarta.annotation.PreDestroy; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.job.config.SmartJobConfig; +import net.lab1024.sa.base.module.support.job.constant.SmartJobConst; +import net.lab1024.sa.base.module.support.job.constant.SmartJobUtil; +import net.lab1024.sa.base.module.support.job.repository.SmartJobRepository; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobEntity; +import org.redisson.api.RedissonClient; +import org.springframework.util.CollectionUtils; + +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.stream.Collectors; + +/** + * 定时任务 作业启动类 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Slf4j +public class SmartJobLauncher { + + private final SmartJobRepository jobRepository; + + private final List jobInterfaceList; + + private final RedissonClient redissonClient; + + public SmartJobLauncher(SmartJobConfig jobConfig, + SmartJobRepository jobRepository, + List jobInterfaceList, + RedissonClient redissonClient) { + this.jobRepository = jobRepository; + this.jobInterfaceList = jobInterfaceList; + this.redissonClient = redissonClient; + + // init job scheduler + SmartJobScheduler.init(jobConfig); + + // 任务自动检测配置 固定1个线程 + Integer initDelay = jobConfig.getInitDelay(); + Boolean refreshEnabled = jobConfig.getDbRefreshEnabled(); + Integer refreshInterval = jobConfig.getDbRefreshInterval(); + + ThreadFactory factory = new ThreadFactoryBuilder().setNameFormat("SmartJobLauncher-%d").build(); + ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1, factory); + Runnable launcherRunnable = () -> { + try { + // 查询所有任务 + List smartJobList = this.queryJob(); + this.startOrRefreshJob(smartJobList); + } catch (Throwable t) { + log.error("SmartJob Error:", t); + } + // 只在启动时 执行一次 + if (!refreshEnabled) { + executor.shutdown(); + } + }; + executor.scheduleWithFixedDelay(launcherRunnable, initDelay, refreshInterval, TimeUnit.SECONDS); + + // 打印信息 + String refreshDesc = refreshEnabled ? "开启|检测间隔" + refreshInterval + "秒" : "关闭"; + String format = String.format(SmartJobConst.LOGO, jobConfig.getCorePoolSize(), initDelay, refreshDesc); + SmartJobUtil.printInfo(format); + } + + /** + * 查询数据库 + * 启动/刷新任务 + */ + public void startOrRefreshJob(List smartJobList) { + // 查询任务配置 + if (CollectionUtils.isEmpty(smartJobList) || CollectionUtils.isEmpty(jobInterfaceList)) { + log.info("==== SmartJob ==== job list empty"); + return; + } + + // 任务实现类 + Map jobImplMap = jobInterfaceList.stream().collect(Collectors.toMap(SmartJob::getClassName, Function.identity())); + for (SmartJobEntity jobEntity : smartJobList) { + // 任务是否存在 判断是否需要更新 + Integer jobId = jobEntity.getJobId(); + SmartJobEntity oldJobEntity = SmartJobScheduler.getJobInfo(jobId); + if (null != oldJobEntity) { + // 不需要更新 + if (!isNeedUpdate(oldJobEntity, jobEntity)) { + continue; + } + // 需要更新 移除原任务 + SmartJobScheduler.removeJob(jobId); + } + // 任务未开启 + if (!jobEntity.getEnabledFlag()) { + continue; + } + // 任务删除 + if (jobEntity.getDeletedFlag()) { + continue; + } + // 查找任务实现类 + SmartJob jobImpl = jobImplMap.get(jobEntity.getJobClass()); + if (null == jobImpl) { + continue; + } + // 添加任务 + SmartJobExecutor jobExecute = new SmartJobExecutor(jobEntity, jobRepository, jobImpl, redissonClient); + SmartJobScheduler.addJob(jobExecute); + } + List runjJobList = SmartJobScheduler.getJobInfo(); + List jobNameList = runjJobList.stream().map(SmartJobEntity::getJobName).collect(Collectors.toList()); + log.info("==== SmartJob ==== start/refresh job num:{}->{}", runjJobList.size(), jobNameList); + } + + /** + * 查询全部任务 + * + * @return + */ + private List queryJob() { + return jobRepository.getJobDao().selectList(null); + } + + /** + * 手动判断 任务配置 是否需要更新 + * 新增字段的话 在这个方法里增加判断 + * + * @return + */ + private static boolean isNeedUpdate(SmartJobEntity oldJob, SmartJobEntity newJob) { + // cron为空时 fixedDelay 才有意义 + return !Objects.equals(oldJob.getEnabledFlag(), newJob.getEnabledFlag()) + || !Objects.equals(oldJob.getDeletedFlag(), newJob.getDeletedFlag()) + || !Objects.equals(oldJob.getTriggerType(), newJob.getTriggerType()) + || !Objects.equals(oldJob.getTriggerValue(), newJob.getTriggerValue()) + || !Objects.equals(oldJob.getJobClass(), newJob.getJobClass()); + } + + @PreDestroy + public void destroy() { + SmartJobScheduler.destroy(); + log.info("==== SmartJob ==== destroy job"); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobScheduler.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobScheduler.java new file mode 100644 index 0000000..6706736 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/core/SmartJobScheduler.java @@ -0,0 +1,178 @@ +package net.lab1024.sa.base.module.support.job.core; + +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.job.config.SmartJobConfig; +import net.lab1024.sa.base.module.support.job.constant.SmartJobTriggerTypeEnum; +import net.lab1024.sa.base.module.support.job.constant.SmartJobUtil; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobEntity; +import org.apache.commons.lang3.tuple.Pair; +import org.springframework.scheduling.Trigger; +import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler; +import org.springframework.scheduling.support.CronTrigger; +import org.springframework.scheduling.support.PeriodicTrigger; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.TimeUnit; +import java.util.stream.Collectors; + +/** + * 定时任务 调度管理 + * + * @author huke + * @date 2024/6/22 21:30 + */ +@Slf4j +public class SmartJobScheduler { + + /** + * Spring线程池任务调度器 + */ + private static ThreadPoolTaskScheduler TASK_SCHEDULER; + + /** + * 定时任务 map + */ + private static Map>> JOB_FUTURE_MAP; + + private SmartJobScheduler() { + + } + + /** + * 初始化任务调度配置 + */ + public static void init(SmartJobConfig config) { + TASK_SCHEDULER = new ThreadPoolTaskScheduler(); + ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("SmartJobExecutor-%d").build(); + TASK_SCHEDULER.setThreadFactory(threadFactory); + TASK_SCHEDULER.setPoolSize(config.getCorePoolSize()); + // 线程池在关闭时会等待所有任务完成 + TASK_SCHEDULER.setWaitForTasksToCompleteOnShutdown(true); + // 在调用shutdown方法后,等待任务完成的最长时间 + TASK_SCHEDULER.setAwaitTerminationSeconds(10); + // 错误处理 + TASK_SCHEDULER.setErrorHandler((t) -> log.error("SmartJobExecute Err:", t)); + // 当一个任务在被调度执行前被取消时,是否应该从线程池的任务队列中移除 + TASK_SCHEDULER.setRemoveOnCancelPolicy(true); + TASK_SCHEDULER.initialize(); + + JOB_FUTURE_MAP = new ConcurrentHashMap<>(); + } + + /** + * 获取任务执行对象 + * + * @param jobId + * @return + */ + public static ScheduledFuture getJobFuture(Integer jobId) { + Pair> pair = JOB_FUTURE_MAP.get(jobId); + if (null == pair) { + return null; + } + return pair.getRight(); + } + + /** + * 获取当前所有执行任务 + * + * @return + */ + public static List getJobInfo() { + return JOB_FUTURE_MAP.values().stream().map(Pair::getLeft).collect(Collectors.toList()); + } + + /** + * 获取任务执行实体类 + * + * @param jobId + * @return + */ + public static SmartJobEntity getJobInfo(Integer jobId) { + Pair> pair = JOB_FUTURE_MAP.get(jobId); + if (null == pair) { + return null; + } + return pair.getLeft(); + } + + /** + * 添加任务 + * + * @param jobExecute + * @return + */ + public static void addJob(SmartJobExecutor jobExecute) { + // 任务是否存在 + SmartJobEntity jobEntity = jobExecute.getJob(); + Integer jobId = jobEntity.getJobId(); + if (JOB_FUTURE_MAP.containsKey(jobId)) { + // 移除任务 + removeJob(jobId); + } + // 任务触发类型 + Trigger trigger = null; + String triggerType = jobEntity.getTriggerType(); + String triggerValue = jobEntity.getTriggerValue(); + // 优先 cron 表达式 + if (SmartJobTriggerTypeEnum.CRON.equalsValue(triggerType)) { + trigger = new CronTrigger(triggerValue); + } else if (SmartJobTriggerTypeEnum.FIXED_DELAY.equalsValue(triggerType)) { + trigger = new PeriodicTrigger(SmartJobUtil.getFixedDelayVal(triggerValue), TimeUnit.SECONDS); + } + String jobName = jobEntity.getJobName(); + if (null == trigger) { + log.error("==== SmartJob ==== trigger-value not null {}", jobName); + return; + } + // 执行任务 + ScheduledFuture schedule = TASK_SCHEDULER.schedule(jobExecute, trigger); + JOB_FUTURE_MAP.put(jobId, Pair.of(jobEntity, schedule)); + log.info("==== SmartJob ==== add job:{}", jobName); + } + + /** + * 移除任务 + * 等待任务执行完成后移除 + * + * @param jobId + */ + public static void removeJob(Integer jobId) { + ScheduledFuture jobFuture = getJobFuture(jobId); + if (null == jobFuture) { + return; + } + // 结束任务 + stopJob(jobFuture); + JOB_FUTURE_MAP.remove(jobId); + log.info("==== SmartJob ==== remove job:{}", jobId); + } + + /** + * 停止所有定时任务 + */ + public static void destroy() { + // 启动一个有序的关闭过程,在这个过程中,不再接受新的任务提交,但已提交的任务(包括正在执行的和队列中等待的)会被允许执行完成。 + TASK_SCHEDULER.destroy(); + JOB_FUTURE_MAP.clear(); + } + + /** + * 结束任务 + * 如果任务还没有开始执行,会直接被取消。 + * 如果任务已经开始执行,此时不会中断执行中的线程,任务会执行完成再被取消 + * + * @param scheduledFuture + */ + private static void stopJob(ScheduledFuture scheduledFuture) { + if (null == scheduledFuture || scheduledFuture.isCancelled()) { + return; + } + scheduledFuture.cancel(false); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobDao.java new file mode 100644 index 0000000..028f87c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobDao.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.base.module.support.job.repository; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.job.api.domain.SmartJobQueryForm; +import net.lab1024.sa.base.module.support.job.api.domain.SmartJobVO; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 定时任务 dao + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Mapper +public interface SmartJobDao extends BaseMapper { + + /** + * 定时任务-分页查询 + * + * @param page + * @param queryForm + * @return + */ + List query(Page page, @Param("query") SmartJobQueryForm queryForm); + + /** + * 假删除 + * + * @param jobId + * @return + */ + void updateDeletedFlag(@Param("jobId") Integer jobId, @Param("deletedFlag") Boolean deletedFlag); + + /** + * 根据 任务class 查找 + * + * @param jobClass + * @return + */ + SmartJobEntity selectByJobClass(@Param("jobClass") String jobClass); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobLogDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobLogDao.java new file mode 100644 index 0000000..b3b6a3d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobLogDao.java @@ -0,0 +1,31 @@ +package net.lab1024.sa.base.module.support.job.repository; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.job.api.domain.SmartJobLogQueryForm; +import net.lab1024.sa.base.module.support.job.api.domain.SmartJobLogVO; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobLogEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 定时任务-执行记录 dao + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Mapper +public interface SmartJobLogDao extends BaseMapper { + + /** + * 定时任务-执行记录-分页查询 + * + * @param page + * @param queryForm + * @return + */ + List query(Page page, @Param("query") SmartJobLogQueryForm queryForm); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobRepository.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobRepository.java new file mode 100644 index 0000000..f8d1773 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/SmartJobRepository.java @@ -0,0 +1,45 @@ +package net.lab1024.sa.base.module.support.job.repository; + +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobEntity; +import net.lab1024.sa.base.module.support.job.repository.domain.SmartJobLogEntity; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * job 持久化业务 + * + * @author huke + * @date 2024/6/22 22:28 + */ +@Service +public class SmartJobRepository { + + @Autowired + private SmartJobDao jobDao; + + @Autowired + private SmartJobLogDao jobLogDao; + + public SmartJobDao getJobDao() { + return jobDao; + } + + public SmartJobLogDao getJobLogDao() { + return jobLogDao; + } + + /** + * 保存执行记录 + * + * @param logEntity + * @param jobEntity + */ + @Transactional(rollbackFor = Throwable.class) + public void saveLog(SmartJobLogEntity logEntity, SmartJobEntity jobEntity) { + jobLogDao.insert(logEntity); + + jobEntity.setLastExecuteLogId(logEntity.getLogId()); + jobDao.updateById(jobEntity); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/domain/SmartJobEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/domain/SmartJobEntity.java new file mode 100644 index 0000000..890bc63 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/domain/SmartJobEntity.java @@ -0,0 +1,89 @@ +package net.lab1024.sa.base.module.support.job.repository.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.base.module.support.job.constant.SmartJobTriggerTypeEnum; + +import java.time.LocalDateTime; + +/** + * 定时任务 实体类 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Data +@TableName("t_smart_job") +public class SmartJobEntity { + + /** + * 任务id + */ + @TableId(type = IdType.AUTO) + private Integer jobId; + + /** + * 任务名称 + */ + private String jobName; + + /** + * 执行类 + */ + private String jobClass; + + /** + * 触发类型 + * + * @see SmartJobTriggerTypeEnum + */ + private String triggerType; + + /** + * 触发配置 + */ + private String triggerValue; + + /** + * 定时任务参数 可选 + */ + private String param; + + /** + * 是否启用 + */ + private Boolean enabledFlag; + + /** + * 最后一执行时间 + */ + private LocalDateTime lastExecuteTime; + + /** + * 最后一次执行记录id + */ + private Long lastExecuteLogId; + + /** + * 备注描述 可选 + */ + private String remark; + + /** + * 排序 + */ + private Integer sort; + + /** + * 是否删除 + */ + private Boolean deletedFlag; + + private String updateName; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/domain/SmartJobLogEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/domain/SmartJobLogEntity.java new file mode 100644 index 0000000..95c1d49 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/repository/domain/SmartJobLogEntity.java @@ -0,0 +1,81 @@ +package net.lab1024.sa.base.module.support.job.repository.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 定时任务 执行记录 实体类 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Data +@TableName("t_smart_job_log") +public class SmartJobLogEntity { + + @TableId(type = IdType.AUTO) + private Long logId; + + /** + * 任务id + */ + private Integer jobId; + + /** + * 任务名称 + */ + private String jobName; + + /** + * 定时任务参数 可选 + */ + private String param; + + /** + * 执行结果 是否成功 + */ + private Boolean successFlag; + + /** + * 开始执行时间 + */ + private LocalDateTime executeStartTime; + + /** + * 执行时长-毫秒 + */ + private Long executeTimeMillis; + + /** + * 执行结束时间 + */ + private LocalDateTime executeEndTime; + + /** + * 执行结果 描述 可选 + */ + private String executeResult; + + /** + * ip + */ + private String ip; + + /** + * 进程id + */ + private String processId; + + /** + * 程序目录 + */ + private String programPath; + + private String createName; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/SmartJobSample1.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/SmartJobSample1.java new file mode 100644 index 0000000..7036915 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/SmartJobSample1.java @@ -0,0 +1,29 @@ +package net.lab1024.sa.base.module.support.job.sample; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.job.core.SmartJob; +import org.springframework.stereotype.Service; + +/** + * 定时任务 示例1 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Slf4j +@Service +public class SmartJobSample1 implements SmartJob { + + /** + * 定时任务示例 + * + * @param param 可选参数 任务不需要时不用管 + * @return + */ + @Override + public String run(String param) { + // 写点什么业务逻辑 + return "执行完毕,随便说点什么吧"; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/SmartJobSample2.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/SmartJobSample2.java new file mode 100644 index 0000000..18d9a21 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/SmartJobSample2.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.base.module.support.job.sample; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.config.ConfigDao; +import net.lab1024.sa.base.module.support.config.domain.ConfigEntity; +import net.lab1024.sa.base.module.support.job.core.SmartJob; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +/** + * 定时任务 示例2 + * + * @author huke + * @date 2024/6/17 21:30 + */ +@Slf4j +@Service +public class SmartJobSample2 implements SmartJob { + + @Autowired + private ConfigDao configDao; + + /** + * 定时任务示例 + * 需要事务时 添加 @Transactional 注解 + * + * @param param 可选参数 任务不需要时不用管 + * @return + */ + @Transactional(rollbackFor = Throwable.class) + @Override + public String run(String param) { + // 随便更新点什么东西 + ConfigEntity configEntity = new ConfigEntity(); + configEntity.setConfigId(1L); + configEntity.setRemark(param); + configDao.updateById(configEntity); + + configEntity = new ConfigEntity(); + configEntity.setConfigId(2L); + configEntity.setRemark("SmartJob Sample2 update"); + configDao.updateById(configEntity); + + return "执行成功,本次处理数据1条"; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/package-info.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/package-info.java new file mode 100644 index 0000000..d72e5a7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/job/sample/package-info.java @@ -0,0 +1,5 @@ +/** + * 定时任务 示例包 + * 可以删除 + */ +package net.lab1024.sa.base.module.support.job.sample; \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogDao.java new file mode 100644 index 0000000..cfc409c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogDao.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.module.support.loginlog; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogEntity; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogQueryForm; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 登录日志 + * + * @Author wzh + * @Date 2022/07/22 19:46:23 + */ +@Mapper +public interface LoginLogDao extends BaseMapper { + + /** + * 分页查询 + * + * @param page + * @param queryForm + * @return LoginLogVO + */ + List queryByPage(Page page, @Param("query") LoginLogQueryForm queryForm); + + /** + * 查询上一个登录记录 + * + * @param userId + * @param userType + * @return LoginLogVO + */ + LoginLogVO queryLastByUserId(@Param("userId") Long userId,@Param("userType") Integer userType, @Param("loginLogResult")Integer loginLogResult); + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogResultEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogResultEnum.java new file mode 100644 index 0000000..a1f2d01 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogResultEnum.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.loginlog; + +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 登录类型 + * + * @Author wzh + * @Date 2022/07/22 19:46:23 + */ +public enum LoginLogResultEnum implements BaseEnum { + + LOGIN_SUCCESS(0, "登录成功"), + LOGIN_FAIL(1, "登录失败"), + LOGIN_OUT(2, "退出登录"); + + private Integer type; + private String desc; + + LoginLogResultEnum(Integer type, String desc) { + this.type = type; + this.desc = desc; + } + + @Override + public Integer getValue() { + return type; + } + + @Override + public String getDesc() { + return desc; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogService.java new file mode 100644 index 0000000..62505b2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/LoginLogService.java @@ -0,0 +1,64 @@ +package net.lab1024.sa.base.module.support.loginlog; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogEntity; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogQueryForm; +import net.lab1024.sa.base.module.support.loginlog.domain.LoginLogVO; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 登录日志 + * + * @Author wzh + * @Date 2022/07/22 19:46:23 + */ +@Service +@Slf4j +public class LoginLogService { + + @Resource + private LoginLogDao loginLogDao; + + /** + * @author 卓大 + * @description 分页查询 + */ + public ResponseDTO> queryByPage(LoginLogQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List logList = loginLogDao.queryByPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, logList); + return ResponseDTO.ok(pageResult); + } + + /** + * @author 卓大 + * @description 添加 + */ + public void log(LoginLogEntity loginLogEntity) { + try { + loginLogDao.insert(loginLogEntity); + } catch (Throwable e) { + log.error(e.getMessage(), e); + } + } + + + /** + * 查询上一个登录记录 + * + * @author 卓大 + * @description 查询上一个登录记录 + */ + public LoginLogVO queryLastByUserId(Long userId, UserTypeEnum userTypeEnum, LoginLogResultEnum loginLogResultEnum) { + return loginLogDao.queryLastByUserId(userId,userTypeEnum.getValue(), loginLogResultEnum.getValue()); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogEntity.java new file mode 100644 index 0000000..97e3e91 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogEntity.java @@ -0,0 +1,74 @@ +package net.lab1024.sa.base.module.support.loginlog.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 登录日志 + * + * @Author wzh + * @Date 2022/07/22 19:46:23 + */ +@TableName("t_login_log") +@Data +@Builder +public class LoginLogEntity { + + @TableId(type = IdType.AUTO) + private Long loginLogId; + + /** + * 用户id + */ + private Long userId; + + /** + * 用户类型 + */ + private Integer userType; + + /** + * 用户名 + */ + private String userName; + + /** + * 登录ip + */ + private String loginIp; + + /** + * 登录ip地区 + */ + private String loginIpRegion; + + /** + * user-agent + */ + private String userAgent; + + /** + * 备注 + */ + private String remark; + + /** + * 登录设备 + */ + private String loginDevice; + + /** + * 登录类型 + */ + private Integer loginResult; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogQueryForm.java new file mode 100644 index 0000000..c3bce3a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogQueryForm.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.loginlog.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +/** + * 登录查询日志 + * + * @Author wzh + * @Date 2022/07/22 19:46:23 + */ +@Data +public class LoginLogQueryForm extends PageParam { + + @Schema(description = "用户ID") + private Long userId; + + @Schema(description = "用户类型") + private Integer userType; + + @Schema(description = "开始日期") + private String startDate; + + @Schema(description = "结束日期") + private String endDate; + + @Schema(description = "用户名称") + private String userName; + + @Schema(description = "ip") + private String ip; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogVO.java new file mode 100644 index 0000000..e9a6ded --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/loginlog/domain/LoginLogVO.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.module.support.loginlog.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.loginlog.LoginLogResultEnum; + +import java.time.LocalDateTime; + +/** + * 登录日志 + * + * @Author wzh + * @Date 2022/07/22 19:46:23 + */ +@Data +public class LoginLogVO { + + private Long loginLogId; + + @Schema(description = "用户id") + private Long userId; + + @SchemaEnum(value = UserTypeEnum.class, desc = "用户类型") + private Integer userType; + + @Schema(description = "用户名") + private String userName; + + @Schema(description = "登录ip") + private String loginIp; + + @Schema(description = "登录ip地区") + private String loginIpRegion; + + @Schema(description = "user-agent") + private String userAgent; + + @Schema(description = "remark") + private String remark; + + @SchemaEnum(LoginLogResultEnum.class) + private Integer loginResult; + + private String loginDevice; + + private LocalDateTime createTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/MailService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/MailService.java new file mode 100644 index 0000000..24f6284 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/MailService.java @@ -0,0 +1,176 @@ +package net.lab1024.sa.base.module.support.mail; + + +import cn.hutool.core.lang.UUID; +import freemarker.cache.StringTemplateLoader; +import freemarker.template.Configuration; +import freemarker.template.Template; +import jakarta.annotation.Resource; +import jakarta.mail.MessagingException; +import jakarta.mail.internet.MimeMessage; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.SystemEnvironment; +import net.lab1024.sa.base.module.support.mail.constant.MailTemplateCodeEnum; +import net.lab1024.sa.base.module.support.mail.constant.MailTemplateTypeEnum; +import net.lab1024.sa.base.module.support.mail.domain.MailTemplateEntity; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringSubstitutor; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.mail.javamail.JavaMailSender; +import org.springframework.mail.javamail.MimeMessageHelper; +import org.springframework.stereotype.Component; + +import java.io.File; +import java.io.StringWriter; +import java.io.Writer; +import java.util.List; +import java.util.Map; + +/** + * + * 发生邮件:
+ * 1、支持直接发送
+ * 2、支持使用邮件模板发送 + * + * @Author wzh + * @Date 2024/8/5 + */ +@Slf4j +@Component +public class MailService { + + @Autowired + private JavaMailSender javaMailSender; + + @Resource + private MailTemplateDao mailTemplateDao; + + @Resource + private SystemEnvironment systemEnvironment; + + @Value("${spring.mail.username}") + private String clientMail; + + + /** + * 使用模板发送邮件 + */ + public ResponseDTO sendMail(MailTemplateCodeEnum templateCode, Map templateParamsMap, List receiverUserList, List fileList) { + + MailTemplateEntity mailTemplateEntity = mailTemplateDao.selectById(templateCode.name().toLowerCase()); + if (mailTemplateEntity == null) { + return ResponseDTO.userErrorParam("模版不存在"); + } + + if (mailTemplateEntity.getDisableFlag()) { + return ResponseDTO.userErrorParam("模版已禁用,无法发送"); + } + + String content = null; + if (MailTemplateTypeEnum.FREEMARKER.name().equalsIgnoreCase(mailTemplateEntity.getTemplateType().trim())) { + content = freemarkerResolverContent(mailTemplateEntity.getTemplateContent(), templateParamsMap); + } else if (MailTemplateTypeEnum.STRING.name().equalsIgnoreCase(mailTemplateEntity.getTemplateType().trim())) { + content = stringResolverContent(mailTemplateEntity.getTemplateContent(), templateParamsMap); + } else { + return ResponseDTO.userErrorParam("模版类型不存在"); + } + + try { + + this.sendMail(mailTemplateEntity.getTemplateSubject(), content, fileList, receiverUserList, true); + + } catch (Throwable e) { + log.error("邮件发送失败", e); + return ResponseDTO.userErrorParam("邮件发送失败"); + } + return ResponseDTO.ok(); + } + + /** + * 使用模板发送邮件 + */ + public ResponseDTO sendMail(MailTemplateCodeEnum templateCode, Map templateParamsMap, List receiverUserList) { + return this.sendMail(templateCode, templateParamsMap, receiverUserList, null); + } + + + /** + * 发送邮件 + * + * @param subject 主题 + * @param content 内容 + * @param fileList 文件 + * @param receiverUserList 接收方 + * @throws MessagingException + */ + public void sendMail(String subject, String content, List fileList, List receiverUserList, boolean isHtml) throws MessagingException { + + if (CollectionUtils.isEmpty(receiverUserList)) { + throw new RuntimeException("接收方不能为空"); + } + + if (StringUtils.isBlank(content)) { + throw new RuntimeException("邮件内容不能为空"); + } + + if (!systemEnvironment.isProd()) { + subject = "(测试)" + subject; + } + + MimeMessage mimeMessage = javaMailSender.createMimeMessage(); + + //是否为多文件上传 + boolean multiparty = !CollectionUtils.isEmpty(fileList); + MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, multiparty); + helper.setFrom(clientMail); + helper.setTo(receiverUserList.toArray(new String[0])); + helper.setSubject(subject); + //发送html格式 + helper.setText(content, isHtml); + + //附件 + if (multiparty) { + for (File file : fileList) { + helper.addAttachment(file.getName(), file); + } + } + javaMailSender.send(mimeMessage); + } + + /** + * 使用字符串生成最终内容 + */ + private String stringResolverContent(String stringTemplate, Map templateParamsMap) { + StringSubstitutor stringSubstitutor = new StringSubstitutor(templateParamsMap); + String contractHtml = stringSubstitutor.replace(stringTemplate); + Document doc = Jsoup.parse(contractHtml); + doc.outputSettings().syntax(Document.OutputSettings.Syntax.xml); + return doc.outerHtml(); + } + + + /** + * 使用 freemarker 生成最终内容 + */ + private String freemarkerResolverContent(String htmlTemplate, Map templateParamsMap) { + Configuration configuration = new Configuration(Configuration.VERSION_2_3_23); + StringTemplateLoader stringLoader = new StringTemplateLoader(); + String templateName = UUID.fastUUID().toString(true); + stringLoader.putTemplate(templateName, htmlTemplate); + configuration.setTemplateLoader(stringLoader); + try { + Template template = configuration.getTemplate(templateName, "utf-8"); + Writer out = new StringWriter(2048); + template.process(templateParamsMap, out); + return out.toString(); + } catch (Throwable e) { + log.error("freemarkerResolverContent error: ", e); + } + return ""; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/MailTemplateDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/MailTemplateDao.java new file mode 100644 index 0000000..ecc6b07 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/MailTemplateDao.java @@ -0,0 +1,21 @@ +package net.lab1024.sa.base.module.support.mail; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.mail.domain.MailTemplateEntity; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +/** + * 邮件模板 + * + * @Author 1024创新实验室-创始人兼主任:卓大 + * @Date 2024/8/5 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 ,Since 2012 + */ +@Mapper +public interface MailTemplateDao extends BaseMapper { + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/constant/MailTemplateCodeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/constant/MailTemplateCodeEnum.java new file mode 100644 index 0000000..9eab6ca --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/constant/MailTemplateCodeEnum.java @@ -0,0 +1,19 @@ +package net.lab1024.sa.base.module.support.mail.constant; + +/** + * 模版编码 + * + * @Author 1024创新实验室-创始人兼主任:卓大 + * @Date 2024/8/5 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 ,Since 2012 + */ +public enum MailTemplateCodeEnum { + + /** + * 登录验证码 + */ + LOGIN_VERIFICATION_CODE + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/constant/MailTemplateTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/constant/MailTemplateTypeEnum.java new file mode 100644 index 0000000..f26ef24 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/constant/MailTemplateTypeEnum.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.base.module.support.mail.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 邮件模板类型 + * + * @Author 1024创新实验室-创始人兼主任:卓大 + * @Date 2024/8/5 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 ,Since 2012 + */ + +@Getter +@AllArgsConstructor +public enum MailTemplateTypeEnum implements BaseEnum { + + STRING("string", "字符串替代器"), + + FREEMARKER("freemarker", "freemarker模板引擎"); + + private String value; + + private String desc; + + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/domain/MailTemplateEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/domain/MailTemplateEntity.java new file mode 100644 index 0000000..8f16163 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/mail/domain/MailTemplateEntity.java @@ -0,0 +1,51 @@ +package net.lab1024.sa.base.module.support.mail.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * + * 邮件模板 + * + * @Author 1024创新实验室-创始人兼主任:卓大 + * @Date 2024/8/5 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 ,Since 2012 + */ +@Data +@TableName("t_mail_template") +public class MailTemplateEntity { + + @TableId(type = IdType.NONE) + private String templateCode; + + /** + * 主题 + */ + private String templateSubject; + + /** + * 模板类型 + */ + private String templateType; + + /** + * 模板内容 + */ + private String templateContent; + + /** + * 禁用标识 + */ + private Boolean disableFlag; + + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/constant/MessageTemplateEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/constant/MessageTemplateEnum.java new file mode 100644 index 0000000..d9c6785 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/constant/MessageTemplateEnum.java @@ -0,0 +1,31 @@ +package net.lab1024.sa.base.module.support.message.constant; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 消息模板类型 + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Getter +@AllArgsConstructor +public enum MessageTemplateEnum implements BaseEnum { + + + + ORDER_AUDIT(1000, "订单审批", MessageTypeEnum.ORDER, "您有一个订单等待审批,订单号【${orderNumber}】"), + + ; + + private final Integer value; + + private final String desc; + + private final MessageTypeEnum messageTypeEnum; + + private final String content; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/constant/MessageTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/constant/MessageTypeEnum.java new file mode 100644 index 0000000..b94cb10 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/constant/MessageTypeEnum.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.message.constant; + + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + + +/** + * 消息类型 + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Getter +@AllArgsConstructor +public enum MessageTypeEnum implements BaseEnum { + + MAIL(1, "站内信"), + + ORDER(2, "订单"), + ; + + private final Integer value; + + private final String desc; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/controller/MessageController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/controller/MessageController.java new file mode 100644 index 0000000..449a124 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/controller/MessageController.java @@ -0,0 +1,67 @@ +package net.lab1024.sa.base.module.support.message.controller; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.message.domain.MessageQueryForm; +import net.lab1024.sa.base.module.support.message.domain.MessageVO; +import net.lab1024.sa.base.module.support.message.service.MessageService; +import org.springframework.web.bind.annotation.*; + +/** + * 消息 + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@RestController +@Tag(name = SwaggerTagConst.Support.MESSAGE) +public class MessageController extends SupportBaseController { + + @Resource + private MessageService messageService; + + @Operation(summary = "分页查询我的消息 @luoyi") + @PostMapping("/message/queryMyMessage") + public ResponseDTO> query(@RequestBody @Valid MessageQueryForm queryForm) { + RequestUser user = SmartRequestUtil.getRequestUser(); + if(user == null){ + return ResponseDTO.userErrorParam("用户未登录"); + } + + queryForm.setSearchCount(false); + queryForm.setReceiverUserId(user.getUserId()); + queryForm.setReceiverUserType(user.getUserType().getValue()); + return ResponseDTO.ok(messageService.query(queryForm)); + } + + @Operation(summary = "查询未读消息数量 @luoyi") + @GetMapping("/message/getUnreadCount") + public ResponseDTO getUnreadCount() { + RequestUser user = SmartRequestUtil.getRequestUser(); + if(user == null){ + return ResponseDTO.userErrorParam("用户未登录"); + } + return ResponseDTO.ok(messageService.getUnreadCount(user.getUserType(), user.getUserId())); + } + + @Operation(summary = "更新已读 @luoyi") + @GetMapping("/message/read/{messageId}") + public ResponseDTO updateReadFlag(@PathVariable Long messageId) { + RequestUser user = SmartRequestUtil.getRequestUser(); + if(user == null){ + return ResponseDTO.userErrorParam("用户未登录"); + } + + messageService.updateReadFlag(messageId, user.getUserType(), user.getUserId()); + return ResponseDTO.ok(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/dao/MessageDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/dao/MessageDao.java new file mode 100644 index 0000000..01389e0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/dao/MessageDao.java @@ -0,0 +1,45 @@ +package net.lab1024.sa.base.module.support.message.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.message.domain.MessageEntity; +import net.lab1024.sa.base.module.support.message.domain.MessageQueryForm; +import net.lab1024.sa.base.module.support.message.domain.MessageVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 消息 接受者类型枚举 + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Mapper +public interface MessageDao extends BaseMapper { + + /** + * 分页查询消息 + * + */ + List query(Page page, @Param("query") MessageQueryForm queryForm); + + /** + * 更新已读状态 + */ + Integer updateReadFlag(@Param("messageId") Long messageId, + @Param("receiverUserType") Integer receiverUserType, + @Param("receiverUserId") Long receiverUserId, + @Param("readFlag") Boolean readFlag); + + /** + * 查询未读消息数 + */ + Long getUnreadCount( @Param("receiverUserType") Integer receiverUserType, + @Param("receiverUserId") Long receiverUserId); + + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageEntity.java new file mode 100644 index 0000000..673ed69 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageEntity.java @@ -0,0 +1,70 @@ +package net.lab1024.sa.base.module.support.message.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.base.module.support.message.constant.MessageTypeEnum; + +import java.time.LocalDateTime; + +/** + * 消息实体 + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Data +@TableName("t_message") +public class MessageEntity { + + @TableId(type = IdType.AUTO) + private Long messageId; + + /** + * 消息类型 + * + * @see MessageTypeEnum + */ + private Integer messageType; + /** + * 接收者类型 + * + * @see net.lab1024.sa.base.common.enumeration.UserTypeEnum + */ + private Integer receiverUserType; + + /** + * 接收者id + */ + private Long receiverUserId; + + /** + * 相关业务id + */ + private String dataId; + + /** + * 消息标题 + */ + private String title; + + /** + * 消息内容 + */ + private String content; + + /** + * 是否已读 + */ + private Boolean readFlag; + + /** + * 已读时间 + */ + private LocalDateTime readTime; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageQueryForm.java new file mode 100644 index 0000000..fe80d70 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageQueryForm.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.base.module.support.message.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.common.validator.enumeration.CheckEnum; +import net.lab1024.sa.base.module.support.message.constant.MessageTypeEnum; +import org.hibernate.validator.constraints.Length; + +import java.time.LocalDate; + +/** + * 消息查询form + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Data +public class MessageQueryForm extends PageParam { + + @Schema(description = "搜索词") + @Length(max = 50, message = "搜索词最多50字符") + private String searchWord; + + @SchemaEnum(value = MessageTypeEnum.class) + @CheckEnum(value = MessageTypeEnum.class, message = "消息类型") + private Integer messageType; + + @Schema(description = "是否已读") + private Boolean readFlag; + + @Schema(description = "查询开始时间") + private LocalDate startDate; + + @Schema(description = "查询结束时间") + private LocalDate endDate; + + @Schema(description = "接收人") + private Long receiverUserId; + + @Schema(description = "接收人类型") + private Integer receiverUserType; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageSendForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageSendForm.java new file mode 100644 index 0000000..d62d216 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageSendForm.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.base.module.support.message.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.message.constant.MessageTypeEnum; +/** + * 消息发送form + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Data +public class MessageSendForm { + + @SchemaEnum(value = MessageTypeEnum.class, desc = "消息类型") + @NotNull(message = "消息类型不能为空") + private Integer messageType; + + @SchemaEnum(value = UserTypeEnum.class, desc = "接收者类型") + @NotNull(message = "接收者类型不能为空") + private Integer receiverUserType; + + @Schema(description = "接收者id") + @NotNull(message = "接收者id不能为空") + private Long receiverUserId; + + @Schema(description = "标题") + @NotBlank(message = "标题") + private String title; + + @Schema(description = "内容") + @NotBlank(message = "内容") + private String content; + + /** + * 相关业务id | 可选 + */ + private Object dataId; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageTemplateSendForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageTemplateSendForm.java new file mode 100644 index 0000000..9f70ac6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageTemplateSendForm.java @@ -0,0 +1,41 @@ +package net.lab1024.sa.base.module.support.message.domain; + +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.module.support.message.constant.MessageTemplateEnum; + +import java.util.Map; + +/** + * 消息发送form + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Data +public class MessageTemplateSendForm { + + @NotNull(message = "消息子类型不能为空") + private MessageTemplateEnum messageTemplateEnum; + + @NotNull(message = "接收者类型不能为空") + private UserTypeEnum receiverUserType; + + @NotNull(message = "接收者id不能为空") + private Long receiverUserId; + + /** + * 相关业务id | 可选 + * 用于跳转具体业务 + */ + private Object dataId; + + /** + * 消息参数 | 可选 + * 例:订单号:【{orderId}】{time}所提交的对账单被作废,请核实信息重新提交~ + * {orderId} {time} 就是消息的参数变量 + * 发送消息时 需要在map中放入k->orderId k->time + */ + private Map contentParam; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageVO.java new file mode 100644 index 0000000..eb7366f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/domain/MessageVO.java @@ -0,0 +1,48 @@ +package net.lab1024.sa.base.module.support.message.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; +import net.lab1024.sa.base.module.support.message.constant.MessageTypeEnum; + +import java.time.LocalDateTime; + +/** + * 消息 + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Data +public class MessageVO { + + private Long messageId; + + @SchemaEnum(value = MessageTypeEnum.class) + private Integer messageType; + + @SchemaEnum(value = UserTypeEnum.class) + private Integer receiverUserType; + + @Schema(description = "接收者id") + private Long receiverUserId; + + @Schema(description = "相关业务id") + private String dataId; + + @Schema(description = "消息标题") + private String title; + + @Schema(description = "消息内容") + private String content; + + @Schema(description = "是否已读") + private Boolean readFlag; + + @Schema(description = "已读时间") + private LocalDateTime readTime; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/service/MessageManager.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/service/MessageManager.java new file mode 100644 index 0000000..e1e2419 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/service/MessageManager.java @@ -0,0 +1,18 @@ +package net.lab1024.sa.base.module.support.message.service; + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import net.lab1024.sa.base.module.support.message.dao.MessageDao; +import net.lab1024.sa.base.module.support.message.domain.MessageEntity; +import org.springframework.stereotype.Service; + +/** + * 消息manager + * + * @author luoyi + * @date 2024/06/22 20:20 + */ +@Service +public class MessageManager extends ServiceImpl { + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/service/MessageService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/service/MessageService.java new file mode 100644 index 0000000..d380c19 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/message/service/MessageService.java @@ -0,0 +1,118 @@ +package net.lab1024.sa.base.module.support.message.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.google.common.collect.Lists; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.message.constant.MessageTemplateEnum; +import net.lab1024.sa.base.module.support.message.dao.MessageDao; +import net.lab1024.sa.base.module.support.message.domain.*; +import org.apache.commons.text.StringSubstitutor; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author luoyi + * @date 2024/6/27 12:14 上午 + */ +@Service +public class MessageService { + + @Resource + private MessageDao messageDao; + + @Resource + private MessageManager messageManager; + + /** + * 分页查询 消息 + */ + public PageResult query(MessageQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List messageVOList = messageDao.query(page, queryForm); + return SmartPageUtil.convert2PageResult(page, messageVOList); + } + + /** + * 查询未读消息数量 + */ + public Long getUnreadCount(UserTypeEnum userType, Long userId) { + return messageDao.getUnreadCount(userType.getValue(), userId); + } + + /** + * 更新已读状态 + */ + public void updateReadFlag(Long messageId, UserTypeEnum userType, Long receiverUserId) { + messageDao.updateReadFlag(messageId, userType.getValue(), receiverUserId, true); + } + + + /** + * 发送【模板消息】 + */ + public void sendTemplateMessage(MessageTemplateSendForm... sendTemplateForms) { + List sendFormList = Lists.newArrayList(); + for (MessageTemplateSendForm sendTemplateForm : sendTemplateForms) { + MessageTemplateEnum msgTemplateTypeEnum = sendTemplateForm.getMessageTemplateEnum(); + StringSubstitutor stringSubstitutor = new StringSubstitutor(sendTemplateForm.getContentParam()); + String content = stringSubstitutor.replace(msgTemplateTypeEnum.getContent()); + + MessageSendForm messageSendForm = new MessageSendForm(); + messageSendForm.setMessageType(msgTemplateTypeEnum.getMessageTypeEnum().getValue()); + messageSendForm.setReceiverUserType(sendTemplateForm.getReceiverUserType().getValue()); + messageSendForm.setReceiverUserId(sendTemplateForm.getReceiverUserId()); + messageSendForm.setTitle(msgTemplateTypeEnum.getDesc()); + messageSendForm.setContent(content); + messageSendForm.setDataId(sendTemplateForm.getDataId()); + sendFormList.add(messageSendForm); + + } + this.sendMessage(sendFormList); + } + + /** + * 发送消息 + */ + public void sendMessage(MessageSendForm... sendForms) { + this.sendMessage(Lists.newArrayList(sendForms)); + } + + /** + * 批量发送通知消息 + */ + public void sendMessage(List sendList) { + for (MessageSendForm sendDTO : sendList) { + String verify = SmartBeanUtil.verify(sendDTO); + if (null != verify) { + throw new RuntimeException("send msg error: " + verify); + } + } + List messageEntityList = sendList.stream().map(e -> { + MessageEntity messageEntity = new MessageEntity(); + messageEntity.setMessageType(e.getMessageType()); + messageEntity.setReceiverUserType(e.getReceiverUserType()); + messageEntity.setReceiverUserId(e.getReceiverUserId()); + messageEntity.setDataId(String.valueOf(e.getDataId())); + messageEntity.setTitle(e.getTitle()); + messageEntity.setContent(e.getContent()); + return messageEntity; + }).collect(Collectors.toList()); + messageManager.saveBatch(messageEntityList); + } + + // 删除消息 + public ResponseDTO delete(Long messageId) { + if(messageId == null){ + return ResponseDTO.userErrorParam(); + } + messageDao.deleteById(messageId); + return ResponseDTO.ok(); + } +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/OperateLogDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/OperateLogDao.java new file mode 100644 index 0000000..982c1a3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/OperateLogDao.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.module.support.operatelog; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogEntity; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogQueryForm; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 操作日志 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Mapper +public interface OperateLogDao extends BaseMapper { + + /** + * 分页查询 + * @param page + * @param queryForm + * @return UserOperateLogEntity + */ + List queryByPage(Page page, @Param("query") OperateLogQueryForm queryForm); + + + /** + * 批量删除 + * + * @param idList + * @return + */ + void deleteByIds(@Param("idList") List idList); + + /** + * 去重模块名称(下拉) + */ + List selectDistinctModules(); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/OperateLogService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/OperateLogService.java new file mode 100644 index 0000000..5ad1684 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/OperateLogService.java @@ -0,0 +1,69 @@ +package net.lab1024.sa.base.module.support.operatelog; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogEntity; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogQueryForm; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogVO; +import org.springframework.stereotype.Service; + +import java.util.Collections; +import java.util.List; + +/** + * 操作日志 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Service +public class OperateLogService { + + @Resource + private OperateLogDao operateLogDao; + + /** + * @author 罗伊 + * @description 分页查询 + */ + public ResponseDTO> queryByPage(OperateLogQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List logEntityList = operateLogDao.queryByPage(page, queryForm); + PageResult pageResult = SmartPageUtil.convert2PageResult(page, logEntityList, OperateLogVO.class); + return ResponseDTO.ok(pageResult); + } + + + /** + * 查询详情 + * @param operateLogId + * @return + */ + public ResponseDTO detail(Long operateLogId) { + OperateLogEntity operateLogEntity = operateLogDao.selectById(operateLogId); + if(operateLogEntity == null){ + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + OperateLogVO operateLogVO = SmartBeanUtil.copy(operateLogEntity, OperateLogVO.class); + return ResponseDTO.ok(operateLogVO); + } + + /** + * 操作模块下拉(去重) + */ + public ResponseDTO> queryModuleList() { + List list = operateLogDao.selectDistinctModules(); + if (list == null) { + return ResponseDTO.ok(Collections.emptyList()); + } + return ResponseDTO.ok(list); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/annotation/OperateLog.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/annotation/OperateLog.java new file mode 100644 index 0000000..232cbe1 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/annotation/OperateLog.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.module.support.operatelog.annotation; + +import net.lab1024.sa.base.module.support.operatelog.core.OperationTypeEnum; + +import java.lang.annotation.*; + +/** + * 用户操作日志 注解(可选:用于忽略记录或覆盖模块/类型/说明) + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target({ElementType.TYPE, ElementType.METHOD}) +@Documented +public @interface OperateLog { + + /** + * 为 true 时不记录操作日志(如高频轮询接口) + */ + boolean ignored() default false; + + /** + * 操作类型(默认由切面根据 URL/HTTP 推导) + */ + OperationTypeEnum operationType() default OperationTypeEnum.OTHER; + + /** + * 覆盖操作模块(为空则使用 Swagger @Tag) + */ + String module() default ""; + + /** + * 覆盖操作说明(为空则使用 Swagger @Operation.summary) + */ + String content() default ""; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogAspect.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogAspect.java new file mode 100644 index 0000000..5d3415f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogAspect.java @@ -0,0 +1,373 @@ +package net.lab1024.sa.base.module.support.operatelog.core; + +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.servlet.JakartaServletUtil; +import com.alibaba.fastjson.JSON; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.constant.RequestHeaderConst; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.util.SmartIpUtil; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.module.support.operatelog.OperateLogDao; +import net.lab1024.sa.base.module.support.operatelog.annotation.OperateLog; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogEntity; +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.springframework.boot.context.properties.bind.BindResult; +import org.springframework.context.ApplicationContext; +import org.springframework.core.annotation.AnnotationUtils; +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.multipart.MultipartFile; +import org.springframework.web.servlet.ModelAndView; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ThreadPoolExecutor; + +/** + * 操作日志:全局拦截 Controller,异步落库 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Slf4j +@Aspect +public abstract class OperateLogAspect { + + private static final String POINT_CUT = + "execution(* net.lab1024.sa..*.controller..*.*(..)) || execution(* net.lab1024.sa..*Controller.*(..))"; + + @Resource + private ApplicationContext applicationContext; + + private ThreadPoolTaskExecutor taskExecutor; + + public abstract OperateLogConfig getOperateLogConfig(); + + public OperateLogAspect() { + this.initThread(); + } + + @Pointcut(POINT_CUT) + public void logPointCut() { + } + + @Around("logPointCut()") + public Object aroundController(ProceedingJoinPoint joinPoint) throws Throwable { + ServletRequestAttributes attrs = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + if (attrs == null) { + return joinPoint.proceed(); + } + HttpServletRequest request = attrs.getRequest(); + String uri = request.getRequestURI(); + if (uri == null) { + uri = StringConst.EMPTY; + } + if (shouldIgnoreUri(uri)) { + return joinPoint.proceed(); + } + + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + OperateLog classAnn = AnnotationUtils.findAnnotation(method.getDeclaringClass(), OperateLog.class); + OperateLog methodAnn = AnnotationUtils.findAnnotation(method, OperateLog.class); + if (isIgnored(classAnn, methodAnn)) { + return joinPoint.proceed(); + } + + Object result = null; + Throwable error = null; + try { + result = joinPoint.proceed(); + return result; + } catch (Throwable t) { + error = t; + throw t; + } finally { + try { + enqueueLog(joinPoint, request, result, error, classAnn, methodAnn); + } catch (Exception e) { + log.error("保存操作日志异常:{}", e.getMessage()); + } + } + } + + private boolean shouldIgnoreUri(String uri) { + OperateLogConfig cfg = getOperateLogConfig(); + List patterns = cfg.getIgnoreUrlPatterns(); + if (patterns == null || patterns.isEmpty()) { + return false; + } + for (String p : patterns) { + if (StrUtil.isNotBlank(p) && uri.contains(p)) { + return true; + } + } + return false; + } + + private boolean isIgnored(OperateLog classAnn, OperateLog methodAnn) { + if (methodAnn != null) { + return methodAnn.ignored(); + } + return classAnn != null && classAnn.ignored(); + } + + private void initThread() { + OperateLogConfig config = getOperateLogConfig(); + int corePoolSize = Runtime.getRuntime().availableProcessors(); + if (null != config.getCorePoolSize()) { + corePoolSize = config.getCorePoolSize(); + } + taskExecutor = new ThreadPoolTaskExecutor(); + taskExecutor.initialize(); + taskExecutor.setCorePoolSize(corePoolSize); + taskExecutor.setMaxPoolSize(corePoolSize * 2); + int queue = 1000; + if (config.getQueueCapacity() != null) { + queue = config.getQueueCapacity(); + } + taskExecutor.setQueueCapacity(queue); + taskExecutor.setKeepAliveSeconds(60); + taskExecutor.setThreadNamePrefix("smart-operate-log"); + taskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); + taskExecutor.setWaitForTasksToCompleteOnShutdown(true); + } + + private void enqueueLog(ProceedingJoinPoint joinPoint, HttpServletRequest request, Object result, Throwable error, + OperateLog classAnn, OperateLog methodAnn) { + OperateLogConfig cfg = getOperateLogConfig(); + Set maskKeys = OperateLogMaskUtil.mergeMaskKeys(cfg.getMaskFieldNames()); + + RequestUser user = SmartRequestUtil.getRequestUser(); + Long operateUserId = 0L; + Integer operateUserType = 0; + String operateUserName = "匿名"; + String operateUserAccount = StringConst.EMPTY; + String operateUserRole = StringConst.EMPTY; + String ip = JakartaServletUtil.getClientIP(request); + String ua = JakartaServletUtil.getHeaderIgnoreCase(request, RequestHeaderConst.USER_AGENT); + if (user != null) { + operateUserId = user.getUserId() == null ? 0L : user.getUserId(); + operateUserType = user.getUserType() == null ? 0 : user.getUserType().getValue(); + operateUserName = StrUtil.blankToDefault(user.getUserName(), "匿名"); + operateUserAccount = StrUtil.nullToEmpty(user.getLoginAccount()); + operateUserRole = StrUtil.nullToEmpty(user.getRoleNames()); + if (StrUtil.isNotBlank(user.getIp())) { + ip = user.getIp(); + } + if (StrUtil.isNotBlank(user.getUserAgent())) { + ua = user.getUserAgent(); + } + } + + String className = joinPoint.getTarget().getClass().getName(); + String simpleMethod = joinPoint.getSignature().getName(); + String javaMethod = className + "." + simpleMethod; + String httpMethod = request.getMethod(); + String uri = request.getRequestURI(); + + String paramRaw = buildParamRaw(joinPoint.getArgs(), request); + String paramMasked = OperateLogMaskUtil.maskAndTruncate(paramRaw, cfg.getMaxParamLength(), maskKeys); + + boolean success = error == null; + String failReason = null; + if (!success) { + failReason = OperateLogMaskUtil.truncate(getExceptionString(error), cfg.getMaxResultLength()); + } + + String responseRaw = StringConst.EMPTY; + if (success && cfg.isRecordResponse()) { + responseRaw = serializeResult(result); + } else if (!success) { + responseRaw = StringConst.EMPTY; + } + String responseMasked = OperateLogMaskUtil.maskAndTruncate(responseRaw, cfg.getMaxResultLength(), maskKeys); + + OperationTypeEnum opEnum = resolveOperationType(classAnn, methodAnn, uri, httpMethod); + // 可通过配置关闭查询类日志(避免日志量过大);后续需要再打开即可 + if (!cfg.isRecordQuery()) { + if (OperationTypeEnum.QUERY == opEnum || "GET".equalsIgnoreCase(httpMethod)) { + return; + } + } + String module = resolveModule(classAnn, methodAnn, joinPoint); + String content = resolveContent(classAnn, methodAnn, joinPoint); + + String deviceInfo = OperateLogMaskUtil.parseDevice(ua); + String osInfo = OperateLogMaskUtil.parseOs(ua); + + OperateLogEntity entity = OperateLogEntity.builder() + .operateUserId(operateUserId) + .operateUserType(operateUserType) + .operateUserName(operateUserName) + .operateUserAccount(operateUserAccount) + .operateUserRole(operateUserRole) + .module(module) + .content(content) + .url(uri) + .method(javaMethod) + .httpMethod(httpMethod) + .operationType(opEnum.getCode()) + .param(paramMasked) + .ip(ip) + .ipRegion(SmartIpUtil.getRegion(ip)) + .userAgent(ua) + .deviceInfo(deviceInfo) + .osInfo(osInfo) + .responseResult(responseMasked) + .successFlag(success) + .failReason(failReason) + .build(); + + taskExecutor.execute(() -> saveLog(entity)); + } + + private OperationTypeEnum resolveOperationType(OperateLog classAnn, OperateLog methodAnn, String uri, String httpMethod) { + OperationTypeEnum fromMethod = methodAnn == null ? null : pickNonOther(methodAnn.operationType()); + if (fromMethod != null) { + return fromMethod; + } + OperationTypeEnum fromClass = classAnn == null ? null : pickNonOther(classAnn.operationType()); + if (fromClass != null) { + return fromClass; + } + return OperationTypeEnum.derive(uri, httpMethod); + } + + private OperationTypeEnum pickNonOther(OperationTypeEnum e) { + if (e == null || e == OperationTypeEnum.OTHER) { + return null; + } + return e; + } + + private String resolveModule(OperateLog classAnn, OperateLog methodAnn, ProceedingJoinPoint joinPoint) { + if (methodAnn != null && StrUtil.isNotBlank(methodAnn.module())) { + return methodAnn.module(); + } + if (classAnn != null && StrUtil.isNotBlank(classAnn.module())) { + return classAnn.module(); + } + Tag tag = getTag(joinPoint); + if (tag != null) { + return StrUtil.join(",", tag.name()); + } + return StringConst.EMPTY; + } + + private String resolveContent(OperateLog classAnn, OperateLog methodAnn, ProceedingJoinPoint joinPoint) { + if (methodAnn != null && StrUtil.isNotBlank(methodAnn.content())) { + return methodAnn.content(); + } + if (classAnn != null && StrUtil.isNotBlank(classAnn.content())) { + return classAnn.content(); + } + Operation op = getOperation(joinPoint); + if (op != null) { + return op.summary(); + } + return StringConst.EMPTY; + } + + private Tag getTag(ProceedingJoinPoint joinPoint) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + return AnnotationUtils.findAnnotation(method.getDeclaringClass(), Tag.class); + } + + private Operation getOperation(ProceedingJoinPoint joinPoint) { + MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature(); + Method method = methodSignature.getMethod(); + return method.getAnnotation(Operation.class); + } + + private String buildParamRaw(Object[] args, HttpServletRequest request) { + StringBuilder sb = new StringBuilder(); + String body = buildParamString(args); + if (StrUtil.isNotBlank(body)) { + sb.append(body); + } + String qs = request.getQueryString(); + if (StrUtil.isNotBlank(qs)) { + if (sb.length() > 0) { + sb.append(' '); + } + sb.append("queryString=").append(qs); + } + return sb.toString(); + } + + private String buildParamString(Object[] args) { + if (args == null || args.length == 0) { + return StringConst.EMPTY; + } + List filterArgs = new ArrayList<>(); + for (Object arg : args) { + if (arg == null) { + continue; + } + if (arg instanceof HttpServletRequest + || arg instanceof HttpServletResponse + || arg instanceof ModelAndView + || arg instanceof MultipartFile + || arg instanceof BindResult) { + continue; + } + filterArgs.add(arg); + } + return JSON.toJSONString(filterArgs); + } + + private String serializeResult(Object result) { + if (result == null) { + return StringConst.EMPTY; + } + try { + return JSON.toJSONString(result); + } catch (Exception e) { + return String.valueOf(result); + } + } + + private String getExceptionString(Throwable e) { + StringWriter sw = new StringWriter(); + try (PrintWriter pw = new PrintWriter(sw)) { + e.printStackTrace(pw); + } + return sw.toString(); + } + + private Boolean saveLog(OperateLogEntity operateLogEntity) { + OperateLogConfig operateLogConfig = getOperateLogConfig(); + if (operateLogConfig.getSaveFunction() == null) { + BaseMapper mapper = applicationContext.getBean(OperateLogDao.class); + if (mapper == null) { + return false; + } + mapper.insert(operateLogEntity); + return true; + } + return operateLogConfig.getSaveFunction().apply(operateLogEntity); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogConfig.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogConfig.java new file mode 100644 index 0000000..5b6aac7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogConfig.java @@ -0,0 +1,77 @@ +package net.lab1024.sa.base.module.support.operatelog.core; + +import lombok.Builder; +import lombok.Data; +import net.lab1024.sa.base.module.support.operatelog.domain.OperateLogEntity; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + +/** + * 配置 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@Builder +public class OperateLogConfig { + + /** + * 操作日志存储方法 + */ + private Function saveFunction; + + /** + * 核心线程数 + */ + private Integer corePoolSize; + + /** + * 队列大小 + */ + private Integer queueCapacity; + + /** + * 请求 URI 包含以下任一子串时不记录(防循环、大文件等) + */ + @Builder.Default + private List ignoreUrlPatterns = new ArrayList<>(); + + /** + * 请求参数最大长度 + */ + @Builder.Default + private Integer maxParamLength = 4000; + + /** + * 响应结果最大长度 + */ + @Builder.Default + private Integer maxResultLength = 4000; + + /** + * 额外脱敏字段名(小写比较) + */ + @Builder.Default + private Set maskFieldNames = new HashSet<>(); + + /** + * 是否记录响应体 + */ + @Builder.Default + private boolean recordResponse = true; + + /** + * 是否记录查询类日志(OperationType=QUERY 或 HTTP=GET) + * 默认 true;可在 admin 的 OperateLogAspectConfig 里关闭,避免日志量过大 + */ + @Builder.Default + private boolean recordQuery = true; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogMaskUtil.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogMaskUtil.java new file mode 100644 index 0000000..7b67b06 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperateLogMaskUtil.java @@ -0,0 +1,205 @@ +package net.lab1024.sa.base.module.support.operatelog.core; + +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashSet; +import java.util.Locale; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * 操作日志:参数/响应脱敏、截断、UA 轻量解析 + * + * @author smart-flow + */ +@Slf4j +public final class OperateLogMaskUtil { + + private static final String MASK = "***"; + private static final String TRUNC_SUFFIX = "...(truncated)"; + + private static final Set DEFAULT_MASK_KEYS = new HashSet<>(); + + static { + DEFAULT_MASK_KEYS.add("password"); + DEFAULT_MASK_KEYS.add("pwd"); + DEFAULT_MASK_KEYS.add("loginpwd"); + DEFAULT_MASK_KEYS.add("oldpwd"); + DEFAULT_MASK_KEYS.add("newpwd"); + DEFAULT_MASK_KEYS.add("token"); + DEFAULT_MASK_KEYS.add("authorization"); + DEFAULT_MASK_KEYS.add("secret"); + DEFAULT_MASK_KEYS.add("appkey"); + DEFAULT_MASK_KEYS.add("appsecret"); + DEFAULT_MASK_KEYS.add("accesstoken"); + DEFAULT_MASK_KEYS.add("refreshtoken"); + DEFAULT_MASK_KEYS.add("idcard"); + DEFAULT_MASK_KEYS.add("bankcard"); + DEFAULT_MASK_KEYS.add("cardno"); + } + + private static final Pattern WIN_VER = Pattern.compile("Windows NT ([0-9.]+)", Pattern.CASE_INSENSITIVE); + private static final Pattern MAC_OS = Pattern.compile("Mac OS X ([0-9_]+)", Pattern.CASE_INSENSITIVE); + private static final Pattern ANDROID = Pattern.compile("Android ([0-9.]+)", Pattern.CASE_INSENSITIVE); + private static final Pattern IPHONE = Pattern.compile("iPhone OS ([0-9_]+)", Pattern.CASE_INSENSITIVE); + private static final Pattern CHROME = Pattern.compile("Chrome/([0-9.]+)", Pattern.CASE_INSENSITIVE); + private static final Pattern EDG = Pattern.compile("Edg/([0-9.]+)", Pattern.CASE_INSENSITIVE); + private static final Pattern FIREFOX = Pattern.compile("Firefox/([0-9.]+)", Pattern.CASE_INSENSITIVE); + private static final Pattern SAFARI = Pattern.compile("Version/([0-9.]+).*Safari/", Pattern.CASE_INSENSITIVE); + + private OperateLogMaskUtil() { + } + + public static Set mergeMaskKeys(Set extra) { + Set all = new HashSet<>(DEFAULT_MASK_KEYS); + if (extra != null) { + for (String k : extra) { + if (StrUtil.isNotBlank(k)) { + all.add(k.trim().toLowerCase(Locale.ROOT)); + } + } + } + return all; + } + + public static String maskAndTruncate(String raw, int maxLen, Set maskKeys) { + if (raw == null) { + return ""; + } + String masked = maskJsonLike(raw, maskKeys); + return truncate(masked, maxLen); + } + + public static String maskJsonLike(String raw, Set maskKeys) { + if (StrUtil.isBlank(raw)) { + return raw == null ? "" : raw; + } + String trimmed = raw.trim(); + try { + if (trimmed.startsWith("{")) { + JSONObject o = JSON.parseObject(trimmed); + maskObject(o, maskKeys); + return JSON.toJSONString(o); + } + if (trimmed.startsWith("[")) { + JSONArray a = JSON.parseArray(trimmed); + maskObject(a, maskKeys); + return JSON.toJSONString(a); + } + } catch (Exception e) { + log.trace("maskJsonLike parse skip: {}", e.getMessage()); + } + return raw; + } + + private static void maskObject(Object node, Set maskKeys) { + if (node == null) { + return; + } + if (node instanceof JSONObject jsonObject) { + for (String key : jsonObject.keySet()) { + Object val = jsonObject.get(key); + if (shouldMaskKey(key, maskKeys)) { + jsonObject.put(key, MASK); + } else if (val instanceof JSONObject || val instanceof JSONArray) { + maskObject(val, maskKeys); + } + } + } else if (node instanceof JSONArray jsonArray) { + for (int i = 0; i < jsonArray.size(); i++) { + Object val = jsonArray.get(i); + if (val instanceof JSONObject || val instanceof JSONArray) { + maskObject(val, maskKeys); + } + } + } + } + + private static boolean shouldMaskKey(String key, Set maskKeys) { + if (key == null) { + return false; + } + String k = key.toLowerCase(Locale.ROOT); + for (String mk : maskKeys) { + if (k.equals(mk) || k.contains(mk)) { + return true; + } + } + return false; + } + + public static String truncate(String s, int maxLen) { + if (s == null || maxLen <= 0) { + return ""; + } + if (s.length() <= maxLen) { + return s; + } + int keep = Math.max(0, maxLen - TRUNC_SUFFIX.length()); + return s.substring(0, keep) + TRUNC_SUFFIX; + } + + /** + * 从 User-Agent 解析操作系统简述 + */ + public static String parseOs(String ua) { + if (StrUtil.isBlank(ua)) { + return ""; + } + Matcher m; + m = ANDROID.matcher(ua); + if (m.find()) { + return "Android " + m.group(1); + } + m = IPHONE.matcher(ua); + if (m.find()) { + return "iOS " + m.group(1).replace('_', '.'); + } + m = MAC_OS.matcher(ua); + if (m.find()) { + return "macOS " + m.group(1).replace('_', '.'); + } + m = WIN_VER.matcher(ua); + if (m.find()) { + return "Windows " + m.group(1); + } + if (ua.contains("Linux")) { + return "Linux"; + } + return ""; + } + + /** + * 从 User-Agent 解析浏览器/设备简述 + */ + public static String parseDevice(String ua) { + if (StrUtil.isBlank(ua)) { + return ""; + } + Matcher m = EDG.matcher(ua); + if (m.find()) { + return "Edge " + m.group(1); + } + m = CHROME.matcher(ua); + if (m.find()) { + return "Chrome " + m.group(1); + } + m = FIREFOX.matcher(ua); + if (m.find()) { + return "Firefox " + m.group(1); + } + m = SAFARI.matcher(ua); + if (m.find()) { + return "Safari " + m.group(1); + } + if (ua.contains("Mobile")) { + return "Mobile"; + } + return "Desktop"; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperationTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperationTypeEnum.java new file mode 100644 index 0000000..295508c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/core/OperationTypeEnum.java @@ -0,0 +1,57 @@ +package net.lab1024.sa.base.module.support.operatelog.core; + +import cn.hutool.core.util.StrUtil; +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * 操作日志:操作类型(审计归类) + * + * @author smart-flow + */ +@Getter +@AllArgsConstructor +public enum OperationTypeEnum { + + QUERY("QUERY", "查询"), + CREATE("CREATE", "新增"), + UPDATE("UPDATE", "修改"), + DELETE("DELETE", "删除"), + OTHER("OTHER", "其他"); + + private final String code; + private final String desc; + + /** + * 根据 HTTP 方法与 URL 推导操作类型(无注解时使用) + */ + public static OperationTypeEnum derive(String url, String httpMethod) { + String u = url == null ? "" : url.toLowerCase(); + String m = httpMethod == null ? "" : httpMethod.toUpperCase(); + if ("DELETE".equals(m)) { + return DELETE; + } + if ("GET".equals(m)) { + return QUERY; + } + if (StrUtil.containsAny(u, "/delete", "/remove", "/del/", "deleteby", "batchdelete")) { + return DELETE; + } + if (StrUtil.containsAny(u, "/add", "/save", "/create", "/insert", "batchadd")) { + return CREATE; + } + if (StrUtil.containsAny(u, "/update", "/edit", "/modify", "/reset", "/change", "batchupdate")) { + return UPDATE; + } + if ("PUT".equals(m) || "PATCH".equals(m)) { + return UPDATE; + } + if ("POST".equals(m)) { + if (StrUtil.containsAny(u, "query", "page", "list", "get", "detail", "export", "download")) { + return QUERY; + } + return OTHER; + } + return OTHER; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogEntity.java new file mode 100644 index 0000000..c260e2d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogEntity.java @@ -0,0 +1,147 @@ +package net.lab1024.sa.base.module.support.operatelog.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * 操作记录 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor +@TableName("t_operate_log") +public class OperateLogEntity { + + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long operateLogId; + + /** + * 操作人id + */ + private Long operateUserId; + + /** + * 用户类型 + */ + private Integer operateUserType; + + /** + * 操作人名称(姓名) + */ + private String operateUserName; + + /** + * 登录账号 + */ + private String operateUserAccount; + + /** + * 角色名称汇总 + */ + private String operateUserRole; + + /** + * 操作模块 + */ + private String module; + + /** + * 操作内容 + */ + private String content; + + /** + * 请求路径 + */ + private String url; + + /** + * Java 类.方法 + */ + private String method; + + /** + * HTTP 方法 GET/POST/... + */ + private String httpMethod; + + /** + * 操作类型 QUERY/CREATE/... + */ + private String operationType; + + /** + * 请求参数 + */ + private String param; + + /** + * 客户ip + */ + private String ip; + + /** + * 客户ip地区 + */ + private String ipRegion; + + /** + * user-agent + */ + private String userAgent; + + /** + * 设备信息(浏览器等简述) + */ + private String deviceInfo; + + /** + * 操作系统简述 + */ + private String osInfo; + + /** + * 响应结果(脱敏截断后 JSON 文本) + */ + private String responseResult; + + /** + * 请求结果 0失败 1成功 + */ + private Boolean successFlag; + + /** + * 失败原因 + */ + private String failReason; + + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogQueryForm.java new file mode 100644 index 0000000..da81c0d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogQueryForm.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.module.support.operatelog.domain; + +import net.lab1024.sa.base.common.domain.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 操作日志查询 表单 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class OperateLogQueryForm extends PageParam { + + @Schema(description = "用户ID") + private Long operateUserId; + + @Schema(description = "用户类型") + private Integer operateUserType; + + @Schema(description = "关键字:模块、操作内容") + private String keywords; + + @Schema(description = "请求关键字:请求地址、请求方法、请求参数") + private String requestKeywords; + + @Schema(description = "开始日期") + private String startDate; + + @Schema(description = "结束日期") + private String endDate; + + + @Schema(description = "用户名称(姓名)") + private String userName; + + @Schema(description = "登录账号模糊") + private String loginName; + + @Schema(description = "操作模块(精确)") + private String module; + + @Schema(description = "HTTP方法") + private String httpMethod; + + @Schema(description = "操作类型 QUERY/CREATE/UPDATE/DELETE/OTHER") + private String operationType; + + @Schema(description = "请求结果 false失败 true成功") + private Boolean successFlag; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogVO.java new file mode 100644 index 0000000..58a7158 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/operatelog/domain/OperateLogVO.java @@ -0,0 +1,95 @@ +package net.lab1024.sa.base.module.support.operatelog.domain; + +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.swagger.SchemaEnum; + +import java.time.LocalDateTime; + +/** + * 操作日志信息 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2021-12-08 20:48:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class OperateLogVO { + + @Schema(description = "主键") + private Long operateLogId; + + @Schema(description = "用户id") + private Long operateUserId; + + @SchemaEnum(value = UserTypeEnum.class, desc = "用户类型") + private Integer operateUserType; + + @Schema(description = "用户名称(姓名)") + private String operateUserName; + + @Schema(description = "登录账号") + private String operateUserAccount; + + @Schema(description = "角色名称汇总") + private String operateUserRole; + + @Schema(description = "操作模块") + private String module; + + @Schema(description = "操作内容") + private String content; + + @Schema(description = "请求路径") + private String url; + + @Schema(description = "Java类方法") + private String method; + + @Schema(description = "HTTP方法") + private String httpMethod; + + @Schema(description = "操作类型") + private String operationType; + + @Schema(description = "请求参数") + private String param; + + @Schema(description = "客户ip") + private String ip; + + @Schema(description = "客户ip地区") + private String ipRegion; + + @Schema(description = "user-agent") + private String userAgent; + + @Schema(description = "设备信息") + private String deviceInfo; + + @Schema(description = "操作系统") + private String osInfo; + + @Schema(description = "响应结果") + private String responseResult; + + @Schema(description = "请求结果 0失败 1成功") + private Boolean successFlag; + + @Schema(description = "失败原因") + private String failReason; + + @Schema(description = "更新时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime updateTime; + + @Schema(description = "创建时间") + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") + private LocalDateTime createTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedisService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedisService.java new file mode 100644 index 0000000..a45f812 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedisService.java @@ -0,0 +1,224 @@ +package net.lab1024.sa.base.module.support.redis; + +import com.alibaba.fastjson.JSON; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.SystemEnvironment; +import net.lab1024.sa.base.common.enumeration.SystemEnvironmentEnum; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.constant.RedisKeyConst; +import org.slf4j.Logger; +import org.springframework.data.redis.core.*; +import org.springframework.stereotype.Service; +import org.springframework.util.CollectionUtils; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.ChronoUnit; +import java.util.Collection; +import java.util.List; +import java.util.concurrent.TimeUnit; + +/** + * redis 一顿操作 + * + * @Author 1024创新实验室: 罗伊 + * @Date 2020/8/25 21:57 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Service +public class RedisService { + + private static final Logger log = org.slf4j.LoggerFactory.getLogger(RedisService.class); + + @Resource + private StringRedisTemplate stringRedisTemplate; + + @Resource + private RedisTemplate redisTemplate; + + @Resource + private ValueOperations redisValueOperations; + + @Resource + private HashOperations redisHashOperations; + + @Resource + private ListOperations redisListOperations; + + @Resource + private SetOperations redisSetOperations; + + @Resource + private SystemEnvironment systemEnvironment; + + + /** + * 生成redis key + * @param prefix + * @param key + * @return + */ + public String generateRedisKey(String prefix, String key) { + SystemEnvironmentEnum currentEnvironment = systemEnvironment.getCurrentEnvironment(); + return systemEnvironment.getProjectName() + RedisKeyConst.SEPARATOR + currentEnvironment.getValue() + RedisKeyConst.SEPARATOR + prefix + key; + } + + /** + * redis key 解析成真实的内容 + * @param redisKey + * @return + */ + public static String redisKeyParse(String redisKey) { + if(SmartStringUtil.isBlank(redisKey)){ + return ""; + } + int index = redisKey.lastIndexOf(RedisKeyConst.SEPARATOR); + if(index < 1){ + return redisKey; + } + return redisKey.substring(index); + } + + public boolean getLock(String key, long expire) { + return redisValueOperations.setIfAbsent(key, String.valueOf(System.currentTimeMillis()), expire, TimeUnit.MILLISECONDS); + } + + public void unLock(String key) { + redisValueOperations.getOperations().delete(key); + } + + /** + * 指定缓存失效时间 + * + * @param key 键 + * @param time 时间(秒) + * @return + */ + public boolean expire(String key, long time) { + return redisTemplate.expire(key, time, TimeUnit.SECONDS); + } + + /** + * 获取当天剩余的秒数 + * + * @return + */ + public static long currentDaySecond() { + return ChronoUnit.SECONDS.between(LocalDateTime.now(), LocalDateTime.of(LocalDate.now(), LocalTime.MAX)); + } + + /** + * 根据key 获取过期时间 + * + * @param key 键 不能为null + * @return 时间(秒) 返回0代表为永久有效 + */ + public long getExpire(String key) { + return redisTemplate.getExpire(key, TimeUnit.SECONDS); + } + + /** + * 判断key是否存在 + * + * @param key 键 + * @return true 存在 false不存在 + */ + public boolean hasKey(String key) { + return redisTemplate.hasKey(key); + } + + /** + * 删除缓存 + * + * @param key 可以传一个值 或多个 + */ + @SuppressWarnings("unchecked") + public void delete(String... key) { + if (key != null && key.length > 0) { + if (key.length == 1) { + redisTemplate.delete(key[0]); + } else { + redisTemplate.delete((Collection) CollectionUtils.arrayToList(key)); + } + } + } + + /** + * 删除缓存 + * + * @param keyList + */ + public void delete(List keyList) { + if (CollectionUtils.isEmpty(keyList)) { + return; + } + redisTemplate.delete(keyList); + } + + //============================String============================= + + /** + * 普通缓存获取 + * + * @param key 键 + * @return 值 + */ + public String get(String key) { + return key == null ? null : redisValueOperations.get(key); + } + + public T getObject(String key, Class clazz) { + Object json = this.get(key); + if (json == null) { + return null; + } + T obj = JSON.parseObject(json.toString(), clazz); + return obj; + } + + + /** + * 普通缓存放入 + */ + public void set(String key, String value) { + redisValueOperations.set(key, value); + } + public void set(Object key, Object value) { + String jsonString = JSON.toJSONString(value); + redisValueOperations.set(key.toString(), jsonString); + } + + /** + * 普通缓存放入 + */ + public void set(String key, String value, long second) { + redisValueOperations.set(key, value, second, TimeUnit.SECONDS); + } + + /** + * 普通缓存放入并设置时间 + */ + public void set(Object key, Object value, long second) { + String jsonString = JSON.toJSONString(value); + if (second > 0) { + redisValueOperations.set(key.toString(), jsonString, second, TimeUnit.SECONDS); + } else { + set(key.toString(), jsonString); + } + } + + //============================ map ============================= + + + public void mset(String key, String hashKey, Object value) { + redisHashOperations.put(key, hashKey, value); + } + + public Object mget(String key, String hashKey) { + return redisHashOperations.get(key, hashKey); + } + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedissonPasswordConfigurationCustomizer.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedissonPasswordConfigurationCustomizer.java new file mode 100644 index 0000000..3781ca8 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedissonPasswordConfigurationCustomizer.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.redis; + +import net.lab1024.sa.base.common.util.SmartStringUtil; +import org.redisson.config.Config; +import org.redisson.spring.starter.RedissonAutoConfigurationCustomizer; +import org.springframework.stereotype.Component; + +/** + * + * redission对于password 为空处理有问题,重新设置下 + * + * @Author 1024创新实验室-主任:卓大 + * @Date 2024/7/16 01:04:18 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 ,Since 2012 + */ + +@Component +public class RedissonPasswordConfigurationCustomizer implements RedissonAutoConfigurationCustomizer { + @Override + public void customize(Config configuration) { + if (configuration.isSingleConfig() && SmartStringUtil.isEmpty(configuration.useSingleServer().getPassword())) { + configuration.useSingleServer().setPassword(null); + } + + if (configuration.isClusterConfig() && SmartStringUtil.isEmpty(configuration.useClusterServers().getPassword())) { + configuration.useClusterServers().setPassword(null); + } + if (configuration.isSentinelConfig() && SmartStringUtil.isEmpty(configuration.useSentinelServers().getPassword())) { + configuration.useSentinelServers().setPassword(null); + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedissonService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedissonService.java new file mode 100644 index 0000000..aaab74a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/redis/RedissonService.java @@ -0,0 +1,139 @@ +package net.lab1024.sa.base.module.support.redis; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.exception.BusinessException; +import org.redisson.api.RBucket; +import org.redisson.api.RIdGenerator; +import org.redisson.api.RLock; +import org.redisson.api.RedissonClient; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.Duration; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +/** + * Redisson 业务 + * + * @author huke + * @date 2024/6/19 20:39 + */ +@Slf4j +@Service +public class RedissonService { + + @Autowired + private final RedissonClient redissonClient; + + public RedissonService(RedissonClient redissonClient) { + this.redissonClient = redissonClient; + } + + public RedissonClient getRedissonClient() { + return redissonClient; + } + + /** + * 获取锁 并 执行程序 + * + * @param lockKey + * @param waitTime 毫秒 + * @param lockTime 毫秒 + * @param supplier + */ + public T executeWithLock(String lockKey, long waitTime, long lockTime, Supplier supplier) { + // 获取锁 + RLock lock = this.tryLock(lockKey, waitTime, lockTime); + try { + return supplier.get(); + } finally { + // 释放锁 + if (lock.isHeldByCurrentThread()) { + lock.unlock(); + } + } + } + + /** + * 获取锁 并 执行程序 + * + * @param lockKey + * @param waitTime 毫秒 + * @param lockTime 毫秒 + * @param runnable + */ + public void executeWithLock(String lockKey, long waitTime, long lockTime, Runnable runnable) { + // 获取锁 + RLock lock = this.tryLock(lockKey, waitTime, lockTime); + try { + runnable.run(); + } finally { + // 释放锁 + if (lock.isHeldByCurrentThread()) { + lock.unlock(); + } + } + } + + /** + * 尝试获取锁 + * 最多等待 waitTime 毫秒 + * 获取锁成功后占用 lockTime 毫秒 + * ps:需要手动解锁 lock.unlock() + * + * @param lockKey + * @param waitTime 毫秒 + * @param lockTime 毫秒 + * @return + */ + public RLock tryLock(String lockKey, long waitTime, long lockTime) { + RLock lock = redissonClient.getLock(lockKey); + try { + boolean getLock = lock.tryLock(waitTime, lockTime, TimeUnit.MILLISECONDS); + if (getLock) { + return lock; + } + } catch (InterruptedException e) { + log.error("Redisson tryLock", e); + } + throw new BusinessException("业务繁忙,请稍后重试~"); + } + + /** + * 获取 id 生成器 + * nextId 可生成连续不重复的id + * + * @param key + * @return + */ + public RIdGenerator idGenerator(String key) { + return redissonClient.getIdGenerator(key); + } + + /** + * 存放任意数据类型 + * + * @param key + * @param v + * @param duration + * @param + */ + public void putObj(String key, T v, Duration duration) { + redissonClient.getBucket(key).set(v, duration); + } + + /** + * 获取任意数据类型 + * + * @param key + * @param clazz + * @param + * @return 如果没有找到则返回null + */ + public T getObj(String key, Class clazz) { + RBucket bucket = redissonClient.getBucket(key); + return bucket.get(); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/ReloadCommand.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/ReloadCommand.java new file mode 100644 index 0000000..e848b05 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/ReloadCommand.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.module.support.reload; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.module.support.reload.core.AbstractSmartReloadCommand; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadItem; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadResult; +import net.lab1024.sa.base.module.support.reload.dao.ReloadItemDao; +import net.lab1024.sa.base.module.support.reload.dao.ReloadResultDao; +import net.lab1024.sa.base.module.support.reload.domain.ReloadItemEntity; +import net.lab1024.sa.base.module.support.reload.domain.ReloadResultEntity; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * reload 操作 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Component +public class ReloadCommand extends AbstractSmartReloadCommand { + + @Resource + private ReloadItemDao reloadItemDao; + + @Resource + private ReloadResultDao reloadResultDao; + + /** + * 读取数据库中SmartReload项 + * + * @return List + */ + @Override + public List readReloadItem() { + List reloadItemEntityList = reloadItemDao.selectList(null); + return SmartBeanUtil.copyList(reloadItemEntityList, SmartReloadItem.class); + } + + + /** + * 保存reload结果 + * + * @param smartReloadResult + */ + @Override + public void handleReloadResult(SmartReloadResult smartReloadResult) { + ReloadResultEntity reloadResultEntity = SmartBeanUtil.copy(smartReloadResult, ReloadResultEntity.class); + reloadResultDao.insert(reloadResultEntity); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/ReloadService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/ReloadService.java new file mode 100644 index 0000000..98b8ae3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/ReloadService.java @@ -0,0 +1,68 @@ +package net.lab1024.sa.base.module.support.reload; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.module.support.reload.dao.ReloadItemDao; +import net.lab1024.sa.base.module.support.reload.dao.ReloadResultDao; +import net.lab1024.sa.base.module.support.reload.domain.ReloadForm; +import net.lab1024.sa.base.module.support.reload.domain.ReloadItemEntity; +import net.lab1024.sa.base.module.support.reload.domain.ReloadItemVO; +import net.lab1024.sa.base.module.support.reload.domain.ReloadResultVO; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * reload (内存热加载、钩子等) + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Service +public class ReloadService { + + @Resource + private ReloadItemDao reloadItemDao; + + @Resource + private ReloadResultDao reloadResultDao; + + /** + * 查询 + * + * @return + */ + public ResponseDTO> query() { + List list = reloadItemDao.query(); + return ResponseDTO.ok(list); + } + + public ResponseDTO> queryReloadItemResult(String tag) { + List reloadResultList = reloadResultDao.query(tag); + return ResponseDTO.ok(reloadResultList); + } + + + /** + * 通过标签更新标识符 + * + * @param reloadForm + * @return + */ + public ResponseDTO updateByTag(ReloadForm reloadForm) { + ReloadItemEntity reloadItemEntity = reloadItemDao.selectById(reloadForm.getTag()); + if (null == reloadItemEntity) { + return ResponseDTO.error(UserErrorCode.DATA_NOT_EXIST); + } + reloadItemEntity.setIdentification(reloadForm.getIdentification()); + reloadItemEntity.setUpdateTime(LocalDateTime.now()); + reloadItemEntity.setArgs(reloadForm.getArgs()); + reloadItemDao.updateById(reloadItemEntity); + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/AbstractSmartReloadCommand.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/AbstractSmartReloadCommand.java new file mode 100644 index 0000000..a19aa06 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/AbstractSmartReloadCommand.java @@ -0,0 +1,96 @@ +package net.lab1024.sa.base.module.support.reload.core; + + +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadItem; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadObject; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadResult; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 检测是否 Reload 的类 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +public abstract class AbstractSmartReloadCommand { + + /** + * 当前ReloadItem的存储器 + */ + private ConcurrentHashMap tagIdentifierMap = new ConcurrentHashMap<>(); + + private SmartReloadManager smartReloadManager; + + /** + * @return + */ + public void setReloadManager(SmartReloadManager smartReloadManager) { + this.smartReloadManager = smartReloadManager; + } + + public void init() { + List smartReloadItems = this.readReloadItem(); + if (smartReloadItems != null) { + for (SmartReloadItem smartReloadItem : smartReloadItems) { + tagIdentifierMap.put(smartReloadItem.getTag(), smartReloadItem.getIdentification()); + } + } + } + + + /** + * 该方法返回一个List:
+ * ReloadItem对象的tagIdentify为:该tag的 状态(状态其实就是个字符串,如果该字符串跟上次有变化则进行reload操作)
+ * ReloadItem对象的args为: reload操作需要的参数

+ * + * @return List + */ + public abstract List readReloadItem(); + + /** + * 处理Reload结果 + * + * @param smartReloadResult + */ + public abstract void handleReloadResult(SmartReloadResult smartReloadResult); + + + /** + * 获取本地缓存tag标识 + * + * @return + */ + public ConcurrentHashMap getTagIdentifierMap() { + return tagIdentifierMap; + } + + /** + * 设置新的缓存标识 + * + * @param tag + * @param identification + */ + public void putIdentifierMap(String tag, String identification) { + tagIdentifierMap.put(tag, identification); + } + + + /** + * 获取重载对象 + * + * @return + */ + public SmartReloadObject reloadObject(String tag) { + if (this.smartReloadManager == null) { + return null; + } + Map reloadObjectMap = smartReloadManager.reloadObjectMap(); + return reloadObjectMap.get(tag); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/SmartReloadManager.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/SmartReloadManager.java new file mode 100644 index 0000000..98773e1 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/SmartReloadManager.java @@ -0,0 +1,124 @@ +package net.lab1024.sa.base.module.support.reload.core; + + +import jakarta.annotation.PostConstruct; +import jakarta.annotation.PreDestroy; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.reload.core.annoation.SmartReload; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadObject; +import net.lab1024.sa.base.module.support.reload.core.thread.SmartReloadRunnable; +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.stereotype.Service; +import org.springframework.util.ReflectionUtils; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ScheduledThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +/** + * SmartReloadManager 管理器 + *

+ * 可以在此类中添加 检测任务 以及注册 处理程序 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Slf4j +@Service +public class SmartReloadManager implements BeanPostProcessor { + + private static final String THREAD_NAME_PREFIX = "smart-reload"; + private static final int THREAD_COUNT = 1; + + @Value("${reload.interval-seconds}") + private Integer intervalSeconds; + + @Resource + private AbstractSmartReloadCommand reloadCommand; + + private final Map reloadObjectMap = new ConcurrentHashMap<>(); + + private ScheduledThreadPoolExecutor threadPoolExecutor; + + + @PostConstruct + public void init() { + if (threadPoolExecutor != null) { + return; + } + + this.threadPoolExecutor = new ScheduledThreadPoolExecutor(THREAD_COUNT, r -> { + Thread t = new Thread(r, THREAD_NAME_PREFIX); + if (!t.isDaemon()) { + t.setDaemon(true); + } + return t; + }); + this.threadPoolExecutor.scheduleWithFixedDelay(new SmartReloadRunnable(this.reloadCommand), 10, this.intervalSeconds, TimeUnit.SECONDS); + this.reloadCommand.setReloadManager(this); + } + + + @PreDestroy + public void shutdown() { + if (this.threadPoolExecutor != null) { + this.threadPoolExecutor.shutdownNow(); + this.threadPoolExecutor = null; + } + } + + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { + Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass()); + for (Method method : methods) { + SmartReload smartReload = method.getAnnotation(SmartReload.class); + if (smartReload == null) { + continue; + } + int paramCount = method.getParameterCount(); + if (paramCount > 1) { + log.error("<> register tag reload : " + smartReload.value() + " , param count cannot greater than one !"); + continue; + } + String reloadTag = smartReload.value(); + this.register(reloadTag, new SmartReloadObject(bean, method)); + } + return bean; + } + + /** + * 注册reload + * + * @param tag + * @param smartReloadObject + */ + private void register(String tag, SmartReloadObject smartReloadObject) { + if (reloadObjectMap.containsKey(tag)) { + log.error("<> register duplicated tag reload : " + tag + " , and it will be cover!"); + } + reloadObjectMap.put(tag, smartReloadObject); + } + + /** + * 获取重载对象 + * + * @return + */ + public Map reloadObjectMap() { + return this.reloadObjectMap; + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/annoation/SmartReload.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/annoation/SmartReload.java new file mode 100644 index 0000000..0dc3f5b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/annoation/SmartReload.java @@ -0,0 +1,22 @@ +package net.lab1024.sa.base.module.support.reload.core.annoation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 定义 SmartReload 注解 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) +public @interface SmartReload { + + String value(); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadItem.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadItem.java new file mode 100644 index 0000000..19dc6be --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadItem.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.base.module.support.reload.core.domain; + +import lombok.Data; + +/** + * reload项目 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class SmartReloadItem { + + /** + * 项名称 + */ + private String tag; + + /** + * 参数 + */ + private String args; + + /** + * 标识 + */ + private String identification; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadObject.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadObject.java new file mode 100644 index 0000000..c05efd2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadObject.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.base.module.support.reload.core.domain; + +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.lang.reflect.Method; + +/** + * Reload 处理程序的实现方法,用于包装以注解 SmartReload 实现的处理类 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@AllArgsConstructor +public class SmartReloadObject { + + /** + * 方法对应的实例化对象 + */ + private Object reloadObject; + + /** + * 重新加载执行的方法 + */ + private Method method; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadResult.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadResult.java new file mode 100644 index 0000000..2a38c02 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/domain/SmartReloadResult.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.base.module.support.reload.core.domain; + +import lombok.Data; + +/** + * t_reload_result 表 实体类 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class SmartReloadResult { + + /** + * 项名称 + */ + private String tag; + + /** + * 参数 + */ + private String args; + + /** + * 标识 + */ + private String identification; + + /** + * 处理结果 + */ + private boolean result; + + /** + * 异常说明 + */ + private String exception; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/thread/SmartReloadRunnable.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/thread/SmartReloadRunnable.java new file mode 100644 index 0000000..88cb1a4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/core/thread/SmartReloadRunnable.java @@ -0,0 +1,121 @@ +package net.lab1024.sa.base.module.support.reload.core.thread; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.module.support.reload.core.AbstractSmartReloadCommand; +import net.lab1024.sa.base.module.support.reload.core.SmartReloadManager; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadItem; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadObject; +import net.lab1024.sa.base.module.support.reload.core.domain.SmartReloadResult; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.Method; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * reload 线程 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Slf4j +public class SmartReloadRunnable implements Runnable { + + private AbstractSmartReloadCommand abstractSmartReloadCommand; + + private boolean isInit = false; + + public SmartReloadRunnable(AbstractSmartReloadCommand abstractSmartReloadCommand) { + this.abstractSmartReloadCommand = abstractSmartReloadCommand; + } + + @Override + public void run() { + try { + this.doTask(); + } catch (Throwable e) { + log.error("", e); + } + } + + /** + * 检测Identifier变化,执行reload + */ + private void doTask() { + if (!isInit) { + this.abstractSmartReloadCommand.init(); + isInit = true; + return; + } + + List smartReloadItemList = this.abstractSmartReloadCommand.readReloadItem(); + ConcurrentHashMap tagIdentifierMap = this.abstractSmartReloadCommand.getTagIdentifierMap(); + for (SmartReloadItem smartReloadItem : smartReloadItemList) { + String tag = smartReloadItem.getTag(); + String tagIdentifier = smartReloadItem.getIdentification(); + String preTagChangeIdentifier = tagIdentifierMap.get(tag); + // 数据不一致 + if (preTagChangeIdentifier == null || !preTagChangeIdentifier.equals(tagIdentifier)) { + this.abstractSmartReloadCommand.putIdentifierMap(tag, tagIdentifier); + // 执行重新加载此项的动作 + SmartReloadResult smartReloadResult = this.doReload(smartReloadItem); + this.abstractSmartReloadCommand.handleReloadResult(smartReloadResult); + } + } + } + + /** + * 方法调用 + * + * @param smartReloadItem + * @return + */ + private SmartReloadResult doReload(SmartReloadItem smartReloadItem) { + SmartReloadResult result = new SmartReloadResult(); + SmartReloadObject smartReloadObject = this.abstractSmartReloadCommand.reloadObject(smartReloadItem.getTag()); + try { + if (smartReloadObject == null) { + result.setResult(false); + result.setException("不能从系统中找到对应的tag:" + smartReloadItem.getTag()); + return result; + } + + Method method = smartReloadObject.getMethod(); + if (method == null) { + result.setResult(false); + result.setException("reload方法不存在"); + return result; + } + + result.setTag(smartReloadItem.getTag()); + result.setArgs(smartReloadItem.getArgs()); + result.setIdentification(smartReloadItem.getIdentification()); + result.setResult(true); + int paramCount = method.getParameterCount(); + if (paramCount > 1) { + result.setResult(false); + result.setException("reload方法" + method.getName() + "参数太多"); + return result; + } + + if (paramCount == 0) { + method.invoke(smartReloadObject.getReloadObject()); + } else { + method.invoke(smartReloadObject.getReloadObject(), smartReloadItem.getArgs()); + } + } catch (Throwable throwable) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + throwable.printStackTrace(pw); + + result.setResult(false); + result.setException(throwable.toString()); + } + return result; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/dao/ReloadItemDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/dao/ReloadItemDao.java new file mode 100644 index 0000000..30fe8f8 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/dao/ReloadItemDao.java @@ -0,0 +1,24 @@ +package net.lab1024.sa.base.module.support.reload.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.reload.domain.ReloadItemEntity; +import net.lab1024.sa.base.module.support.reload.domain.ReloadItemVO; +import org.apache.ibatis.annotations.Mapper; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * t_reload_item 数据表dao + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Mapper +public interface ReloadItemDao extends BaseMapper { + + List query(); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/dao/ReloadResultDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/dao/ReloadResultDao.java new file mode 100644 index 0000000..93cb07a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/dao/ReloadResultDao.java @@ -0,0 +1,25 @@ +package net.lab1024.sa.base.module.support.reload.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.reload.domain.ReloadResultEntity; +import net.lab1024.sa.base.module.support.reload.domain.ReloadResultVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * t_reload_result 数据表dao + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Mapper +public interface ReloadResultDao extends BaseMapper { + + List query(@Param("tag") String tag); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadForm.java new file mode 100644 index 0000000..c704fc2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadForm.java @@ -0,0 +1,30 @@ +package net.lab1024.sa.base.module.support.reload.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import lombok.Data; + +/** + * reload (内存热加载、钩子等) + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class ReloadForm { + + @Schema(description = "标签") + @NotBlank(message = "标签不能为空") + private String tag; + + @Schema(description = "状态标识") + @NotBlank(message = "状态标识不能为空") + private String identification; + + @Schema(description = "参数") + private String args; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadItemEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadItemEntity.java new file mode 100644 index 0000000..9c24af9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadItemEntity.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.module.support.reload.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * t_reload_item 数据表 实体类 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@TableName("t_reload_item") +public class ReloadItemEntity { + + /** + * 加载项标签 + */ + @TableId(type = IdType.INPUT) + private String tag; + + /** + * 参数 + */ + private String args; + + /** + * 运行标识 + */ + private String identification; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadItemVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadItemVO.java new file mode 100644 index 0000000..a9c81e4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadItemVO.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.module.support.reload.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * reload (内存热加载、钩子等) + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class ReloadItemVO { + + @Schema(description = "加载项标签") + private String tag; + + @Schema(description = "参数") + private String args; + + @Schema(description = "运行标识") + private String identification; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadResultEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadResultEntity.java new file mode 100644 index 0000000..7516e6c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadResultEntity.java @@ -0,0 +1,56 @@ +package net.lab1024.sa.base.module.support.reload.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * reload结果
+ * t_reload_result 数据表 实体类 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@TableName("t_reload_result") +public class ReloadResultEntity { + + /** + * 加载项标签 + */ + @TableId(type= IdType.NONE) + private String tag; + + /** + * 运行标识 + */ + private String identification; + + /** + * 参数 + */ + private String args; + + /** + * 运行结果 + */ + private Boolean result; + + /** + * 异常 + */ + private String exception; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadResultVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadResultVO.java new file mode 100644 index 0000000..da63994 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/reload/domain/ReloadResultVO.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.reload.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * reload结果 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2015-03-02 19:11:52 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class ReloadResultVO { + + @Schema(description = "加载项标签") + private String tag; + + @Schema(description = "参数") + private String args; + + @Schema(description = "运行结果") + private Boolean result; + + @Schema(description = "异常") + private String exception; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/RepeatSubmitAspect.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/RepeatSubmitAspect.java new file mode 100644 index 0000000..723ecd7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/RepeatSubmitAspect.java @@ -0,0 +1,78 @@ +package net.lab1024.sa.base.module.support.repeatsubmit; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; +import net.lab1024.sa.base.module.support.repeatsubmit.ticket.AbstractRepeatSubmitTicket; +import org.apache.commons.lang3.StringUtils; +import org.aspectj.lang.ProceedingJoinPoint; +import org.aspectj.lang.annotation.Around; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; + +import java.lang.reflect.Method; + +/** + * 重复提交 aop切口 + * + * @Author 1024创新实验室: 胡克 + * @Date 2020-11-25 20:56:58 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Aspect +@Slf4j +public class RepeatSubmitAspect { + + private final AbstractRepeatSubmitTicket repeatSubmitTicket; + + /** + * 获取凭证信息 + */ + public RepeatSubmitAspect(AbstractRepeatSubmitTicket repeatSubmitTicket) { + this.repeatSubmitTicket = repeatSubmitTicket; + } + + /** + * 定义切入点 + */ + @Around("@annotation(net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit)") + public Object around(ProceedingJoinPoint point) throws Throwable { + + ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); + String ticketToken = attributes.getRequest().getServletPath(); + String ticket = this.repeatSubmitTicket.getTicket(ticketToken); + if (StringUtils.isEmpty(ticket)) { + return point.proceed(); + } + + Method method = ((MethodSignature) point.getSignature()).getMethod(); + RepeatSubmit annotation = method.getAnnotation(RepeatSubmit.class); + int limit = annotation.value(); + + // 获取上一次请求时间 + Long lastRequestTime = this.repeatSubmitTicket.getTicketTimestamp(ticket); + // 校验是否限制时间内重复提交 + if (lastRequestTime != null && System.currentTimeMillis() < lastRequestTime + limit) { + return ResponseDTO.error(UserErrorCode.REPEAT_SUBMIT); + } + + // 执行 + Object obj = null; + try { + // 给 ticket 设置在执行中 + this.repeatSubmitTicket.putTicket(ticket); + // 执行 + obj = point.proceed(); + } catch (Throwable throwable) { + log.error("", throwable); + throw throwable; + } + return obj; + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/annoation/RepeatSubmit.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/annoation/RepeatSubmit.java new file mode 100644 index 0000000..7469ba6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/annoation/RepeatSubmit.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.repeatsubmit.annoation; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * 标记 需要防止重复提交 的注解
+ * 单位:毫秒 + * + * @Author 1024创新实验室: 胡克 + * @Date 2020-11-25 20:56:58 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface RepeatSubmit { + + /** + * 重复提交间隔时间/毫秒 + */ + int value() default 300; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/AbstractRepeatSubmitTicket.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/AbstractRepeatSubmitTicket.java new file mode 100644 index 0000000..bc2f8e6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/AbstractRepeatSubmitTicket.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.module.support.repeatsubmit.ticket; + +import java.util.function.Function; + +/** + * 凭证(用于校验重复提交的东西) + * + * @Author 1024创新实验室: 罗伊 + * @Date 2020-11-25 20:56:58 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +public abstract class AbstractRepeatSubmitTicket { + + private final Function ticketFunction; + + + public AbstractRepeatSubmitTicket(Function ticketFunction) { + this.ticketFunction = ticketFunction; + } + + + /** + * 获取凭证 + */ + public String getTicket(String ticketToken) { + return this.ticketFunction.apply(ticketToken); + } + + /** + * 获取凭证 时间戳 + */ + public abstract Long getTicketTimestamp(String ticket); + + + /** + * 设置本次请求时间 + */ + public abstract void putTicket(String ticket); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/RepeatSubmitCaffeineTicket.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/RepeatSubmitCaffeineTicket.java new file mode 100644 index 0000000..a2070a3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/RepeatSubmitCaffeineTicket.java @@ -0,0 +1,45 @@ +package net.lab1024.sa.base.module.support.repeatsubmit.ticket; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; + +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +/** + * 凭证(内存实现) + * + * @Author 1024创新实验室: 罗伊 + * @Date 2020-11-25 20:56:58 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +public class RepeatSubmitCaffeineTicket extends AbstractRepeatSubmitTicket { + + /** + * 限制缓存最大数量 超过后先放入的会自动移除 + * 默认缓存时间 + * 初始大小为:100万 + */ + private static final Cache cache = Caffeine.newBuilder() + .maximumSize(100 * 10000) + .expireAfterWrite(300 * 1000L, TimeUnit.MILLISECONDS).build(); + + + public RepeatSubmitCaffeineTicket(Function ticketFunction) { + super(ticketFunction); + } + + @Override + public Long getTicketTimestamp(String ticket) { + return cache.getIfPresent(ticket); + } + + + @Override + public void putTicket(String ticket) { + cache.put(ticket, System.currentTimeMillis()); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/RepeatSubmitRedisTicket.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/RepeatSubmitRedisTicket.java new file mode 100644 index 0000000..cb1404d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/repeatsubmit/ticket/RepeatSubmitRedisTicket.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.module.support.repeatsubmit.ticket; + +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; +import org.springframework.data.redis.core.ValueOperations; + +import java.util.concurrent.TimeUnit; +import java.util.function.Function; + +/** + * 凭证(redis实现) + * + * @Author 1024创新实验室: 罗伊 + * @Date 2020-11-25 20:56:58 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +public class RepeatSubmitRedisTicket extends AbstractRepeatSubmitTicket { + + private final ValueOperations redisValueOperations; + + public RepeatSubmitRedisTicket(ValueOperations redisValueOperations, + Function ticketFunction) { + super(ticketFunction); + this.redisValueOperations = redisValueOperations; + } + + @Override + public Long getTicketTimestamp(String ticket) { + String ticketLastTime = redisValueOperations.get(ticket); + return ticketLastTime == null ? null : Long.valueOf(ticketLastTime); + } + + @Override + public void putTicket(String ticket) { + redisValueOperations.getOperations().delete(ticket); + this.getTicketTimestamp(ticket); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/dao/LoginFailDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/dao/LoginFailDao.java new file mode 100644 index 0000000..587dd43 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/dao/LoginFailDao.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.base.module.support.securityprotect.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailEntity; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailQueryForm; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailVO; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 登录失败 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022/07/22 19:46:23 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Mapper +public interface LoginFailDao extends BaseMapper { + + /** + * 根据用户id和类型查询 + * + * @param userId + * @param userType + * @return + */ + LoginFailEntity selectByUserIdAndUserType(@Param("userId") Long userId, @Param("userType") Integer userType); + + /** + * 根据用户id和类型查询 进行删除 + * + * @param userId + * @param userType + * @return + */ + void deleteByUserIdAndUserType(@Param("userId") Long userId, @Param("userType") Integer userType); + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List queryPage(Page page, @Param("queryForm") LoginFailQueryForm queryForm); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/dao/PasswordLogDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/dao/PasswordLogDao.java new file mode 100644 index 0000000..77dae29 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/dao/PasswordLogDao.java @@ -0,0 +1,33 @@ +package net.lab1024.sa.base.module.support.securityprotect.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.securityprotect.domain.PasswordLogEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.util.List; + +@Mapper +public interface PasswordLogDao extends BaseMapper { + + /** + * 查询最后一次修改密码记录 + * + * @param userType + * @param userId + * @return + */ + PasswordLogEntity selectLastByUserTypeAndUserId(@Param("userType") Integer userType, @Param("userId") Long userId); + + + /** + * 查询最近几次修改后的密码 + * + * @param userType + * @param userId + * @return + */ + List selectOldPassword(@Param("userType") Integer userType, @Param("userId") Long userId, @Param("limit") int limit); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/Level3ProtectConfigForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/Level3ProtectConfigForm.java new file mode 100644 index 0000000..8333493 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/Level3ProtectConfigForm.java @@ -0,0 +1,57 @@ +package net.lab1024.sa.base.module.support.securityprotect.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 三级等保相关配置 + * + * @Author 1024创新实验室-创始人兼主任:卓大 + * @Date 2024/7/30 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 ,Since 2012 + */ + +@Data +public class Level3ProtectConfigForm { + + @Schema(description = "连续登录失败次数则锁定") + @NotNull(message = "连续登录失败次数则锁定 不能为空") + private Integer loginFailMaxTimes; + + @Schema(description = "连续登录失败锁定时间(单位:分钟)") + @NotNull(message = "连续登录失败锁定时间(单位:分钟) 不能为空") + private Integer loginFailLockMinutes; + + @Schema(description = "最低活跃时间(单位:分钟)") + @NotNull(message = "最低活跃时间(单位:分钟) 不能为空") + private Integer loginActiveTimeoutMinutes; + + @Schema(description = "开启双因子登录") + @NotNull(message = "开启双因子登录 不能为空") + private Boolean twoFactorLoginEnabled; + + @Schema(description = "密码复杂度 是否开启,默认:开启") + @NotNull(message = "密码复杂度 是否开启 不能为空") + private Boolean passwordComplexityEnabled; + + @Schema(description = "定期修改密码时间间隔(默认:月)") + @NotNull(message = "定期修改密码时间间隔(默认:月) 不能为空") + private Integer regularChangePasswordMonths; + + @Schema(description = "定期修改密码不允许重复次数,默认:3次以内密码不能相同(默认:次)") + @NotNull(message = "定期修改密码不允许重复次数 不能为空") + private Integer regularChangePasswordNotAllowRepeatTimes; + + @Schema(description = "文件检测,默认:不开启") + @NotNull(message = "文件检测 是否开启 不能为空") + private Boolean fileDetectFlag; + + @Schema(description = "文件大小限制,单位 mb ,(默认:50 mb)") + @NotNull(message = "文件大小限制 不能为空") + private Long maxUploadFileSizeMb; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailEntity.java new file mode 100644 index 0000000..f1219b4 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailEntity.java @@ -0,0 +1,66 @@ +package net.lab1024.sa.base.module.support.securityprotect.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Builder; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 登录失败记录 + * + * @Author 1024创新实验室-主任:卓大 + * @Date 2023/10/11 19:29:18 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室,Since 2012 + */ + +@Data +@Builder +@TableName("t_login_fail") +public class LoginFailEntity { + + + @TableId(type = IdType.AUTO) + private Long loginFailId; + + /** + * 用户id + */ + private Long userId; + + /** + * 用户类型 + */ + private Integer userType; + + /** + * 登录名 + */ + private String loginName; + + /** + * 锁定状态 + */ + private Boolean lockFlag; + + /** + * 登录失败次数 + */ + private Integer loginFailCount; + + /** + * 连续登录失败锁定开始时间 + */ + private LocalDateTime loginLockBeginTime; + + + private LocalDateTime updateTime; + + private LocalDateTime createTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailQueryForm.java new file mode 100644 index 0000000..41c048b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailQueryForm.java @@ -0,0 +1,32 @@ +package net.lab1024.sa.base.module.support.securityprotect.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +import java.time.LocalDate; + +/** + * 登录失败 分页查询表单 + * + * @Author 1024创新实验室-主任-卓大 + * @Date 2023-10-17 18:02:37 + * @Copyright 1024创新实验室 + */ + +@Data +public class LoginFailQueryForm extends PageParam { + + @Schema(description = "登录名") + private String loginName; + + @Schema(description = "锁定状态") + private Boolean lockFlag; + + @Schema(description = "登录失败锁定时间") + private LocalDate loginLockBeginTimeBegin; + + @Schema(description = "登录失败锁定时间") + private LocalDate loginLockBeginTimeEnd; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailVO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailVO.java new file mode 100644 index 0000000..317ee74 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/LoginFailVO.java @@ -0,0 +1,46 @@ +package net.lab1024.sa.base.module.support.securityprotect.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 登录失败 列表VO + * + * @Author 1024创新实验室-主任-卓大 + * @Date 2023-10-17 18:02:37 + * @Copyright 1024创新实验室 + */ + +@Data +public class LoginFailVO { + + private Long loginFailId; + + + @Schema(description = "用户id") + private Long userId; + + @Schema(description = "用户类型") + private Integer userType; + + @Schema(description = "登录名") + private String loginName; + + @Schema(description = "连续登录失败次数") + private Integer loginFailCount; + + @Schema(description = "锁定状态:1锁定,0未锁定") + private Integer lockFlag; + + @Schema(description = "连续登录失败锁定开始时间") + private LocalDateTime loginLockBeginTime; + + @Schema(description = "创建时间") + private LocalDateTime createTime; + + @Schema(description = "更新时间") + private LocalDateTime updateTime; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/PasswordLogEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/PasswordLogEntity.java new file mode 100644 index 0000000..93927dc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/domain/PasswordLogEntity.java @@ -0,0 +1,43 @@ +package net.lab1024.sa.base.module.support.securityprotect.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * @author yandy + * @description: + * @date 2024/7/15 1:39 下午 + */ +@Data +@TableName("t_password_log") +public class PasswordLogEntity { + + /** + * 主键id + */ + @TableId(type = IdType.AUTO) + private Long id; + + private Integer userType; + + private Long userId; + + private String oldPassword; + + private String newPassword; + + /** + * 更新时间 + */ + private LocalDateTime updateTime; + + /** + * 创建时间 + */ + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/Level3ProtectConfigService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/Level3ProtectConfigService.java new file mode 100644 index 0000000..00cb51e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/Level3ProtectConfigService.java @@ -0,0 +1,211 @@ +package net.lab1024.sa.base.module.support.securityprotect.service; + +import cn.dev33.satoken.stp.StpUtil; +import cn.hutool.core.util.StrUtil; +import com.alibaba.fastjson.JSON; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.module.support.config.ConfigKeyEnum; +import net.lab1024.sa.base.module.support.config.ConfigService; +import net.lab1024.sa.base.module.support.securityprotect.domain.Level3ProtectConfigForm; +import org.springframework.stereotype.Service; + +/** + * 三级等保配置 + * + * @Author 1024创新实验室-创始人兼主任:卓大 + * @Date 2024/7/30 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 ,Since 2012 + */ + +@Service +@Slf4j +public class Level3ProtectConfigService { + + /** + * 开启双因子登录,默认:开启 + */ + private boolean twoFactorLoginEnabled = false; + + /** + * 连续登录失败次数则锁定,-1表示不受限制,可以一直尝试登录 + */ + private int loginFailMaxTimes = -1; + + /** + * 连续登录失败锁定时间(单位:秒),-1表示不锁定,建议锁定30分钟 + */ + private int loginFailLockSeconds = 1800; + + /** + * 最低活跃时间(单位:秒),超过此时间没有操作系统就会被冻结,默认-1 代表不限制,永不冻结; 默认 30分钟 + */ + private int loginActiveTimeoutSeconds = -1; + + /** + * 密码复杂度 是否开启,默认:开启 + */ + private boolean passwordComplexityEnabled = true; + + /** + * 定期修改密码时间间隔(默认:天),默认:建议90天更换密码 + */ + private int regularChangePasswordDays = 90; + + /** + * 定期修改密码不允许相同次数,默认:3次以内密码不能相同 + */ + private int regularChangePasswordNotAllowRepeatTimes = 3; + + /** + * 文件大小限制,单位 mb ,(默认:50 mb) + */ + private long maxUploadFileSizeMb = 50; + + /** + * 文件检测,默认:不开启 + */ + private boolean fileDetectFlag = false; + + + @Resource + private ConfigService configService; + + /** + * 文件检测,默认:不开启 + */ + public boolean isFileDetectFlag() { + return fileDetectFlag; + } + + /** + * 文件大小限制,单位 mb ,(默认:50 mb) + */ + public long getMaxUploadFileSizeMb() { + return maxUploadFileSizeMb; + } + + /** + * 连续登录失败次数则锁定,-1表示不受限制,可以一直尝试登录 + */ + public int getLoginFailMaxTimes() { + return loginFailMaxTimes; + } + + /** + * 连续登录失败锁定时间(单位:秒),-1表示不锁定,建议锁定30分钟 + */ + public int getLoginFailLockSeconds() { + return loginFailLockSeconds; + } + + /** + * 最低活跃时间(单位:秒),超过此时间没有操作系统就会被冻结,默认-1 代表不限制,永不冻结; 默认 30分钟 + */ + public int getLoginActiveTimeoutSeconds() { + return loginActiveTimeoutSeconds > 0 ? loginActiveTimeoutSeconds : -1; + } + + /** + * 定期修改密码时间间隔(默认:天),默认:建议90天更换密码 + */ + public int getRegularChangePasswordDays() { + return regularChangePasswordDays; + } + + /** + * 开启双因子登录,默认:开启 + */ + public boolean isTwoFactorLoginEnabled() { + return twoFactorLoginEnabled; + } + + /** + * 密码复杂度 是否开启,默认:开启 + */ + public boolean isPasswordComplexityEnabled() { + return passwordComplexityEnabled; + } + + /** + * 定期修改密码不允许相同次数,默认:3次以内密码不能相同 + */ + public int getRegularChangePasswordNotAllowRepeatTimes() { + return regularChangePasswordNotAllowRepeatTimes; + } + + @PostConstruct + void init() { + String configValue = configService.getConfigValue(ConfigKeyEnum.LEVEL3_PROTECT_CONFIG); + if (StrUtil.isEmpty(configValue)) { + throw new ExceptionInInitializerError("t_config 表 三级等保配置为空,请进行配置!"); + } + Level3ProtectConfigForm level3ProtectConfigForm = JSON.parseObject(configValue, Level3ProtectConfigForm.class); + setProp(level3ProtectConfigForm); + } + + /** + * 设置属性 + */ + private void setProp(Level3ProtectConfigForm configForm) { + + if (configForm.getFileDetectFlag() != null) { + this.fileDetectFlag = configForm.getFileDetectFlag(); + } + + if (configForm.getMaxUploadFileSizeMb() != null) { + this.maxUploadFileSizeMb = configForm.getMaxUploadFileSizeMb(); + } + + if (configForm.getLoginFailMaxTimes() != null) { + this.loginFailMaxTimes = configForm.getLoginFailMaxTimes(); + } + + if (configForm.getLoginFailLockMinutes() != null) { + this.loginFailLockSeconds = configForm.getLoginFailLockMinutes() * 60; + } + + if (configForm.getLoginActiveTimeoutMinutes() != null) { + this.loginActiveTimeoutSeconds = configForm.getLoginActiveTimeoutMinutes() * 60; + this.loginActiveTimeoutSeconds = loginActiveTimeoutSeconds > 0 ? loginActiveTimeoutSeconds : -1; + } + + if (configForm.getPasswordComplexityEnabled() != null) { + this.passwordComplexityEnabled = configForm.getPasswordComplexityEnabled(); + } + + if (configForm.getRegularChangePasswordMonths() != null) { + this.regularChangePasswordDays = configForm.getRegularChangePasswordMonths() * 30; + } + + if (configForm.getTwoFactorLoginEnabled() != null) { + this.twoFactorLoginEnabled = configForm.getTwoFactorLoginEnabled(); + } + + if (configForm.getRegularChangePasswordNotAllowRepeatTimes() != null) { + this.regularChangePasswordNotAllowRepeatTimes = configForm.getRegularChangePasswordNotAllowRepeatTimes(); + } + + // 设置 最低活跃时间(单位:秒) + if (this.loginActiveTimeoutSeconds > 0) { + StpUtil.getStpLogic().getConfigOrGlobal().setActiveTimeout(getLoginActiveTimeoutSeconds()); + } else { + StpUtil.getStpLogic().getConfigOrGlobal().setActiveTimeout(-1); + } + } + + /** + * 更新三级等保配置 + */ + public ResponseDTO updateLevel3Config(Level3ProtectConfigForm configForm) { + // 设置属性 + setProp(configForm); + // 保存数据库 + String configFormJsonString = JSON.toJSONString(configForm, true); + return configService.updateValueByKey(ConfigKeyEnum.LEVEL3_PROTECT_CONFIG, configFormJsonString); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java new file mode 100644 index 0000000..9ecfd75 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityFileService.java @@ -0,0 +1,120 @@ +package net.lab1024.sa.base.module.support.securityprotect.service; + +import lombok.extern.slf4j.Slf4j; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import org.apache.tika.config.TikaConfig; +import org.apache.tika.exception.TikaException; +import org.apache.tika.io.TikaInputStream; +import org.apache.tika.metadata.Metadata; +import org.apache.tika.metadata.TikaCoreProperties; +import org.apache.tika.mime.MediaType; +import org.apache.tika.mime.MimeTypes; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; + +/** + * 三级等保 文件 相关 + * + * @Author 1024创新实验室-主任:卓大 + * @Date 2024/08/22 19:25:59 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室,Since 2012 + */ + +@Service +@Slf4j +public class SecurityFileService { + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + // 定义白名单MIME类型 + private static final List ALLOWED_MIME_TYPES = Arrays.asList( + "application/json", + "application/zip", + "application/x-7z-compressed", + "application/pdf", + "application/vnd.ms-excel", + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "application/vnd.ms-powerpoint", + "application/vnd.openxmlformats-officedocument.presentationml.presentation", + "application/msword", + "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + "application/vnd.ms-works", + "text/csv", + "audio/*", + "video/*", + // 图片类型 svg有安全隐患,所以不使用"image/*" + "image/jpeg", + "image/png", + "image/gif", + "image/bmp" + ); + + /** + * 检测文件安全类型 + */ + public ResponseDTO checkFile(MultipartFile file) { + + // 检验文件大小 + if (level3ProtectConfigService.getMaxUploadFileSizeMb() > 0) { + long maxSize = level3ProtectConfigService.getMaxUploadFileSizeMb() * 1024 * 1024; + if (file.getSize() > maxSize) { + return ResponseDTO.userErrorParam("上传文件最大为:" + level3ProtectConfigService.getMaxUploadFileSizeMb() + " mb"); + } + } + + // 文件类型安全检测 + if (level3ProtectConfigService.isFileDetectFlag()) { + String fileType = getFileMimeType(file); + if (ALLOWED_MIME_TYPES.stream() + .noneMatch(allowedType -> matchesMimeType(fileType, allowedType))) { + return ResponseDTO.userErrorParam("禁止上传此文件类型"); + } + } + + return ResponseDTO.ok(); + } + + /** + * 获取文件的 MIME 类型 + * + * @param file 要检查的文件 + * @return 文件的 MIME 类型 + */ + public static String getFileMimeType(MultipartFile file) { + try { + TikaConfig tika = new TikaConfig(); + Metadata metadata = new Metadata(); + metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, file.getOriginalFilename()); + TikaInputStream stream = TikaInputStream.get(file.getInputStream()); + MediaType mimetype = tika.getDetector().detect(stream, metadata); + return mimetype.toString(); + } catch (IOException | TikaException e) { + log.error(e.getMessage(), e); + return MimeTypes.OCTET_STREAM; + } + } + + /** + * 检查文件的 MIME 类型是否与指定的MIME 类型匹配(支持通配符) + * + * @param fileType 文件的 MIME 类型 + * @param mimetype MIME 类型(支持通配符) + * @return 是否匹配 + */ + private static boolean matchesMimeType(String fileType, String mimetype) { + if (mimetype.endsWith("/*")) { + String prefix = mimetype.substring(0, mimetype.length() - 1); + return fileType.startsWith(prefix); + } else { + return fileType.equalsIgnoreCase(mimetype); + } + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityLoginService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityLoginService.java new file mode 100644 index 0000000..c51eb0c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityLoginService.java @@ -0,0 +1,175 @@ +package net.lab1024.sa.base.module.support.securityprotect.service; + +import cn.hutool.core.date.LocalDateTimeUtil; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.code.UserErrorCode; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.enumeration.UserTypeEnum; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.securityprotect.dao.LoginFailDao; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailEntity; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailQueryForm; +import net.lab1024.sa.base.module.support.securityprotect.domain.LoginFailVO; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 三级等保 登录 相关 + * + * @Author 1024创新实验室-主任:卓大 + * @Date 2023/10/11 19:25:59 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室,Since 2012 + */ + +@Service +public class SecurityLoginService { + + private static final String LOGIN_LOCK_MSG = "您已连续登录失败%s次,账号锁定%s分钟,解锁时间为:%s,请您耐心等待!"; + + private static final String LOGIN_FAIL_MSG = "登录名或密码错误!连续登录失败%s次,账号将锁定%s分钟!您还可以再尝试%s次!"; + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + @Resource + private LoginFailDao loginFailDao; + + + /** + * 检查是否可以登录 + * + * @param userId + * @param userType + * @return + */ + public ResponseDTO checkLogin(Long userId, UserTypeEnum userType) { + + // 若登录最大失败次数小于1,无需校验 + if (level3ProtectConfigService.getLoginFailMaxTimes() < 1) { + return ResponseDTO.ok(); + } + + + LoginFailEntity loginFailEntity = loginFailDao.selectByUserIdAndUserType(userId, userType.getValue()); + if (loginFailEntity == null) { + return ResponseDTO.ok(); + } + + // 校验登录失败次数 + if (loginFailEntity.getLoginFailCount() < level3ProtectConfigService.getLoginFailMaxTimes()) { + return ResponseDTO.ok(loginFailEntity); + } + + // 校验是否锁定 + if (loginFailEntity.getLoginLockBeginTime() == null) { + return ResponseDTO.ok(loginFailEntity); + } + + // 校验锁定时长 + if (loginFailEntity.getLoginLockBeginTime().plusSeconds(level3ProtectConfigService.getLoginFailLockSeconds()).isBefore(LocalDateTime.now())) { + // 过了锁定时间 + return ResponseDTO.ok(loginFailEntity); + } + + LocalDateTime unlockTime = loginFailEntity.getLoginLockBeginTime().plusSeconds(level3ProtectConfigService.getLoginFailLockSeconds()); + return ResponseDTO.error(UserErrorCode.LOGIN_FAIL_LOCK, String.format(LOGIN_LOCK_MSG, loginFailEntity.getLoginFailCount(), level3ProtectConfigService.getLoginFailLockSeconds() / 60, LocalDateTimeUtil.formatNormal(unlockTime))); + } + + /** + * 登录失败后记录 + * + * @param userId + * @param userType + * @param loginFailEntity + */ + public String recordLoginFail(Long userId, UserTypeEnum userType, String loginName, LoginFailEntity loginFailEntity) { + + // 若登录最大失败次数小于1,无需记录 + if (level3ProtectConfigService.getLoginFailMaxTimes() < 1) { + return null; + } + + // 登录失败 + int loginFailCount = loginFailEntity == null ? 1 : loginFailEntity.getLoginFailCount() + 1; + boolean lockFlag = loginFailCount >= level3ProtectConfigService.getLoginFailMaxTimes(); + LocalDateTime lockBeginTime = lockFlag ? LocalDateTime.now() : null; + + if (loginFailEntity == null) { + loginFailEntity = LoginFailEntity.builder() + .userId(userId) + .userType(userType.getValue()) + .loginName(loginName) + .loginFailCount(loginFailCount) + .lockFlag(lockFlag) + .loginLockBeginTime(lockBeginTime) + .build(); + loginFailDao.insert(loginFailEntity); + } else { + loginFailEntity.setLoginLockBeginTime(lockBeginTime); + loginFailEntity.setLoginFailCount(loginFailCount); + loginFailEntity.setLockFlag(lockFlag); + loginFailEntity.setLoginName(loginName); + loginFailDao.updateById(loginFailEntity); + } + + // 提示信息 + if (lockFlag) { + LocalDateTime unlockTime = loginFailEntity.getLoginLockBeginTime().plusSeconds(level3ProtectConfigService.getLoginFailLockSeconds()); + return String.format(LOGIN_LOCK_MSG, loginFailEntity.getLoginFailCount(), level3ProtectConfigService.getLoginFailLockSeconds() / 60, LocalDateTimeUtil.formatNormal(unlockTime)); + } else { + return String.format(LOGIN_FAIL_MSG, level3ProtectConfigService.getLoginFailMaxTimes(), level3ProtectConfigService.getLoginFailLockSeconds() / 60, level3ProtectConfigService.getLoginFailMaxTimes() - loginFailEntity.getLoginFailCount()); + } + } + + /** + * 清除登录失败 + * + * @param userId + * @param userType + */ + public void removeLoginFail(Long userId, UserTypeEnum userType) { + + // 若登录最大失败次数小于1,无需校验 + if (level3ProtectConfigService.getLoginFailMaxTimes() < 1) { + return; + } + + loginFailDao.deleteByUserIdAndUserType(userId, userType.getValue()); + } + + /** + * 分页查询 + * + * @param queryForm + * @return + */ + public PageResult queryPage(LoginFailQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List list = loginFailDao.queryPage(page, queryForm); + return SmartPageUtil.convert2PageResult(page, list); + } + + /** + * 批量删除 + * + * @param idList + * @return + */ + public ResponseDTO batchDelete(List idList) { + if (CollectionUtils.isEmpty(idList)) { + return ResponseDTO.ok(); + } + + loginFailDao.deleteBatchIds(idList); + return ResponseDTO.ok(); + } + +} +; \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityPasswordService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityPasswordService.java new file mode 100644 index 0000000..3cd8305 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/securityprotect/service/SecurityPasswordService.java @@ -0,0 +1,157 @@ +package net.lab1024.sa.base.module.support.securityprotect.service; + +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartStringUtil; +import net.lab1024.sa.base.module.support.securityprotect.dao.PasswordLogDao; +import net.lab1024.sa.base.module.support.securityprotect.domain.PasswordLogEntity; +import org.apache.commons.codec.digest.DigestUtils; +import org.apache.commons.lang3.RandomStringUtils; +import org.springframework.security.crypto.argon2.Argon2PasswordEncoder; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; + +/** + * 三级等保 密码 相关 + * + * @Author 1024创新实验室-主任:卓大 + * @Date 2023/10/11 19:25:59 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室,Since 2012 + */ + +@Service +public class SecurityPasswordService { + + /** + * 密码长度8-20位且包含大小写字母、数字、特殊符号三种及以上组合 + */ + public static final String PASSWORD_PATTERN = "^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\\W_!@#$%^&*`~()-+=]+$)(?![0-9\\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\\W_!@#$%^&*`~()-+=]*$"; + + public static final String PASSWORD_FORMAT_MSG = "密码必须为长度8-20位且必须包含大小写字母、数字、特殊符号(如:@#$%^&*()_+-=)等三种字符"; + + private static final int PASSWORD_LENGTH = 8; + + + @Resource + private PasswordLogDao passwordLogDao; + + @Resource + private Level3ProtectConfigService level3ProtectConfigService; + + static Argon2PasswordEncoder ARGON2_PASSWORD_ENCODER = Argon2PasswordEncoder.defaultsForSpringSecurity_v5_8(); + + /** + * 校验密码复杂度 + */ + public ResponseDTO validatePasswordComplexity(String password) { + + if (SmartStringUtil.isEmpty(password)) { + return ResponseDTO.userErrorParam(PASSWORD_FORMAT_MSG); + } + + // 密码长度必须大于等于8位 + if (password.length() < PASSWORD_LENGTH) { + return ResponseDTO.userErrorParam(PASSWORD_FORMAT_MSG); + } + + // 无需校验 密码复杂度 + if (!level3ProtectConfigService.isPasswordComplexityEnabled()) { + return ResponseDTO.ok(); + } + + if (!password.matches(PASSWORD_PATTERN)) { + return ResponseDTO.userErrorParam(PASSWORD_FORMAT_MSG); + } + + return ResponseDTO.ok(); + } + + /** + * 校验密码重复次数 + */ + public ResponseDTO validatePasswordRepeatTimes(RequestUser requestUser, String newPassword) { + + // 密码重复次数小于1 无需校验 + if (level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes() < 1) { + return ResponseDTO.ok(); + } + + // 检查最近几次是否有重复密码 + List oldPasswords = passwordLogDao.selectOldPassword(requestUser.getUserType().getValue(), requestUser.getUserId(), level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes()); + boolean isDuplicate = oldPasswords.stream().anyMatch(oldPassword -> ARGON2_PASSWORD_ENCODER.matches(newPassword, oldPassword)); + if (isDuplicate) { + return ResponseDTO.userErrorParam(String.format("与前%d个历史密码重复,请换个密码!", level3ProtectConfigService.getRegularChangePasswordNotAllowRepeatTimes())); + } + + return ResponseDTO.ok(); + } + + /** + * 随机生成密码 + */ + public String randomPassword() { + // 未开启密码复杂度,则由8为数字构成 + if (!level3ProtectConfigService.isPasswordComplexityEnabled()) { + return RandomStringUtils.randomNumeric(PASSWORD_LENGTH); + } + + // 3位大写字母,2位数字,2位小写字母 + 1位特殊符号 + return RandomStringUtils.randomAlphabetic(3).toUpperCase() + + RandomStringUtils.randomNumeric(2) + + RandomStringUtils.randomAlphabetic(2).toLowerCase() + + (ThreadLocalRandom.current().nextBoolean() ? "#" : "@"); + } + + + /** + * 保存修改密码 + */ + public void saveUserChangePasswordLog(RequestUser requestUser, String newPassword, String oldPassword) { + + PasswordLogEntity passwordLogEntity = new PasswordLogEntity(); + passwordLogEntity.setNewPassword(newPassword); + passwordLogEntity.setOldPassword(oldPassword); + passwordLogEntity.setUserId(requestUser.getUserId()); + passwordLogEntity.setUserType(requestUser.getUserType().getValue()); + passwordLogDao.insert(passwordLogEntity); + } + + /** + * 检查是否需要修改密码 + */ + public boolean checkNeedChangePassword(Integer userType, Long userId) { + + if (level3ProtectConfigService.getRegularChangePasswordDays() < 1) { + return false; + } + + PasswordLogEntity passwordLogEntity = passwordLogDao.selectLastByUserTypeAndUserId(userType, userId); + if (passwordLogEntity == null) { + return false; + } + + LocalDateTime nextUpdateTime = passwordLogEntity.getCreateTime().plusDays(level3ProtectConfigService.getRegularChangePasswordDays()); + return nextUpdateTime.isBefore(LocalDateTime.now()); + } + + /** + * 获取 加密后 的密码 + */ + public static String getEncryptPwd(String password) { + return ARGON2_PASSWORD_ENCODER.encode(password); + } + + /** + * 校验密码是否匹配 + */ + public static Boolean matchesPwd(String password, String encodedPassword) { + return ARGON2_PASSWORD_ENCODER.matches(password, encodedPassword); + } + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/constant/SerialNumberIdEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/constant/SerialNumberIdEnum.java new file mode 100644 index 0000000..6a12d41 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/constant/SerialNumberIdEnum.java @@ -0,0 +1,42 @@ +package net.lab1024.sa.base.module.support.serialnumber.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 单据序列号 枚举 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@AllArgsConstructor +@Getter +public enum SerialNumberIdEnum implements BaseEnum { + + ORDER(1, "订单id"), + + CONTRACT(2, "合同id"), + + ; + + private final Integer serialNumberId; + + private final String desc; + + @Override + public Integer getValue() { + return serialNumberId; + } + + @Override + public String toString() { + return "SerialNumberIdEnum{" + + "serialNumberId=" + serialNumberId + + ", desc='" + desc + '\'' + + '}'; + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/constant/SerialNumberRuleTypeEnum.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/constant/SerialNumberRuleTypeEnum.java new file mode 100644 index 0000000..01f4f42 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/constant/SerialNumberRuleTypeEnum.java @@ -0,0 +1,44 @@ +package net.lab1024.sa.base.module.support.serialnumber.constant; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.constant.StringConst; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * 单据序列号 周期 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@AllArgsConstructor +@Getter +public enum SerialNumberRuleTypeEnum implements BaseEnum { + /** + * 没有周期 + */ + NONE(StringConst.EMPTY, "", "没有周期"), + /** + * 年周期 + */ + YEAR("[yyyy]", "\\[yyyy\\]", "年"), + /** + * 月周期 + */ + MONTH("[mm]", "\\[mm\\]", "年月"), + /** + * 日周期 + */ + DAY("[dd]", "\\[dd\\]", "年月日"); + + private final String value; + + private final String regex; + + private final String desc; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberDao.java new file mode 100644 index 0000000..6e3303b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberDao.java @@ -0,0 +1,40 @@ +package net.lab1024.sa.base.module.support.serialnumber.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +/** + * 单据序列号 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Mapper +public interface SerialNumberDao extends BaseMapper { + + /** + * 排他锁查询 + * + * @param serialNumberId + * @return + */ + SerialNumberEntity selectForUpdate(@Param("serialNumberId") Integer serialNumberId); + + /** + * 更新上一次的 数值和时间 + * + * @param serialNumberId + * @param lastNumber + * @param lastTime + */ + void updateLastNumberAndTime(@Param("serialNumberId") Integer serialNumberId, @Param("lastNumber") Long lastNumber, @Param("lastTime") LocalDateTime lastTime); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberRecordDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberRecordDao.java new file mode 100644 index 0000000..f363cd6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/dao/SerialNumberRecordDao.java @@ -0,0 +1,54 @@ +package net.lab1024.sa.base.module.support.serialnumber.dao; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberRecordEntity; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberRecordQueryForm; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +import java.time.LocalDate; +import java.util.List; + +/** + * 单据序列号 生成的记录 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Mapper +public interface SerialNumberRecordDao extends BaseMapper { + + /** + * 根据 id和日期 查询 记录id + * + * @param serialNumberId + * @param recordDate + * @return + */ + Long selectRecordIdBySerialNumberIdAndDate(@Param("serialNumberId") Integer serialNumberId, @Param("recordDate") String recordDate); + + /** + * 更新记录 + * + * @param serialNumberId + * @param recordDate + * @param lastNumber + * @param count + * @return + */ + Long updateRecord(@Param("serialNumberId") Integer serialNumberId, @Param("recordDate") LocalDate recordDate, @Param("lastNumber") Long lastNumber, @Param("count") int count); + + /** + * 分页查询记录 + * + * @param page + * @param queryForm + * @return + */ + List query(Page page, @Param("queryForm") SerialNumberRecordQueryForm queryForm); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberEntity.java new file mode 100644 index 0000000..46ae303 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberEntity.java @@ -0,0 +1,79 @@ +package net.lab1024.sa.base.module.support.serialnumber.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberIdEnum; +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberRuleTypeEnum; + +import java.time.LocalDateTime; + +/** + * 单据序列号 定义表 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@TableName("t_serial_number") +public class SerialNumberEntity { + + /** + * 主键id + * + * @see SerialNumberIdEnum + */ + @TableId(type = IdType.INPUT) + private Integer serialNumberId; + + /** + * 业务 + */ + private String businessName; + + /** + * 格式 + */ + private String format; + + /** + * 生成规则 + * + * @see SerialNumberRuleTypeEnum + */ + private String ruleType; + + + /** + * 初始值 + */ + private Long initNumber; + + /** + * 步长随机数范围 + */ + private Integer stepRandomRange; + + /** + * 备注 + */ + private String remark; + + /** + * 上次产生的单号, 默认为空 + */ + private Long lastNumber; + + /** + * 上次产生的单号时间 + */ + private LocalDateTime lastTime; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberGenerateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberGenerateForm.java new file mode 100644 index 0000000..0308cfd --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberGenerateForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.serialnumber.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 单据序列号 生成表单 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class SerialNumberGenerateForm { + + @Schema(description = "单号id") + @NotNull(message = "单号id不能为空") + private Integer serialNumberId; + + @Schema(description = "生成的数量") + @NotNull(message = "生成的数量") + private Integer count; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberGenerateResultBO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberGenerateResultBO.java new file mode 100644 index 0000000..6250b61 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberGenerateResultBO.java @@ -0,0 +1,52 @@ +package net.lab1024.sa.base.module.support.serialnumber.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 单据序列号 生成结果 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class SerialNumberGenerateResultBO { + + /** + * 序号id + */ + private Integer serialNumberId; + + /** + * 是否重置的初始值 + */ + private Boolean isReset; + + /** + * 上次生成的数字 + */ + private Long lastNumber; + + /** + * 上次生成的时间 + */ + private LocalDateTime lastTime; + + /** + * 生成的 number 集合 + */ + private List numberList; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberInfoBO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberInfoBO.java new file mode 100644 index 0000000..4bb3071 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberInfoBO.java @@ -0,0 +1,97 @@ +package net.lab1024.sa.base.module.support.serialnumber.domain; + +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; +import lombok.NoArgsConstructor; +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberIdEnum; +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberRuleTypeEnum; + +/** + * 单据序列号 信息 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ + +@Getter +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class SerialNumberInfoBO { + + /** + * 主键id + * + * @see SerialNumberIdEnum + */ + private Integer serialNumberId; + + /** + * 业务 + */ + private String businessName; + + /** + * 格式 + */ + private String format; + + /** + * 生成规则 + * + * @see SerialNumberRuleTypeEnum + */ + private String ruleType; + + + /** + * 初始值 + */ + private Long initNumber; + + /** + * 步长随机数范围 + */ + private Integer stepRandomRange; + + /** + * 备注 + */ + private String remark; + + /** + * 规则枚举 + */ + private SerialNumberRuleTypeEnum serialNumberRuleTypeEnum; + + + /** + * 存在[nnnnnn]中 n 的数量 + */ + private Integer numberCount; + + /** + * [nnnnnn] 的格式(主要用于替换) + */ + private String numberFormat; + + /** + * 是否存在年份 + */ + private Boolean haveYearFlag; + + /** + * 是否存在月份 + */ + private Boolean haveMonthFlag; + + /** + * 是否存在 月 + */ + private Boolean haveDayFlag; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberLastGenerateBO.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberLastGenerateBO.java new file mode 100644 index 0000000..f695df0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberLastGenerateBO.java @@ -0,0 +1,47 @@ +package net.lab1024.sa.base.module.support.serialnumber.domain; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDateTime; + +/** + * 上次生成信息 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +@Builder +public class SerialNumberLastGenerateBO { + + /** + * 序号id + */ + private Integer serialNumberId; + + /** + * 上次生成的数字 + */ + private Long lastNumber; + + /** + * 上次生成的时间 + */ + @JsonDeserialize(using = LocalDateTimeDeserializer.class) + @JsonSerialize(using = LocalDateTimeSerializer.class) + private LocalDateTime lastTime; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberRecordEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberRecordEntity.java new file mode 100644 index 0000000..f7c3a7d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberRecordEntity.java @@ -0,0 +1,60 @@ +package net.lab1024.sa.base.module.support.serialnumber.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +/** + * 单据序列号 表结构 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@TableName("t_serial_number_record") +public class SerialNumberRecordEntity { + + /** + * 单号id + */ + @TableId(type= IdType.NONE) + private Integer serialNumberId; + + /** + * 记录日期 + */ + private LocalDate recordDate; + + /** + * 最后更新值 + */ + private Long lastNumber; + + /** + * 上次生成时间 + */ + private LocalDateTime lastTime; + + /** + * 数量 + */ + private Long count; + + private LocalDateTime updateTime; + + private LocalDateTime createTime; + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberRecordQueryForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberRecordQueryForm.java new file mode 100644 index 0000000..95041bb --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/domain/SerialNumberRecordQueryForm.java @@ -0,0 +1,23 @@ +package net.lab1024.sa.base.module.support.serialnumber.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import net.lab1024.sa.base.common.domain.PageParam; + +/** + * 单据序列号 生成记录 查询 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class SerialNumberRecordQueryForm extends PageParam { + + @Schema(description = "单号id") + @NotNull(message = "单号id不能为空") + private Integer serialNumberId; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberBaseService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberBaseService.java new file mode 100644 index 0000000..baa912b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberBaseService.java @@ -0,0 +1,252 @@ +package net.lab1024.sa.base.module.support.serialnumber.service; + +import com.google.common.collect.Lists; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.exception.BusinessException; +import net.lab1024.sa.base.common.util.SmartEnumUtil; +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberIdEnum; +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberRuleTypeEnum; +import net.lab1024.sa.base.module.support.serialnumber.dao.SerialNumberDao; +import net.lab1024.sa.base.module.support.serialnumber.dao.SerialNumberRecordDao; +import net.lab1024.sa.base.module.support.serialnumber.domain.*; +import org.apache.commons.lang3.RandomUtils; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 单据序列号 基类 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +public abstract class SerialNumberBaseService implements SerialNumberService { + + @Resource + protected SerialNumberRecordDao serialNumberRecordDao; + + @Resource + protected SerialNumberDao serialNumberDao; + + private ConcurrentHashMap serialNumberMap = new ConcurrentHashMap<>(); + + public abstract List generateSerialNumberList(SerialNumberInfoBO serialNumber, int count); + + @PostConstruct + void init() { + List serialNumberEntityList = serialNumberDao.selectList(null); + if (serialNumberEntityList == null) { + return; + } + for (SerialNumberEntity serialNumberEntity : serialNumberEntityList) { + SerialNumberRuleTypeEnum ruleTypeEnum = SmartEnumUtil.getEnumByName(serialNumberEntity.getRuleType().toUpperCase(), SerialNumberRuleTypeEnum.class); + if (ruleTypeEnum == null) { + throw new ExceptionInInitializerError("cannot find rule type , id : " + serialNumberEntity.getSerialNumberId()); + } + + String format = serialNumberEntity.getFormat(); + int startIndex = format.indexOf("[n"); + int endIndex = format.indexOf("n]"); + if (startIndex == -1 || endIndex == -1 || endIndex <= startIndex) { + throw new ExceptionInInitializerError("[nnn] 配置错误,请仔细查看 id : " + serialNumberEntity.getSerialNumberId()); + } + + String numberFormat = format.substring(startIndex + 1, endIndex + 1); + + if (serialNumberEntity.getStepRandomRange() < 1) { + throw new ExceptionInInitializerError("random step range must greater than 1 " + serialNumberEntity.getSerialNumberId()); + } + + SerialNumberInfoBO serialNumberInfoBO = SerialNumberInfoBO.builder() + .serialNumberId(serialNumberEntity.getSerialNumberId()) + .serialNumberRuleTypeEnum(ruleTypeEnum) + .initNumber(serialNumberEntity.getInitNumber()) + .format(serialNumberEntity.getFormat()) + .stepRandomRange(serialNumberEntity.getStepRandomRange()) + .haveDayFlag(format.contains(SerialNumberRuleTypeEnum.DAY.getValue())) + .haveMonthFlag(format.contains(SerialNumberRuleTypeEnum.MONTH.getValue())) + .haveYearFlag(format.contains(SerialNumberRuleTypeEnum.YEAR.getValue())) + .numberCount(endIndex - startIndex) + .numberFormat("\\[" + numberFormat + "\\]") + .build(); + + this.serialNumberMap.put(serialNumberEntity.getSerialNumberId(), serialNumberInfoBO); + } + + //初始化数据 + initLastGenerateData(serialNumberEntityList); + } + + /** + * 初始化上次生成的数据 + * + * @param serialNumberEntityList + */ + public abstract void initLastGenerateData(List serialNumberEntityList); + + @Override + public String generate(SerialNumberIdEnum serialNumberIdEnum) { + List generateList = this.generate(serialNumberIdEnum, 1); + if (generateList == null || generateList.isEmpty()) { + throw new BusinessException("cannot generate : " + serialNumberIdEnum.toString()); + } + return generateList.get(0); + } + + @Override + public List generate(SerialNumberIdEnum serialNumberIdEnum, int count) { + SerialNumberInfoBO serialNumberInfoBO = serialNumberMap.get(serialNumberIdEnum.getSerialNumberId()); + if (serialNumberInfoBO == null) { + throw new BusinessException("cannot found SerialNumberId : " + serialNumberIdEnum.toString()); + } + return this.generateSerialNumberList(serialNumberInfoBO, count); + } + + /** + * 循环生成 number 集合 + * + * @param lastGenerate + * @param serialNumberInfo + * @param count + * @return + */ + protected SerialNumberGenerateResultBO loopNumberList(SerialNumberLastGenerateBO lastGenerate, SerialNumberInfoBO serialNumberInfo, int count) { + Long lastNumber = lastGenerate.getLastNumber(); + boolean isReset = false; + if (isResetInitNumber(lastGenerate, serialNumberInfo)) { + lastNumber = serialNumberInfo.getInitNumber(); + isReset = true; + } + + ArrayList numberList = Lists.newArrayListWithCapacity(count); + for (int i = 0; i < count; i++) { + Integer stepRandomRange = serialNumberInfo.getStepRandomRange(); + if (stepRandomRange > 1) { + lastNumber = lastNumber + RandomUtils.nextInt(1, stepRandomRange + 1); + } else { + lastNumber = lastNumber + 1; + } + + numberList.add(lastNumber); + } + + return SerialNumberGenerateResultBO + .builder() + .serialNumberId(serialNumberInfo.getSerialNumberId()) + .lastNumber(lastNumber) + .lastTime(LocalDateTime.now()) + .numberList(numberList) + .isReset(isReset) + .build(); + } + + protected void saveRecord(SerialNumberGenerateResultBO resultBO) { + Long effectRows = serialNumberRecordDao.updateRecord(resultBO.getSerialNumberId(), + resultBO.getLastTime().toLocalDate(), + resultBO.getLastNumber(), + resultBO.getNumberList().size() + ); + + // 需要插入 + if (effectRows == null || effectRows == 0) { + SerialNumberRecordEntity recordEntity = SerialNumberRecordEntity.builder() + .serialNumberId(resultBO.getSerialNumberId()) + .recordDate(LocalDate.now()) + .lastTime(resultBO.getLastTime()) + .lastNumber(resultBO.getLastNumber()) + .count((long) resultBO.getNumberList().size()) + .build(); + serialNumberRecordDao.insert(recordEntity); + } + + } + + /** + * 若不在规则周期内,重制初始值 + * + * @return + */ + private boolean isResetInitNumber(SerialNumberLastGenerateBO lastGenerate, SerialNumberInfoBO serialNumberInfo) { + LocalDateTime lastTime = lastGenerate.getLastTime(); + if (lastTime == null) { + return true; + } + + SerialNumberRuleTypeEnum serialNumberRuleTypeEnum = serialNumberInfo.getSerialNumberRuleTypeEnum(); + int lastTimeYear = lastTime.getYear(); + int lastTimeMonth = lastTime.getMonthValue(); + int lastTimeDay = lastTime.getDayOfYear(); + + LocalDateTime now = LocalDateTime.now(); + + switch (serialNumberRuleTypeEnum) { + case YEAR: + return lastTimeYear != now.getYear(); + case MONTH: + return lastTimeYear != now.getYear() || lastTimeMonth != now.getMonthValue(); + case DAY: + return lastTimeYear != now.getYear() || lastTimeDay != now.getDayOfYear(); + default: + return false; + } + } + + /** + * 替换特殊rule,即替换[yyyy][mm][dd][nnn]等规则 + */ + protected List formatNumberList(SerialNumberGenerateResultBO generateResult, SerialNumberInfoBO serialNumberInfo) { + + /** + * 第一步:替换年、月、日 + */ + LocalDate lastTime = generateResult.getLastTime().toLocalDate(); + String year = String.valueOf(lastTime.getYear()); + String month = lastTime.getMonthValue() > 9 ? String.valueOf(lastTime.getMonthValue()) : "0" + lastTime.getMonthValue(); + String day = lastTime.getDayOfMonth() > 9 ? String.valueOf(lastTime.getDayOfMonth()) : "0" + lastTime.getDayOfMonth(); + + // 把年月日替换 + String format = serialNumberInfo.getFormat(); + + if (serialNumberInfo.getHaveYearFlag()) { + format = format.replaceAll(SerialNumberRuleTypeEnum.YEAR.getRegex(), year); + } + if (serialNumberInfo.getHaveMonthFlag()) { + format = format.replaceAll(SerialNumberRuleTypeEnum.MONTH.getRegex(), month); + } + if (serialNumberInfo.getHaveDayFlag()) { + format = format.replaceAll(SerialNumberRuleTypeEnum.DAY.getRegex(), day); + } + + + /** + * 第二步:替换数字 + */ + + List numberList = Lists.newArrayListWithCapacity(generateResult.getNumberList().size()); + for (Long number : generateResult.getNumberList()) { + StringBuilder numberStringBuilder = new StringBuilder(); + int currentNumberCount = String.valueOf(number).length(); + //数量不够,前面补0 + if (serialNumberInfo.getNumberCount() > currentNumberCount) { + int remain = serialNumberInfo.getNumberCount() - currentNumberCount; + for (int i = 0; i < remain; i++) { + numberStringBuilder.append(0); + } + } + numberStringBuilder.append(number); + //最终替换 + String finalNumber = format.replaceAll(serialNumberInfo.getNumberFormat(), numberStringBuilder.toString()); + numberList.add(finalNumber); + } + return numberList; + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberRecordService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberRecordService.java new file mode 100644 index 0000000..d102ea5 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberRecordService.java @@ -0,0 +1,34 @@ +package net.lab1024.sa.base.module.support.serialnumber.service; + +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.PageResult; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.module.support.serialnumber.dao.SerialNumberRecordDao; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberRecordEntity; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberRecordQueryForm; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 单据序列号 记录 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Service +public class SerialNumberRecordService { + + @Resource + private SerialNumberRecordDao serialNumberRecordDao; + + public PageResult query(SerialNumberRecordQueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List recordList = serialNumberRecordDao.query(page, queryForm); + return SmartPageUtil.convert2PageResult(page, recordList); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberService.java new file mode 100644 index 0000000..50d1dbe --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/SerialNumberService.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.module.support.serialnumber.service; + +import net.lab1024.sa.base.module.support.serialnumber.constant.SerialNumberIdEnum; + +import java.util.List; + +/** + * 单据序列号 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +public interface SerialNumberService { + + /** + * 生成 + * + * @param serialNumberIdEnum + * @return + */ + String generate(SerialNumberIdEnum serialNumberIdEnum); + + + /** + * 生成n个 + * + * @param serialNumberIdEnum + * @param count + * @return + */ + List generate(SerialNumberIdEnum serialNumberIdEnum, int count); + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberInternService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberInternService.java new file mode 100644 index 0000000..8a21ebc --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberInternService.java @@ -0,0 +1,78 @@ +package net.lab1024.sa.base.module.support.serialnumber.service.impl; + +import com.google.common.collect.Interner; +import com.google.common.collect.Interners; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberEntity; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberGenerateResultBO; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberInfoBO; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberLastGenerateBO; +import net.lab1024.sa.base.module.support.serialnumber.service.SerialNumberBaseService; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 单据序列号 基于内存锁实现 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Service +public class SerialNumberInternService extends SerialNumberBaseService { + + /** + * 按照 serialNumberId 进行锁 + */ + private static final Interner POOL = Interners.newStrongInterner(); + + + private ConcurrentHashMap serialNumberLastGenerateMap = new ConcurrentHashMap<>(); + + @Override + public void initLastGenerateData(List serialNumberEntityList) { + if (serialNumberEntityList == null) { + return; + } + + for (SerialNumberEntity serialNumberEntity : serialNumberEntityList) { + SerialNumberLastGenerateBO lastGenerateBO = SerialNumberLastGenerateBO + .builder() + .serialNumberId(serialNumberEntity.getSerialNumberId()) + .lastNumber(serialNumberEntity.getLastNumber()) + .lastTime(serialNumberEntity.getLastTime()) + .build(); + serialNumberLastGenerateMap.put(serialNumberEntity.getSerialNumberId(), lastGenerateBO); + } + } + + @Override + public List generateSerialNumberList(SerialNumberInfoBO serialNumberInfo, int count) { + SerialNumberGenerateResultBO serialNumberGenerateResult = null; + synchronized (POOL.intern(serialNumberInfo.getSerialNumberId())) { + + // 获取上次的生成结果 + SerialNumberLastGenerateBO lastGenerateBO = serialNumberLastGenerateMap.get(serialNumberInfo.getSerialNumberId()); + + // 生成 + serialNumberGenerateResult = super.loopNumberList(lastGenerateBO, serialNumberInfo, count); + + // 将生成信息保存的内存和数据库 + lastGenerateBO.setLastNumber(serialNumberGenerateResult.getLastNumber()); + lastGenerateBO.setLastTime(serialNumberGenerateResult.getLastTime()); + serialNumberDao.updateLastNumberAndTime(serialNumberInfo.getSerialNumberId(), + serialNumberGenerateResult.getLastNumber(), + serialNumberGenerateResult.getLastTime()); + + // 把生成过程保存到数据库里 + super.saveRecord(serialNumberGenerateResult); + } + + return formatNumberList(serialNumberGenerateResult, serialNumberInfo); + } + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberMysqlService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberMysqlService.java new file mode 100644 index 0000000..0d13dc7 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberMysqlService.java @@ -0,0 +1,61 @@ +package net.lab1024.sa.base.module.support.serialnumber.service.impl; + +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.exception.BusinessException; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberEntity; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberGenerateResultBO; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberInfoBO; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberLastGenerateBO; +import net.lab1024.sa.base.module.support.serialnumber.service.SerialNumberBaseService; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 单据序列号 基于mysql锁实现 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Slf4j +public class SerialNumberMysqlService extends SerialNumberBaseService { + + @Override + @Transactional(rollbackFor = Throwable.class) + public List generateSerialNumberList(SerialNumberInfoBO serialNumberInfo, int count) { + // // 获取上次的生成结果 + SerialNumberEntity serialNumberEntity = serialNumberDao.selectForUpdate(serialNumberInfo.getSerialNumberId()); + if (serialNumberEntity == null) { + throw new BusinessException("cannot found SerialNumberId 数据库不存在:" + serialNumberInfo.getSerialNumberId()); + } + SerialNumberLastGenerateBO lastGenerateBO = SerialNumberLastGenerateBO + .builder() + .lastNumber(serialNumberEntity.getLastNumber()) + .lastTime(serialNumberEntity.getLastTime()) + .serialNumberId(serialNumberEntity.getSerialNumberId()) + .build(); + + // 生成 + SerialNumberGenerateResultBO serialNumberGenerateResult = super.loopNumberList(lastGenerateBO, serialNumberInfo, count); + + // 将生成信息保存的内存和数据库 + lastGenerateBO.setLastNumber(serialNumberGenerateResult.getLastNumber()); + lastGenerateBO.setLastTime(serialNumberGenerateResult.getLastTime()); + serialNumberDao.updateLastNumberAndTime(serialNumberInfo.getSerialNumberId(), + serialNumberGenerateResult.getLastNumber(), + serialNumberGenerateResult.getLastTime()); + + // 把生成过程保存到数据库里 + super.saveRecord(serialNumberGenerateResult); + + return formatNumberList(serialNumberGenerateResult, serialNumberInfo); + } + + @Override + public void initLastGenerateData(List serialNumberEntityList) { + + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberRedisService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberRedisService.java new file mode 100644 index 0000000..571e0d9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/serialnumber/service/impl/SerialNumberRedisService.java @@ -0,0 +1,108 @@ +package net.lab1024.sa.base.module.support.serialnumber.service.impl; + +import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; +import net.lab1024.sa.base.common.exception.BusinessException; +import net.lab1024.sa.base.constant.RedisKeyConst; +import net.lab1024.sa.base.module.support.redis.RedisService; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberEntity; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberGenerateResultBO; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberInfoBO; +import net.lab1024.sa.base.module.support.serialnumber.domain.SerialNumberLastGenerateBO; +import net.lab1024.sa.base.module.support.serialnumber.service.SerialNumberBaseService; + +import java.util.List; + +/** + * 单据序列号 基于redis锁实现 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-03-25 21:46:07 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Slf4j +public class SerialNumberRedisService extends SerialNumberBaseService { + + private static final int MAX_GET_LOCK_COUNT = 5; + + private static final long SLEEP_MILLISECONDS = 200L; + + @Resource + private RedisService redisService; + + @Override + public void initLastGenerateData(List serialNumberEntityList) { + if (serialNumberEntityList == null) { + return; + } + + //删除之前的 + redisService.delete(RedisKeyConst.Support.SERIAL_NUMBER_LAST_INFO); + + for (SerialNumberEntity serialNumberEntity : serialNumberEntityList) { + SerialNumberLastGenerateBO lastGenerateBO = SerialNumberLastGenerateBO + .builder() + .serialNumberId(serialNumberEntity.getSerialNumberId()) + .lastNumber(serialNumberEntity.getLastNumber()) + .lastTime(serialNumberEntity.getLastTime()) + .build(); + + redisService.mset(RedisKeyConst.Support.SERIAL_NUMBER_LAST_INFO, + String.valueOf(serialNumberEntity.getSerialNumberId()), + lastGenerateBO + ); + } + } + + @Override + public List generateSerialNumberList(SerialNumberInfoBO serialNumberInfo, int count) { + SerialNumberGenerateResultBO serialNumberGenerateResult = null; + String lockKey = RedisKeyConst.Support.SERIAL_NUMBER + serialNumberInfo.getSerialNumberId(); + try { + boolean lock = false; + for (int i = 0; i < MAX_GET_LOCK_COUNT; i++) { + try { + lock = redisService.getLock(lockKey, 60 * 1000L); + if (lock) { + break; + } + Thread.sleep(SLEEP_MILLISECONDS); + } catch (Throwable e) { + log.error(e.getMessage(), e); + } + } + if (!lock) { + throw new BusinessException("SerialNumber 尝试5次,未能生成单号"); + } + // 获取上次的生成结果 + SerialNumberLastGenerateBO lastGenerateBO = (SerialNumberLastGenerateBO) redisService.mget( + RedisKeyConst.Support.SERIAL_NUMBER_LAST_INFO, + String.valueOf(serialNumberInfo.getSerialNumberId())); + + // 生成 + serialNumberGenerateResult = super.loopNumberList(lastGenerateBO, serialNumberInfo, count); + + // 将生成信息保存的内存和数据库 + lastGenerateBO.setLastNumber(serialNumberGenerateResult.getLastNumber()); + lastGenerateBO.setLastTime(serialNumberGenerateResult.getLastTime()); + serialNumberDao.updateLastNumberAndTime(serialNumberInfo.getSerialNumberId(), + serialNumberGenerateResult.getLastNumber(), + serialNumberGenerateResult.getLastTime()); + + redisService.mset(RedisKeyConst.Support.SERIAL_NUMBER_LAST_INFO, + String.valueOf(serialNumberInfo.getSerialNumberId()), lastGenerateBO); + + // 把生成过程保存到数据库里 + super.saveRecord(serialNumberGenerateResult); + } catch (Throwable e) { + log.error(e.getMessage(), e); + throw e; + } finally { + redisService.unLock(lockKey); + } + + return formatNumberList(serialNumberGenerateResult, serialNumberInfo); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnController.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnController.java new file mode 100644 index 0000000..66b3dc5 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnController.java @@ -0,0 +1,50 @@ +package net.lab1024.sa.base.module.support.table; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import net.lab1024.sa.base.common.controller.SupportBaseController; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.util.SmartRequestUtil; +import net.lab1024.sa.base.constant.SwaggerTagConst; +import net.lab1024.sa.base.module.support.repeatsubmit.annoation.RepeatSubmit; +import net.lab1024.sa.base.module.support.table.domain.TableColumnUpdateForm; +import org.springframework.web.bind.annotation.*; + +/** + * 表格自定义列(前端用户自定义表格列,并保存到数据库里) + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-08-12 22:52:21 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@RestController +@Tag(name = SwaggerTagConst.Support.TABLE_COLUMN) +public class TableColumnController extends SupportBaseController { + + @Resource + private TableColumnService tableColumnService; + + @Operation(summary = "修改表格列 @author 卓大") + @PostMapping("/tableColumn/update") + @RepeatSubmit + public ResponseDTO updateTableColumn(@RequestBody @Valid TableColumnUpdateForm updateForm) { + return tableColumnService.updateTableColumns(SmartRequestUtil.getRequestUser(), updateForm); + } + + @Operation(summary = "恢复默认(删除) @author 卓大") + @GetMapping("/tableColumn/delete/{tableId}") + @RepeatSubmit + public ResponseDTO deleteTableColumn(@PathVariable Integer tableId) { + return tableColumnService.deleteTableColumn(SmartRequestUtil.getRequestUser(), tableId); + } + + @Operation(summary = "查询表格列 @author 卓大") + @GetMapping("/tableColumn/getColumns/{tableId}") + public ResponseDTO getColumns(@PathVariable Integer tableId) { + return ResponseDTO.ok(tableColumnService.getTableColumns(SmartRequestUtil.getRequestUser(), tableId)); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnDao.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnDao.java new file mode 100644 index 0000000..6dbe22f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnDao.java @@ -0,0 +1,23 @@ +package net.lab1024.sa.base.module.support.table; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import net.lab1024.sa.base.module.support.table.domain.TableColumnEntity; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +/** + * 表格自定义列(前端用户自定义表格列,并保存到数据库里) + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-08-12 22:52:21 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Mapper +public interface TableColumnDao extends BaseMapper { + + TableColumnEntity selectByUserIdAndTableId(@Param("userId") Long userId, @Param("userType") Integer userType, @Param("tableId") Integer tableId); + + void deleteTableColumn(@Param("userId") Long userId, @Param("userType") Integer userType, @Param("tableId") Integer tableId); +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnService.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnService.java new file mode 100644 index 0000000..871e1aa --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/TableColumnService.java @@ -0,0 +1,72 @@ +package net.lab1024.sa.base.module.support.table; + +import com.alibaba.fastjson.JSONArray; +import jakarta.annotation.Resource; +import net.lab1024.sa.base.common.domain.RequestUser; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.module.support.table.domain.TableColumnEntity; +import net.lab1024.sa.base.module.support.table.domain.TableColumnUpdateForm; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +/** + * 表格自定义列(前端用户自定义表格列,并保存到数据库里) + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-08-12 22:52:21 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Service +public class TableColumnService { + + @Resource + private TableColumnDao tableColumnDao; + + /** + * 获取 - 表格列 + * + * @return + */ + public String getTableColumns(RequestUser requestUser, Integer tableId) { + TableColumnEntity tableColumnEntity = tableColumnDao.selectByUserIdAndTableId(requestUser.getUserId(), requestUser.getUserType().getValue(), tableId); + return tableColumnEntity == null ? null : tableColumnEntity.getColumns(); + } + + /** + * 更新表格列 + * + * @return + */ + public ResponseDTO updateTableColumns(RequestUser requestUser, TableColumnUpdateForm updateForm) { + if (CollectionUtils.isEmpty(updateForm.getColumnList())) { + return ResponseDTO.ok(); + } + Integer tableId = updateForm.getTableId(); + TableColumnEntity tableColumnEntity = tableColumnDao.selectByUserIdAndTableId(requestUser.getUserId(), requestUser.getUserType().getValue(), tableId); + if (tableColumnEntity == null) { + tableColumnEntity = new TableColumnEntity(); + tableColumnEntity.setTableId(tableId); + tableColumnEntity.setUserId(requestUser.getUserId()); + tableColumnEntity.setUserType(requestUser.getUserType().getValue()); + + tableColumnEntity.setColumns(JSONArray.toJSONString(updateForm.getColumnList())); + tableColumnDao.insert(tableColumnEntity); + } else { + tableColumnEntity.setColumns(JSONArray.toJSONString(updateForm.getColumnList())); + tableColumnDao.updateById(tableColumnEntity); + } + return ResponseDTO.ok(); + } + + /** + * 删除表格列 + * + * @return + */ + public ResponseDTO deleteTableColumn(RequestUser requestUser, Integer tableId) { + tableColumnDao.deleteTableColumn(requestUser.getUserId(), requestUser.getUserType().getValue(), tableId); + return ResponseDTO.ok(); + } +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnEntity.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnEntity.java new file mode 100644 index 0000000..b8b89cb --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnEntity.java @@ -0,0 +1,49 @@ +package net.lab1024.sa.base.module.support.table.domain; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 自定义表格列 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-08-12 22:52:21 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +@TableName("t_table_column") +public class TableColumnEntity { + + @TableId(type = IdType.AUTO) + private Long tableColumnId; + + /** + * 用户id + */ + private Long userId; + + /** + * 用户类型 + */ + private Integer userType; + + /** + * 表id + */ + private Integer tableId; + + /** + * 表列 + */ + private String columns; + + private LocalDateTime createTime; + + private LocalDateTime updateTime; +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnItemForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnItemForm.java new file mode 100644 index 0000000..4cc96f0 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnItemForm.java @@ -0,0 +1,36 @@ +package net.lab1024.sa.base.module.support.table.domain; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * 自定义表格列 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-08-12 22:52:21 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class TableColumnItemForm { + + @NotEmpty(message = "列不能为空") + @Schema(description = "字段") + private String columnKey; + + @Schema(description = "宽度") + private Integer width; + + @NotNull(message = "显示不能为空") + @Schema(description = "是否显示") + private Boolean showFlag; + + @NotNull(message = "排序不能为空") + @Schema(description = "排序") + private Integer sort; + + +} diff --git a/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnUpdateForm.java b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnUpdateForm.java new file mode 100644 index 0000000..dce303f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/java/net/lab1024/sa/base/module/support/table/domain/TableColumnUpdateForm.java @@ -0,0 +1,27 @@ +package net.lab1024.sa.base.module.support.table.domain; + +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.util.List; + +/** + * 自定义表格列 + * + * @Author 1024创新实验室-主任: 卓大 + * @Date 2022-08-12 22:52:21 + * @Wechat zhuoda1024 + * @Email lab1024@163.com + * @Copyright 1024创新实验室 + */ +@Data +public class TableColumnUpdateForm { + + @NotNull(message = "表id不能为空") + private Integer tableId; + + @NotEmpty(message = "请上传列") + private List columnList; + +} diff --git a/smart-flow-api/sa-base/src/main/resources/META-INF/spring.factories b/smart-flow-api/sa-base/src/main/resources/META-INF/spring.factories new file mode 100644 index 0000000..7dc64b8 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/META-INF/spring.factories @@ -0,0 +1,2 @@ +org.springframework.boot.env.EnvironmentPostProcessor=\ + net.lab1024.sa.base.config.YamlProcessor \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/banner.txt b/smart-flow-api/sa-base/src/main/resources/banner.txt new file mode 100644 index 0000000..5e14f0d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/banner.txt @@ -0,0 +1,13 @@ + ${AnsiColor.BRIGHT_GREEN} + + / ____| | | /\ | | (_) +| (___ _ __ ___ __ _ _ __| |_ / \ __| |_ __ ___ _ _ __ + \___ \| '_ ` _ \ / _` | '__| __| / /\ \ / _` | '_ ` _ \| | '_ \ + ____) | | | | | | (_| | | | |_ / ____ \ (_| | | | | | | | | | | +|_____/|_| |_| |_|\__,_|_| \__/_/ \_\__,_|_| |_| |_|_|_| |_| + +保持谦逊 保持学习 ! +热爱代码 热爱生活 ! +永远年轻 永远前行 ! + +${AnsiColor.DEFAULT} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/constant/enum.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/constant/enum.java.vm new file mode 100644 index 0000000..87c2c64 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/constant/enum.java.vm @@ -0,0 +1,24 @@ +package ${packageName}; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import net.lab1024.sa.base.common.enumeration.BaseEnum; + +/** + * ${enumDesc} + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@AllArgsConstructor +@Getter +public enum ${enumName} implements BaseEnum { + + ; + + private final ${enumJavaType} value; + + private final String desc; +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/controller/Controller.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/controller/Controller.java.vm new file mode 100644 index 0000000..3d0657b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/controller/Controller.java.vm @@ -0,0 +1,74 @@ +package ${packageName}; + +#foreach ($importClass in $importPackageList) +$importClass +#end +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.PageResult; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RestController; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.Operation; +import cn.dev33.satoken.annotation.SaCheckPermission; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; + +/** + * ${basic.description} Controller + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@RestController +@Tag(name = "${basic.description}") +public class ${name.upperCamel}Controller { + + @Resource + private ${name.upperCamel}Service ${name.lowerCamel}Service; + + @Operation(summary = "分页查询 @author ${basic.backendAuthor}") + @PostMapping("/${name.lowerCamel}/queryPage") + @SaCheckPermission("${name.lowerCamel}:query") + public ResponseDTO> queryPage(@RequestBody @Valid ${name.upperCamel}QueryForm queryForm) { + return ResponseDTO.ok(${name.lowerCamel}Service.queryPage(queryForm)); + } + +#if($insertAndUpdate.isSupportInsertAndUpdate) + @Operation(summary = "添加 @author ${basic.backendAuthor}") + @PostMapping("/${name.lowerCamel}/add") + @SaCheckPermission("${name.lowerCamel}:add") + public ResponseDTO add(@RequestBody @Valid ${name.upperCamel}AddForm addForm) { + return ${name.lowerCamel}Service.add(addForm); + } + + @Operation(summary = "更新 @author ${basic.backendAuthor}") + @PostMapping("/${name.lowerCamel}/update") + @SaCheckPermission("${name.lowerCamel}:update") + public ResponseDTO update(@RequestBody @Valid ${name.upperCamel}UpdateForm updateForm) { + return ${name.lowerCamel}Service.update(updateForm); + } +#end + +#if($deleteInfo.isSupportDelete) + #if($deleteInfo.deleteEnum == "Batch" || $deleteInfo.deleteEnum == "SingleAndBatch") + @Operation(summary = "批量删除 @author ${basic.backendAuthor}") + @PostMapping("/${name.lowerCamel}/batchDelete") + @SaCheckPermission("${name.lowerCamel}:delete") + public ResponseDTO batchDelete(@RequestBody ValidateList<${primaryKeyJavaType}> idList) { + return ${name.lowerCamel}Service.batchDelete(idList); + } + #end + + #if($deleteInfo.deleteEnum == "Single" || $deleteInfo.deleteEnum == "SingleAndBatch") + @Operation(summary = "单个删除 @author ${basic.backendAuthor}") + @GetMapping("/${name.lowerCamel}/delete/{${primaryKeyFieldName}}") + @SaCheckPermission("${name.lowerCamel}:delete") + public ResponseDTO batchDelete(@PathVariable ${primaryKeyJavaType} ${primaryKeyFieldName}) { + return ${name.lowerCamel}Service.delete(${primaryKeyFieldName}); + } + #end +#end +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/dao/Dao.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/dao/Dao.java.vm new file mode 100644 index 0000000..374c374 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/dao/Dao.java.vm @@ -0,0 +1,51 @@ +package ${packageName}; + +#foreach ($importClass in $importPackageList) +$importClass +#end +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.springframework.stereotype.Component; + +/** + * ${basic.description} Dao + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@Mapper +public interface ${name.upperCamel}Dao extends BaseMapper<${name.upperCamel}Entity> { + + /** + * 分页 查询 + * + * @param page + * @param queryForm + * @return + */ + List<${name.upperCamel}VO> queryPage(Page page, @Param("queryForm") ${name.upperCamel}QueryForm queryForm); + +#if($deleteInfo.isSupportDelete) +### 假删除 +#if(!${deleteInfo.isPhysicallyDeleted}) +#if($deleteInfo.deleteEnum == "Single" || $deleteInfo.deleteEnum == "SingleAndBatch") + /** + * 更新删除状态 + */ + long updateDeleted(@Param("${primaryKeyFieldName}")${primaryKeyJavaType} ${primaryKeyFieldName},@Param("deletedFlag")boolean deletedFlag); + +#end +#if($deleteInfo.deleteEnum == "Batch" || $deleteInfo.deleteEnum == "SingleAndBatch") + /** + * 批量更新删除状态 + */ + void batchUpdateDeleted(@Param("idList")List<${primaryKeyJavaType}> idList,@Param("deletedFlag")boolean deletedFlag); + +#end +#end +#end +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/entity/Entity.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/entity/Entity.java.vm new file mode 100644 index 0000000..04230b3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/entity/Entity.java.vm @@ -0,0 +1,38 @@ +package ${basic.javaPackageName}.domain.entity; + +#foreach ($importClass in $importPackageList) +$importClass +#end + +/** + * ${basic.description} 实体类 + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@Data +@TableName("${tableName}") +public class ${name.upperCamel}Entity { +#foreach ($field in $fields) + + /** + * $field.label + */ + #if($field.primaryKeyFlag && $field.autoIncreaseFlag) + @TableId(type = IdType.AUTO) + #end + #if($field.primaryKeyFlag && !$field.autoIncreaseFlag) + @TableId + #end + #if($field.columnName == "create_time") + @TableField(fill = FieldFill.INSERT) + #end + #if($field.columnName == "update_time") + @TableField(fill = FieldFill.INSERT_UPDATE) + #end + private $field.javaType $field.fieldName; +#end + +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/AddForm.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/AddForm.java.vm new file mode 100644 index 0000000..d1e8581 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/AddForm.java.vm @@ -0,0 +1,30 @@ +package ${packageName}; + +#foreach ($importClass in $importPackageList) +$importClass +#end + +/** + * ${basic.description} 新建表单 + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@Data +public class ${name.upperCamel}AddForm { +#foreach ($field in $fields) + +#if($field.isEnum) + ${field.apiModelProperty} + ${field.checkEnum} + private $field.javaType $field.fieldName; +#end +#if(!$field.isEnum) + ${field.apiModelProperty}$!{field.notEmpty}$!{field.dict}$!{field.file} + private $field.javaType $field.fieldName; +#end +#end + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/QueryForm.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/QueryForm.java.vm new file mode 100644 index 0000000..69a247e --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/QueryForm.java.vm @@ -0,0 +1,39 @@ +package ${packageName}; + +import net.lab1024.sa.base.common.domain.PageParam; +#foreach ($importClass in $importPackageList) +$importClass +#end + +/** + * ${basic.description} 分页查询表单 + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@Data +@EqualsAndHashCode(callSuper = false) +public class ${name.upperCamel}QueryForm extends PageParam { +#foreach ($field in $fields) + +#if($field.isEnum) + ${field.apiModelProperty} + ${field.checkEnum} + private $field.javaType $field.fieldName; +#end +#if(!$field.isEnum && $field.queryTypeEnum != "DateRange") + ${field.apiModelProperty}$!{field.dict} + private $field.javaType $field.fieldName; +#end +#if(!$field.isEnum && $field.queryTypeEnum == "DateRange") + ${field.apiModelProperty} + private $field.javaType ${field.fieldName}Begin; + + ${field.apiModelProperty} + private $field.javaType ${field.fieldName}End; +#end +#end + +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/UpdateForm.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/UpdateForm.java.vm new file mode 100644 index 0000000..15cbe9a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/form/UpdateForm.java.vm @@ -0,0 +1,30 @@ +package ${packageName}; + +#foreach ($importClass in $importPackageList) +$importClass +#end + +/** + * ${basic.description} 更新表单 + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@Data +public class ${name.upperCamel}UpdateForm { +#foreach ($field in $fields) + +#if($field.isEnum) + ${field.apiModelProperty} + ${field.checkEnum} + private $field.javaType $field.fieldName; +#end +#if(!$field.isEnum) + ${field.apiModelProperty}$!{field.notEmpty}$!{field.dict}$!{field.file} + private $field.javaType $field.fieldName; +#end +#end + +} \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/vo/VO.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/vo/VO.java.vm new file mode 100644 index 0000000..76ebd3d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/domain/vo/VO.java.vm @@ -0,0 +1,24 @@ +package ${packageName}; + +#foreach ($importClass in $importPackageList) +$importClass +#end + +/** + * ${basic.description} 列表VO + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@Data +public class ${name.upperCamel}VO { + +#foreach ($field in $fields) + + ${field.apiModelProperty}$!{field.notEmpty}$!{field.file} + private $field.javaType $field.fieldName; +#end + +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/manager/Manager.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/manager/Manager.java.vm new file mode 100644 index 0000000..52811ca --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/manager/Manager.java.vm @@ -0,0 +1,21 @@ +package ${packageName}; + +#foreach ($importClass in $importPackageList) +$importClass +#end + +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import org.springframework.stereotype.Service; + +/** + * ${basic.description} Manager + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ +@Service +public class ${name.upperCamel}Manager extends ServiceImpl<${name.upperCamel}Dao, ${name.upperCamel}Entity> { + + +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/mapper/Mapper.xml.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/mapper/Mapper.xml.vm new file mode 100644 index 0000000..7a82712 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/mapper/Mapper.xml.vm @@ -0,0 +1,76 @@ + + + + + + + #foreach ($field in $fields) + ${tableName}.${field.columnName}#if($foreach.hasNext),#end + #end + + + + + +#if($deleteInfo.isSupportDelete) +### 假删除 +#if(!${deleteInfo.isPhysicallyDeleted}) +#if($deleteInfo.deleteEnum == "Batch" || $deleteInfo.deleteEnum == "SingleAndBatch") + + update ${tableName} set deleted_flag = #{deletedFlag} + where ${primaryKeyColumnName} in + + #{item} + + +#end +#if($deleteInfo.deleteEnum == "Single" || $deleteInfo.deleteEnum == "SingleAndBatch") + + + update ${tableName} set deleted_flag = #{deletedFlag} + where ${primaryKeyColumnName} = #{${primaryKeyFieldName}} + +#end +#end +#end + + diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/service/Service.java.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/service/Service.java.vm new file mode 100644 index 0000000..e21bb2f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/service/Service.java.vm @@ -0,0 +1,100 @@ +package ${packageName}; + +#foreach ($importClass in $importPackageList) +$importClass +#end +import net.lab1024.sa.base.common.util.SmartBeanUtil; +import net.lab1024.sa.base.common.util.SmartPageUtil; +import net.lab1024.sa.base.common.domain.ResponseDTO; +import net.lab1024.sa.base.common.domain.PageResult; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.stereotype.Service; + +import jakarta.annotation.Resource; + +/** + * ${basic.description} Service + * + * @Author ${basic.backendAuthor} + * @Date ${basic.backendDate} + * @Copyright ${basic.copyright} + */ + +@Service +public class ${name.upperCamel}Service { + + @Resource + private ${name.upperCamel}Dao ${name.lowerCamel}Dao; + + /** + * 分页查询 + */ + public PageResult<${name.upperCamel}VO> queryPage(${name.upperCamel}QueryForm queryForm) { + Page page = SmartPageUtil.convert2PageQuery(queryForm); + List<${name.upperCamel}VO> list = ${name.lowerCamel}Dao.queryPage(page, queryForm); + return SmartPageUtil.convert2PageResult(page, list); + } + +#if($insertAndUpdate.isSupportInsertAndUpdate) + /** + * 添加 + */ + public ResponseDTO add(${name.upperCamel}AddForm addForm) { + ${name.upperCamel}Entity ${name.lowerCamel}Entity = SmartBeanUtil.copy(addForm, ${name.upperCamel}Entity.class); + ${name.lowerCamel}Dao.insert(${name.lowerCamel}Entity); + return ResponseDTO.ok(); + } + + /** + * 更新 + * + */ + public ResponseDTO update(${name.upperCamel}UpdateForm updateForm) { + ${name.upperCamel}Entity ${name.lowerCamel}Entity = SmartBeanUtil.copy(updateForm, ${name.upperCamel}Entity.class); + ${name.lowerCamel}Dao.updateById(${name.lowerCamel}Entity); + return ResponseDTO.ok(); + } +#end + +#if($deleteInfo.isSupportDelete) + #if($deleteInfo.deleteEnum == "Batch" || $deleteInfo.deleteEnum == "SingleAndBatch") + /** + * 批量删除 + */ + public ResponseDTO batchDelete(List<${primaryKeyJavaType}> idList) { + if (CollectionUtils.isEmpty(idList)){ + return ResponseDTO.ok(); + } + +### 真删除 or 假删除 +#if(!${deleteInfo.isPhysicallyDeleted}) + ${name.lowerCamel}Dao.batchUpdateDeleted(idList, true); +#else + ${name.lowerCamel}Dao.deleteBatchIds(idList); +#end + return ResponseDTO.ok(); + } + #end + + #if($deleteInfo.deleteEnum == "Single" || $deleteInfo.deleteEnum == "SingleAndBatch") + /** + * 单个删除 + */ + public ResponseDTO delete(${primaryKeyJavaType} ${primaryKeyFieldName}) { + if (null == ${primaryKeyFieldName}){ + return ResponseDTO.ok(); + } + +### 真删除 or 假删除 +#if(!${deleteInfo.isPhysicallyDeleted}) + ${name.lowerCamel}Dao.updateDeleted(${primaryKeyFieldName}, true); +#end +#if(${deleteInfo.isPhysicallyDeleted}) + ${name.lowerCamel}Dao.deleteById(${primaryKeyFieldName}); +#end + return ResponseDTO.ok(); + } + #end +#end +} diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/sql/Menu.sql.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/sql/Menu.sql.vm new file mode 100644 index 0000000..4f066e3 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/java/sql/Menu.sql.vm @@ -0,0 +1,22 @@ +# 默认是按前端工程文件的 /views/business 文件夹的路径作为前端组件路径,如果你没把生成的 .vue 前端代码放在 /views/business 下, +# 那就根据自己实际情况修改下面 SQL 的 path,component 字段值,避免执行 SQL 后菜单无法访问。 +# 如果你一切都是按照默认,那么下面的 SQL 基本不用改 + +INSERT INTO t_menu ( menu_name, menu_type, parent_id, path, component, frame_flag, cache_flag, visible_flag, disabled_flag, perms_type, create_user_id ) +VALUES ( '${basic.description}', 2, 0, '/${name.lowerHyphenCamel}/list', '/business/${name.lowerHyphenCamel}/${name.lowerHyphenCamel}-list.vue', false, false, true, false, 1, 1 ); + +# 按菜单名称查询该菜单的 menu_id 作为按钮权限的 父菜单ID 与 功能点关联菜单ID +SET @parent_id = NULL; +SELECT t_menu.menu_id INTO @parent_id FROM t_menu WHERE t_menu.menu_name = '${basic.description}'; + +INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, perms_type, api_perms, web_perms, context_menu_id, create_user_id ) +VALUES ( '查询', 3, @parent_id, false, false, true, false, 1, '${name.lowerCamel}:query', '${name.lowerCamel}:query', @parent_id, 1 ); + +INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, perms_type, api_perms, web_perms, context_menu_id, create_user_id ) +VALUES ( '添加', 3, @parent_id, false, false, true, false, 1, '${name.lowerCamel}:add', '${name.lowerCamel}:add', @parent_id, 1 ); + +INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, perms_type, api_perms, web_perms, context_menu_id, create_user_id ) +VALUES ( '更新', 3, @parent_id, false, false, true, false, 1, '${name.lowerCamel}:update', '${name.lowerCamel}:update', @parent_id, 1 ); + +INSERT INTO t_menu ( menu_name, menu_type, parent_id, frame_flag, cache_flag, visible_flag, disabled_flag, perms_type, api_perms, web_perms, context_menu_id, create_user_id ) +VALUES ( '删除', 3, @parent_id, false, false, true, false, 1, '${name.lowerCamel}:delete', '${name.lowerCamel}:delete', @parent_id, 1 ); diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/api.js.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/api.js.vm new file mode 100644 index 0000000..b249d0c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/api.js.vm @@ -0,0 +1,78 @@ +/** + * ${basic.description} api 封装 + * + * @Author: ${basic.frontAuthor} + * @Date: ${basic.frontDate} + * @Copyright ${basic.copyright} + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const ${name.lowerCamel}Api = { + + /** + * 分页查询 @author ${basic.frontAuthor} + */ + queryPage : (param) => { + return postRequest('/${name.lowerCamel}/queryPage', param); + }, + + /** + * 增加 @author ${basic.frontAuthor} + */ + add: (param) => { + return postRequest('/${name.lowerCamel}/add', param); + }, + + /** + * 修改 @author ${basic.frontAuthor} + */ + update: (param) => { + return postRequest('/${name.lowerCamel}/update', param); + }, +## ------------------ 详情 ------------------ + +#if($deleteInfo.isSupportDetail) + /** + * 获取详情 @author ${basic.frontAuthor} + */ + getDetail: (id) => { + return getRequest(`/${name.lowerCamel}/getDetail/\${id}`); + }, +#end + +## ------------------ 删除 ------------------ +#if($deleteInfo.isSupportDelete) + #if($deleteInfo.deleteEnum == 'Single') + /** + * 删除 @author ${basic.frontAuthor} + */ + delete: (id) => { + return getRequest(`/${name.lowerCamel}/delete/${id}`); + }, + #end + #if($deleteInfo.deleteEnum == 'Batch') + /** + * 批量删除 @author ${basic.frontAuthor} + */ + batchDelete: (idList) => { + return postRequest('/${name.lowerCamel}/batchDelete', idList); + }, + #end + #if($deleteInfo.deleteEnum == 'SingleAndBatch') + /** + * 删除 @author ${basic.frontAuthor} + */ + delete: (id) => { + return getRequest(`/${name.lowerCamel}/delete/${id}`); + }, + + /** + * 批量删除 @author ${basic.frontAuthor} + */ + batchDelete: (idList) => { + return postRequest('/${name.lowerCamel}/batchDelete', idList); + }, + #end +#end + +}; diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/const.js.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/const.js.vm new file mode 100644 index 0000000..30ca06a --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/const.js.vm @@ -0,0 +1,23 @@ +/** + * ${basic.description} 枚举 + * + * @Author: ${basic.frontAuthor} + * @Date: ${basic.frontDate} + * @Copyright ${basic.copyright} + */ + +#foreach ($enum in $enumList) + +/** + * $enum.columnComment + */ +export const $enum.upperUnderscoreEnum = { + +} +#end + +export default { +#foreach ($enum in $enumList) + $enum.upperUnderscoreEnum, +#end +}; \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/form.vue.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/form.vue.vm new file mode 100644 index 0000000..6291a44 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/form.vue.vm @@ -0,0 +1,239 @@ + + + diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/list.vue.vm b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/list.vue.vm new file mode 100644 index 0000000..e336227 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/js/list.vue.vm @@ -0,0 +1,340 @@ + + + diff --git a/smart-flow-api/sa-base/src/main/resources/code-generator-template/tools.xml b/smart-flow-api/sa-base/src/main/resources/code-generator-template/tools.xml new file mode 100644 index 0000000..bcfc8fe --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/code-generator-template/tools.xml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/smart-flow-api/sa-base/src/main/resources/dev/sa-base.yaml b/smart-flow-api/sa-base/src/main/resources/dev/sa-base.yaml new file mode 100644 index 0000000..bffea0c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/dev/sa-base.yaml @@ -0,0 +1,186 @@ +spring: + # 数据库连接信息 + datasource: + url: jdbc:kingbase8://8.162.3.203:54321/economic_crime_dev?currentSchema=public&clientEncoding=utf8&socketTimeout=30000&loginTimeout=30 + username: dcms_dev + password: sdy@2025#dc$ks + driver-class-name: com.kingbase8.Driver + initial-size: 2 + min-idle: 2 + max-active: 10 + max-wait: 60000 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + filters: stat + druid: + username: druid + password: 1024 + login: + enabled: false + method: + pointcut: net.lab1024.sa..*Service.* + + # redis 连接池配置信息 + data: + redis: + database: 10 + host: 127.0.0.1 + port: 6379 + password: + timeout: 10000ms + lettuce: + pool: + max-active: 5 + min-idle: 1 + max-idle: 3 + max-wait: 30000ms + + # 邮件,置以SSL的方式发送, 这个需要使用这种方式并且端口是465 + mail: + host: smtp.163.com + port: 465 + username: lab1024@163.com + password: LAB1024LAB + properties: + mail: + smtp: + auth: true + ssl: + enable: true + socketFactory: + class: com.sun.mail.util.MailSSLSocketFactory + fallback: false + debug: false + + # json序列化相关配置 + jackson: + serialization: + write-enums-using-to-string: true + write-dates-as-timestamps: false + deserialization: + read-enums-using-to-string: true + fail-on-unknown-properties: false + default-property-inclusion: always + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + + # 缓存实现类型 + cache: + type: caffeine + +# tomcat 配置,主要用于 配置 访问日志(便于将来排查错误) +server: + tomcat: + basedir: ${project.log-directory}/tomcat-logs + accesslog: + enabled: true + max-days: 7 + pattern: "%t %{X-Forwarded-For}i %a %r %s (%D ms) %I (%B byte)" + +# 文件上传 配置 +file: + storage: + mode: local + local: + upload-path: ../upload/ #文件上传目录 + url-prefix: + cloud: + region: oss-cn-hangzhou + endpoint: oss-cn-hangzhou.aliyuncs.com + bucket-name: 1024lab-smart-admin + access-key: + secret-key: + url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ + private-url-expire-seconds: 3600 + +# open api配置 +springdoc: + swagger-ui: + enabled: true # 开关 + doc-expansion: none #关闭展开 + tags-sorter: alpha + server-base-url: + api-docs: + enabled: true # 开关 +knife4j: + enable: true + basic: + enable: false + username: api # Basic认证用户名 + password: 1024 # Basic认证密码 + +# RestTemplate 请求配置 +http: + pool: + max-total: 20 + connect-timeout: 50000 + read-timeout: 50000 + write-timeout: 50000 + keep-alive: 300000 + +# 跨域配置 +access-control-allow-origin: '*' + +# 心跳配置 +heart-beat: + interval-seconds: 300 + +# 热加载配置 +reload: + interval-seconds: 300 + +# sa-token 配置 +sa-token: + # token 名称(同时也是 cookie 名称) + token-name: Authorization + # token 前缀 例如:Bearer + token-prefix: Bearer + # token 有效期(单位:秒) 默认30天(2592000秒),-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: false + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)(jwt模式下恒false) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)(jwt模式下无用) + token-style: simple-uuid + # 是否打开自动续签 (如果此值为true,框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作) + auto-renew: true + # 是否输出操作日志 + is-log: true + # 日志等级(trace、debug、info、warn、error、fatal) + log-level: debug + # 启动时的字符画打印 + is-print: false + # 是否从cookie读取token + is-read-cookie: false + +# SmartJob 定时任务配置(不需要可以直接删除以下配置,详细文档请看:https://www.xxxxxx.com) +smart: + job: + enabled: true + # 任务初始化延迟 默认30秒 可选 + init-delay: 10 + # 定时任务执行线程池数量 默认2 可选 + core-pool-size: 2 + # 数据库配置检测-开关 默认开启 可选(作用是固定间隔读取数据库配置更新任务,关闭后只能重启服务或通过接口修改定时任务,建议开启) + db-refresh-enabled: true + # 数据库配置检测-执行间隔 默认120秒 可选 + db-refresh-interval: 60 +--- # warm-flow工作流配置 +warm-flow: + # 是否开启工作流,默认true + enabled: true + # 是否开启设计器ui + ui: true + # 默认Authorization,如果有多个token,用逗号分隔 + token-name: ${sa-token.token-name} + # 流程状态对应的三元色 + chart-status-color: + ## 未办理 + - 62,62,62 + ## 待办理 + - 255,205,23 + ## 已办理 + - 157,255,0 \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/ip2region.xdb b/smart-flow-api/sa-base/src/main/resources/ip2region.xdb new file mode 100644 index 0000000..9f6502b Binary files /dev/null and b/smart-flow-api/sa-base/src/main/resources/ip2region.xdb differ diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/ChangeLogMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/ChangeLogMapper.xml new file mode 100644 index 0000000..5e31fed --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/ChangeLogMapper.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/CodeGeneratorMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/CodeGeneratorMapper.xml new file mode 100644 index 0000000..106d536 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/CodeGeneratorMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + + + diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/ConfigMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/ConfigMapper.xml new file mode 100644 index 0000000..5c4ee5b --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/ConfigMapper.xml @@ -0,0 +1,22 @@ + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/DataTracerMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/DataTracerMapper.xml new file mode 100644 index 0000000..9810494 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/DataTracerMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/DictDataMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/DictDataMapper.xml new file mode 100644 index 0000000..0a3ae5c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/DictDataMapper.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/DictMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/DictMapper.xml new file mode 100644 index 0000000..65c8b6f --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/DictMapper.xml @@ -0,0 +1,45 @@ + + + + + + + t_dict.dict_id, + t_dict.dict_name, + t_dict.dict_code, + t_dict.remark, + t_dict.disabled_flag, + t_dict.create_time, + t_dict.update_time + + + + + + + + + diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/FeedbackMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/FeedbackMapper.xml new file mode 100644 index 0000000..6d7eb71 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/FeedbackMapper.xml @@ -0,0 +1,26 @@ + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/FileMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/FileMapper.xml new file mode 100644 index 0000000..a583d02 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/FileMapper.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/HeartBeatRecordMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/HeartBeatRecordMapper.xml new file mode 100644 index 0000000..225442c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/HeartBeatRecordMapper.xml @@ -0,0 +1,37 @@ + + + + + + + update t_heart_beat_record + set heart_beat_time = #{heartBeatTime} + + heart_beat_record_id = #{id} + + + + + + + + diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/HelpDocDao.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/HelpDocDao.xml new file mode 100644 index 0000000..e0994d6 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/HelpDocDao.xml @@ -0,0 +1,127 @@ + + + + + + + + + + + + update t_help_doc + set page_view_count = page_view_count + #{pageViewCountIncrease}, + user_view_count = user_view_count + #{userViewCountIncrease} + where help_doc_id = #{helpDocId} + + + + + + + + + + insert into t_help_doc_relation + (relation_id, relation_name, help_doc_id) + values + + ( #{item.relationId} ,#{item.relationName}, #{helpDocId} ) + + + + + delete + from t_help_doc_relation + where help_doc_id = #{helpDocId} + + + + + + + + insert into t_help_doc_view_record (help_doc_id, user_id,user_name, first_ip, first_user_agent, page_view_count) + values (#{helpDocId}, #{userId},#{userName}, #{ip}, #{userAgent}, #{pageViewCount}) + + + update t_help_doc_view_record + set page_view_count = page_view_count + 1, + last_ip = #{ip}, + last_user_agent = #{userAgent} + where help_doc_id = #{helpDocId} + and user_id = #{userId} + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/LoginFailMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/LoginFailMapper.xml new file mode 100644 index 0000000..15d1c31 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/LoginFailMapper.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + delete + from t_login_fail + where user_id = #{userId} + and user_type = #{userType} + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/LoginLogMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/LoginLogMapper.xml new file mode 100644 index 0000000..be1105d --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/LoginLogMapper.xml @@ -0,0 +1,47 @@ + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/MessageMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/MessageMapper.xml new file mode 100644 index 0000000..0512056 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/MessageMapper.xml @@ -0,0 +1,55 @@ + + + + + + + UPDATE t_message + SET read_flag = #{readFlag}, + read_time = now() + WHERE message_id = #{messageId} + AND receiver_user_type = #{receiverUserType} + AND receiver_user_id = #{receiverUserId} + AND read_flag != #{readFlag} + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/OperateLogMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/OperateLogMapper.xml new file mode 100644 index 0000000..0a6b562 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/OperateLogMapper.xml @@ -0,0 +1,73 @@ + + + + + + + + + delete from t_operate_log where operate_log_id in + + #{item} + + + + + + diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/PasswordLogMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/PasswordLogMapper.xml new file mode 100644 index 0000000..84ef798 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/PasswordLogMapper.xml @@ -0,0 +1,28 @@ + + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/ReloadItemMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/ReloadItemMapper.xml new file mode 100644 index 0000000..40fea4c --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/ReloadItemMapper.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/ReloadResultMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/ReloadResultMapper.xml new file mode 100644 index 0000000..99a4fb9 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/ReloadResultMapper.xml @@ -0,0 +1,10 @@ + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/SerialNumberMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/SerialNumberMapper.xml new file mode 100644 index 0000000..eba23ed --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/SerialNumberMapper.xml @@ -0,0 +1,21 @@ + + + + + + update t_serial_number + set + last_number = #{lastNumber}, + last_time = #{lastTime} + where + serial_number_id = #{serialNumberId} + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/SerialNumberRecordMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/SerialNumberRecordMapper.xml new file mode 100644 index 0000000..b59fc53 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/SerialNumberRecordMapper.xml @@ -0,0 +1,32 @@ + + + + + + update t_serial_number_record + set last_number = #{lastNumber}, + count = count + #{count} + where + serial_number_id = #{serialNumberId} + and + record_date = #{recordDate} + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/SmartJobLogMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/SmartJobLogMapper.xml new file mode 100644 index 0000000..29ae945 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/SmartJobLogMapper.xml @@ -0,0 +1,34 @@ + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/SmartJobMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/SmartJobMapper.xml new file mode 100644 index 0000000..9dfbed2 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/SmartJobMapper.xml @@ -0,0 +1,42 @@ + + + + + + update t_smart_job + set deleted_flag = #{deletedFlag} + where job_id = #{jobId} + + + + + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/mapper/support/TableColumnMapper.xml b/smart-flow-api/sa-base/src/main/resources/mapper/support/TableColumnMapper.xml new file mode 100644 index 0000000..1f11c60 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/mapper/support/TableColumnMapper.xml @@ -0,0 +1,18 @@ + + + + + delete + from t_table_column + where user_id = #{userId} + and table_id = #{tableId} + + + + \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/pre/sa-base.yaml b/smart-flow-api/sa-base/src/main/resources/pre/sa-base.yaml new file mode 100644 index 0000000..31f1a35 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/pre/sa-base.yaml @@ -0,0 +1,171 @@ +spring: + # 数据库连接信息 + datasource: + url: jdbc:kingbase8://8.162.3.203:54321/economic_crime_dev?currentSchema=public&clientEncoding=utf8&socketTimeout=30000&loginTimeout=30 + username: dcms_dev + password: dy@2025#dc$ks + driver-class-name: com.kingbase8.Driver + initial-size: 2 + min-idle: 2 + max-active: 10 + max-wait: 60000 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + filters: stat + druid: + username: druid + password: 1024 + login: + enabled: false + method: + pointcut: net.lab1024.sa..*Service.* + + # redis 连接池配置信息 + data: + redis: + database: 1 + host: 127.0.0.1 + port: 6379 + password: + timeout: 10000ms + lettuce: + pool: + max-active: 5 + min-idle: 1 + max-idle: 3 + max-wait: 30000ms + + # 邮件,置以SSL的方式发送, 这个需要使用这种方式并且端口是465 + mail: + host: smtp.163.com + port: 465 + username: lab1024@163.com + password: LAB1024LAB + properties: + mail: + smtp: + auth: true + ssl: + enable: true + socketFactory: + class: com.sun.mail.util.MailSSLSocketFactory + fallback: false + debug: false + + # json序列化相关配置 + jackson: + serialization: + write-enums-using-to-string: true + write-dates-as-timestamps: false + deserialization: + read-enums-using-to-string: true + fail-on-unknown-properties: false + default-property-inclusion: always + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + + # 缓存实现类型 + cache: + type: caffeine + +# tomcat 配置,主要用于 配置 访问日志(便于将来排查错误) +server: + tomcat: + basedir: ${project.log-directory}/tomcat-logs + connection-timeout: -1 + accesslog: + enabled: true + max-days: 7 + pattern: "%t %{X-Forwarded-For}i %a %r %s (%D ms) %I (%B byte)" + +# 文件上传 配置 +file: + storage: + mode: local + local: + upload-path: /home/smart_admin_v3/upload/ #文件上传目录 + url-prefix: + cloud: + region: oss-cn-hangzhou + endpoint: oss-cn-hangzhou.aliyuncs.com + bucket-name: 1024lab-smart-admin + access-key: + secret-key: + url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ + private-url-expire-seconds: 3600 + +# open api配置 +springdoc: + swagger-ui: + enabled: true # 开关 + doc-expansion: none #关闭展开 + tags-sorter: alpha + server-base-url: + api-docs: + enabled: true # 开关 +knife4j: + enable: true + basic: + enable: false + username: api # Basic认证用户名 + password: 1024 # Basic认证密码 + +# RestTemplate 请求配置 +http: + pool: + max-total: 20 + connect-timeout: 50000 + read-timeout: 50000 + write-timeout: 50000 + keep-alive: 300000 + +# 跨域配置 +access-control-allow-origin: '*' + +# 心跳配置 +heart-beat: + interval-seconds: 300 + +# 热加载配置 +reload: + interval-seconds: 300 + +# sa-token 配置 +sa-token: + # token 名称(同时也是 cookie 名称) + token-name: Authorization + # token 前缀 例如:Bear + token-prefix: Bearer + # token 有效期(单位:秒) 默认30天(2592000秒),-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: false + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)(jwt模式下恒false) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)(jwt模式下无用) + token-style: simple-uuid + # 是否打开自动续签 (如果此值为true,框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作) + auto-renew: true + # 是否输出操作日志 + is-log: true + # 日志等级(trace、debug、info、warn、error、fatal) + log-level: debug + # 启动时的字符画打印 + is-print: false + # 是否从cookie读取token + is-read-cookie: false + +# SmartJob 定时任务配置(不需要可以直接删除以下配置,详细文档请看:https://www.xxxxxx.com) +smart: + job: + enabled: true + # 任务初始化延迟 默认30秒 可选 + init-delay: 10 + # 定时任务执行线程池数量 默认2 可选 + core-pool-size: 2 + # 数据库配置检测-开关 默认开启 可选(作用是固定间隔读取数据库配置更新任务,关闭后只能重启服务或通过接口修改定时任务,建议开启) + db-refresh-enabled: true + # 数据库配置检测-执行间隔 默认120秒 可选 + db-refresh-interval: 60 \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/prod/sa-base.yaml b/smart-flow-api/sa-base/src/main/resources/prod/sa-base.yaml new file mode 100644 index 0000000..7309c20 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/prod/sa-base.yaml @@ -0,0 +1,167 @@ +spring: + # 数据库连接信息 + datasource: + url: jdbc:kingbase8://8.162.3.203:54321/economic_crime_dev?currentSchema=public&clientEncoding=utf8&socketTimeout=30000&loginTimeout=30 + username: dcms_dev + password: dy@2025#dc$ks + driver-class-name: com.kingbase8.Driver + initial-size: 10 + min-idle: 10 + max-active: 100 + max-wait: 60000 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + filters: stat + druid: + username: druid + password: 1024lab + login: + enabled: false + method: + pointcut: net.lab1024.sa..*Service.* + + # redis 连接池配置信息 + data: + redis: + database: 1 + host: 127.0.0.1 + port: 6379 + password: + timeout: 10000ms + lettuce: + pool: + max-active: 100 + min-idle: 10 + max-idle: 50 + max-wait: 30000ms + # 邮件,置以SSL的方式发送, 这个需要使用这种方式并且端口是465 + mail: + host: smtp.163.com + port: 465 + username: lab1024@163.com + password: LAB1024LAB + properties: + mail: + smtp: + auth: true + ssl: + enable: true + socketFactory: + class: com.sun.mail.util.MailSSLSocketFactory + fallback: false + debug: false + + # json序列化相关配置 + jackson: + serialization: + write-enums-using-to-string: true + write-dates-as-timestamps: false + deserialization: + read-enums-using-to-string: true + fail-on-unknown-properties: false + default-property-inclusion: always + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + + # 缓存实现类型 + cache: + type: caffeine + +# tomcat 配置,主要用于 配置 访问日志(便于将来排查错误) +server: + tomcat: + basedir: ${project.log-directory}/tomcat-logs + accesslog: + enabled: true + max-days: 30 + pattern: "%t %{X-Forwarded-For}i %a %r %s (%D ms) %I (%B byte)" + + +# 文件上传 配置 +file: + storage: + mode: local + local: + upload-path: /home/smart_admin_v3/upload/ #文件上传目录 + url-prefix: + cloud: + region: oss-cn-hangzhou + endpoint: oss-cn-hangzhou.aliyuncs.com + bucket-name: 1024lab-smart-admin + access-key: + secret-key: + url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ + private-url-expire-seconds: 3600 + + +# open api配置 +springdoc: + swagger-ui: + enabled: true # 开关 + doc-expansion: none #关闭展开 + tags-sorter: alpha + api-docs: + enabled: true # 开关 +knife4j: + enable: true + basic: + enable: true + username: api # Basic认证用户名 + password: 1024 # Basic认证密码 + +# RestTemplate 请求配置 +http: + pool: + max-total: 100 + connect-timeout: 50000 + read-timeout: 50000 + write-timeout: 50000 + keep-alive: 300000 + +# 心跳配置 +heart-beat: + interval-seconds: 60 + +# 热加载配置 +reload: + interval-seconds: 60 + +# sa-token 配置 +sa-token: + # token 名称(同时也是 cookie 名称) + token-name: Authorization + # token 前缀 例如:Bear + token-prefix: Bearer + # token 有效期(单位:秒) 默认30天(2592000秒),-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: false + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)(jwt模式下恒false) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)(jwt模式下无用) + token-style: simple-uuid + # 是否打开自动续签 (如果此值为true,框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作) + auto-renew: true + # 是否输出操作日志 + is-log: false + # 日志等级(trace、debug、info、warn、error、fatal) + log-level: warn + # 启动时的字符画打印 + is-print: false + # 是否从cookie读取token + is-read-cookie: false + +# SmartJob 定时任务配置(不需要可以直接删除以下配置,详细文档请看:https://www.xxxxxx.com) +smart: + job: + enabled: true + # 任务初始化延迟 默认30秒 可选 + init-delay: 10 + # 定时任务执行线程池数量 默认2 可选 + core-pool-size: 2 + # 数据库配置检测-开关 默认开启 可选(作用是固定间隔读取数据库配置更新任务,关闭后只能重启服务或通过接口修改定时任务,建议开启) + db-refresh-enabled: true + # 数据库配置检测-执行间隔 默认120秒 可选 + db-refresh-interval: 60 \ No newline at end of file diff --git a/smart-flow-api/sa-base/src/main/resources/test/sa-base.yaml b/smart-flow-api/sa-base/src/main/resources/test/sa-base.yaml new file mode 100644 index 0000000..5352c66 --- /dev/null +++ b/smart-flow-api/sa-base/src/main/resources/test/sa-base.yaml @@ -0,0 +1,170 @@ +spring: + # 数据库连接信息 + datasource: + url: jdbc:kingbase8://8.162.3.203:54321/economic_crime_dev?currentSchema=public&clientEncoding=utf8&socketTimeout=30000&loginTimeout=30 + username: dcms_dev + password: dy@2025#dc$ks + driver-class-name: com.kingbase8.Driver + initial-size: 2 + min-idle: 2 + max-active: 10 + max-wait: 60000 + time-between-eviction-runs-millis: 60000 + min-evictable-idle-time-millis: 300000 + filters: stat + druid: + username: druid + password: 1024 + login: + enabled: false + method: + pointcut: net.lab1024.sa..*Service.* + + # redis 连接池配置信息 + data: + redis: + database: 1 + host: 127.0.0.1 + port: 6379 + password: + timeout: 10000ms + lettuce: + pool: + max-active: 5 + min-idle: 1 + max-idle: 3 + max-wait: 30000ms + + # 邮件,置以SSL的方式发送, 这个需要使用这种方式并且端口是465 + mail: + host: smtp.163.com + port: 465 + username: lab1024@163.com + password: LAB1024LAB + properties: + mail: + smtp: + auth: true + ssl: + enable: true + socketFactory: + class: com.sun.mail.util.MailSSLSocketFactory + fallback: false + debug: false + + # json序列化相关配置 + jackson: + serialization: + write-enums-using-to-string: true + write-dates-as-timestamps: false + deserialization: + read-enums-using-to-string: true + fail-on-unknown-properties: false + default-property-inclusion: always + date-format: yyyy-MM-dd HH:mm:ss + time-zone: GMT+8 + + # 缓存实现类型 + cache: + type: caffeine + +# tomcat 配置,主要用于 配置 访问日志(便于将来排查错误) +server: + tomcat: + basedir: ${project.log-directory}/tomcat-logs + accesslog: + enabled: true + max-days: 7 + pattern: "%t %{X-Forwarded-For}i %a %r %s (%D ms) %I (%B byte)" + +# 文件上传 配置 +file: + storage: + mode: local + local: + upload-path: /home/smart_admin_v3/upload/ #文件上传目录 + url-prefix: + cloud: + region: oss-cn-hangzhou + endpoint: oss-cn-hangzhou.aliyuncs.com + bucket-name: 1024lab-smart-admin + access-key: + secret-key: + url-prefix: https://${file.storage.cloud.bucket-name}.${file.storage.cloud.endpoint}/ + private-url-expire-seconds: 3600 + +# open api配置 +springdoc: + swagger-ui: + enabled: true # 开关 + doc-expansion: none #关闭展开 + tags-sorter: alpha + server-base-url: + api-docs: + enabled: true # 开关 +knife4j: + enable: true + basic: + enable: false + username: api # Basic认证用户名 + password: 1024 # Basic认证密码 + +# RestTemplate 请求配置 +http: + pool: + max-total: 20 + connect-timeout: 50000 + read-timeout: 50000 + write-timeout: 50000 + keep-alive: 300000 + +# 跨域配置 +access-control-allow-origin: '*' + +# 心跳配置 +heart-beat: + interval-seconds: 300 + +# 热加载配置 +reload: + interval-seconds: 300 + +# sa-token 配置 +sa-token: + # token 名称(同时也是 cookie 名称) + token-name: Authorization + # token 前缀 例如:Bear + token-prefix: Bearer + # token 有效期(单位:秒) 默认30天(2592000秒),-1 代表永久有效 + timeout: 2592000 + # token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结 + active-timeout: -1 + # 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录) + is-concurrent: false + # 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)(jwt模式下恒false) + is-share: false + # token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)(jwt模式下无用) + token-style: simple-uuid + # 是否打开自动续签 (如果此值为true,框架会在每次直接或间接调用 getLoginId() 时进行一次过期检查与续签操作) + auto-renew: true + # 是否输出操作日志 + is-log: true + # 日志等级(trace、debug、info、warn、error、fatal) + log-level: debug + # 启动时的字符画打印 + is-print: false + # 是否从cookie读取token + is-read-cookie: false + +# SmartJob 定时任务配置(不需要可以直接删除以下配置,详细文档请看:https://www.xxxxxx.com) +smart: + job: + enabled: true + # 任务初始化延迟 默认30秒 可选 + init-delay: 10 + # 定时任务执行线程池数量 默认2 可选 + core-pool-size: 2 + # 数据库配置检测-开关 默认开启 可选(作用是固定间隔读取数据库配置更新任务,关闭后只能重启服务或通过接口修改定时任务,建议开启) + db-refresh-enabled: true + # 数据库配置检测-执行间隔 默认120秒 可选 + db-refresh-interval: 60 \ No newline at end of file diff --git a/smart-flow-api/scripts/install-kingbase8-to-local-m2.sh b/smart-flow-api/scripts/install-kingbase8-to-local-m2.sh new file mode 100755 index 0000000..605bc23 --- /dev/null +++ b/smart-flow-api/scripts/install-kingbase8-to-local-m2.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash +# Installs the KingbaseES JDBC driver into the local Maven repository as +# cn.com.kingbase8:kingbase8:${KINGBASE8_VERSION:-8.6.0} +# +# The artifact is not published to Maven Central; use the jar shipped with your +# Kingbase server/client (often named like kingbase8-*.jar). +# +# If Maven cached a failed resolution, clear it first: +# rm -rf ~/.m2/repository/cn/com/kingbase8 +# +# Usage: +# ./scripts/install-kingbase8-to-local-m2.sh /path/to/kingbase8-8.6.0.jar +# KINGBASE8_JAR=/path/to/kingbase8.jar KINGBASE8_VERSION=8.6.0 ./scripts/install-kingbase8-to-local-m2.sh + +set -euo pipefail + +JAR="${1:-${KINGBASE8_JAR:-}}" +if [[ -z "$JAR" || ! -f "$JAR" ]]; then + echo "Usage: $0 /path/to/kingbase8.jar" >&2 + echo " or: KINGBASE8_JAR=/path/to/kingbase8.jar $0" >&2 + exit 1 +fi + +VERSION="${KINGBASE8_VERSION:-8.6.0}" + +if ! command -v mvn >/dev/null 2>&1; then + echo "mvn not found in PATH. Use IntelliJ bundled Maven or add Maven to PATH." >&2 + exit 1 +fi + +mvn -q install:install-file \ + -Dfile="$JAR" \ + -DgroupId=cn.com.kingbase8 \ + -DartifactId=kingbase8 \ + -Dversion="$VERSION" \ + -Dpackaging=jar + +echo "Installed cn.com.kingbase8:kingbase8:${VERSION} from: $JAR" + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" +mkdir -p "$REPO_ROOT/sa-base/lib" +cp -f "$JAR" "$REPO_ROOT/sa-base/lib/kingbase8.jar" +echo "Also copied to $REPO_ROOT/sa-base/lib/kingbase8.jar (required for sa-admin system dependency / IDE run)" diff --git a/smart-flow-web/.env.development b/smart-flow-web/.env.development new file mode 100644 index 0000000..dbe7243 --- /dev/null +++ b/smart-flow-web/.env.development @@ -0,0 +1,5 @@ +NODE_ENV=development +VITE_APP_TITLE='铜陵市公安局经侦案件智慧管理平台(Dev)' +VITE_APP_API_URL='http://127.0.0.1:1024' +# 客户端id +VITE_APP_CLIENT_ID = 'e5cd7e4891bf95d1d19206ce24a7b32e' \ No newline at end of file diff --git a/smart-flow-web/.env.localhost b/smart-flow-web/.env.localhost new file mode 100644 index 0000000..63bf899 --- /dev/null +++ b/smart-flow-web/.env.localhost @@ -0,0 +1,3 @@ +NODE_ENV=development +VITE_APP_TITLE='铜陵市公安局经侦案件智慧管理平台(Local)' +VITE_APP_API_URL='http://127.0.0.1:1024' diff --git a/smart-flow-web/.env.pre b/smart-flow-web/.env.pre new file mode 100644 index 0000000..b480bca --- /dev/null +++ b/smart-flow-web/.env.pre @@ -0,0 +1,3 @@ +NODE_ENV=production +VITE_APP_TITLE='铜陵市公安局经侦案件智慧管理平台预发布环境(Pre)' +VITE_APP_API_URL='https://preview.smartadmin.vip/smart-admin-api' \ No newline at end of file diff --git a/smart-flow-web/.env.production b/smart-flow-web/.env.production new file mode 100644 index 0000000..b5f9f13 --- /dev/null +++ b/smart-flow-web/.env.production @@ -0,0 +1,3 @@ +NODE_ENV=production +VITE_APP_TITLE='铜陵市公安局经侦案件智慧管理平台' +VITE_APP_API_URL='https://preview.smartadmin.vip/smart-admin-api' \ No newline at end of file diff --git a/smart-flow-web/.env.test b/smart-flow-web/.env.test new file mode 100644 index 0000000..ccf4cd2 --- /dev/null +++ b/smart-flow-web/.env.test @@ -0,0 +1,3 @@ +NODE_ENV=production +VITE_APP_TITLE='铜陵市公安局经侦案件智慧管理平台测试环境(Test)' +VITE_APP_API_URL='http://127.0.0.1:1024' diff --git a/smart-flow-web/.eslintignore b/smart-flow-web/.eslintignore new file mode 100644 index 0000000..78e1638 --- /dev/null +++ b/smart-flow-web/.eslintignore @@ -0,0 +1,18 @@ + +*.sh +node_modules +lib +*.md +*.woff +*.ttf +.vscode +.idea +dist +public +/docs +.husky +.local +.localhost +/bin +Dockerfile +src/assets diff --git a/smart-flow-web/.eslintrc.cjs b/smart-flow-web/.eslintrc.cjs new file mode 100644 index 0000000..81e7acc --- /dev/null +++ b/smart-flow-web/.eslintrc.cjs @@ -0,0 +1,66 @@ +/* + * @Description: + * @Author: zhuoda + * @Date: 2021-11-05 + * @LastEditTime: 2022-07-05 + * @LastEditors: zhuoda + */ +module.exports = { + root: true, //此项是用来告诉eslint找当前配置文件不能往父级查找 + env: { + browser: true, + es2021: true, + node: true, + }, + parser: 'vue-eslint-parser', //使用vue-eslint-parser 来解析vue文件中的 template和script + parserOptions: { + ecmaVersion: 12, // 默认情况下,ESLint使用的是ECMAScript5语法,此处我们设置的选项是 es12 + sourceType: 'module', // 指定js导入的方式 + }, + extends: ['plugin:vue/vue3-essential', 'eslint:recommended', 'plugin:vue/base'], + globals: { + defineProps: 'readonly', + defineEmits: 'readonly', + defineExpose: 'readonly', + withDefaults: 'readonly', + }, + plugins: ['vue'], + rules: { + 'no-unused-vars': [ + 'error', + // we are only using this rule to check for unused arguments since TS + // catches unused variables but not args. + { varsIgnorePattern: '.*', args: 'none' }, + ], + 'space-before-function-paren': 'off', + + 'vue/attributes-order': 'off', + 'vue/one-component-per-file': 'off', + 'vue/html-closing-bracket-newline': 'off', + 'vue/max-attributes-per-line': 'off', + 'vue/multiline-html-element-content-newline': 'off', + 'vue/singleline-html-element-content-newline': 'off', + 'vue/attribute-hyphenation': 'off', + 'vue/require-default-prop': 'off', + 'vue/multi-word-component-names': [ + 'error', + { + ignores: ['index'], //需要忽略的组件名 + }, + ], + 'vue/html-self-closing': [ + 'error', + { + html: { + void: 'always', + normal: 'never', + component: 'always', + }, + svg: 'always', + math: 'always', + }, + ], + // Enable vue/script-setup-uses-vars rule + 'vue/script-setup-uses-vars': 'error', + }, +}; diff --git a/smart-flow-web/.gitignore b/smart-flow-web/.gitignore new file mode 100644 index 0000000..61425d5 --- /dev/null +++ b/smart-flow-web/.gitignore @@ -0,0 +1,7 @@ +node_modules +.DS_Store +**/.DS_Store +dist +dist-ssr +*.local +.idea diff --git a/smart-flow-web/.prettierrc.cjs b/smart-flow-web/.prettierrc.cjs new file mode 100644 index 0000000..d1c4ba8 --- /dev/null +++ b/smart-flow-web/.prettierrc.cjs @@ -0,0 +1,30 @@ +/* + * 代码格式化配置 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-12 14:44:18 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +module.exports = { + printWidth: 150, // 每行代码长度(默认80) + tabWidth: 2, // 缩进空格数 + useTabs: false, //不用tab缩进 + semi: true, //// 在语句末尾打印分号 + singleQuote: true, // 使用单引号而不是双引号 + vueIndentScriptAndStyle: true, //Vue文件脚本和样式标签缩进 + quoteProps: 'as-needed', // 更改引用对象属性的时间 可选值"" + jsxSingleQuote: true, // 在JSX中使用单引号而不是双引号 + trailingComma: 'es5', //多行时尽可能打印尾随逗号。(例如,单行数组永远不会出现逗号结尾。) 可选值"",默认none + bracketSpacing: true, // 在对象文字中的括号之间打印空格 + jsxBracketSameLine: false, //jsx 标签的反尖括号需要换行 + arrowParens: 'always', // 在单独的箭头函数参数周围包括括号 always:(x) => x \ avoid:x => x + rangeStart: 0, // 这两个选项可用于格式化以给定字符偏移量(分别包括和不包括)开始和结束的代码 + rangeEnd: Infinity, + requirePragma: false, // 指定要使用的解析器,不需要写文件开头的 @prettier + insertPragma: false, // 不需要自动在文件开头插入 @prettier + proseWrap: 'preserve', // 使用默认的折行标准 always\never\preserve + htmlWhitespaceSensitivity: 'css', // 指定HTML文件的全局空格敏感度 css\strict\ignore + endOfLine: 'auto', // 因为prettier的规范和eslint的换行规则不同,所以这个必须配置。要不然每次打开文件都会有一堆的警告;换行符使用 lf 结尾是 可选值" + + + + + + + + %VITE_APP_TITLE% + + + +

+ + + diff --git a/smart-flow-web/jsconfig.json b/smart-flow-web/jsconfig.json new file mode 100644 index 0000000..c97f579 --- /dev/null +++ b/smart-flow-web/jsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "target": "ES6", + "jsx":"preserve", + "module": "commonjs", + "allowSyntheticDefaultImports": true, + "baseUrl": "./", + "paths": { + "/@/*": [ + "src/*" + ] + } + }, + "exclude": [ + "node_modules" + ] +} \ No newline at end of file diff --git a/smart-flow-web/package-lock.json b/smart-flow-web/package-lock.json new file mode 100644 index 0000000..daecf03 --- /dev/null +++ b/smart-flow-web/package-lock.json @@ -0,0 +1,7244 @@ +{ + "name": "SmartFlow", + "version": "3.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "SmartFlow", + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "@wangeditor-next/editor": "5.6.34", + "@wangeditor-next/editor-for-vue": "5.1.14", + "ant-design-vue": "4.2.5", + "axios": "1.6.8", + "clipboard": "2.0.11", + "crypto-js": "4.1.1", + "dayjs": "1.10.5", + "decimal.js": "10.3.1", + "diff": "5.2.0", + "diff2html": "3.4.47", + "echarts": "5.4.3", + "highlight.js": "11.8.0", + "lodash": "4.17.21", + "lunar-javascript": "1.6.12", + "mitt": "3.0.1", + "nprogress": "0.2.0", + "pinia": "2.1.7", + "sm-crypto": "0.3.13", + "sortablejs": "1.15.0", + "ua-parser-js": "1.0.35", + "uuid": "^11.1.0", + "v-viewer": "~1.6.4", + "vue": "3.4.27", + "vue-i18n": "9.13.1", + "vue-router": "4.3.2", + "vue3-json-viewer": "2.2.2" + }, + "devDependencies": { + "@vitejs/plugin-vue": "5.0.4", + "@vue/compiler-sfc": "3.4.27", + "eslint": "^8.16.0", + "eslint-config-prettier": "~9.0.0", + "eslint-plugin-prettier": "~5.0.0", + "eslint-plugin-vue": "~9.17.0", + "less": "~4.2.0", + "less-loader": "~11.1.3", + "prettier": "~3.0.2", + "rimraf": "~5.0.1", + "stylelint": "~14.8.5", + "stylelint-config-prettier": "~9.0.3", + "stylelint-config-standard": "~25.0.0", + "stylelint-order": "~5.0.0", + "terser": "~5.29.2", + "vite": "5.2.12", + "vue-eslint-parser": "~9.4.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ant-design/colors": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-6.0.0.tgz", + "integrity": "sha512-qAZRvPzfdWHtfameEGP2Qvuf838NhergR35o+EuVyB5XvSA98xod5r4utvi4TJ3ywmevm290g9nsCG5MryrdWQ==", + "license": "MIT", + "dependencies": { + "@ctrl/tinycolor": "^3.4.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.4.2.tgz", + "integrity": "sha512-vHbT+zJEVzllwP+CM+ul7reTEfBR0vgxFe7+lREAsAA7YGsYpboiq2sQNeQeRvh09GfQgs/GyFEvZpJ9cLXpXA==", + "license": "MIT" + }, + "node_modules/@ant-design/icons-vue": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons-vue/-/icons-vue-7.0.1.tgz", + "integrity": "sha512-eCqY2unfZK6Fe02AwFlDHLfoyEFreP6rBwAZMIJ1LugmfMiVgwWDYlp1YsRugaPtICYOabV1iWxXdP12u9U43Q==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-svg": "^4.2.1" + }, + "peerDependencies": { + "vue": ">=3.0.3" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz", + "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.2", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz", + "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@emotion/hash": { + "version": "0.9.2", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz", + "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz", + "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==", + "license": "MIT" + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@intlify/core-base": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.13.1.tgz", + "integrity": "sha512-+bcQRkJO9pcX8d0gel9ZNfrzU22sZFSA0WVhfXrf5jdJOS24a+Bp8pozuS9sBI9Hk/tGz83pgKfmqcn/Ci7/8w==", + "license": "MIT", + "dependencies": { + "@intlify/message-compiler": "9.13.1", + "@intlify/shared": "9.13.1" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/message-compiler": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.13.1.tgz", + "integrity": "sha512-SKsVa4ajYGBVm7sHMXd5qX70O2XXjm55zdZB3VeMFCvQyvLew/dLvq3MqnaIsTMF1VkkOb9Ttr6tHcMlyPDL9w==", + "license": "MIT", + "dependencies": { + "@intlify/shared": "9.13.1", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@intlify/shared": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.13.1.tgz", + "integrity": "sha512-u3b6BKGhE6j/JeRU6C/RL2FgyJfy6LakbtfeVF8fJXURpZZTzfh3e05J0bu0XPw447Q6/WUp3C4ajv4TMS4YsQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@pkgr/core": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.1.2.tgz", + "integrity": "sha512-fdDH1LSGfZdTH2sxdpVMw31BanV28K/Gry0cVFxaNP77neJSkd82mM8ErPNYs9e+0O7SdHBLTDzDgwUuy18RnQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.4.tgz", + "integrity": "sha512-F5QXMSiFebS9hKZj02XhWLLnRpJ3B3AROP0tWbFBSj+6kCbg5m9j5JoHKd4mmSVy5mS/IMQloYgYxCuJC0fxEQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.4.tgz", + "integrity": "sha512-GxxTKApUpzRhof7poWvCJHRF51C67u1R7D6DiluBE8wKU1u5GWE8t+v81JvJYtbawoBFX1hLv5Ei4eVjkWokaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.4.tgz", + "integrity": "sha512-tua0TaJxMOB1R0V0RS1jFZ/RpURFDJIOR2A6jWwQeawuFyS4gBW+rntLRaQd0EQ4bd6Vp44Z2rXW+YYDBsj6IA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.4.tgz", + "integrity": "sha512-CSKq7MsP+5PFIcydhAiR1K0UhEI1A2jWXVKHPCBZ151yOutENwvnPocgVHkivu2kviURtCEB6zUQw0vs8RrhMg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.4.tgz", + "integrity": "sha512-+O8OkVdyvXMtJEciu2wS/pzm1IxntEEQx3z5TAVy4l32G0etZn+RsA48ARRrFm6Ri8fvqPQfgrvNxSjKAbnd3g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.4.tgz", + "integrity": "sha512-Iw3oMskH3AfNuhU0MSN7vNbdi4me/NiYo2azqPz/Le16zHSa+3RRmliCMWWQmh4lcndccU40xcJuTYJZxNo/lw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.4.tgz", + "integrity": "sha512-EIPRXTVQpHyF8WOo219AD2yEltPehLTcTMz2fn6JsatLYSzQf00hj3rulF+yauOlF9/FtM2WpkT/hJh/KJFGhA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.4.tgz", + "integrity": "sha512-J3Yh9PzzF1Ovah2At+lHiGQdsYgArxBbXv/zHfSyaiFQEqvNv7DcW98pCrmdjCZBrqBiKrKKe2V+aaSGWuBe/w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.4.tgz", + "integrity": "sha512-BFDEZMYfUvLn37ONE1yMBojPxnMlTFsdyNoqncT0qFq1mAfllL+ATMMJd8TeuVMiX84s1KbcxcZbXInmcO2mRg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.4.tgz", + "integrity": "sha512-pc9EYOSlOgdQ2uPl1o9PF6/kLSgaUosia7gOuS8mB69IxJvlclko1MECXysjs5ryez1/5zjYqx3+xYU0TU6R1A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.4.tgz", + "integrity": "sha512-NxnomyxYerDh5n4iLrNa+sH+Z+U4BMEE46V2PgQ/hoB909i8gV1M5wPojWg9fk1jWpO3IQnOs20K4wyZuFLEFQ==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.4.tgz", + "integrity": "sha512-nbJnQ8a3z1mtmrwImCYhc6BGpThAyYVRQxw9uKSKG4wR6aAYno9sVjJ0zaZcW9BPJX1GbrDPf+SvdWjgTuDmnw==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.4.tgz", + "integrity": "sha512-2EU6acNrQLd8tYvo/LXW535wupT3m6fo7HKo6lr7ktQoItxTyOL1ZCR/GfGCuXl2vR+zmfI6eRXkSemafv+iVg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.4.tgz", + "integrity": "sha512-WeBtoMuaMxiiIrO2IYP3xs6GMWkJP2C0EoT8beTLkUPmzV1i/UcOSVw1d5r9KBODtHKilG5yFxsGRnBbK3wJ4A==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.4.tgz", + "integrity": "sha512-FJHFfqpKUI3A10WrWKiFbBZ7yVbGT4q4B5o1qKFFojqpaYoh9LrQgqWCmmcxQzVSXYtyB5bzkXrYzlHTs21MYA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.4.tgz", + "integrity": "sha512-mcEl6CUT5IAUmQf1m9FYSmVqCJlpQ8r8eyftFUHG8i9OhY7BkBXSUdnLH5DOf0wCOjcP9v/QO93zpmF1SptCCw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.4.tgz", + "integrity": "sha512-ynt3JxVd2w2buzoKDWIyiV1pJW93xlQic1THVLXilz429oijRpSHivZAgp65KBu+cMcgf1eVVjdnTLvPxgCuoQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.4.tgz", + "integrity": "sha512-Boiz5+MsaROEWDf+GGEwF8VMHGhlUoQMtIPjOgA5fv4osupqTVnJteQNKJwUcnUog2G55jYXH7KZFFiJe0TEzQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.4.tgz", + "integrity": "sha512-+qfSY27qIrFfI/Hom04KYFw3GKZSGU4lXus51wsb5EuySfFlWRwjkKWoE9emgRw/ukoT4Udsj4W/+xxG8VbPKg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.4.tgz", + "integrity": "sha512-VpTfOPHgVXEBeeR8hZ2O0F3aSso+JDWqTWmTmzcQKted54IAdUVbxE+j/MVxUsKa8L20HJhv3vUezVPoquqWjA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.4.tgz", + "integrity": "sha512-IPOsh5aRYuLv/nkU51X10Bf75Bsf6+gZdx1X+QP5QM6lIJFHHqbHLG0uJn/hWthzo13UAc2umiUorqZy3axoZg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.4.tgz", + "integrity": "sha512-4QzE9E81OohJ/HKzHhsqU+zcYYojVOXlFMs1DdyMT6qXl/niOH7AVElmmEdUNHHS/oRkc++d5k6Vy85zFs0DEw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.4.tgz", + "integrity": "sha512-zTPgT1YuHHcd+Tmx7h8aml0FWFVelV5N54oHow9SLj+GfoDy/huQ+UV396N/C7KpMDMiPspRktzM1/0r1usYEA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.4.tgz", + "integrity": "sha512-DRS4G7mi9lJxqEDezIkKCaUIKCrLUUDCUaCsTPCi/rtqaC6D/jjwslMQyiDU50Ka0JKpeXeRBFBAXwArY52vBw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.4.tgz", + "integrity": "sha512-QVTUovf40zgTqlFVrKA1uXMVvU2QWEFWfAH8Wdc48IxLvrJMQVMBRjuQyUpzZCDkakImib9eVazbWlC6ksWtJw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@simonwep/pickr": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@simonwep/pickr/-/pickr-1.8.2.tgz", + "integrity": "sha512-/l5w8BIkrpP6n1xsetx9MWPWlU6OblN5YgZZphxan0Tq4BByTCETL6lyIeY8lagalS2Nbt4F2W034KHLIiunKA==", + "license": "MIT", + "dependencies": { + "core-js": "^3.15.1", + "nanopop": "^2.1.0" + } + }, + "node_modules/@transloadit/prettier-bytes": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/@transloadit/prettier-bytes/-/prettier-bytes-0.0.7.tgz", + "integrity": "sha512-VeJbUb0wEKbcwaSlj5n+LscBl9IPgLPkHVGBkh00cztv6X4L/TJXK58LzFuBKX7/GAfiGhIwH67YTLTlzvIzBA==", + "license": "MIT" + }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@types/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-zx2/Gg0Eg7gwEiOIIh5w9TrhKKTeQh7CPCOPNc0el4pLSwzebA8SmnHwZs2dWlLONvyulykSwGSQxQHLhjGLvQ==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.8.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.8.0.tgz", + "integrity": "sha512-TCFSk8IZh+iLX1xtksoBVtdmgL+1IX0fC9BeU4QqFSuNdN/K+HUlhqOzEmSYYpZUVsLYcPqc9KX+60iDuninSQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "undici-types": ">=7.24.0 <7.24.7" + } + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/parse-json": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", + "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", + "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/@uppy/companion-client": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/@uppy/companion-client/-/companion-client-2.2.2.tgz", + "integrity": "sha512-5mTp2iq97/mYSisMaBtFRry6PTgZA6SIL7LePteOV5x0/DxKfrZW3DEiQERJmYpHzy7k8johpm2gHnEKto56Og==", + "license": "MIT", + "dependencies": { + "@uppy/utils": "^4.1.2", + "namespace-emitter": "^2.0.1" + } + }, + "node_modules/@uppy/core": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/@uppy/core/-/core-2.3.4.tgz", + "integrity": "sha512-iWAqppC8FD8mMVqewavCz+TNaet6HPXitmGXpGGREGrakZ4FeuWytVdrelydzTdXx6vVKkOmI2FLztGg73sENQ==", + "license": "MIT", + "dependencies": { + "@transloadit/prettier-bytes": "0.0.7", + "@uppy/store-default": "^2.1.1", + "@uppy/utils": "^4.1.3", + "lodash.throttle": "^4.1.1", + "mime-match": "^1.0.2", + "namespace-emitter": "^2.0.1", + "nanoid": "^3.1.25", + "preact": "^10.5.13" + } + }, + "node_modules/@uppy/core/node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/@uppy/store-default": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@uppy/store-default/-/store-default-2.1.1.tgz", + "integrity": "sha512-xnpTxvot2SeAwGwbvmJ899ASk5tYXhmZzD/aCFsXePh/v8rNvR2pKlcQUH7cF/y4baUGq3FHO/daKCok/mpKqQ==", + "license": "MIT" + }, + "node_modules/@uppy/utils": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/@uppy/utils/-/utils-4.1.3.tgz", + "integrity": "sha512-nTuMvwWYobnJcytDO3t+D6IkVq/Qs4Xv3vyoEZ+Iaf8gegZP+rEyoaFT2CK5XLRMienPyqRqNbIfRuFaOWSIFw==", + "license": "MIT", + "dependencies": { + "lodash.throttle": "^4.1.1" + } + }, + "node_modules/@uppy/xhr-upload": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@uppy/xhr-upload/-/xhr-upload-2.1.3.tgz", + "integrity": "sha512-YWOQ6myBVPs+mhNjfdWsQyMRWUlrDLMoaG7nvf/G6Y3GKZf8AyjFDjvvJ49XWQ+DaZOftGkHmF1uh/DBeGivJQ==", + "license": "MIT", + "dependencies": { + "@uppy/companion-client": "^2.2.2", + "@uppy/utils": "^4.1.2", + "nanoid": "^3.1.25" + }, + "peerDependencies": { + "@uppy/core": "^2.3.3" + } + }, + "node_modules/@uppy/xhr-upload/node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz", + "integrity": "sha512-WS3hevEszI6CEVEx28F8RjTX97k3KsrcY6kvTg7+Whm5y3oYvcqzVeGCU3hxSAn4uY2CLCkeokkGKpoctccilQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" + } + }, + "node_modules/@vue/compiler-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", + "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.4", + "@vue/shared": "3.4.27", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", + "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-core": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/compiler-sfc": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", + "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.24.4", + "@vue/compiler-core": "3.4.27", + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.38", + "source-map-js": "^1.2.0" + } + }, + "node_modules/@vue/compiler-ssr": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", + "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "license": "MIT" + }, + "node_modules/@vue/reactivity": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", + "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", + "license": "MIT", + "dependencies": { + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/runtime-core": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", + "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", + "license": "MIT", + "dependencies": { + "@vue/reactivity": "3.4.27", + "@vue/shared": "3.4.27" + } + }, + "node_modules/@vue/runtime-dom": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", + "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", + "license": "MIT", + "dependencies": { + "@vue/runtime-core": "3.4.27", + "@vue/shared": "3.4.27", + "csstype": "^3.1.3" + } + }, + "node_modules/@vue/server-renderer": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", + "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27" + }, + "peerDependencies": { + "vue": "3.4.27" + } + }, + "node_modules/@vue/shared": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", + "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==", + "license": "MIT" + }, + "node_modules/@wangeditor-next/basic-modules": { + "version": "1.5.53", + "resolved": "https://registry.npmjs.org/@wangeditor-next/basic-modules/-/basic-modules-1.5.53.tgz", + "integrity": "sha512-dszUCEgO9POfxDCRn3S8Usu4ShrzqzZ95KovsexmL8uqecWH61vGferYDkV7iAkaK+DFdyeA6/O0cJx5NDlXmA==", + "license": "MIT", + "dependencies": { + "is-url": "^1.2.4" + }, + "peerDependencies": { + "@wangeditor-next/core": "1.7.51", + "dom7": "^3.0.0 || ^4.0.0", + "lodash.throttle": "^4.1.1", + "nanoid": "^5.0.0", + "slate": "^0.123.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@wangeditor-next/code-highlight": { + "version": "1.3.49", + "resolved": "https://registry.npmjs.org/@wangeditor-next/code-highlight/-/code-highlight-1.3.49.tgz", + "integrity": "sha512-5dGGkid5pD1i3irYbbwmlOGhviyh/kXpQe8Gly11IZ4T3NFoUcdicDqgLgPnBbGxNvRrICLfJJQVKaoXPEjFtg==", + "license": "MIT", + "dependencies": { + "prismjs": "^1.23.0" + }, + "peerDependencies": { + "@wangeditor-next/core": "1.7.51", + "dom7": "^3.0.0 || ^4.0.0", + "slate": "^0.123.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@wangeditor-next/core": { + "version": "1.7.51", + "resolved": "https://registry.npmjs.org/@wangeditor-next/core/-/core-1.7.51.tgz", + "integrity": "sha512-aGU3nFx69NPlwzX6Bhmsbh4x6AwtYq06LJSkGujRfGY469DR+xbI+vhHpyhw7IW/Xds7SfQ1kC112CeoNIUV/Q==", + "license": "MIT", + "dependencies": { + "@types/event-emitter": "^0.3.3", + "event-emitter": "^0.3.5", + "html-void-elements": "^3.0.0", + "i18next": "^23.0.0", + "scroll-into-view-if-needed": "^3.0.0", + "slate-history": "^0.115.0" + }, + "peerDependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "dom7": "^3.0.0 || ^4.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^5.0.0", + "slate": "^0.123.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@wangeditor-next/editor": { + "version": "5.6.34", + "resolved": "https://registry.npmjs.org/@wangeditor-next/editor/-/editor-5.6.34.tgz", + "integrity": "sha512-ZBRl9+Zzvt9DheIFjDfcwfGXVt7+5oP7ZZazyFh5Ta23RLBHQhwbWPkSbFYUzigPXwILofXPAxdwyyFVnHe5jw==", + "license": "MIT", + "dependencies": { + "@uppy/core": "^2.1.1", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor-next/basic-modules": "~1.5.34", + "@wangeditor-next/code-highlight": "~1.3.31", + "@wangeditor-next/core": "~1.7.34", + "@wangeditor-next/list-module": "~1.1.40", + "@wangeditor-next/table-module": "~1.6.44", + "@wangeditor-next/upload-image-module": "~1.1.37", + "@wangeditor-next/video-module": "~1.3.40", + "dom7": "^4.0.0", + "is-hotkey": "^0.2.0", + "lodash.camelcase": "^4.3.0", + "lodash.clonedeep": "^4.5.0", + "lodash.debounce": "^4.0.8", + "lodash.foreach": "^4.5.0", + "lodash.isequal": "^4.5.0", + "lodash.throttle": "^4.1.1", + "lodash.toarray": "^4.4.0", + "nanoid": "^5.0.0", + "slate": "^0.82.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@wangeditor-next/editor-for-vue": { + "version": "5.1.14", + "resolved": "https://registry.npmjs.org/@wangeditor-next/editor-for-vue/-/editor-for-vue-5.1.14.tgz", + "integrity": "sha512-Xkrdo590AhLHvzyR+U246t6T89nIWHz1weAgMuo8jEA2HS5RiUnsA4U6+iUGaQ2E5c8mYQaeNqzHQXUp9Okbiw==", + "license": "MIT", + "peerDependencies": { + "@wangeditor-next/editor": ">=5.1.0", + "vue": "^3.0.5" + } + }, + "node_modules/@wangeditor-next/editor/node_modules/slate": { + "version": "0.82.1", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.82.1.tgz", + "integrity": "sha512-3mdRdq7U3jSEoyFrGvbeb28hgrvrr4NdFCtJX+IjaNvSFozY0VZd/CGHF0zf/JDx7aEov864xd5uj0HQxxEWTQ==", + "license": "MIT", + "dependencies": { + "immer": "^9.0.6", + "is-plain-object": "^5.0.0", + "tiny-warning": "^1.0.3" + } + }, + "node_modules/@wangeditor-next/list-module": { + "version": "1.1.58", + "resolved": "https://registry.npmjs.org/@wangeditor-next/list-module/-/list-module-1.1.58.tgz", + "integrity": "sha512-oMF4s4y82KKjnuWB6zhYb1SaVxufi9zmjmlIrJXbnQ4C3YHfHpz78/psGwY4LR7Nnw4E+RTroEIKtRn0bZTbLA==", + "license": "MIT", + "peerDependencies": { + "@wangeditor-next/core": "1.7.51", + "dom7": "^3.0.0 || ^4.0.0", + "slate": "^0.123.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@wangeditor-next/table-module": { + "version": "1.6.67", + "resolved": "https://registry.npmjs.org/@wangeditor-next/table-module/-/table-module-1.6.67.tgz", + "integrity": "sha512-YYMmgA6CKx0t8RCUkzKomgJ8tnFHFMDAL94s3CJ0wQQWW4l706g8nB7jxbuaquChzVP6DIiwjM+iObKS02E8Ig==", + "license": "MIT", + "peerDependencies": { + "@wangeditor-next/core": "1.7.51", + "dom7": "^3.0.0 || ^4.0.0", + "lodash.debounce": "^4.0.8", + "lodash.throttle": "^4.1.1", + "nanoid": "^5.0.0", + "slate": "^0.123.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@wangeditor-next/upload-image-module": { + "version": "1.1.56", + "resolved": "https://registry.npmjs.org/@wangeditor-next/upload-image-module/-/upload-image-module-1.1.56.tgz", + "integrity": "sha512-fb9YFQhRiX/W4NVM42gca8nov2jqXBdfKLxP9B6j1Nb71djnklFB7EBdak+tJ138YfE+VX4gfV0D63RSSmKwcw==", + "license": "MIT", + "peerDependencies": { + "@uppy/core": "^2.0.3", + "@uppy/xhr-upload": "^2.0.3", + "@wangeditor-next/basic-modules": "1.5.53", + "@wangeditor-next/core": "1.7.51", + "dom7": "^3.0.0 || ^4.0.0", + "lodash.foreach": "^4.5.0", + "slate": "^0.123.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@wangeditor-next/video-module": { + "version": "1.3.57", + "resolved": "https://registry.npmjs.org/@wangeditor-next/video-module/-/video-module-1.3.57.tgz", + "integrity": "sha512-b/mprDvi+b6GKKTyoWErbi9UqLFGuQ8qRDYSJNl0uuC2iVjkSkVu10FeCg7m0WEhD/z63x0740XtQ0g9Qu1QTA==", + "license": "MIT", + "peerDependencies": { + "@uppy/core": "^2.1.4", + "@uppy/xhr-upload": "^2.0.7", + "@wangeditor-next/core": "1.7.51", + "dom7": "^3.0.0 || ^4.0.0", + "nanoid": "^5.0.0", + "slate": "^0.123.0", + "snabbdom": "^3.6.0" + } + }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause", + "peer": true + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC" + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-import-phases": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", + "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + }, + "peerDependencies": { + "acorn": "^8.14.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-formats/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ant-design-vue": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/ant-design-vue/-/ant-design-vue-4.2.5.tgz", + "integrity": "sha512-dh5CBXSaxJZBFQBd156sOUuZPfxI7pZsNXDYpHNBt/JyKZoYlbetRp/nJmSragS2Oo0mVC23Ote+TQSGc0TX6g==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^6.0.0", + "@ant-design/icons-vue": "^7.0.0", + "@babel/runtime": "^7.10.5", + "@ctrl/tinycolor": "^3.5.0", + "@emotion/hash": "^0.9.0", + "@emotion/unitless": "^0.8.0", + "@simonwep/pickr": "~1.8.0", + "array-tree-filter": "^2.1.0", + "async-validator": "^4.0.0", + "csstype": "^3.1.1", + "dayjs": "^1.10.5", + "dom-align": "^1.12.1", + "dom-scroll-into-view": "^2.0.0", + "lodash": "^4.17.21", + "lodash-es": "^4.17.15", + "resize-observer-polyfill": "^1.5.1", + "scroll-into-view-if-needed": "^2.2.25", + "shallow-equal": "^1.0.0", + "stylis": "^4.1.3", + "throttle-debounce": "^5.0.0", + "vue-types": "^3.0.0", + "warning": "^4.0.0" + }, + "engines": { + "node": ">=12.22.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design-vue" + }, + "peerDependencies": { + "vue": ">=3.2.0" + } + }, + "node_modules/ant-design-vue/node_modules/compute-scroll-into-view": { + "version": "1.0.20", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-1.0.20.tgz", + "integrity": "sha512-UCB0ioiyj8CRjtrvaceBLqqhZCVP+1B8+NWQhmdsm0VXOJtobBCf1dBQmebCCo34qZmUwZfIH2MZLqNHazrfjg==", + "license": "MIT" + }, + "node_modules/ant-design-vue/node_modules/scroll-into-view-if-needed": { + "version": "2.2.31", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-2.2.31.tgz", + "integrity": "sha512-dGCXy99wZQivjmjIqihaBQNjryrz5rueJY7eHfTdyWEiR4ttYpsajb14rn9s5d4DY4EcY6+4+U/maARBXJedkA==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^1.0.20" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==", + "license": "MIT" + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.29", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.29.tgz", + "integrity": "sha512-Asa2krT+XTPZINCS+2QcyS8WTkObE77RwkydwF7h6DmnKqbvlalz93m/dnphUyCa6SWSP51VgtEUf2FN+gelFQ==", + "dev": true, + "license": "Apache-2.0", + "peer": true, + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "dev": true, + "license": "ISC" + }, + "node_modules/brace-expansion": { + "version": "1.1.14", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.14.tgz", + "integrity": "sha512-MWPGfDxnyzKU7rNOW9SP/c50vi3xrmrua/+6hfPbCS2ABNWfx24vPidzvC7krjU/RTo235sV776ymlsMtGKj8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz", + "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "baseline-browser-mapping": "^2.10.12", + "caniuse-lite": "^1.0.30001782", + "electron-to-chromium": "^1.5.328", + "node-releases": "^2.0.36", + "update-browserslist-db": "^1.2.3" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001792", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz", + "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0", + "peer": true + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/clipboard": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.11.tgz", + "integrity": "sha512-C+0bbOqkezLIsmWSvlsXS0Q0bmkugu7jcfMIACB+RDEntIzQIkdr148we28AfSloQLRdZlYL/QYyrq05j/3Faw==", + "license": "MIT", + "dependencies": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, + "node_modules/clone-regexp": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clone-regexp/-/clone-regexp-2.2.0.tgz", + "integrity": "sha512-beMpP7BOtTipFuW8hrJvREQ2DrRu3BE7by0ZpibtfBA+qfHYvMGTc2Yb1JMYPKg/JUw0CHYvpg796aNTSW9z7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-regexp": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-anything": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-2.0.6.tgz", + "integrity": "sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-what": "^3.14.1" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/core-js": { + "version": "3.49.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz", + "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==", + "hasInstallScript": true, + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/cosmiconfig": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-js": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/crypto-js/-/crypto-js-4.1.1.tgz", + "integrity": "sha512-o2JlM7ydqd3Qk9CA0L4NL6mTzU2sdx96a+oOfPu8Mkl/PK51vSyoi8/rQ8NknZtk44vq15lmhAj9CIAGwgeWKw==", + "license": "MIT" + }, + "node_modules/css-functions-list": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.3.3.tgz", + "integrity": "sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/dayjs": { + "version": "1.10.5", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.10.5.tgz", + "integrity": "sha512-BUFis41ikLz+65iH6LHQCDm4YPMj5r1YFLdupPIyM4SGcXMmtiLQ7U37i+hGS8urIuqe7I/ou3IS1jVc4nbN4g==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decimal.js": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.3.1.tgz", + "integrity": "sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==", + "license": "MIT" + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "license": "MIT" + }, + "node_modules/diff": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", + "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff2html": { + "version": "3.4.47", + "resolved": "https://registry.npmjs.org/diff2html/-/diff2html-3.4.47.tgz", + "integrity": "sha512-2llDp8750FRUJl8n7apM0tlcqZYxbDHTw7qhzv/kGddByHRpn3Xg/sWHHIy34h492aGSpStEULydxqrITYpuoA==", + "license": "MIT", + "dependencies": { + "diff": "5.1.0", + "hogan.js": "3.0.2" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "highlight.js": "11.9.0" + } + }, + "node_modules/diff2html/node_modules/diff": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-5.1.0.tgz", + "integrity": "sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/diff2html/node_modules/highlight.js": { + "version": "11.9.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", + "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", + "license": "BSD-3-Clause", + "optional": true, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dom-align": { + "version": "1.12.4", + "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz", + "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw==", + "license": "MIT" + }, + "node_modules/dom-scroll-into-view": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/dom-scroll-into-view/-/dom-scroll-into-view-2.0.1.tgz", + "integrity": "sha512-bvVTQe1lfaUr1oFzZX80ce9KLDlZ3iU+XGNE/bz9HnGdklTieqsbmsLHe+rT2XWqopvL0PckkYqN7ksmm5pe3w==", + "license": "MIT" + }, + "node_modules/dom7": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/dom7/-/dom7-4.0.6.tgz", + "integrity": "sha512-emjdpPLhpNubapLFdjNL9tP06Sr+GZkrIHEXLWvOGsytACUrkbeIdjO5g77m00BrHTznnlcNqgmn7pCN192TBA==", + "license": "MIT", + "dependencies": { + "ssr-window": "^4.0.0" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "node_modules/echarts": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/echarts/-/echarts-5.4.3.tgz", + "integrity": "sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "2.3.0", + "zrender": "5.4.4" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.356", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.356.tgz", + "integrity": "sha512-9NgFd7m5t5MCJ5rUSjJITUXAH9mEGlrlofnMf4YEr+pz6JlP7cWmTAH+JFmbPnaSW8koVTkuW7pacORWAnA5Yw==", + "dev": true, + "license": "ISC", + "peer": true + }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/enhanced-resolve": { + "version": "5.21.3", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.3.tgz", + "integrity": "sha512-QyL119InA+XXEkNLNTPCXPugSvOfhwv0JOlGNzvxs0hZaiHLNvXSpudUWsOlsXGWJh8G6ckCScEkVHfX3kw/2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/errno": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz", + "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "prr": "~1.0.1" + }, + "bin": { + "errno": "cli.js" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-module-lexer": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz", + "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", + "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.0.1.tgz", + "integrity": "sha512-m3u5RnR56asrwV/lDC4GHorlW75DsFfmUcjfCYylTUs85dBRnB7VM6xG8eCMJdeDRnppzmxZVf1GEPJvl1JmNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0", + "synckit": "^0.8.5" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/prettier" + }, + "peerDependencies": { + "@types/eslint": ">=8.0.0", + "eslint": ">=8.0.0", + "prettier": ">=3.0.0" + }, + "peerDependenciesMeta": { + "@types/eslint": { + "optional": true + }, + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-vue": { + "version": "9.17.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-9.17.0.tgz", + "integrity": "sha512-r7Bp79pxQk9I5XDP0k2dpUC7Ots3OSWgvGZNu3BxmKK6Zg7NgVtcOB6OCna5Kb9oQwJPl5hq183WD0SY5tZtIQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.4.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.1.1", + "postcss-selector-parser": "^6.0.13", + "semver": "^7.5.4", + "vue-eslint-parser": "^9.3.1", + "xml-name-validator": "^4.0.0" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execall": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/execall/-/execall-2.0.0.tgz", + "integrity": "sha512-0FU2hZ5Hh6iQnarpRtQurM/aAvp3RIbfvgLHrcqJYzhXyV2KFruhuChf9NC6waAhiUR7FFtlugkI4p7f2Fqlow==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone-regexp": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz", + "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flat-cache/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flat-cache/node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stdin": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-8.0.0.tgz", + "integrity": "sha512-sY22aA6xchAzprjyqmSEQv4UbAAzRN0L2dQB0NlN5acTTK9Don6nhoc3eAbUnpZiCANAMfd/+40kVdKfFygohg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", + "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.2" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "dev": true, + "license": "MIT" + }, + "node_modules/good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha512-goW1b+d9q/HIwbVYZzZ6SsTr4IgE+WA44A0GmPIQstuOrgsFcT7VEJ48nmr9GaRtNu0XTKacFLGnBPAM6Afouw==", + "license": "MIT", + "dependencies": { + "delegate": "^3.1.2" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz", + "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.8.0.tgz", + "integrity": "sha512-MedQhoqVdr0U6SSnWPzfiadUcDHfN/Wzq25AkXiQv9oiOO/sG0S7XkvpFIqWBl9Yq1UYyYOOVORs5UW2XlPyzg==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/hogan.js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "integrity": "sha512-RqGs4wavGYJWE07t35JQccByczmNUXQT0E12ZYV1VKYu5UiAU9lsos/yBAcf840+zrUQQxgVduCR5/B8nNtibg==", + "dependencies": { + "mkdirp": "0.3.0", + "nopt": "1.0.10" + }, + "bin": { + "hulk": "bin/hulk" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/html-void-elements": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", + "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/i18next": { + "version": "23.16.8", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", + "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "0.5.5", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-0.5.5.tgz", + "integrity": "sha512-6TDAlDPZxUFCv+fuOkIoXT/V/f3Qbq8e37p+YOiYrUv3v9cc3/6x78VdfPgFVaB9dZYeLUfKgHRebpkm/oP2VQ==", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/immer": { + "version": "9.0.21", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz", + "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dev": true, + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-hotkey": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/is-hotkey/-/is-hotkey-0.2.0.tgz", + "integrity": "sha512-UknnZK4RakDmTgz4PI1wIph5yxSs/mvChWs9ifnlXsKuXgWmOkY/hAE0H/k2MIqH0RlRye0i1oC07MCRSD28Mw==", + "license": "MIT" + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regexp": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-2.1.0.tgz", + "integrity": "sha512-OZ4IlER3zmRIoB9AqNhEggVxqIH4ofDns5nRrPS6yQxXE1TPCUpFznBfRQmQa8uC+pXqjMnukiJBxCisIxiLGA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "license": "MIT" + }, + "node_modules/is-what": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-3.14.1.tgz", + "integrity": "sha512-sNxgpk9793nzSs7bA6JQJGeIuRBQhAaNGG77kzYQgMkrID+lS6SlK07K5LaptscDlSaIgH+GPFzf+d75FVxozA==", + "dev": true, + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/known-css-properties": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/known-css-properties/-/known-css-properties-0.25.0.tgz", + "integrity": "sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA==", + "dev": true, + "license": "MIT" + }, + "node_modules/less": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/less/-/less-4.2.2.tgz", + "integrity": "sha512-tkuLHQlvWUTeQ3doAqnHbNn8T6WX1KA8yvbKG9x4VtKtIjHsVKQZCH11zRgAfbDAXC2UNIg/K9BYAAcEzUIrNg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "copy-anything": "^2.0.1", + "parse-node-version": "^1.0.1", + "tslib": "^2.3.0" + }, + "bin": { + "lessc": "bin/lessc" + }, + "engines": { + "node": ">=6" + }, + "optionalDependencies": { + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "make-dir": "^2.1.0", + "mime": "^1.4.1", + "needle": "^3.1.0", + "source-map": "~0.6.0" + } + }, + "node_modules/less-loader": { + "version": "11.1.4", + "resolved": "https://registry.npmjs.org/less-loader/-/less-loader-11.1.4.tgz", + "integrity": "sha512-6/GrYaB6QcW6Vj+/9ZPgKKs6G10YZai/l/eJ4SLwbzqNTBsAqt5hSLVF47TgsiBxV1P6eAU0GYRH3YRuQU9V3A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.15.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "less": "^3.5.0 || ^4.0.0", + "webpack": "^5.0.0" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz", + "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "license": "MIT" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==", + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha512-aEXTF4d+m05rVOAUG3z4vZZ4xVexLKZGF0lIxuHZ1Hplpk/3B6Z1+/ICICYRLm7c41Z2xiejbkCkJoTlypoXhQ==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/lodash.toarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz", + "integrity": "sha512-QyffEA3i5dma5q2490+SgCvDN0pXLmRGSyAANuVi0HQ01Pkfr9fuoKQW8wm1wGBnJITs/mS7wQvS6VshUEBFCw==", + "license": "MIT" + }, + "node_modules/lodash.truncate": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz", + "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/lunar-javascript": { + "version": "1.6.12", + "resolved": "https://registry.npmjs.org/lunar-javascript/-/lunar-javascript-1.6.12.tgz", + "integrity": "sha512-8BIYt50up4B2ihh0O1MCUh7+y6hDiDRIPp0ubP8KKaA7cIgAi4jD3QvM9OdZj0QNhSvopZPKipLt2Eb9+cLhxw==", + "license": "MIT" + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "optional": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/mathml-tag-names": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/mathml-tag-names/-/mathml-tag-names-2.1.3.tgz", + "integrity": "sha512-APMBEanjybaPzUrfqU0IMU5I0AswKMH7k8OTLs0vvV4KZpExkTkY87nR/zpbuTPj+gARop7aGUbl11pnDfW6xg==", + "dev": true, + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, + "node_modules/meow": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/meow/-/meow-9.0.0.tgz", + "integrity": "sha512-+obSblOQmRhcyBt62furQqRAQpNyWXo8BuQ5bN7dG8wmwQ+vwHKp/rCFD4CrTP8CsDQD1sjoZ94K417XEUk8IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize": "^1.2.0", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow/node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mime-match/-/mime-match-1.0.2.tgz", + "integrity": "sha512-VXp/ugGDVh3eCLOBCiHZMYWQaTNUHv2IJrut+yXA6+JbLPXHglHwfS/5A5L0ll+jkCY7fIzRJcH6OIunF+c6Cg==", + "license": "ISC", + "dependencies": { + "wildcard": "^1.1.0" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.3.tgz", + "integrity": "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha512-OHsdUcVAQ6pOtg5JYWpCBo9W/GySVuwvP9hueRMW7UqshC0tbfzLv8wjySTPm3tfUZ/21CE9E1pJagOA91Pxew==", + "deprecated": "Legacy versions of mkdirp are no longer supported. Please update to mkdirp 1.x. (Note that the API surface has changed to use Promises in 1.x.)", + "license": "MIT/X11", + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/namespace-emitter": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/namespace-emitter/-/namespace-emitter-2.0.1.tgz", + "integrity": "sha512-N/sMKHniSDJBjfrkbS/tpkPj4RAbvW3mr8UAzvlMHyun93XEm83IAvhWtJVHo+RHn/oO8Job5YN4b+wRjSVp5g==", + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "5.1.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.11.tgz", + "integrity": "sha512-v+KEsUv2ps74PaSKv0gHTxTCgMXOIfBEbaqa6w6ISIGC7ZsvHN4N9oJ8d4cmf0n5oTzQz2SLmThbQWhjd/8eKg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.js" + }, + "engines": { + "node": "^18 || >=20" + } + }, + "node_modules/nanopop": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/nanopop/-/nanopop-2.4.2.tgz", + "integrity": "sha512-NzOgmMQ+elxxHeIha+OG/Pv3Oc3p4RU2aBhwWwAqDpXrdTbtRylbRLQztLy8dMMwfl6pclznBdfUhccEn9ZIzw==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/needle": { + "version": "3.5.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-3.5.0.tgz", + "integrity": "sha512-jaQyPKKk2YokHrEg+vFDYxXIHTCBgiZwSHOoVx/8V3GIBS8/VN6NdVRmg8q1ERtPkMvmOvebsgga4sAj5hls/w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.3", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, + "node_modules/node-releases": { + "version": "2.0.44", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.44.tgz", + "integrity": "sha512-5WUyunoPMsvvEhS8AxHtRzP+oA8UCkJ7YRxatWKjngndhDGLiqEVAQKWjFAiAiuL8zMRGzGSJxFnLetoa43qGQ==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "license": "MIT", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==", + "license": "MIT" + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-node-version": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz", + "integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/pinia": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/pinia/-/pinia-2.1.7.tgz", + "integrity": "sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.5.0", + "vue-demi": ">=0.14.5" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "@vue/composition-api": "^1.4.0", + "typescript": ">=4.4.4", + "vue": "^2.6.14 || ^3.3.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/pinia/node_modules/vue-demi": { + "version": "0.14.10", + "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz", + "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==", + "hasInstallScript": true, + "license": "MIT", + "bin": { + "vue-demi-fix": "bin/vue-demi-fix.js", + "vue-demi-switch": "bin/vue-demi-switch.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vue/composition-api": "^1.0.0-rc.1", + "vue": "^3.0.0-0 || ^2.6.0" + }, + "peerDependenciesMeta": { + "@vue/composition-api": { + "optional": true + } + } + }, + "node_modules/postcss": { + "version": "8.5.14", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz", + "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-media-query-parser": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/postcss-media-query-parser/-/postcss-media-query-parser-0.2.3.tgz", + "integrity": "sha512-3sOlxmbKcSHMjlUXQZKQ06jOswE7oVkXPxmZdoB1r5l0q6gTFTQSHxNxOrCccElbW7dxNytifNEo8qidX2Vsig==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-resolve-nested-selector": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/postcss-resolve-nested-selector/-/postcss-resolve-nested-selector-0.1.6.tgz", + "integrity": "sha512-0sglIs9Wmkzbr8lQwEyIzlDOOC9bGmfVKcJTaxv3vMmd3uo4o4DerC3En0bnmgceeql9BfC8hRkp7cg0fjdVqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss-safe-parser": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz", + "integrity": "sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.3.3" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-sorting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-sorting/-/postcss-sorting-7.0.1.tgz", + "integrity": "sha512-iLBFYz6VRYyLJEJsBJ8M3TCqNcckVzz4wFounSc5Oez35ogE/X+aoC5fFu103Ot7NyvjU3/xqIXn93Gp3kJk4g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "postcss": "^8.3.9" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/postcss/node_modules/nanoid": { + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/preact": { + "version": "10.29.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.29.1.tgz", + "integrity": "sha512-gQCLc/vWroE8lIpleXtdJhTFDogTdZG9AjMUpVkDf2iTCNwYNWA+u16dL41TqUDJO4gm2IgrcMv3uTpjd4Pwmg==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/preact" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", + "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prismjs": { + "version": "1.30.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", + "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, + "node_modules/prr": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz", + "integrity": "sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true, + "license": "ISC" + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "5.0.10", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", + "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "glob": "^10.3.7" + }, + "bin": { + "rimraf": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rollup": { + "version": "4.60.4", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.4.tgz", + "integrity": "sha512-WHeFSbZYsPu3+bLoNRUuAO+wavNlocOPf3wSHTP7hcFKVnJeWsYlCDbr3mTS14FCizf9ccIxXA8sGL8zKeQN3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.60.4", + "@rollup/rollup-android-arm64": "4.60.4", + "@rollup/rollup-darwin-arm64": "4.60.4", + "@rollup/rollup-darwin-x64": "4.60.4", + "@rollup/rollup-freebsd-arm64": "4.60.4", + "@rollup/rollup-freebsd-x64": "4.60.4", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.4", + "@rollup/rollup-linux-arm-musleabihf": "4.60.4", + "@rollup/rollup-linux-arm64-gnu": "4.60.4", + "@rollup/rollup-linux-arm64-musl": "4.60.4", + "@rollup/rollup-linux-loong64-gnu": "4.60.4", + "@rollup/rollup-linux-loong64-musl": "4.60.4", + "@rollup/rollup-linux-ppc64-gnu": "4.60.4", + "@rollup/rollup-linux-ppc64-musl": "4.60.4", + "@rollup/rollup-linux-riscv64-gnu": "4.60.4", + "@rollup/rollup-linux-riscv64-musl": "4.60.4", + "@rollup/rollup-linux-s390x-gnu": "4.60.4", + "@rollup/rollup-linux-x64-gnu": "4.60.4", + "@rollup/rollup-linux-x64-musl": "4.60.4", + "@rollup/rollup-openbsd-x64": "4.60.4", + "@rollup/rollup-openharmony-arm64": "4.60.4", + "@rollup/rollup-win32-arm64-msvc": "4.60.4", + "@rollup/rollup-win32-ia32-msvc": "4.60.4", + "@rollup/rollup-win32-x64-gnu": "4.60.4", + "@rollup/rollup-win32-x64-msvc": "4.60.4", + "fsevents": "~2.3.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/sax": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz", + "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==", + "dev": true, + "license": "BlueOak-1.0.0", + "optional": true, + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/schema-utils": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", + "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha512-OwpTSOfy6xSs1+pwcNrv0RBMOzI39Lp3qQKUTPVVPRjCdNa5JH/oPRiqsesIskK8TVgmRiHwO4KXlV2Li9dANA==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shallow-equal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shallow-equal/-/shallow-equal-1.2.1.tgz", + "integrity": "sha512-S4vJDjHHMBaiZuT9NPb616CSmLf618jawtv3sufLl6ivK8WocjAo58cXwbRV1cgqxH0Qbv+iUt6m05eqEa2IRA==", + "license": "MIT" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slate": { + "version": "0.123.0", + "resolved": "https://registry.npmjs.org/slate/-/slate-0.123.0.tgz", + "integrity": "sha512-Oon3HR/QzJQBjuOUJT1jGGlp8Ff7t3Bkr/rJ2lDqxNT4H+cBnXpEVQ/si6hn1ZCHhD2xY/2N91PQoH/rD7kxTg==", + "license": "MIT", + "peer": true + }, + "node_modules/slate-history": { + "version": "0.115.0", + "resolved": "https://registry.npmjs.org/slate-history/-/slate-history-0.115.0.tgz", + "integrity": "sha512-QdUm9aVyQFz6JG4a84Z6Um+tJpZJmsh9bjXwTVTvYiN4rdKbqL6+/4HT94on1WYxe10Q4vY6mA6BCpoYxgF3tQ==", + "license": "MIT", + "peerDependencies": { + "slate": ">=0.114.3" + } + }, + "node_modules/slice-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/sm-crypto": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/sm-crypto/-/sm-crypto-0.3.13.tgz", + "integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==", + "license": "MIT", + "dependencies": { + "jsbn": "^1.1.0" + } + }, + "node_modules/snabbdom": { + "version": "3.6.3", + "resolved": "https://registry.npmjs.org/snabbdom/-/snabbdom-3.6.3.tgz", + "integrity": "sha512-W2lHLLw2qR2Vv0DcMmcxXqcfdBaIcoN+y/86SmHv8fn4DazEQSH6KN3TjZcWvwujW56OHiiirsbHWZb4vx/0fg==", + "license": "MIT", + "engines": { + "node": ">=12.17.0" + } + }, + "node_modules/sortablejs": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", + "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==", + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/specificity": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/specificity/-/specificity-0.4.1.tgz", + "integrity": "sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg==", + "dev": true, + "license": "MIT", + "bin": { + "specificity": "bin/specificity" + } + }, + "node_modules/ssr-window": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/ssr-window/-/ssr-window-4.0.2.tgz", + "integrity": "sha512-ISv/Ch+ig7SOtw7G2+qkwfVASzazUnvlDTwypdLoPoySv+6MqlOV10VwPSE6EWkGjhW50lUmghPmpYZXMu/+AQ==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/string-width/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/style-search": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/style-search/-/style-search-0.1.0.tgz", + "integrity": "sha512-Dj1Okke1C3uKKwQcetra4jSuk0DqbzbYtXipzFlFMZtowbF1x7BKJwB9AayVMyFARvU8EDrZdcax4At/452cAg==", + "dev": true, + "license": "ISC" + }, + "node_modules/stylelint": { + "version": "14.8.5", + "resolved": "https://registry.npmjs.org/stylelint/-/stylelint-14.8.5.tgz", + "integrity": "sha512-e3t4H/hlWlspkcNUrkhf44RU3OpPTA7uBOoREGBzSwdEF+2g/+gbZq7WEpMP7BpopcSe/uLaTvDuL+URL7cdnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^2.0.0", + "colord": "^2.9.2", + "cosmiconfig": "^7.0.1", + "css-functions-list": "^3.0.1", + "debug": "^4.3.4", + "execall": "^2.0.0", + "fast-glob": "^3.2.11", + "fastest-levenshtein": "^1.0.12", + "file-entry-cache": "^6.0.1", + "get-stdin": "^8.0.0", + "global-modules": "^2.0.0", + "globby": "^11.1.0", + "globjoin": "^0.1.4", + "html-tags": "^3.2.0", + "ignore": "^5.2.0", + "import-lazy": "^4.0.0", + "imurmurhash": "^0.1.4", + "is-plain-object": "^5.0.0", + "known-css-properties": "^0.25.0", + "mathml-tag-names": "^2.1.3", + "meow": "^9.0.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.14", + "postcss-media-query-parser": "^0.2.3", + "postcss-resolve-nested-selector": "^0.1.1", + "postcss-safe-parser": "^6.0.0", + "postcss-selector-parser": "^6.0.10", + "postcss-value-parser": "^4.2.0", + "resolve-from": "^5.0.0", + "specificity": "^0.4.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "style-search": "^0.1.0", + "supports-hyperlinks": "^2.2.0", + "svg-tags": "^1.0.0", + "table": "^6.8.0", + "v8-compile-cache": "^2.3.0", + "write-file-atomic": "^4.0.1" + }, + "bin": { + "stylelint": "bin/stylelint.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/stylelint" + } + }, + "node_modules/stylelint-config-prettier": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/stylelint-config-prettier/-/stylelint-config-prettier-9.0.5.tgz", + "integrity": "sha512-U44lELgLZhbAD/xy/vncZ2Pq8sh2TnpiPvo38Ifg9+zeioR+LAkHu0i6YORIOxFafZoVg0xqQwex6e6F25S5XA==", + "dev": true, + "license": "MIT", + "bin": { + "stylelint-config-prettier": "bin/check.js", + "stylelint-config-prettier-check": "bin/check.js" + }, + "engines": { + "node": ">= 12" + }, + "peerDependencies": { + "stylelint": ">= 11.x < 15" + } + }, + "node_modules/stylelint-config-recommended": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-recommended/-/stylelint-config-recommended-7.0.0.tgz", + "integrity": "sha512-yGn84Bf/q41J4luis1AZ95gj0EQwRX8lWmGmBwkwBNSkpGSpl66XcPTulxGa/Z91aPoNGuIGBmFkcM1MejMo9Q==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "stylelint": "^14.4.0" + } + }, + "node_modules/stylelint-config-standard": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/stylelint-config-standard/-/stylelint-config-standard-25.0.0.tgz", + "integrity": "sha512-21HnP3VSpaT1wFjFvv9VjvOGDtAviv47uTp3uFmzcN+3Lt+RYRv6oAplLaV51Kf792JSxJ6svCJh/G18E9VnCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "stylelint-config-recommended": "^7.0.0" + }, + "peerDependencies": { + "stylelint": "^14.4.0" + } + }, + "node_modules/stylelint-order": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/stylelint-order/-/stylelint-order-5.0.0.tgz", + "integrity": "sha512-OWQ7pmicXufDw5BlRqzdz3fkGKJPgLyDwD1rFY3AIEfIH/LQY38Vu/85v8/up0I+VPiuGRwbc2Hg3zLAsJaiyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss": "^8.3.11", + "postcss-sorting": "^7.0.1" + }, + "peerDependencies": { + "stylelint": "^14.0.0" + } + }, + "node_modules/stylelint/node_modules/balanced-match": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-2.0.0.tgz", + "integrity": "sha512-1ugUSr8BHXRnK23KfuYS+gVMC3LB8QGH9W1iGtDPsNWoQbgtXSExkBu2aDR4epiGWZOjZsj6lDl/N/AqqTC3UA==", + "dev": true, + "license": "MIT" + }, + "node_modules/stylelint/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/stylelint/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stylelint/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-hyperlinks": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/supports-hyperlinks/-/supports-hyperlinks-2.3.0.tgz", + "integrity": "sha512-RpsAZlpWcDwOPQA22aCH4J0t7L8JmAvsCxfOSEwm7cQs3LshN36QaTkwd70DnBOXDWGssw2eUoc8CaRWT0XunA==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svg-tags": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz", + "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", + "dev": true + }, + "node_modules/synckit": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.8.8.tgz", + "integrity": "sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@pkgr/core": "^0.1.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/unts" + } + }, + "node_modules/synckit/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "dev": true, + "license": "0BSD" + }, + "node_modules/table": { + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", + "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "ajv": "^8.0.1", + "lodash.truncate": "^4.4.2", + "slice-ansi": "^4.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/table/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/table/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/table/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser": { + "version": "5.29.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.29.2.tgz", + "integrity": "sha512-ZiGkhUBIM+7LwkNjXYJq8svgkd+QK3UUr0wJqY4MieaezBSAIPgbSPZyIx0idM6XWK5CMzSWa8MJIzmRcB8Caw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.0.tgz", + "integrity": "sha512-Eum+5ajkaOhf5KbM26osvv21kLD7BaGqQ1UA4Ami4arYwylmGUQTgHFpHDdmJod1q4QXa66p0to/FBKID+J1vA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/terser": { + "version": "5.47.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.47.1.tgz", + "integrity": "sha512-tPbLXTI6ohPASb/1YViL428oEHu6/qv1OxqYnfaonVCFHqx4+wCd95pHrQWsL5X4pl90CTyW9piSAsS2L0VoMw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "license": "MIT" + }, + "node_modules/tiny-warning": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tiny-warning/-/tiny-warning-1.0.3.tgz", + "integrity": "sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==", + "license": "MIT" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tslib": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", + "integrity": "sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==", + "license": "0BSD" + }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ua-parser-js": { + "version": "1.0.35", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.35.tgz", + "integrity": "sha512-fKnGuqmTBnIE+/KXSzCn4db8RTigUzw1AN0DmdU6hJovUTbYJKyqj+8Mt1c4VfRDnOVJnENmfYkIPZ946UrSAA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/ua-parser-js" + }, + { + "type": "paypal", + "url": "https://paypal.me/faisalman" + } + ], + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/undici-types": { + "version": "7.24.6", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.24.6.tgz", + "integrity": "sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==", + "dev": true, + "license": "MIT", + "peer": true + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "peer": true, + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.1.tgz", + "integrity": "sha512-vIYxrBCC/N/K+Js3qSN88go7kIfNPssr/hHCesKCQNAjmgvYS2oqr69kIufEG+O4+PfezOH4EbIeHCfFov8ZgQ==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/esm/bin/uuid" + } + }, + "node_modules/v-viewer": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/v-viewer/-/v-viewer-1.6.4.tgz", + "integrity": "sha512-LVkiUHpmsbsZXebeNXnu8krRCi5i2n07FeLFxoIVGhw8lVvTBO0ffpbDC6mLEuacCjrIh09HjIqpciwUtWE8lQ==", + "license": "MIT", + "dependencies": { + "throttle-debounce": "^2.0.1", + "viewerjs": "^1.5.0" + }, + "engines": { + "node": ">=4", + "npm": ">=3" + } + }, + "node_modules/v-viewer/node_modules/throttle-debounce": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-2.3.0.tgz", + "integrity": "sha512-H7oLPV0P7+jgvrk+6mwwwBDmxTaxnu9HMXmloNLXwnNO0ZxZ31Orah2n8lU1eMPvsaowP2CX+USCgyovXfdOFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/v8-compile-cache": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz", + "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/viewerjs": { + "version": "1.11.7", + "resolved": "https://registry.npmjs.org/viewerjs/-/viewerjs-1.11.7.tgz", + "integrity": "sha512-0JuVqOmL5v1jmEAlG5EBDR3XquxY8DWFQbFMprOXgaBB0F7Q/X9xWdEaQc59D8xzwkdUgXEMSSknTpriq95igg==", + "license": "MIT" + }, + "node_modules/vite": { + "version": "5.2.12", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.12.tgz", + "integrity": "sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.20.1", + "postcss": "^8.4.38", + "rollup": "^4.13.0" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vue": { + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", + "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-sfc": "3.4.27", + "@vue/runtime-dom": "3.4.27", + "@vue/server-renderer": "3.4.27", + "@vue/shared": "3.4.27" + }, + "peerDependencies": { + "typescript": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/vue-eslint-parser": { + "version": "9.4.3", + "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-9.4.3.tgz", + "integrity": "sha512-2rYRLWlIpaiN8xbPiDyXZXRgLGOtWxERV7ND5fFAv5qo1D2N9Fu9MNajBNc6o13lZ+24DAWCkQCvj4klgmcITg==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "eslint-scope": "^7.1.1", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "lodash": "^4.17.21", + "semver": "^7.3.6" + }, + "engines": { + "node": "^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=6.0.0" + } + }, + "node_modules/vue-i18n": { + "version": "9.13.1", + "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.13.1.tgz", + "integrity": "sha512-mh0GIxx0wPtPlcB1q4k277y0iKgo25xmDPWioVVYanjPufDBpvu5ySTjP5wOrSvlYQ2m1xI+CFhGdauv/61uQg==", + "deprecated": "v9 and v10 no longer supported. please migrate to v11. about maintenance status, see https://vue-i18n.intlify.dev/guide/maintenance.html", + "license": "MIT", + "dependencies": { + "@intlify/core-base": "9.13.1", + "@intlify/shared": "9.13.1", + "@vue/devtools-api": "^6.5.0" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/kazupon" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-router": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.2.tgz", + "integrity": "sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==", + "license": "MIT", + "dependencies": { + "@vue/devtools-api": "^6.5.1" + }, + "funding": { + "url": "https://github.com/sponsors/posva" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/vue-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/vue-types/-/vue-types-3.0.2.tgz", + "integrity": "sha512-IwUC0Aq2zwaXqy74h4WCvFCUtoV0iSWr0snWnE9TnU18S66GAQyqQbRf2qfJtUuiFsBf6qp0MEwdonlwznlcrw==", + "license": "MIT", + "dependencies": { + "is-plain-object": "3.0.1" + }, + "engines": { + "node": ">=10.15.0" + }, + "peerDependencies": { + "vue": "^3.0.0" + } + }, + "node_modules/vue-types/node_modules/is-plain-object": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz", + "integrity": "sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/vue3-json-viewer": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/vue3-json-viewer/-/vue3-json-viewer-2.2.2.tgz", + "integrity": "sha512-56l3XDGggnpwEqZieXsSMhNT4NhtO6d7zuSAxHo4i0UVxymyY2jRb7UMQOU1ztChKALZCAzX7DlgrsnEhxu77A==", + "license": "ISC", + "dependencies": { + "clipboard": "^2.0.10" + }, + "peerDependencies": { + "vue": "^3.2.0" + } + }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/watchpack": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", + "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack": { + "version": "5.106.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz", + "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.16.0", + "acorn-import-phases": "^1.0.3", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.20.0", + "es-module-lexer": "^2.0.0", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "loader-runner": "^4.3.1", + "mime-db": "^1.54.0", + "neo-async": "^2.6.2", + "schema-utils": "^4.3.3", + "tapable": "^2.3.0", + "terser-webpack-plugin": "^5.3.17", + "watchpack": "^2.5.1", + "webpack-sources": "^3.3.4" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-sources": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz", + "integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "peer": true, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/webpack/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "dev": true, + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/wildcard": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-1.1.2.tgz", + "integrity": "sha512-DXukZJxpHA8LuotRwL0pP1+rS6CS7FF2qStDDE1C7DDg2rLud2PXRMuEDYIPhgEezwnlHNL4c+N6MfMTjCGTng==", + "license": "MIT" + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/xml-name-validator": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz", + "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "1.10.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", + "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zrender": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/zrender/-/zrender-5.4.4.tgz", + "integrity": "sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==", + "license": "BSD-3-Clause", + "dependencies": { + "tslib": "2.3.0" + } + } + } +} diff --git a/smart-flow-web/package.json b/smart-flow-web/package.json new file mode 100644 index 0000000..a98748b --- /dev/null +++ b/smart-flow-web/package.json @@ -0,0 +1,74 @@ +{ + "name": "SmartFlow", + "version": "3.0.0", + "author": { + "name": "lovefawn", + "email": "", + "url": "" + }, + "license": "MIT", + "homepage": "", + "scripts": { + "localhost": "vite --mode localhost", + "dev": "vite", + "build:test": "vite build --base=/admin/ --mode test", + "build:pre": "vite build --mode pre", + "build:prod": "vite build --mode production" + }, + "type": "module", + "dependencies": { + "@ant-design/icons-vue": "^7.0.1", + "@wangeditor-next/editor": "5.6.34", + "@wangeditor-next/editor-for-vue": "5.1.14", + "ant-design-vue": "4.2.5", + "axios": "1.6.8", + "clipboard": "2.0.11", + "crypto-js": "4.1.1", + "dayjs": "1.10.5", + "decimal.js": "10.3.1", + "diff": "5.2.0", + "diff2html": "3.4.47", + "echarts": "5.4.3", + "highlight.js": "11.8.0", + "lodash": "4.17.21", + "lunar-javascript": "1.6.12", + "mitt": "3.0.1", + "nprogress": "0.2.0", + "pinia": "2.1.7", + "sm-crypto": "0.3.13", + "sortablejs": "1.15.0", + "ua-parser-js": "1.0.35", + "uuid": "^11.1.0", + "v-viewer": "~1.6.4", + "vue": "3.4.27", + "vue-i18n": "9.13.1", + "vue-router": "4.3.2", + "vue3-json-viewer": "2.2.2" + }, + "devDependencies": { + "@vitejs/plugin-vue": "5.0.4", + "@vue/compiler-sfc": "3.4.27", + "eslint": "^8.16.0", + "eslint-config-prettier": "~9.0.0", + "eslint-plugin-prettier": "~5.0.0", + "eslint-plugin-vue": "~9.17.0", + "less": "~4.2.0", + "less-loader": "~11.1.3", + "prettier": "~3.0.2", + "rimraf": "~5.0.1", + "stylelint": "~14.8.5", + "stylelint-config-prettier": "~9.0.3", + "stylelint-config-standard": "~25.0.0", + "stylelint-order": "~5.0.0", + "terser": "~5.29.2", + "vite": "5.2.12", + "vue-eslint-parser": "~9.4.2" + }, + "engines": { + "node": ">=18" + }, + "repository": { + "type": "git", + "url": "" + } +} diff --git a/smart-flow-web/postcss.config.cjs b/smart-flow-web/postcss.config.cjs new file mode 100644 index 0000000..2c7ab7c --- /dev/null +++ b/smart-flow-web/postcss.config.cjs @@ -0,0 +1,4 @@ +module.exports = { + plugins: { + }, +}; diff --git a/smart-flow-web/public/favicon.ico b/smart-flow-web/public/favicon.ico new file mode 100644 index 0000000..5b38c41 Binary files /dev/null and b/smart-flow-web/public/favicon.ico differ diff --git a/smart-flow-web/src/App.vue b/smart-flow-web/src/App.vue new file mode 100644 index 0000000..cb5c981 --- /dev/null +++ b/smart-flow-web/src/App.vue @@ -0,0 +1,99 @@ + + + + + + diff --git a/smart-flow-web/src/api/business/category/category-api.js b/smart-flow-web/src/api/business/category/category-api.js new file mode 100644 index 0000000..5eb80d2 --- /dev/null +++ b/smart-flow-web/src/api/business/category/category-api.js @@ -0,0 +1,30 @@ +/* + * 类目api + * + * @Author: 卓大 + * @Date: 2022-09-03 21:35:00 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest, postRequest } from '/@/lib/axios'; + +export const categoryApi = { + // 添加类目 @author 卓大 + addCategory: (param) => { + return postRequest('/category/add', param); + }, + // GET + // 删除类目 @author 卓大 + deleteCategoryById: (categoryId) => { + return getRequest(`/category/delete/${categoryId}`); + }, + // 查询类目层级树 @author 卓大 + queryCategoryTree: (param) => { + return postRequest('/category/tree', param); + }, + // 更新类目 @author 卓大 + updateCategory: (param) => { + return postRequest('/category/update', param); + }, +}; diff --git a/smart-flow-web/src/api/business/goods/goods-api.js b/smart-flow-web/src/api/business/goods/goods-api.js new file mode 100644 index 0000000..007029b --- /dev/null +++ b/smart-flow-web/src/api/business/goods/goods-api.js @@ -0,0 +1,41 @@ +/* + * @Description: + * @Author: zhuoda + * @Date: 2021-11-05 + * @LastEditTime: 2022-06-23 + * @LastEditors: zhuoda + */ +import {postRequest, getRequest, getDownload} from '/@/lib/axios'; + +export const goodsApi = { + // 添加商品 @author zhuoda + addGoods: (param) => { + return postRequest('/goods/add', param); + }, + // 删除 @author zhuoda + deleteGoods: (goodsId) => { + return getRequest(`/goods/delete/${goodsId}`); + }, + // 批量 @author zhuoda + batchDelete: (goodsIdList) => { + return postRequest('/goods/batchDelete', goodsIdList); + }, + // 分页查询 @author zhuoda + queryGoodsList: (param) => { + return postRequest('/goods/query', param); + }, + // 更新商品 @author zhuoda + updateGoods: (param) => { + return postRequest('/goods/update', param); + }, + + // 导入 @author 卓大 + importGoods : (file) =>{ + return postRequest('/goods/importGoods',file); + }, + + // 导出 @author 卓大 + exportGoods : () =>{ + return getDownload('/goods/exportGoods'); + } +}; diff --git a/smart-flow-web/src/api/business/oa/bank-api.js b/smart-flow-web/src/api/business/oa/bank-api.js new file mode 100644 index 0000000..7e9b627 --- /dev/null +++ b/smart-flow-web/src/api/business/oa/bank-api.js @@ -0,0 +1,42 @@ +/* + * 银行卡 + * + * @Author: 善逸 + * @Date: 2022-09-03 21:42:08 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const bankApi = { + // 新建银行信息 @author 善逸 + create: (param) => { + return postRequest('/oa/bank/create', param); + }, + + // 删除银行信息 @author 善逸 + delete: (bankId) => { + return getRequest(`/oa/bank/delete/${bankId}`); + }, + + // 查询银行信息详情 @author 善逸 + detail: (bankId) => { + return getRequest(`/oa/bank/get/${bankId}`); + }, + + // 分页查询银行信息 @author 善逸 + pageQuery: (param) => { + return postRequest('/oa/bank/page/query', param); + }, + + // 编辑银行信息 @author 善逸 + update: (param) => { + return postRequest('/oa/bank/update', param); + }, + + // 根据企业ID查询不分页的银行列表 @author 善逸 + queryList: (enterpriseId) => { + return getRequest(`/oa/bank/query/list/${enterpriseId}`); + }, +}; diff --git a/smart-flow-web/src/api/business/oa/enterprise-api.js b/smart-flow-web/src/api/business/oa/enterprise-api.js new file mode 100644 index 0000000..5c2ad68 --- /dev/null +++ b/smart-flow-web/src/api/business/oa/enterprise-api.js @@ -0,0 +1,69 @@ +/* + * 企业信息 + * + * @Author: 开云 + * @Date: 2022-09-03 21:47:28 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import {postRequest, getRequest, postDownload} from '/@/lib/axios'; + +export const enterpriseApi = { + // 新建企业 @author 开云 + create: (param) => { + return postRequest('/oa/enterprise/create', param); + }, + + // 删除企业 @author 开云 + delete: (enterpriseId) => { + return getRequest(`/oa/enterprise/delete/${enterpriseId}`); + }, + + // 查询企业详情 @author 开云 + detail: (enterpriseId) => { + return getRequest(`/oa/enterprise/get/${enterpriseId}`); + }, + + // 分页查询企业模块 @author 开云 + pageQuery: (param) => { + return postRequest('/oa/enterprise/page/query', param); + }, + + // 导出企业数据excel @author 卓大 + exportExcel: (param) => { + return postDownload('/oa/enterprise/exportExcel', param); + }, + + //企业列表查询 含数据范围 @author 开云 + queryList: (type) => { + let query = ''; + if (type) { + query = `?type=${type}`; + } + return getRequest(`/oa/enterprise/query/list${query}`); + }, + + // 编辑企业 @author 开云 + update: (param) => { + return postRequest('/oa/enterprise/update', param); + }, + // 企业全部员工List @author yandy + employeeList: (param) => { + return postRequest('/oa/enterprise/employee/list', param); + }, + // 分页查询企业员工List @author 卓大 + queryPageEmployeeList: (param) => { + return postRequest('/oa/enterprise/employee/queryPage', param); + }, + // 添加员工 @author yandy + addEmployee: (param) => { + return postRequest('/oa/enterprise/employee/add', param); + }, + + // 删除员工 @author yandy + deleteEmployee: (param) => { + return postRequest('/oa/enterprise/employee/delete', param); + }, + +}; diff --git a/smart-flow-web/src/api/business/oa/invoice-api.js b/smart-flow-web/src/api/business/oa/invoice-api.js new file mode 100644 index 0000000..d347af2 --- /dev/null +++ b/smart-flow-web/src/api/business/oa/invoice-api.js @@ -0,0 +1,44 @@ +/* + * OA发票信息 + * + * @Author: 善逸 + * @Date: 2022-09-03 21:48:54 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const invoiceApi = { + + // 新建发票信息 @author 善逸 + create: (param) => { + return postRequest('/oa/invoice/create', param); + }, + + // 删除发票信息 @author 善逸 + delete: (bankId) => { + return getRequest(`/oa/invoice/delete/${bankId}`); + }, + + // 查询发票信息详情 @author 善逸 + detail: (bankId) => { + return getRequest(`//oa/invoice/get/${bankId}`); + }, + + // 分页查询发票信息 @author 善逸 + pageQuery: (param) => { + return postRequest('/oa/invoice/page/query', param); + }, + + // 编辑发票信息 @author 善逸 + update: (param) => { + return postRequest('/oa/invoice/update', param); + }, + + // 查询发票列表 @author 善逸 + queryList: (enterpriseId) => { + return getRequest(`/oa/invoice/query/list/${enterpriseId}`); + }, + +}; diff --git a/smart-flow-web/src/api/business/oa/leave-api.js b/smart-flow-web/src/api/business/oa/leave-api.js new file mode 100644 index 0000000..31e0545 --- /dev/null +++ b/smart-flow-web/src/api/business/oa/leave-api.js @@ -0,0 +1,55 @@ +/** + * OA 请假申请表 api 封装 + * + * @Author: lf + * @Date: 2025-05-31 20:00:10 + * @Copyright lf + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const leaveApi = { + + /** + * 分页查询 @author lf + */ + queryPage : (param) => { + return postRequest('/leave/queryPage', param); + }, + + /** + * 增加 @author lf + */ + add: (param) => { + return postRequest('/leave/add', param); + }, + + /** + * 修改 @author lf + */ + update: (param) => { + return postRequest('/leave/update', param); + }, + + + /** + * 删除 @author lf + */ + delete: (id) => { + return getRequest(`/leave/delete/${id}`); + }, + + /** + * 批量删除 @author lf + */ + batchDelete: (idList) => { + return postRequest('/leave/batchDelete', idList); + }, + + /** + * 删除 @author lf + */ + getDetail: (id) => { + return getRequest(`/leave/${id}`); + }, + +}; diff --git a/smart-flow-web/src/api/business/oa/notice-api.js b/smart-flow-web/src/api/business/oa/notice-api.js new file mode 100644 index 0000000..056eb2d --- /dev/null +++ b/smart-flow-web/src/api/business/oa/notice-api.js @@ -0,0 +1,74 @@ +/* + * @Description: 公告信息、企业动态 + * @version: + * @Author: zhuoda + * @Date: 2022-08-16 20:34:36 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const noticeApi = { + // ---------------- 通知公告类型 ----------------------- + + // 通知公告类型-获取全部 @author zhuoda + getAllNoticeTypeList() { + return getRequest('/oa/noticeType/getAll'); + }, + + // 通知公告类型-添加 @author zhuoda + addNoticeType(name) { + return getRequest(`/oa/noticeType/add/${name}`); + }, + + // 通知公告类型-修改 @author zhuoda + updateNoticeType(noticeTypeId, name) { + return getRequest(`/oa/noticeType/update/${noticeTypeId}/${name}`); + }, + // 通知公告类型-删除 @author zhuoda + deleteNoticeType(noticeTypeId) { + return getRequest(`/oa/noticeType/delete/${noticeTypeId}`); + }, + + // ---------------- 通知公告管理 ----------------------- + + // 通知公告-分页查询 @author zhuoda + queryNotice(param) { + return postRequest('/oa/notice/query', param); + }, + + // 通知公告-添加 @author zhuoda + addNotice(param) { + return postRequest('/oa/notice/add', param); + }, + + // 通知公告-更新 @author zhuoda + updateNotice(param) { + return postRequest('/oa/notice/update', param); + }, + + // 通知公告-删除 @author zhuoda + deleteNotice(noticeId) { + return getRequest(`/oa/notice/delete/${noticeId}`); + }, + + // 通知公告-更新详情 @author zhuoda + getUpdateNoticeInfo(noticeId) { + return getRequest(`/oa/notice/getUpdateVO/${noticeId}`); + }, + + // --------------------- 【员工】查看 通知公告 ------------------------- + + // 通知公告-员工-查看详情 @author zhuoda + view(noticeId) { + return getRequest(`/oa/notice/employee/view/${noticeId}`); + }, + + // 通知公告-员工-查询 @author zhuoda + queryEmployeeNotice(param) { + return postRequest('/oa/notice/employee/query', param); + }, + + // 【员工】通知公告-查询 查看记录 @author zhuoda + queryViewRecord(param) { + return postRequest('/oa/notice/employee/queryViewRecord', param); + }, +}; diff --git a/smart-flow-web/src/api/flow/definition-api.js b/smart-flow-web/src/api/flow/definition-api.js new file mode 100644 index 0000000..1662227 --- /dev/null +++ b/smart-flow-web/src/api/flow/definition-api.js @@ -0,0 +1,87 @@ +/** + * 流程定义 api 封装 + * + * @Author: lovefawn + * @Date: 2025-04-01 23:31:38 + */ +import { postRequest, getRequest, postDownload } from '/@/lib/axios'; + +export const definitionApi = { + /** + * 分页查询 @author lovefawn + */ + queryPage: (param) => { + return postRequest('/flow/definition/queryPage', param); + }, + + /** + * 增加 @author lovefawn + */ + add: (param) => { + return postRequest('/flow/definition/add', param); + }, + + /** + * 修改 @author lovefawn + */ + update: (param) => { + return postRequest('/flow/definition/update', param); + }, + + /** + * 删除 @author lovefawn + */ + delete: (id) => { + return getRequest(`/flow/definition/delete/${id}`); + }, + + /** + * 批量删除 @author lovefawn + */ + batchDelete: (idList) => { + return postRequest('/flow/definition/batchDelete', idList); + }, + + /** + * 查询列表 @author lovefawn + */ + queryList: () => { + return getRequest('/flow/definition/queryList'); + }, + + // 查看流程图 + chartDef: (definitionId) => { + return getRequest('/flow/definition/chartDef/' + definitionId); + }, + // 发布流程定义 + publish: (id) => { + return getRequest('/flow/definition/publish/' + id); + }, + + // 取消发布流程定义 + unPublish: (id) => { + return getRequest('/flow/definition/unPublish/' + id); + }, + + // 复制流程定义 + copyDef: (id) => { + return getRequest('/flow/definition/copyDef/' + id); + }, + // 激活流程 + active: (definitionId) => { + return getRequest('/flow/definition/active/' + definitionId); + }, + + // 挂起流程 + unActive: (definitionId) => { + return getRequest('/flow/definition/unActive/' + definitionId); + }, + // 导入流程定义 + importDefinition: (file) => { + return postRequest('/flow/definition/importDefinition', file); + }, + // 导出流程定义 + export: (record) => { + return postDownload('/flow/definition/exportDefinition/' + record.id, record.flowCode + '_' + record.version + '.json'); + } +}; diff --git a/smart-flow-web/src/api/flow/instance-api.js b/smart-flow-web/src/api/flow/instance-api.js new file mode 100644 index 0000000..2fc4813 --- /dev/null +++ b/smart-flow-web/src/api/flow/instance-api.js @@ -0,0 +1,95 @@ +import {postRequest, getRequest} from "/@/lib/axios.js"; + +export const instanceApi = { + /** + * 启动流程 + * @param data + * @returns {*} + */ +startWorkFlow : (data) => { + return postRequest('/flow/execute/startWorkFlow',data); +}, + /** + * 审批流程 + * @param data + * @returns {*} + */ + approveTaskByInstance : (data) => { + return postRequest('/flow/execute/approveTaskByInstance',data); + }, + +/** + * 办理流程 + * @param data + * @returns {*} + */ +completeTask :(data) => { + return postRequest('/flow/execute/completeTask', data); +}, + /** + * 查询待办任务列表 @author lovefawn + */ + toDoPage: (query) => { + return getRequest('/flow/execute/toDoPage', query); + }, + + /** + * 查询已办任务列表 @author lovefawn + */ + donePage: (query) => { + return getRequest('/flow/execute/donePage', query); + }, + + /** + * 查询抄送任务列表 @author lovefawn + */ + copyPage: (query) => { + return getRequest('/flow/execute/copyPage', query); + }, + + /** + * 查询实例已办列表 @author lovefawn + */ + doneList: (instanceId) => { + return getRequest(`/flow/execute/doneList/${instanceId}`); + }, + + /** + * 查询跳转节点列表 @author lovefawn + */ + anyNodeList: (instanceId) => { + return getRequest(`/flow/execute/anyNodeList/${instanceId}`); + }, + + /** + * 任务操作(转办/加签/委派/减签) @author lovefawn + */ + interactiveType: (params) => { + return postRequest('/flow/execute/interactiveType', params); + }, + + // 查询用户列表-转办|加签|委派|减签 + interactiveTypeEmployeeEntity:(query) => {return getRequest('/flow/execute/interactiveTypeEmployeeEntity', query); + }, + + /** + * 通过ID查询任务详情 @author lovefawn + */ + getTaskById: (taskId) => { + return getRequest(`/flow/execute/getTaskById/${taskId}`); + }, + + /** + * 激活流程实例 @author lovefawn + */ + active: (instanceId) => { + return getRequest(`/flow/execute/active/${instanceId}`); + }, + + /** + * 挂起流程实例 @author lovefawn + */ + unActive: (instanceId) => { + return getRequest(`/flow/execute/unActive/${instanceId}`); + }, +} \ No newline at end of file diff --git a/smart-flow-web/src/api/support/api-encrypt-api.js b/smart-flow-web/src/api/support/api-encrypt-api.js new file mode 100644 index 0000000..83f9ff4 --- /dev/null +++ b/smart-flow-web/src/api/support/api-encrypt-api.js @@ -0,0 +1,40 @@ +/** + * 接口:加密、解密 + * + * @Author: 1024创新实验室-主任-卓大 + * @Date: 2023-10-17 20:02:37 + * @Copyright 1024创新实验室 + */ +import { postRequest, postEncryptRequest } from '/@/lib/axios'; + +export const encryptApi = { + + /** + * 测试 请求加密 @author 1024创新实验室-主任-卓大 + */ + testRequestEncrypt: (param) => { + return postEncryptRequest('/support/apiEncrypt/testRequestEncrypt', param); + }, + + /** + * 测试 返回加密 @author 1024创新实验室-主任-卓大 + */ + testResponseEncrypt: (param) => { + return postRequest('/support/apiEncrypt/testResponseEncrypt', param); + }, + + /** + * 测试 请求参数加密和解密、返回数据加密和解密 @author 1024创新实验室-主任-卓大 + */ + testDecryptAndEncrypt: (param) => { + return postEncryptRequest('/support/apiEncrypt/testDecryptAndEncrypt', param); + }, + + /** + * 测试 数组加解密 @author 1024创新实验室-主任-卓大 + */ + testArray : (param) => { + return postEncryptRequest('/support/apiEncrypt/testArray', param); + }, + +}; diff --git a/smart-flow-web/src/api/support/cache-api.js b/smart-flow-web/src/api/support/cache-api.js new file mode 100644 index 0000000..5cb4d37 --- /dev/null +++ b/smart-flow-web/src/api/support/cache-api.js @@ -0,0 +1,25 @@ +/* + * 缓存 + * + * @Author: 罗伊 + * @Date: 2022-09-03 21:51:34 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import {getRequest} from '/@/lib/axios'; + +export const cacheApi = { + // 获取某个缓存的所有key @author 罗伊 + getKeys: (cacheName) => { + return getRequest(`/support/cache/keys/${cacheName}`); + }, + // 移除某个缓存 @author 罗伊 + remove: (cacheName) => { + return getRequest(`/support/cache/remove/${cacheName}`); + }, + // 获取所有缓存 @author 罗伊 + getAllCacheNames: () => { + return getRequest('/support/cache/names'); + }, +}; diff --git a/smart-flow-web/src/api/support/change-log-api.js b/smart-flow-web/src/api/support/change-log-api.js new file mode 100644 index 0000000..e5ce1cb --- /dev/null +++ b/smart-flow-web/src/api/support/change-log-api.js @@ -0,0 +1,45 @@ +/** + * 系统更新日志 api 封装 + * + * @Author: 卓大 + * @Date: 2022-09-26 14:53:50 + * @Copyright 1024创新实验室 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const changeLogApi = { + /** + * 分页查询 @author 卓大 + */ + queryPage: (param) => { + return postRequest('/support/changeLog/queryPage', param); + }, + + /** + * 增加 @author 卓大 + */ + add: (param) => { + return postRequest('/support/changeLog/add', param); + }, + + /** + * 修改 @author 卓大 + */ + update: (param) => { + return postRequest('/support/changeLog/update', param); + }, + + /** + * 删除 @author 卓大 + */ + delete: (id) => { + return getRequest(`/support/changeLog/delete/${id}`); + }, + + /** + * 批量删除 @author 卓大 + */ + batchDelete: (idList) => { + return postRequest('/support/changeLog/batchDelete', idList); + }, +}; diff --git a/smart-flow-web/src/api/support/code-generator-api.js b/smart-flow-web/src/api/support/code-generator-api.js new file mode 100644 index 0000000..7289b62 --- /dev/null +++ b/smart-flow-web/src/api/support/code-generator-api.js @@ -0,0 +1,46 @@ +/* + * 代码生成器 + * + * @Author: 卓大 + * @Date: 2022-09-03 21:51:54 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest, postRequest, getDownload } from '/@/lib/axios'; + +export const codeGeneratorApi = { + // 查询数据库的表 @author 卓大 + queryTableList: (param) => { + return postRequest('/support/codeGenerator/table/queryTableList', param); + }, + + // 查询表的列 @author 卓大 + getTableColumns: (table) => { + return getRequest(`/support/codeGenerator/table/getTableColumns/${table}`); + }, + + // ------------------- 配置 ------------------- + + // 获取表的配置信息 @author 卓大 + getConfig: (table) => { + return getRequest(`/support/codeGenerator/table/getConfig/${table}`); + }, + + // 更新配置信息 @author 卓大 + updateConfig: (param) => { + return postRequest('/support/codeGenerator/table/updateConfig', param); + }, + + // ------------------- 生成 ------------------- + + // 预览代码 @author 卓大 + preview: (param) => { + return postRequest('/support/codeGenerator/code/preview', param); + }, + + // 下载代码 @author 卓大 + downloadCode: (tableName) => { + return getDownload(`/support/codeGenerator/code/download/${tableName}`); + }, +}; diff --git a/smart-flow-web/src/api/support/config-api.js b/smart-flow-web/src/api/support/config-api.js new file mode 100644 index 0000000..c5e5397 --- /dev/null +++ b/smart-flow-web/src/api/support/config-api.js @@ -0,0 +1,29 @@ +/* + * 配置 + * + * @Author: 卓大 + * @Date: 2022-09-03 21:51:54 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const configApi = { + // 分页查询 @author 卓大 + queryList: (param) => { + return postRequest('/support/config/query', param); + }, + // 添加配置参数 @author 卓大 + addConfig: (param) => { + return postRequest('/support/config/add', param); + }, + // 修改配置参数 @author 卓大 + updateConfig: (param) => { + return postRequest('/support/config/update', param); + }, + // 查询配置详情 @author 卓大 + queryByKey: (param) => { + return getRequest(`/support/config/queryByKey?configKey=${param}`); + }, +}; diff --git a/smart-flow-web/src/api/support/data-masking-api.js b/smart-flow-web/src/api/support/data-masking-api.js new file mode 100644 index 0000000..8921186 --- /dev/null +++ b/smart-flow-web/src/api/support/data-masking-api.js @@ -0,0 +1,17 @@ +/** + * 数据脱敏api + * + * @Author: 1024创新实验室-主任-卓大 + * @Date: 2024-07-31 21:02:37 + * @Copyright 1024创新实验室 + */ +import { getRequest } from '/@/lib/axios'; + +export const dataMaskingApi = { + /** + * 查询脱敏数据 + */ + query: () => { + return getRequest('/support/dataMasking/demo/query'); + }, +}; diff --git a/smart-flow-web/src/api/support/data-tracer-api.js b/smart-flow-web/src/api/support/data-tracer-api.js new file mode 100644 index 0000000..afa75f8 --- /dev/null +++ b/smart-flow-web/src/api/support/data-tracer-api.js @@ -0,0 +1,18 @@ +/* + * 数据变动 + * + * @Author: 卓大 + * @Date: 2022-09-03 21:51:54 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest } from '/@/lib/axios'; + +export const dataTracerApi = { + // 分页查询业务操作日志 - @author 卓大 + queryList: (param) => { + return postRequest('/support/dataTracer/query', param); + }, + +}; diff --git a/smart-flow-web/src/api/support/dict-api.js b/smart-flow-web/src/api/support/dict-api.js new file mode 100644 index 0000000..be56224 --- /dev/null +++ b/smart-flow-web/src/api/support/dict-api.js @@ -0,0 +1,75 @@ +/* + * 字典 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:55:25 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const dictApi = { + + // 获取所有字典code @author 1024创新实验室-主任-卓大 + getAllDict: () => { + return getRequest('/support/dict/getAllDict'); + }, + + // 获取全部字典数据 @author 1024创新实验室-主任-卓大 + getAllDictData: () => { + return getRequest('/support/dict/getAllDictData'); + }, + + // 分页查询 @author 1024创新实验室-主任-卓大 + queryDict: (param) => { + return postRequest('/support/dict/queryPage', param); + }, + + // 添加 @author 1024创新实验室-主任-卓大 + addDict: (param) => { + return postRequest('/support/dict/add', param); + }, + + // 更新 @author 1024创新实验室-主任-卓大 + updateDict: (param) => { + return postRequest('/support/dict/update', param); + }, + + // 字典-删除- @author 卓大 + batchDeleteDict: (dictIdList) => { + return postRequest('/support/dict/batchDelete', dictIdList); + }, + + // 字典 启用 禁用 @author 1024创新实验室-主任-卓大 + updateDisabled: (dictId) => { + return getRequest(`/support/dict/updateDisabled/${dictId}`); + }, + + // ------------- 查询字典数据 ------------- + + // 字典数据 分页查询 @author 1024创新实验室-主任-卓大 + queryDictData: (dictId) => { + return getRequest(`/support/dict/dictData/queryDictData/${dictId}`); + }, + + // 字典数据 添加 - @author 卓大 + addDictData: (param) => { + return postRequest('/support/dict/dictData/add', param); + }, + + // 字典数据 更新- @author 卓大 + updateDictData: (param) => { + return postRequest('/support/dict/dictData/update', param); + }, + + // 字典数据-删除- @author 卓大 + batchDeleteDictData: (dictDataIdList) => { + return postRequest('/support/dict/dictData/batchDelete', dictDataIdList); + }, + + // 字典数据 启用 禁用 @author 1024创新实验室-主任-卓大 + updateDictDataDisabled: (dictDataId) => { + return getRequest(`/support/dict/dictData/updateDisabled/${dictDataId}`); + }, +}; diff --git a/smart-flow-web/src/api/support/feedback-api.js b/smart-flow-web/src/api/support/feedback-api.js new file mode 100644 index 0000000..c951b8a --- /dev/null +++ b/smart-flow-web/src/api/support/feedback-api.js @@ -0,0 +1,21 @@ +/* + * 意见反馈 + * + * @Author: 1024创新实验室:开云 + * @Date: 2022-09-03 21:56:31 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest } from '/@/lib/axios'; + +export const feedbackApi = { + // 意见反馈-新增 + addFeedback: (params) => { + return postRequest('/support/feedback/add', params); + }, + // 意见反馈-分页查询 + queryFeedback: (params) => { + return postRequest('/support/feedback/query', params); + }, +}; diff --git a/smart-flow-web/src/api/support/file-api.js b/smart-flow-web/src/api/support/file-api.js new file mode 100644 index 0000000..7c06d36 --- /dev/null +++ b/smart-flow-web/src/api/support/file-api.js @@ -0,0 +1,38 @@ +/* + * 文件上传 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:55:25 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest, getDownload } from '/@/lib/axios'; + +export const fileApi = { + // 文件上传 @author 卓大 + uploadUrl: '/support/file/upload', + uploadFile: (param, folder) => { + return postRequest(`/support/file/upload?folder=${folder}`, param); + }, + + /** + * 分页查询 @author 卓大 + */ + queryPage: (param) => { + return postRequest('/support/file/queryPage', param); + }, + /** + * 获取文件URL:根据fileKey + */ + getUrl: (fileKey) => { + return getRequest(`/support/file/getFileUrl?fileKey=${fileKey}`); + }, + + /** + * 下载文件流(根据fileKey) + */ + downLoadFile: (fileKey) => { + return getDownload('/support/file/downLoad', { fileKey }); + }, +}; diff --git a/smart-flow-web/src/api/support/heart-beat-api.js b/smart-flow-web/src/api/support/heart-beat-api.js new file mode 100644 index 0000000..0a1eab4 --- /dev/null +++ b/smart-flow-web/src/api/support/heart-beat-api.js @@ -0,0 +1,17 @@ +/* + * 心跳 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:55:47 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest } from '/@/lib/axios'; + +export const heartBeatApi = { + // 分页查询 @author 卓大 + queryList: (param) => { + return postRequest('/support/heartBeat/query', param); + }, +}; diff --git a/smart-flow-web/src/api/support/help-doc-api.js b/smart-flow-web/src/api/support/help-doc-api.js new file mode 100644 index 0000000..dc4fac4 --- /dev/null +++ b/smart-flow-web/src/api/support/help-doc-api.js @@ -0,0 +1,59 @@ +/* + * 帮助文档 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:56:31 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const helpDocApi = { + // 【管理】帮助文档-分页查询 @author zhuoda + query: (param) => { + return postRequest('/support/helpDoc/query', param); + }, + + //【管理】帮助文档-更新 @author zhuoda + update: (param) => { + return postRequest('/support/helpDoc/update', param); + }, + + // 【管理】帮助文档-添加 @author zhuoda + add: (param) => { + return postRequest('/support/helpDoc/add', param); + }, + + //【管理】帮助文档-删除 @author zhuoda + delete: (helpDocId) => { + return getRequest(`/support/helpDoc/delete/${helpDocId}`); + }, + + //【管理】帮助文档-获取详情 @author zhuoda + getDetail: (helpDocId) => { + return getRequest(`/support/helpDoc/getDetail/${helpDocId}`); + }, + + //【管理】帮助文档-根据关联id查询 @author zhuoda + queryHelpDocByRelationId: (relationId) => { + return getRequest(`/support/helpDoc/queryHelpDocByRelationId/${relationId}`); + }, + + //----------------------- 用户相关 -------------------------------- + + //【用户】帮助文档-查询全部 @author zhuoda + getAllHelpDocList() { + return getRequest('/support/helpDoc/user/queryAllHelpDocList'); + }, + + //【用户】帮助文档-查询全部 @author zhuoda + view(helpDocId) { + return getRequest(`/support/helpDoc/user/view/${helpDocId}`); + }, + + //【用户】帮助文档-查询 查看记录 @author zhuoda + queryViewRecord(param) { + return postRequest('/support/helpDoc/user/queryViewRecord', param); + }, +}; diff --git a/smart-flow-web/src/api/support/help-doc-catalog-api.js b/smart-flow-web/src/api/support/help-doc-catalog-api.js new file mode 100644 index 0000000..a8fd6c6 --- /dev/null +++ b/smart-flow-web/src/api/support/help-doc-catalog-api.js @@ -0,0 +1,32 @@ +/* + * 帮助文档 目录 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:56:31 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const helpDocCatalogApi = { + //帮助文档目录-获取全部 @author zhuoda + getAll: () => { + return getRequest('/support/helpDoc/helpDocCatalog/getAll'); + }, + + //帮助文档目录-添加 @author zhuoda + add: (param) => { + return postRequest('/support/helpDoc/helpDocCatalog/add', param); + }, + + //帮助文档目录-更新 @author zhuoda + update: (param) => { + return postRequest('/support/helpDoc/helpDocCatalog/update', param); + }, + + //帮助文档目录-删除 @author zhuoda + delete: (helpDocCatalogId) => { + return getRequest(`/support/helpDoc/helpDocCatalog/delete/${helpDocCatalogId}`); + }, +}; diff --git a/smart-flow-web/src/api/support/job-api.js b/smart-flow-web/src/api/support/job-api.js new file mode 100644 index 0000000..2d9e060 --- /dev/null +++ b/smart-flow-web/src/api/support/job-api.js @@ -0,0 +1,42 @@ +/* + * job api + * + * @Author: huke + * @Date: 2024/06/25 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const jobApi = { + // 分页查询 @huke + queryJob: (param) => { + return postRequest('/support/job/query', param); + }, + // 定时任务-查询详情 @huke + queryJobInfo: (param) => { + return getRequest(`/support/job/${param}`); + }, + // 执行任务 @huke + executeJob: (param) => { + return postRequest('/support/job/execute', param); + }, + // 定时任务-新增-任务信息 @huke + addJob: (param) => { + return postRequest('/support/job/add', param); + }, + // 定时任务-更新-任务信息 @huke + updateJob: (param) => { + return postRequest('/support/job/update', param); + }, + // 定时任务-更新-开启状态 @huke + updateJobEnabled: (param) => { + return postRequest('/support/job/update/enabled', param); + }, + // 定时任务-执行记录-分页查询 @huke + queryJobLog: (param) => { + return postRequest('/support/job/log/query', param); + }, + // 定时任务-删除 @zhuoda + deleteJob: (param) => { + return getRequest(`/support/job/delete?jobId=${param}`); + }, +}; diff --git a/smart-flow-web/src/api/support/level3-protect-api.js b/smart-flow-web/src/api/support/level3-protect-api.js new file mode 100644 index 0000000..2e99db2 --- /dev/null +++ b/smart-flow-web/src/api/support/level3-protect-api.js @@ -0,0 +1,24 @@ +/** + * 三级等保 api 封装 + * + * @Author: 1024创新实验室-主任-卓大 + * @Date: 2024-07-31 21:02:37 + * @Copyright 1024创新实验室 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const level3ProtectApi = { + /** + * 查询 三级等保配置 @author 1024创新实验室-主任-卓大 + */ + getConfig: () => { + return getRequest('/support/protect/level3protect/getConfig'); + }, + + /** + * 更新三级等保配置 @author 1024创新实验室-主任-卓大 + */ + updateConfig: (form) => { + return postRequest('/support/protect/level3protect/updateConfig', form); + }, +}; diff --git a/smart-flow-web/src/api/support/login-fail-api.js b/smart-flow-web/src/api/support/login-fail-api.js new file mode 100644 index 0000000..42888d3 --- /dev/null +++ b/smart-flow-web/src/api/support/login-fail-api.js @@ -0,0 +1,26 @@ +/** + * 登录锁定 api 封装 + * + * @Author: 1024创新实验室-主任-卓大 + * @Date: 2023-10-17 18:02:37 + * @Copyright 1024创新实验室 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const loginFailApi = { + + /** + * 分页查询 @author 1024创新实验室-主任-卓大 + */ + queryPage : (param) => { + return postRequest('/support/protect/loginFail/queryPage', param); + }, + + /** + * 批量删除 @author 1024创新实验室-主任-卓大 + */ + batchDelete: (idList) => { + return postRequest('/support/protect/loginFail/batchDelete', idList); + }, + +}; diff --git a/smart-flow-web/src/api/support/login-log-api.js b/smart-flow-web/src/api/support/login-log-api.js new file mode 100644 index 0000000..d447c0b --- /dev/null +++ b/smart-flow-web/src/api/support/login-log-api.js @@ -0,0 +1,21 @@ +/* + * 登录日志 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:56:31 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const loginLogApi = { + // 分页查询 @author 卓大 + queryList: (param) => { + return postRequest('/support/loginLog/page/query', param); + }, + // 分页查询当前登录人信息 @author 善逸 + queryListLogin: (param) => { + return postRequest('/support/loginLog/page/query/login', param); + }, +}; diff --git a/smart-flow-web/src/api/support/message-api.js b/smart-flow-web/src/api/support/message-api.js new file mode 100644 index 0000000..4716e54 --- /dev/null +++ b/smart-flow-web/src/api/support/message-api.js @@ -0,0 +1,31 @@ +import { getRequest, postRequest } from '/@/lib/axios'; + +export const messageApi = { + // 通知消息-分页查询 + queryMessage: (param) => { + return postRequest('/support/message/queryMyMessage', param); + }, + // 通知消息-查询未读消息数 + queryUnreadCount: () => { + return getRequest('/support/message/getUnreadCount'); + }, + // 通知消息-标记已读 + updateReadFlag: (messageId) => { + return getRequest(`/support/message/read/${messageId}`); + }, + + //通知消息-分页查询 @author 卓大 + queryAdminMessage: (param) => { + return postRequest('/message/query', param); + }, + + //通知消息-新建 @author 卓大 + sendMessages: (param) => { + return postRequest('/message/sendMessages', param); + }, + + //通知消息-删除 @author 卓大 + deleteMessage: (messageId) => { + return getRequest(`/message/delete/${messageId}`); + }, +}; diff --git a/smart-flow-web/src/api/support/operate-log-api.js b/smart-flow-web/src/api/support/operate-log-api.js new file mode 100644 index 0000000..80e6c61 --- /dev/null +++ b/smart-flow-web/src/api/support/operate-log-api.js @@ -0,0 +1,29 @@ +/* + * 操作日志 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:56:45 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const operateLogApi = { + // 分页查询 @author 卓大 + queryList: (param) => { + return postRequest('/support/operateLog/page/query', param); + }, + // 详情 @author 卓大 + detail: (id) => { + return getRequest(`/support/operateLog/detail/${id}`); + }, + // 分页查询当前登录人信息 @author 善逸 + queryListLogin: (param) => { + return postRequest('/support/operateLog/page/query/login', param); + }, + // 操作模块下拉(去重) + queryModuleList: () => { + return getRequest('/support/operateLog/module/list'); + }, +}; diff --git a/smart-flow-web/src/api/support/reload-api.js b/smart-flow-web/src/api/support/reload-api.js new file mode 100644 index 0000000..721d563 --- /dev/null +++ b/smart-flow-web/src/api/support/reload-api.js @@ -0,0 +1,25 @@ +/* + * reload (内存热加载、钩子等) + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:57:19 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const reloadApi = { + // 查询reload列表 @author 卓大 + queryList: () => { + return getRequest('/support/reload/query'); + }, + // 获取reload result @author 卓大 + queryReloadResult: (tag) => { + return getRequest(`/support/reload/result/${tag}`); + }, + // 执行reload @author 卓大 + reload: (reloadForm) => { + return postRequest('/support/reload/update', reloadForm); + }, +}; diff --git a/smart-flow-web/src/api/support/serial-number-api.js b/smart-flow-web/src/api/support/serial-number-api.js new file mode 100644 index 0000000..b9ae35a --- /dev/null +++ b/smart-flow-web/src/api/support/serial-number-api.js @@ -0,0 +1,25 @@ +/* + * 单据序列号 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:57:52 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const serialNumberApi = { + // 生成单号 @author 卓大 + generate: (generateForm) => { + return postRequest('/support/serialNumber/generate', generateForm); + }, + // 获取所有单号定义 @author 卓大 + getAll: () => { + return getRequest('/support/serialNumber/all'); + }, + // 获取生成记录 @author 卓大 + queryRecord: (form) => { + return postRequest('/support/serialNumber/queryRecord', form); + }, +}; diff --git a/smart-flow-web/src/api/support/table-column-api.js b/smart-flow-web/src/api/support/table-column-api.js new file mode 100644 index 0000000..7223ab9 --- /dev/null +++ b/smart-flow-web/src/api/support/table-column-api.js @@ -0,0 +1,26 @@ +/* + * @Description:表格自定义列 + * @version: + * @Author: zhuoda + * @Date: 2022-08-17 23:32:36 + * @LastEditors: zhuoda + * @LastEditTime: 2022-08-21 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const tableColumnApi = { + // 修改表格列 @author zhuoda + updateTableColumn: (param) => { + return postRequest('/support/tableColumn/update', param); + }, + + // 查询表格列 @author zhuoda + getColumns: (tableId) => { + return getRequest(`/support/tableColumn/getColumns/${tableId}`); + }, + + // 删除表格列 @author zhuoda + deleteColumns: (tableId) => { + return getRequest(`/support/tableColumn/delete/${tableId}`); + }, +}; diff --git a/smart-flow-web/src/api/system/department-api.js b/smart-flow-web/src/api/system/department-api.js new file mode 100644 index 0000000..c34994c --- /dev/null +++ b/smart-flow-web/src/api/system/department-api.js @@ -0,0 +1,45 @@ +/* + * 部门 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:58:50 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest, postRequest } from '/@/lib/axios'; + +export const departmentApi = { + /** + * 查询部门列表 @author 卓大 + */ + queryAllDepartment: () => { + return getRequest('/department/listAll'); + }, + + /** + * 查询部门树形列表 @author 卓大 + */ + queryDepartmentTree: () => { + return getRequest('/department/treeList'); + }, + + /** + * 添加部门 @author 卓大 + */ + addDepartment: (param) => { + return postRequest('/department/add', param); + }, + /** + * 更新部门信息 @author 卓大 + */ + updateDepartment: (param) => { + return postRequest('/department/update', param); + }, + /** + * 删除 + */ + deleteDepartment: (departmentId) => { + return getRequest(`/department/delete/${departmentId}`); + }, +}; diff --git a/smart-flow-web/src/api/system/employee-api.js b/smart-flow-web/src/api/system/employee-api.js new file mode 100644 index 0000000..cb4ec95 --- /dev/null +++ b/smart-flow-web/src/api/system/employee-api.js @@ -0,0 +1,98 @@ +/* + * 员工 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:59:15 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import { getRequest, postEncryptRequest, postRequest } from '/@/lib/axios'; + +export const employeeApi = { + /** + * 查询所有员工 @author 卓大 + */ + queryAll: () => { + return getRequest('/employee/queryAll'); + }, + /** + * 员工管理查询 + */ + queryEmployee: (params) => { + return postRequest('/employee/query', params); + }, + /** + * 添加员工 + */ + addEmployee: (params) => { + return postRequest('/employee/add', params); + }, + /** + * 更新员工信息 + */ + updateEmployee: (params) => { + return postRequest('/employee/update', params); + }, + /** + * 更新员工个人中心信息 + */ + updateCenter: (params) => { + return postRequest('/employee/update/center', params); + }, + /** + * 更新登录人头像 + */ + updateAvatar: (params) => { + return postRequest('/employee/update/avatar', params); + }, + /** + * 删除员工 + */ + deleteEmployee: (employeeId) => { + return getRequest(`/employee/delete/${employeeId}`); + }, + /** + * 批量删除员工 + */ + batchDeleteEmployee: (employeeIdList) => { + return postRequest('/employee/update/batch/delete', employeeIdList); + }, + /** + * 批量调整员工部门 + */ + batchUpdateDepartmentEmployee: (updateParam) => { + return postRequest('/employee/update/batch/department', updateParam); + }, + /** + * 重置员工密码 + */ + resetPassword: (employeeId) => { + return getRequest(`/employee/update/password/reset/${employeeId}`); + }, + /** + * 修改密码 + */ + updateEmployeePassword: (param) => { + return postEncryptRequest('/employee/update/password', param); + }, + /** + * 获取密码复杂度 + */ + getPasswordComplexityEnabled: () => { + return getRequest('/employee/getPasswordComplexityEnabled'); + }, + /** + * 更新员工禁用状态 + */ + updateDisabled: (employeeId) => { + return getRequest(`/employee/update/disabled/${employeeId}`); + }, + /** + * 查询员工-根据部门id + */ + queryEmployeeByDeptId: (departmentId) => { + return getRequest(`/employee/getAllEmployeeByDepartmentId/${departmentId}`); + }, +}; diff --git a/smart-flow-web/src/api/system/home-api.js b/smart-flow-web/src/api/system/home-api.js new file mode 100644 index 0000000..2b71ecb --- /dev/null +++ b/smart-flow-web/src/api/system/home-api.js @@ -0,0 +1,25 @@ +/* + * 首页api + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:59:39 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest } from '/@/lib/axios'; + +export const homeApi = { + /** + * @description: 首页-金额统计(业绩、收款、订单数等) @author 卓大 + */ + homeAmountStatistics: () => { + return getRequest('/home/amount/statistics'); + }, + /** + * @description: 首页-待办信息 @author 卓大 + */ + homeWaitHandle: () => { + return getRequest('home/wait/handle'); + }, +}; diff --git a/smart-flow-web/src/api/system/login-api.js b/smart-flow-web/src/api/system/login-api.js new file mode 100644 index 0000000..7cb5909 --- /dev/null +++ b/smart-flow-web/src/api/system/login-api.js @@ -0,0 +1,54 @@ +/* + * 登录 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 21:59:58 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest, postRequest } from '/@/lib/axios'; + +export const loginApi = { + /** + * 登录 @author 卓大 + */ + login: (param) => { + return postRequest('/login', param); + }, + + /** + * 退出登录 @author 卓大 + */ + logout: () => { + return getRequest('/login/logout'); + }, + + /** + * 获取验证码 @author 卓大 + */ + getCaptcha: () => { + return getRequest('/login/getCaptcha'); + }, + + /** + * 获取登录信息 @author 卓大 + */ + getLoginInfo: () => { + return getRequest('/login/getLoginInfo'); + }, + + /** + * 获取邮箱登录验证码 @author 卓大 + */ + sendLoginEmailCode: (loginName) => { + return getRequest(`/login/sendEmailCode/${loginName}`); + }, + + /** + * 获取双因子登录标识 @author 卓大 + */ + getTwoFactorLoginFlag: () => { + return getRequest('/login/getTwoFactorLoginFlag'); + }, +}; diff --git a/smart-flow-web/src/api/system/menu-api.js b/smart-flow-web/src/api/system/menu-api.js new file mode 100644 index 0000000..43c8872 --- /dev/null +++ b/smart-flow-web/src/api/system/menu-api.js @@ -0,0 +1,54 @@ +/* + * 菜单 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:00:32 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest, postRequest } from '/@/lib/axios'; + +export const menuApi = { + /** + * 添加菜单 + */ + addMenu: (param) => { + return postRequest('/menu/add', param); + }, + + /** + * 更新菜单 + */ + updateMenu: (param) => { + return postRequest('/menu/update', param); + }, + + /** + * 批量删除菜单 + */ + batchDeleteMenu: (menuIdList) => { + return getRequest(`/menu/batchDelete?menuIdList=${menuIdList}`); + }, + + /** + * 查询所有菜单列表 + */ + queryMenu: () => { + return getRequest('/menu/query'); + }, + + /** + * 查询菜单树 + */ + queryMenuTree: (onlyMenu) => { + return getRequest(`/menu/tree?onlyMenu=${onlyMenu}`); + }, + + /** + * 获取所有请求路径 + */ + getAuthUrl: () => { + return getRequest('/menu/auth/url'); + }, +}; diff --git a/smart-flow-web/src/api/system/position-api.js b/smart-flow-web/src/api/system/position-api.js new file mode 100644 index 0000000..e6d0990 --- /dev/null +++ b/smart-flow-web/src/api/system/position-api.js @@ -0,0 +1,55 @@ +/** + * 职务表 api 封装 + * + * @Author: kaiyun + * @Date: 2024-06-23 23:31:38 + * @Copyright 1024创新实验室 + */ +import { postRequest, getRequest } from '/@/lib/axios'; + +export const positionApi = { + + /** + * 分页查询 @author kaiyun + */ + queryPage : (param) => { + return postRequest('/position/queryPage', param); + }, + + /** + * 增加 @author kaiyun + */ + add: (param) => { + return postRequest('/position/add', param); + }, + + /** + * 修改 @author kaiyun + */ + update: (param) => { + return postRequest('/position/update', param); + }, + + + /** + * 删除 @author kaiyun + */ + delete: (id) => { + return getRequest(`/position/delete/${id}`); + }, + + /** + * 批量删除 @author kaiyun + */ + batchDelete: (idList) => { + return postRequest('/position/batchDelete', idList); + }, + + /** + * 查询列表 @author kaiyun + */ + queryList: () => { + return getRequest('/position/queryList'); + }, + +}; diff --git a/smart-flow-web/src/api/system/role-api.js b/smart-flow-web/src/api/system/role-api.js new file mode 100644 index 0000000..0b62bb6 --- /dev/null +++ b/smart-flow-web/src/api/system/role-api.js @@ -0,0 +1,85 @@ +/* + * 角色 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:00:41 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest, postRequest } from '/@/lib/axios'; + +export const roleApi = { + /** + * @description: 获取所有角色 + */ + queryAll: () => { + return getRequest('/role/getAll'); + }, + /** + * @description:添加角色 + */ + addRole: (data) => { + return postRequest('/role/add', data); + }, + /** + * @description:更新角色 + */ + updateRole: (data) => { + return postRequest('/role/update', data); + }, + /** + * @description: 删除角色 + */ + deleteRole: (roleId) => { + return getRequest(`/role/delete/${roleId}`); + }, + /** + * @description: 批量设置某角色数据范围 + */ + updateDataScope: (data) => { + return postRequest('/role/dataScope/updateRoleDataScopeList', data); + }, + /** + * @description: 获取当前系统所配置的所有数据范围 + */ + getDataScopeList: () => { + return getRequest('/dataScope/list'); + }, + /** + * @description: 获取某角色所设置的数据范围 + */ + getDataScopeByRoleId: (roleId) => { + return getRequest(`/role/dataScope/getRoleDataScopeList/${roleId}`); + }, + /** + * @description: 获取角色成员-员工列表 + */ + queryRoleEmployee: (params) => { + return postRequest('/role/employee/queryEmployee', params); + }, + /** + * @description: 从角色成员列表中移除员工 + */ + deleteEmployeeRole: (employeeId, roleId) => { + return getRequest('/role/employee/removeEmployee?employeeId=' + employeeId + '&roleId=' + roleId); + }, + /** + * @description: 从角色成员列表中批量移除员工 + */ + batchRemoveRoleEmployee: (data) => { + return postRequest('/role/employee/batchRemoveRoleEmployee', data); + }, + /** + * @description: 根据角色id获取角色员工列表(无分页) + */ + getRoleAllEmployee: (roleId) => { + return getRequest(`/role/employee/getAllEmployeeByRoleId/${roleId}`); + }, + /** + * @description: 角色成员列表中批量添加员工 + */ + batchAddRoleEmployee: (data) => { + return postRequest('/role/employee/batchAddRoleEmployee', data); + }, +}; diff --git a/smart-flow-web/src/api/system/role-menu-api.js b/smart-flow-web/src/api/system/role-menu-api.js new file mode 100644 index 0000000..37096a9 --- /dev/null +++ b/smart-flow-web/src/api/system/role-menu-api.js @@ -0,0 +1,24 @@ +/* + * 角色菜单 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:00:49 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { getRequest, postRequest } from '/@/lib/axios'; +export const roleMenuApi = { + /** + * @description: 获取角色关联菜单权限 + */ + getRoleSelectedMenu: (roleId) => { + return getRequest(`role/menu/getRoleSelectedMenu/${roleId}`); + }, + /** + * @description: 更新角色权限 + */ + updateRoleMenu: (data) => { + return postRequest('role/menu/updateRoleMenu', data); + }, +}; diff --git a/smart-flow-web/src/assets/images/1024lab/1024lab-gzh.jpg b/smart-flow-web/src/assets/images/1024lab/1024lab-gzh.jpg new file mode 100644 index 0000000..d6b03f5 Binary files /dev/null and b/smart-flow-web/src/assets/images/1024lab/1024lab-gzh.jpg differ diff --git a/smart-flow-web/src/assets/images/1024lab/gzh.jpg b/smart-flow-web/src/assets/images/1024lab/gzh.jpg new file mode 100644 index 0000000..a55e8d9 Binary files /dev/null and b/smart-flow-web/src/assets/images/1024lab/gzh.jpg differ diff --git a/smart-flow-web/src/assets/images/1024lab/xiaozhen-gzh.jpg b/smart-flow-web/src/assets/images/1024lab/xiaozhen-gzh.jpg new file mode 100644 index 0000000..9c6319e Binary files /dev/null and b/smart-flow-web/src/assets/images/1024lab/xiaozhen-gzh.jpg differ diff --git a/smart-flow-web/src/assets/images/1024lab/zhuoda-wechat.jpg b/smart-flow-web/src/assets/images/1024lab/zhuoda-wechat.jpg new file mode 100644 index 0000000..9e11778 Binary files /dev/null and b/smart-flow-web/src/assets/images/1024lab/zhuoda-wechat.jpg differ diff --git a/smart-flow-web/src/assets/images/login/ali-icon.png b/smart-flow-web/src/assets/images/login/ali-icon.png new file mode 100644 index 0000000..c81d647 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/ali-icon.png differ diff --git a/smart-flow-web/src/assets/images/login/blue-login-bg.png b/smart-flow-web/src/assets/images/login/blue-login-bg.png new file mode 100644 index 0000000..706cb9c Binary files /dev/null and b/smart-flow-web/src/assets/images/login/blue-login-bg.png differ diff --git a/smart-flow-web/src/assets/images/login/douyin-icon.png b/smart-flow-web/src/assets/images/login/douyin-icon.png new file mode 100644 index 0000000..82525fe Binary files /dev/null and b/smart-flow-web/src/assets/images/login/douyin-icon.png differ diff --git a/smart-flow-web/src/assets/images/login/feishu-icon.png b/smart-flow-web/src/assets/images/login/feishu-icon.png new file mode 100644 index 0000000..dc8468c Binary files /dev/null and b/smart-flow-web/src/assets/images/login/feishu-icon.png differ diff --git a/smart-flow-web/src/assets/images/login/google-icon.png b/smart-flow-web/src/assets/images/login/google-icon.png new file mode 100644 index 0000000..465069c Binary files /dev/null and b/smart-flow-web/src/assets/images/login/google-icon.png differ diff --git a/smart-flow-web/src/assets/images/login/left-bg1.png b/smart-flow-web/src/assets/images/login/left-bg1.png new file mode 100644 index 0000000..83084aa Binary files /dev/null and b/smart-flow-web/src/assets/images/login/left-bg1.png differ diff --git a/smart-flow-web/src/assets/images/login/left-bg2.png b/smart-flow-web/src/assets/images/login/left-bg2.png new file mode 100644 index 0000000..ba4eaec Binary files /dev/null and b/smart-flow-web/src/assets/images/login/left-bg2.png differ diff --git a/smart-flow-web/src/assets/images/login/login-bg.png b/smart-flow-web/src/assets/images/login/login-bg.png new file mode 100644 index 0000000..16cf505 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login-bg.png differ diff --git a/smart-flow-web/src/assets/images/login/login-bg2.png b/smart-flow-web/src/assets/images/login/login-bg2.png new file mode 100644 index 0000000..fa33669 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login-bg2.png differ diff --git a/smart-flow-web/src/assets/images/login/login-bg3.png b/smart-flow-web/src/assets/images/login/login-bg3.png new file mode 100644 index 0000000..5533b14 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login-bg3.png differ diff --git a/smart-flow-web/src/assets/images/login/login-bg4 .png b/smart-flow-web/src/assets/images/login/login-bg4 .png new file mode 100644 index 0000000..cb51b61 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login-bg4 .png differ diff --git a/smart-flow-web/src/assets/images/login/login-form-open-eyes-close.png b/smart-flow-web/src/assets/images/login/login-form-open-eyes-close.png new file mode 100644 index 0000000..89f8530 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login-form-open-eyes-close.png differ diff --git a/smart-flow-web/src/assets/images/login/login-form-open-eyes.png b/smart-flow-web/src/assets/images/login/login-form-open-eyes.png new file mode 100644 index 0000000..f8eb3d7 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login-form-open-eyes.png differ diff --git a/smart-flow-web/src/assets/images/login/login-qr.png b/smart-flow-web/src/assets/images/login/login-qr.png new file mode 100644 index 0000000..9f00281 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login-qr.png differ diff --git a/smart-flow-web/src/assets/images/login/login.gif b/smart-flow-web/src/assets/images/login/login.gif new file mode 100644 index 0000000..15cb607 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/login.gif differ diff --git a/smart-flow-web/src/assets/images/login/qq-icon.png b/smart-flow-web/src/assets/images/login/qq-icon.png new file mode 100644 index 0000000..2b1e45e Binary files /dev/null and b/smart-flow-web/src/assets/images/login/qq-icon.png differ diff --git a/smart-flow-web/src/assets/images/login/wechat-icon.png b/smart-flow-web/src/assets/images/login/wechat-icon.png new file mode 100644 index 0000000..644137b Binary files /dev/null and b/smart-flow-web/src/assets/images/login/wechat-icon.png differ diff --git a/smart-flow-web/src/assets/images/login/weibo-icon.png b/smart-flow-web/src/assets/images/login/weibo-icon.png new file mode 100644 index 0000000..e0ff440 Binary files /dev/null and b/smart-flow-web/src/assets/images/login/weibo-icon.png differ diff --git a/smart-flow-web/src/assets/images/logo/logo-min.png b/smart-flow-web/src/assets/images/logo/logo-min.png new file mode 100644 index 0000000..0691a0e Binary files /dev/null and b/smart-flow-web/src/assets/images/logo/logo-min.png differ diff --git a/smart-flow-web/src/assets/images/logo/logo.png b/smart-flow-web/src/assets/images/logo/logo.png new file mode 100644 index 0000000..0691a0e Binary files /dev/null and b/smart-flow-web/src/assets/images/logo/logo.png differ diff --git a/smart-flow-web/src/assets/images/logo/smart-admin-logo-white.png b/smart-flow-web/src/assets/images/logo/smart-admin-logo-white.png new file mode 100644 index 0000000..7efd997 Binary files /dev/null and b/smart-flow-web/src/assets/images/logo/smart-admin-logo-white.png differ diff --git a/smart-flow-web/src/assets/images/logo/smart-admin-logo.png b/smart-flow-web/src/assets/images/logo/smart-admin-logo.png new file mode 100644 index 0000000..48a7b16 Binary files /dev/null and b/smart-flow-web/src/assets/images/logo/smart-admin-logo.png differ diff --git a/smart-flow-web/src/assets/images/nav/active_bg2.svg b/smart-flow-web/src/assets/images/nav/active_bg2.svg new file mode 100644 index 0000000..60a4b36 --- /dev/null +++ b/smart-flow-web/src/assets/images/nav/active_bg2.svg @@ -0,0 +1,3 @@ + + + diff --git a/smart-flow-web/src/assets/images/nav/active_bg2_default.svg b/smart-flow-web/src/assets/images/nav/active_bg2_default.svg new file mode 100644 index 0000000..5a55527 --- /dev/null +++ b/smart-flow-web/src/assets/images/nav/active_bg2_default.svg @@ -0,0 +1,3 @@ + + + diff --git a/smart-flow-web/src/assets/images/notice/edit_icon.png b/smart-flow-web/src/assets/images/notice/edit_icon.png new file mode 100644 index 0000000..6cb12f0 Binary files /dev/null and b/smart-flow-web/src/assets/images/notice/edit_icon.png differ diff --git a/smart-flow-web/src/assets/images/notice/file_icon.png b/smart-flow-web/src/assets/images/notice/file_icon.png new file mode 100644 index 0000000..70c88d8 Binary files /dev/null and b/smart-flow-web/src/assets/images/notice/file_icon.png differ diff --git a/smart-flow-web/src/components/business/category-tree-select/index.vue b/smart-flow-web/src/components/business/category-tree-select/index.vue new file mode 100644 index 0000000..0a7fdfe --- /dev/null +++ b/smart-flow-web/src/components/business/category-tree-select/index.vue @@ -0,0 +1,86 @@ + + + + diff --git a/smart-flow-web/src/components/business/oa/enterprise-bank-select/index.vue b/smart-flow-web/src/components/business/oa/enterprise-bank-select/index.vue new file mode 100644 index 0000000..3fe98ad --- /dev/null +++ b/smart-flow-web/src/components/business/oa/enterprise-bank-select/index.vue @@ -0,0 +1,109 @@ + + + + diff --git a/smart-flow-web/src/components/business/oa/enterprise-invoice-select/index.vue b/smart-flow-web/src/components/business/oa/enterprise-invoice-select/index.vue new file mode 100644 index 0000000..7d6c4ce --- /dev/null +++ b/smart-flow-web/src/components/business/oa/enterprise-invoice-select/index.vue @@ -0,0 +1,108 @@ + + + + diff --git a/smart-flow-web/src/components/business/oa/enterprise-select/index.vue b/smart-flow-web/src/components/business/oa/enterprise-select/index.vue new file mode 100644 index 0000000..97bf474 --- /dev/null +++ b/smart-flow-web/src/components/business/oa/enterprise-select/index.vue @@ -0,0 +1,85 @@ + + + + diff --git a/smart-flow-web/src/components/framework/area-cascader/index.vue b/smart-flow-web/src/components/framework/area-cascader/index.vue new file mode 100644 index 0000000..43e68fe --- /dev/null +++ b/smart-flow-web/src/components/framework/area-cascader/index.vue @@ -0,0 +1,87 @@ + + + + + diff --git a/smart-flow-web/src/components/framework/area-cascader/province-city-district.js b/smart-flow-web/src/components/framework/area-cascader/province-city-district.js new file mode 100644 index 0000000..5d8cbef --- /dev/null +++ b/smart-flow-web/src/components/framework/area-cascader/province-city-district.js @@ -0,0 +1,17546 @@ +export const PROVINCE_CITY_DISTRICT = [ + { + children: [ + { + children: [ + { + children: [], + label: '东城区', + value: 110101, + }, + { + children: [], + label: '西城区', + value: 110102, + }, + { + children: [], + label: '朝阳区', + value: 110105, + }, + { + children: [], + label: '丰台区', + value: 110106, + }, + { + children: [], + label: '石景山区', + value: 110107, + }, + { + children: [], + label: '海淀区', + value: 110108, + }, + { + children: [], + label: '门头沟区', + value: 110109, + }, + { + children: [], + label: '房山区', + value: 110111, + }, + { + children: [], + label: '通州区', + value: 110112, + }, + { + children: [], + label: '顺义区', + value: 110113, + }, + { + children: [], + label: '昌平区', + value: 110114, + }, + { + children: [], + label: '大兴区', + value: 110115, + }, + { + children: [], + label: '怀柔区', + value: 110116, + }, + { + children: [], + label: '平谷区', + value: 110117, + }, + { + children: [], + label: '密云区', + value: 110118, + }, + { + children: [], + label: '延庆区', + value: 110119, + }, + ], + label: '北京市', + value: 110100, + }, + ], + label: '北京市', + value: 110000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '和平区', + value: 120101, + }, + { + children: [], + label: '河东区', + value: 120102, + }, + { + children: [], + label: '河西区', + value: 120103, + }, + { + children: [], + label: '南开区', + value: 120104, + }, + { + children: [], + label: '河北区', + value: 120105, + }, + { + children: [], + label: '红桥区', + value: 120106, + }, + { + children: [], + label: '东丽区', + value: 120110, + }, + { + children: [], + label: '西青区', + value: 120111, + }, + { + children: [], + label: '津南区', + value: 120112, + }, + { + children: [], + label: '北辰区', + value: 120113, + }, + { + children: [], + label: '武清区', + value: 120114, + }, + { + children: [], + label: '宝坻区', + value: 120115, + }, + { + children: [], + label: '滨海新区', + value: 120116, + }, + { + children: [], + label: '宁河区', + value: 120117, + }, + { + children: [], + label: '静海区', + value: 120118, + }, + { + children: [], + label: '蓟州区', + value: 120119, + }, + ], + label: '天津市', + value: 120100, + }, + ], + label: '天津市', + value: 120000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '长安区', + value: 130102, + }, + { + children: [], + label: '桥西区', + value: 130104, + }, + { + children: [], + label: '新华区', + value: 130105, + }, + { + children: [], + label: '井陉矿区', + value: 130107, + }, + { + children: [], + label: '裕华区', + value: 130108, + }, + { + children: [], + label: '藁城区', + value: 130109, + }, + { + children: [], + label: '鹿泉区', + value: 130110, + }, + { + children: [], + label: '栾城区', + value: 130111, + }, + { + children: [], + label: '井陉县', + value: 130121, + }, + { + children: [], + label: '正定县', + value: 130123, + }, + { + children: [], + label: '行唐县', + value: 130125, + }, + { + children: [], + label: '灵寿县', + value: 130126, + }, + { + children: [], + label: '高邑县', + value: 130127, + }, + { + children: [], + label: '深泽县', + value: 130128, + }, + { + children: [], + label: '赞皇县', + value: 130129, + }, + { + children: [], + label: '无极县', + value: 130130, + }, + { + children: [], + label: '平山县', + value: 130131, + }, + { + children: [], + label: '元氏县', + value: 130132, + }, + { + children: [], + label: '赵县', + value: 130133, + }, + { + children: [], + label: '辛集市', + value: 130181, + }, + { + children: [], + label: '晋州市', + value: 130183, + }, + { + children: [], + label: '新乐市', + value: 130184, + }, + ], + label: '石家庄市', + value: 130100, + }, + { + children: [ + { + children: [], + label: '路南区', + value: 130202, + }, + { + children: [], + label: '路北区', + value: 130203, + }, + { + children: [], + label: '古冶区', + value: 130204, + }, + { + children: [], + label: '开平区', + value: 130205, + }, + { + children: [], + label: '丰南区', + value: 130207, + }, + { + children: [], + label: '丰润区', + value: 130208, + }, + { + children: [], + label: '曹妃甸区', + value: 130209, + }, + { + children: [], + label: '滦南县', + value: 130224, + }, + { + children: [], + label: '乐亭县', + value: 130225, + }, + { + children: [], + label: '迁西县', + value: 130227, + }, + { + children: [], + label: '玉田县', + value: 130229, + }, + { + children: [], + label: '遵化市', + value: 130281, + }, + { + children: [], + label: '迁安市', + value: 130283, + }, + { + children: [], + label: '滦州市', + value: 130284, + }, + ], + label: '唐山市', + value: 130200, + }, + { + children: [ + { + children: [], + label: '海港区', + value: 130302, + }, + { + children: [], + label: '山海关区', + value: 130303, + }, + { + children: [], + label: '北戴河区', + value: 130304, + }, + { + children: [], + label: '抚宁区', + value: 130306, + }, + { + children: [], + label: '青龙满族自治县', + value: 130321, + }, + { + children: [], + label: '昌黎县', + value: 130322, + }, + { + children: [], + label: '卢龙县', + value: 130324, + }, + ], + label: '秦皇岛市', + value: 130300, + }, + { + children: [ + { + children: [], + label: '邯山区', + value: 130402, + }, + { + children: [], + label: '丛台区', + value: 130403, + }, + { + children: [], + label: '复兴区', + value: 130404, + }, + { + children: [], + label: '峰峰矿区', + value: 130406, + }, + { + children: [], + label: '肥乡区', + value: 130407, + }, + { + children: [], + label: '永年区', + value: 130408, + }, + { + children: [], + label: '临漳县', + value: 130423, + }, + { + children: [], + label: '成安县', + value: 130424, + }, + { + children: [], + label: '大名县', + value: 130425, + }, + { + children: [], + label: '涉县', + value: 130426, + }, + { + children: [], + label: '磁县', + value: 130427, + }, + { + children: [], + label: '邱县', + value: 130430, + }, + { + children: [], + label: '鸡泽县', + value: 130431, + }, + { + children: [], + label: '广平县', + value: 130432, + }, + { + children: [], + label: '馆陶县', + value: 130433, + }, + { + children: [], + label: '魏县', + value: 130434, + }, + { + children: [], + label: '曲周县', + value: 130435, + }, + { + children: [], + label: '武安市', + value: 130481, + }, + ], + label: '邯郸市', + value: 130400, + }, + { + children: [ + { + children: [], + label: '桥东区', + value: 130502, + }, + { + children: [], + label: '桥西区', + value: 130503, + }, + { + children: [], + label: '邢台县', + value: 130521, + }, + { + children: [], + label: '临城县', + value: 130522, + }, + { + children: [], + label: '内丘县', + value: 130523, + }, + { + children: [], + label: '柏乡县', + value: 130524, + }, + { + children: [], + label: '隆尧县', + value: 130525, + }, + { + children: [], + label: '任县', + value: 130526, + }, + { + children: [], + label: '南和县', + value: 130527, + }, + { + children: [], + label: '宁晋县', + value: 130528, + }, + { + children: [], + label: '巨鹿县', + value: 130529, + }, + { + children: [], + label: '新河县', + value: 130530, + }, + { + children: [], + label: '广宗县', + value: 130531, + }, + { + children: [], + label: '平乡县', + value: 130532, + }, + { + children: [], + label: '威县', + value: 130533, + }, + { + children: [], + label: '清河县', + value: 130534, + }, + { + children: [], + label: '临西县', + value: 130535, + }, + { + children: [], + label: '南宫市', + value: 130581, + }, + { + children: [], + label: '沙河市', + value: 130582, + }, + ], + label: '邢台市', + value: 130500, + }, + { + children: [ + { + children: [], + label: '竞秀区', + value: 130602, + }, + { + children: [], + label: '莲池区', + value: 130606, + }, + { + children: [], + label: '满城区', + value: 130607, + }, + { + children: [], + label: '清苑区', + value: 130608, + }, + { + children: [], + label: '徐水区', + value: 130609, + }, + { + children: [], + label: '涞水县', + value: 130623, + }, + { + children: [], + label: '阜平县', + value: 130624, + }, + { + children: [], + label: '定兴县', + value: 130626, + }, + { + children: [], + label: '唐县', + value: 130627, + }, + { + children: [], + label: '高阳县', + value: 130628, + }, + { + children: [], + label: '容城县', + value: 130629, + }, + { + children: [], + label: '涞源县', + value: 130630, + }, + { + children: [], + label: '望都县', + value: 130631, + }, + { + children: [], + label: '安新县', + value: 130632, + }, + { + children: [], + label: '易县', + value: 130633, + }, + { + children: [], + label: '曲阳县', + value: 130634, + }, + { + children: [], + label: '蠡县', + value: 130635, + }, + { + children: [], + label: '顺平县', + value: 130636, + }, + { + children: [], + label: '博野县', + value: 130637, + }, + { + children: [], + label: '雄县', + value: 130638, + }, + { + children: [], + label: '涿州市', + value: 130681, + }, + { + children: [], + label: '定州市', + value: 130682, + }, + { + children: [], + label: '安国市', + value: 130683, + }, + { + children: [], + label: '高碑店市', + value: 130684, + }, + ], + label: '保定市', + value: 130600, + }, + { + children: [ + { + children: [], + label: '桥东区', + value: 130702, + }, + { + children: [], + label: '桥西区', + value: 130703, + }, + { + children: [], + label: '宣化区', + value: 130705, + }, + { + children: [], + label: '下花园区', + value: 130706, + }, + { + children: [], + label: '万全区', + value: 130708, + }, + { + children: [], + label: '崇礼区', + value: 130709, + }, + { + children: [], + label: '张北县', + value: 130722, + }, + { + children: [], + label: '康保县', + value: 130723, + }, + { + children: [], + label: '沽源县', + value: 130724, + }, + { + children: [], + label: '尚义县', + value: 130725, + }, + { + children: [], + label: '蔚县', + value: 130726, + }, + { + children: [], + label: '阳原县', + value: 130727, + }, + { + children: [], + label: '怀安县', + value: 130728, + }, + { + children: [], + label: '怀来县', + value: 130730, + }, + { + children: [], + label: '涿鹿县', + value: 130731, + }, + { + children: [], + label: '赤城县', + value: 130732, + }, + ], + label: '张家口市', + value: 130700, + }, + { + children: [ + { + children: [], + label: '双桥区', + value: 130802, + }, + { + children: [], + label: '双滦区', + value: 130803, + }, + { + children: [], + label: '鹰手营子矿区', + value: 130804, + }, + { + children: [], + label: '承德县', + value: 130821, + }, + { + children: [], + label: '兴隆县', + value: 130822, + }, + { + children: [], + label: '滦平县', + value: 130824, + }, + { + children: [], + label: '隆化县', + value: 130825, + }, + { + children: [], + label: '丰宁满族自治县', + value: 130826, + }, + { + children: [], + label: '宽城满族自治县', + value: 130827, + }, + { + children: [], + label: '围场满族蒙古族自治县', + value: 130828, + }, + { + children: [], + label: '平泉市', + value: 130881, + }, + ], + label: '承德市', + value: 130800, + }, + { + children: [ + { + children: [], + label: '新华区', + value: 130902, + }, + { + children: [], + label: '运河区', + value: 130903, + }, + { + children: [], + label: '沧县', + value: 130921, + }, + { + children: [], + label: '青县', + value: 130922, + }, + { + children: [], + label: '东光县', + value: 130923, + }, + { + children: [], + label: '海兴县', + value: 130924, + }, + { + children: [], + label: '盐山县', + value: 130925, + }, + { + children: [], + label: '肃宁县', + value: 130926, + }, + { + children: [], + label: '南皮县', + value: 130927, + }, + { + children: [], + label: '吴桥县', + value: 130928, + }, + { + children: [], + label: '献县', + value: 130929, + }, + { + children: [], + label: '孟村回族自治县', + value: 130930, + }, + { + children: [], + label: '泊头市', + value: 130981, + }, + { + children: [], + label: '任丘市', + value: 130982, + }, + { + children: [], + label: '黄骅市', + value: 130983, + }, + { + children: [], + label: '河间市', + value: 130984, + }, + ], + label: '沧州市', + value: 130900, + }, + { + children: [ + { + children: [], + label: '安次区', + value: 131002, + }, + { + children: [], + label: '广阳区', + value: 131003, + }, + { + children: [], + label: '固安县', + value: 131022, + }, + { + children: [], + label: '永清县', + value: 131023, + }, + { + children: [], + label: '香河县', + value: 131024, + }, + { + children: [], + label: '大城县', + value: 131025, + }, + { + children: [], + label: '文安县', + value: 131026, + }, + { + children: [], + label: '大厂回族自治县', + value: 131028, + }, + { + children: [], + label: '霸州市', + value: 131081, + }, + { + children: [], + label: '三河市', + value: 131082, + }, + ], + label: '廊坊市', + value: 131000, + }, + { + children: [ + { + children: [], + label: '桃城区', + value: 131102, + }, + { + children: [], + label: '冀州区', + value: 131103, + }, + { + children: [], + label: '枣强县', + value: 131121, + }, + { + children: [], + label: '武邑县', + value: 131122, + }, + { + children: [], + label: '武强县', + value: 131123, + }, + { + children: [], + label: '饶阳县', + value: 131124, + }, + { + children: [], + label: '安平县', + value: 131125, + }, + { + children: [], + label: '故城县', + value: 131126, + }, + { + children: [], + label: '景县', + value: 131127, + }, + { + children: [], + label: '阜城县', + value: 131128, + }, + { + children: [], + label: '深州市', + value: 131182, + }, + ], + label: '衡水市', + value: 131100, + }, + ], + label: '河北省', + value: 130000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '小店区', + value: 140105, + }, + { + children: [], + label: '迎泽区', + value: 140106, + }, + { + children: [], + label: '杏花岭区', + value: 140107, + }, + { + children: [], + label: '尖草坪区', + value: 140108, + }, + { + children: [], + label: '万柏林区', + value: 140109, + }, + { + children: [], + label: '晋源区', + value: 140110, + }, + { + children: [], + label: '清徐县', + value: 140121, + }, + { + children: [], + label: '阳曲县', + value: 140122, + }, + { + children: [], + label: '娄烦县', + value: 140123, + }, + { + children: [], + label: '古交市', + value: 140181, + }, + ], + label: '太原市', + value: 140100, + }, + { + children: [ + { + children: [], + label: '新荣区', + value: 140212, + }, + { + children: [], + label: '平城区', + value: 140213, + }, + { + children: [], + label: '云冈区', + value: 140214, + }, + { + children: [], + label: '云州区', + value: 140215, + }, + { + children: [], + label: '阳高县', + value: 140221, + }, + { + children: [], + label: '天镇县', + value: 140222, + }, + { + children: [], + label: '广灵县', + value: 140223, + }, + { + children: [], + label: '灵丘县', + value: 140224, + }, + { + children: [], + label: '浑源县', + value: 140225, + }, + { + children: [], + label: '左云县', + value: 140226, + }, + ], + label: '大同市', + value: 140200, + }, + { + children: [ + { + children: [], + label: '城区', + value: 140302, + }, + { + children: [], + label: '矿区', + value: 140303, + }, + { + children: [], + label: '郊区', + value: 140311, + }, + { + children: [], + label: '平定县', + value: 140321, + }, + { + children: [], + label: '盂县', + value: 140322, + }, + ], + label: '阳泉市', + value: 140300, + }, + { + children: [ + { + children: [], + label: '潞州区', + value: 140403, + }, + { + children: [], + label: '上党区', + value: 140404, + }, + { + children: [], + label: '屯留区', + value: 140405, + }, + { + children: [], + label: '潞城区', + value: 140406, + }, + { + children: [], + label: '襄垣县', + value: 140423, + }, + { + children: [], + label: '平顺县', + value: 140425, + }, + { + children: [], + label: '黎城县', + value: 140426, + }, + { + children: [], + label: '壶关县', + value: 140427, + }, + { + children: [], + label: '长子县', + value: 140428, + }, + { + children: [], + label: '武乡县', + value: 140429, + }, + { + children: [], + label: '沁县', + value: 140430, + }, + { + children: [], + label: '沁源县', + value: 140431, + }, + ], + label: '长治市', + value: 140400, + }, + { + children: [ + { + children: [], + label: '城区', + value: 140502, + }, + { + children: [], + label: '沁水县', + value: 140521, + }, + { + children: [], + label: '阳城县', + value: 140522, + }, + { + children: [], + label: '陵川县', + value: 140524, + }, + { + children: [], + label: '泽州县', + value: 140525, + }, + { + children: [], + label: '高平市', + value: 140581, + }, + ], + label: '晋城市', + value: 140500, + }, + { + children: [ + { + children: [], + label: '朔城区', + value: 140602, + }, + { + children: [], + label: '平鲁区', + value: 140603, + }, + { + children: [], + label: '山阴县', + value: 140621, + }, + { + children: [], + label: '应县', + value: 140622, + }, + { + children: [], + label: '右玉县', + value: 140623, + }, + { + children: [], + label: '怀仁市', + value: 140681, + }, + ], + label: '朔州市', + value: 140600, + }, + { + children: [ + { + children: [], + label: '榆次区', + value: 140702, + }, + { + children: [], + label: '榆社县', + value: 140721, + }, + { + children: [], + label: '左权县', + value: 140722, + }, + { + children: [], + label: '和顺县', + value: 140723, + }, + { + children: [], + label: '昔阳县', + value: 140724, + }, + { + children: [], + label: '寿阳县', + value: 140725, + }, + { + children: [], + label: '太谷县', + value: 140726, + }, + { + children: [], + label: '祁县', + value: 140727, + }, + { + children: [], + label: '平遥县', + value: 140728, + }, + { + children: [], + label: '灵石县', + value: 140729, + }, + { + children: [], + label: '介休市', + value: 140781, + }, + ], + label: '晋中市', + value: 140700, + }, + { + children: [ + { + children: [], + label: '盐湖区', + value: 140802, + }, + { + children: [], + label: '临猗县', + value: 140821, + }, + { + children: [], + label: '万荣县', + value: 140822, + }, + { + children: [], + label: '闻喜县', + value: 140823, + }, + { + children: [], + label: '稷山县', + value: 140824, + }, + { + children: [], + label: '新绛县', + value: 140825, + }, + { + children: [], + label: '绛县', + value: 140826, + }, + { + children: [], + label: '垣曲县', + value: 140827, + }, + { + children: [], + label: '夏县', + value: 140828, + }, + { + children: [], + label: '平陆县', + value: 140829, + }, + { + children: [], + label: '芮城县', + value: 140830, + }, + { + children: [], + label: '永济市', + value: 140881, + }, + { + children: [], + label: '河津市', + value: 140882, + }, + ], + label: '运城市', + value: 140800, + }, + { + children: [ + { + children: [], + label: '忻府区', + value: 140902, + }, + { + children: [], + label: '定襄县', + value: 140921, + }, + { + children: [], + label: '五台县', + value: 140922, + }, + { + children: [], + label: '代县', + value: 140923, + }, + { + children: [], + label: '繁峙县', + value: 140924, + }, + { + children: [], + label: '宁武县', + value: 140925, + }, + { + children: [], + label: '静乐县', + value: 140926, + }, + { + children: [], + label: '神池县', + value: 140927, + }, + { + children: [], + label: '五寨县', + value: 140928, + }, + { + children: [], + label: '岢岚县', + value: 140929, + }, + { + children: [], + label: '河曲县', + value: 140930, + }, + { + children: [], + label: '保德县', + value: 140931, + }, + { + children: [], + label: '偏关县', + value: 140932, + }, + { + children: [], + label: '原平市', + value: 140981, + }, + ], + label: '忻州市', + value: 140900, + }, + { + children: [ + { + children: [], + label: '尧都区', + value: 141002, + }, + { + children: [], + label: '曲沃县', + value: 141021, + }, + { + children: [], + label: '翼城县', + value: 141022, + }, + { + children: [], + label: '襄汾县', + value: 141023, + }, + { + children: [], + label: '洪洞县', + value: 141024, + }, + { + children: [], + label: '古县', + value: 141025, + }, + { + children: [], + label: '安泽县', + value: 141026, + }, + { + children: [], + label: '浮山县', + value: 141027, + }, + { + children: [], + label: '吉县', + value: 141028, + }, + { + children: [], + label: '乡宁县', + value: 141029, + }, + { + children: [], + label: '大宁县', + value: 141030, + }, + { + children: [], + label: '隰县', + value: 141031, + }, + { + children: [], + label: '永和县', + value: 141032, + }, + { + children: [], + label: '蒲县', + value: 141033, + }, + { + children: [], + label: '汾西县', + value: 141034, + }, + { + children: [], + label: '侯马市', + value: 141081, + }, + { + children: [], + label: '霍州市', + value: 141082, + }, + ], + label: '临汾市', + value: 141000, + }, + { + children: [ + { + children: [], + label: '离石区', + value: 141102, + }, + { + children: [], + label: '文水县', + value: 141121, + }, + { + children: [], + label: '交城县', + value: 141122, + }, + { + children: [], + label: '兴县', + value: 141123, + }, + { + children: [], + label: '临县', + value: 141124, + }, + { + children: [], + label: '柳林县', + value: 141125, + }, + { + children: [], + label: '石楼县', + value: 141126, + }, + { + children: [], + label: '岚县', + value: 141127, + }, + { + children: [], + label: '方山县', + value: 141128, + }, + { + children: [], + label: '中阳县', + value: 141129, + }, + { + children: [], + label: '交口县', + value: 141130, + }, + { + children: [], + label: '孝义市', + value: 141181, + }, + { + children: [], + label: '汾阳市', + value: 141182, + }, + ], + label: '吕梁市', + value: 141100, + }, + ], + label: '山西省', + value: 140000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '新城区', + value: 150102, + }, + { + children: [], + label: '回民区', + value: 150103, + }, + { + children: [], + label: '玉泉区', + value: 150104, + }, + { + children: [], + label: '赛罕区', + value: 150105, + }, + { + children: [], + label: '土默特左旗', + value: 150121, + }, + { + children: [], + label: '托克托县', + value: 150122, + }, + { + children: [], + label: '和林格尔县', + value: 150123, + }, + { + children: [], + label: '清水河县', + value: 150124, + }, + { + children: [], + label: '武川县', + value: 150125, + }, + ], + label: '呼和浩特市', + value: 150100, + }, + { + children: [ + { + children: [], + label: '东河区', + value: 150202, + }, + { + children: [], + label: '昆都仑区', + value: 150203, + }, + { + children: [], + label: '青山区', + value: 150204, + }, + { + children: [], + label: '石拐区', + value: 150205, + }, + { + children: [], + label: '白云鄂博矿区', + value: 150206, + }, + { + children: [], + label: '九原区', + value: 150207, + }, + { + children: [], + label: '土默特右旗', + value: 150221, + }, + { + children: [], + label: '固阳县', + value: 150222, + }, + { + children: [], + label: '达尔罕茂明安联合旗', + value: 150223, + }, + ], + label: '包头市', + value: 150200, + }, + { + children: [ + { + children: [], + label: '海勃湾区', + value: 150302, + }, + { + children: [], + label: '海南区', + value: 150303, + }, + { + children: [], + label: '乌达区', + value: 150304, + }, + ], + label: '乌海市', + value: 150300, + }, + { + children: [ + { + children: [], + label: '红山区', + value: 150402, + }, + { + children: [], + label: '元宝山区', + value: 150403, + }, + { + children: [], + label: '松山区', + value: 150404, + }, + { + children: [], + label: '阿鲁科尔沁旗', + value: 150421, + }, + { + children: [], + label: '巴林左旗', + value: 150422, + }, + { + children: [], + label: '巴林右旗', + value: 150423, + }, + { + children: [], + label: '林西县', + value: 150424, + }, + { + children: [], + label: '克什克腾旗', + value: 150425, + }, + { + children: [], + label: '翁牛特旗', + value: 150426, + }, + { + children: [], + label: '喀喇沁旗', + value: 150428, + }, + { + children: [], + label: '宁城县', + value: 150429, + }, + { + children: [], + label: '敖汉旗', + value: 150430, + }, + ], + label: '赤峰市', + value: 150400, + }, + { + children: [ + { + children: [], + label: '科尔沁区', + value: 150502, + }, + { + children: [], + label: '科尔沁左翼中旗', + value: 150521, + }, + { + children: [], + label: '科尔沁左翼后旗', + value: 150522, + }, + { + children: [], + label: '开鲁县', + value: 150523, + }, + { + children: [], + label: '库伦旗', + value: 150524, + }, + { + children: [], + label: '奈曼旗', + value: 150525, + }, + { + children: [], + label: '扎鲁特旗', + value: 150526, + }, + { + children: [], + label: '霍林郭勒市', + value: 150581, + }, + ], + label: '通辽市', + value: 150500, + }, + { + children: [ + { + children: [], + label: '东胜区', + value: 150602, + }, + { + children: [], + label: '康巴什区', + value: 150603, + }, + { + children: [], + label: '达拉特旗', + value: 150621, + }, + { + children: [], + label: '准格尔旗', + value: 150622, + }, + { + children: [], + label: '鄂托克前旗', + value: 150623, + }, + { + children: [], + label: '鄂托克旗', + value: 150624, + }, + { + children: [], + label: '杭锦旗', + value: 150625, + }, + { + children: [], + label: '乌审旗', + value: 150626, + }, + { + children: [], + label: '伊金霍洛旗', + value: 150627, + }, + ], + label: '鄂尔多斯市', + value: 150600, + }, + { + children: [ + { + children: [], + label: '海拉尔区', + value: 150702, + }, + { + children: [], + label: '扎赉诺尔区', + value: 150703, + }, + { + children: [], + label: '阿荣旗', + value: 150721, + }, + { + children: [], + label: '莫力达瓦达斡尔族自治旗', + value: 150722, + }, + { + children: [], + label: '鄂伦春自治旗', + value: 150723, + }, + { + children: [], + label: '鄂温克族自治旗', + value: 150724, + }, + { + children: [], + label: '陈巴尔虎旗', + value: 150725, + }, + { + children: [], + label: '新巴尔虎左旗', + value: 150726, + }, + { + children: [], + label: '新巴尔虎右旗', + value: 150727, + }, + { + children: [], + label: '满洲里市', + value: 150781, + }, + { + children: [], + label: '牙克石市', + value: 150782, + }, + { + children: [], + label: '扎兰屯市', + value: 150783, + }, + { + children: [], + label: '额尔古纳市', + value: 150784, + }, + { + children: [], + label: '根河市', + value: 150785, + }, + ], + label: '呼伦贝尔市', + value: 150700, + }, + { + children: [ + { + children: [], + label: '临河区', + value: 150802, + }, + { + children: [], + label: '五原县', + value: 150821, + }, + { + children: [], + label: '磴口县', + value: 150822, + }, + { + children: [], + label: '乌拉特前旗', + value: 150823, + }, + { + children: [], + label: '乌拉特中旗', + value: 150824, + }, + { + children: [], + label: '乌拉特后旗', + value: 150825, + }, + { + children: [], + label: '杭锦后旗', + value: 150826, + }, + ], + label: '巴彦淖尔市', + value: 150800, + }, + { + children: [ + { + children: [], + label: '集宁区', + value: 150902, + }, + { + children: [], + label: '卓资县', + value: 150921, + }, + { + children: [], + label: '化德县', + value: 150922, + }, + { + children: [], + label: '商都县', + value: 150923, + }, + { + children: [], + label: '兴和县', + value: 150924, + }, + { + children: [], + label: '凉城县', + value: 150925, + }, + { + children: [], + label: '察哈尔右翼前旗', + value: 150926, + }, + { + children: [], + label: '察哈尔右翼中旗', + value: 150927, + }, + { + children: [], + label: '察哈尔右翼后旗', + value: 150928, + }, + { + children: [], + label: '四子王旗', + value: 150929, + }, + { + children: [], + label: '丰镇市', + value: 150981, + }, + ], + label: '乌兰察布市', + value: 150900, + }, + { + children: [ + { + children: [], + label: '乌兰浩特市', + value: 152201, + }, + { + children: [], + label: '阿尔山市', + value: 152202, + }, + { + children: [], + label: '科尔沁右翼前旗', + value: 152221, + }, + { + children: [], + label: '科尔沁右翼中旗', + value: 152222, + }, + { + children: [], + label: '扎赉特旗', + value: 152223, + }, + { + children: [], + label: '突泉县', + value: 152224, + }, + ], + label: '兴安盟', + value: 152200, + }, + { + children: [ + { + children: [], + label: '二连浩特市', + value: 152501, + }, + { + children: [], + label: '锡林浩特市', + value: 152502, + }, + { + children: [], + label: '阿巴嘎旗', + value: 152522, + }, + { + children: [], + label: '苏尼特左旗', + value: 152523, + }, + { + children: [], + label: '苏尼特右旗', + value: 152524, + }, + { + children: [], + label: '东乌珠穆沁旗', + value: 152525, + }, + { + children: [], + label: '西乌珠穆沁旗', + value: 152526, + }, + { + children: [], + label: '太仆寺旗', + value: 152527, + }, + { + children: [], + label: '镶黄旗', + value: 152528, + }, + { + children: [], + label: '正镶白旗', + value: 152529, + }, + { + children: [], + label: '正蓝旗', + value: 152530, + }, + { + children: [], + label: '多伦县', + value: 152531, + }, + ], + label: '锡林郭勒盟', + value: 152500, + }, + { + children: [ + { + children: [], + label: '阿拉善左旗', + value: 152921, + }, + { + children: [], + label: '阿拉善右旗', + value: 152922, + }, + { + children: [], + label: '额济纳旗', + value: 152923, + }, + ], + label: '阿拉善盟', + value: 152900, + }, + ], + label: '内蒙古自治区', + value: 150000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '和平区', + value: 210102, + }, + { + children: [], + label: '沈河区', + value: 210103, + }, + { + children: [], + label: '大东区', + value: 210104, + }, + { + children: [], + label: '皇姑区', + value: 210105, + }, + { + children: [], + label: '铁西区', + value: 210106, + }, + { + children: [], + label: '苏家屯区', + value: 210111, + }, + { + children: [], + label: '浑南区', + value: 210112, + }, + { + children: [], + label: '沈北新区', + value: 210113, + }, + { + children: [], + label: '于洪区', + value: 210114, + }, + { + children: [], + label: '辽中区', + value: 210115, + }, + { + children: [], + label: '康平县', + value: 210123, + }, + { + children: [], + label: '法库县', + value: 210124, + }, + { + children: [], + label: '新民市', + value: 210181, + }, + ], + label: '沈阳市', + value: 210100, + }, + { + children: [ + { + children: [], + label: '中山区', + value: 210202, + }, + { + children: [], + label: '西岗区', + value: 210203, + }, + { + children: [], + label: '沙河口区', + value: 210204, + }, + { + children: [], + label: '甘井子区', + value: 210211, + }, + { + children: [], + label: '旅顺口区', + value: 210212, + }, + { + children: [], + label: '金州区', + value: 210213, + }, + { + children: [], + label: '普兰店区', + value: 210214, + }, + { + children: [], + label: '长海县', + value: 210224, + }, + { + children: [], + label: '瓦房店市', + value: 210281, + }, + { + children: [], + label: '庄河市', + value: 210283, + }, + ], + label: '大连市', + value: 210200, + }, + { + children: [ + { + children: [], + label: '铁东区', + value: 210302, + }, + { + children: [], + label: '铁西区', + value: 210303, + }, + { + children: [], + label: '立山区', + value: 210304, + }, + { + children: [], + label: '千山区', + value: 210311, + }, + { + children: [], + label: '台安县', + value: 210321, + }, + { + children: [], + label: '岫岩满族自治县', + value: 210323, + }, + { + children: [], + label: '海城市', + value: 210381, + }, + ], + label: '鞍山市', + value: 210300, + }, + { + children: [ + { + children: [], + label: '新抚区', + value: 210402, + }, + { + children: [], + label: '东洲区', + value: 210403, + }, + { + children: [], + label: '望花区', + value: 210404, + }, + { + children: [], + label: '顺城区', + value: 210411, + }, + { + children: [], + label: '抚顺县', + value: 210421, + }, + { + children: [], + label: '新宾满族自治县', + value: 210422, + }, + { + children: [], + label: '清原满族自治县', + value: 210423, + }, + ], + label: '抚顺市', + value: 210400, + }, + { + children: [ + { + children: [], + label: '平山区', + value: 210502, + }, + { + children: [], + label: '溪湖区', + value: 210503, + }, + { + children: [], + label: '明山区', + value: 210504, + }, + { + children: [], + label: '南芬区', + value: 210505, + }, + { + children: [], + label: '本溪满族自治县', + value: 210521, + }, + { + children: [], + label: '桓仁满族自治县', + value: 210522, + }, + ], + label: '本溪市', + value: 210500, + }, + { + children: [ + { + children: [], + label: '元宝区', + value: 210602, + }, + { + children: [], + label: '振兴区', + value: 210603, + }, + { + children: [], + label: '振安区', + value: 210604, + }, + { + children: [], + label: '宽甸满族自治县', + value: 210624, + }, + { + children: [], + label: '东港市', + value: 210681, + }, + { + children: [], + label: '凤城市', + value: 210682, + }, + ], + label: '丹东市', + value: 210600, + }, + { + children: [ + { + children: [], + label: '古塔区', + value: 210702, + }, + { + children: [], + label: '凌河区', + value: 210703, + }, + { + children: [], + label: '太和区', + value: 210711, + }, + { + children: [], + label: '黑山县', + value: 210726, + }, + { + children: [], + label: '义县', + value: 210727, + }, + { + children: [], + label: '凌海市', + value: 210781, + }, + { + children: [], + label: '北镇市', + value: 210782, + }, + ], + label: '锦州市', + value: 210700, + }, + { + children: [ + { + children: [], + label: '站前区', + value: 210802, + }, + { + children: [], + label: '西市区', + value: 210803, + }, + { + children: [], + label: '鲅鱼圈区', + value: 210804, + }, + { + children: [], + label: '老边区', + value: 210811, + }, + { + children: [], + label: '盖州市', + value: 210881, + }, + { + children: [], + label: '大石桥市', + value: 210882, + }, + ], + label: '营口市', + value: 210800, + }, + { + children: [ + { + children: [], + label: '海州区', + value: 210902, + }, + { + children: [], + label: '新邱区', + value: 210903, + }, + { + children: [], + label: '太平区', + value: 210904, + }, + { + children: [], + label: '清河门区', + value: 210905, + }, + { + children: [], + label: '细河区', + value: 210911, + }, + { + children: [], + label: '阜新蒙古族自治县', + value: 210921, + }, + { + children: [], + label: '彰武县', + value: 210922, + }, + ], + label: '阜新市', + value: 210900, + }, + { + children: [ + { + children: [], + label: '白塔区', + value: 211002, + }, + { + children: [], + label: '文圣区', + value: 211003, + }, + { + children: [], + label: '宏伟区', + value: 211004, + }, + { + children: [], + label: '弓长岭区', + value: 211005, + }, + { + children: [], + label: '太子河区', + value: 211011, + }, + { + children: [], + label: '辽阳县', + value: 211021, + }, + { + children: [], + label: '灯塔市', + value: 211081, + }, + ], + label: '辽阳市', + value: 211000, + }, + { + children: [ + { + children: [], + label: '双台子区', + value: 211102, + }, + { + children: [], + label: '兴隆台区', + value: 211103, + }, + { + children: [], + label: '大洼区', + value: 211104, + }, + { + children: [], + label: '盘山县', + value: 211122, + }, + ], + label: '盘锦市', + value: 211100, + }, + { + children: [ + { + children: [], + label: '银州区', + value: 211202, + }, + { + children: [], + label: '清河区', + value: 211204, + }, + { + children: [], + label: '铁岭县', + value: 211221, + }, + { + children: [], + label: '西丰县', + value: 211223, + }, + { + children: [], + label: '昌图县', + value: 211224, + }, + { + children: [], + label: '调兵山市', + value: 211281, + }, + { + children: [], + label: '开原市', + value: 211282, + }, + ], + label: '铁岭市', + value: 211200, + }, + { + children: [ + { + children: [], + label: '双塔区', + value: 211302, + }, + { + children: [], + label: '龙城区', + value: 211303, + }, + { + children: [], + label: '朝阳县', + value: 211321, + }, + { + children: [], + label: '建平县', + value: 211322, + }, + { + children: [], + label: '喀喇沁左翼蒙古族自治县', + value: 211324, + }, + { + children: [], + label: '北票市', + value: 211381, + }, + { + children: [], + label: '凌源市', + value: 211382, + }, + ], + label: '朝阳市', + value: 211300, + }, + { + children: [ + { + children: [], + label: '连山区', + value: 211402, + }, + { + children: [], + label: '龙港区', + value: 211403, + }, + { + children: [], + label: '南票区', + value: 211404, + }, + { + children: [], + label: '绥中县', + value: 211421, + }, + { + children: [], + label: '建昌县', + value: 211422, + }, + { + children: [], + label: '兴城市', + value: 211481, + }, + ], + label: '葫芦岛市', + value: 211400, + }, + ], + label: '辽宁省', + value: 210000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '南关区', + value: 220102, + }, + { + children: [], + label: '宽城区', + value: 220103, + }, + { + children: [], + label: '朝阳区', + value: 220104, + }, + { + children: [], + label: '二道区', + value: 220105, + }, + { + children: [], + label: '绿园区', + value: 220106, + }, + { + children: [], + label: '双阳区', + value: 220112, + }, + { + children: [], + label: '九台区', + value: 220113, + }, + { + children: [], + label: '农安县', + value: 220122, + }, + { + children: [], + label: '榆树市', + value: 220182, + }, + { + children: [], + label: '德惠市', + value: 220183, + }, + ], + label: '长春市', + value: 220100, + }, + { + children: [ + { + children: [], + label: '昌邑区', + value: 220202, + }, + { + children: [], + label: '龙潭区', + value: 220203, + }, + { + children: [], + label: '船营区', + value: 220204, + }, + { + children: [], + label: '丰满区', + value: 220211, + }, + { + children: [], + label: '永吉县', + value: 220221, + }, + { + children: [], + label: '蛟河市', + value: 220281, + }, + { + children: [], + label: '桦甸市', + value: 220282, + }, + { + children: [], + label: '舒兰市', + value: 220283, + }, + { + children: [], + label: '磐石市', + value: 220284, + }, + ], + label: '吉林市', + value: 220200, + }, + { + children: [ + { + children: [], + label: '铁西区', + value: 220302, + }, + { + children: [], + label: '铁东区', + value: 220303, + }, + { + children: [], + label: '梨树县', + value: 220322, + }, + { + children: [], + label: '伊通满族自治县', + value: 220323, + }, + { + children: [], + label: '公主岭市', + value: 220381, + }, + { + children: [], + label: '双辽市', + value: 220382, + }, + ], + label: '四平市', + value: 220300, + }, + { + children: [ + { + children: [], + label: '龙山区', + value: 220402, + }, + { + children: [], + label: '西安区', + value: 220403, + }, + { + children: [], + label: '东丰县', + value: 220421, + }, + { + children: [], + label: '东辽县', + value: 220422, + }, + ], + label: '辽源市', + value: 220400, + }, + { + children: [ + { + children: [], + label: '东昌区', + value: 220502, + }, + { + children: [], + label: '二道江区', + value: 220503, + }, + { + children: [], + label: '通化县', + value: 220521, + }, + { + children: [], + label: '辉南县', + value: 220523, + }, + { + children: [], + label: '柳河县', + value: 220524, + }, + { + children: [], + label: '梅河口市', + value: 220581, + }, + { + children: [], + label: '集安市', + value: 220582, + }, + ], + label: '通化市', + value: 220500, + }, + { + children: [ + { + children: [], + label: '浑江区', + value: 220602, + }, + { + children: [], + label: '江源区', + value: 220605, + }, + { + children: [], + label: '抚松县', + value: 220621, + }, + { + children: [], + label: '靖宇县', + value: 220622, + }, + { + children: [], + label: '长白朝鲜族自治县', + value: 220623, + }, + { + children: [], + label: '临江市', + value: 220681, + }, + ], + label: '白山市', + value: 220600, + }, + { + children: [ + { + children: [], + label: '宁江区', + value: 220702, + }, + { + children: [], + label: '前郭尔罗斯蒙古族自治县', + value: 220721, + }, + { + children: [], + label: '长岭县', + value: 220722, + }, + { + children: [], + label: '乾安县', + value: 220723, + }, + { + children: [], + label: '扶余市', + value: 220781, + }, + ], + label: '松原市', + value: 220700, + }, + { + children: [ + { + children: [], + label: '洮北区', + value: 220802, + }, + { + children: [], + label: '镇赉县', + value: 220821, + }, + { + children: [], + label: '通榆县', + value: 220822, + }, + { + children: [], + label: '洮南市', + value: 220881, + }, + { + children: [], + label: '大安市', + value: 220882, + }, + ], + label: '白城市', + value: 220800, + }, + { + children: [ + { + children: [], + label: '延吉市', + value: 222401, + }, + { + children: [], + label: '图们市', + value: 222402, + }, + { + children: [], + label: '敦化市', + value: 222403, + }, + { + children: [], + label: '珲春市', + value: 222404, + }, + { + children: [], + label: '龙井市', + value: 222405, + }, + { + children: [], + label: '和龙市', + value: 222406, + }, + { + children: [], + label: '汪清县', + value: 222424, + }, + { + children: [], + label: '安图县', + value: 222426, + }, + ], + label: '延边朝鲜族自治州', + value: 222400, + }, + ], + label: '吉林省', + value: 220000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '道里区', + value: 230102, + }, + { + children: [], + label: '南岗区', + value: 230103, + }, + { + children: [], + label: '道外区', + value: 230104, + }, + { + children: [], + label: '平房区', + value: 230108, + }, + { + children: [], + label: '松北区', + value: 230109, + }, + { + children: [], + label: '香坊区', + value: 230110, + }, + { + children: [], + label: '呼兰区', + value: 230111, + }, + { + children: [], + label: '阿城区', + value: 230112, + }, + { + children: [], + label: '双城区', + value: 230113, + }, + { + children: [], + label: '依兰县', + value: 230123, + }, + { + children: [], + label: '方正县', + value: 230124, + }, + { + children: [], + label: '宾县', + value: 230125, + }, + { + children: [], + label: '巴彦县', + value: 230126, + }, + { + children: [], + label: '木兰县', + value: 230127, + }, + { + children: [], + label: '通河县', + value: 230128, + }, + { + children: [], + label: '延寿县', + value: 230129, + }, + { + children: [], + label: '尚志市', + value: 230183, + }, + { + children: [], + label: '五常市', + value: 230184, + }, + ], + label: '哈尔滨市', + value: 230100, + }, + { + children: [ + { + children: [], + label: '龙沙区', + value: 230202, + }, + { + children: [], + label: '建华区', + value: 230203, + }, + { + children: [], + label: '铁锋区', + value: 230204, + }, + { + children: [], + label: '昂昂溪区', + value: 230205, + }, + { + children: [], + label: '富拉尔基区', + value: 230206, + }, + { + children: [], + label: '碾子山区', + value: 230207, + }, + { + children: [], + label: '梅里斯达斡尔族区', + value: 230208, + }, + { + children: [], + label: '龙江县', + value: 230221, + }, + { + children: [], + label: '依安县', + value: 230223, + }, + { + children: [], + label: '泰来县', + value: 230224, + }, + { + children: [], + label: '甘南县', + value: 230225, + }, + { + children: [], + label: '富裕县', + value: 230227, + }, + { + children: [], + label: '克山县', + value: 230229, + }, + { + children: [], + label: '克东县', + value: 230230, + }, + { + children: [], + label: '拜泉县', + value: 230231, + }, + { + children: [], + label: '讷河市', + value: 230281, + }, + ], + label: '齐齐哈尔市', + value: 230200, + }, + { + children: [ + { + children: [], + label: '鸡冠区', + value: 230302, + }, + { + children: [], + label: '恒山区', + value: 230303, + }, + { + children: [], + label: '滴道区', + value: 230304, + }, + { + children: [], + label: '梨树区', + value: 230305, + }, + { + children: [], + label: '城子河区', + value: 230306, + }, + { + children: [], + label: '麻山区', + value: 230307, + }, + { + children: [], + label: '鸡东县', + value: 230321, + }, + { + children: [], + label: '虎林市', + value: 230381, + }, + { + children: [], + label: '密山市', + value: 230382, + }, + ], + label: '鸡西市', + value: 230300, + }, + { + children: [ + { + children: [], + label: '向阳区', + value: 230402, + }, + { + children: [], + label: '工农区', + value: 230403, + }, + { + children: [], + label: '南山区', + value: 230404, + }, + { + children: [], + label: '兴安区', + value: 230405, + }, + { + children: [], + label: '东山区', + value: 230406, + }, + { + children: [], + label: '兴山区', + value: 230407, + }, + { + children: [], + label: '萝北县', + value: 230421, + }, + { + children: [], + label: '绥滨县', + value: 230422, + }, + ], + label: '鹤岗市', + value: 230400, + }, + { + children: [ + { + children: [], + label: '尖山区', + value: 230502, + }, + { + children: [], + label: '岭东区', + value: 230503, + }, + { + children: [], + label: '四方台区', + value: 230505, + }, + { + children: [], + label: '宝山区', + value: 230506, + }, + { + children: [], + label: '集贤县', + value: 230521, + }, + { + children: [], + label: '友谊县', + value: 230522, + }, + { + children: [], + label: '宝清县', + value: 230523, + }, + { + children: [], + label: '饶河县', + value: 230524, + }, + ], + label: '双鸭山市', + value: 230500, + }, + { + children: [ + { + children: [], + label: '萨尔图区', + value: 230602, + }, + { + children: [], + label: '龙凤区', + value: 230603, + }, + { + children: [], + label: '让胡路区', + value: 230604, + }, + { + children: [], + label: '红岗区', + value: 230605, + }, + { + children: [], + label: '大同区', + value: 230606, + }, + { + children: [], + label: '肇州县', + value: 230621, + }, + { + children: [], + label: '肇源县', + value: 230622, + }, + { + children: [], + label: '林甸县', + value: 230623, + }, + { + children: [], + label: '杜尔伯特蒙古族自治县', + value: 230624, + }, + ], + label: '大庆市', + value: 230600, + }, + { + children: [ + { + children: [], + label: '伊春区', + value: 230702, + }, + { + children: [], + label: '南岔区', + value: 230703, + }, + { + children: [], + label: '友好区', + value: 230704, + }, + { + children: [], + label: '西林区', + value: 230705, + }, + { + children: [], + label: '翠峦区', + value: 230706, + }, + { + children: [], + label: '新青区', + value: 230707, + }, + { + children: [], + label: '美溪区', + value: 230708, + }, + { + children: [], + label: '金山屯区', + value: 230709, + }, + { + children: [], + label: '五营区', + value: 230710, + }, + { + children: [], + label: '乌马河区', + value: 230711, + }, + { + children: [], + label: '汤旺河区', + value: 230712, + }, + { + children: [], + label: '带岭区', + value: 230713, + }, + { + children: [], + label: '乌伊岭区', + value: 230714, + }, + { + children: [], + label: '红星区', + value: 230715, + }, + { + children: [], + label: '上甘岭区', + value: 230716, + }, + { + children: [], + label: '嘉荫县', + value: 230722, + }, + { + children: [], + label: '铁力市', + value: 230781, + }, + ], + label: '伊春市', + value: 230700, + }, + { + children: [ + { + children: [], + label: '向阳区', + value: 230803, + }, + { + children: [], + label: '前进区', + value: 230804, + }, + { + children: [], + label: '东风区', + value: 230805, + }, + { + children: [], + label: '郊区', + value: 230811, + }, + { + children: [], + label: '桦南县', + value: 230822, + }, + { + children: [], + label: '桦川县', + value: 230826, + }, + { + children: [], + label: '汤原县', + value: 230828, + }, + { + children: [], + label: '同江市', + value: 230881, + }, + { + children: [], + label: '富锦市', + value: 230882, + }, + { + children: [], + label: '抚远市', + value: 230883, + }, + ], + label: '佳木斯市', + value: 230800, + }, + { + children: [ + { + children: [], + label: '新兴区', + value: 230902, + }, + { + children: [], + label: '桃山区', + value: 230903, + }, + { + children: [], + label: '茄子河区', + value: 230904, + }, + { + children: [], + label: '勃利县', + value: 230921, + }, + ], + label: '七台河市', + value: 230900, + }, + { + children: [ + { + children: [], + label: '东安区', + value: 231002, + }, + { + children: [], + label: '阳明区', + value: 231003, + }, + { + children: [], + label: '爱民区', + value: 231004, + }, + { + children: [], + label: '西安区', + value: 231005, + }, + { + children: [], + label: '林口县', + value: 231025, + }, + { + children: [], + label: '绥芬河市', + value: 231081, + }, + { + children: [], + label: '海林市', + value: 231083, + }, + { + children: [], + label: '宁安市', + value: 231084, + }, + { + children: [], + label: '穆棱市', + value: 231085, + }, + { + children: [], + label: '东宁市', + value: 231086, + }, + ], + label: '牡丹江市', + value: 231000, + }, + { + children: [ + { + children: [], + label: '爱辉区', + value: 231102, + }, + { + children: [], + label: '嫩江县', + value: 231121, + }, + { + children: [], + label: '逊克县', + value: 231123, + }, + { + children: [], + label: '孙吴县', + value: 231124, + }, + { + children: [], + label: '北安市', + value: 231181, + }, + { + children: [], + label: '五大连池市', + value: 231182, + }, + ], + label: '黑河市', + value: 231100, + }, + { + children: [ + { + children: [], + label: '北林区', + value: 231202, + }, + { + children: [], + label: '望奎县', + value: 231221, + }, + { + children: [], + label: '兰西县', + value: 231222, + }, + { + children: [], + label: '青冈县', + value: 231223, + }, + { + children: [], + label: '庆安县', + value: 231224, + }, + { + children: [], + label: '明水县', + value: 231225, + }, + { + children: [], + label: '绥棱县', + value: 231226, + }, + { + children: [], + label: '安达市', + value: 231281, + }, + { + children: [], + label: '肇东市', + value: 231282, + }, + { + children: [], + label: '海伦市', + value: 231283, + }, + ], + label: '绥化市', + value: 231200, + }, + { + children: [ + { + children: [], + label: '漠河市', + value: 232701, + }, + { + children: [], + label: '呼玛县', + value: 232721, + }, + { + children: [], + label: '塔河县', + value: 232722, + }, + { + children: [], + label: '大兴安岭地区直辖', + value: 232723, + }, + ], + label: '大兴安岭地区', + value: 232700, + }, + ], + label: '黑龙江省', + value: 230000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '黄浦区', + value: 310101, + }, + { + children: [], + label: '徐汇区', + value: 310104, + }, + { + children: [], + label: '长宁区', + value: 310105, + }, + { + children: [], + label: '静安区', + value: 310106, + }, + { + children: [], + label: '普陀区', + value: 310107, + }, + { + children: [], + label: '虹口区', + value: 310109, + }, + { + children: [], + label: '杨浦区', + value: 310110, + }, + { + children: [], + label: '闵行区', + value: 310112, + }, + { + children: [], + label: '宝山区', + value: 310113, + }, + { + children: [], + label: '嘉定区', + value: 310114, + }, + { + children: [], + label: '浦东新区', + value: 310115, + }, + { + children: [], + label: '金山区', + value: 310116, + }, + { + children: [], + label: '松江区', + value: 310117, + }, + { + children: [], + label: '青浦区', + value: 310118, + }, + { + children: [], + label: '奉贤区', + value: 310120, + }, + { + children: [], + label: '崇明区', + value: 310151, + }, + ], + label: '上海市', + value: 310100, + }, + ], + label: '上海市', + value: 310000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '玄武区', + value: 320102, + }, + { + children: [], + label: '秦淮区', + value: 320104, + }, + { + children: [], + label: '建邺区', + value: 320105, + }, + { + children: [], + label: '鼓楼区', + value: 320106, + }, + { + children: [], + label: '浦口区', + value: 320111, + }, + { + children: [], + label: '栖霞区', + value: 320113, + }, + { + children: [], + label: '雨花台区', + value: 320114, + }, + { + children: [], + label: '江宁区', + value: 320115, + }, + { + children: [], + label: '六合区', + value: 320116, + }, + { + children: [], + label: '溧水区', + value: 320117, + }, + { + children: [], + label: '高淳区', + value: 320118, + }, + ], + label: '南京市', + value: 320100, + }, + { + children: [ + { + children: [], + label: '锡山区', + value: 320205, + }, + { + children: [], + label: '惠山区', + value: 320206, + }, + { + children: [], + label: '滨湖区', + value: 320211, + }, + { + children: [], + label: '梁溪区', + value: 320213, + }, + { + children: [], + label: '新吴区', + value: 320214, + }, + { + children: [], + label: '江阴市', + value: 320281, + }, + { + children: [], + label: '宜兴市', + value: 320282, + }, + ], + label: '无锡市', + value: 320200, + }, + { + children: [ + { + children: [], + label: '鼓楼区', + value: 320302, + }, + { + children: [], + label: '云龙区', + value: 320303, + }, + { + children: [], + label: '贾汪区', + value: 320305, + }, + { + children: [], + label: '泉山区', + value: 320311, + }, + { + children: [], + label: '铜山区', + value: 320312, + }, + { + children: [], + label: '丰县', + value: 320321, + }, + { + children: [], + label: '沛县', + value: 320322, + }, + { + children: [], + label: '睢宁县', + value: 320324, + }, + { + children: [], + label: '新沂市', + value: 320381, + }, + { + children: [], + label: '邳州市', + value: 320382, + }, + ], + label: '徐州市', + value: 320300, + }, + { + children: [ + { + children: [], + label: '天宁区', + value: 320402, + }, + { + children: [], + label: '钟楼区', + value: 320404, + }, + { + children: [], + label: '新北区', + value: 320411, + }, + { + children: [], + label: '武进区', + value: 320412, + }, + { + children: [], + label: '金坛区', + value: 320413, + }, + { + children: [], + label: '溧阳市', + value: 320481, + }, + ], + label: '常州市', + value: 320400, + }, + { + children: [ + { + children: [], + label: '虎丘区', + value: 320505, + }, + { + children: [], + label: '吴中区', + value: 320506, + }, + { + children: [], + label: '相城区', + value: 320507, + }, + { + children: [], + label: '姑苏区', + value: 320508, + }, + { + children: [], + label: '吴江区', + value: 320509, + }, + { + children: [], + label: '苏州工业园区', + value: 320571, + }, + { + children: [], + label: '常熟市', + value: 320581, + }, + { + children: [], + label: '张家港市', + value: 320582, + }, + { + children: [], + label: '昆山市', + value: 320583, + }, + { + children: [], + label: '太仓市', + value: 320585, + }, + ], + label: '苏州市', + value: 320500, + }, + { + children: [ + { + children: [], + label: '崇川区', + value: 320602, + }, + { + children: [], + label: '港闸区', + value: 320611, + }, + { + children: [], + label: '通州区', + value: 320612, + }, + { + children: [], + label: '如东县', + value: 320623, + }, + { + children: [], + label: '启东市', + value: 320681, + }, + { + children: [], + label: '如皋市', + value: 320682, + }, + { + children: [], + label: '海门市', + value: 320684, + }, + { + children: [], + label: '海安市', + value: 320685, + }, + ], + label: '南通市', + value: 320600, + }, + { + children: [ + { + children: [], + label: '连云区', + value: 320703, + }, + { + children: [], + label: '海州区', + value: 320706, + }, + { + children: [], + label: '赣榆区', + value: 320707, + }, + { + children: [], + label: '东海县', + value: 320722, + }, + { + children: [], + label: '灌云县', + value: 320723, + }, + { + children: [], + label: '灌南县', + value: 320724, + }, + ], + label: '连云港市', + value: 320700, + }, + { + children: [ + { + children: [], + label: '淮安区', + value: 320803, + }, + { + children: [], + label: '淮阴区', + value: 320804, + }, + { + children: [], + label: '清江浦区', + value: 320812, + }, + { + children: [], + label: '洪泽区', + value: 320813, + }, + { + children: [], + label: '涟水县', + value: 320826, + }, + { + children: [], + label: '盱眙县', + value: 320830, + }, + { + children: [], + label: '金湖县', + value: 320831, + }, + ], + label: '淮安市', + value: 320800, + }, + { + children: [ + { + children: [], + label: '亭湖区', + value: 320902, + }, + { + children: [], + label: '盐都区', + value: 320903, + }, + { + children: [], + label: '大丰区', + value: 320904, + }, + { + children: [], + label: '响水县', + value: 320921, + }, + { + children: [], + label: '滨海县', + value: 320922, + }, + { + children: [], + label: '阜宁县', + value: 320923, + }, + { + children: [], + label: '射阳县', + value: 320924, + }, + { + children: [], + label: '建湖县', + value: 320925, + }, + { + children: [], + label: '东台市', + value: 320981, + }, + ], + label: '盐城市', + value: 320900, + }, + { + children: [ + { + children: [], + label: '广陵区', + value: 321002, + }, + { + children: [], + label: '邗江区', + value: 321003, + }, + { + children: [], + label: '江都区', + value: 321012, + }, + { + children: [], + label: '宝应县', + value: 321023, + }, + { + children: [], + label: '仪征市', + value: 321081, + }, + { + children: [], + label: '高邮市', + value: 321084, + }, + ], + label: '扬州市', + value: 321000, + }, + { + children: [ + { + children: [], + label: '京口区', + value: 321102, + }, + { + children: [], + label: '润州区', + value: 321111, + }, + { + children: [], + label: '丹徒区', + value: 321112, + }, + { + children: [], + label: '丹阳市', + value: 321181, + }, + { + children: [], + label: '扬中市', + value: 321182, + }, + { + children: [], + label: '句容市', + value: 321183, + }, + ], + label: '镇江市', + value: 321100, + }, + { + children: [ + { + children: [], + label: '海陵区', + value: 321202, + }, + { + children: [], + label: '高港区', + value: 321203, + }, + { + children: [], + label: '姜堰区', + value: 321204, + }, + { + children: [], + label: '兴化市', + value: 321281, + }, + { + children: [], + label: '靖江市', + value: 321282, + }, + { + children: [], + label: '泰兴市', + value: 321283, + }, + ], + label: '泰州市', + value: 321200, + }, + { + children: [ + { + children: [], + label: '宿城区', + value: 321302, + }, + { + children: [], + label: '宿豫区', + value: 321311, + }, + { + children: [], + label: '沭阳县', + value: 321322, + }, + { + children: [], + label: '泗阳县', + value: 321323, + }, + { + children: [], + label: '泗洪县', + value: 321324, + }, + ], + label: '宿迁市', + value: 321300, + }, + ], + label: '江苏省', + value: 320000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '上城区', + value: 330102, + }, + { + children: [], + label: '下城区', + value: 330103, + }, + { + children: [], + label: '江干区', + value: 330104, + }, + { + children: [], + label: '拱墅区', + value: 330105, + }, + { + children: [], + label: '西湖区', + value: 330106, + }, + { + children: [], + label: '滨江区', + value: 330108, + }, + { + children: [], + label: '萧山区', + value: 330109, + }, + { + children: [], + label: '余杭区', + value: 330110, + }, + { + children: [], + label: '富阳区', + value: 330111, + }, + { + children: [], + label: '临安区', + value: 330112, + }, + { + children: [], + label: '桐庐县', + value: 330122, + }, + { + children: [], + label: '淳安县', + value: 330127, + }, + { + children: [], + label: '建德市', + value: 330182, + }, + ], + label: '杭州市', + value: 330100, + }, + { + children: [ + { + children: [], + label: '海曙区', + value: 330203, + }, + { + children: [], + label: '江北区', + value: 330205, + }, + { + children: [], + label: '北仑区', + value: 330206, + }, + { + children: [], + label: '镇海区', + value: 330211, + }, + { + children: [], + label: '鄞州区', + value: 330212, + }, + { + children: [], + label: '奉化区', + value: 330213, + }, + { + children: [], + label: '象山县', + value: 330225, + }, + { + children: [], + label: '宁海县', + value: 330226, + }, + { + children: [], + label: '余姚市', + value: 330281, + }, + { + children: [], + label: '慈溪市', + value: 330282, + }, + ], + label: '宁波市', + value: 330200, + }, + { + children: [ + { + children: [], + label: '鹿城区', + value: 330302, + }, + { + children: [], + label: '龙湾区', + value: 330303, + }, + { + children: [], + label: '瓯海区', + value: 330304, + }, + { + children: [], + label: '洞头区', + value: 330305, + }, + { + children: [], + label: '永嘉县', + value: 330324, + }, + { + children: [], + label: '平阳县', + value: 330326, + }, + { + children: [], + label: '苍南县', + value: 330327, + }, + { + children: [], + label: '文成县', + value: 330328, + }, + { + children: [], + label: '泰顺县', + value: 330329, + }, + { + children: [], + label: '瑞安市', + value: 330381, + }, + { + children: [], + label: '乐清市', + value: 330382, + }, + ], + label: '温州市', + value: 330300, + }, + { + children: [ + { + children: [], + label: '南湖区', + value: 330402, + }, + { + children: [], + label: '秀洲区', + value: 330411, + }, + { + children: [], + label: '嘉善县', + value: 330421, + }, + { + children: [], + label: '海盐县', + value: 330424, + }, + { + children: [], + label: '海宁市', + value: 330481, + }, + { + children: [], + label: '平湖市', + value: 330482, + }, + { + children: [], + label: '桐乡市', + value: 330483, + }, + ], + label: '嘉兴市', + value: 330400, + }, + { + children: [ + { + children: [], + label: '吴兴区', + value: 330502, + }, + { + children: [], + label: '南浔区', + value: 330503, + }, + { + children: [], + label: '德清县', + value: 330521, + }, + { + children: [], + label: '长兴县', + value: 330522, + }, + { + children: [], + label: '安吉县', + value: 330523, + }, + ], + label: '湖州市', + value: 330500, + }, + { + children: [ + { + children: [], + label: '越城区', + value: 330602, + }, + { + children: [], + label: '柯桥区', + value: 330603, + }, + { + children: [], + label: '上虞区', + value: 330604, + }, + { + children: [], + label: '新昌县', + value: 330624, + }, + { + children: [], + label: '诸暨市', + value: 330681, + }, + { + children: [], + label: '嵊州市', + value: 330683, + }, + ], + label: '绍兴市', + value: 330600, + }, + { + children: [ + { + children: [], + label: '婺城区', + value: 330702, + }, + { + children: [], + label: '金东区', + value: 330703, + }, + { + children: [], + label: '武义县', + value: 330723, + }, + { + children: [], + label: '浦江县', + value: 330726, + }, + { + children: [], + label: '磐安县', + value: 330727, + }, + { + children: [], + label: '兰溪市', + value: 330781, + }, + { + children: [], + label: '义乌市', + value: 330782, + }, + { + children: [], + label: '东阳市', + value: 330783, + }, + { + children: [], + label: '永康市', + value: 330784, + }, + ], + label: '金华市', + value: 330700, + }, + { + children: [ + { + children: [], + label: '柯城区', + value: 330802, + }, + { + children: [], + label: '衢江区', + value: 330803, + }, + { + children: [], + label: '常山县', + value: 330822, + }, + { + children: [], + label: '开化县', + value: 330824, + }, + { + children: [], + label: '龙游县', + value: 330825, + }, + { + children: [], + label: '江山市', + value: 330881, + }, + ], + label: '衢州市', + value: 330800, + }, + { + children: [ + { + children: [], + label: '定海区', + value: 330902, + }, + { + children: [], + label: '普陀区', + value: 330903, + }, + { + children: [], + label: '岱山县', + value: 330921, + }, + { + children: [], + label: '嵊泗县', + value: 330922, + }, + ], + label: '舟山市', + value: 330900, + }, + { + children: [ + { + children: [], + label: '椒江区', + value: 331002, + }, + { + children: [], + label: '黄岩区', + value: 331003, + }, + { + children: [], + label: '路桥区', + value: 331004, + }, + { + children: [], + label: '三门县', + value: 331022, + }, + { + children: [], + label: '天台县', + value: 331023, + }, + { + children: [], + label: '仙居县', + value: 331024, + }, + { + children: [], + label: '温岭市', + value: 331081, + }, + { + children: [], + label: '临海市', + value: 331082, + }, + { + children: [], + label: '玉环市', + value: 331083, + }, + ], + label: '台州市', + value: 331000, + }, + { + children: [ + { + children: [], + label: '莲都区', + value: 331102, + }, + { + children: [], + label: '青田县', + value: 331121, + }, + { + children: [], + label: '缙云县', + value: 331122, + }, + { + children: [], + label: '遂昌县', + value: 331123, + }, + { + children: [], + label: '松阳县', + value: 331124, + }, + { + children: [], + label: '云和县', + value: 331125, + }, + { + children: [], + label: '庆元县', + value: 331126, + }, + { + children: [], + label: '景宁畲族自治县', + value: 331127, + }, + { + children: [], + label: '龙泉市', + value: 331181, + }, + ], + label: '丽水市', + value: 331100, + }, + ], + label: '浙江省', + value: 330000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '瑶海区', + value: 340102, + }, + { + children: [], + label: '庐阳区', + value: 340103, + }, + { + children: [], + label: '蜀山区', + value: 340104, + }, + { + children: [], + label: '包河区', + value: 340111, + }, + { + children: [], + label: '长丰县', + value: 340121, + }, + { + children: [], + label: '肥东县', + value: 340122, + }, + { + children: [], + label: '肥西县', + value: 340123, + }, + { + children: [], + label: '庐江县', + value: 340124, + }, + { + children: [], + label: '巢湖市', + value: 340181, + }, + ], + label: '合肥市', + value: 340100, + }, + { + children: [ + { + children: [], + label: '镜湖区', + value: 340202, + }, + { + children: [], + label: '弋江区', + value: 340203, + }, + { + children: [], + label: '鸠江区', + value: 340207, + }, + { + children: [], + label: '三山区', + value: 340208, + }, + { + children: [], + label: '芜湖县', + value: 340221, + }, + { + children: [], + label: '繁昌县', + value: 340222, + }, + { + children: [], + label: '南陵县', + value: 340223, + }, + { + children: [], + label: '无为县', + value: 340225, + }, + ], + label: '芜湖市', + value: 340200, + }, + { + children: [ + { + children: [], + label: '龙子湖区', + value: 340302, + }, + { + children: [], + label: '蚌山区', + value: 340303, + }, + { + children: [], + label: '禹会区', + value: 340304, + }, + { + children: [], + label: '淮上区', + value: 340311, + }, + { + children: [], + label: '怀远县', + value: 340321, + }, + { + children: [], + label: '五河县', + value: 340322, + }, + { + children: [], + label: '固镇县', + value: 340323, + }, + ], + label: '蚌埠市', + value: 340300, + }, + { + children: [ + { + children: [], + label: '大通区', + value: 340402, + }, + { + children: [], + label: '田家庵区', + value: 340403, + }, + { + children: [], + label: '谢家集区', + value: 340404, + }, + { + children: [], + label: '八公山区', + value: 340405, + }, + { + children: [], + label: '潘集区', + value: 340406, + }, + { + children: [], + label: '凤台县', + value: 340421, + }, + { + children: [], + label: '寿县', + value: 340422, + }, + ], + label: '淮南市', + value: 340400, + }, + { + children: [ + { + children: [], + label: '花山区', + value: 340503, + }, + { + children: [], + label: '雨山区', + value: 340504, + }, + { + children: [], + label: '博望区', + value: 340506, + }, + { + children: [], + label: '当涂县', + value: 340521, + }, + { + children: [], + label: '含山县', + value: 340522, + }, + { + children: [], + label: '和县', + value: 340523, + }, + ], + label: '马鞍山市', + value: 340500, + }, + { + children: [ + { + children: [], + label: '杜集区', + value: 340602, + }, + { + children: [], + label: '相山区', + value: 340603, + }, + { + children: [], + label: '烈山区', + value: 340604, + }, + { + children: [], + label: '濉溪县', + value: 340621, + }, + ], + label: '淮北市', + value: 340600, + }, + { + children: [ + { + children: [], + label: '铜官区', + value: 340705, + }, + { + children: [], + label: '义安区', + value: 340706, + }, + { + children: [], + label: '郊区', + value: 340711, + }, + { + children: [], + label: '枞阳县', + value: 340722, + }, + ], + label: '铜陵市', + value: 340700, + }, + { + children: [ + { + children: [], + label: '迎江区', + value: 340802, + }, + { + children: [], + label: '大观区', + value: 340803, + }, + { + children: [], + label: '宜秀区', + value: 340811, + }, + { + children: [], + label: '怀宁县', + value: 340822, + }, + { + children: [], + label: '太湖县', + value: 340825, + }, + { + children: [], + label: '宿松县', + value: 340826, + }, + { + children: [], + label: '望江县', + value: 340827, + }, + { + children: [], + label: '岳西县', + value: 340828, + }, + { + children: [], + label: '桐城市', + value: 340881, + }, + { + children: [], + label: '潜山市', + value: 340882, + }, + ], + label: '安庆市', + value: 340800, + }, + { + children: [ + { + children: [], + label: '屯溪区', + value: 341002, + }, + { + children: [], + label: '黄山区', + value: 341003, + }, + { + children: [], + label: '徽州区', + value: 341004, + }, + { + children: [], + label: '歙县', + value: 341021, + }, + { + children: [], + label: '休宁县', + value: 341022, + }, + { + children: [], + label: '黟县', + value: 341023, + }, + { + children: [], + label: '祁门县', + value: 341024, + }, + ], + label: '黄山市', + value: 341000, + }, + { + children: [ + { + children: [], + label: '琅琊区', + value: 341102, + }, + { + children: [], + label: '南谯区', + value: 341103, + }, + { + children: [], + label: '来安县', + value: 341122, + }, + { + children: [], + label: '全椒县', + value: 341124, + }, + { + children: [], + label: '定远县', + value: 341125, + }, + { + children: [], + label: '凤阳县', + value: 341126, + }, + { + children: [], + label: '天长市', + value: 341181, + }, + { + children: [], + label: '明光市', + value: 341182, + }, + ], + label: '滁州市', + value: 341100, + }, + { + children: [ + { + children: [], + label: '颍州区', + value: 341202, + }, + { + children: [], + label: '颍东区', + value: 341203, + }, + { + children: [], + label: '颍泉区', + value: 341204, + }, + { + children: [], + label: '临泉县', + value: 341221, + }, + { + children: [], + label: '太和县', + value: 341222, + }, + { + children: [], + label: '阜南县', + value: 341225, + }, + { + children: [], + label: '颍上县', + value: 341226, + }, + { + children: [], + label: '界首市', + value: 341282, + }, + ], + label: '阜阳市', + value: 341200, + }, + { + children: [ + { + children: [], + label: '埇桥区', + value: 341302, + }, + { + children: [], + label: '砀山县', + value: 341321, + }, + { + children: [], + label: '萧县', + value: 341322, + }, + { + children: [], + label: '灵璧县', + value: 341323, + }, + { + children: [], + label: '泗县', + value: 341324, + }, + ], + label: '宿州市', + value: 341300, + }, + { + children: [ + { + children: [], + label: '金安区', + value: 341502, + }, + { + children: [], + label: '裕安区', + value: 341503, + }, + { + children: [], + label: '叶集区', + value: 341504, + }, + { + children: [], + label: '霍邱县', + value: 341522, + }, + { + children: [], + label: '舒城县', + value: 341523, + }, + { + children: [], + label: '金寨县', + value: 341524, + }, + { + children: [], + label: '霍山县', + value: 341525, + }, + ], + label: '六安市', + value: 341500, + }, + { + children: [ + { + children: [], + label: '谯城区', + value: 341602, + }, + { + children: [], + label: '涡阳县', + value: 341621, + }, + { + children: [], + label: '蒙城县', + value: 341622, + }, + { + children: [], + label: '利辛县', + value: 341623, + }, + ], + label: '亳州市', + value: 341600, + }, + { + children: [ + { + children: [], + label: '贵池区', + value: 341702, + }, + { + children: [], + label: '东至县', + value: 341721, + }, + { + children: [], + label: '石台县', + value: 341722, + }, + { + children: [], + label: '青阳县', + value: 341723, + }, + ], + label: '池州市', + value: 341700, + }, + { + children: [ + { + children: [], + label: '宣州区', + value: 341802, + }, + { + children: [], + label: '郎溪县', + value: 341821, + }, + { + children: [], + label: '广德县', + value: 341822, + }, + { + children: [], + label: '泾县', + value: 341823, + }, + { + children: [], + label: '绩溪县', + value: 341824, + }, + { + children: [], + label: '旌德县', + value: 341825, + }, + { + children: [], + label: '宁国市', + value: 341881, + }, + ], + label: '宣城市', + value: 341800, + }, + ], + label: '安徽省', + value: 340000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '鼓楼区', + value: 350102, + }, + { + children: [], + label: '台江区', + value: 350103, + }, + { + children: [], + label: '仓山区', + value: 350104, + }, + { + children: [], + label: '马尾区', + value: 350105, + }, + { + children: [], + label: '晋安区', + value: 350111, + }, + { + children: [], + label: '长乐区', + value: 350112, + }, + { + children: [], + label: '闽侯县', + value: 350121, + }, + { + children: [], + label: '连江县', + value: 350122, + }, + { + children: [], + label: '罗源县', + value: 350123, + }, + { + children: [], + label: '闽清县', + value: 350124, + }, + { + children: [], + label: '永泰县', + value: 350125, + }, + { + children: [], + label: '平潭县', + value: 350128, + }, + { + children: [], + label: '福清市', + value: 350181, + }, + ], + label: '福州市', + value: 350100, + }, + { + children: [ + { + children: [], + label: '思明区', + value: 350203, + }, + { + children: [], + label: '海沧区', + value: 350205, + }, + { + children: [], + label: '湖里区', + value: 350206, + }, + { + children: [], + label: '集美区', + value: 350211, + }, + { + children: [], + label: '同安区', + value: 350212, + }, + { + children: [], + label: '翔安区', + value: 350213, + }, + ], + label: '厦门市', + value: 350200, + }, + { + children: [ + { + children: [], + label: '城厢区', + value: 350302, + }, + { + children: [], + label: '涵江区', + value: 350303, + }, + { + children: [], + label: '荔城区', + value: 350304, + }, + { + children: [], + label: '秀屿区', + value: 350305, + }, + { + children: [], + label: '仙游县', + value: 350322, + }, + ], + label: '莆田市', + value: 350300, + }, + { + children: [ + { + children: [], + label: '梅列区', + value: 350402, + }, + { + children: [], + label: '三元区', + value: 350403, + }, + { + children: [], + label: '明溪县', + value: 350421, + }, + { + children: [], + label: '清流县', + value: 350423, + }, + { + children: [], + label: '宁化县', + value: 350424, + }, + { + children: [], + label: '大田县', + value: 350425, + }, + { + children: [], + label: '尤溪县', + value: 350426, + }, + { + children: [], + label: '沙县', + value: 350427, + }, + { + children: [], + label: '将乐县', + value: 350428, + }, + { + children: [], + label: '泰宁县', + value: 350429, + }, + { + children: [], + label: '建宁县', + value: 350430, + }, + { + children: [], + label: '永安市', + value: 350481, + }, + ], + label: '三明市', + value: 350400, + }, + { + children: [ + { + children: [], + label: '鲤城区', + value: 350502, + }, + { + children: [], + label: '丰泽区', + value: 350503, + }, + { + children: [], + label: '洛江区', + value: 350504, + }, + { + children: [], + label: '泉港区', + value: 350505, + }, + { + children: [], + label: '惠安县', + value: 350521, + }, + { + children: [], + label: '安溪县', + value: 350524, + }, + { + children: [], + label: '永春县', + value: 350525, + }, + { + children: [], + label: '德化县', + value: 350526, + }, + { + children: [], + label: '金门县', + value: 350527, + }, + { + children: [], + label: '石狮市', + value: 350581, + }, + { + children: [], + label: '晋江市', + value: 350582, + }, + { + children: [], + label: '南安市', + value: 350583, + }, + ], + label: '泉州市', + value: 350500, + }, + { + children: [ + { + children: [], + label: '芗城区', + value: 350602, + }, + { + children: [], + label: '龙文区', + value: 350603, + }, + { + children: [], + label: '云霄县', + value: 350622, + }, + { + children: [], + label: '漳浦县', + value: 350623, + }, + { + children: [], + label: '诏安县', + value: 350624, + }, + { + children: [], + label: '长泰县', + value: 350625, + }, + { + children: [], + label: '东山县', + value: 350626, + }, + { + children: [], + label: '南靖县', + value: 350627, + }, + { + children: [], + label: '平和县', + value: 350628, + }, + { + children: [], + label: '华安县', + value: 350629, + }, + { + children: [], + label: '龙海市', + value: 350681, + }, + ], + label: '漳州市', + value: 350600, + }, + { + children: [ + { + children: [], + label: '延平区', + value: 350702, + }, + { + children: [], + label: '建阳区', + value: 350703, + }, + { + children: [], + label: '顺昌县', + value: 350721, + }, + { + children: [], + label: '浦城县', + value: 350722, + }, + { + children: [], + label: '光泽县', + value: 350723, + }, + { + children: [], + label: '松溪县', + value: 350724, + }, + { + children: [], + label: '政和县', + value: 350725, + }, + { + children: [], + label: '邵武市', + value: 350781, + }, + { + children: [], + label: '武夷山市', + value: 350782, + }, + { + children: [], + label: '建瓯市', + value: 350783, + }, + ], + label: '南平市', + value: 350700, + }, + { + children: [ + { + children: [], + label: '新罗区', + value: 350802, + }, + { + children: [], + label: '永定区', + value: 350803, + }, + { + children: [], + label: '长汀县', + value: 350821, + }, + { + children: [], + label: '上杭县', + value: 350823, + }, + { + children: [], + label: '武平县', + value: 350824, + }, + { + children: [], + label: '连城县', + value: 350825, + }, + { + children: [], + label: '漳平市', + value: 350881, + }, + ], + label: '龙岩市', + value: 350800, + }, + { + children: [ + { + children: [], + label: '蕉城区', + value: 350902, + }, + { + children: [], + label: '霞浦县', + value: 350921, + }, + { + children: [], + label: '古田县', + value: 350922, + }, + { + children: [], + label: '屏南县', + value: 350923, + }, + { + children: [], + label: '寿宁县', + value: 350924, + }, + { + children: [], + label: '周宁县', + value: 350925, + }, + { + children: [], + label: '柘荣县', + value: 350926, + }, + { + children: [], + label: '福安市', + value: 350981, + }, + { + children: [], + label: '福鼎市', + value: 350982, + }, + ], + label: '宁德市', + value: 350900, + }, + ], + label: '福建省', + value: 350000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '东湖区', + value: 360102, + }, + { + children: [], + label: '西湖区', + value: 360103, + }, + { + children: [], + label: '青云谱区', + value: 360104, + }, + { + children: [], + label: '湾里区', + value: 360105, + }, + { + children: [], + label: '青山湖区', + value: 360111, + }, + { + children: [], + label: '新建区', + value: 360112, + }, + { + children: [], + label: '南昌县', + value: 360121, + }, + { + children: [], + label: '安义县', + value: 360123, + }, + { + children: [], + label: '进贤县', + value: 360124, + }, + ], + label: '南昌市', + value: 360100, + }, + { + children: [ + { + children: [], + label: '昌江区', + value: 360202, + }, + { + children: [], + label: '珠山区', + value: 360203, + }, + { + children: [], + label: '浮梁县', + value: 360222, + }, + { + children: [], + label: '乐平市', + value: 360281, + }, + ], + label: '景德镇市', + value: 360200, + }, + { + children: [ + { + children: [], + label: '安源区', + value: 360302, + }, + { + children: [], + label: '湘东区', + value: 360313, + }, + { + children: [], + label: '莲花县', + value: 360321, + }, + { + children: [], + label: '上栗县', + value: 360322, + }, + { + children: [], + label: '芦溪县', + value: 360323, + }, + ], + label: '萍乡市', + value: 360300, + }, + { + children: [ + { + children: [], + label: '濂溪区', + value: 360402, + }, + { + children: [], + label: '浔阳区', + value: 360403, + }, + { + children: [], + label: '柴桑区', + value: 360404, + }, + { + children: [], + label: '武宁县', + value: 360423, + }, + { + children: [], + label: '修水县', + value: 360424, + }, + { + children: [], + label: '永修县', + value: 360425, + }, + { + children: [], + label: '德安县', + value: 360426, + }, + { + children: [], + label: '都昌县', + value: 360428, + }, + { + children: [], + label: '湖口县', + value: 360429, + }, + { + children: [], + label: '彭泽县', + value: 360430, + }, + { + children: [], + label: '瑞昌市', + value: 360481, + }, + { + children: [], + label: '共青城市', + value: 360482, + }, + { + children: [], + label: '庐山市', + value: 360483, + }, + ], + label: '九江市', + value: 360400, + }, + { + children: [ + { + children: [], + label: '渝水区', + value: 360502, + }, + { + children: [], + label: '分宜县', + value: 360521, + }, + ], + label: '新余市', + value: 360500, + }, + { + children: [ + { + children: [], + label: '月湖区', + value: 360602, + }, + { + children: [], + label: '余江区', + value: 360603, + }, + { + children: [], + label: '贵溪市', + value: 360681, + }, + ], + label: '鹰潭市', + value: 360600, + }, + { + children: [ + { + children: [], + label: '章贡区', + value: 360702, + }, + { + children: [], + label: '南康区', + value: 360703, + }, + { + children: [], + label: '赣县区', + value: 360704, + }, + { + children: [], + label: '信丰县', + value: 360722, + }, + { + children: [], + label: '大余县', + value: 360723, + }, + { + children: [], + label: '上犹县', + value: 360724, + }, + { + children: [], + label: '崇义县', + value: 360725, + }, + { + children: [], + label: '安远县', + value: 360726, + }, + { + children: [], + label: '龙南县', + value: 360727, + }, + { + children: [], + label: '定南县', + value: 360728, + }, + { + children: [], + label: '全南县', + value: 360729, + }, + { + children: [], + label: '宁都县', + value: 360730, + }, + { + children: [], + label: '于都县', + value: 360731, + }, + { + children: [], + label: '兴国县', + value: 360732, + }, + { + children: [], + label: '会昌县', + value: 360733, + }, + { + children: [], + label: '寻乌县', + value: 360734, + }, + { + children: [], + label: '石城县', + value: 360735, + }, + { + children: [], + label: '瑞金市', + value: 360781, + }, + ], + label: '赣州市', + value: 360700, + }, + { + children: [ + { + children: [], + label: '吉州区', + value: 360802, + }, + { + children: [], + label: '青原区', + value: 360803, + }, + { + children: [], + label: '吉安县', + value: 360821, + }, + { + children: [], + label: '吉水县', + value: 360822, + }, + { + children: [], + label: '峡江县', + value: 360823, + }, + { + children: [], + label: '新干县', + value: 360824, + }, + { + children: [], + label: '永丰县', + value: 360825, + }, + { + children: [], + label: '泰和县', + value: 360826, + }, + { + children: [], + label: '遂川县', + value: 360827, + }, + { + children: [], + label: '万安县', + value: 360828, + }, + { + children: [], + label: '安福县', + value: 360829, + }, + { + children: [], + label: '永新县', + value: 360830, + }, + { + children: [], + label: '井冈山市', + value: 360881, + }, + ], + label: '吉安市', + value: 360800, + }, + { + children: [ + { + children: [], + label: '袁州区', + value: 360902, + }, + { + children: [], + label: '奉新县', + value: 360921, + }, + { + children: [], + label: '万载县', + value: 360922, + }, + { + children: [], + label: '上高县', + value: 360923, + }, + { + children: [], + label: '宜丰县', + value: 360924, + }, + { + children: [], + label: '靖安县', + value: 360925, + }, + { + children: [], + label: '铜鼓县', + value: 360926, + }, + { + children: [], + label: '丰城市', + value: 360981, + }, + { + children: [], + label: '樟树市', + value: 360982, + }, + { + children: [], + label: '高安市', + value: 360983, + }, + ], + label: '宜春市', + value: 360900, + }, + { + children: [ + { + children: [], + label: '临川区', + value: 361002, + }, + { + children: [], + label: '东乡区', + value: 361003, + }, + { + children: [], + label: '南城县', + value: 361021, + }, + { + children: [], + label: '黎川县', + value: 361022, + }, + { + children: [], + label: '南丰县', + value: 361023, + }, + { + children: [], + label: '崇仁县', + value: 361024, + }, + { + children: [], + label: '乐安县', + value: 361025, + }, + { + children: [], + label: '宜黄县', + value: 361026, + }, + { + children: [], + label: '金溪县', + value: 361027, + }, + { + children: [], + label: '资溪县', + value: 361028, + }, + { + children: [], + label: '广昌县', + value: 361030, + }, + ], + label: '抚州市', + value: 361000, + }, + { + children: [ + { + children: [], + label: '信州区', + value: 361102, + }, + { + children: [], + label: '广丰区', + value: 361103, + }, + { + children: [], + label: '上饶县', + value: 361121, + }, + { + children: [], + label: '玉山县', + value: 361123, + }, + { + children: [], + label: '铅山县', + value: 361124, + }, + { + children: [], + label: '横峰县', + value: 361125, + }, + { + children: [], + label: '弋阳县', + value: 361126, + }, + { + children: [], + label: '余干县', + value: 361127, + }, + { + children: [], + label: '鄱阳县', + value: 361128, + }, + { + children: [], + label: '万年县', + value: 361129, + }, + { + children: [], + label: '婺源县', + value: 361130, + }, + { + children: [], + label: '德兴市', + value: 361181, + }, + ], + label: '上饶市', + value: 361100, + }, + ], + label: '江西省', + value: 360000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '历下区', + value: 370102, + }, + { + children: [], + label: '市中区', + value: 370103, + }, + { + children: [], + label: '槐荫区', + value: 370104, + }, + { + children: [], + label: '天桥区', + value: 370105, + }, + { + children: [], + label: '历城区', + value: 370112, + }, + { + children: [], + label: '长清区', + value: 370113, + }, + { + children: [], + label: '章丘区', + value: 370114, + }, + { + children: [], + label: '济阳区', + value: 370115, + }, + { + children: [], + label: '莱芜区', + value: 370116, + }, + { + children: [], + label: '钢城区', + value: 370117, + }, + { + children: [], + label: '平阴县', + value: 370124, + }, + { + children: [], + label: '商河县', + value: 370126, + }, + ], + label: '济南市', + value: 370100, + }, + { + children: [ + { + children: [], + label: '市南区', + value: 370202, + }, + { + children: [], + label: '市北区', + value: 370203, + }, + { + children: [], + label: '黄岛区', + value: 370211, + }, + { + children: [], + label: '崂山区', + value: 370212, + }, + { + children: [], + label: '李沧区', + value: 370213, + }, + { + children: [], + label: '城阳区', + value: 370214, + }, + { + children: [], + label: '即墨区', + value: 370215, + }, + { + children: [], + label: '胶州市', + value: 370281, + }, + { + children: [], + label: '平度市', + value: 370283, + }, + { + children: [], + label: '莱西市', + value: 370285, + }, + ], + label: '青岛市', + value: 370200, + }, + { + children: [ + { + children: [], + label: '淄川区', + value: 370302, + }, + { + children: [], + label: '张店区', + value: 370303, + }, + { + children: [], + label: '博山区', + value: 370304, + }, + { + children: [], + label: '临淄区', + value: 370305, + }, + { + children: [], + label: '周村区', + value: 370306, + }, + { + children: [], + label: '桓台县', + value: 370321, + }, + { + children: [], + label: '高青县', + value: 370322, + }, + { + children: [], + label: '沂源县', + value: 370323, + }, + ], + label: '淄博市', + value: 370300, + }, + { + children: [ + { + children: [], + label: '市中区', + value: 370402, + }, + { + children: [], + label: '薛城区', + value: 370403, + }, + { + children: [], + label: '峄城区', + value: 370404, + }, + { + children: [], + label: '台儿庄区', + value: 370405, + }, + { + children: [], + label: '山亭区', + value: 370406, + }, + { + children: [], + label: '滕州市', + value: 370481, + }, + ], + label: '枣庄市', + value: 370400, + }, + { + children: [ + { + children: [], + label: '东营区', + value: 370502, + }, + { + children: [], + label: '河口区', + value: 370503, + }, + { + children: [], + label: '垦利区', + value: 370505, + }, + { + children: [], + label: '利津县', + value: 370522, + }, + { + children: [], + label: '广饶县', + value: 370523, + }, + ], + label: '东营市', + value: 370500, + }, + { + children: [ + { + children: [], + label: '芝罘区', + value: 370602, + }, + { + children: [], + label: '福山区', + value: 370611, + }, + { + children: [], + label: '牟平区', + value: 370612, + }, + { + children: [], + label: '莱山区', + value: 370613, + }, + { + children: [], + label: '长岛县', + value: 370634, + }, + { + children: [], + label: '龙口市', + value: 370681, + }, + { + children: [], + label: '莱阳市', + value: 370682, + }, + { + children: [], + label: '莱州市', + value: 370683, + }, + { + children: [], + label: '蓬莱市', + value: 370684, + }, + { + children: [], + label: '招远市', + value: 370685, + }, + { + children: [], + label: '栖霞市', + value: 370686, + }, + { + children: [], + label: '海阳市', + value: 370687, + }, + ], + label: '烟台市', + value: 370600, + }, + { + children: [ + { + children: [], + label: '潍城区', + value: 370702, + }, + { + children: [], + label: '寒亭区', + value: 370703, + }, + { + children: [], + label: '坊子区', + value: 370704, + }, + { + children: [], + label: '奎文区', + value: 370705, + }, + { + children: [], + label: '临朐县', + value: 370724, + }, + { + children: [], + label: '昌乐县', + value: 370725, + }, + { + children: [], + label: '青州市', + value: 370781, + }, + { + children: [], + label: '诸城市', + value: 370782, + }, + { + children: [], + label: '寿光市', + value: 370783, + }, + { + children: [], + label: '安丘市', + value: 370784, + }, + { + children: [], + label: '高密市', + value: 370785, + }, + { + children: [], + label: '昌邑市', + value: 370786, + }, + ], + label: '潍坊市', + value: 370700, + }, + { + children: [ + { + children: [], + label: '任城区', + value: 370811, + }, + { + children: [], + label: '兖州区', + value: 370812, + }, + { + children: [], + label: '微山县', + value: 370826, + }, + { + children: [], + label: '鱼台县', + value: 370827, + }, + { + children: [], + label: '金乡县', + value: 370828, + }, + { + children: [], + label: '嘉祥县', + value: 370829, + }, + { + children: [], + label: '汶上县', + value: 370830, + }, + { + children: [], + label: '泗水县', + value: 370831, + }, + { + children: [], + label: '梁山县', + value: 370832, + }, + { + children: [], + label: '曲阜市', + value: 370881, + }, + { + children: [], + label: '邹城市', + value: 370883, + }, + ], + label: '济宁市', + value: 370800, + }, + { + children: [ + { + children: [], + label: '泰山区', + value: 370902, + }, + { + children: [], + label: '岱岳区', + value: 370911, + }, + { + children: [], + label: '宁阳县', + value: 370921, + }, + { + children: [], + label: '东平县', + value: 370923, + }, + { + children: [], + label: '新泰市', + value: 370982, + }, + { + children: [], + label: '肥城市', + value: 370983, + }, + ], + label: '泰安市', + value: 370900, + }, + { + children: [ + { + children: [], + label: '环翠区', + value: 371002, + }, + { + children: [], + label: '文登区', + value: 371003, + }, + { + children: [], + label: '荣成市', + value: 371082, + }, + { + children: [], + label: '乳山市', + value: 371083, + }, + ], + label: '威海市', + value: 371000, + }, + { + children: [ + { + children: [], + label: '东港区', + value: 371102, + }, + { + children: [], + label: '岚山区', + value: 371103, + }, + { + children: [], + label: '五莲县', + value: 371121, + }, + { + children: [], + label: '莒县', + value: 371122, + }, + ], + label: '日照市', + value: 371100, + }, + { + children: [ + { + children: [], + label: '兰山区', + value: 371302, + }, + { + children: [], + label: '罗庄区', + value: 371311, + }, + { + children: [], + label: '河东区', + value: 371312, + }, + { + children: [], + label: '沂南县', + value: 371321, + }, + { + children: [], + label: '郯城县', + value: 371322, + }, + { + children: [], + label: '沂水县', + value: 371323, + }, + { + children: [], + label: '兰陵县', + value: 371324, + }, + { + children: [], + label: '费县', + value: 371325, + }, + { + children: [], + label: '平邑县', + value: 371326, + }, + { + children: [], + label: '莒南县', + value: 371327, + }, + { + children: [], + label: '蒙阴县', + value: 371328, + }, + { + children: [], + label: '临沭县', + value: 371329, + }, + ], + label: '临沂市', + value: 371300, + }, + { + children: [ + { + children: [], + label: '德城区', + value: 371402, + }, + { + children: [], + label: '陵城区', + value: 371403, + }, + { + children: [], + label: '宁津县', + value: 371422, + }, + { + children: [], + label: '庆云县', + value: 371423, + }, + { + children: [], + label: '临邑县', + value: 371424, + }, + { + children: [], + label: '齐河县', + value: 371425, + }, + { + children: [], + label: '平原县', + value: 371426, + }, + { + children: [], + label: '夏津县', + value: 371427, + }, + { + children: [], + label: '武城县', + value: 371428, + }, + { + children: [], + label: '乐陵市', + value: 371481, + }, + { + children: [], + label: '禹城市', + value: 371482, + }, + ], + label: '德州市', + value: 371400, + }, + { + children: [ + { + children: [], + label: '东昌府区', + value: 371502, + }, + { + children: [], + label: '阳谷县', + value: 371521, + }, + { + children: [], + label: '莘县', + value: 371522, + }, + { + children: [], + label: '茌平县', + value: 371523, + }, + { + children: [], + label: '东阿县', + value: 371524, + }, + { + children: [], + label: '冠县', + value: 371525, + }, + { + children: [], + label: '高唐县', + value: 371526, + }, + { + children: [], + label: '临清市', + value: 371581, + }, + ], + label: '聊城市', + value: 371500, + }, + { + children: [ + { + children: [], + label: '滨城区', + value: 371602, + }, + { + children: [], + label: '沾化区', + value: 371603, + }, + { + children: [], + label: '惠民县', + value: 371621, + }, + { + children: [], + label: '阳信县', + value: 371622, + }, + { + children: [], + label: '无棣县', + value: 371623, + }, + { + children: [], + label: '博兴县', + value: 371625, + }, + { + children: [], + label: '邹平市', + value: 371681, + }, + ], + label: '滨州市', + value: 371600, + }, + { + children: [ + { + children: [], + label: '牡丹区', + value: 371702, + }, + { + children: [], + label: '定陶区', + value: 371703, + }, + { + children: [], + label: '曹县', + value: 371721, + }, + { + children: [], + label: '单县', + value: 371722, + }, + { + children: [], + label: '成武县', + value: 371723, + }, + { + children: [], + label: '巨野县', + value: 371724, + }, + { + children: [], + label: '郓城县', + value: 371725, + }, + { + children: [], + label: '鄄城县', + value: 371726, + }, + { + children: [], + label: '东明县', + value: 371728, + }, + ], + label: '菏泽市', + value: 371700, + }, + ], + label: '山东省', + value: 370000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '中原区', + value: 410102, + }, + { + children: [], + label: '二七区', + value: 410103, + }, + { + children: [], + label: '管城回族区', + value: 410104, + }, + { + children: [], + label: '金水区', + value: 410105, + }, + { + children: [], + label: '上街区', + value: 410106, + }, + { + children: [], + label: '惠济区', + value: 410108, + }, + { + children: [], + label: '中牟县', + value: 410122, + }, + { + children: [], + label: '巩义市', + value: 410181, + }, + { + children: [], + label: '荥阳市', + value: 410182, + }, + { + children: [], + label: '新密市', + value: 410183, + }, + { + children: [], + label: '新郑市', + value: 410184, + }, + { + children: [], + label: '登封市', + value: 410185, + }, + ], + label: '郑州市', + value: 410100, + }, + { + children: [ + { + children: [], + label: '龙亭区', + value: 410202, + }, + { + children: [], + label: '顺河回族区', + value: 410203, + }, + { + children: [], + label: '鼓楼区', + value: 410204, + }, + { + children: [], + label: '禹王台区', + value: 410205, + }, + { + children: [], + label: '祥符区', + value: 410212, + }, + { + children: [], + label: '杞县', + value: 410221, + }, + { + children: [], + label: '通许县', + value: 410222, + }, + { + children: [], + label: '尉氏县', + value: 410223, + }, + { + children: [], + label: '兰考县', + value: 410225, + }, + ], + label: '开封市', + value: 410200, + }, + { + children: [ + { + children: [], + label: '老城区', + value: 410302, + }, + { + children: [], + label: '西工区', + value: 410303, + }, + { + children: [], + label: '瀍河回族区', + value: 410304, + }, + { + children: [], + label: '涧西区', + value: 410305, + }, + { + children: [], + label: '吉利区', + value: 410306, + }, + { + children: [], + label: '洛龙区', + value: 410311, + }, + { + children: [], + label: '孟津县', + value: 410322, + }, + { + children: [], + label: '新安县', + value: 410323, + }, + { + children: [], + label: '栾川县', + value: 410324, + }, + { + children: [], + label: '嵩县', + value: 410325, + }, + { + children: [], + label: '汝阳县', + value: 410326, + }, + { + children: [], + label: '宜阳县', + value: 410327, + }, + { + children: [], + label: '洛宁县', + value: 410328, + }, + { + children: [], + label: '伊川县', + value: 410329, + }, + { + children: [], + label: '偃师市', + value: 410381, + }, + ], + label: '洛阳市', + value: 410300, + }, + { + children: [ + { + children: [], + label: '新华区', + value: 410402, + }, + { + children: [], + label: '卫东区', + value: 410403, + }, + { + children: [], + label: '石龙区', + value: 410404, + }, + { + children: [], + label: '湛河区', + value: 410411, + }, + { + children: [], + label: '宝丰县', + value: 410421, + }, + { + children: [], + label: '叶县', + value: 410422, + }, + { + children: [], + label: '鲁山县', + value: 410423, + }, + { + children: [], + label: '郏县', + value: 410425, + }, + { + children: [], + label: '舞钢市', + value: 410481, + }, + { + children: [], + label: '汝州市', + value: 410482, + }, + ], + label: '平顶山市', + value: 410400, + }, + { + children: [ + { + children: [], + label: '文峰区', + value: 410502, + }, + { + children: [], + label: '北关区', + value: 410503, + }, + { + children: [], + label: '殷都区', + value: 410505, + }, + { + children: [], + label: '龙安区', + value: 410506, + }, + { + children: [], + label: '安阳县', + value: 410522, + }, + { + children: [], + label: '汤阴县', + value: 410523, + }, + { + children: [], + label: '滑县', + value: 410526, + }, + { + children: [], + label: '内黄县', + value: 410527, + }, + { + children: [], + label: '林州市', + value: 410581, + }, + ], + label: '安阳市', + value: 410500, + }, + { + children: [ + { + children: [], + label: '鹤山区', + value: 410602, + }, + { + children: [], + label: '山城区', + value: 410603, + }, + { + children: [], + label: '淇滨区', + value: 410611, + }, + { + children: [], + label: '浚县', + value: 410621, + }, + { + children: [], + label: '淇县', + value: 410622, + }, + ], + label: '鹤壁市', + value: 410600, + }, + { + children: [ + { + children: [], + label: '红旗区', + value: 410702, + }, + { + children: [], + label: '卫滨区', + value: 410703, + }, + { + children: [], + label: '凤泉区', + value: 410704, + }, + { + children: [], + label: '牧野区', + value: 410711, + }, + { + children: [], + label: '新乡县', + value: 410721, + }, + { + children: [], + label: '获嘉县', + value: 410724, + }, + { + children: [], + label: '原阳县', + value: 410725, + }, + { + children: [], + label: '延津县', + value: 410726, + }, + { + children: [], + label: '封丘县', + value: 410727, + }, + { + children: [], + label: '长垣县', + value: 410728, + }, + { + children: [], + label: '卫辉市', + value: 410781, + }, + { + children: [], + label: '辉县市', + value: 410782, + }, + ], + label: '新乡市', + value: 410700, + }, + { + children: [ + { + children: [], + label: '解放区', + value: 410802, + }, + { + children: [], + label: '中站区', + value: 410803, + }, + { + children: [], + label: '马村区', + value: 410804, + }, + { + children: [], + label: '山阳区', + value: 410811, + }, + { + children: [], + label: '修武县', + value: 410821, + }, + { + children: [], + label: '博爱县', + value: 410822, + }, + { + children: [], + label: '武陟县', + value: 410823, + }, + { + children: [], + label: '温县', + value: 410825, + }, + { + children: [], + label: '沁阳市', + value: 410882, + }, + { + children: [], + label: '孟州市', + value: 410883, + }, + ], + label: '焦作市', + value: 410800, + }, + { + children: [ + { + children: [], + label: '华龙区', + value: 410902, + }, + { + children: [], + label: '清丰县', + value: 410922, + }, + { + children: [], + label: '南乐县', + value: 410923, + }, + { + children: [], + label: '范县', + value: 410926, + }, + { + children: [], + label: '台前县', + value: 410927, + }, + { + children: [], + label: '濮阳县', + value: 410928, + }, + ], + label: '濮阳市', + value: 410900, + }, + { + children: [ + { + children: [], + label: '魏都区', + value: 411002, + }, + { + children: [], + label: '建安区', + value: 411003, + }, + { + children: [], + label: '鄢陵县', + value: 411024, + }, + { + children: [], + label: '襄城县', + value: 411025, + }, + { + children: [], + label: '禹州市', + value: 411081, + }, + { + children: [], + label: '长葛市', + value: 411082, + }, + ], + label: '许昌市', + value: 411000, + }, + { + children: [ + { + children: [], + label: '源汇区', + value: 411102, + }, + { + children: [], + label: '郾城区', + value: 411103, + }, + { + children: [], + label: '召陵区', + value: 411104, + }, + { + children: [], + label: '舞阳县', + value: 411121, + }, + { + children: [], + label: '临颍县', + value: 411122, + }, + ], + label: '漯河市', + value: 411100, + }, + { + children: [ + { + children: [], + label: '湖滨区', + value: 411202, + }, + { + children: [], + label: '陕州区', + value: 411203, + }, + { + children: [], + label: '渑池县', + value: 411221, + }, + { + children: [], + label: '卢氏县', + value: 411224, + }, + { + children: [], + label: '义马市', + value: 411281, + }, + { + children: [], + label: '灵宝市', + value: 411282, + }, + ], + label: '三门峡市', + value: 411200, + }, + { + children: [ + { + children: [], + label: '宛城区', + value: 411302, + }, + { + children: [], + label: '卧龙区', + value: 411303, + }, + { + children: [], + label: '南召县', + value: 411321, + }, + { + children: [], + label: '方城县', + value: 411322, + }, + { + children: [], + label: '西峡县', + value: 411323, + }, + { + children: [], + label: '镇平县', + value: 411324, + }, + { + children: [], + label: '内乡县', + value: 411325, + }, + { + children: [], + label: '淅川县', + value: 411326, + }, + { + children: [], + label: '社旗县', + value: 411327, + }, + { + children: [], + label: '唐河县', + value: 411328, + }, + { + children: [], + label: '新野县', + value: 411329, + }, + { + children: [], + label: '桐柏县', + value: 411330, + }, + { + children: [], + label: '邓州市', + value: 411381, + }, + ], + label: '南阳市', + value: 411300, + }, + { + children: [ + { + children: [], + label: '梁园区', + value: 411402, + }, + { + children: [], + label: '睢阳区', + value: 411403, + }, + { + children: [], + label: '民权县', + value: 411421, + }, + { + children: [], + label: '睢县', + value: 411422, + }, + { + children: [], + label: '宁陵县', + value: 411423, + }, + { + children: [], + label: '柘城县', + value: 411424, + }, + { + children: [], + label: '虞城县', + value: 411425, + }, + { + children: [], + label: '夏邑县', + value: 411426, + }, + { + children: [], + label: '永城市', + value: 411481, + }, + ], + label: '商丘市', + value: 411400, + }, + { + children: [ + { + children: [], + label: '浉河区', + value: 411502, + }, + { + children: [], + label: '平桥区', + value: 411503, + }, + { + children: [], + label: '罗山县', + value: 411521, + }, + { + children: [], + label: '光山县', + value: 411522, + }, + { + children: [], + label: '新县', + value: 411523, + }, + { + children: [], + label: '商城县', + value: 411524, + }, + { + children: [], + label: '固始县', + value: 411525, + }, + { + children: [], + label: '潢川县', + value: 411526, + }, + { + children: [], + label: '淮滨县', + value: 411527, + }, + { + children: [], + label: '息县', + value: 411528, + }, + ], + label: '信阳市', + value: 411500, + }, + { + children: [ + { + children: [], + label: '川汇区', + value: 411602, + }, + { + children: [], + label: '扶沟县', + value: 411621, + }, + { + children: [], + label: '西华县', + value: 411622, + }, + { + children: [], + label: '商水县', + value: 411623, + }, + { + children: [], + label: '沈丘县', + value: 411624, + }, + { + children: [], + label: '郸城县', + value: 411625, + }, + { + children: [], + label: '淮阳县', + value: 411626, + }, + { + children: [], + label: '太康县', + value: 411627, + }, + { + children: [], + label: '鹿邑县', + value: 411628, + }, + { + children: [], + label: '项城市', + value: 411681, + }, + ], + label: '周口市', + value: 411600, + }, + { + children: [ + { + children: [], + label: '驿城区', + value: 411702, + }, + { + children: [], + label: '西平县', + value: 411721, + }, + { + children: [], + label: '上蔡县', + value: 411722, + }, + { + children: [], + label: '平舆县', + value: 411723, + }, + { + children: [], + label: '正阳县', + value: 411724, + }, + { + children: [], + label: '确山县', + value: 411725, + }, + { + children: [], + label: '泌阳县', + value: 411726, + }, + { + children: [], + label: '汝南县', + value: 411727, + }, + { + children: [], + label: '遂平县', + value: 411728, + }, + { + children: [], + label: '新蔡县', + value: 411729, + }, + ], + label: '驻马店市', + value: 411700, + }, + { + children: [], + label: '济源市', + value: 419001, + }, + ], + label: '河南省', + value: 410000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '江岸区', + value: 420102, + }, + { + children: [], + label: '江汉区', + value: 420103, + }, + { + children: [], + label: '硚口区', + value: 420104, + }, + { + children: [], + label: '汉阳区', + value: 420105, + }, + { + children: [], + label: '武昌区', + value: 420106, + }, + { + children: [], + label: '青山区', + value: 420107, + }, + { + children: [], + label: '洪山区', + value: 420111, + }, + { + children: [], + label: '东西湖区', + value: 420112, + }, + { + children: [], + label: '汉南区', + value: 420113, + }, + { + children: [], + label: '蔡甸区', + value: 420114, + }, + { + children: [], + label: '江夏区', + value: 420115, + }, + { + children: [], + label: '黄陂区', + value: 420116, + }, + { + children: [], + label: '新洲区', + value: 420117, + }, + ], + label: '武汉市', + value: 420100, + }, + { + children: [ + { + children: [], + label: '黄石港区', + value: 420202, + }, + { + children: [], + label: '西塞山区', + value: 420203, + }, + { + children: [], + label: '下陆区', + value: 420204, + }, + { + children: [], + label: '铁山区', + value: 420205, + }, + { + children: [], + label: '阳新县', + value: 420222, + }, + { + children: [], + label: '大冶市', + value: 420281, + }, + ], + label: '黄石市', + value: 420200, + }, + { + children: [ + { + children: [], + label: '茅箭区', + value: 420302, + }, + { + children: [], + label: '张湾区', + value: 420303, + }, + { + children: [], + label: '郧阳区', + value: 420304, + }, + { + children: [], + label: '郧西县', + value: 420322, + }, + { + children: [], + label: '竹山县', + value: 420323, + }, + { + children: [], + label: '竹溪县', + value: 420324, + }, + { + children: [], + label: '房县', + value: 420325, + }, + { + children: [], + label: '丹江口市', + value: 420381, + }, + ], + label: '十堰市', + value: 420300, + }, + { + children: [ + { + children: [], + label: '西陵区', + value: 420502, + }, + { + children: [], + label: '伍家岗区', + value: 420503, + }, + { + children: [], + label: '点军区', + value: 420504, + }, + { + children: [], + label: '猇亭区', + value: 420505, + }, + { + children: [], + label: '夷陵区', + value: 420506, + }, + { + children: [], + label: '远安县', + value: 420525, + }, + { + children: [], + label: '兴山县', + value: 420526, + }, + { + children: [], + label: '秭归县', + value: 420527, + }, + { + children: [], + label: '长阳土家族自治县', + value: 420528, + }, + { + children: [], + label: '五峰土家族自治县', + value: 420529, + }, + { + children: [], + label: '宜都市', + value: 420581, + }, + { + children: [], + label: '当阳市', + value: 420582, + }, + { + children: [], + label: '枝江市', + value: 420583, + }, + ], + label: '宜昌市', + value: 420500, + }, + { + children: [ + { + children: [], + label: '襄城区', + value: 420602, + }, + { + children: [], + label: '樊城区', + value: 420606, + }, + { + children: [], + label: '襄州区', + value: 420607, + }, + { + children: [], + label: '南漳县', + value: 420624, + }, + { + children: [], + label: '谷城县', + value: 420625, + }, + { + children: [], + label: '保康县', + value: 420626, + }, + { + children: [], + label: '老河口市', + value: 420682, + }, + { + children: [], + label: '枣阳市', + value: 420683, + }, + { + children: [], + label: '宜城市', + value: 420684, + }, + ], + label: '襄阳市', + value: 420600, + }, + { + children: [ + { + children: [], + label: '梁子湖区', + value: 420702, + }, + { + children: [], + label: '华容区', + value: 420703, + }, + { + children: [], + label: '鄂城区', + value: 420704, + }, + ], + label: '鄂州市', + value: 420700, + }, + { + children: [ + { + children: [], + label: '东宝区', + value: 420802, + }, + { + children: [], + label: '掇刀区', + value: 420804, + }, + { + children: [], + label: '沙洋县', + value: 420822, + }, + { + children: [], + label: '钟祥市', + value: 420881, + }, + { + children: [], + label: '京山市', + value: 420882, + }, + ], + label: '荆门市', + value: 420800, + }, + { + children: [ + { + children: [], + label: '孝南区', + value: 420902, + }, + { + children: [], + label: '孝昌县', + value: 420921, + }, + { + children: [], + label: '大悟县', + value: 420922, + }, + { + children: [], + label: '云梦县', + value: 420923, + }, + { + children: [], + label: '应城市', + value: 420981, + }, + { + children: [], + label: '安陆市', + value: 420982, + }, + { + children: [], + label: '汉川市', + value: 420984, + }, + ], + label: '孝感市', + value: 420900, + }, + { + children: [ + { + children: [], + label: '沙市区', + value: 421002, + }, + { + children: [], + label: '荆州区', + value: 421003, + }, + { + children: [], + label: '公安县', + value: 421022, + }, + { + children: [], + label: '监利县', + value: 421023, + }, + { + children: [], + label: '江陵县', + value: 421024, + }, + { + children: [], + label: '石首市', + value: 421081, + }, + { + children: [], + label: '洪湖市', + value: 421083, + }, + { + children: [], + label: '松滋市', + value: 421087, + }, + ], + label: '荆州市', + value: 421000, + }, + { + children: [ + { + children: [], + label: '黄州区', + value: 421102, + }, + { + children: [], + label: '团风县', + value: 421121, + }, + { + children: [], + label: '红安县', + value: 421122, + }, + { + children: [], + label: '罗田县', + value: 421123, + }, + { + children: [], + label: '英山县', + value: 421124, + }, + { + children: [], + label: '浠水县', + value: 421125, + }, + { + children: [], + label: '蕲春县', + value: 421126, + }, + { + children: [], + label: '黄梅县', + value: 421127, + }, + { + children: [], + label: '麻城市', + value: 421181, + }, + { + children: [], + label: '武穴市', + value: 421182, + }, + ], + label: '黄冈市', + value: 421100, + }, + { + children: [ + { + children: [], + label: '咸安区', + value: 421202, + }, + { + children: [], + label: '嘉鱼县', + value: 421221, + }, + { + children: [], + label: '通城县', + value: 421222, + }, + { + children: [], + label: '崇阳县', + value: 421223, + }, + { + children: [], + label: '通山县', + value: 421224, + }, + { + children: [], + label: '赤壁市', + value: 421281, + }, + ], + label: '咸宁市', + value: 421200, + }, + { + children: [ + { + children: [], + label: '曾都区', + value: 421303, + }, + { + children: [], + label: '随县', + value: 421321, + }, + { + children: [], + label: '广水市', + value: 421381, + }, + ], + label: '随州市', + value: 421300, + }, + { + children: [ + { + children: [], + label: '恩施市', + value: 422801, + }, + { + children: [], + label: '利川市', + value: 422802, + }, + { + children: [], + label: '建始县', + value: 422822, + }, + { + children: [], + label: '巴东县', + value: 422823, + }, + { + children: [], + label: '宣恩县', + value: 422825, + }, + { + children: [], + label: '咸丰县', + value: 422826, + }, + { + children: [], + label: '来凤县', + value: 422827, + }, + { + children: [], + label: '鹤峰县', + value: 422828, + }, + ], + label: '恩施土家族苗族自治州', + value: 422800, + }, + { + children: [], + label: '仙桃市', + value: 429004, + }, + { + children: [], + label: '潜江市', + value: 429005, + }, + { + children: [], + label: '天门市', + value: 429006, + }, + { + children: [], + label: '神农架林区', + value: 429021, + }, + ], + label: '湖北省', + value: 420000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '芙蓉区', + value: 430102, + }, + { + children: [], + label: '天心区', + value: 430103, + }, + { + children: [], + label: '岳麓区', + value: 430104, + }, + { + children: [], + label: '开福区', + value: 430105, + }, + { + children: [], + label: '雨花区', + value: 430111, + }, + { + children: [], + label: '望城区', + value: 430112, + }, + { + children: [], + label: '长沙县', + value: 430121, + }, + { + children: [], + label: '浏阳市', + value: 430181, + }, + { + children: [], + label: '宁乡市', + value: 430182, + }, + ], + label: '长沙市', + value: 430100, + }, + { + children: [ + { + children: [], + label: '荷塘区', + value: 430202, + }, + { + children: [], + label: '芦淞区', + value: 430203, + }, + { + children: [], + label: '石峰区', + value: 430204, + }, + { + children: [], + label: '天元区', + value: 430211, + }, + { + children: [], + label: '渌口区', + value: 430212, + }, + { + children: [], + label: '攸县', + value: 430223, + }, + { + children: [], + label: '茶陵县', + value: 430224, + }, + { + children: [], + label: '炎陵县', + value: 430225, + }, + { + children: [], + label: '醴陵市', + value: 430281, + }, + ], + label: '株洲市', + value: 430200, + }, + { + children: [ + { + children: [], + label: '雨湖区', + value: 430302, + }, + { + children: [], + label: '岳塘区', + value: 430304, + }, + { + children: [], + label: '湘潭县', + value: 430321, + }, + { + children: [], + label: '湘乡市', + value: 430381, + }, + { + children: [], + label: '韶山市', + value: 430382, + }, + ], + label: '湘潭市', + value: 430300, + }, + { + children: [ + { + children: [], + label: '珠晖区', + value: 430405, + }, + { + children: [], + label: '雁峰区', + value: 430406, + }, + { + children: [], + label: '石鼓区', + value: 430407, + }, + { + children: [], + label: '蒸湘区', + value: 430408, + }, + { + children: [], + label: '南岳区', + value: 430412, + }, + { + children: [], + label: '衡阳县', + value: 430421, + }, + { + children: [], + label: '衡南县', + value: 430422, + }, + { + children: [], + label: '衡山县', + value: 430423, + }, + { + children: [], + label: '衡东县', + value: 430424, + }, + { + children: [], + label: '祁东县', + value: 430426, + }, + { + children: [], + label: '耒阳市', + value: 430481, + }, + { + children: [], + label: '常宁市', + value: 430482, + }, + ], + label: '衡阳市', + value: 430400, + }, + { + children: [ + { + children: [], + label: '双清区', + value: 430502, + }, + { + children: [], + label: '大祥区', + value: 430503, + }, + { + children: [], + label: '北塔区', + value: 430511, + }, + { + children: [], + label: '邵东县', + value: 430521, + }, + { + children: [], + label: '新邵县', + value: 430522, + }, + { + children: [], + label: '邵阳县', + value: 430523, + }, + { + children: [], + label: '隆回县', + value: 430524, + }, + { + children: [], + label: '洞口县', + value: 430525, + }, + { + children: [], + label: '绥宁县', + value: 430527, + }, + { + children: [], + label: '新宁县', + value: 430528, + }, + { + children: [], + label: '城步苗族自治县', + value: 430529, + }, + { + children: [], + label: '武冈市', + value: 430581, + }, + ], + label: '邵阳市', + value: 430500, + }, + { + children: [ + { + children: [], + label: '岳阳楼区', + value: 430602, + }, + { + children: [], + label: '云溪区', + value: 430603, + }, + { + children: [], + label: '君山区', + value: 430611, + }, + { + children: [], + label: '岳阳县', + value: 430621, + }, + { + children: [], + label: '华容县', + value: 430623, + }, + { + children: [], + label: '湘阴县', + value: 430624, + }, + { + children: [], + label: '平江县', + value: 430626, + }, + { + children: [], + label: '汨罗市', + value: 430681, + }, + { + children: [], + label: '临湘市', + value: 430682, + }, + ], + label: '岳阳市', + value: 430600, + }, + { + children: [ + { + children: [], + label: '武陵区', + value: 430702, + }, + { + children: [], + label: '鼎城区', + value: 430703, + }, + { + children: [], + label: '安乡县', + value: 430721, + }, + { + children: [], + label: '汉寿县', + value: 430722, + }, + { + children: [], + label: '澧县', + value: 430723, + }, + { + children: [], + label: '临澧县', + value: 430724, + }, + { + children: [], + label: '桃源县', + value: 430725, + }, + { + children: [], + label: '石门县', + value: 430726, + }, + { + children: [], + label: '津市市', + value: 430781, + }, + ], + label: '常德市', + value: 430700, + }, + { + children: [ + { + children: [], + label: '永定区', + value: 430802, + }, + { + children: [], + label: '武陵源区', + value: 430811, + }, + { + children: [], + label: '慈利县', + value: 430821, + }, + { + children: [], + label: '桑植县', + value: 430822, + }, + ], + label: '张家界市', + value: 430800, + }, + { + children: [ + { + children: [], + label: '资阳区', + value: 430902, + }, + { + children: [], + label: '赫山区', + value: 430903, + }, + { + children: [], + label: '南县', + value: 430921, + }, + { + children: [], + label: '桃江县', + value: 430922, + }, + { + children: [], + label: '安化县', + value: 430923, + }, + { + children: [], + label: '沅江市', + value: 430981, + }, + ], + label: '益阳市', + value: 430900, + }, + { + children: [ + { + children: [], + label: '北湖区', + value: 431002, + }, + { + children: [], + label: '苏仙区', + value: 431003, + }, + { + children: [], + label: '桂阳县', + value: 431021, + }, + { + children: [], + label: '宜章县', + value: 431022, + }, + { + children: [], + label: '永兴县', + value: 431023, + }, + { + children: [], + label: '嘉禾县', + value: 431024, + }, + { + children: [], + label: '临武县', + value: 431025, + }, + { + children: [], + label: '汝城县', + value: 431026, + }, + { + children: [], + label: '桂东县', + value: 431027, + }, + { + children: [], + label: '安仁县', + value: 431028, + }, + { + children: [], + label: '资兴市', + value: 431081, + }, + ], + label: '郴州市', + value: 431000, + }, + { + children: [ + { + children: [], + label: '零陵区', + value: 431102, + }, + { + children: [], + label: '冷水滩区', + value: 431103, + }, + { + children: [], + label: '祁阳县', + value: 431121, + }, + { + children: [], + label: '东安县', + value: 431122, + }, + { + children: [], + label: '双牌县', + value: 431123, + }, + { + children: [], + label: '道县', + value: 431124, + }, + { + children: [], + label: '江永县', + value: 431125, + }, + { + children: [], + label: '宁远县', + value: 431126, + }, + { + children: [], + label: '蓝山县', + value: 431127, + }, + { + children: [], + label: '新田县', + value: 431128, + }, + { + children: [], + label: '江华瑶族自治县', + value: 431129, + }, + ], + label: '永州市', + value: 431100, + }, + { + children: [ + { + children: [], + label: '鹤城区', + value: 431202, + }, + { + children: [], + label: '中方县', + value: 431221, + }, + { + children: [], + label: '沅陵县', + value: 431222, + }, + { + children: [], + label: '辰溪县', + value: 431223, + }, + { + children: [], + label: '溆浦县', + value: 431224, + }, + { + children: [], + label: '会同县', + value: 431225, + }, + { + children: [], + label: '麻阳苗族自治县', + value: 431226, + }, + { + children: [], + label: '新晃侗族自治县', + value: 431227, + }, + { + children: [], + label: '芷江侗族自治县', + value: 431228, + }, + { + children: [], + label: '靖州苗族侗族自治县', + value: 431229, + }, + { + children: [], + label: '通道侗族自治县', + value: 431230, + }, + { + children: [], + label: '洪江市', + value: 431281, + }, + ], + label: '怀化市', + value: 431200, + }, + { + children: [ + { + children: [], + label: '娄星区', + value: 431302, + }, + { + children: [], + label: '双峰县', + value: 431321, + }, + { + children: [], + label: '新化县', + value: 431322, + }, + { + children: [], + label: '冷水江市', + value: 431381, + }, + { + children: [], + label: '涟源市', + value: 431382, + }, + ], + label: '娄底市', + value: 431300, + }, + { + children: [ + { + children: [], + label: '吉首市', + value: 433101, + }, + { + children: [], + label: '泸溪县', + value: 433122, + }, + { + children: [], + label: '凤凰县', + value: 433123, + }, + { + children: [], + label: '花垣县', + value: 433124, + }, + { + children: [], + label: '保靖县', + value: 433125, + }, + { + children: [], + label: '古丈县', + value: 433126, + }, + { + children: [], + label: '永顺县', + value: 433127, + }, + { + children: [], + label: '龙山县', + value: 433130, + }, + ], + label: '湘西土家族苗族自治州', + value: 433100, + }, + ], + label: '湖南省', + value: 430000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '荔湾区', + value: 440103, + }, + { + children: [], + label: '越秀区', + value: 440104, + }, + { + children: [], + label: '海珠区', + value: 440105, + }, + { + children: [], + label: '天河区', + value: 440106, + }, + { + children: [], + label: '白云区', + value: 440111, + }, + { + children: [], + label: '黄埔区', + value: 440112, + }, + { + children: [], + label: '番禺区', + value: 440113, + }, + { + children: [], + label: '花都区', + value: 440114, + }, + { + children: [], + label: '南沙区', + value: 440115, + }, + { + children: [], + label: '从化区', + value: 440117, + }, + { + children: [], + label: '增城区', + value: 440118, + }, + ], + label: '广州市', + value: 440100, + }, + { + children: [ + { + children: [], + label: '武江区', + value: 440203, + }, + { + children: [], + label: '浈江区', + value: 440204, + }, + { + children: [], + label: '曲江区', + value: 440205, + }, + { + children: [], + label: '始兴县', + value: 440222, + }, + { + children: [], + label: '仁化县', + value: 440224, + }, + { + children: [], + label: '翁源县', + value: 440229, + }, + { + children: [], + label: '乳源瑶族自治县', + value: 440232, + }, + { + children: [], + label: '新丰县', + value: 440233, + }, + { + children: [], + label: '乐昌市', + value: 440281, + }, + { + children: [], + label: '南雄市', + value: 440282, + }, + ], + label: '韶关市', + value: 440200, + }, + { + children: [ + { + children: [], + label: '罗湖区', + value: 440303, + }, + { + children: [], + label: '福田区', + value: 440304, + }, + { + children: [], + label: '南山区', + value: 440305, + }, + { + children: [], + label: '宝安区', + value: 440306, + }, + { + children: [], + label: '龙岗区', + value: 440307, + }, + { + children: [], + label: '盐田区', + value: 440308, + }, + { + children: [], + label: '龙华区', + value: 440309, + }, + { + children: [], + label: '坪山区', + value: 440310, + }, + { + children: [], + label: '光明区', + value: 440311, + }, + ], + label: '深圳市', + value: 440300, + }, + { + children: [ + { + children: [], + label: '香洲区', + value: 440402, + }, + { + children: [], + label: '斗门区', + value: 440403, + }, + { + children: [], + label: '金湾区', + value: 440404, + }, + ], + label: '珠海市', + value: 440400, + }, + { + children: [ + { + children: [], + label: '龙湖区', + value: 440507, + }, + { + children: [], + label: '金平区', + value: 440511, + }, + { + children: [], + label: '濠江区', + value: 440512, + }, + { + children: [], + label: '潮阳区', + value: 440513, + }, + { + children: [], + label: '潮南区', + value: 440514, + }, + { + children: [], + label: '澄海区', + value: 440515, + }, + { + children: [], + label: '南澳县', + value: 440523, + }, + ], + label: '汕头市', + value: 440500, + }, + { + children: [ + { + children: [], + label: '禅城区', + value: 440604, + }, + { + children: [], + label: '南海区', + value: 440605, + }, + { + children: [], + label: '顺德区', + value: 440606, + }, + { + children: [], + label: '三水区', + value: 440607, + }, + { + children: [], + label: '高明区', + value: 440608, + }, + ], + label: '佛山市', + value: 440600, + }, + { + children: [ + { + children: [], + label: '蓬江区', + value: 440703, + }, + { + children: [], + label: '江海区', + value: 440704, + }, + { + children: [], + label: '新会区', + value: 440705, + }, + { + children: [], + label: '台山市', + value: 440781, + }, + { + children: [], + label: '开平市', + value: 440783, + }, + { + children: [], + label: '鹤山市', + value: 440784, + }, + { + children: [], + label: '恩平市', + value: 440785, + }, + ], + label: '江门市', + value: 440700, + }, + { + children: [ + { + children: [], + label: '赤坎区', + value: 440802, + }, + { + children: [], + label: '霞山区', + value: 440803, + }, + { + children: [], + label: '坡头区', + value: 440804, + }, + { + children: [], + label: '麻章区', + value: 440811, + }, + { + children: [], + label: '遂溪县', + value: 440823, + }, + { + children: [], + label: '徐闻县', + value: 440825, + }, + { + children: [], + label: '廉江市', + value: 440881, + }, + { + children: [], + label: '雷州市', + value: 440882, + }, + { + children: [], + label: '吴川市', + value: 440883, + }, + ], + label: '湛江市', + value: 440800, + }, + { + children: [ + { + children: [], + label: '茂南区', + value: 440902, + }, + { + children: [], + label: '电白区', + value: 440904, + }, + { + children: [], + label: '高州市', + value: 440981, + }, + { + children: [], + label: '化州市', + value: 440982, + }, + { + children: [], + label: '信宜市', + value: 440983, + }, + ], + label: '茂名市', + value: 440900, + }, + { + children: [ + { + children: [], + label: '端州区', + value: 441202, + }, + { + children: [], + label: '鼎湖区', + value: 441203, + }, + { + children: [], + label: '高要区', + value: 441204, + }, + { + children: [], + label: '广宁县', + value: 441223, + }, + { + children: [], + label: '怀集县', + value: 441224, + }, + { + children: [], + label: '封开县', + value: 441225, + }, + { + children: [], + label: '德庆县', + value: 441226, + }, + { + children: [], + label: '四会市', + value: 441284, + }, + ], + label: '肇庆市', + value: 441200, + }, + { + children: [ + { + children: [], + label: '惠城区', + value: 441302, + }, + { + children: [], + label: '惠阳区', + value: 441303, + }, + { + children: [], + label: '博罗县', + value: 441322, + }, + { + children: [], + label: '惠东县', + value: 441323, + }, + { + children: [], + label: '龙门县', + value: 441324, + }, + ], + label: '惠州市', + value: 441300, + }, + { + children: [ + { + children: [], + label: '梅江区', + value: 441402, + }, + { + children: [], + label: '梅县区', + value: 441403, + }, + { + children: [], + label: '大埔县', + value: 441422, + }, + { + children: [], + label: '丰顺县', + value: 441423, + }, + { + children: [], + label: '五华县', + value: 441424, + }, + { + children: [], + label: '平远县', + value: 441426, + }, + { + children: [], + label: '蕉岭县', + value: 441427, + }, + { + children: [], + label: '兴宁市', + value: 441481, + }, + ], + label: '梅州市', + value: 441400, + }, + { + children: [ + { + children: [], + label: '城区', + value: 441502, + }, + { + children: [], + label: '海丰县', + value: 441521, + }, + { + children: [], + label: '陆河县', + value: 441523, + }, + { + children: [], + label: '陆丰市', + value: 441581, + }, + ], + label: '汕尾市', + value: 441500, + }, + { + children: [ + { + children: [], + label: '源城区', + value: 441602, + }, + { + children: [], + label: '紫金县', + value: 441621, + }, + { + children: [], + label: '龙川县', + value: 441622, + }, + { + children: [], + label: '连平县', + value: 441623, + }, + { + children: [], + label: '和平县', + value: 441624, + }, + { + children: [], + label: '东源县', + value: 441625, + }, + ], + label: '河源市', + value: 441600, + }, + { + children: [ + { + children: [], + label: '江城区', + value: 441702, + }, + { + children: [], + label: '阳东区', + value: 441704, + }, + { + children: [], + label: '阳西县', + value: 441721, + }, + { + children: [], + label: '阳春市', + value: 441781, + }, + ], + label: '阳江市', + value: 441700, + }, + { + children: [ + { + children: [], + label: '清城区', + value: 441802, + }, + { + children: [], + label: '清新区', + value: 441803, + }, + { + children: [], + label: '佛冈县', + value: 441821, + }, + { + children: [], + label: '阳山县', + value: 441823, + }, + { + children: [], + label: '连山壮族瑶族自治县', + value: 441825, + }, + { + children: [], + label: '连南瑶族自治县', + value: 441826, + }, + { + children: [], + label: '英德市', + value: 441881, + }, + { + children: [], + label: '连州市', + value: 441882, + }, + ], + label: '清远市', + value: 441800, + }, + { + children: [], + label: '东莞市', + value: 441900, + }, + { + children: [], + label: '中山市', + value: 442000, + }, + { + children: [ + { + children: [], + label: '湘桥区', + value: 445102, + }, + { + children: [], + label: '潮安区', + value: 445103, + }, + { + children: [], + label: '饶平县', + value: 445122, + }, + ], + label: '潮州市', + value: 445100, + }, + { + children: [ + { + children: [], + label: '榕城区', + value: 445202, + }, + { + children: [], + label: '揭东区', + value: 445203, + }, + { + children: [], + label: '揭西县', + value: 445222, + }, + { + children: [], + label: '惠来县', + value: 445224, + }, + { + children: [], + label: '普宁市', + value: 445281, + }, + ], + label: '揭阳市', + value: 445200, + }, + { + children: [ + { + children: [], + label: '云城区', + value: 445302, + }, + { + children: [], + label: '云安区', + value: 445303, + }, + { + children: [], + label: '新兴县', + value: 445321, + }, + { + children: [], + label: '郁南县', + value: 445322, + }, + { + children: [], + label: '罗定市', + value: 445381, + }, + ], + label: '云浮市', + value: 445300, + }, + ], + label: '广东省', + value: 440000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '兴宁区', + value: 450102, + }, + { + children: [], + label: '青秀区', + value: 450103, + }, + { + children: [], + label: '江南区', + value: 450105, + }, + { + children: [], + label: '西乡塘区', + value: 450107, + }, + { + children: [], + label: '良庆区', + value: 450108, + }, + { + children: [], + label: '邕宁区', + value: 450109, + }, + { + children: [], + label: '武鸣区', + value: 450110, + }, + { + children: [], + label: '隆安县', + value: 450123, + }, + { + children: [], + label: '马山县', + value: 450124, + }, + { + children: [], + label: '上林县', + value: 450125, + }, + { + children: [], + label: '宾阳县', + value: 450126, + }, + { + children: [], + label: '横县', + value: 450127, + }, + ], + label: '南宁市', + value: 450100, + }, + { + children: [ + { + children: [], + label: '城中区', + value: 450202, + }, + { + children: [], + label: '鱼峰区', + value: 450203, + }, + { + children: [], + label: '柳南区', + value: 450204, + }, + { + children: [], + label: '柳北区', + value: 450205, + }, + { + children: [], + label: '柳江区', + value: 450206, + }, + { + children: [], + label: '柳城县', + value: 450222, + }, + { + children: [], + label: '鹿寨县', + value: 450223, + }, + { + children: [], + label: '融安县', + value: 450224, + }, + { + children: [], + label: '融水苗族自治县', + value: 450225, + }, + { + children: [], + label: '三江侗族自治县', + value: 450226, + }, + ], + label: '柳州市', + value: 450200, + }, + { + children: [ + { + children: [], + label: '秀峰区', + value: 450302, + }, + { + children: [], + label: '叠彩区', + value: 450303, + }, + { + children: [], + label: '象山区', + value: 450304, + }, + { + children: [], + label: '七星区', + value: 450305, + }, + { + children: [], + label: '雁山区', + value: 450311, + }, + { + children: [], + label: '临桂区', + value: 450312, + }, + { + children: [], + label: '阳朔县', + value: 450321, + }, + { + children: [], + label: '灵川县', + value: 450323, + }, + { + children: [], + label: '全州县', + value: 450324, + }, + { + children: [], + label: '兴安县', + value: 450325, + }, + { + children: [], + label: '永福县', + value: 450326, + }, + { + children: [], + label: '灌阳县', + value: 450327, + }, + { + children: [], + label: '龙胜各族自治县', + value: 450328, + }, + { + children: [], + label: '资源县', + value: 450329, + }, + { + children: [], + label: '平乐县', + value: 450330, + }, + { + children: [], + label: '恭城瑶族自治县', + value: 450332, + }, + { + children: [], + label: '荔浦市', + value: 450381, + }, + ], + label: '桂林市', + value: 450300, + }, + { + children: [ + { + children: [], + label: '万秀区', + value: 450403, + }, + { + children: [], + label: '长洲区', + value: 450405, + }, + { + children: [], + label: '龙圩区', + value: 450406, + }, + { + children: [], + label: '苍梧县', + value: 450421, + }, + { + children: [], + label: '藤县', + value: 450422, + }, + { + children: [], + label: '蒙山县', + value: 450423, + }, + { + children: [], + label: '岑溪市', + value: 450481, + }, + ], + label: '梧州市', + value: 450400, + }, + { + children: [ + { + children: [], + label: '海城区', + value: 450502, + }, + { + children: [], + label: '银海区', + value: 450503, + }, + { + children: [], + label: '铁山港区', + value: 450512, + }, + { + children: [], + label: '合浦县', + value: 450521, + }, + ], + label: '北海市', + value: 450500, + }, + { + children: [ + { + children: [], + label: '港口区', + value: 450602, + }, + { + children: [], + label: '防城区', + value: 450603, + }, + { + children: [], + label: '上思县', + value: 450621, + }, + { + children: [], + label: '东兴市', + value: 450681, + }, + ], + label: '防城港市', + value: 450600, + }, + { + children: [ + { + children: [], + label: '钦南区', + value: 450702, + }, + { + children: [], + label: '钦北区', + value: 450703, + }, + { + children: [], + label: '灵山县', + value: 450721, + }, + { + children: [], + label: '浦北县', + value: 450722, + }, + ], + label: '钦州市', + value: 450700, + }, + { + children: [ + { + children: [], + label: '港北区', + value: 450802, + }, + { + children: [], + label: '港南区', + value: 450803, + }, + { + children: [], + label: '覃塘区', + value: 450804, + }, + { + children: [], + label: '平南县', + value: 450821, + }, + { + children: [], + label: '桂平市', + value: 450881, + }, + ], + label: '贵港市', + value: 450800, + }, + { + children: [ + { + children: [], + label: '玉州区', + value: 450902, + }, + { + children: [], + label: '福绵区', + value: 450903, + }, + { + children: [], + label: '容县', + value: 450921, + }, + { + children: [], + label: '陆川县', + value: 450922, + }, + { + children: [], + label: '博白县', + value: 450923, + }, + { + children: [], + label: '兴业县', + value: 450924, + }, + { + children: [], + label: '北流市', + value: 450981, + }, + ], + label: '玉林市', + value: 450900, + }, + { + children: [ + { + children: [], + label: '右江区', + value: 451002, + }, + { + children: [], + label: '田阳县', + value: 451021, + }, + { + children: [], + label: '田东县', + value: 451022, + }, + { + children: [], + label: '平果县', + value: 451023, + }, + { + children: [], + label: '德保县', + value: 451024, + }, + { + children: [], + label: '那坡县', + value: 451026, + }, + { + children: [], + label: '凌云县', + value: 451027, + }, + { + children: [], + label: '乐业县', + value: 451028, + }, + { + children: [], + label: '田林县', + value: 451029, + }, + { + children: [], + label: '西林县', + value: 451030, + }, + { + children: [], + label: '隆林各族自治县', + value: 451031, + }, + { + children: [], + label: '靖西市', + value: 451081, + }, + ], + label: '百色市', + value: 451000, + }, + { + children: [ + { + children: [], + label: '八步区', + value: 451102, + }, + { + children: [], + label: '平桂区', + value: 451103, + }, + { + children: [], + label: '昭平县', + value: 451121, + }, + { + children: [], + label: '钟山县', + value: 451122, + }, + { + children: [], + label: '富川瑶族自治县', + value: 451123, + }, + ], + label: '贺州市', + value: 451100, + }, + { + children: [ + { + children: [], + label: '金城江区', + value: 451202, + }, + { + children: [], + label: '宜州区', + value: 451203, + }, + { + children: [], + label: '南丹县', + value: 451221, + }, + { + children: [], + label: '天峨县', + value: 451222, + }, + { + children: [], + label: '凤山县', + value: 451223, + }, + { + children: [], + label: '东兰县', + value: 451224, + }, + { + children: [], + label: '罗城仫佬族自治县', + value: 451225, + }, + { + children: [], + label: '环江毛南族自治县', + value: 451226, + }, + { + children: [], + label: '巴马瑶族自治县', + value: 451227, + }, + { + children: [], + label: '都安瑶族自治县', + value: 451228, + }, + { + children: [], + label: '大化瑶族自治县', + value: 451229, + }, + ], + label: '河池市', + value: 451200, + }, + { + children: [ + { + children: [], + label: '兴宾区', + value: 451302, + }, + { + children: [], + label: '忻城县', + value: 451321, + }, + { + children: [], + label: '象州县', + value: 451322, + }, + { + children: [], + label: '武宣县', + value: 451323, + }, + { + children: [], + label: '金秀瑶族自治县', + value: 451324, + }, + { + children: [], + label: '合山市', + value: 451381, + }, + ], + label: '来宾市', + value: 451300, + }, + { + children: [ + { + children: [], + label: '江州区', + value: 451402, + }, + { + children: [], + label: '扶绥县', + value: 451421, + }, + { + children: [], + label: '宁明县', + value: 451422, + }, + { + children: [], + label: '龙州县', + value: 451423, + }, + { + children: [], + label: '大新县', + value: 451424, + }, + { + children: [], + label: '天等县', + value: 451425, + }, + { + children: [], + label: '凭祥市', + value: 451481, + }, + ], + label: '崇左市', + value: 451400, + }, + ], + label: '广西壮族自治区', + value: 450000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '秀英区', + value: 460105, + }, + { + children: [], + label: '龙华区', + value: 460106, + }, + { + children: [], + label: '琼山区', + value: 460107, + }, + { + children: [], + label: '美兰区', + value: 460108, + }, + ], + label: '海口市', + value: 460100, + }, + { + children: [ + { + children: [], + label: '海棠区', + value: 460202, + }, + { + children: [], + label: '吉阳区', + value: 460203, + }, + { + children: [], + label: '天涯区', + value: 460204, + }, + { + children: [], + label: '崖州区', + value: 460205, + }, + ], + label: '三亚市', + value: 460200, + }, + { + children: [ + { + children: [], + label: '西沙群岛', + value: 460321, + }, + { + children: [], + label: '南沙群岛', + value: 460322, + }, + { + children: [], + label: '中沙群岛', + value: 460323, + }, + ], + label: '三沙市', + value: 460300, + }, + { + children: [], + label: '儋州市', + value: 460400, + }, + { + children: [], + label: '五指山市', + value: 469001, + }, + { + children: [], + label: '琼海市', + value: 469002, + }, + { + children: [], + label: '文昌市', + value: 469005, + }, + { + children: [], + label: '万宁市', + value: 469006, + }, + { + children: [], + label: '东方市', + value: 469007, + }, + { + children: [], + label: '定安县', + value: 469021, + }, + { + children: [], + label: '屯昌县', + value: 469022, + }, + { + children: [], + label: '澄迈县', + value: 469023, + }, + { + children: [], + label: '临高县', + value: 469024, + }, + { + children: [], + label: '白沙黎族自治县', + value: 469025, + }, + { + children: [], + label: '昌江黎族自治县', + value: 469026, + }, + { + children: [], + label: '乐东黎族自治县', + value: 469027, + }, + { + children: [], + label: '陵水黎族自治县', + value: 469028, + }, + { + children: [], + label: '保亭黎族苗族自治县', + value: 469029, + }, + { + children: [], + label: '琼中黎族苗族自治县', + value: 469030, + }, + ], + label: '海南省', + value: 460000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '万州区', + value: 500101, + }, + { + children: [], + label: '涪陵区', + value: 500102, + }, + { + children: [], + label: '渝中区', + value: 500103, + }, + { + children: [], + label: '大渡口区', + value: 500104, + }, + { + children: [], + label: '江北区', + value: 500105, + }, + { + children: [], + label: '沙坪坝区', + value: 500106, + }, + { + children: [], + label: '九龙坡区', + value: 500107, + }, + { + children: [], + label: '南岸区', + value: 500108, + }, + { + children: [], + label: '北碚区', + value: 500109, + }, + { + children: [], + label: '綦江区', + value: 500110, + }, + { + children: [], + label: '大足区', + value: 500111, + }, + { + children: [], + label: '渝北区', + value: 500112, + }, + { + children: [], + label: '巴南区', + value: 500113, + }, + { + children: [], + label: '黔江区', + value: 500114, + }, + { + children: [], + label: '长寿区', + value: 500115, + }, + { + children: [], + label: '江津区', + value: 500116, + }, + { + children: [], + label: '合川区', + value: 500117, + }, + { + children: [], + label: '永川区', + value: 500118, + }, + { + children: [], + label: '南川区', + value: 500119, + }, + { + children: [], + label: '璧山区', + value: 500120, + }, + { + children: [], + label: '铜梁区', + value: 500151, + }, + { + children: [], + label: '潼南区', + value: 500152, + }, + { + children: [], + label: '荣昌区', + value: 500153, + }, + { + children: [], + label: '开州区', + value: 500154, + }, + { + children: [], + label: '梁平区', + value: 500155, + }, + { + children: [], + label: '武隆区', + value: 500156, + }, + ], + label: '重庆市', + value: 500100, + }, + { + children: [ + { + children: [], + label: '城口县', + value: 500229, + }, + { + children: [], + label: '丰都县', + value: 500230, + }, + { + children: [], + label: '垫江县', + value: 500231, + }, + { + children: [], + label: '忠县', + value: 500233, + }, + { + children: [], + label: '云阳县', + value: 500235, + }, + { + children: [], + label: '奉节县', + value: 500236, + }, + { + children: [], + label: '巫山县', + value: 500237, + }, + { + children: [], + label: '巫溪县', + value: 500238, + }, + { + children: [], + label: '石柱土家族自治县', + value: 500240, + }, + { + children: [], + label: '秀山土家族苗族自治县', + value: 500241, + }, + { + children: [], + label: '酉阳土家族苗族自治县', + value: 500242, + }, + { + children: [], + label: '彭水苗族土家族自治县', + value: 500243, + }, + ], + label: '重庆市', + value: 500200, + }, + ], + label: '重庆市', + value: 500000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '锦江区', + value: 510104, + }, + { + children: [], + label: '青羊区', + value: 510105, + }, + { + children: [], + label: '金牛区', + value: 510106, + }, + { + children: [], + label: '武侯区', + value: 510107, + }, + { + children: [], + label: '成华区', + value: 510108, + }, + { + children: [], + label: '龙泉驿区', + value: 510112, + }, + { + children: [], + label: '青白江区', + value: 510113, + }, + { + children: [], + label: '新都区', + value: 510114, + }, + { + children: [], + label: '温江区', + value: 510115, + }, + { + children: [], + label: '双流区', + value: 510116, + }, + { + children: [], + label: '郫都区', + value: 510117, + }, + { + children: [], + label: '金堂县', + value: 510121, + }, + { + children: [], + label: '大邑县', + value: 510129, + }, + { + children: [], + label: '蒲江县', + value: 510131, + }, + { + children: [], + label: '新津县', + value: 510132, + }, + { + children: [], + label: '都江堰市', + value: 510181, + }, + { + children: [], + label: '彭州市', + value: 510182, + }, + { + children: [], + label: '邛崃市', + value: 510183, + }, + { + children: [], + label: '崇州市', + value: 510184, + }, + { + children: [], + label: '简阳市', + value: 510185, + }, + ], + label: '成都市', + value: 510100, + }, + { + children: [ + { + children: [], + label: '自流井区', + value: 510302, + }, + { + children: [], + label: '贡井区', + value: 510303, + }, + { + children: [], + label: '大安区', + value: 510304, + }, + { + children: [], + label: '沿滩区', + value: 510311, + }, + { + children: [], + label: '荣县', + value: 510321, + }, + { + children: [], + label: '富顺县', + value: 510322, + }, + ], + label: '自贡市', + value: 510300, + }, + { + children: [ + { + children: [], + label: '东区', + value: 510402, + }, + { + children: [], + label: '西区', + value: 510403, + }, + { + children: [], + label: '仁和区', + value: 510411, + }, + { + children: [], + label: '米易县', + value: 510421, + }, + { + children: [], + label: '盐边县', + value: 510422, + }, + ], + label: '攀枝花市', + value: 510400, + }, + { + children: [ + { + children: [], + label: '江阳区', + value: 510502, + }, + { + children: [], + label: '纳溪区', + value: 510503, + }, + { + children: [], + label: '龙马潭区', + value: 510504, + }, + { + children: [], + label: '泸县', + value: 510521, + }, + { + children: [], + label: '合江县', + value: 510522, + }, + { + children: [], + label: '叙永县', + value: 510524, + }, + { + children: [], + label: '古蔺县', + value: 510525, + }, + ], + label: '泸州市', + value: 510500, + }, + { + children: [ + { + children: [], + label: '旌阳区', + value: 510603, + }, + { + children: [], + label: '罗江区', + value: 510604, + }, + { + children: [], + label: '中江县', + value: 510623, + }, + { + children: [], + label: '广汉市', + value: 510681, + }, + { + children: [], + label: '什邡市', + value: 510682, + }, + { + children: [], + label: '绵竹市', + value: 510683, + }, + ], + label: '德阳市', + value: 510600, + }, + { + children: [ + { + children: [], + label: '涪城区', + value: 510703, + }, + { + children: [], + label: '游仙区', + value: 510704, + }, + { + children: [], + label: '安州区', + value: 510705, + }, + { + children: [], + label: '三台县', + value: 510722, + }, + { + children: [], + label: '盐亭县', + value: 510723, + }, + { + children: [], + label: '梓潼县', + value: 510725, + }, + { + children: [], + label: '北川羌族自治县', + value: 510726, + }, + { + children: [], + label: '平武县', + value: 510727, + }, + { + children: [], + label: '江油市', + value: 510781, + }, + ], + label: '绵阳市', + value: 510700, + }, + { + children: [ + { + children: [], + label: '利州区', + value: 510802, + }, + { + children: [], + label: '昭化区', + value: 510811, + }, + { + children: [], + label: '朝天区', + value: 510812, + }, + { + children: [], + label: '旺苍县', + value: 510821, + }, + { + children: [], + label: '青川县', + value: 510822, + }, + { + children: [], + label: '剑阁县', + value: 510823, + }, + { + children: [], + label: '苍溪县', + value: 510824, + }, + ], + label: '广元市', + value: 510800, + }, + { + children: [ + { + children: [], + label: '船山区', + value: 510903, + }, + { + children: [], + label: '安居区', + value: 510904, + }, + { + children: [], + label: '蓬溪县', + value: 510921, + }, + { + children: [], + label: '射洪县', + value: 510922, + }, + { + children: [], + label: '大英县', + value: 510923, + }, + ], + label: '遂宁市', + value: 510900, + }, + { + children: [ + { + children: [], + label: '市中区', + value: 511002, + }, + { + children: [], + label: '东兴区', + value: 511011, + }, + { + children: [], + label: '威远县', + value: 511024, + }, + { + children: [], + label: '资中县', + value: 511025, + }, + { + children: [], + label: '隆昌市', + value: 511083, + }, + ], + label: '内江市', + value: 511000, + }, + { + children: [ + { + children: [], + label: '市中区', + value: 511102, + }, + { + children: [], + label: '沙湾区', + value: 511111, + }, + { + children: [], + label: '五通桥区', + value: 511112, + }, + { + children: [], + label: '金口河区', + value: 511113, + }, + { + children: [], + label: '犍为县', + value: 511123, + }, + { + children: [], + label: '井研县', + value: 511124, + }, + { + children: [], + label: '夹江县', + value: 511126, + }, + { + children: [], + label: '沐川县', + value: 511129, + }, + { + children: [], + label: '峨边彝族自治县', + value: 511132, + }, + { + children: [], + label: '马边彝族自治县', + value: 511133, + }, + { + children: [], + label: '峨眉山市', + value: 511181, + }, + ], + label: '乐山市', + value: 511100, + }, + { + children: [ + { + children: [], + label: '顺庆区', + value: 511302, + }, + { + children: [], + label: '高坪区', + value: 511303, + }, + { + children: [], + label: '嘉陵区', + value: 511304, + }, + { + children: [], + label: '南部县', + value: 511321, + }, + { + children: [], + label: '营山县', + value: 511322, + }, + { + children: [], + label: '蓬安县', + value: 511323, + }, + { + children: [], + label: '仪陇县', + value: 511324, + }, + { + children: [], + label: '西充县', + value: 511325, + }, + { + children: [], + label: '阆中市', + value: 511381, + }, + ], + label: '南充市', + value: 511300, + }, + { + children: [ + { + children: [], + label: '东坡区', + value: 511402, + }, + { + children: [], + label: '彭山区', + value: 511403, + }, + { + children: [], + label: '仁寿县', + value: 511421, + }, + { + children: [], + label: '洪雅县', + value: 511423, + }, + { + children: [], + label: '丹棱县', + value: 511424, + }, + { + children: [], + label: '青神县', + value: 511425, + }, + ], + label: '眉山市', + value: 511400, + }, + { + children: [ + { + children: [], + label: '翠屏区', + value: 511502, + }, + { + children: [], + label: '南溪区', + value: 511503, + }, + { + children: [], + label: '叙州区', + value: 511504, + }, + { + children: [], + label: '江安县', + value: 511523, + }, + { + children: [], + label: '长宁县', + value: 511524, + }, + { + children: [], + label: '高县', + value: 511525, + }, + { + children: [], + label: '珙县', + value: 511526, + }, + { + children: [], + label: '筠连县', + value: 511527, + }, + { + children: [], + label: '兴文县', + value: 511528, + }, + { + children: [], + label: '屏山县', + value: 511529, + }, + ], + label: '宜宾市', + value: 511500, + }, + { + children: [ + { + children: [], + label: '广安区', + value: 511602, + }, + { + children: [], + label: '前锋区', + value: 511603, + }, + { + children: [], + label: '岳池县', + value: 511621, + }, + { + children: [], + label: '武胜县', + value: 511622, + }, + { + children: [], + label: '邻水县', + value: 511623, + }, + { + children: [], + label: '华蓥市', + value: 511681, + }, + ], + label: '广安市', + value: 511600, + }, + { + children: [ + { + children: [], + label: '通川区', + value: 511702, + }, + { + children: [], + label: '达川区', + value: 511703, + }, + { + children: [], + label: '宣汉县', + value: 511722, + }, + { + children: [], + label: '开江县', + value: 511723, + }, + { + children: [], + label: '大竹县', + value: 511724, + }, + { + children: [], + label: '渠县', + value: 511725, + }, + { + children: [], + label: '万源市', + value: 511781, + }, + ], + label: '达州市', + value: 511700, + }, + { + children: [ + { + children: [], + label: '雨城区', + value: 511802, + }, + { + children: [], + label: '名山区', + value: 511803, + }, + { + children: [], + label: '荥经县', + value: 511822, + }, + { + children: [], + label: '汉源县', + value: 511823, + }, + { + children: [], + label: '石棉县', + value: 511824, + }, + { + children: [], + label: '天全县', + value: 511825, + }, + { + children: [], + label: '芦山县', + value: 511826, + }, + { + children: [], + label: '宝兴县', + value: 511827, + }, + ], + label: '雅安市', + value: 511800, + }, + { + children: [ + { + children: [], + label: '巴州区', + value: 511902, + }, + { + children: [], + label: '恩阳区', + value: 511903, + }, + { + children: [], + label: '通江县', + value: 511921, + }, + { + children: [], + label: '南江县', + value: 511922, + }, + { + children: [], + label: '平昌县', + value: 511923, + }, + ], + label: '巴中市', + value: 511900, + }, + { + children: [ + { + children: [], + label: '雁江区', + value: 512002, + }, + { + children: [], + label: '安岳县', + value: 512021, + }, + { + children: [], + label: '乐至县', + value: 512022, + }, + ], + label: '资阳市', + value: 512000, + }, + { + children: [ + { + children: [], + label: '马尔康市', + value: 513201, + }, + { + children: [], + label: '汶川县', + value: 513221, + }, + { + children: [], + label: '理县', + value: 513222, + }, + { + children: [], + label: '茂县', + value: 513223, + }, + { + children: [], + label: '松潘县', + value: 513224, + }, + { + children: [], + label: '九寨沟县', + value: 513225, + }, + { + children: [], + label: '金川县', + value: 513226, + }, + { + children: [], + label: '小金县', + value: 513227, + }, + { + children: [], + label: '黑水县', + value: 513228, + }, + { + children: [], + label: '壤塘县', + value: 513230, + }, + { + children: [], + label: '阿坝县', + value: 513231, + }, + { + children: [], + label: '若尔盖县', + value: 513232, + }, + { + children: [], + label: '红原县', + value: 513233, + }, + ], + label: '阿坝藏族羌族自治州', + value: 513200, + }, + { + children: [ + { + children: [], + label: '康定市', + value: 513301, + }, + { + children: [], + label: '泸定县', + value: 513322, + }, + { + children: [], + label: '丹巴县', + value: 513323, + }, + { + children: [], + label: '九龙县', + value: 513324, + }, + { + children: [], + label: '雅江县', + value: 513325, + }, + { + children: [], + label: '道孚县', + value: 513326, + }, + { + children: [], + label: '炉霍县', + value: 513327, + }, + { + children: [], + label: '甘孜县', + value: 513328, + }, + { + children: [], + label: '新龙县', + value: 513329, + }, + { + children: [], + label: '德格县', + value: 513330, + }, + { + children: [], + label: '白玉县', + value: 513331, + }, + { + children: [], + label: '石渠县', + value: 513332, + }, + { + children: [], + label: '色达县', + value: 513333, + }, + { + children: [], + label: '理塘县', + value: 513334, + }, + { + children: [], + label: '巴塘县', + value: 513335, + }, + { + children: [], + label: '乡城县', + value: 513336, + }, + { + children: [], + label: '稻城县', + value: 513337, + }, + { + children: [], + label: '得荣县', + value: 513338, + }, + ], + label: '甘孜藏族自治州', + value: 513300, + }, + { + children: [ + { + children: [], + label: '西昌市', + value: 513401, + }, + { + children: [], + label: '木里藏族自治县', + value: 513422, + }, + { + children: [], + label: '盐源县', + value: 513423, + }, + { + children: [], + label: '德昌县', + value: 513424, + }, + { + children: [], + label: '会理县', + value: 513425, + }, + { + children: [], + label: '会东县', + value: 513426, + }, + { + children: [], + label: '宁南县', + value: 513427, + }, + { + children: [], + label: '普格县', + value: 513428, + }, + { + children: [], + label: '布拖县', + value: 513429, + }, + { + children: [], + label: '金阳县', + value: 513430, + }, + { + children: [], + label: '昭觉县', + value: 513431, + }, + { + children: [], + label: '喜德县', + value: 513432, + }, + { + children: [], + label: '冕宁县', + value: 513433, + }, + { + children: [], + label: '越西县', + value: 513434, + }, + { + children: [], + label: '甘洛县', + value: 513435, + }, + { + children: [], + label: '美姑县', + value: 513436, + }, + { + children: [], + label: '雷波县', + value: 513437, + }, + ], + label: '凉山彝族自治州', + value: 513400, + }, + ], + label: '四川省', + value: 510000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '南明区', + value: 520102, + }, + { + children: [], + label: '云岩区', + value: 520103, + }, + { + children: [], + label: '花溪区', + value: 520111, + }, + { + children: [], + label: '乌当区', + value: 520112, + }, + { + children: [], + label: '白云区', + value: 520113, + }, + { + children: [], + label: '观山湖区', + value: 520115, + }, + { + children: [], + label: '开阳县', + value: 520121, + }, + { + children: [], + label: '息烽县', + value: 520122, + }, + { + children: [], + label: '修文县', + value: 520123, + }, + { + children: [], + label: '清镇市', + value: 520181, + }, + ], + label: '贵阳市', + value: 520100, + }, + { + children: [ + { + children: [], + label: '钟山区', + value: 520201, + }, + { + children: [], + label: '六枝特区', + value: 520203, + }, + { + children: [], + label: '水城县', + value: 520221, + }, + { + children: [], + label: '盘州市', + value: 520281, + }, + ], + label: '六盘水市', + value: 520200, + }, + { + children: [ + { + children: [], + label: '红花岗区', + value: 520302, + }, + { + children: [], + label: '汇川区', + value: 520303, + }, + { + children: [], + label: '播州区', + value: 520304, + }, + { + children: [], + label: '桐梓县', + value: 520322, + }, + { + children: [], + label: '绥阳县', + value: 520323, + }, + { + children: [], + label: '正安县', + value: 520324, + }, + { + children: [], + label: '道真仡佬族苗族自治县', + value: 520325, + }, + { + children: [], + label: '务川仡佬族苗族自治县', + value: 520326, + }, + { + children: [], + label: '凤冈县', + value: 520327, + }, + { + children: [], + label: '湄潭县', + value: 520328, + }, + { + children: [], + label: '余庆县', + value: 520329, + }, + { + children: [], + label: '习水县', + value: 520330, + }, + { + children: [], + label: '赤水市', + value: 520381, + }, + { + children: [], + label: '仁怀市', + value: 520382, + }, + ], + label: '遵义市', + value: 520300, + }, + { + children: [ + { + children: [], + label: '西秀区', + value: 520402, + }, + { + children: [], + label: '平坝区', + value: 520403, + }, + { + children: [], + label: '普定县', + value: 520422, + }, + { + children: [], + label: '镇宁布依族苗族自治县', + value: 520423, + }, + { + children: [], + label: '关岭布依族苗族自治县', + value: 520424, + }, + { + children: [], + label: '紫云苗族布依族自治县', + value: 520425, + }, + ], + label: '安顺市', + value: 520400, + }, + { + children: [ + { + children: [], + label: '七星关区', + value: 520502, + }, + { + children: [], + label: '大方县', + value: 520521, + }, + { + children: [], + label: '黔西县', + value: 520522, + }, + { + children: [], + label: '金沙县', + value: 520523, + }, + { + children: [], + label: '织金县', + value: 520524, + }, + { + children: [], + label: '纳雍县', + value: 520525, + }, + { + children: [], + label: '威宁彝族回族苗族自治县', + value: 520526, + }, + { + children: [], + label: '赫章县', + value: 520527, + }, + ], + label: '毕节市', + value: 520500, + }, + { + children: [ + { + children: [], + label: '碧江区', + value: 520602, + }, + { + children: [], + label: '万山区', + value: 520603, + }, + { + children: [], + label: '江口县', + value: 520621, + }, + { + children: [], + label: '玉屏侗族自治县', + value: 520622, + }, + { + children: [], + label: '石阡县', + value: 520623, + }, + { + children: [], + label: '思南县', + value: 520624, + }, + { + children: [], + label: '印江土家族苗族自治县', + value: 520625, + }, + { + children: [], + label: '德江县', + value: 520626, + }, + { + children: [], + label: '沿河土家族自治县', + value: 520627, + }, + { + children: [], + label: '松桃苗族自治县', + value: 520628, + }, + ], + label: '铜仁市', + value: 520600, + }, + { + children: [ + { + children: [], + label: '兴义市', + value: 522301, + }, + { + children: [], + label: '兴仁市', + value: 522302, + }, + { + children: [], + label: '普安县', + value: 522323, + }, + { + children: [], + label: '晴隆县', + value: 522324, + }, + { + children: [], + label: '贞丰县', + value: 522325, + }, + { + children: [], + label: '望谟县', + value: 522326, + }, + { + children: [], + label: '册亨县', + value: 522327, + }, + { + children: [], + label: '安龙县', + value: 522328, + }, + ], + label: '黔西南布依族苗族自治州', + value: 522300, + }, + { + children: [ + { + children: [], + label: '凯里市', + value: 522601, + }, + { + children: [], + label: '黄平县', + value: 522622, + }, + { + children: [], + label: '施秉县', + value: 522623, + }, + { + children: [], + label: '三穗县', + value: 522624, + }, + { + children: [], + label: '镇远县', + value: 522625, + }, + { + children: [], + label: '岑巩县', + value: 522626, + }, + { + children: [], + label: '天柱县', + value: 522627, + }, + { + children: [], + label: '锦屏县', + value: 522628, + }, + { + children: [], + label: '剑河县', + value: 522629, + }, + { + children: [], + label: '台江县', + value: 522630, + }, + { + children: [], + label: '黎平县', + value: 522631, + }, + { + children: [], + label: '榕江县', + value: 522632, + }, + { + children: [], + label: '从江县', + value: 522633, + }, + { + children: [], + label: '雷山县', + value: 522634, + }, + { + children: [], + label: '麻江县', + value: 522635, + }, + { + children: [], + label: '丹寨县', + value: 522636, + }, + ], + label: '黔东南苗族侗族自治州', + value: 522600, + }, + { + children: [ + { + children: [], + label: '都匀市', + value: 522701, + }, + { + children: [], + label: '福泉市', + value: 522702, + }, + { + children: [], + label: '荔波县', + value: 522722, + }, + { + children: [], + label: '贵定县', + value: 522723, + }, + { + children: [], + label: '瓮安县', + value: 522725, + }, + { + children: [], + label: '独山县', + value: 522726, + }, + { + children: [], + label: '平塘县', + value: 522727, + }, + { + children: [], + label: '罗甸县', + value: 522728, + }, + { + children: [], + label: '长顺县', + value: 522729, + }, + { + children: [], + label: '龙里县', + value: 522730, + }, + { + children: [], + label: '惠水县', + value: 522731, + }, + { + children: [], + label: '三都水族自治县', + value: 522732, + }, + ], + label: '黔南布依族苗族自治州', + value: 522700, + }, + ], + label: '贵州省', + value: 520000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '五华区', + value: 530102, + }, + { + children: [], + label: '盘龙区', + value: 530103, + }, + { + children: [], + label: '官渡区', + value: 530111, + }, + { + children: [], + label: '西山区', + value: 530112, + }, + { + children: [], + label: '东川区', + value: 530113, + }, + { + children: [], + label: '呈贡区', + value: 530114, + }, + { + children: [], + label: '晋宁区', + value: 530115, + }, + { + children: [], + label: '富民县', + value: 530124, + }, + { + children: [], + label: '宜良县', + value: 530125, + }, + { + children: [], + label: '石林彝族自治县', + value: 530126, + }, + { + children: [], + label: '嵩明县', + value: 530127, + }, + { + children: [], + label: '禄劝彝族苗族自治县', + value: 530128, + }, + { + children: [], + label: '寻甸回族彝族自治县', + value: 530129, + }, + { + children: [], + label: '安宁市', + value: 530181, + }, + ], + label: '昆明市', + value: 530100, + }, + { + children: [ + { + children: [], + label: '麒麟区', + value: 530302, + }, + { + children: [], + label: '沾益区', + value: 530303, + }, + { + children: [], + label: '马龙区', + value: 530304, + }, + { + children: [], + label: '陆良县', + value: 530322, + }, + { + children: [], + label: '师宗县', + value: 530323, + }, + { + children: [], + label: '罗平县', + value: 530324, + }, + { + children: [], + label: '富源县', + value: 530325, + }, + { + children: [], + label: '会泽县', + value: 530326, + }, + { + children: [], + label: '宣威市', + value: 530381, + }, + ], + label: '曲靖市', + value: 530300, + }, + { + children: [ + { + children: [], + label: '红塔区', + value: 530402, + }, + { + children: [], + label: '江川区', + value: 530403, + }, + { + children: [], + label: '澄江县', + value: 530422, + }, + { + children: [], + label: '通海县', + value: 530423, + }, + { + children: [], + label: '华宁县', + value: 530424, + }, + { + children: [], + label: '易门县', + value: 530425, + }, + { + children: [], + label: '峨山彝族自治县', + value: 530426, + }, + { + children: [], + label: '新平彝族傣族自治县', + value: 530427, + }, + { + children: [], + label: '元江哈尼族彝族傣族自治县', + value: 530428, + }, + ], + label: '玉溪市', + value: 530400, + }, + { + children: [ + { + children: [], + label: '隆阳区', + value: 530502, + }, + { + children: [], + label: '施甸县', + value: 530521, + }, + { + children: [], + label: '龙陵县', + value: 530523, + }, + { + children: [], + label: '昌宁县', + value: 530524, + }, + { + children: [], + label: '腾冲市', + value: 530581, + }, + ], + label: '保山市', + value: 530500, + }, + { + children: [ + { + children: [], + label: '昭阳区', + value: 530602, + }, + { + children: [], + label: '鲁甸县', + value: 530621, + }, + { + children: [], + label: '巧家县', + value: 530622, + }, + { + children: [], + label: '盐津县', + value: 530623, + }, + { + children: [], + label: '大关县', + value: 530624, + }, + { + children: [], + label: '永善县', + value: 530625, + }, + { + children: [], + label: '绥江县', + value: 530626, + }, + { + children: [], + label: '镇雄县', + value: 530627, + }, + { + children: [], + label: '彝良县', + value: 530628, + }, + { + children: [], + label: '威信县', + value: 530629, + }, + { + children: [], + label: '水富市', + value: 530681, + }, + ], + label: '昭通市', + value: 530600, + }, + { + children: [ + { + children: [], + label: '古城区', + value: 530702, + }, + { + children: [], + label: '玉龙纳西族自治县', + value: 530721, + }, + { + children: [], + label: '永胜县', + value: 530722, + }, + { + children: [], + label: '华坪县', + value: 530723, + }, + { + children: [], + label: '宁蒗彝族自治县', + value: 530724, + }, + ], + label: '丽江市', + value: 530700, + }, + { + children: [ + { + children: [], + label: '思茅区', + value: 530802, + }, + { + children: [], + label: '宁洱哈尼族彝族自治县', + value: 530821, + }, + { + children: [], + label: '墨江哈尼族自治县', + value: 530822, + }, + { + children: [], + label: '景东彝族自治县', + value: 530823, + }, + { + children: [], + label: '景谷傣族彝族自治县', + value: 530824, + }, + { + children: [], + label: '镇沅彝族哈尼族拉祜族自治县', + value: 530825, + }, + { + children: [], + label: '江城哈尼族彝族自治县', + value: 530826, + }, + { + children: [], + label: '孟连傣族拉祜族佤族自治县', + value: 530827, + }, + { + children: [], + label: '澜沧拉祜族自治县', + value: 530828, + }, + { + children: [], + label: '西盟佤族自治县', + value: 530829, + }, + ], + label: '普洱市', + value: 530800, + }, + { + children: [ + { + children: [], + label: '临翔区', + value: 530902, + }, + { + children: [], + label: '凤庆县', + value: 530921, + }, + { + children: [], + label: '云县', + value: 530922, + }, + { + children: [], + label: '永德县', + value: 530923, + }, + { + children: [], + label: '镇康县', + value: 530924, + }, + { + children: [], + label: '双江拉祜族佤族布朗族傣族自治县', + value: 530925, + }, + { + children: [], + label: '耿马傣族佤族自治县', + value: 530926, + }, + { + children: [], + label: '沧源佤族自治县', + value: 530927, + }, + ], + label: '临沧市', + value: 530900, + }, + { + children: [ + { + children: [], + label: '楚雄市', + value: 532301, + }, + { + children: [], + label: '双柏县', + value: 532322, + }, + { + children: [], + label: '牟定县', + value: 532323, + }, + { + children: [], + label: '南华县', + value: 532324, + }, + { + children: [], + label: '姚安县', + value: 532325, + }, + { + children: [], + label: '大姚县', + value: 532326, + }, + { + children: [], + label: '永仁县', + value: 532327, + }, + { + children: [], + label: '元谋县', + value: 532328, + }, + { + children: [], + label: '武定县', + value: 532329, + }, + { + children: [], + label: '禄丰县', + value: 532331, + }, + ], + label: '楚雄彝族自治州', + value: 532300, + }, + { + children: [ + { + children: [], + label: '个旧市', + value: 532501, + }, + { + children: [], + label: '开远市', + value: 532502, + }, + { + children: [], + label: '蒙自市', + value: 532503, + }, + { + children: [], + label: '弥勒市', + value: 532504, + }, + { + children: [], + label: '屏边苗族自治县', + value: 532523, + }, + { + children: [], + label: '建水县', + value: 532524, + }, + { + children: [], + label: '石屏县', + value: 532525, + }, + { + children: [], + label: '泸西县', + value: 532527, + }, + { + children: [], + label: '元阳县', + value: 532528, + }, + { + children: [], + label: '红河县', + value: 532529, + }, + { + children: [], + label: '金平苗族瑶族傣族自治县', + value: 532530, + }, + { + children: [], + label: '绿春县', + value: 532531, + }, + { + children: [], + label: '河口瑶族自治县', + value: 532532, + }, + ], + label: '红河哈尼族彝族自治州', + value: 532500, + }, + { + children: [ + { + children: [], + label: '文山市', + value: 532601, + }, + { + children: [], + label: '砚山县', + value: 532622, + }, + { + children: [], + label: '西畴县', + value: 532623, + }, + { + children: [], + label: '麻栗坡县', + value: 532624, + }, + { + children: [], + label: '马关县', + value: 532625, + }, + { + children: [], + label: '丘北县', + value: 532626, + }, + { + children: [], + label: '广南县', + value: 532627, + }, + { + children: [], + label: '富宁县', + value: 532628, + }, + ], + label: '文山壮族苗族自治州', + value: 532600, + }, + { + children: [ + { + children: [], + label: '景洪市', + value: 532801, + }, + { + children: [], + label: '勐海县', + value: 532822, + }, + { + children: [], + label: '勐腊县', + value: 532823, + }, + ], + label: '西双版纳傣族自治州', + value: 532800, + }, + { + children: [ + { + children: [], + label: '大理市', + value: 532901, + }, + { + children: [], + label: '漾濞彝族自治县', + value: 532922, + }, + { + children: [], + label: '祥云县', + value: 532923, + }, + { + children: [], + label: '宾川县', + value: 532924, + }, + { + children: [], + label: '弥渡县', + value: 532925, + }, + { + children: [], + label: '南涧彝族自治县', + value: 532926, + }, + { + children: [], + label: '巍山彝族回族自治县', + value: 532927, + }, + { + children: [], + label: '永平县', + value: 532928, + }, + { + children: [], + label: '云龙县', + value: 532929, + }, + { + children: [], + label: '洱源县', + value: 532930, + }, + { + children: [], + label: '剑川县', + value: 532931, + }, + { + children: [], + label: '鹤庆县', + value: 532932, + }, + ], + label: '大理白族自治州', + value: 532900, + }, + { + children: [ + { + children: [], + label: '瑞丽市', + value: 533102, + }, + { + children: [], + label: '芒市', + value: 533103, + }, + { + children: [], + label: '梁河县', + value: 533122, + }, + { + children: [], + label: '盈江县', + value: 533123, + }, + { + children: [], + label: '陇川县', + value: 533124, + }, + ], + label: '德宏傣族景颇族自治州', + value: 533100, + }, + { + children: [ + { + children: [], + label: '泸水市', + value: 533301, + }, + { + children: [], + label: '福贡县', + value: 533323, + }, + { + children: [], + label: '贡山独龙族怒族自治县', + value: 533324, + }, + { + children: [], + label: '兰坪白族普米族自治县', + value: 533325, + }, + ], + label: '怒江傈僳族自治州', + value: 533300, + }, + { + children: [ + { + children: [], + label: '香格里拉市', + value: 533401, + }, + { + children: [], + label: '德钦县', + value: 533422, + }, + { + children: [], + label: '维西傈僳族自治县', + value: 533423, + }, + ], + label: '迪庆藏族自治州', + value: 533400, + }, + ], + label: '云南省', + value: 530000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '城关区', + value: 540102, + }, + { + children: [], + label: '堆龙德庆区', + value: 540103, + }, + { + children: [], + label: '达孜区', + value: 540104, + }, + { + children: [], + label: '林周县', + value: 540121, + }, + { + children: [], + label: '当雄县', + value: 540122, + }, + { + children: [], + label: '尼木县', + value: 540123, + }, + { + children: [], + label: '曲水县', + value: 540124, + }, + { + children: [], + label: '墨竹工卡县', + value: 540127, + }, + ], + label: '拉萨市', + value: 540100, + }, + { + children: [ + { + children: [], + label: '桑珠孜区', + value: 540202, + }, + { + children: [], + label: '南木林县', + value: 540221, + }, + { + children: [], + label: '江孜县', + value: 540222, + }, + { + children: [], + label: '定日县', + value: 540223, + }, + { + children: [], + label: '萨迦县', + value: 540224, + }, + { + children: [], + label: '拉孜县', + value: 540225, + }, + { + children: [], + label: '昂仁县', + value: 540226, + }, + { + children: [], + label: '谢通门县', + value: 540227, + }, + { + children: [], + label: '白朗县', + value: 540228, + }, + { + children: [], + label: '仁布县', + value: 540229, + }, + { + children: [], + label: '康马县', + value: 540230, + }, + { + children: [], + label: '定结县', + value: 540231, + }, + { + children: [], + label: '仲巴县', + value: 540232, + }, + { + children: [], + label: '亚东县', + value: 540233, + }, + { + children: [], + label: '吉隆县', + value: 540234, + }, + { + children: [], + label: '聂拉木县', + value: 540235, + }, + { + children: [], + label: '萨嘎县', + value: 540236, + }, + { + children: [], + label: '岗巴县', + value: 540237, + }, + ], + label: '日喀则市', + value: 540200, + }, + { + children: [ + { + children: [], + label: '卡若区', + value: 540302, + }, + { + children: [], + label: '江达县', + value: 540321, + }, + { + children: [], + label: '贡觉县', + value: 540322, + }, + { + children: [], + label: '类乌齐县', + value: 540323, + }, + { + children: [], + label: '丁青县', + value: 540324, + }, + { + children: [], + label: '察雅县', + value: 540325, + }, + { + children: [], + label: '八宿县', + value: 540326, + }, + { + children: [], + label: '左贡县', + value: 540327, + }, + { + children: [], + label: '芒康县', + value: 540328, + }, + { + children: [], + label: '洛隆县', + value: 540329, + }, + { + children: [], + label: '边坝县', + value: 540330, + }, + ], + label: '昌都市', + value: 540300, + }, + { + children: [ + { + children: [], + label: '巴宜区', + value: 540402, + }, + { + children: [], + label: '工布江达县', + value: 540421, + }, + { + children: [], + label: '米林县', + value: 540422, + }, + { + children: [], + label: '墨脱县', + value: 540423, + }, + { + children: [], + label: '波密县', + value: 540424, + }, + { + children: [], + label: '察隅县', + value: 540425, + }, + { + children: [], + label: '朗县', + value: 540426, + }, + ], + label: '林芝市', + value: 540400, + }, + { + children: [ + { + children: [], + label: '乃东区', + value: 540502, + }, + { + children: [], + label: '扎囊县', + value: 540521, + }, + { + children: [], + label: '贡嘎县', + value: 540522, + }, + { + children: [], + label: '桑日县', + value: 540523, + }, + { + children: [], + label: '琼结县', + value: 540524, + }, + { + children: [], + label: '曲松县', + value: 540525, + }, + { + children: [], + label: '措美县', + value: 540526, + }, + { + children: [], + label: '洛扎县', + value: 540527, + }, + { + children: [], + label: '加查县', + value: 540528, + }, + { + children: [], + label: '隆子县', + value: 540529, + }, + { + children: [], + label: '错那县', + value: 540530, + }, + { + children: [], + label: '浪卡子县', + value: 540531, + }, + ], + label: '山南市', + value: 540500, + }, + { + children: [ + { + children: [], + label: '色尼区', + value: 540602, + }, + { + children: [], + label: '嘉黎县', + value: 540621, + }, + { + children: [], + label: '比如县', + value: 540622, + }, + { + children: [], + label: '聂荣县', + value: 540623, + }, + { + children: [], + label: '安多县', + value: 540624, + }, + { + children: [], + label: '申扎县', + value: 540625, + }, + { + children: [], + label: '索县', + value: 540626, + }, + { + children: [], + label: '班戈县', + value: 540627, + }, + { + children: [], + label: '巴青县', + value: 540628, + }, + { + children: [], + label: '尼玛县', + value: 540629, + }, + { + children: [], + label: '双湖县', + value: 540630, + }, + ], + label: '那曲市', + value: 540600, + }, + { + children: [ + { + children: [], + label: '普兰县', + value: 542521, + }, + { + children: [], + label: '札达县', + value: 542522, + }, + { + children: [], + label: '噶尔县', + value: 542523, + }, + { + children: [], + label: '日土县', + value: 542524, + }, + { + children: [], + label: '革吉县', + value: 542525, + }, + { + children: [], + label: '改则县', + value: 542526, + }, + { + children: [], + label: '措勤县', + value: 542527, + }, + ], + label: '阿里地区', + value: 542500, + }, + ], + label: '西藏自治区', + value: 540000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '新城区', + value: 610102, + }, + { + children: [], + label: '碑林区', + value: 610103, + }, + { + children: [], + label: '莲湖区', + value: 610104, + }, + { + children: [], + label: '灞桥区', + value: 610111, + }, + { + children: [], + label: '未央区', + value: 610112, + }, + { + children: [], + label: '雁塔区', + value: 610113, + }, + { + children: [], + label: '阎良区', + value: 610114, + }, + { + children: [], + label: '临潼区', + value: 610115, + }, + { + children: [], + label: '长安区', + value: 610116, + }, + { + children: [], + label: '高陵区', + value: 610117, + }, + { + children: [], + label: '鄠邑区', + value: 610118, + }, + { + children: [], + label: '蓝田县', + value: 610122, + }, + { + children: [], + label: '周至县', + value: 610124, + }, + ], + label: '西安市', + value: 610100, + }, + { + children: [ + { + children: [], + label: '王益区', + value: 610202, + }, + { + children: [], + label: '印台区', + value: 610203, + }, + { + children: [], + label: '耀州区', + value: 610204, + }, + { + children: [], + label: '宜君县', + value: 610222, + }, + ], + label: '铜川市', + value: 610200, + }, + { + children: [ + { + children: [], + label: '渭滨区', + value: 610302, + }, + { + children: [], + label: '金台区', + value: 610303, + }, + { + children: [], + label: '陈仓区', + value: 610304, + }, + { + children: [], + label: '凤翔县', + value: 610322, + }, + { + children: [], + label: '岐山县', + value: 610323, + }, + { + children: [], + label: '扶风县', + value: 610324, + }, + { + children: [], + label: '眉县', + value: 610326, + }, + { + children: [], + label: '陇县', + value: 610327, + }, + { + children: [], + label: '千阳县', + value: 610328, + }, + { + children: [], + label: '麟游县', + value: 610329, + }, + { + children: [], + label: '凤县', + value: 610330, + }, + { + children: [], + label: '太白县', + value: 610331, + }, + ], + label: '宝鸡市', + value: 610300, + }, + { + children: [ + { + children: [], + label: '秦都区', + value: 610402, + }, + { + children: [], + label: '杨陵区', + value: 610403, + }, + { + children: [], + label: '渭城区', + value: 610404, + }, + { + children: [], + label: '三原县', + value: 610422, + }, + { + children: [], + label: '泾阳县', + value: 610423, + }, + { + children: [], + label: '乾县', + value: 610424, + }, + { + children: [], + label: '礼泉县', + value: 610425, + }, + { + children: [], + label: '永寿县', + value: 610426, + }, + { + children: [], + label: '长武县', + value: 610428, + }, + { + children: [], + label: '旬邑县', + value: 610429, + }, + { + children: [], + label: '淳化县', + value: 610430, + }, + { + children: [], + label: '武功县', + value: 610431, + }, + { + children: [], + label: '兴平市', + value: 610481, + }, + { + children: [], + label: '彬州市', + value: 610482, + }, + ], + label: '咸阳市', + value: 610400, + }, + { + children: [ + { + children: [], + label: '临渭区', + value: 610502, + }, + { + children: [], + label: '华州区', + value: 610503, + }, + { + children: [], + label: '潼关县', + value: 610522, + }, + { + children: [], + label: '大荔县', + value: 610523, + }, + { + children: [], + label: '合阳县', + value: 610524, + }, + { + children: [], + label: '澄城县', + value: 610525, + }, + { + children: [], + label: '蒲城县', + value: 610526, + }, + { + children: [], + label: '白水县', + value: 610527, + }, + { + children: [], + label: '富平县', + value: 610528, + }, + { + children: [], + label: '韩城市', + value: 610581, + }, + { + children: [], + label: '华阴市', + value: 610582, + }, + ], + label: '渭南市', + value: 610500, + }, + { + children: [ + { + children: [], + label: '宝塔区', + value: 610602, + }, + { + children: [], + label: '安塞区', + value: 610603, + }, + { + children: [], + label: '延长县', + value: 610621, + }, + { + children: [], + label: '延川县', + value: 610622, + }, + { + children: [], + label: '子长县', + value: 610623, + }, + { + children: [], + label: '志丹县', + value: 610625, + }, + { + children: [], + label: '吴起县', + value: 610626, + }, + { + children: [], + label: '甘泉县', + value: 610627, + }, + { + children: [], + label: '富县', + value: 610628, + }, + { + children: [], + label: '洛川县', + value: 610629, + }, + { + children: [], + label: '宜川县', + value: 610630, + }, + { + children: [], + label: '黄龙县', + value: 610631, + }, + { + children: [], + label: '黄陵县', + value: 610632, + }, + ], + label: '延安市', + value: 610600, + }, + { + children: [ + { + children: [], + label: '汉台区', + value: 610702, + }, + { + children: [], + label: '南郑区', + value: 610703, + }, + { + children: [], + label: '城固县', + value: 610722, + }, + { + children: [], + label: '洋县', + value: 610723, + }, + { + children: [], + label: '西乡县', + value: 610724, + }, + { + children: [], + label: '勉县', + value: 610725, + }, + { + children: [], + label: '宁强县', + value: 610726, + }, + { + children: [], + label: '略阳县', + value: 610727, + }, + { + children: [], + label: '镇巴县', + value: 610728, + }, + { + children: [], + label: '留坝县', + value: 610729, + }, + { + children: [], + label: '佛坪县', + value: 610730, + }, + ], + label: '汉中市', + value: 610700, + }, + { + children: [ + { + children: [], + label: '榆阳区', + value: 610802, + }, + { + children: [], + label: '横山区', + value: 610803, + }, + { + children: [], + label: '府谷县', + value: 610822, + }, + { + children: [], + label: '靖边县', + value: 610824, + }, + { + children: [], + label: '定边县', + value: 610825, + }, + { + children: [], + label: '绥德县', + value: 610826, + }, + { + children: [], + label: '米脂县', + value: 610827, + }, + { + children: [], + label: '佳县', + value: 610828, + }, + { + children: [], + label: '吴堡县', + value: 610829, + }, + { + children: [], + label: '清涧县', + value: 610830, + }, + { + children: [], + label: '子洲县', + value: 610831, + }, + { + children: [], + label: '神木市', + value: 610881, + }, + ], + label: '榆林市', + value: 610800, + }, + { + children: [ + { + children: [], + label: '汉滨区', + value: 610902, + }, + { + children: [], + label: '汉阴县', + value: 610921, + }, + { + children: [], + label: '石泉县', + value: 610922, + }, + { + children: [], + label: '宁陕县', + value: 610923, + }, + { + children: [], + label: '紫阳县', + value: 610924, + }, + { + children: [], + label: '岚皋县', + value: 610925, + }, + { + children: [], + label: '平利县', + value: 610926, + }, + { + children: [], + label: '镇坪县', + value: 610927, + }, + { + children: [], + label: '旬阳县', + value: 610928, + }, + { + children: [], + label: '白河县', + value: 610929, + }, + ], + label: '安康市', + value: 610900, + }, + { + children: [ + { + children: [], + label: '商州区', + value: 611002, + }, + { + children: [], + label: '洛南县', + value: 611021, + }, + { + children: [], + label: '丹凤县', + value: 611022, + }, + { + children: [], + label: '商南县', + value: 611023, + }, + { + children: [], + label: '山阳县', + value: 611024, + }, + { + children: [], + label: '镇安县', + value: 611025, + }, + { + children: [], + label: '柞水县', + value: 611026, + }, + ], + label: '商洛市', + value: 611000, + }, + ], + label: '陕西省', + value: 610000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '城关区', + value: 620102, + }, + { + children: [], + label: '七里河区', + value: 620103, + }, + { + children: [], + label: '西固区', + value: 620104, + }, + { + children: [], + label: '安宁区', + value: 620105, + }, + { + children: [], + label: '红古区', + value: 620111, + }, + { + children: [], + label: '永登县', + value: 620121, + }, + { + children: [], + label: '皋兰县', + value: 620122, + }, + { + children: [], + label: '榆中县', + value: 620123, + }, + ], + label: '兰州市', + value: 620100, + }, + { + children: [], + label: '嘉峪关市', + value: 620200, + }, + { + children: [ + { + children: [], + label: '金川区', + value: 620302, + }, + { + children: [], + label: '永昌县', + value: 620321, + }, + ], + label: '金昌市', + value: 620300, + }, + { + children: [ + { + children: [], + label: '白银区', + value: 620402, + }, + { + children: [], + label: '平川区', + value: 620403, + }, + { + children: [], + label: '靖远县', + value: 620421, + }, + { + children: [], + label: '会宁县', + value: 620422, + }, + { + children: [], + label: '景泰县', + value: 620423, + }, + ], + label: '白银市', + value: 620400, + }, + { + children: [ + { + children: [], + label: '秦州区', + value: 620502, + }, + { + children: [], + label: '麦积区', + value: 620503, + }, + { + children: [], + label: '清水县', + value: 620521, + }, + { + children: [], + label: '秦安县', + value: 620522, + }, + { + children: [], + label: '甘谷县', + value: 620523, + }, + { + children: [], + label: '武山县', + value: 620524, + }, + { + children: [], + label: '张家川回族自治县', + value: 620525, + }, + ], + label: '天水市', + value: 620500, + }, + { + children: [ + { + children: [], + label: '凉州区', + value: 620602, + }, + { + children: [], + label: '民勤县', + value: 620621, + }, + { + children: [], + label: '古浪县', + value: 620622, + }, + { + children: [], + label: '天祝藏族自治县', + value: 620623, + }, + ], + label: '武威市', + value: 620600, + }, + { + children: [ + { + children: [], + label: '甘州区', + value: 620702, + }, + { + children: [], + label: '肃南裕固族自治县', + value: 620721, + }, + { + children: [], + label: '民乐县', + value: 620722, + }, + { + children: [], + label: '临泽县', + value: 620723, + }, + { + children: [], + label: '高台县', + value: 620724, + }, + { + children: [], + label: '山丹县', + value: 620725, + }, + ], + label: '张掖市', + value: 620700, + }, + { + children: [ + { + children: [], + label: '崆峒区', + value: 620802, + }, + { + children: [], + label: '泾川县', + value: 620821, + }, + { + children: [], + label: '灵台县', + value: 620822, + }, + { + children: [], + label: '崇信县', + value: 620823, + }, + { + children: [], + label: '庄浪县', + value: 620825, + }, + { + children: [], + label: '静宁县', + value: 620826, + }, + { + children: [], + label: '华亭市', + value: 620881, + }, + ], + label: '平凉市', + value: 620800, + }, + { + children: [ + { + children: [], + label: '肃州区', + value: 620902, + }, + { + children: [], + label: '金塔县', + value: 620921, + }, + { + children: [], + label: '瓜州县', + value: 620922, + }, + { + children: [], + label: '肃北蒙古族自治县', + value: 620923, + }, + { + children: [], + label: '阿克塞哈萨克族自治县', + value: 620924, + }, + { + children: [], + label: '玉门市', + value: 620981, + }, + { + children: [], + label: '敦煌市', + value: 620982, + }, + ], + label: '酒泉市', + value: 620900, + }, + { + children: [ + { + children: [], + label: '西峰区', + value: 621002, + }, + { + children: [], + label: '庆城县', + value: 621021, + }, + { + children: [], + label: '环县', + value: 621022, + }, + { + children: [], + label: '华池县', + value: 621023, + }, + { + children: [], + label: '合水县', + value: 621024, + }, + { + children: [], + label: '正宁县', + value: 621025, + }, + { + children: [], + label: '宁县', + value: 621026, + }, + { + children: [], + label: '镇原县', + value: 621027, + }, + ], + label: '庆阳市', + value: 621000, + }, + { + children: [ + { + children: [], + label: '安定区', + value: 621102, + }, + { + children: [], + label: '通渭县', + value: 621121, + }, + { + children: [], + label: '陇西县', + value: 621122, + }, + { + children: [], + label: '渭源县', + value: 621123, + }, + { + children: [], + label: '临洮县', + value: 621124, + }, + { + children: [], + label: '漳县', + value: 621125, + }, + { + children: [], + label: '岷县', + value: 621126, + }, + ], + label: '定西市', + value: 621100, + }, + { + children: [ + { + children: [], + label: '武都区', + value: 621202, + }, + { + children: [], + label: '成县', + value: 621221, + }, + { + children: [], + label: '文县', + value: 621222, + }, + { + children: [], + label: '宕昌县', + value: 621223, + }, + { + children: [], + label: '康县', + value: 621224, + }, + { + children: [], + label: '西和县', + value: 621225, + }, + { + children: [], + label: '礼县', + value: 621226, + }, + { + children: [], + label: '徽县', + value: 621227, + }, + { + children: [], + label: '两当县', + value: 621228, + }, + ], + label: '陇南市', + value: 621200, + }, + { + children: [ + { + children: [], + label: '临夏市', + value: 622901, + }, + { + children: [], + label: '临夏县', + value: 622921, + }, + { + children: [], + label: '康乐县', + value: 622922, + }, + { + children: [], + label: '永靖县', + value: 622923, + }, + { + children: [], + label: '广河县', + value: 622924, + }, + { + children: [], + label: '和政县', + value: 622925, + }, + { + children: [], + label: '东乡族自治县', + value: 622926, + }, + { + children: [], + label: '积石山保安族东乡族撒拉族自治县', + value: 622927, + }, + ], + label: '临夏回族自治州', + value: 622900, + }, + { + children: [ + { + children: [], + label: '合作市', + value: 623001, + }, + { + children: [], + label: '临潭县', + value: 623021, + }, + { + children: [], + label: '卓尼县', + value: 623022, + }, + { + children: [], + label: '舟曲县', + value: 623023, + }, + { + children: [], + label: '迭部县', + value: 623024, + }, + { + children: [], + label: '玛曲县', + value: 623025, + }, + { + children: [], + label: '碌曲县', + value: 623026, + }, + { + children: [], + label: '夏河县', + value: 623027, + }, + ], + label: '甘南藏族自治州', + value: 623000, + }, + ], + label: '甘肃省', + value: 620000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '城东区', + value: 630102, + }, + { + children: [], + label: '城中区', + value: 630103, + }, + { + children: [], + label: '城西区', + value: 630104, + }, + { + children: [], + label: '城北区', + value: 630105, + }, + { + children: [], + label: '大通回族土族自治县', + value: 630121, + }, + { + children: [], + label: '湟中县', + value: 630122, + }, + { + children: [], + label: '湟源县', + value: 630123, + }, + ], + label: '西宁市', + value: 630100, + }, + { + children: [ + { + children: [], + label: '乐都区', + value: 630202, + }, + { + children: [], + label: '平安区', + value: 630203, + }, + { + children: [], + label: '民和回族土族自治县', + value: 630222, + }, + { + children: [], + label: '互助土族自治县', + value: 630223, + }, + { + children: [], + label: '化隆回族自治县', + value: 630224, + }, + { + children: [], + label: '循化撒拉族自治县', + value: 630225, + }, + ], + label: '海东市', + value: 630200, + }, + { + children: [ + { + children: [], + label: '门源回族自治县', + value: 632221, + }, + { + children: [], + label: '祁连县', + value: 632222, + }, + { + children: [], + label: '海晏县', + value: 632223, + }, + { + children: [], + label: '刚察县', + value: 632224, + }, + ], + label: '海北藏族自治州', + value: 632200, + }, + { + children: [ + { + children: [], + label: '同仁县', + value: 632321, + }, + { + children: [], + label: '尖扎县', + value: 632322, + }, + { + children: [], + label: '泽库县', + value: 632323, + }, + { + children: [], + label: '河南蒙古族自治县', + value: 632324, + }, + ], + label: '黄南藏族自治州', + value: 632300, + }, + { + children: [ + { + children: [], + label: '共和县', + value: 632521, + }, + { + children: [], + label: '同德县', + value: 632522, + }, + { + children: [], + label: '贵德县', + value: 632523, + }, + { + children: [], + label: '兴海县', + value: 632524, + }, + { + children: [], + label: '贵南县', + value: 632525, + }, + ], + label: '海南藏族自治州', + value: 632500, + }, + { + children: [ + { + children: [], + label: '玛沁县', + value: 632621, + }, + { + children: [], + label: '班玛县', + value: 632622, + }, + { + children: [], + label: '甘德县', + value: 632623, + }, + { + children: [], + label: '达日县', + value: 632624, + }, + { + children: [], + label: '久治县', + value: 632625, + }, + { + children: [], + label: '玛多县', + value: 632626, + }, + ], + label: '果洛藏族自治州', + value: 632600, + }, + { + children: [ + { + children: [], + label: '玉树市', + value: 632701, + }, + { + children: [], + label: '杂多县', + value: 632722, + }, + { + children: [], + label: '称多县', + value: 632723, + }, + { + children: [], + label: '治多县', + value: 632724, + }, + { + children: [], + label: '囊谦县', + value: 632725, + }, + { + children: [], + label: '曲麻莱县', + value: 632726, + }, + ], + label: '玉树藏族自治州', + value: 632700, + }, + { + children: [ + { + children: [], + label: '格尔木市', + value: 632801, + }, + { + children: [], + label: '德令哈市', + value: 632802, + }, + { + children: [], + label: '茫崖市', + value: 632803, + }, + { + children: [], + label: '乌兰县', + value: 632821, + }, + { + children: [], + label: '都兰县', + value: 632822, + }, + { + children: [], + label: '天峻县', + value: 632823, + }, + { + children: [], + label: '海西蒙古族藏族自治州直辖', + value: 632824, + }, + ], + label: '海西蒙古族藏族自治州', + value: 632800, + }, + ], + label: '青海省', + value: 630000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '兴庆区', + value: 640104, + }, + { + children: [], + label: '西夏区', + value: 640105, + }, + { + children: [], + label: '金凤区', + value: 640106, + }, + { + children: [], + label: '永宁县', + value: 640121, + }, + { + children: [], + label: '贺兰县', + value: 640122, + }, + { + children: [], + label: '灵武市', + value: 640181, + }, + ], + label: '银川市', + value: 640100, + }, + { + children: [ + { + children: [], + label: '大武口区', + value: 640202, + }, + { + children: [], + label: '惠农区', + value: 640205, + }, + { + children: [], + label: '平罗县', + value: 640221, + }, + ], + label: '石嘴山市', + value: 640200, + }, + { + children: [ + { + children: [], + label: '利通区', + value: 640302, + }, + { + children: [], + label: '红寺堡区', + value: 640303, + }, + { + children: [], + label: '盐池县', + value: 640323, + }, + { + children: [], + label: '同心县', + value: 640324, + }, + { + children: [], + label: '青铜峡市', + value: 640381, + }, + ], + label: '吴忠市', + value: 640300, + }, + { + children: [ + { + children: [], + label: '原州区', + value: 640402, + }, + { + children: [], + label: '西吉县', + value: 640422, + }, + { + children: [], + label: '隆德县', + value: 640423, + }, + { + children: [], + label: '泾源县', + value: 640424, + }, + { + children: [], + label: '彭阳县', + value: 640425, + }, + ], + label: '固原市', + value: 640400, + }, + { + children: [ + { + children: [], + label: '沙坡头区', + value: 640502, + }, + { + children: [], + label: '中宁县', + value: 640521, + }, + { + children: [], + label: '海原县', + value: 640522, + }, + ], + label: '中卫市', + value: 640500, + }, + ], + label: '宁夏回族自治区', + value: 640000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '天山区', + value: 650102, + }, + { + children: [], + label: '沙依巴克区', + value: 650103, + }, + { + children: [], + label: '新市区', + value: 650104, + }, + { + children: [], + label: '水磨沟区', + value: 650105, + }, + { + children: [], + label: '头屯河区', + value: 650106, + }, + { + children: [], + label: '达坂城区', + value: 650107, + }, + { + children: [], + label: '米东区', + value: 650109, + }, + { + children: [], + label: '乌鲁木齐县', + value: 650121, + }, + ], + label: '乌鲁木齐市', + value: 650100, + }, + { + children: [ + { + children: [], + label: '独山子区', + value: 650202, + }, + { + children: [], + label: '克拉玛依区', + value: 650203, + }, + { + children: [], + label: '白碱滩区', + value: 650204, + }, + { + children: [], + label: '乌尔禾区', + value: 650205, + }, + ], + label: '克拉玛依市', + value: 650200, + }, + { + children: [ + { + children: [], + label: '高昌区', + value: 650402, + }, + { + children: [], + label: '鄯善县', + value: 650421, + }, + { + children: [], + label: '托克逊县', + value: 650422, + }, + ], + label: '吐鲁番市', + value: 650400, + }, + { + children: [ + { + children: [], + label: '伊州区', + value: 650502, + }, + { + children: [], + label: '巴里坤哈萨克自治县', + value: 650521, + }, + { + children: [], + label: '伊吾县', + value: 650522, + }, + ], + label: '哈密市', + value: 650500, + }, + { + children: [ + { + children: [], + label: '昌吉市', + value: 652301, + }, + { + children: [], + label: '阜康市', + value: 652302, + }, + { + children: [], + label: '呼图壁县', + value: 652323, + }, + { + children: [], + label: '玛纳斯县', + value: 652324, + }, + { + children: [], + label: '奇台县', + value: 652325, + }, + { + children: [], + label: '吉木萨尔县', + value: 652327, + }, + { + children: [], + label: '木垒哈萨克自治县', + value: 652328, + }, + ], + label: '昌吉回族自治州', + value: 652300, + }, + { + children: [ + { + children: [], + label: '博乐市', + value: 652701, + }, + { + children: [], + label: '阿拉山口市', + value: 652702, + }, + { + children: [], + label: '精河县', + value: 652722, + }, + { + children: [], + label: '温泉县', + value: 652723, + }, + ], + label: '博尔塔拉蒙古自治州', + value: 652700, + }, + { + children: [ + { + children: [], + label: '库尔勒市', + value: 652801, + }, + { + children: [], + label: '轮台县', + value: 652822, + }, + { + children: [], + label: '尉犁县', + value: 652823, + }, + { + children: [], + label: '若羌县', + value: 652824, + }, + { + children: [], + label: '且末县', + value: 652825, + }, + { + children: [], + label: '焉耆回族自治县', + value: 652826, + }, + { + children: [], + label: '和静县', + value: 652827, + }, + { + children: [], + label: '和硕县', + value: 652828, + }, + { + children: [], + label: '博湖县', + value: 652829, + }, + ], + label: '巴音郭楞蒙古自治州', + value: 652800, + }, + { + children: [ + { + children: [], + label: '阿克苏市', + value: 652901, + }, + { + children: [], + label: '温宿县', + value: 652922, + }, + { + children: [], + label: '库车县', + value: 652923, + }, + { + children: [], + label: '沙雅县', + value: 652924, + }, + { + children: [], + label: '新和县', + value: 652925, + }, + { + children: [], + label: '拜城县', + value: 652926, + }, + { + children: [], + label: '乌什县', + value: 652927, + }, + { + children: [], + label: '阿瓦提县', + value: 652928, + }, + { + children: [], + label: '柯坪县', + value: 652929, + }, + ], + label: '阿克苏地区', + value: 652900, + }, + { + children: [ + { + children: [], + label: '阿图什市', + value: 653001, + }, + { + children: [], + label: '阿克陶县', + value: 653022, + }, + { + children: [], + label: '阿合奇县', + value: 653023, + }, + { + children: [], + label: '乌恰县', + value: 653024, + }, + ], + label: '克孜勒苏柯尔克孜自治州', + value: 653000, + }, + { + children: [ + { + children: [], + label: '喀什市', + value: 653101, + }, + { + children: [], + label: '疏附县', + value: 653121, + }, + { + children: [], + label: '疏勒县', + value: 653122, + }, + { + children: [], + label: '英吉沙县', + value: 653123, + }, + { + children: [], + label: '泽普县', + value: 653124, + }, + { + children: [], + label: '莎车县', + value: 653125, + }, + { + children: [], + label: '叶城县', + value: 653126, + }, + { + children: [], + label: '麦盖提县', + value: 653127, + }, + { + children: [], + label: '岳普湖县', + value: 653128, + }, + { + children: [], + label: '伽师县', + value: 653129, + }, + { + children: [], + label: '巴楚县', + value: 653130, + }, + { + children: [], + label: '塔什库尔干塔吉克自治县', + value: 653131, + }, + ], + label: '喀什地区', + value: 653100, + }, + { + children: [ + { + children: [], + label: '和田市', + value: 653201, + }, + { + children: [], + label: '和田县', + value: 653221, + }, + { + children: [], + label: '墨玉县', + value: 653222, + }, + { + children: [], + label: '皮山县', + value: 653223, + }, + { + children: [], + label: '洛浦县', + value: 653224, + }, + { + children: [], + label: '策勒县', + value: 653225, + }, + { + children: [], + label: '于田县', + value: 653226, + }, + { + children: [], + label: '民丰县', + value: 653227, + }, + ], + label: '和田地区', + value: 653200, + }, + { + children: [ + { + children: [], + label: '伊宁市', + value: 654002, + }, + { + children: [], + label: '奎屯市', + value: 654003, + }, + { + children: [], + label: '霍尔果斯市', + value: 654004, + }, + { + children: [], + label: '伊宁县', + value: 654021, + }, + { + children: [], + label: '察布查尔锡伯自治县', + value: 654022, + }, + { + children: [], + label: '霍城县', + value: 654023, + }, + { + children: [], + label: '巩留县', + value: 654024, + }, + { + children: [], + label: '新源县', + value: 654025, + }, + { + children: [], + label: '昭苏县', + value: 654026, + }, + { + children: [], + label: '特克斯县', + value: 654027, + }, + { + children: [], + label: '尼勒克县', + value: 654028, + }, + ], + label: '伊犁哈萨克自治州', + value: 654000, + }, + { + children: [ + { + children: [], + label: '塔城市', + value: 654201, + }, + { + children: [], + label: '乌苏市', + value: 654202, + }, + { + children: [], + label: '额敏县', + value: 654221, + }, + { + children: [], + label: '沙湾县', + value: 654223, + }, + { + children: [], + label: '托里县', + value: 654224, + }, + { + children: [], + label: '裕民县', + value: 654225, + }, + { + children: [], + label: '和布克赛尔蒙古自治县', + value: 654226, + }, + ], + label: '塔城地区', + value: 654200, + }, + { + children: [ + { + children: [], + label: '阿勒泰市', + value: 654301, + }, + { + children: [], + label: '布尔津县', + value: 654321, + }, + { + children: [], + label: '富蕴县', + value: 654322, + }, + { + children: [], + label: '福海县', + value: 654323, + }, + { + children: [], + label: '哈巴河县', + value: 654324, + }, + { + children: [], + label: '青河县', + value: 654325, + }, + { + children: [], + label: '吉木乃县', + value: 654326, + }, + ], + label: '阿勒泰地区', + value: 654300, + }, + { + children: [], + label: '石河子市', + value: 659001, + }, + { + children: [], + label: '阿拉尔市', + value: 659002, + }, + { + children: [], + label: '图木舒克市', + value: 659003, + }, + { + children: [], + label: '五家渠市', + value: 659004, + }, + { + children: [], + label: '北屯市', + value: 659005, + }, + { + children: [], + label: '铁门关市', + value: 659006, + }, + { + children: [], + label: '双河市', + value: 659007, + }, + { + children: [], + label: '可克达拉市', + value: 659008, + }, + { + children: [], + label: '昆玉市', + value: 659009, + }, + ], + label: '新疆维吾尔自治区', + value: 650000, + }, + { + children: [ + { + children: [ + { + children: [], + label: '北投区', + value: 710101, + }, + { + children: [], + label: '松山区', + value: 710102, + }, + { + children: [], + label: '大同区', + value: 710103, + }, + { + children: [], + label: '文山区', + value: 710104, + }, + { + children: [], + label: '信义区', + value: 710105, + }, + { + children: [], + label: '内湖区', + value: 710106, + }, + { + children: [], + label: '中正区', + value: 710107, + }, + { + children: [], + label: '万华区', + value: 710108, + }, + { + children: [], + label: '中山区', + value: 710109, + }, + { + children: [], + label: '士林区', + value: 710110, + }, + { + children: [], + label: '南港区', + value: 710111, + }, + { + children: [], + label: '大安区', + value: 710112, + }, + ], + label: '台北市', + value: 710100, + }, + { + children: [ + { + children: [], + label: '小港区', + value: 710201, + }, + { + children: [], + label: '左营区', + value: 710202, + }, + { + children: [], + label: '大寮区', + value: 710203, + }, + { + children: [], + label: '那玛夏区', + value: 710204, + }, + { + children: [], + label: '旗津区', + value: 710205, + }, + { + children: [], + label: '弥陀区', + value: 710206, + }, + { + children: [], + label: '燕巢区', + value: 710207, + }, + { + children: [], + label: '大树区', + value: 710208, + }, + { + children: [], + label: '阿莲区', + value: 710209, + }, + { + children: [], + label: '楠梓区', + value: 710210, + }, + { + children: [], + label: '鸟松区', + value: 710211, + }, + { + children: [], + label: '苓雅区', + value: 710212, + }, + { + children: [], + label: '桥头区', + value: 710213, + }, + { + children: [], + label: '梓官区', + value: 710214, + }, + { + children: [], + label: '美浓区', + value: 710215, + }, + { + children: [], + label: '仁武区', + value: 710216, + }, + { + children: [], + label: '凤山区', + value: 710217, + }, + { + children: [], + label: '甲仙区', + value: 710218, + }, + { + children: [], + label: '茄萣区', + value: 710219, + }, + { + children: [], + label: '大社区', + value: 710220, + }, + { + children: [], + label: '前镇区', + value: 710221, + }, + { + children: [], + label: '茂林区', + value: 710222, + }, + { + children: [], + label: '湖内区', + value: 710223, + }, + { + children: [], + label: '六龟区', + value: 710224, + }, + { + children: [], + label: '林园区', + value: 710225, + }, + { + children: [], + label: '内门区', + value: 710226, + }, + { + children: [], + label: '鼓山区', + value: 710227, + }, + { + children: [], + label: '杉林区', + value: 710228, + }, + { + children: [], + label: '三民区', + value: 710229, + }, + { + children: [], + label: '前金区', + value: 710230, + }, + { + children: [], + label: '冈山区', + value: 710231, + }, + { + children: [], + label: '田寮区', + value: 710232, + }, + { + children: [], + label: '桃源区', + value: 710233, + }, + { + children: [], + label: '盐埕区', + value: 710234, + }, + { + children: [], + label: '旗山区', + value: 710235, + }, + { + children: [], + label: '永安区', + value: 710236, + }, + { + children: [], + label: '路竹区', + value: 710237, + }, + { + children: [], + label: '新兴区', + value: 710238, + }, + ], + label: '高雄市', + value: 710200, + }, + { + children: [ + { + children: [], + label: '八里区', + value: 710301, + }, + { + children: [], + label: '三峡区', + value: 710302, + }, + { + children: [], + label: '新庄区', + value: 710303, + }, + { + children: [], + label: '坪林区', + value: 710304, + }, + { + children: [], + label: '莺歌区', + value: 710305, + }, + { + children: [], + label: '汐止区', + value: 710306, + }, + { + children: [], + label: '深坑区', + value: 710307, + }, + { + children: [], + label: '芦洲区', + value: 710308, + }, + { + children: [], + label: '三芝区', + value: 710309, + }, + { + children: [], + label: '三重区', + value: 710310, + }, + { + children: [], + label: '平溪区', + value: 710311, + }, + { + children: [], + label: '中和区', + value: 710312, + }, + { + children: [], + label: '永和区', + value: 710313, + }, + { + children: [], + label: '泰山区', + value: 710314, + }, + { + children: [], + label: '土城区', + value: 710315, + }, + { + children: [], + label: '石碇区', + value: 710316, + }, + { + children: [], + label: '五股区', + value: 710317, + }, + { + children: [], + label: '林口区', + value: 710318, + }, + { + children: [], + label: '双溪区', + value: 710319, + }, + { + children: [], + label: '树林区', + value: 710320, + }, + { + children: [], + label: '板桥区', + value: 710321, + }, + { + children: [], + label: '新店区', + value: 710322, + }, + { + children: [], + label: '乌来区', + value: 710323, + }, + { + children: [], + label: '贡寮区', + value: 710324, + }, + { + children: [], + label: '金山区', + value: 710325, + }, + { + children: [], + label: '万里区', + value: 710326, + }, + { + children: [], + label: '淡水区', + value: 710327, + }, + { + children: [], + label: '瑞芳区', + value: 710328, + }, + { + children: [], + label: '石门区', + value: 710329, + }, + ], + label: '新北市', + value: 710300, + }, + { + children: [ + { + children: [], + label: '东区', + value: 710401, + }, + { + children: [], + label: '新社区', + value: 710402, + }, + { + children: [], + label: '中区', + value: 710403, + }, + { + children: [], + label: '南屯区', + value: 710404, + }, + { + children: [], + label: '神冈区', + value: 710405, + }, + { + children: [], + label: '沙鹿区', + value: 710406, + }, + { + children: [], + label: '丰原区', + value: 710407, + }, + { + children: [], + label: '大里区', + value: 710408, + }, + { + children: [], + label: '龙井区', + value: 710409, + }, + { + children: [], + label: '西区', + value: 710410, + }, + { + children: [], + label: '南区', + value: 710411, + }, + { + children: [], + label: '西屯区', + value: 710412, + }, + { + children: [], + label: '太平区', + value: 710413, + }, + { + children: [], + label: '北屯区', + value: 710414, + }, + { + children: [], + label: '大雅区', + value: 710415, + }, + { + children: [], + label: '石冈区', + value: 710416, + }, + { + children: [], + label: '北区', + value: 710417, + }, + { + children: [], + label: '大甲区', + value: 710418, + }, + { + children: [], + label: '梧栖区', + value: 710419, + }, + { + children: [], + label: '东势区', + value: 710420, + }, + { + children: [], + label: '和平区', + value: 710421, + }, + { + children: [], + label: '雾峰区', + value: 710422, + }, + { + children: [], + label: '乌日区', + value: 710423, + }, + { + children: [], + label: '后里区', + value: 710424, + }, + { + children: [], + label: '潭子区', + value: 710425, + }, + { + children: [], + label: '大肚区', + value: 710426, + }, + { + children: [], + label: '外埔区', + value: 710427, + }, + { + children: [], + label: '清水区', + value: 710428, + }, + { + children: [], + label: '大安区', + value: 710429, + }, + ], + label: '台中市', + value: 710400, + }, + { + children: [ + { + children: [], + label: '安定区', + value: 710501, + }, + { + children: [], + label: '大内区', + value: 710502, + }, + { + children: [], + label: '东山区', + value: 710503, + }, + { + children: [], + label: '下营区', + value: 710504, + }, + { + children: [], + label: '山上区', + value: 710505, + }, + { + children: [], + label: '永康区', + value: 710506, + }, + { + children: [], + label: '新营区', + value: 710507, + }, + { + children: [], + label: '白河区', + value: 710508, + }, + { + children: [], + label: '盐水区', + value: 710509, + }, + { + children: [], + label: '归仁区', + value: 710510, + }, + { + children: [], + label: '龙崎区', + value: 710511, + }, + { + children: [], + label: '关庙区', + value: 710512, + }, + { + children: [], + label: '仁德区', + value: 710513, + }, + { + children: [], + label: '学甲区', + value: 710514, + }, + { + children: [], + label: '善化区', + value: 710515, + }, + { + children: [], + label: '新市区', + value: 710516, + }, + { + children: [], + label: '佳里区', + value: 710517, + }, + { + children: [], + label: '新化区', + value: 710518, + }, + { + children: [], + label: '西港区', + value: 710519, + }, + { + children: [], + label: '麻豆区', + value: 710520, + }, + { + children: [], + label: '安南区', + value: 710521, + }, + { + children: [], + label: '后壁区', + value: 710522, + }, + { + children: [], + label: '柳营区', + value: 710523, + }, + { + children: [], + label: '玉井区', + value: 710524, + }, + { + children: [], + label: '官田区', + value: 710525, + }, + { + children: [], + label: '东区', + value: 710526, + }, + { + children: [], + label: '六甲区', + value: 710527, + }, + { + children: [], + label: '中西区', + value: 710528, + }, + { + children: [], + label: '北区', + value: 710529, + }, + { + children: [], + label: '楠西区', + value: 710530, + }, + { + children: [], + label: '南化区', + value: 710531, + }, + { + children: [], + label: '左镇区', + value: 710532, + }, + { + children: [], + label: '南区', + value: 710533, + }, + { + children: [], + label: '安平区', + value: 710534, + }, + { + children: [], + label: '北门区', + value: 710535, + }, + { + children: [], + label: '七股区', + value: 710536, + }, + { + children: [], + label: '将军区', + value: 710537, + }, + ], + label: '台南市', + value: 710500, + }, + { + children: [ + { + children: [], + label: '平镇市', + value: 710601, + }, + { + children: [], + label: '杨梅市', + value: 710602, + }, + { + children: [], + label: '八德市', + value: 710603, + }, + { + children: [], + label: '桃园区', + value: 710604, + }, + { + children: [], + label: '龟山乡', + value: 710605, + }, + { + children: [], + label: '复兴乡', + value: 710606, + }, + { + children: [], + label: '芦竹乡', + value: 710607, + }, + { + children: [], + label: '观音乡', + value: 710608, + }, + { + children: [], + label: '龙潭乡', + value: 710609, + }, + { + children: [], + label: '大溪镇', + value: 710610, + }, + { + children: [], + label: '大园乡', + value: 710611, + }, + { + children: [], + label: '新屋乡', + value: 710612, + }, + { + children: [], + label: '中坜市', + value: 710613, + }, + ], + label: '桃园市', + value: 710600, + }, + { + children: [], + label: '基隆市', + value: 719001, + }, + { + children: [], + label: '新竹市', + value: 719002, + }, + { + children: [], + label: '嘉义市', + value: 719003, + }, + { + children: [], + label: '新竹县', + value: 719004, + }, + { + children: [], + label: '宜兰县', + value: 719005, + }, + { + children: [], + label: '苗栗县', + value: 719006, + }, + { + children: [], + label: '彰化县', + value: 719007, + }, + { + children: [], + label: '云林县', + value: 719008, + }, + { + children: [], + label: '南投县', + value: 719009, + }, + { + children: [], + label: '嘉义县', + value: 719010, + }, + { + children: [], + label: '屏东县', + value: 719011, + }, + { + children: [], + label: '台东县', + value: 719012, + }, + { + children: [], + label: '花莲县', + value: 719013, + }, + { + children: [], + label: '澎湖县', + value: 719014, + }, + ], + label: '台湾省', + value: 710000, + }, + { + children: [ + { + children: [], + label: '中西区', + value: 810101, + }, + { + children: [], + label: '东区', + value: 810102, + }, + { + children: [], + label: '九龙城区', + value: 810103, + }, + { + children: [], + label: '观塘区', + value: 810104, + }, + { + children: [], + label: '南区', + value: 810105, + }, + { + children: [], + label: '深水埗区', + value: 810106, + }, + { + children: [], + label: '湾仔区', + value: 810107, + }, + { + children: [], + label: '黄大仙区', + value: 810108, + }, + { + children: [], + label: '油尖旺区', + value: 810109, + }, + { + children: [], + label: '离岛区', + value: 810110, + }, + { + children: [], + label: '葵青区', + value: 810111, + }, + { + children: [], + label: '北区', + value: 810112, + }, + { + children: [], + label: '西贡区', + value: 810113, + }, + { + children: [], + label: '沙田区', + value: 810114, + }, + { + children: [], + label: '屯门区', + value: 810115, + }, + { + children: [], + label: '大埔区', + value: 810116, + }, + { + children: [], + label: '荃湾区', + value: 810117, + }, + { + children: [], + label: '元朗区', + value: 810118, + }, + ], + label: '香港', + value: 810000, + }, + { + children: [ + { + children: [], + label: '花王堂区', + value: 820001, + }, + { + children: [], + label: '望德堂区', + value: 820002, + }, + { + children: [], + label: '风顺堂区', + value: 820003, + }, + { + children: [], + label: '圣方济各堂区', + value: 820004, + }, + { + children: [], + label: '嘉模堂区', + value: 820005, + }, + { + children: [], + label: '大堂区', + value: 820006, + }, + { + children: [], + label: '路氹填海区', + value: 820007, + }, + { + children: [], + label: '花地玛堂区', + value: 820008, + }, + { + children: [], + label: '澳门特别行政区直辖', + value: 820010, + }, + ], + label: '澳门', + value: 820000, + }, +]; diff --git a/smart-flow-web/src/components/framework/area-cascader/province-city.js b/smart-flow-web/src/components/framework/area-cascader/province-city.js new file mode 100644 index 0000000..50ba58d --- /dev/null +++ b/smart-flow-web/src/components/framework/area-cascader/province-city.js @@ -0,0 +1,1727 @@ +export const PROVINCE_CITY = [ + { + children: [ + { + value: 110100, + label: '北京', + }, + ], + value: 110000, + label: '北京市', + }, + { + children: [ + { + value: 120100, + label: '天津', + }, + ], + value: 120000, + label: '天津市', + }, + { + children: [ + { + value: 130100, + label: '石家庄', + }, + { + value: 130200, + label: '唐山', + }, + { + value: 130300, + label: '秦皇岛', + }, + { + value: 130400, + label: '邯郸', + }, + { + value: 130500, + label: '邢台', + }, + { + value: 130600, + label: '保定', + }, + { + value: 130700, + label: '张家口', + }, + { + value: 130800, + label: '承德', + }, + { + value: 130900, + label: '沧州', + }, + { + value: 131000, + label: '廊坊', + }, + { + value: 131100, + label: '衡水', + }, + ], + value: 130000, + label: '河北省', + }, + { + children: [ + { + value: 140100, + label: '太原', + }, + { + value: 140200, + label: '大同', + }, + { + value: 140300, + label: '阳泉', + }, + { + value: 140400, + label: '长治', + }, + { + value: 140500, + label: '晋城', + }, + { + value: 140600, + label: '朔州', + }, + { + value: 140700, + label: '晋中', + }, + { + value: 140800, + label: '运城', + }, + { + value: 140900, + label: '忻州', + }, + { + value: 141000, + label: '临汾', + }, + { + value: 141100, + label: '吕梁', + }, + ], + value: 140000, + label: '山西省', + }, + { + children: [ + { + value: 150100, + label: '呼和浩特', + }, + { + value: 150200, + label: '包头', + }, + { + value: 150300, + label: '乌海', + }, + { + value: 150400, + label: '赤峰', + }, + { + value: 150500, + label: '通辽', + }, + { + value: 150600, + label: '鄂尔多斯', + }, + { + value: 150700, + label: '呼伦贝尔', + }, + { + value: 150800, + label: '巴彦淖尔', + }, + { + value: 150900, + label: '乌兰察布', + }, + { + value: 152200, + label: '兴安盟', + }, + { + value: 152500, + label: '锡林郭勒盟', + }, + { + value: 152900, + label: '阿拉善盟', + }, + ], + value: 150000, + label: '内蒙古自治区', + }, + { + children: [ + { + value: 210100, + label: '沈阳', + }, + { + value: 210200, + label: '大连', + }, + { + value: 210300, + label: '鞍山', + }, + { + value: 210400, + label: '抚顺', + }, + { + value: 210500, + label: '本溪', + }, + { + value: 210600, + label: '丹东', + }, + { + value: 210700, + label: '锦州', + }, + { + value: 210800, + label: '营口', + }, + { + value: 210900, + label: '阜新', + }, + { + value: 211000, + label: '辽阳', + }, + { + value: 211100, + label: '盘锦', + }, + { + value: 211200, + label: '铁岭', + }, + { + value: 211300, + label: '朝阳', + }, + { + value: 211400, + label: '葫芦岛', + }, + ], + value: 210000, + label: '辽宁省', + }, + { + children: [ + { + value: 220100, + label: '长春', + }, + { + value: 220200, + label: '吉林', + }, + { + value: 220300, + label: '四平', + }, + { + value: 220400, + label: '辽源', + }, + { + value: 220500, + label: '通化', + }, + { + value: 220600, + label: '白山', + }, + { + value: 220700, + label: '松原', + }, + { + value: 220800, + label: '白城', + }, + { + value: 222400, + label: '延边', + }, + ], + value: 220000, + label: '吉林省', + }, + { + children: [ + { + value: 230100, + label: '哈尔滨', + }, + { + value: 230200, + label: '齐齐哈尔', + }, + { + value: 230300, + label: '鸡西', + }, + { + value: 230400, + label: '鹤岗', + }, + { + value: 230500, + label: '双鸭山', + }, + { + value: 230600, + label: '大庆', + }, + { + value: 230700, + label: '伊春', + }, + { + value: 230800, + label: '佳木斯', + }, + { + value: 230900, + label: '七台河', + }, + { + value: 231000, + label: '牡丹江', + }, + { + value: 231100, + label: '黑河', + }, + { + value: 231200, + label: '绥化', + }, + { + value: 232700, + label: '大兴安岭地区', + }, + ], + value: 230000, + label: '黑龙江省', + }, + { + children: [ + { + value: 310100, + label: '上海', + }, + ], + value: 310000, + label: '上海市', + }, + { + children: [ + { + value: 320100, + label: '南京', + }, + { + value: 320200, + label: '无锡', + }, + { + value: 320300, + label: '徐州', + }, + { + value: 320400, + label: '常州', + }, + { + value: 320500, + label: '苏州', + }, + { + value: 320600, + label: '南通', + }, + { + value: 320700, + label: '连云港', + }, + { + value: 320800, + label: '淮安', + }, + { + value: 320900, + label: '盐城', + }, + { + value: 321000, + label: '扬州', + }, + { + value: 321100, + label: '镇江', + }, + { + value: 321200, + label: '泰州', + }, + { + value: 321300, + label: '宿迁', + }, + ], + value: 320000, + label: '江苏省', + }, + { + children: [ + { + value: 330100, + label: '杭州', + }, + { + value: 330200, + label: '宁波', + }, + { + value: 330300, + label: '温州', + }, + { + value: 330400, + label: '嘉兴', + }, + { + value: 330500, + label: '湖州', + }, + { + value: 330600, + label: '绍兴', + }, + { + value: 330700, + label: '金华', + }, + { + value: 330800, + label: '衢州', + }, + { + value: 330900, + label: '舟山', + }, + { + value: 331000, + label: '台州', + }, + { + value: 331100, + label: '丽水', + }, + ], + value: 330000, + label: '浙江省', + }, + { + children: [ + { + value: 340100, + label: '合肥', + }, + { + value: 340200, + label: '芜湖', + }, + { + value: 340300, + label: '蚌埠', + }, + { + value: 340400, + label: '淮南', + }, + { + value: 340500, + label: '马鞍山', + }, + { + value: 340600, + label: '淮北', + }, + { + value: 340700, + label: '铜陵', + }, + { + value: 340800, + label: '安庆', + }, + { + value: 341000, + label: '黄山', + }, + { + value: 341100, + label: '滁州', + }, + { + value: 341200, + label: '阜阳', + }, + { + value: 341300, + label: '宿州', + }, + { + value: 341500, + label: '六安', + }, + { + value: 341600, + label: '亳州', + }, + { + value: 341700, + label: '池州', + }, + { + value: 341800, + label: '宣城', + }, + ], + value: 340000, + label: '安徽省', + }, + { + children: [ + { + value: 350100, + label: '福州', + }, + { + value: 350200, + label: '厦门', + }, + { + value: 350300, + label: '莆田', + }, + { + value: 350400, + label: '三明', + }, + { + value: 350500, + label: '泉州', + }, + { + value: 350600, + label: '漳州', + }, + { + value: 350700, + label: '南平', + }, + { + value: 350800, + label: '龙岩', + }, + { + value: 350900, + label: '宁德', + }, + ], + value: 350000, + label: '福建省', + }, + { + children: [ + { + value: 360100, + label: '南昌', + }, + { + value: 360200, + label: '景德镇', + }, + { + value: 360300, + label: '萍乡', + }, + { + value: 360400, + label: '九江', + }, + { + value: 360500, + label: '新余', + }, + { + value: 360600, + label: '鹰潭', + }, + { + value: 360700, + label: '赣州', + }, + { + value: 360800, + label: '吉安', + }, + { + value: 360900, + label: '宜春', + }, + { + value: 361000, + label: '抚州', + }, + { + value: 361100, + label: '上饶', + }, + ], + value: 360000, + label: '江西省', + }, + { + children: [ + { + value: 370100, + label: '济南', + }, + { + value: 370200, + label: '青岛', + }, + { + value: 370300, + label: '淄博', + }, + { + value: 370400, + label: '枣庄', + }, + { + value: 370500, + label: '东营', + }, + { + value: 370600, + label: '烟台', + }, + { + value: 370700, + label: '潍坊', + }, + { + value: 370800, + label: '济宁', + }, + { + value: 370900, + label: '泰安', + }, + { + value: 371000, + label: '威海', + }, + { + value: 371100, + label: '日照', + }, + { + value: 371300, + label: '临沂', + }, + { + value: 371400, + label: '德州', + }, + { + value: 371500, + label: '聊城', + }, + { + value: 371600, + label: '滨州', + }, + { + value: 371700, + label: '菏泽', + }, + { + value: 1072447, + label: '莱芜', + }, + ], + value: 370000, + label: '山东省', + }, + { + children: [ + { + value: 410100, + label: '郑州', + }, + { + value: 410200, + label: '开封', + }, + { + value: 410300, + label: '洛阳', + }, + { + value: 410400, + label: '平顶山', + }, + { + value: 410500, + label: '安阳', + }, + { + value: 410600, + label: '鹤壁', + }, + { + value: 410700, + label: '新乡', + }, + { + value: 410800, + label: '焦作', + }, + { + value: 410900, + label: '濮阳', + }, + { + value: 411000, + label: '许昌', + }, + { + value: 411100, + label: '漯河', + }, + { + value: 411200, + label: '三门峡', + }, + { + value: 411300, + label: '南阳', + }, + { + value: 411400, + label: '商丘', + }, + { + value: 411500, + label: '信阳', + }, + { + value: 411600, + label: '周口', + }, + { + value: 411700, + label: '驻马店', + }, + { + value: 419001, + label: '济源', + }, + ], + value: 410000, + label: '河南省', + }, + { + children: [ + { + value: 420100, + label: '武汉', + }, + { + value: 420200, + label: '黄石', + }, + { + value: 420300, + label: '十堰', + }, + { + value: 420500, + label: '宜昌', + }, + { + value: 420600, + label: '襄阳', + }, + { + value: 420700, + label: '鄂州', + }, + { + value: 420800, + label: '荆门', + }, + { + value: 420900, + label: '孝感', + }, + { + value: 421000, + label: '荆州', + }, + { + value: 421100, + label: '黄冈', + }, + { + value: 421200, + label: '咸宁', + }, + { + value: 421300, + label: '随州', + }, + { + value: 422800, + label: '恩施', + }, + { + value: 1072452, + label: '潜江', + }, + { + value: 1072453, + label: '仙桃', + }, + { + value: 1072457, + label: '大冶', + }, + { + value: 1072458, + label: '天门', + }, + { + value: 1072460, + label: '神农架', + }, + ], + value: 420000, + label: '湖北省', + }, + { + children: [ + { + value: 430100, + label: '长沙', + }, + { + value: 430200, + label: '株洲', + }, + { + value: 430300, + label: '湘潭', + }, + { + value: 430400, + label: '衡阳', + }, + { + value: 430500, + label: '邵阳', + }, + { + value: 430600, + label: '岳阳', + }, + { + value: 430700, + label: '常德', + }, + { + value: 430800, + label: '张家界', + }, + { + value: 430900, + label: '益阳', + }, + { + value: 431000, + label: '郴州', + }, + { + value: 431100, + label: '永州', + }, + { + value: 431200, + label: '怀化', + }, + { + value: 431300, + label: '娄底', + }, + { + value: 433100, + label: '湘西', + }, + ], + value: 430000, + label: '湖南省', + }, + { + children: [ + { + value: 440100, + label: '广州', + }, + { + value: 440200, + label: '韶关', + }, + { + value: 440300, + label: '深圳', + }, + { + value: 440400, + label: '珠海', + }, + { + value: 440500, + label: '汕头', + }, + { + value: 440600, + label: '佛山', + }, + { + value: 440700, + label: '江门', + }, + { + value: 440800, + label: '湛江', + }, + { + value: 440900, + label: '茂名', + }, + { + value: 441200, + label: '肇庆', + }, + { + value: 441300, + label: '惠州', + }, + { + value: 441400, + label: '梅州', + }, + { + value: 441500, + label: '汕尾', + }, + { + value: 441600, + label: '河源', + }, + { + value: 441700, + label: '阳江', + }, + { + value: 441800, + label: '清远', + }, + { + value: 441900, + label: '东莞', + }, + { + value: 442000, + label: '中山', + }, + { + value: 445100, + label: '潮州', + }, + { + value: 445200, + label: '揭阳', + }, + { + value: 445300, + label: '云浮', + }, + ], + value: 440000, + label: '广东省', + }, + { + children: [ + { + value: 450100, + label: '南宁', + }, + { + value: 450200, + label: '柳州', + }, + { + value: 450300, + label: '桂林', + }, + { + value: 450400, + label: '梧州', + }, + { + value: 450500, + label: '北海', + }, + { + value: 450600, + label: '防城港', + }, + { + value: 450700, + label: '钦州', + }, + { + value: 450800, + label: '贵港', + }, + { + value: 450900, + label: '玉林', + }, + { + value: 451000, + label: '百色', + }, + { + value: 451100, + label: '贺州', + }, + { + value: 451200, + label: '河池', + }, + { + value: 451300, + label: '来宾', + }, + { + value: 451400, + label: '崇左', + }, + ], + value: 450000, + label: '广西壮族自治区', + }, + { + children: [ + { + value: 460100, + label: '海口', + }, + { + value: 460200, + label: '三亚', + }, + { + value: 460300, + label: '三沙', + }, + { + value: 460400, + label: '儋州', + }, + { + value: 1072449, + label: '文昌', + }, + ], + value: 460000, + label: '海南省', + }, + { + children: [ + { + value: 500100, + label: '重庆', + }, + ], + value: 500000, + label: '重庆市', + }, + { + children: [ + { + value: 510100, + label: '成都', + }, + { + value: 510300, + label: '自贡', + }, + { + value: 510400, + label: '攀枝花', + }, + { + value: 510500, + label: '泸州', + }, + { + value: 510600, + label: '德阳', + }, + { + value: 510700, + label: '绵阳', + }, + { + value: 510800, + label: '广元', + }, + { + value: 510900, + label: '遂宁', + }, + { + value: 511000, + label: '内江', + }, + { + value: 511100, + label: '乐山', + }, + { + value: 511300, + label: '南充', + }, + { + value: 511400, + label: '眉山', + }, + { + value: 511500, + label: '宜宾', + }, + { + value: 511600, + label: '广安', + }, + { + value: 511700, + label: '达州', + }, + { + value: 511800, + label: '雅安', + }, + { + value: 511900, + label: '巴中', + }, + { + value: 512000, + label: '资阳', + }, + { + value: 513200, + label: '阿坝', + }, + { + value: 513300, + label: '甘孜', + }, + { + value: 513400, + label: '凉山', + }, + { + value: 1072456, + label: '西昌', + }, + ], + value: 510000, + label: '四川省', + }, + { + children: [ + { + value: 520100, + label: '贵阳', + }, + { + value: 520200, + label: '六盘水', + }, + { + value: 520300, + label: '遵义', + }, + { + value: 520400, + label: '安顺', + }, + { + value: 520500, + label: '毕节', + }, + { + value: 520600, + label: '铜仁', + }, + { + value: 522300, + label: '黔西南', + }, + { + value: 522600, + label: '黔东南', + }, + { + value: 522700, + label: '黔南', + }, + ], + value: 520000, + label: '贵州省', + }, + { + children: [ + { + value: 530100, + label: '昆明', + }, + { + value: 530300, + label: '曲靖', + }, + { + value: 530400, + label: '玉溪', + }, + { + value: 530500, + label: '保山', + }, + { + value: 530600, + label: '昭通', + }, + { + value: 530700, + label: '丽江', + }, + { + value: 530800, + label: '普洱', + }, + { + value: 530900, + label: '临沧', + }, + { + value: 532300, + label: '楚雄彝族自治州', + }, + { + value: 532500, + label: '红河哈尼族彝族自治州', + }, + { + value: 532600, + label: '文山壮族苗族自治州', + }, + { + value: 532800, + label: '西双版纳傣族自治州', + }, + { + value: 532900, + label: '大理', + }, + { + value: 533100, + label: '德宏傣族景颇族自治州', + }, + { + value: 533300, + label: '怒江傈僳族自治州', + }, + { + value: 533400, + label: '迪庆藏族自治州', + }, + ], + value: 530000, + label: '云南省', + }, + { + children: [ + { + value: 540100, + label: '拉萨', + }, + { + value: 540200, + label: '日喀则', + }, + { + value: 540300, + label: '昌都', + }, + { + value: 540400, + label: '林芝', + }, + { + value: 540500, + label: '山南', + }, + { + value: 540600, + label: '那曲', + }, + { + value: 542500, + label: '阿里', + }, + ], + value: 540000, + label: '西藏自治区', + }, + { + children: [ + { + value: 610100, + label: '西安', + }, + { + value: 610200, + label: '铜川', + }, + { + value: 610300, + label: '宝鸡', + }, + { + value: 610400, + label: '咸阳', + }, + { + value: 610500, + label: '渭南', + }, + { + value: 610600, + label: '延安', + }, + { + value: 610700, + label: '汉中', + }, + { + value: 610800, + label: '榆林', + }, + { + value: 610900, + label: '安康', + }, + { + value: 611000, + label: '商洛', + }, + { + value: 1072448, + label: '杨凌', + }, + ], + value: 610000, + label: '陕西省', + }, + { + children: [ + { + value: 620100, + label: '兰州', + }, + { + value: 620200, + label: '嘉峪关', + }, + { + value: 620300, + label: '金昌', + }, + { + value: 620400, + label: '白银', + }, + { + value: 620500, + label: '天水', + }, + { + value: 620600, + label: '武威', + }, + { + value: 620700, + label: '张掖', + }, + { + value: 620800, + label: '平凉', + }, + { + value: 620900, + label: '酒泉', + }, + { + value: 621000, + label: '庆阳', + }, + { + value: 621100, + label: '定西', + }, + { + value: 621200, + label: '陇南', + }, + { + value: 622900, + label: '临夏回族自治州', + }, + { + value: 623000, + label: '甘南藏族自治州', + }, + ], + value: 620000, + label: '甘肃省', + }, + { + children: [ + { + value: 630100, + label: '西宁', + }, + { + value: 630200, + label: '海东', + }, + { + value: 632200, + label: '海北', + }, + { + value: 632300, + label: '黄南', + }, + { + value: 632500, + label: '海南', + }, + { + value: 632600, + label: '果洛', + }, + { + value: 632700, + label: '玉树', + }, + { + value: 632800, + label: '海西', + }, + ], + value: 630000, + label: '青海省', + }, + { + children: [ + { + value: 640100, + label: '银川', + }, + { + value: 640200, + label: '石嘴山', + }, + { + value: 640300, + label: '吴忠', + }, + { + value: 640400, + label: '固原', + }, + { + value: 640500, + label: '中卫', + }, + ], + value: 640000, + label: '宁夏回族自治区', + }, + { + children: [ + { + value: 650100, + label: '乌鲁木齐', + }, + { + value: 650200, + label: '克拉玛依', + }, + { + value: 650400, + label: '吐鲁番', + }, + { + value: 650500, + label: '哈密', + }, + { + value: 652300, + label: '昌吉', + }, + { + value: 652700, + label: '博尔塔拉', + }, + { + value: 652800, + label: '巴音郭楞', + }, + { + value: 652900, + label: '阿克苏', + }, + { + value: 653000, + label: '克孜勒苏柯尔克孜', + }, + { + value: 653100, + label: '喀什地区', + }, + { + value: 653200, + label: '和田', + }, + { + value: 654000, + label: '伊犁', + }, + { + value: 654200, + label: '塔城', + }, + { + value: 654300, + label: '阿勒泰', + }, + { + value: 1072450, + label: '阿拉尔', + }, + { + value: 1072454, + label: '铁门关', + }, + { + value: 1072455, + label: '五家渠', + }, + { + value: 1072459, + label: '石河子', + }, + ], + value: 650000, + label: '新疆维吾尔自治区', + }, + { + children: [ + { + value: 8345963, + label: '台北', + }, + { + value: 8345964, + label: '高雄', + }, + ], + value: 710000, + label: '台湾省', + }, + { + children: [ + { + value: 810001, + label: '中西区', + }, + { + value: 810002, + label: '湾仔区', + }, + { + value: 810003, + label: '东区', + }, + { + value: 810004, + label: '南区', + }, + { + value: 810005, + label: '油尖旺区', + }, + { + value: 810006, + label: '深水埗区', + }, + { + value: 810007, + label: '九龙城区', + }, + { + value: 810008, + label: '黄大仙区', + }, + { + value: 810009, + label: '观塘区', + }, + { + value: 810010, + label: '荃湾区', + }, + { + value: 810011, + label: '屯门区', + }, + { + value: 810012, + label: '元朗区', + }, + { + value: 810013, + label: '北区', + }, + { + value: 810014, + label: '大埔区', + }, + { + value: 810015, + label: '西贡区', + }, + { + value: 810016, + label: '沙田区', + }, + { + value: 810017, + label: '葵青区', + }, + { + value: 810018, + label: '离岛区', + }, + ], + value: 810000, + label: '香港特别行政区', + }, + { + children: [ + { + value: 820001, + label: '花地玛堂区', + }, + { + value: 820002, + label: '花王堂区', + }, + { + value: 820003, + label: '望德堂区', + }, + { + value: 820004, + label: '大堂区', + }, + { + value: 820005, + label: '风顺堂区', + }, + { + value: 820006, + label: '嘉模堂区', + }, + { + value: 820007, + label: '路凼填海区', + }, + { + value: 820008, + label: '圣方济各堂区', + }, + ], + value: 820000, + label: '澳门特别行政区', + }, + { + children: [], + value: 900000, + label: '外国', + }, +]; diff --git a/smart-flow-web/src/components/framework/boolean-select/index.vue b/smart-flow-web/src/components/framework/boolean-select/index.vue new file mode 100644 index 0000000..e336bc8 --- /dev/null +++ b/smart-flow-web/src/components/framework/boolean-select/index.vue @@ -0,0 +1,80 @@ + + + + diff --git a/smart-flow-web/src/components/framework/icon-select/index.vue b/smart-flow-web/src/components/framework/icon-select/index.vue new file mode 100644 index 0000000..468335d --- /dev/null +++ b/smart-flow-web/src/components/framework/icon-select/index.vue @@ -0,0 +1,133 @@ + + + + + + diff --git a/smart-flow-web/src/components/framework/iframe/iframe-index.vue b/smart-flow-web/src/components/framework/iframe/iframe-index.vue new file mode 100644 index 0000000..f2478b1 --- /dev/null +++ b/smart-flow-web/src/components/framework/iframe/iframe-index.vue @@ -0,0 +1,18 @@ + + + diff --git a/smart-flow-web/src/components/framework/iframe/route-default-component.vue b/smart-flow-web/src/components/framework/iframe/route-default-component.vue new file mode 100644 index 0000000..7b8b46c --- /dev/null +++ b/smart-flow-web/src/components/framework/iframe/route-default-component.vue @@ -0,0 +1,3 @@ + diff --git a/smart-flow-web/src/components/framework/smart-copy-icon/index.vue b/smart-flow-web/src/components/framework/smart-copy-icon/index.vue new file mode 100644 index 0000000..5eeeaf4 --- /dev/null +++ b/smart-flow-web/src/components/framework/smart-copy-icon/index.vue @@ -0,0 +1,38 @@ + + + + diff --git a/smart-flow-web/src/components/framework/smart-enum-checkbox/index.vue b/smart-flow-web/src/components/framework/smart-enum-checkbox/index.vue new file mode 100644 index 0000000..cc2d2e3 --- /dev/null +++ b/smart-flow-web/src/components/framework/smart-enum-checkbox/index.vue @@ -0,0 +1,75 @@ + + + + diff --git a/smart-flow-web/src/components/framework/smart-enum-radio/index.vue b/smart-flow-web/src/components/framework/smart-enum-radio/index.vue new file mode 100644 index 0000000..830c2f1 --- /dev/null +++ b/smart-flow-web/src/components/framework/smart-enum-radio/index.vue @@ -0,0 +1,88 @@ + + + + diff --git a/smart-flow-web/src/components/framework/smart-enum-select/index.vue b/smart-flow-web/src/components/framework/smart-enum-select/index.vue new file mode 100644 index 0000000..df745a4 --- /dev/null +++ b/smart-flow-web/src/components/framework/smart-enum-select/index.vue @@ -0,0 +1,88 @@ + + + + diff --git a/smart-flow-web/src/components/framework/smart-loading/index.js b/smart-flow-web/src/components/framework/smart-loading/index.js new file mode 100644 index 0000000..2dd5dc3 --- /dev/null +++ b/smart-flow-web/src/components/framework/smart-loading/index.js @@ -0,0 +1,20 @@ +/* + * loading 组件 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-07-22 20:33:41 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { useSpinStore } from "/@/store/modules/system/spin"; + +export const SmartLoading = { + show: () => { + useSpinStore().show(); + }, + + hide: () => { + useSpinStore().hide(); + }, +}; diff --git a/smart-flow-web/src/components/framework/text-ellipsis/index.vue b/smart-flow-web/src/components/framework/text-ellipsis/index.vue new file mode 100644 index 0000000..cd67cbd --- /dev/null +++ b/smart-flow-web/src/components/framework/text-ellipsis/index.vue @@ -0,0 +1,77 @@ + + + + diff --git a/smart-flow-web/src/components/framework/wangeditor/index.vue b/smart-flow-web/src/components/framework/wangeditor/index.vue new file mode 100644 index 0000000..dc3c31c --- /dev/null +++ b/smart-flow-web/src/components/framework/wangeditor/index.vue @@ -0,0 +1,118 @@ + + + + + + + diff --git a/smart-flow-web/src/components/support/data-tracer/data-tracer-table.vue b/smart-flow-web/src/components/support/data-tracer/data-tracer-table.vue new file mode 100644 index 0000000..ca5ea35 --- /dev/null +++ b/smart-flow-web/src/components/support/data-tracer/data-tracer-table.vue @@ -0,0 +1,97 @@ + + + + diff --git a/smart-flow-web/src/components/support/data-tracer/data-tracer-timeline.vue b/smart-flow-web/src/components/support/data-tracer/data-tracer-timeline.vue new file mode 100644 index 0000000..ddb7e05 --- /dev/null +++ b/smart-flow-web/src/components/support/data-tracer/data-tracer-timeline.vue @@ -0,0 +1,50 @@ + + + + diff --git a/smart-flow-web/src/components/support/data-tracer/index.vue b/smart-flow-web/src/components/support/data-tracer/index.vue new file mode 100644 index 0000000..d807227 --- /dev/null +++ b/smart-flow-web/src/components/support/data-tracer/index.vue @@ -0,0 +1,180 @@ + + + diff --git a/smart-flow-web/src/components/support/dict-code-select/index.vue b/smart-flow-web/src/components/support/dict-code-select/index.vue new file mode 100644 index 0000000..10852a5 --- /dev/null +++ b/smart-flow-web/src/components/support/dict-code-select/index.vue @@ -0,0 +1,83 @@ + + + + diff --git a/smart-flow-web/src/components/support/dict-label/index.vue b/smart-flow-web/src/components/support/dict-label/index.vue new file mode 100644 index 0000000..1f5d3f0 --- /dev/null +++ b/smart-flow-web/src/components/support/dict-label/index.vue @@ -0,0 +1,16 @@ + + + diff --git a/smart-flow-web/src/components/support/dict-select/index.vue b/smart-flow-web/src/components/support/dict-select/index.vue new file mode 100644 index 0000000..49f88bf --- /dev/null +++ b/smart-flow-web/src/components/support/dict-select/index.vue @@ -0,0 +1,103 @@ + + + + diff --git a/smart-flow-web/src/components/support/file-preview-modal/index.vue b/smart-flow-web/src/components/support/file-preview-modal/index.vue new file mode 100644 index 0000000..03f46ca --- /dev/null +++ b/smart-flow-web/src/components/support/file-preview-modal/index.vue @@ -0,0 +1,83 @@ + + + + + + diff --git a/smart-flow-web/src/components/support/file-preview/index.vue b/smart-flow-web/src/components/support/file-preview/index.vue new file mode 100644 index 0000000..665708c --- /dev/null +++ b/smart-flow-web/src/components/support/file-preview/index.vue @@ -0,0 +1,79 @@ + + + diff --git a/smart-flow-web/src/components/support/file-upload/index.vue b/smart-flow-web/src/components/support/file-upload/index.vue new file mode 100644 index 0000000..a661865 --- /dev/null +++ b/smart-flow-web/src/components/support/file-upload/index.vue @@ -0,0 +1,229 @@ + + + + diff --git a/smart-flow-web/src/components/support/table-header-cell/index.vue b/smart-flow-web/src/components/support/table-header-cell/index.vue new file mode 100644 index 0000000..2714bc0 --- /dev/null +++ b/smart-flow-web/src/components/support/table-header-cell/index.vue @@ -0,0 +1,178 @@ + + + diff --git a/smart-flow-web/src/components/support/table-operator/index.vue b/smart-flow-web/src/components/support/table-operator/index.vue new file mode 100644 index 0000000..c2f6710 --- /dev/null +++ b/smart-flow-web/src/components/support/table-operator/index.vue @@ -0,0 +1,222 @@ + + + + + diff --git a/smart-flow-web/src/components/support/table-operator/smart-table-column-merge.js b/smart-flow-web/src/components/support/table-operator/smart-table-column-merge.js new file mode 100644 index 0000000..3a19736 --- /dev/null +++ b/smart-flow-web/src/components/support/table-operator/smart-table-column-merge.js @@ -0,0 +1,63 @@ +/* + * 表格列设置 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-08-26 23:45:51 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import _ from 'lodash'; + +/** + * 将原视表格列和用户表格列进行合并、排序 + * @param {*} originalTableColumnArray + * @param {*} userTableColumnArray + */ +export function mergeColumn(originalTableColumnArray, userTableColumnArray) { + let saveFlag = false; + if (!userTableColumnArray) { + return originalTableColumnArray; + } + + //第一步:将用户的列数据转为Map,以后备使用 + let userTableColumnMap = new Map(); + for (const item of userTableColumnArray) { + userTableColumnMap.set(item.columnKey, item); + } + + //第二步:以前端的table columns列为基础,将用户后端的数据填充到前端表格列里 + let fontColumnSort = 1; + let newColumns = []; + for (const fontColumn of originalTableColumnArray) { + //原始表格列默认显示 + fontColumn.columnKey = fontColumn.dataIndex; + fontColumn.showFlag = true; + fontColumn.sort = fontColumnSort; + + // 如果用户存在此列,则覆盖 sort和width、showFlag字段 + let userColumn = userTableColumnMap.get(fontColumn.columnKey); + if (userColumn) { + fontColumn.sort = userColumn.sort; + fontColumn.showFlag = userColumn.showFlag; + if (fontColumn.dragAndDropFlag) { + saveFlag = true; + delete fontColumn.dragAndDropFlag; + } else { + if (userColumn.width) { + fontColumn.width = userColumn.width; + } + } + } + newColumns.push(fontColumn); + fontColumnSort++; + } + + //第三步:前端列进行排序 + newColumns = _.sortBy(newColumns, (e) => e.sort); + return { + newColumns, + saveFlag, + }; +} diff --git a/smart-flow-web/src/components/support/table-operator/smart-table-column-modal.vue b/smart-flow-web/src/components/support/table-operator/smart-table-column-modal.vue new file mode 100644 index 0000000..6071202 --- /dev/null +++ b/smart-flow-web/src/components/support/table-operator/smart-table-column-modal.vue @@ -0,0 +1,312 @@ + + + + diff --git a/smart-flow-web/src/components/system/department-tree-select/index.vue b/smart-flow-web/src/components/system/department-tree-select/index.vue new file mode 100644 index 0000000..e9de799 --- /dev/null +++ b/smart-flow-web/src/components/system/department-tree-select/index.vue @@ -0,0 +1,58 @@ + + + diff --git a/smart-flow-web/src/components/system/employee-select/index.vue b/smart-flow-web/src/components/system/employee-select/index.vue new file mode 100644 index 0000000..c963957 --- /dev/null +++ b/smart-flow-web/src/components/system/employee-select/index.vue @@ -0,0 +1,97 @@ + + + + diff --git a/smart-flow-web/src/components/system/employee-table-select-modal/index.vue b/smart-flow-web/src/components/system/employee-table-select-modal/index.vue new file mode 100644 index 0000000..b68dfc3 --- /dev/null +++ b/smart-flow-web/src/components/system/employee-table-select-modal/index.vue @@ -0,0 +1,199 @@ + + + diff --git a/smart-flow-web/src/components/system/menu-tree-select/index.vue b/smart-flow-web/src/components/system/menu-tree-select/index.vue new file mode 100644 index 0000000..e7b1b62 --- /dev/null +++ b/smart-flow-web/src/components/system/menu-tree-select/index.vue @@ -0,0 +1,76 @@ + + + diff --git a/smart-flow-web/src/components/system/position-select/index.vue b/smart-flow-web/src/components/system/position-select/index.vue new file mode 100644 index 0000000..16be61b --- /dev/null +++ b/smart-flow-web/src/components/system/position-select/index.vue @@ -0,0 +1,79 @@ + + + + diff --git a/smart-flow-web/src/config/app-config.js b/smart-flow-web/src/config/app-config.js new file mode 100644 index 0000000..3bb3cfd --- /dev/null +++ b/smart-flow-web/src/config/app-config.js @@ -0,0 +1,49 @@ +/* + * 应用默认配置 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:07:01 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const appDefaultConfig = { + // i18n 语言选择 + language: 'zh_CN', + // 布局: side 或者 side-expand 或者 top + layout: 'side', + // 侧边菜单宽度(长标题需足够宽才能完整显示) + sideMenuWidth: 200, + //标签页位置 + pageTagLocation: 'center', + // 菜单主题 + sideMenuTheme: 'dark', + // 主题颜色索引 + colorIndex: 0, + // 顶部菜单页面宽度 + pageWidth: '99%', + // 圆角 + borderRadius: 6, + // 菜单展开模式 + flatPattern: true, + // 标签页 + pageTagFlag: true, + // 标签页样式: default、 antd、chrome + pageTagStyle: 'default', + // 面包屑 + breadCrumbFlag: true, + // 页脚 + footerFlag: true, + // 帮助文档 + helpDocFlag: true, + // 帮助文档默认展开 + helpDocExpandFlag: false, + // 水印 + watermarkFlag: true, + // 网站名称(侧栏、浏览器标题等;侧栏内自动换行完整展示) + websiteName: '铜陵市公安局经侦案件智慧管理平台', + // 主题颜色 + primaryColor: '#1677ff', + // 紧凑 + compactFlag: false, +}; diff --git a/smart-flow-web/src/constants/business/erp/category-const.js b/smart-flow-web/src/constants/business/erp/category-const.js new file mode 100644 index 0000000..e401e14 --- /dev/null +++ b/smart-flow-web/src/constants/business/erp/category-const.js @@ -0,0 +1,23 @@ +/* + * 类别 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:07:51 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const CATEGORY_TYPE_ENUM = { + GOODS: { + value: 1, + desc: '商品', + }, + DEMO: { + value: 2, + desc: '演示分类', + }, +}; + +export default { + CATEGORY_TYPE_ENUM, +}; diff --git a/smart-flow-web/src/constants/business/erp/goods-const.js b/smart-flow-web/src/constants/business/erp/goods-const.js new file mode 100644 index 0000000..599a62d --- /dev/null +++ b/smart-flow-web/src/constants/business/erp/goods-const.js @@ -0,0 +1,26 @@ +/* + * 商品 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:08:10 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const GOODS_STATUS_ENUM = { + APPOINTMENT: { + value: 1, + desc: '预约中', + }, + SELL: { + value: 2, + desc: '售卖中', + }, + SELL_OUT: { + value: 3, + desc: '售罄', + }, +}; +export default { + GOODS_STATUS_ENUM, +}; diff --git a/smart-flow-web/src/constants/business/message/message-const.js b/smart-flow-web/src/constants/business/message/message-const.js new file mode 100644 index 0000000..b71d130 --- /dev/null +++ b/smart-flow-web/src/constants/business/message/message-const.js @@ -0,0 +1,30 @@ +/* + * @Description: file content + * @Author: yandy + * @Date: 2022-07-24 21:43:43 + * @LastEditors: + * @LastEditTime: 2022-07-24 21:43:43 + */ +export const MESSAGE_TYPE_ENUM = { + MAIL: { + value: 1, + desc: '站内信' + }, + ORDER: { + value: 2, + desc: '订单' + }, + }; + + +export const MESSAGE_RECEIVE_TYPE_ENUM = { + EMPLOYEE: { + value: 1, + desc: '员工' + }, + }; + +export default { + MESSAGE_TYPE_ENUM, + MESSAGE_RECEIVE_TYPE_ENUM +}; diff --git a/smart-flow-web/src/constants/business/oa/enterprise-const.js b/smart-flow-web/src/constants/business/oa/enterprise-const.js new file mode 100644 index 0000000..b8aaccf --- /dev/null +++ b/smart-flow-web/src/constants/business/oa/enterprise-const.js @@ -0,0 +1,24 @@ +/* + * 企业 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:07:27 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +export const ENTERPRISE_TYPE_ENUM = { + NORMAL: { + value: 1, + desc: '有限企业', + }, + FOREIGN: { + value: 2, + desc: '外资企业', + }, +}; + +export default { + ENTERPRISE_TYPE_ENUM, +}; diff --git a/smart-flow-web/src/constants/business/oa/notice-const.js b/smart-flow-web/src/constants/business/oa/notice-const.js new file mode 100644 index 0000000..94ee083 --- /dev/null +++ b/smart-flow-web/src/constants/business/oa/notice-const.js @@ -0,0 +1,36 @@ +/* + * 通知 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:07:27 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +export const NOTICE_VISIBLE_RANGE_DATA_TYPE_ENUM = { + EMPLOYEE: { + value: 1, + desc: '员工', + }, + DEPARTMENT: { + value: 2, + desc: '部门', + }, +}; + +export const NOTICE_TYPE_ENUM = { + ANNOUNCEMENT: { + value: 1, + desc: '公告', + }, + NOTICE: { + value: 2, + desc: '通知', + }, +}; + +export default { + NOTICE_VISIBLE_RANGE_DATA_TYPE_ENUM, + NOTICE_TYPE_ENUM, +}; diff --git a/smart-flow-web/src/constants/common-const.js b/smart-flow-web/src/constants/common-const.js new file mode 100644 index 0000000..129a01f --- /dev/null +++ b/smart-flow-web/src/constants/common-const.js @@ -0,0 +1,72 @@ +/* + * 通用常量 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:57:29 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +export const PAGE_SIZE = 10; + +export const PAGE_SIZE_OPTIONS = ['5', '10', '15', '20', '30', '40', '50', '75', '100', '150', '200', '300', '500']; + +//登录页面名字 +export const PAGE_PATH_LOGIN = '/login'; +//首页页面名字 +export const HOME_PAGE_PATH = '/home'; + +//404页面名字 +export const PAGE_PATH_404 = '/404'; + +export const showTableTotal = function (total) { + return `共${total}条`; +}; + +export const FLAG_NUMBER_ENUM = { + TRUE: { + value: 1, + desc: '是', + }, + FALSE: { + value: 0, + desc: '否', + }, +}; + +export const GENDER_ENUM = { + UNKNOWN: { + value: 0, + desc: '未知', + }, + MAN: { + value: 1, + desc: '男', + }, + WOMAN: { + value: 2, + desc: '女', + }, +}; + +export const USER_TYPE_ENUM = { + ADMIN_EMPLOYEE: { + value: 1, + desc: '员工', + }, + +}; + +export const DATA_TYPE_ENUM = { + NORMAL: { + value: 1, + desc: '普通', + }, + ENCRYPT: { + value: 10, + desc: '加密', + }, + +}; + diff --git a/smart-flow-web/src/constants/flow/flow-const.js b/smart-flow-web/src/constants/flow/flow-const.js new file mode 100644 index 0000000..ba0eeb8 --- /dev/null +++ b/smart-flow-web/src/constants/flow/flow-const.js @@ -0,0 +1,60 @@ +export const FLOW_STATUS_ENUM = { + PENDING_SUBMIT: { + value: 0, + desc: '待提交', + }, + APPROVING: { + value: 1, + desc: '审批中', + }, + APPROVED: { + value: 2, + desc: '审批通过', + }, + AUTO_APPROVED: { + value: 3, + desc: '自动通过', + }, + TERMINATED: { + value: 4, + desc: '终止', + }, + INVALID: { + value: 5, + desc: '作废', + }, + REVOKED: { + value: 6, + desc: '撤销', + }, + RETRIEVED: { + value: 7, + desc: '取回', + }, + COMPLETED: { + value: 8, + desc: '已完成', + }, + RETURNED: { + value: 9, + desc: '已退回', + }, + EXPIRED: { + value: 10, + desc: '失效', + }, +}; +export const COOPERATE_TYPE_ENUM = { + APPROVAL: { value: 1, desc: '审批' }, + TRANSFER: { value: 2, desc: '转办' }, + DELEGATE: { value: 3, desc: '委派' }, + COUNTERSIGN: { value: 4, desc: '会签' }, + VOTE_SIGN: { value: 5, desc: '票签' }, + ADD_SIGN: { value: 6, desc: '加签' }, + REMOVE_SIGN: { value: 7, desc: '减签' }, +} + +export default { + FLOW_STATUS_ENUM, + COOPERATE_TYPE_ENUM +}; \ No newline at end of file diff --git a/smart-flow-web/src/constants/index.js b/smart-flow-web/src/constants/index.js new file mode 100644 index 0000000..6f55c45 --- /dev/null +++ b/smart-flow-web/src/constants/index.js @@ -0,0 +1,44 @@ +/* + * 所有常量入口 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:58:28 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import menu from './system/menu-const'; +import goods from './business/erp/goods-const'; +import category from './business/erp/category-const'; +import { LOGIN_DEVICE_ENUM } from './system/login-device-const'; +import { FLAG_NUMBER_ENUM, GENDER_ENUM, USER_TYPE_ENUM } from './common-const'; +import { LAYOUT_ENUM } from './layout-const'; +import file from './support/file-const'; +import notice from './business/oa/notice-const'; +import loginLog from './support/login-log-const'; +import enterprise from './business/oa/enterprise-const'; +import message from './business/message/message-const'; +import codeGeneratorConst from './support/code-generator-const'; +import changeLogConst from './support/change-log-const'; +import jobConst from './support/job-const'; +import flowConst from './flow/flow-const'; + +export default { + FLAG_NUMBER_ENUM, + LOGIN_DEVICE_ENUM, + GENDER_ENUM, + USER_TYPE_ENUM, + LAYOUT_ENUM, + ...loginLog, + ...menu, + ...goods, + ...category, + ...file, + ...notice, + ...enterprise, + ...message, + ...codeGeneratorConst, + ...changeLogConst, + ...jobConst, + ...flowConst +}; diff --git a/smart-flow-web/src/constants/layout-const.js b/smart-flow-web/src/constants/layout-const.js new file mode 100644 index 0000000..07c58ea --- /dev/null +++ b/smart-flow-web/src/constants/layout-const.js @@ -0,0 +1,42 @@ +/* + * 布局格式 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:58:41 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const LAYOUT_ENUM = { + SIDE: { + value: 'side', + desc: '传统', + }, + SIDE_EXPAND: { + value: 'side-expand', + desc: '展开', + }, + TOP: { + value: 'top', + desc: '顶部', + }, + TOP_EXPAND: { + value: 'top-expand', + desc: '分组', + }, +}; + +export const PAGE_TAG_ENUM = { + DEFAULT: { + value: 'default', + desc: '默认', + }, + ANTD: { + value: 'antd', + desc: 'Ant Design', + }, + CHROME: { + value: 'chrome', + desc: 'Chrome', + }, +}; diff --git a/smart-flow-web/src/constants/local-storage-key-const.js b/smart-flow-web/src/constants/local-storage-key-const.js new file mode 100644 index 0000000..b48a1f6 --- /dev/null +++ b/smart-flow-web/src/constants/local-storage-key-const.js @@ -0,0 +1,33 @@ +/* + * key 常量 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:58:50 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +/** + * key前缀 + */ +const KEY_PREFIX = 'smart_admin_'; +/** + * localStorageKey集合 + */ +export default { + // 用户token + USER_TOKEN: `${KEY_PREFIX}user_token`, + // 用户权限点 + USER_POINTS: `${KEY_PREFIX}user_points`, + // 用户的tag列表 + USER_TAG_NAV: `${KEY_PREFIX}user_tag_nav`, + // app config 配置信息 + APP_CONFIG: `${KEY_PREFIX}app_config`, + // 首页快捷入口 + HOME_QUICK_ENTRY: `${KEY_PREFIX}home_quick_entry`, + // 通知信息已读 + NOTICE_READ: `${KEY_PREFIX}notice_read`, + // 待办 + TO_BE_DONE: `${KEY_PREFIX}to_be_done`, +}; diff --git a/smart-flow-web/src/constants/regular-const.js b/smart-flow-web/src/constants/regular-const.js new file mode 100644 index 0000000..4c1338c --- /dev/null +++ b/smart-flow-web/src/constants/regular-const.js @@ -0,0 +1,29 @@ +/* + * 正则常量 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:59:05 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const regular = { + phone: /^(13|14|15|16|17|18|19)\d{9}$/, + qq: /^[1-9]\d{3,}$/, + linkUrl: + /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?'\\+&%$#=~_-]+))*$/, + // eslint-disable-next-line no-useless-escape + isNumber: /(^[\-1-9][1-9]*(.[1-9]+)?)$/, // 判断是否为数字,除了0 外 + isLandlineOrPhone: /^((0\d{2,3}-\d{7,8})|(1[3584]\d{9}))$/, // 验证 座机 或者手机 + account: /^[a-z0-9]{3,16}$/, // 请输入3-16位(小写字母|数字)的账号 + mobileAccount: /^[a-z0-9]{6,16}$/, // 请输入6-16位(小写字母|数字)的账号(和移动端保持一致) + accountDesc: '请输入3-16位(小写字母|数字)的账号', + pwd: /^[A-Za-z0-9._]{6,16}$/, // 请输入6-16位(大小写字母|数字|小数点|下划线)的密码 + pwdDesc: '请输入6-16位(大小写字母|数字|小数点|下划线)的密码', + delBlankSpace: /\s+/g, // 删除空格 + isPdfReg: new RegExp(/\.(pdf|PDF)/), + isElseFileReg: new RegExp(/\.(doc|docx|xls|xlsx|txt|ppt|pptx|pps|ppxs)/), + isIdentityCard: /^[1-9]\d{5}[1-9]\d{3}((0\d)|(1[0-2]))(([0|1|2]\d)|3[0-1])\d{3}([0-9]|X|x)$/, // 验证身份证号 + isChinese: /^[\u4e00-\u9fa5]+$/gi, // 验证是否汉字 + +}; diff --git a/smart-flow-web/src/constants/support/change-log-const.js b/smart-flow-web/src/constants/support/change-log-const.js new file mode 100644 index 0000000..d7c29f5 --- /dev/null +++ b/smart-flow-web/src/constants/support/change-log-const.js @@ -0,0 +1,29 @@ +/** + * 系统更新日志 枚举 + * + * @Author: 卓大 + * @Date: 2022-09-26 14:53:50 + * @Copyright 1024创新实验室 + */ + +/** + * 更新类型:[1:特大版本功能更新;2:功能更新;3:bug修复] + */ +export const CHANGE_LOG_TYPE_ENUM = { + MAJOR_UPDATE: { + value: 1, + desc: '重大更新', + }, + FUNCTION_UPDATE: { + value: 2, + desc: '功能更新', + }, + BUG_FIX: { + value: 3, + desc: 'Bug修复', + }, +}; + +export default { + CHANGE_LOG_TYPE_ENUM, +}; diff --git a/smart-flow-web/src/constants/support/code-generator-const.js b/smart-flow-web/src/constants/support/code-generator-const.js new file mode 100644 index 0000000..ddf2512 --- /dev/null +++ b/smart-flow-web/src/constants/support/code-generator-const.js @@ -0,0 +1,118 @@ +/* + * 代码生成 枚举 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:09:10 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +// 前端组件类型 +export const CODE_FRONT_COMPONENT_ENUM = { + INPUT: { + value: 'Input', + desc: '输入框', + }, + INPUT_NUMBER: { + value: 'InputNumber', + desc: '数字输入框', + }, + TEXTAREA: { + value: 'Textarea', + desc: '文本', + }, + BOOLEAN_SELECT: { + value: 'BooleanSelect', + desc: '布尔下拉框', + }, + ENUM_SELECT: { + value: 'SmartEnumSelect', + desc: '枚举下拉框', + }, + DICT_SELECT: { + value: 'DictSelect', + desc: '字典下拉', + }, + DATE: { + value: 'Date', + desc: '日期选择', + }, + DATE_TIME: { + value: 'DateTime', + desc: '时间选择', + }, + FILE_UPLOAD: { + value: 'FileUpload', + desc: '文件上传', + }, +}; + +// 新增、修改 页面类型 +export const CODE_INSERT_AND_UPDATE_PAGE_ENUM = { + MODAL: { + value: 'modal', + desc: '弹窗', + }, + DRAWER: { + value: 'drawer', + desc: '抽屉', + }, + PAGE: { + value: 'Page', + desc: '新页面', + }, +}; + +// 删除类型 +export const CODE_DELETE_ENUM = { + SINGLE: { + value: 'Single', + desc: '单个删除', + }, + BATCH: { + value: 'Batch', + desc: '批量删除', + }, + SINGLE_AND_BATCH: { + value: 'SingleAndBatch', + desc: '单个删除和批量删除', + }, +}; + +/** + * 查询类型 + */ +export const CODE_QUERY_FIELD_QUERY_TYPE_ENUM = { + LIKE: { + value: 'Like', + desc: '模糊查询', + }, + EQUAL: { + value: 'Equal', + desc: '等于查询', + }, + DATE_RANGE: { + value: 'DateRange', + desc: '日期范围', + }, + DATE: { + value: 'Date', + desc: '指定日期', + }, + ENUM: { + value: 'Enum', + desc: '枚举', + }, + DICT: { + value: 'Dict', + desc: '字典', + }, +}; + +export default { + CODE_FRONT_COMPONENT_ENUM, + CODE_INSERT_AND_UPDATE_PAGE_ENUM, + CODE_DELETE_ENUM, + CODE_QUERY_FIELD_QUERY_TYPE_ENUM +}; diff --git a/smart-flow-web/src/constants/support/data-tracer-const.js b/smart-flow-web/src/constants/support/data-tracer-const.js new file mode 100644 index 0000000..371c682 --- /dev/null +++ b/smart-flow-web/src/constants/support/data-tracer-const.js @@ -0,0 +1,29 @@ +/* + * 数据变动记录 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:09:10 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +// 业务类型 +export const DATA_TRACER_TYPE_ENUM = { + GOODS: { + value: 1, + desc: '商品', + }, + OA_NOTICE: { + value: 2, + desc: 'OA-通知公告', + }, + OA_ENTERPRISE: { + value: 3, + desc: 'OA-企业信息', + }, +}; + +export default { + DATA_TRACER_TYPE_ENUM, +}; diff --git a/smart-flow-web/src/constants/support/dict-const.js b/smart-flow-web/src/constants/support/dict-const.js new file mode 100644 index 0000000..285e665 --- /dev/null +++ b/smart-flow-web/src/constants/support/dict-const.js @@ -0,0 +1,22 @@ +/** + * 字典key 编码 常量 + * + * 该常量来自于 字典管理中的数据,写在该文件目的是为了统一引用,将来好修改 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2024-09-03 22:09:10 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +export const DICT_SPLIT = ','; + +export const DICT_CODE_ENUM = { + GOODS_PLACE: 'GOODS_PLACE', + LEAVE_TYPE: 'LEAVE_TYPE', +}; + +export default { + DICT_CODE_ENUM, +}; diff --git a/smart-flow-web/src/constants/support/file-const.js b/smart-flow-web/src/constants/support/file-const.js new file mode 100644 index 0000000..6435b96 --- /dev/null +++ b/smart-flow-web/src/constants/support/file-const.js @@ -0,0 +1,31 @@ +/* + * 文件类型 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:09:10 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +// 文件上传类型 +export const FILE_FOLDER_TYPE_ENUM = { + COMMON: { + value: 1, + desc: '通用', + }, + NOTICE: { + value: 2, + desc: '公告', + }, + HELP_DOC: { + value: 3, + desc: '帮助中心', + }, + FEEDBACK: { + value: 4, + desc: '意见反馈', + }, +}; +export default { + FILE_FOLDER_TYPE_ENUM, +}; diff --git a/smart-flow-web/src/constants/support/job-const.js b/smart-flow-web/src/constants/support/job-const.js new file mode 100644 index 0000000..6d89f8e --- /dev/null +++ b/smart-flow-web/src/constants/support/job-const.js @@ -0,0 +1,18 @@ +/** + * job 常量 + * @type {{CRON: {value: number, desc: string}, FIXED_DELAY: {value: number, desc: string}}} + */ +export const TRIGGER_TYPE_ENUM = { + CRON: { + value: 'cron', + desc: 'cron表达式', + }, + FIXED_DELAY: { + value: 'fixed_delay', + desc: '固定间隔', + }, +}; + +export default { + TRIGGER_TYPE_ENUM, +}; diff --git a/smart-flow-web/src/constants/support/login-log-const.js b/smart-flow-web/src/constants/support/login-log-const.js new file mode 100644 index 0000000..0420500 --- /dev/null +++ b/smart-flow-web/src/constants/support/login-log-const.js @@ -0,0 +1,27 @@ +/* + * 登录日志 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:08:45 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const LOGIN_RESULT_ENUM = { + LOGIN_SUCCESS: { + value: 0, + desc: '登录成功', + }, + LOGIN_FAIL: { + value: 1, + desc: '登录失败', + }, + LOGIN_OUT: { + value: 2, + desc: '退出登录', + }, +}; + +export default { + LOGIN_RESULT_ENUM, +}; diff --git a/smart-flow-web/src/constants/support/table-id-const.js b/smart-flow-web/src/constants/support/table-id-const.js new file mode 100644 index 0000000..bdc3165 --- /dev/null +++ b/smart-flow-web/src/constants/support/table-id-const.js @@ -0,0 +1,61 @@ +/* + * @Description: 表格id + * @Author: zhuoda + * @Date: 2022-08-21 + * @LastEditTime: 2022-08-21 + * @LastEditors: zhuoda + */ + +//system系统功能表格初始化id +let systemInitTableId = 10000; + +//support支撑功能表格初始化id +let supportInitTableId = 20000; + +//业务表格初始化id +let businessOAInitTableId = 30000; + +let businessERPInitTableId = 40000; + +export const TABLE_ID_CONST = { + /** + * 业务 + */ + BUSINESS: { + OA: { + NOTICE: businessOAInitTableId + 1, //通知公告 + ENTERPRISE: businessOAInitTableId + 2, //企业信息 + ENTERPRISE_EMPLOYEE: businessOAInitTableId + 3, //企业员工 + ENTERPRISE_BANK: businessOAInitTableId + 4, //企业银行 + ENTERPRISE_INVOICE: businessOAInitTableId + 5, //企业发票 + }, + ERP: { + GOODS: businessERPInitTableId + 1, //商品管理 + }, + }, + + /** + * 系统 + */ + SYSTEM: { + EMPLOYEE: systemInitTableId + 1, //员工 + MENU: systemInitTableId + 2, //菜单 + POSITION: systemInitTableId + 3, //职位 + }, + /** + * 支撑 + */ + SUPPORT: { + CONFIG: supportInitTableId + 1, //参数配置 + DICT: supportInitTableId + 2, //字典 + SERIAL_NUMBER: supportInitTableId + 3, //单号 + OPERATE_LOG: supportInitTableId + 4, //请求监控 + HEART_BEAT: supportInitTableId + 5, //心跳 + LOGIN_LOG: supportInitTableId + 6, //登录日志 + RELOAD: supportInitTableId + 7, //reload + HELP_DOC: supportInitTableId + 8, //帮助文档 + JOB: supportInitTableId + 9, //Job + JOB_LOG: supportInitTableId + 10, //JobLog + MAIL: supportInitTableId + 11, + }, +}; diff --git a/smart-flow-web/src/constants/system/employee-const.js b/smart-flow-web/src/constants/system/employee-const.js new file mode 100644 index 0000000..61503b1 --- /dev/null +++ b/smart-flow-web/src/constants/system/employee-const.js @@ -0,0 +1,27 @@ +/* + * 员工 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-03 22:08:45 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const GENDER_ENUM = { + UNKNOWN: { + value: 0, + desc: '未知', + }, + MAN: { + value: 1, + desc: '男', + }, + WOMAN: { + value: 2, + desc: '女', + }, +} + +export default { + GENDER_ENUM, +} diff --git a/smart-flow-web/src/constants/system/home-const.js b/smart-flow-web/src/constants/system/home-const.js new file mode 100644 index 0000000..c0c37db --- /dev/null +++ b/smart-flow-web/src/constants/system/home-const.js @@ -0,0 +1,15 @@ +/* + * 首页页面名词 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:56:43 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +//首页页面名字 +export const HOME_PAGE_NAME = 'Home'; + +//首页页面路径 +export const HOME_PAGE_PATH = '/home'; diff --git a/smart-flow-web/src/constants/system/login-device-const.js b/smart-flow-web/src/constants/system/login-device-const.js new file mode 100644 index 0000000..f203121 --- /dev/null +++ b/smart-flow-web/src/constants/system/login-device-const.js @@ -0,0 +1,31 @@ +/* + * 登录设备 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:56:56 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const LOGIN_DEVICE_ENUM = { + PC: { + value: 1, + desc: '电脑端', + }, + ANDROID: { + value: 2, + desc: '安卓', + }, + APPLE: { + value: 3, + desc: '苹果', + }, + H5: { + value: 3, + desc: 'H5', + }, +}; + +export default { + LOGIN_DEVICE_ENUM, +}; diff --git a/smart-flow-web/src/constants/system/menu-const.js b/smart-flow-web/src/constants/system/menu-const.js new file mode 100644 index 0000000..6adf4b1 --- /dev/null +++ b/smart-flow-web/src/constants/system/menu-const.js @@ -0,0 +1,43 @@ +/* + * 菜单类型 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 19:57:04 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +export const MENU_TYPE_ENUM = { + CATALOG: { + value: 1, + desc: '目录', + }, + MENU: { + value: 2, + desc: '菜单', + }, + POINTS: { + value: 3, + desc: '功能点', + }, +}; + +/** + * 权限类型 + */ +export const MENU_PERMS_TYPE_ENUM = { + SA_TOKEN: { + value: 1, + desc: 'Sa-Token模式', + } +}; + +/** + * 默认的顶级菜单id为0 + */ +export const MENU_DEFAULT_PARENT_ID = 0; + +export default { + MENU_TYPE_ENUM, + MENU_PERMS_TYPE_ENUM +}; diff --git a/smart-flow-web/src/directives/privilege.js b/smart-flow-web/src/directives/privilege.js new file mode 100644 index 0000000..d425664 --- /dev/null +++ b/smart-flow-web/src/directives/privilege.js @@ -0,0 +1,29 @@ +/* + * 权限 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:00:40 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import { useUserStore } from '/@/store/modules/system/user'; +import _ from 'lodash'; + +export function privilegeDirective(el, binding) { + // 超级管理员 + if (useUserStore().administratorFlag) { + return true; + } + // 获取功能点权限 + let userPointsList = useUserStore().getPointList; + if (!userPointsList) { + return false; + } + // 如果没有权限,删除节点 + if (!_.some(userPointsList, ['webPerms', binding.value])) { + el.parentNode.removeChild(el); + } + return true; +} diff --git a/smart-flow-web/src/i18n/index.js b/smart-flow-web/src/i18n/index.js new file mode 100644 index 0000000..44c8b97 --- /dev/null +++ b/smart-flow-web/src/i18n/index.js @@ -0,0 +1,41 @@ +/* + * 国际化入口文件 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:01:19 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import en_US from './lang/en-US/index'; +import zh_CN from './lang/zh-CN/index'; +import { createI18n } from 'vue-i18n'; +import { getInitializedLanguage } from '/@/store/modules/system/app-config'; + +// 语言选择数组 +export const i18nList = [ + { + text: '简体中文', + value: 'zh_CN', + }, + { + text: 'English', + value: 'en_US', + }, +]; + +export const messages = { + zh_CN: zh_CN, + en_US: en_US, +}; + +const i18n = createI18n({ + fallbackLocale: 'zh_CN', //预设语言环境 + globalInjection: true, + legacy: false, // + locale: getInitializedLanguage(), //默认初始化的语言 + messages, // +}); + +export default i18n; diff --git a/smart-flow-web/src/i18n/lang/en-US/index.js b/smart-flow-web/src/i18n/lang/en-US/index.js new file mode 100644 index 0000000..30a5cf1 --- /dev/null +++ b/smart-flow-web/src/i18n/lang/en-US/index.js @@ -0,0 +1,34 @@ +/* + * 英文国际化 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:00:57 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import antd from 'ant-design-vue/es/locale/en_US'; +import dayjs from 'dayjs/locale/eu'; + +export default { + antdLocale: antd, + dayjsLocale: dayjs, + 'setting.title': 'Setting', + 'setting.table.yHeight': 'Table Height', + 'setting.pagetag.location': 'TagPage Position', + 'setting.color': 'Theme Color', + 'setting.menu.layout': 'Menu Layout', + 'setting.menu.width': 'Menu Width', + 'setting.menu.theme': 'Menu Theme', + 'setting.page.width': 'Page Width', + 'setting.border.radius': 'Border Radius', + 'setting.compact': 'Page Compact', + 'setting.bread': 'Show Bread', + 'setting.flatPattern': 'Flat Pattern', + 'setting.pagetag': 'Show PageTag', + 'setting.pagetag.style': 'PageTag Style', + 'setting.footer': 'Show Footer', + 'setting.helpdoc': 'Show Helpdoc', + 'setting.helpdoc.expand': 'Helpdoc Expand', + 'setting.watermark': 'Show Watermark', +}; diff --git a/smart-flow-web/src/i18n/lang/zh-CN/index.js b/smart-flow-web/src/i18n/lang/zh-CN/index.js new file mode 100644 index 0000000..6e085c9 --- /dev/null +++ b/smart-flow-web/src/i18n/lang/zh-CN/index.js @@ -0,0 +1,34 @@ +/* + * 中文国际化 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:01:06 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import antd from 'ant-design-vue/es/locale/zh_CN'; +import dayjs from 'dayjs/locale/zh-cn'; + +export default { + antdLocale: antd, + dayjsLocale: dayjs, + 'setting.title': '网站设置', + 'setting.table.yHeight': '表格高度', + 'setting.pagetag.location': '标签页位置', + 'setting.color': '主题颜色', + 'setting.menu.layout': '菜单布局', + 'setting.menu.width': '菜单宽度', + 'setting.menu.theme': '菜单主题', + 'setting.compact': '页面紧凑', + 'setting.border.radius': '页面圆角', + 'setting.page.width': '页面宽度', + 'setting.bread': '面包屑', + 'setting.flatPattern': '菜单展开模式', + 'setting.pagetag': '标签页', + 'setting.pagetag.style': '标签页样式', + 'setting.footer': '页脚', + 'setting.helpdoc': '帮助文档', + 'setting.helpdoc.expand': '帮助文档展开', + 'setting.watermark': '水印', +}; diff --git a/smart-flow-web/src/layout/components/change-password/regular-change-password-modal.vue b/smart-flow-web/src/layout/components/change-password/regular-change-password-modal.vue new file mode 100644 index 0000000..2f863e6 --- /dev/null +++ b/smart-flow-web/src/layout/components/change-password/regular-change-password-modal.vue @@ -0,0 +1,47 @@ + + + diff --git a/smart-flow-web/src/layout/components/header-user-space/header-avatar.vue b/smart-flow-web/src/layout/components/header-user-space/header-avatar.vue new file mode 100644 index 0000000..509b6c3 --- /dev/null +++ b/smart-flow-web/src/layout/components/header-user-space/header-avatar.vue @@ -0,0 +1,142 @@ + + + + + diff --git a/smart-flow-web/src/layout/components/header-user-space/header-message-detail-modal.vue b/smart-flow-web/src/layout/components/header-user-space/header-message-detail-modal.vue new file mode 100644 index 0000000..3e0e7a3 --- /dev/null +++ b/smart-flow-web/src/layout/components/header-user-space/header-message-detail-modal.vue @@ -0,0 +1,47 @@ + + diff --git a/smart-flow-web/src/layout/components/header-user-space/header-message.vue b/smart-flow-web/src/layout/components/header-user-space/header-message.vue new file mode 100644 index 0000000..aa3de6d --- /dev/null +++ b/smart-flow-web/src/layout/components/header-user-space/header-message.vue @@ -0,0 +1,262 @@ + + + + + + + diff --git a/smart-flow-web/src/layout/components/header-user-space/header-reset-password-modal/index.vue b/smart-flow-web/src/layout/components/header-user-space/header-reset-password-modal/index.vue new file mode 100644 index 0000000..53fd9d5 --- /dev/null +++ b/smart-flow-web/src/layout/components/header-user-space/header-reset-password-modal/index.vue @@ -0,0 +1,88 @@ + + + diff --git a/smart-flow-web/src/layout/components/header-user-space/header-setting.vue b/smart-flow-web/src/layout/components/header-user-space/header-setting.vue new file mode 100644 index 0000000..fa1808c --- /dev/null +++ b/smart-flow-web/src/layout/components/header-user-space/header-setting.vue @@ -0,0 +1,376 @@ + + + + + diff --git a/smart-flow-web/src/layout/components/header-user-space/index.vue b/smart-flow-web/src/layout/components/header-user-space/index.vue new file mode 100644 index 0000000..96e4cbe --- /dev/null +++ b/smart-flow-web/src/layout/components/header-user-space/index.vue @@ -0,0 +1,102 @@ + + + + + + diff --git a/smart-flow-web/src/layout/components/menu-location-breadcrumb/index.vue b/smart-flow-web/src/layout/components/menu-location-breadcrumb/index.vue new file mode 100644 index 0000000..ad30078 --- /dev/null +++ b/smart-flow-web/src/layout/components/menu-location-breadcrumb/index.vue @@ -0,0 +1,40 @@ + + + + \ No newline at end of file diff --git a/smart-flow-web/src/layout/components/page-tag/components/antd-tab.vue b/smart-flow-web/src/layout/components/page-tag/components/antd-tab.vue new file mode 100644 index 0000000..22289a6 --- /dev/null +++ b/smart-flow-web/src/layout/components/page-tag/components/antd-tab.vue @@ -0,0 +1,223 @@ + + + + + + diff --git a/smart-flow-web/src/layout/components/page-tag/components/chrome-tab.vue b/smart-flow-web/src/layout/components/page-tag/components/chrome-tab.vue new file mode 100644 index 0000000..5e485b6 --- /dev/null +++ b/smart-flow-web/src/layout/components/page-tag/components/chrome-tab.vue @@ -0,0 +1,342 @@ + + + + + + diff --git a/smart-flow-web/src/layout/components/page-tag/components/default-tab.vue b/smart-flow-web/src/layout/components/page-tag/components/default-tab.vue new file mode 100644 index 0000000..243fcee --- /dev/null +++ b/smart-flow-web/src/layout/components/page-tag/components/default-tab.vue @@ -0,0 +1,222 @@ + + + + + + diff --git a/smart-flow-web/src/layout/components/page-tag/index.vue b/smart-flow-web/src/layout/components/page-tag/index.vue new file mode 100644 index 0000000..4fc5549 --- /dev/null +++ b/smart-flow-web/src/layout/components/page-tag/index.vue @@ -0,0 +1,27 @@ + + + + diff --git a/smart-flow-web/src/layout/components/side-expand-menu/index.vue b/smart-flow-web/src/layout/components/side-expand-menu/index.vue new file mode 100644 index 0000000..06fd240 --- /dev/null +++ b/smart-flow-web/src/layout/components/side-expand-menu/index.vue @@ -0,0 +1,75 @@ + + + + diff --git a/smart-flow-web/src/layout/components/side-expand-menu/recursion-menu.vue b/smart-flow-web/src/layout/components/side-expand-menu/recursion-menu.vue new file mode 100644 index 0000000..67fd92b --- /dev/null +++ b/smart-flow-web/src/layout/components/side-expand-menu/recursion-menu.vue @@ -0,0 +1,109 @@ + + + + diff --git a/smart-flow-web/src/layout/components/side-expand-menu/side-expand-menu-mitt.js b/smart-flow-web/src/layout/components/side-expand-menu/side-expand-menu-mitt.js new file mode 100644 index 0000000..22e6a40 --- /dev/null +++ b/smart-flow-web/src/layout/components/side-expand-menu/side-expand-menu-mitt.js @@ -0,0 +1,11 @@ +/* + * 展开菜单 event bus + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-07-12 23:32:48 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import mitt from 'mitt'; +export default mitt(); diff --git a/smart-flow-web/src/layout/components/side-expand-menu/sub-menu.vue b/smart-flow-web/src/layout/components/side-expand-menu/sub-menu.vue new file mode 100644 index 0000000..ff46877 --- /dev/null +++ b/smart-flow-web/src/layout/components/side-expand-menu/sub-menu.vue @@ -0,0 +1,46 @@ + + + + diff --git a/smart-flow-web/src/layout/components/side-expand-menu/top-menu.vue b/smart-flow-web/src/layout/components/side-expand-menu/top-menu.vue new file mode 100644 index 0000000..ac29dac --- /dev/null +++ b/smart-flow-web/src/layout/components/side-expand-menu/top-menu.vue @@ -0,0 +1,105 @@ + + + + diff --git a/smart-flow-web/src/layout/components/side-help-doc/components/contact-modal.vue b/smart-flow-web/src/layout/components/side-help-doc/components/contact-modal.vue new file mode 100644 index 0000000..5b9c793 --- /dev/null +++ b/smart-flow-web/src/layout/components/side-help-doc/components/contact-modal.vue @@ -0,0 +1,102 @@ + + + + diff --git a/smart-flow-web/src/layout/components/side-help-doc/components/feedback-modal.vue b/smart-flow-web/src/layout/components/side-help-doc/components/feedback-modal.vue new file mode 100644 index 0000000..0cfdc0e --- /dev/null +++ b/smart-flow-web/src/layout/components/side-help-doc/components/feedback-modal.vue @@ -0,0 +1,85 @@ + + + diff --git a/smart-flow-web/src/layout/components/side-help-doc/index.vue b/smart-flow-web/src/layout/components/side-help-doc/index.vue new file mode 100644 index 0000000..8770f84 --- /dev/null +++ b/smart-flow-web/src/layout/components/side-help-doc/index.vue @@ -0,0 +1,234 @@ + + + + + diff --git a/smart-flow-web/src/layout/components/side-menu/index.vue b/smart-flow-web/src/layout/components/side-menu/index.vue new file mode 100644 index 0000000..a649d37 --- /dev/null +++ b/smart-flow-web/src/layout/components/side-menu/index.vue @@ -0,0 +1,140 @@ + + + + + + diff --git a/smart-flow-web/src/layout/components/side-menu/recursion-menu.vue b/smart-flow-web/src/layout/components/side-menu/recursion-menu.vue new file mode 100644 index 0000000..af9c1ad --- /dev/null +++ b/smart-flow-web/src/layout/components/side-menu/recursion-menu.vue @@ -0,0 +1,115 @@ + + + + + diff --git a/smart-flow-web/src/layout/components/side-menu/sub-menu.vue b/smart-flow-web/src/layout/components/side-menu/sub-menu.vue new file mode 100644 index 0000000..60ccfdc --- /dev/null +++ b/smart-flow-web/src/layout/components/side-menu/sub-menu.vue @@ -0,0 +1,45 @@ + + + diff --git a/smart-flow-web/src/layout/components/smart-footer/index.vue b/smart-flow-web/src/layout/components/smart-footer/index.vue new file mode 100644 index 0000000..84c805a --- /dev/null +++ b/smart-flow-web/src/layout/components/smart-footer/index.vue @@ -0,0 +1,32 @@ + + + + + diff --git a/smart-flow-web/src/layout/components/smart-keep-alive.js b/smart-flow-web/src/layout/components/smart-keep-alive.js new file mode 100644 index 0000000..52cd8d1 --- /dev/null +++ b/smart-flow-web/src/layout/components/smart-keep-alive.js @@ -0,0 +1,39 @@ +/* + * keep-alive + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:39:54 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { computed } from 'vue'; +import { useRoute, useRouter } from 'vue-router'; +import { useUserStore } from '/@/store/modules/system/user'; + +export function smartKeepAlive() { + const route = useRoute(); + const router = useRouter(); + // 需要keep-alive的页面 + const keepAliveIncludes = computed(() => { + return useUserStore().keepAliveIncludes || []; + }); + + // ----------------------- iframe相关 ----------------------- + + // 当前路由是否为不需要缓存的iframe页面 + const iframeNotKeepAlivePageFlag = computed(() => route.meta.frameFlag && !route.meta.keepAlive); + // 打开中的tagNav + const tagNav = computed(() => useUserStore().getTagNav || []); + // 已打开的iframe列表 + const keepAliveIframePages = computed(() => { + let routes = router.getRoutes(); + return routes.filter((e) => e.meta.frameFlag && e.meta.keepAlive && tagNav.value.some((t) => t.menuName == e.name)); + }); + return { + route, + keepAliveIncludes, + iframeNotKeepAlivePageFlag, + keepAliveIframePages, + }; +} diff --git a/smart-flow-web/src/layout/components/top-expand-menu/index.vue b/smart-flow-web/src/layout/components/top-expand-menu/index.vue new file mode 100644 index 0000000..193fe22 --- /dev/null +++ b/smart-flow-web/src/layout/components/top-expand-menu/index.vue @@ -0,0 +1,71 @@ + + + + diff --git a/smart-flow-web/src/layout/components/top-expand-menu/recursion-menu.vue b/smart-flow-web/src/layout/components/top-expand-menu/recursion-menu.vue new file mode 100644 index 0000000..992e763 --- /dev/null +++ b/smart-flow-web/src/layout/components/top-expand-menu/recursion-menu.vue @@ -0,0 +1,192 @@ + + + + diff --git a/smart-flow-web/src/layout/components/top-expand-menu/sub-menu.vue b/smart-flow-web/src/layout/components/top-expand-menu/sub-menu.vue new file mode 100644 index 0000000..ff46877 --- /dev/null +++ b/smart-flow-web/src/layout/components/top-expand-menu/sub-menu.vue @@ -0,0 +1,46 @@ + + + + diff --git a/smart-flow-web/src/layout/components/top-expand-menu/top-expand-menu-mitt.js b/smart-flow-web/src/layout/components/top-expand-menu/top-expand-menu-mitt.js new file mode 100644 index 0000000..22e6a40 --- /dev/null +++ b/smart-flow-web/src/layout/components/top-expand-menu/top-expand-menu-mitt.js @@ -0,0 +1,11 @@ +/* + * 展开菜单 event bus + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-07-12 23:32:48 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import mitt from 'mitt'; +export default mitt(); diff --git a/smart-flow-web/src/layout/components/top-expand-menu/top-menu.vue b/smart-flow-web/src/layout/components/top-expand-menu/top-menu.vue new file mode 100644 index 0000000..210ee32 --- /dev/null +++ b/smart-flow-web/src/layout/components/top-expand-menu/top-menu.vue @@ -0,0 +1,151 @@ + + + + diff --git a/smart-flow-web/src/layout/components/top-menu/index.vue b/smart-flow-web/src/layout/components/top-menu/index.vue new file mode 100644 index 0000000..af3d9b9 --- /dev/null +++ b/smart-flow-web/src/layout/components/top-menu/index.vue @@ -0,0 +1,173 @@ + + + + + + diff --git a/smart-flow-web/src/layout/components/top-menu/recursion-menu.vue b/smart-flow-web/src/layout/components/top-menu/recursion-menu.vue new file mode 100644 index 0000000..120e4c8 --- /dev/null +++ b/smart-flow-web/src/layout/components/top-menu/recursion-menu.vue @@ -0,0 +1,88 @@ + + + + + diff --git a/smart-flow-web/src/layout/components/top-menu/sub-menu.vue b/smart-flow-web/src/layout/components/top-menu/sub-menu.vue new file mode 100644 index 0000000..8faeb1a --- /dev/null +++ b/smart-flow-web/src/layout/components/top-menu/sub-menu.vue @@ -0,0 +1,45 @@ + + + diff --git a/smart-flow-web/src/layout/help-doc-layout.vue b/smart-flow-web/src/layout/help-doc-layout.vue new file mode 100644 index 0000000..7bc858a --- /dev/null +++ b/smart-flow-web/src/layout/help-doc-layout.vue @@ -0,0 +1,305 @@ + + + + + + +../lib/smart-watermark diff --git a/smart-flow-web/src/layout/index.vue b/smart-flow-web/src/layout/index.vue new file mode 100644 index 0000000..96ede82 --- /dev/null +++ b/smart-flow-web/src/layout/index.vue @@ -0,0 +1,33 @@ + + + diff --git a/smart-flow-web/src/layout/layout-const.js b/smart-flow-web/src/layout/layout-const.js new file mode 100644 index 0000000..98fc8b5 --- /dev/null +++ b/smart-flow-web/src/layout/layout-const.js @@ -0,0 +1,9 @@ +/** + * layout 相关元素 id + */ +export const LAYOUT_ELEMENT_IDS = { + menu: 'smartAdminMenu', + main: 'smartAdminMain', + header: 'smartAdminHeader', + content: 'smartAdminLayoutContent', +} diff --git a/smart-flow-web/src/layout/side-expand-layout.vue b/smart-flow-web/src/layout/side-expand-layout.vue new file mode 100644 index 0000000..335cfec --- /dev/null +++ b/smart-flow-web/src/layout/side-expand-layout.vue @@ -0,0 +1,316 @@ + + + + diff --git a/smart-flow-web/src/layout/side-layout.vue b/smart-flow-web/src/layout/side-layout.vue new file mode 100644 index 0000000..bfca2b6 --- /dev/null +++ b/smart-flow-web/src/layout/side-layout.vue @@ -0,0 +1,352 @@ + + + + + diff --git a/smart-flow-web/src/layout/top-expand-layout.vue b/smart-flow-web/src/layout/top-expand-layout.vue new file mode 100644 index 0000000..d8f5b73 --- /dev/null +++ b/smart-flow-web/src/layout/top-expand-layout.vue @@ -0,0 +1,315 @@ + + + + diff --git a/smart-flow-web/src/layout/top-layout.vue b/smart-flow-web/src/layout/top-layout.vue new file mode 100644 index 0000000..9278f2f --- /dev/null +++ b/smart-flow-web/src/layout/top-layout.vue @@ -0,0 +1,198 @@ + + + + + diff --git a/smart-flow-web/src/lib/axios.js b/smart-flow-web/src/lib/axios.js new file mode 100644 index 0000000..d095bf2 --- /dev/null +++ b/smart-flow-web/src/lib/axios.js @@ -0,0 +1,251 @@ +/* + * ajax请求 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:46:03 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { message, Modal } from 'ant-design-vue'; +import axios from 'axios'; +import { localRead } from '/@/utils/local-util'; +import { useUserStore } from '/@/store/modules/system/user'; +import { decryptData, encryptData } from './encrypt'; +import { DATA_TYPE_ENUM } from '../constants/common-const'; +import _ from 'lodash'; +import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; + +// token的消息头 +const TOKEN_HEADER = 'Authorization'; + +// 创建axios对象 +const smartAxios = axios.create({ + baseURL: import.meta.env.VITE_APP_API_URL, +}); + +// 退出系统 +function logout() { + useUserStore().logout(); + location.href = '/'; +} + +// ================================= 请求拦截器 ================================= + +smartAxios.interceptors.request.use( + (config) => { + // 在发送请求之前消息头加入token token + const token = localRead(LocalStorageKeyConst.USER_TOKEN); + if (token) { + config.headers[TOKEN_HEADER] = 'Bearer ' + token; + } else { + delete config.headers[TOKEN_HEADER]; + } + return config; + }, + (error) => { + // 对请求错误做些什么 + return Promise.reject(error); + } +); + +// ================================= 响应拦截器 ================================= + +// 添加响应拦截器 +smartAxios.interceptors.response.use( + (response) => { + // 根据content-type ,判断是否为 json 数据 + let contentType = response.headers['content-type'] ? response.headers['content-type'] : response.headers['Content-Type']; + if (contentType.indexOf('application/json') === -1) { + return Promise.resolve(response); + } + + // 如果是json数据 + if (response.data && response.data instanceof Blob) { + return Promise.reject(response.data); + } + + // 如果是加密数据 + if (response.data.dataType === DATA_TYPE_ENUM.ENCRYPT.value) { + response.data.encryptData = response.data.data; + let decryptStr = decryptData(response.data.data); + if (decryptStr) { + response.data.data = JSON.parse(decryptStr); + } + } + + const res = response.data; + // console.log('response', res); + if (res.code && res.code !== 1) { + // `token` 过期或者账号已在别处登录 + if (res.code === 30007 || res.code === 30008) { + message.destroy(); + message.error('您没有登录,请重新登录'); + setTimeout(logout, 300); + return Promise.reject(response); + } + + // 等保安全的登录提醒 + if (res.code === 30010 || res.code === 30011) { + Modal.error({ + title: '重要提醒', + content: res.msg, + }); + return Promise.reject(response); + } + + // 长时间未操作系统,需要重新登录 + if (res.code === 30012) { + Modal.error({ + title: '重要提醒', + content: res.msg, + onOk: logout, + }); + setTimeout(logout, 3000); + return Promise.reject(response); + } + message.destroy(); + message.error(res.msg); + return Promise.reject(response); + } else { + return Promise.resolve(res); + } + }, + (error) => { + // 对响应错误做点什么 + if (error.message.indexOf('timeout') !== -1) { + message.destroy(); + message.error('网络超时'); + } else if (error.message === 'Network Error') { + message.destroy(); + message.error('网络连接错误'); + } else if (error.message.indexOf('Request') !== -1) { + message.destroy(); + message.error('网络发生错误'); + } + return Promise.reject(error); + } +); + +// ================================= 对外提供请求方法:通用请求,get, post, 下载download等 ================================= + +/** + * get请求 + */ +export const getRequest = (url, params) => { + return request({ url, method: 'get', params }); +}; + +/** + * 通用请求封装 + * @param config + */ +export const request = (config) => { + return smartAxios.request(config); +}; + +/** + * post请求 + */ +export const postRequest = (url, data) => { + return request({ + data, + url, + method: 'post', + }); +}; + +// ================================= 加密 ================================= + +/** + * 加密请求参数的post请求 + */ +export const postEncryptRequest = (url, data) => { + return request({ + data: { encryptData: encryptData(data) }, + url, + method: 'post', + }); +}; + +// ================================= 下载 ================================= + +export const postDownload = function (url, data) { + request({ + method: 'post', + url, + data, + responseType: 'blob', + }) + .then((data) => { + handleDownloadData(data); + }) + .catch((error) => { + handleDownloadError(error); + }); +}; + +/** + * 文件下载 + */ +export const getDownload = function (url, params) { + request({ + method: 'get', + url, + params, + responseType: 'blob', + }) + .then((data) => { + handleDownloadData(data); + }) + .catch((error) => { + handleDownloadError(error); + }); +}; + +function handleDownloadError(error) { + if (error instanceof Blob) { + const fileReader = new FileReader(); + fileReader.readAsText(error); + fileReader.onload = () => { + const msg = fileReader.result; + const jsonMsg = JSON.parse(msg); + message.destroy(); + message.error(jsonMsg.msg); + }; + } else { + message.destroy(); + message.error('网络发生错误', error); + } +} + +function handleDownloadData(response) { + if (!response) { + return; + } + + // 获取返回类型 + let contentType = _.isUndefined(response.headers['content-type']) ? response.headers['Content-Type'] : response.headers['content-type']; + + // 构建下载数据 + let url = window.URL.createObjectURL(new Blob([response.data], { type: contentType })); + let link = document.createElement('a'); + link.style.display = 'none'; + link.href = url; + + // 从消息头获取文件名 + let str = _.isUndefined(response.headers['content-disposition']) + ? response.headers['Content-Disposition'].split(';')[1] + : response.headers['content-disposition'].split(';')[1]; + + let filename = _.isUndefined(str.split('fileName=')[1]) ? str.split('filename=')[1] : str.split('fileName=')[1]; + link.setAttribute('download', decodeURIComponent(filename)); + + // 触发点击下载 + document.body.appendChild(link); + link.click(); + + // 下载完释放 + document.body.removeChild(link); // 下载完成移除元素 + window.URL.revokeObjectURL(url); // 释放掉blob对象 +} diff --git a/smart-flow-web/src/lib/default-time-ranges.js b/smart-flow-web/src/lib/default-time-ranges.js new file mode 100644 index 0000000..634da84 --- /dev/null +++ b/smart-flow-web/src/lib/default-time-ranges.js @@ -0,0 +1,29 @@ +/* + * 时间选择框快捷选择 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:49:28 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import dayjs from 'dayjs'; +import {ref} from 'vue'; + +export const defaultTimeRanges = ref([{label: '今日', value: [dayjs(), dayjs()]}, { + label: '昨日', + value: [dayjs().subtract(1, 'days'), dayjs().subtract(1, 'days')] +}, {label: '本月', value: [dayjs().startOf('month'), dayjs().endOf('month')]}, { + label: '上个月', + value: [dayjs().subtract(1, 'months').startOf('month'), dayjs().subtract(1, 'months').endOf('month')] +}, { + label: '下个月', + value: [dayjs().subtract(-1, 'months').startOf('month'), dayjs().subtract(-1, 'months').endOf('month')] +}, + + {label: '本年度', value: [dayjs().startOf('year'), dayjs().endOf('year')]}, { + label: '上年度', + value: [dayjs().subtract(1, 'years').startOf('year'), dayjs().subtract(1, 'years').endOf('year')] + }]); + diff --git a/smart-flow-web/src/lib/encrypt.js b/smart-flow-web/src/lib/encrypt.js new file mode 100644 index 0000000..3ba986b --- /dev/null +++ b/smart-flow-web/src/lib/encrypt.js @@ -0,0 +1,120 @@ +import CryptoJS from 'crypto-js'; +import CryptoSM from 'sm-crypto'; + +function object2string(data) { + if (typeof data === 'object') { + return JSON.stringify(data); + } + + let str = JSON.stringify(data); + if (str.startsWith("'") || str.startsWith('"')) { + str = str.substring(1); + } + if (str.endsWith("'") || str.endsWith('"')) { + str = str.substring(0, str.length - 1); + } + return str; +} + +/** + * 字符串转为数字 + */ +function stringToHex(str) { + let hex = ''; + for(let i = 0; i < str.length; i++) { + hex += str.charCodeAt(i).toString(16).padStart(2, '0'); + } + return hex; +} + + +/* + * -------------------- ※ AES 加密、解密 begin ※ -------------------- + * + * 1、AES加密算法支持三种密钥长度:128位、192位和256位,这里选择128位 + * 2、AES 要求秘钥为 128bit,转化字节为 16个字节; + * 3、js前端使用 UCS-2 或者 UTF-16 编码,字母、数字、特殊符号等 占用1个字节; + * 4、所以:秘钥Key 组成为:字母、数字、特殊符号 一共16个即可 + * + * -------------------- ※ AES 加密、解密 end ※ -------------------- + */ +const AES_KEY = '1024lab__1024lab'; + +const AES = { + encryptData: function (data) { + // AES 加密 并转为 base64 + let utf8Data = CryptoJS.enc.Utf8.parse(object2string(data)); + const key = CryptoJS.enc.Utf8.parse(AES_KEY); + const encrypted = CryptoJS.AES.encrypt(utf8Data, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7, + }); + return CryptoJS.enc.Base64.stringify(encrypted.ciphertext); + }, + + decryptData: function (data) { + // 第一步:Base64 解码 + let words = CryptoJS.enc.Base64.parse(data); + + // 第二步:AES 解密 + const key = CryptoJS.enc.Utf8.parse(AES_KEY); + return CryptoJS.AES.decrypt({ ciphertext: words }, key, { + mode: CryptoJS.mode.ECB, + padding: CryptoJS.pad.Pkcs7, + }).toString(CryptoJS.enc.Utf8); + }, +}; + +/* + * -------------------- ※ 国密SM4算法 加密、解密 begin ※ -------------------- + * + * 1、国密SM4 要求秘钥为 128bit,转化字节为 16个字节; + * 2、js前端使用 UCS-2 或者 UTF-16 编码,字母、数字、特殊符号等 占用1个字节; + * 3、java中 每个 字母数字 也是占用1个字节; + * 4、所以:前端和后端的 秘钥Key 组成为:字母、数字、特殊符号 一共16个即可 + * + * -------------------- ※ 国密SM4算法 加密、解密 end ※ -------------------- + */ + +// 秘钥Key 组成为:字母、数字、特殊符号 一共16个即可 +const SM4_KEY = '1024lab__1024lab'; + +const SM4 = { + encryptData: function (data) { + // 第一步:SM4 加密 + let encryptData = CryptoSM.sm4.encrypt(object2string(data), stringToHex(SM4_KEY)); + // 第二步: Base64 编码 + return CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(encryptData)); + }, + + decryptData: function (data) { + // 第一步:Base64 解码 + let words = CryptoJS.enc.Base64.parse(data); + let decode64Str = CryptoJS.enc.Utf8.stringify(words); + + // 第二步:SM4 解密 + return CryptoSM.sm4.decrypt(decode64Str, stringToHex(SM4_KEY)); + }, +}; + + + +// ----------------------- 对外暴露: 加密、解密 ----------------------- + +// 默认使用SM4算法 +const EncryptObject = SM4; +// const EncryptObject = AES; + +/** + * 加密 + */ +export const encryptData = function (data) { + return !data ? null : EncryptObject.encryptData(data); +}; + +/** + * 解密 + */ +export const decryptData = function (data) { + return !data ? null : EncryptObject.decryptData(data); +}; diff --git a/smart-flow-web/src/lib/highlight-line-number.js b/smart-flow-web/src/lib/highlight-line-number.js new file mode 100644 index 0000000..7bd21d5 --- /dev/null +++ b/smart-flow-web/src/lib/highlight-line-number.js @@ -0,0 +1,226 @@ +// jshint multistr:true + +let TABLE_NAME = 'hljs-ln', + LINE_NAME = 'hljs-ln-line', + CODE_BLOCK_NAME = 'hljs-ln-code', + NUMBERS_BLOCK_NAME = 'hljs-ln-numbers', + NUMBER_LINE_NAME = 'hljs-ln-n', + DATA_ATTR_NAME = 'data-line-number', + BREAK_LINE_REGEXP = /\r\n|\r|\n/g; + +addStyles(); + +function addStyles() { + let css = document.createElement('style'); + css.type = 'text/css'; + css.innerHTML = format('.{0}{border-collapse:collapse}' + '.{0} td{padding:0}' + '.{1}:before{content:attr({2})}', [ + TABLE_NAME, + NUMBER_LINE_NAME, + DATA_ATTR_NAME, + ]); + document.getElementsByTagName('head')[0].appendChild(css); +} + +function initLineNumbersOnLoad(options) { + if (document.readyState === 'interactive' || document.readyState === 'complete') { + documentReady(options); + } else { + window.addEventListener('DOMContentLoaded', function () { + documentReady(options); + }); + } +} + +function documentReady(options) { + try { + let blocks = document.querySelectorAll('code.hljs,code.nohighlight'); + + for (let i in blocks) { + // eslint-disable-next-line no-prototype-builtins + if (blocks.hasOwnProperty(i)) { + if (!isPluginDisabledForBlock(blocks[i])) { + lineNumbersBlock(blocks[i], options); + } + } + } + } catch (e) { + window.console.error('LineNumbers error: ', e); + } +} + +function isPluginDisabledForBlock(element) { + return element.classList.contains('nohljsln'); +} + +function lineNumbersBlock(element, options) { + if (typeof element !== 'object') return; + element.innerHTML = lineNumbersInternal(element, options); +} + +function lineNumbersInternal(element, options) { + let internalOptions = mapOptions(element, options); + + duplicateMultilineNodes(element); + + return addLineNumbersBlockFor(element.innerHTML, internalOptions); +} + +function addLineNumbersBlockFor(inputHtml, options) { + let lines = getLines(inputHtml); + + // if last line contains only carriage return remove it + if (lines[lines.length - 1].trim() === '') { + lines.pop(); + } + + if (lines.length > 1 || options.singleLine) { + let html = ''; + + for (let i = 0, l = lines.length; i < l; i++) { + html += format( + '' + + '' + + '
' + + '' + + '' + + '{6}' + + '' + + '', + [ + LINE_NAME, + NUMBERS_BLOCK_NAME, + NUMBER_LINE_NAME, + DATA_ATTR_NAME, + CODE_BLOCK_NAME, + i + options.startFrom, + lines[i].length > 0 ? lines[i] : ' ', + ] + ); + } + + return format('{1}
', [TABLE_NAME, html]); + } + + return inputHtml; +} + +/** + * @param {HTMLElement} element Code block. + * @param {Object} options External API options. + * @returns {Object} Internal API options. + */ +function mapOptions(element, options) { + options = options || {}; + return { + singleLine: getSingleLineOption(options), + startFrom: getStartFromOption(element, options), + }; +} + +function getSingleLineOption(options) { + let defaultValue = false; + if (options.singleLine) { + return options.singleLine; + } + return defaultValue; +} + +function getStartFromOption(element, options) { + let defaultValue = 1; + let startFrom = defaultValue; + + if (isFinite(options.startFrom)) { + startFrom = options.startFrom; + } + + // can be overridden because local option is priority + let value = getAttribute(element, 'data-ln-start-from'); + if (value !== null) { + startFrom = toNumber(value, defaultValue); + } + + return startFrom; +} + +/** + * Recursive method for fix multi-line elements implementation in highlight.js + * Doing deep passage on child nodes. + * @param {HTMLElement} element + */ +function duplicateMultilineNodes(element) { + let nodes = element.childNodes; + for (let node in nodes) { + // eslint-disable-next-line no-prototype-builtins + if (nodes.hasOwnProperty(node)) { + let child = nodes[node]; + if (getLinesCount(child.textContent) > 0) { + if (child.childNodes.length > 0) { + duplicateMultilineNodes(child); + } else { + duplicateMultilineNode(child.parentNode); + } + } + } + } +} + +/** + * Method for fix multi-line elements implementation in highlight.js + * @param {HTMLElement} element + */ +function duplicateMultilineNode(element) { + let className = element.className; + + if (!/hljs-/.test(className)) return; + + let lines = getLines(element.innerHTML); + + for (var i = 0, result = ''; i < lines.length; i++) { + let lineText = lines[i].length > 0 ? lines[i] : ' '; + result += format('{1}\n', [className, lineText]); + } + + element.innerHTML = result.trim(); +} + +function getLines(text) { + if (text.length === 0) return []; + return text.split(BREAK_LINE_REGEXP); +} + +function getLinesCount(text) { + return (text.trim().match(BREAK_LINE_REGEXP) || []).length; +} + +/** + * {@link https://wcoder.github.io/notes/string-format-for-string-formating-in-javascript} + * @param {string} format + * @param {array} args + */ +function format(format, args) { + return format.replace(/\{(\d+)\}/g, function (m, n) { + return args[n] !== undefined ? args[n] : m; + }); +} + +/** + * @param {HTMLElement} element Code block. + * @param {String} attrName Attribute name. + * @returns {String} Attribute value or empty. + */ +function getAttribute(element, attrName) { + return element.hasAttribute(attrName) ? element.getAttribute(attrName) : null; +} + +/** + * @param {String} str Source string. + * @param {Number} fallback Fallback value. + * @returns Parsed number or fallback value. + */ +function toNumber(str, fallback) { + if (!str) return fallback; + let number = Number(str); + return isFinite(number) ? number : fallback; +} + +export { lineNumbersBlock, initLineNumbersOnLoad }; diff --git a/smart-flow-web/src/lib/smart-sentry.js b/smart-flow-web/src/lib/smart-sentry.js new file mode 100644 index 0000000..4c6afc1 --- /dev/null +++ b/smart-flow-web/src/lib/smart-sentry.js @@ -0,0 +1,22 @@ +/* + * 错误上报sentry + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:49:28 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +export const smartSentry = { + /** + * sentry 主动上报 + */ + captureError: (error) => { + if (error.config && error.data && error && error.headers && error.request && error.status) { + return; + } + // Sentry.captureException(error); + console.error(error); + }, +}; diff --git a/smart-flow-web/src/lib/smart-watermark.js b/smart-flow-web/src/lib/smart-watermark.js new file mode 100644 index 0000000..3995e39 --- /dev/null +++ b/smart-flow-web/src/lib/smart-watermark.js @@ -0,0 +1,106 @@ +/* + * 水印 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:50:10 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import dayjs from 'dayjs'; + +/** + * 水印DOM id + */ +const WATER_MARK_DOM_ID = 'smart_admin_water_mark'; +let smartAdminWaterMarkIntervalId = null; + +/** + * + * 因为modal的z-index为1000,所以为了modal的黑色背景隐藏掉,z-index为 999 + * + * @param id + * @param str + * @returns + */ + +function setWatermark(id, str) { + //删掉之前的水印 + if (document.getElementById(WATER_MARK_DOM_ID) !== null) { + document.getElementById(WATER_MARK_DOM_ID).remove(); + } + + str = str + ' ' + dayjs().format('YYYY-MM-DD HH:mm'); + + //创建一个画布 + const can = document.createElement('canvas'); + //设置画布的长宽 + can.width = 400; + can.height = 200; + + const cans = can.getContext('2d'); + //旋转角度 + cans.rotate((-15 * Math.PI) / 150); + cans.font = '16px Microsoft JhengHei'; + //设置填充绘画的颜色、渐变或者模式 + cans.fillStyle = 'rgba(190, 190, 190, 0.30)'; + //设置文本内容的当前对齐方式 + cans.textAlign = 'left'; + //设置在绘制文本时使用的当前文本基线 + cans.textBaseline = 'middle'; + //在画布上绘制填色的文本(输出的文本,开始绘制文本的X坐标位置,开始绘制文本的Y坐标位置) + cans.fillText(str, can.width / 8, can.height / 2); + const div = document.createElement('div'); + div.id = WATER_MARK_DOM_ID; + div.style.pointerEvents = 'none'; + div.style.top = '0px'; + div.style.left = '0px'; + div.style.position = 'absolute'; + div.style.zIndex = '99'; + div.style.width = '100%'; + div.style.height = '100%'; + div.style.background = 'url(' + can.toDataURL('image/png') + ') left top repeat'; + document.getElementById(id).appendChild(div); +} + +const watermark = { + show: function () { + document.getElementById(WATER_MARK_DOM_ID).style.display = 'block'; + }, + hide: function () { + document.getElementById(WATER_MARK_DOM_ID).style.display = 'hide'; + }, + // 该方法只允许调用一次 + set: function (id, str) { + // 如果存在水印,则不允许再调用了 + if (document.getElementById(WATER_MARK_DOM_ID) !== null) { + return; + } + + setWatermark(id, str); + + //每隔1分钟检查一次水印 + smartAdminWaterMarkIntervalId = setInterval(() => { + setWatermark(id, str); + }, 60000); + + window.onresize = () => { + setWatermark(id, str); + }; + }, + // 清空水印 + clear: function () { + let watermarkDom = document.getElementById(WATER_MARK_DOM_ID); + if (watermarkDom) { + watermarkDom.remove(); + } + + window.removeEventListener('resize', setWatermark); + if (smartAdminWaterMarkIntervalId) { + clearInterval(smartAdminWaterMarkIntervalId); + smartAdminWaterMarkIntervalId = null; + } + }, +}; +export default watermark; diff --git a/smart-flow-web/src/lib/table-auto-height.js b/smart-flow-web/src/lib/table-auto-height.js new file mode 100644 index 0000000..3b2fd62 --- /dev/null +++ b/smart-flow-web/src/lib/table-auto-height.js @@ -0,0 +1,30 @@ +/** + * 计算表格自适应高度 + * + * @param {*} heightRef + * @param {*} removeRefArray + * @param {*} extraRemoveHeight + * @returns + */ + +import { useAppConfigStore } from '../store/modules/system/app-config'; + +export function calcTableHeight(heightRef, removeRefArray, extraRemoveHeight) { + let removeHeight = 0; + if (removeRefArray && removeRefArray.length > 0) { + for (const item of removeRefArray) { + removeHeight = removeHeight + item.value.$el.offsetHeight; + } + } + + let due = 40; + if (useAppConfigStore().$state.pageTagFlag) { + due = due + 40; + } + if (useAppConfigStore().$state.footerFlag) { + due = due + 40; + } + + removeHeight = removeHeight + extraRemoveHeight + due; + heightRef.value = document.querySelector('#smartAdminLayoutContent').offsetHeight - removeHeight; +} diff --git a/smart-flow-web/src/main.js b/smart-flow-web/src/main.js new file mode 100644 index 0000000..f210506 --- /dev/null +++ b/smart-flow-web/src/main.js @@ -0,0 +1,108 @@ +/* + * 项目启动入口方法 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:59:23 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import { createApp } from 'vue'; +import Antd, { message } from 'ant-design-vue'; +import * as antIcons from '@ant-design/icons-vue'; +import lodash from 'lodash'; +import JsonViewer from 'vue3-json-viewer'; +import 'vue3-json-viewer/dist/index.css'; +import App from './App.vue'; +import { smartSentry } from '/@/lib/smart-sentry'; +import { loginApi } from '/@/api/system/login-api'; +import constantsInfo from '/@/constants/index'; +import { privilegeDirective } from '/@/directives/privilege'; +import i18n from '/@/i18n/index'; +import privilegePlugin from '/@/plugins/privilege-plugin'; +import dictPlugin from '/@/plugins/dict-plugin'; +import smartEnumPlugin from '/@/plugins/smart-enums-plugin'; +import { buildRoutes, router } from '/@/router'; +import { store } from '/@/store'; +import { useUserStore } from '/@/store/modules/system/user'; +import 'ant-design-vue/dist/reset.css'; +import '/@/theme/index.less'; +import { localRead } from '/@/utils/local-util.js'; +import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; +import { Table } from 'ant-design-vue'; +import { useAppConfigStore } from '/@/store/modules/system/app-config'; +import '/@/utils/ployfill'; +import { useDictStore } from '/@/store/modules/system/dict.js'; +import { dictApi } from '/@/api/support/dict-api.js'; + +/* + * -------------------- ※ 着重 解释说明下main.js的初始化逻辑 begin ※ -------------------- + * + * 1、在main.js里很多框架都是 直接调用初始化的vue方法,创建vue实例,然后挂载路由router、状态管理store等等,但是关于router这块是有问题的; + * 2、因为现在大部分路由都是从后端接口返回的,如若直接初始化挂载路由,这时前端还没有从后端请求路由的数据,所以只能写到路由拦截器里,这样很绕很不清晰; + * 正确的做法流程应该是: + * 2.1)如果存在登录信息,则先ajax请求用户的所有路由,然后加载,再去创建vue实例和挂载路由 + * 2.2)如果不存在路由信息,则创建vue实例和挂载路由(此时的路由应该只有login页面,因为用户拥有哪些路由是登录之后才知道的) + * 3、以上,在main.js里两个方法,一个是 获取登录信息getLoginInfo,另一个初始化vue: initVue,在最下的if操作里 + * + * -------------------- ※ 着重 解释说明下main.js的初始化逻辑 end ※ -------------------- + */ + +/** + * 获取用户信息和用户权限对应的路由,构建动态路由 + */ +async function getLoginInfo() { + try { + //获取登录用户信息 + const res = await loginApi.getLoginInfo(); + const dictRes = await dictApi.getAllDictData(); + //构建系统的路由 + let menuRouterList = res.data.menuList.filter((e) => e.path || e.frameUrl); + buildRoutes(menuRouterList); + initVue(); + // 初始化数据字典 + useDictStore().initData(dictRes.data); + //更新用户信息到pinia + useUserStore().setUserLoginInfo(res.data); + } catch (e) { + message.error(e.data ? e.data.msg : e.message); + smartSentry.captureError(e); + initVue(); + } +} + +async function initVue() { + let vueApp = createApp(App); + let app = vueApp + .use(router) + .use(store) + .use(i18n) + .use(Antd) + .use(smartEnumPlugin, constantsInfo) + .use(privilegePlugin) + .use(dictPlugin) + .use(JsonViewer); + //注入权限 + app.directive('privilege', { + mounted(el, binding) { + privilegeDirective(el, binding); + }, + }); + // 注册图标组件 + Object.keys(antIcons).forEach((key) => { + app.component(key, antIcons[key]); + }); + //全局 + app.config.globalProperties.$antIcons = antIcons; + app.config.globalProperties.$lodash = lodash; + //挂载 + app.mount('#app'); +} +//不需要获取用户信息、用户菜单、用户菜单动态路由,直接初始化vue即可 +let token = localRead(LocalStorageKeyConst.USER_TOKEN); +if (!token) { + await initVue(); +} else { + await getLoginInfo(); +} diff --git a/smart-flow-web/src/plugins/dict-plugin.js b/smart-flow-web/src/plugins/dict-plugin.js new file mode 100644 index 0000000..2137996 --- /dev/null +++ b/smart-flow-web/src/plugins/dict-plugin.js @@ -0,0 +1,31 @@ +/* + * 字典插件 + * 此插件为 1024创新实验室 自创的插件 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2024-09-06 20:51:03 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { useDictStore } from '/@/store/modules/system/dict.js'; + +export default { + install: (app) => { + + const dictPlugin = {}; + + /** + * 根据枚举值获取描述 + * @param {*} dictCode 字典编码 + * @param {*} value 值 + * @returns + */ + dictPlugin.getDataLabels = function (dictCode, value) { + return useDictStore().getDataLabels(dictCode, value); + }; + + app.config.globalProperties.$dictPlugin = dictPlugin; + app.provide('dictPlugin', dictPlugin); + }, +}; diff --git a/smart-flow-web/src/plugins/privilege-plugin.js b/smart-flow-web/src/plugins/privilege-plugin.js new file mode 100644 index 0000000..5ae1104 --- /dev/null +++ b/smart-flow-web/src/plugins/privilege-plugin.js @@ -0,0 +1,30 @@ +/* + * 权限插件 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:50:46 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { useUserStore } from '/@/store/modules/system/user'; +import _ from 'lodash'; + +const privilege = (value) => { + // 超级管理员 + if (useUserStore().administratorFlag) { + return true; + } + // 获取功能点权限 + let userPointsList = useUserStore().getPointList; + if (!userPointsList) { + return false; + } + return _.some(userPointsList, ['webPerms', value]); +}; + +export default { + install: (app) => { + app.config.globalProperties.$privilege = privilege; + }, +}; diff --git a/smart-flow-web/src/plugins/smart-enums-plugin.js b/smart-flow-web/src/plugins/smart-enums-plugin.js new file mode 100644 index 0000000..9efc253 --- /dev/null +++ b/smart-flow-web/src/plugins/smart-enums-plugin.js @@ -0,0 +1,81 @@ +/* + * 枚举插件 + * 此插件为 1024创新实验室 自创的插件 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:51:03 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import _ from 'lodash'; +import { FLAG_NUMBER_ENUM } from '/@/constants/common-const'; + +export default { + install: (app, smartEnumWrapper) => { + const smartEnumPlugin = {}; + /** + * 根据枚举值获取描述 + * @param {*} constantName 枚举名 + * @param {*} value 枚举值 + * @returns + */ + smartEnumPlugin.getDescByValue = function (constantName, value) { + if (!smartEnumWrapper || !Object.prototype.hasOwnProperty.call(smartEnumWrapper, constantName)) { + console.error('无法找到变量名称:' + constantName + ',请检查 /constants/index.js 文件中是否引入此变量!'); + return ''; + } + // boolean类型需要做特殊处理 + if (constantName === 'FLAG_NUMBER_ENUM' && !_.isUndefined(value) && typeof value === 'boolean') { + value = value ? FLAG_NUMBER_ENUM.TRUE.value : FLAG_NUMBER_ENUM.FALSE.value; + } + + let smartEnum = smartEnumWrapper[constantName]; + for (let item in smartEnum) { + if (smartEnum[item].value === value) { + return smartEnum[item].desc; + } + } + return ''; + }; + /** + * 根据枚举名获取对应的描述键值对[{value:desc}] + * @param {*} constantName 枚举名 + * @returns + */ + smartEnumPlugin.getValueDescList = function (constantName) { + if (!Object.prototype.hasOwnProperty.call(smartEnumWrapper, constantName)) { + console.error('无法找到变量名称:' + constantName + ',请检查 /constants/index.js 文件中是否引入此变量!'); + return []; + } + const result = []; + let targetSmartEnum = smartEnumWrapper[constantName]; + for (let item in targetSmartEnum) { + result.push(targetSmartEnum[item]); + } + return result; + }; + + /** + * 根据枚举名获取对应的value描述键值对{value:desc} + * @param {*} constantName 枚举名 + * @returns + */ + smartEnumPlugin.getValueDesc = function (constantName) { + if (!Object.prototype.hasOwnProperty.call(smartEnumWrapper, constantName)) { + console.error('无法找到变量名称:' + constantName + ',请检查 /constants/index.js 文件中是否引入此变量!'); + return {}; + } + let smartEnum = smartEnumWrapper[constantName]; + let result = {}; + for (let item in smartEnum) { + let key = smartEnum[item].value + ''; + result[key] = smartEnum[item].desc; + } + return result; + }; + + app.config.globalProperties.$smartEnumPlugin = smartEnumPlugin; + app.provide('smartEnumPlugin', smartEnumPlugin); + }, +}; diff --git a/smart-flow-web/src/router/flow/flow.js b/smart-flow-web/src/router/flow/flow.js new file mode 100644 index 0000000..3531dd5 --- /dev/null +++ b/smart-flow-web/src/router/flow/flow.js @@ -0,0 +1,17 @@ +import SmartLayout from '/@/layout/index.vue'; +export const flowRouters = [ + { + path: '/flow/flow-design', + component: SmartLayout, + hidden: true, + permissions: ['flow:definition:design'], + children: [ + { + path: 'index/:id(\\d+)', + component: () => import('/@/views/flow/definition/warm-flow.vue'), + name: 'Design', + meta: { title: '流程设计', activeMenu: '/flow/definition' } + } + ] + }, + ] \ No newline at end of file diff --git a/smart-flow-web/src/router/index.js b/smart-flow-web/src/router/index.js new file mode 100644 index 0000000..3f78636 --- /dev/null +++ b/smart-flow-web/src/router/index.js @@ -0,0 +1,165 @@ +/* + * 路由 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:52:04 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import nProgress from 'nprogress'; +import 'nprogress/nprogress.css'; +import { nextTick } from 'vue'; +import { createRouter, createWebHashHistory } from 'vue-router'; +import { routerArray } from './routers'; +import { PAGE_PATH_404, PAGE_PATH_LOGIN, HOME_PAGE_PATH } from '/@/constants/common-const'; +import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; +import SmartLayout from '../layout/index.vue'; +import { useUserStore } from '/@/store/modules/system/user'; +import { localClear, localRead } from '/@/utils/local-util'; +import _ from 'lodash'; +import LocalStorageKeyConst from '/@/constants/local-storage-key-const.js'; + +export const router = createRouter({ + history: createWebHashHistory(), + routes: routerArray, + strict: true, + scrollBehavior: () => ({ left: 0, top: 0 }), +}); + +// ----------------------- 路由加载前 ----------------------- +router.beforeEach(async (to, from, next) => { + // 进度条开启 + nProgress.start(); + + // 公共页面,任何时候都可以跳转 + if (to.path === PAGE_PATH_404) { + next(); + return; + } + + // 验证登录 + const token = localRead(LocalStorageKeyConst.USER_TOKEN); + if (!token) { + useUserStore().logout(); + if (to.path === PAGE_PATH_LOGIN) { + next(); + } else { + next({ path: PAGE_PATH_LOGIN }); + } + return; + } + + // 登录页,则跳转到首页 + if (to.path === PAGE_PATH_LOGIN) { + next({ path: HOME_PAGE_PATH }); + return; + } + + // 首页( 需要登录 ,但不需要验证权限) + if (to.path === HOME_PAGE_NAME) { + next(); + return; + } + + // 下载路由对应的 页面组件,并修改组件的Name,如果修改过,则不需要修改 + let toRouterInfo = routerMap.get(to.name); + if (toRouterInfo && _.isFunction(toRouterInfo.component) && toRouterInfo.meta.renameComponentFlag === false) { + // 因为组件component 为 lazy load是个方法,所以可以直接执行 component()方法 + toRouterInfo.component().then((val) => { + // 修改组件的name + val.default.name = to.meta.componentName; + // 记录已经修改过 组件的name + toRouterInfo.meta.renameComponentFlag = true; + }); + } + + // 设置tagNav + useUserStore().setTagNav(to, from); + + // 设置keepAlive + if (to.meta.keepAlive) { + nextTick(() => { + useUserStore().pushKeepAliveIncludes(to.meta.componentName); + }); + } + + next(); +}); + +// ----------------------- 路由加载后 ----------------------- +router.afterEach(() => { + nProgress.done(); +}); + +// ----------------------- 构建router对象 ----------------------- +const routerMap = new Map(); + +export function buildRoutes(menuRouterList) { + let menuList = menuRouterList ? menuRouterList : useUserStore().getMenuRouterList || []; + /** + * 1、构建整个路由信息 + * 2、添加到路由里 + */ + const routerList = []; + // 获取所有vue组件引用地址 用于构建路由 + const modules = import.meta.glob('../views/**/**.vue'); + // 获取所有vue组件 用于注入name属性 name属性用于keep-alive + + //1、构建整个路由信息 + for (const e of menuList) { + if (!e.menuId) { + continue; + } + if (!e.path) { + continue; + } + if (e.deletedFlag && e.deletedFlag === true) { + continue; + } + let route = { + path: e.path.startsWith('/') ? e.path : `/${e.path}`, + // 使用【menuId】作为name唯一标识 + name: e.menuId.toString(), + meta: { + // 数据库菜单(页面)id + id: e.menuId.toString(), + // 组件名称 + componentName: e.menuId.toString(), + // 菜单展示 + title: e.menuName, + // 菜单图标展示 + icon: e.icon, + // 是否在菜单隐藏 + hideInMenu: !e.visibleFlag, + // 页面是否keep-alive缓存 + keepAlive: e.cacheFlag, + // 是否为外链 + frameFlag: e.frameFlag, + // 外链地址 + frameUrl: e.frameUrl, + // 是否 rename了组件的名字 + renameComponentFlag: false, + }, + }; + + if (e.frameFlag) { + route.component = () => import('../components/framework/iframe/iframe-index.vue'); + } else { + let componentPath = e.component && e.component.startsWith('/') ? e.component : '/' + e.component; + let relativePath = `../views${componentPath}`; + // // eslint-disable-next-line no-prototype-builtins + route.component = modules[relativePath]; + } + routerList.push(route); + routerMap.set(e.menuId.toString(), route); + } + + //2、添加到路由里 + router.addRoute({ + path: '/', + meta: {}, + component: SmartLayout, + children: routerList, + }); +} diff --git a/smart-flow-web/src/router/routers.js b/smart-flow-web/src/router/routers.js new file mode 100644 index 0000000..62a93f8 --- /dev/null +++ b/smart-flow-web/src/router/routers.js @@ -0,0 +1,24 @@ +/* + * 所有路由入口 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:52:26 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { homeRouters } from './system/home'; +import { loginRouters } from './system/login'; +import { flowRouters } from './flow/flow'; +import { helpDocRouters } from './support/help-doc'; +import NotFound from '/@/views/system/40X/404.vue'; +import NoPrivilege from '/@/views/system/40X/403.vue'; + +export const routerArray = [ + ...loginRouters, + ...homeRouters, + ...flowRouters, + ...helpDocRouters, + { path: '/:pathMatch(.*)*', name: '404', component: NotFound }, + { path: '/403', name: '403', component: NoPrivilege } +]; diff --git a/smart-flow-web/src/router/support/help-doc.js b/smart-flow-web/src/router/support/help-doc.js new file mode 100644 index 0000000..16c869f --- /dev/null +++ b/smart-flow-web/src/router/support/help-doc.js @@ -0,0 +1,28 @@ +/* + * 帮助文档 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:53:19 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import HelpDocLayout from '/@/layout/help-doc-layout.vue'; + +export const helpDocRouters = [ + { + path: '/help-doc', + name: 'HelpDoc', + component: HelpDocLayout, + meta: { + title: '帮助文档', + hideInMenu: true, + }, + children: [ + { + path: '/help-doc/detail', + component: () => import('/@/views/support/help-doc/user-view/help-doc-user-view.vue'), + }, + ], + }, +]; diff --git a/smart-flow-web/src/router/system/home.js b/smart-flow-web/src/router/system/home.js new file mode 100644 index 0000000..df658b7 --- /dev/null +++ b/smart-flow-web/src/router/system/home.js @@ -0,0 +1,48 @@ +/* + * 首页路由 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:51:41 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; +import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const'; +import SmartLayout from '/@/layout/index.vue'; + +export const homeRouters = [ + { + path: '/', + name: '_home', + redirect: { name: HOME_PAGE_NAME }, + component: SmartLayout, + meta: { + title: '首页', + menuType: MENU_TYPE_ENUM.CATALOG.value, + icon: 'HomeOutlined', + }, + children: [ + { + path: '/home', + name: HOME_PAGE_NAME, + meta: { + title: '首页', + menuType: MENU_TYPE_ENUM.MENU.value, + icon: 'HomeOutlined', + parentMenuList: [{ name: '_home', title: '首页' }], + }, + component: () => import('/@/views/system/home/index.vue'), + }, + { + path: '/account', + name: 'Account', + component: () => import('/@/views/system/account/index.vue'), + meta: { + title: '个人中心', + hideInMenu: false, + }, + }, + ], + }, +]; diff --git a/smart-flow-web/src/router/system/login.js b/smart-flow-web/src/router/system/login.js new file mode 100644 index 0000000..1c1b30a --- /dev/null +++ b/smart-flow-web/src/router/system/login.js @@ -0,0 +1,21 @@ +/* + * 登录页面 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:51:50 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +export const loginRouters = [ + { + path: '/login', + name: 'Login', + component: () => import('/@/views/system/login3/login.vue'), + meta: { + title: '登录', + hideInMenu: true, + }, + }, +]; diff --git a/smart-flow-web/src/store/index.js b/smart-flow-web/src/store/index.js new file mode 100644 index 0000000..8454611 --- /dev/null +++ b/smart-flow-web/src/store/index.js @@ -0,0 +1,12 @@ +/* + * pinia 状态管理 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:58:09 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { createPinia } from 'pinia'; + +export const store = createPinia(); diff --git a/smart-flow-web/src/store/modules/system/app-config.js b/smart-flow-web/src/store/modules/system/app-config.js new file mode 100644 index 0000000..0a48b19 --- /dev/null +++ b/smart-flow-web/src/store/modules/system/app-config.js @@ -0,0 +1,65 @@ +/* + * 项目的配置信息 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:53:47 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { defineStore } from 'pinia'; +import { appDefaultConfig } from '/@/config/app-config'; +import localStorageKeyConst from '/@/constants/local-storage-key-const'; +import { smartSentry } from '/@/lib/smart-sentry'; +import { localRead } from '/@/utils/local-util'; + +let state = { + ...appDefaultConfig +}; + +let appConfigStr = localRead(localStorageKeyConst.APP_CONFIG); +let language = appDefaultConfig.language; +if (appConfigStr) { + try { + state = JSON.parse(appConfigStr); + language = state.language; + } catch (e) { + smartSentry.captureError(e); + } +} + +/** + * 获取初始化的语言 + */ +export const getInitializedLanguage = function () { + return language; +}; + +export const useAppConfigStore = defineStore({ + id: 'appConfig', + state: () => ({ + // 读取config下的默认配置 + ...state, + // 全屏 + fullScreenFlag: false, + }), + actions: { + reset() { + for (const k in appDefaultConfig) { + this[k] = appDefaultConfig[k]; + } + }, + showHelpDoc() { + this.helpDocExpandFlag = true; + }, + hideHelpDoc() { + this.helpDocExpandFlag = false; + }, + startFullScreen() { + this.fullScreenFlag = true; + }, + exitFullScreen() { + this.fullScreenFlag = false; + }, + }, +}); diff --git a/smart-flow-web/src/store/modules/system/dict.js b/smart-flow-web/src/store/modules/system/dict.js new file mode 100644 index 0000000..cd44117 --- /dev/null +++ b/smart-flow-web/src/store/modules/system/dict.js @@ -0,0 +1,61 @@ +import { defineStore } from 'pinia'; +import { dictApi } from '/@/api/support/dict-api'; +import { smartSentry } from '/@/lib/smart-sentry'; +import { DICT_SPLIT } from '/@/constants/support/dict-const.js'; +import _ from 'lodash'; + +export const useDictStore = defineStore({ + id: 'dict', + state: () => ({ + // 字典集合 + dictMap: new Map(), + }), + + actions: { + // 获取字典数据 + getDictData(dictCode) { + if (!dictCode) { + return []; + } + let dictDataList = this.dictMap.get(dictCode); + return dictDataList ? dictDataList : []; + }, + + // 获取字典的值名称 + getDataLabels(dictCode, dataValue) { + if (!dataValue) { + return ''; + } + + // 强制转换dataValue为字符串类型 + let stringValue = dataValue == null ? '' : String(dataValue); + + let dict = this.getDictData(dictCode); + if (dict.length === 0) { + return ''; + } + + let valueArray = stringValue.split(DICT_SPLIT); + let result = []; + for (let item of valueArray) { + let target = _.find(dict, { dataValue: item }); + if (target) { + result.push(target.dataLabel); + } + } + return result.join(DICT_SPLIT); + }, + // 初始化字典 + initData(dictDataList){ + this.dictMap.clear(); + for (let data of dictDataList) { + let dataArray = this.dictMap.get(data.dictCode); + if (!dataArray) { + dataArray = []; + this.dictMap.set(data.dictCode, dataArray); + } + dataArray.push(data); + } + }, + }, +}); diff --git a/smart-flow-web/src/store/modules/system/role.js b/smart-flow-web/src/store/modules/system/role.js new file mode 100644 index 0000000..5902308 --- /dev/null +++ b/smart-flow-web/src/store/modules/system/role.js @@ -0,0 +1,95 @@ +/* + * 角色 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:54:39 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import _ from 'lodash'; +import { defineStore } from 'pinia'; + +export const useRoleStore = defineStore({ + id: 'role', + state: () => ({ + checkedData: [], + treeMap: new Map(), + }), + + actions: { + // 初始化权限树选中数据 + initCheckedData(data) { + this.checkedData = [...new Set(data)]; + }, + // 选中 + addCheckedData(data) { + if (this.checkedData.some((e) => e === data)) { + return; + } + this.checkedData.push(data); + }, + // 选中本级以及子级 + addCheckedDataAndChildren(data) { + let findIndex = this.checkedData.findIndex((val) => val === data.menuId); + if (data.menuId && findIndex === -1) { + this.addCheckedData(data.menuId); + } + if (data.children) { + data.children.forEach((item) => { + this.addCheckedDataAndChildren(item); + }); + } + }, + // 取消选中 + deleteCheckedData(index) { + this.checkedData.splice(index, 1); + }, + // 取消选中本级以及子级 + deleteCheckedDataAndChildren(data) { + let findIndex = this.checkedData.findIndex((val) => val === data.menuId); + if (findIndex !== -1) { + this.deleteCheckedData(findIndex); + } + if (data.children) { + data.children.forEach((item) => { + this.deleteCheckedDataAndChildren(item); + }); + } + }, + // 初始化权限树对象 + initTreeMap(tree) { + for (let treeElement of tree) { + if (!treeElement.menuId) { + continue; + } + this.treeMap.set(treeElement.menuId, treeElement); + if (treeElement.children && !_.isEmpty(treeElement.children)) { + this.initTreeMap(treeElement.children); + } + } + }, + // 选中上一级 + selectUpperLevel(module) { + // 拿到上级key + let parentId = module.parentId; + if (!parentId) { + return; + } + // 从权限树对象 获取该父级对象 + let parentModule = this.treeMap.get(parentId); + if (!parentModule) { + return; + } + // 选中父级 + let parentIndex = this.checkedData.findIndex((e) => parentModule.menuId === e); + if (parentModule.menuId && parentIndex === -1) { + this.addCheckedData(parentModule.menuId); + } + // 如果上级还有上级 则进行递归 + if (parentModule.parentId) { + this.selectUpperLevel(parentModule); + } + }, + }, +}); diff --git a/smart-flow-web/src/store/modules/system/spin.js b/smart-flow-web/src/store/modules/system/spin.js new file mode 100644 index 0000000..fd12a61 --- /dev/null +++ b/smart-flow-web/src/store/modules/system/spin.js @@ -0,0 +1,30 @@ +/* + * loading + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:54:50 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { defineStore } from 'pinia'; + +export const useSpinStore = defineStore({ + id: 'spin', + state: () => ({ + loading: false, + }), + + actions: { + hide() { + this.loading = false; + let spins = document.querySelector('.ant-spin-nested-loading'); + spins.style.zIndex = 999; + }, + show() { + this.loading = true; + let spins = document.querySelector('.ant-spin-nested-loading'); + spins.style.zIndex = 1001; + }, + }, +}); diff --git a/smart-flow-web/src/store/modules/system/user.js b/smart-flow-web/src/store/modules/system/user.js new file mode 100644 index 0000000..ff262e2 --- /dev/null +++ b/smart-flow-web/src/store/modules/system/user.js @@ -0,0 +1,360 @@ +/* + * 登录用户 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:55:09 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import _ from 'lodash'; +import { defineStore } from 'pinia'; +import localKey from '/@/constants/local-storage-key-const'; +import { HOME_PAGE_NAME } from '/@/constants/system/home-const'; +import { MENU_TYPE_ENUM } from '/@/constants/system/menu-const'; +import { messageApi } from '/@/api/support/message-api.js'; +import { smartSentry } from '/@/lib/smart-sentry.js'; +import { localRead, localSave, localRemove } from '/@/utils/local-util'; + + +export const useUserStore = defineStore({ + id: 'userStore', + state: () => ({ + token: '', + //员工id + employeeId: '', + // 头像 + avatar: '', + //登录名 + loginName: '', + //姓名 + actualName: '', + //手机号 + phone: '', + //部门id + departmentId: '', + //部门名词 + departmentName: '', + //是否需要修改密码 + needUpdatePwdFlag: false, + //是否为超级管理员 + administratorFlag: true, + //上次登录ip + lastLoginIp: '', + //上次登录ip地区 + lastLoginIpRegion: '', + //上次登录 设备 + lastLoginUserAgent: '', + //上次登录时间 + lastLoginTime: '', + //左侧菜单树形结构 + menuTree: [], + //存在页面路由的菜单集合 + menuRouterList: [], + //是否完成menuRouter初始化 + menuRouterInitFlag: false, + //父类菜单集合 + menuParentIdListMap: new Map(), + // 功能点集合 + pointsList: [], + // 标签页 + tagNav: null, + // 缓存 + keepAliveIncludes: [], + // 未读消息数量 + unreadMessageCount: 0, + // 待办工作数 + toBeDoneCount: 0, + }), + getters: { + getToken(state) { + if (state.token) { + return state.token; + } + return localRead(localKey.USER_TOKEN); + }, + getNeedUpdatePwdFlag(state){ + return state.needUpdatePwdFlag; + }, + //是否初始化了 路由 + getMenuRouterInitFlag(state) { + return state.menuRouterInitFlag; + }, + //菜单树 + getMenuTree(state) { + return state.menuTree; + }, + //菜单的路由 + getMenuRouterList(state) { + return state.menuRouterList; + }, + //菜单的父级id + getMenuParentIdListMap(state) { + return state.menuParentIdListMap; + }, + //功能点 + getPointList(state) { + if (_.isEmpty(state.pointsList)) { + let localUserPoints = localRead(localKey.USER_POINTS) || ''; + state.pointsList = localUserPoints ? JSON.parse(localUserPoints) : []; + } + return state.pointsList; + }, + //标签页 + getTagNav(state) { + if (_.isNull(state.tagNav)) { + let localTagNav = localRead(localKey.USER_TAG_NAV) || ''; + state.tagNav = localTagNav ? JSON.parse(localTagNav) : []; + } + let tagNavList = _.cloneDeep(state.tagNav) || []; + tagNavList.unshift({ + menuName: HOME_PAGE_NAME, + menuTitle: '首页', + }); + return tagNavList; + }, + }, + + actions: { + logout() { + this.token = ''; + this.menuList = []; + this.tagNav = []; + this.unreadMessageCount = 0; + localRemove(localKey.USER_TOKEN); + localRemove(localKey.USER_POINTS); + localRemove(localKey.USER_TAG_NAV); + localRemove(localKey.APP_CONFIG); + localRemove(localKey.HOME_QUICK_ENTRY); + localRemove(localKey.NOTICE_READ); + localRemove(localKey.TO_BE_DONE); + }, + // 查询未读消息数量 + async queryUnreadMessageCount() { + try { + let result = await messageApi.queryUnreadCount(); + this.unreadMessageCount = result.data; + } catch (e) { + smartSentry.captureError(e); + } + }, + async queryToBeDoneList() { + try { + let localToBeDoneList = localRead(localKey.TO_BE_DONE); + if (localToBeDoneList) { + this.toBeDoneCount = JSON.parse(localToBeDoneList).filter((e) => !e.doneFlag).length; + } + } catch (err) { + smartSentry.captureError(err); + } + }, + //设置登录信息 + setUserLoginInfo(data) { + // 用户基本信息 + this.token = data.token; + this.employeeId = data.employeeId; + this.avatar = data.avatar; + this.loginName = data.loginName; + this.actualName = data.actualName; + this.phone = data.phone; + this.departmentId = data.departmentId; + this.departmentName = data.departmentName; + this.needUpdatePwdFlag = data.needUpdatePwdFlag; + this.administratorFlag = data.administratorFlag; + this.lastLoginIp = data.lastLoginIp; + this.lastLoginIpRegion = data.lastLoginIpRegion; + this.lastLoginUserAgent = data.lastLoginUserAgent; + this.lastLoginTime = data.lastLoginTime; + + //菜单权限 + this.menuTree = buildMenuTree(data.menuList); + + //拥有路由的菜单 + this.menuRouterList = data.menuList.filter((e) => e.path || e.frameUrl); + + //父级菜单集合 + this.menuParentIdListMap = buildMenuParentIdListMap(this.menuTree); + + //功能点 + this.pointsList = data.menuList.filter((menu) => menu.menuType === MENU_TYPE_ENUM.POINTS.value && menu.visibleFlag && !menu.disabledFlag); + + // 获取用户未读消息 + this.queryUnreadMessageCount(); + // 获取待办工作数 + this.queryToBeDoneList(); + }, + + setToken(token) { + this.token = token; + }, + + //设置标签页 + setTagNav(route, from) { + if (_.isNull(this.tagNav)) { + let localTagNav = localRead(localKey.USER_TAG_NAV) || ''; + this.tagNav = localTagNav ? JSON.parse(localTagNav) : []; + } + // name唯一标识 + let name = route.name; + if (!name || name === HOME_PAGE_NAME || name === '403' || name === '404') { + return; + } + let findTag = (this.tagNav || []).find((e) => e.menuName === name); + if (findTag) { + // @ts-ignore + findTag.fromMenuName = from.name; + findTag.fromMenuQuery = from.query; + } else { + // @ts-ignore + this.tagNav.push({ + // @ts-ignore + menuName: name, + // @ts-ignore + menuTitle: route.meta.title, + menuQuery: route.query, + menuIcon:route.meta?.icon, + // @ts-ignore + fromMenuName: from.name, + fromMenuQuery: from.query, + }); + } + localSave(localKey.USER_TAG_NAV, JSON.stringify(this.tagNav)); + }, + //关闭标签页 + closeTagNav(menuName, closeAll) { + if (_.isEmpty(this.getTagNav)) return; + if (closeAll && !menuName) { + this.tagNav = []; + this.clearKeepAliveIncludes(); + } else { + let findIndex = (this.tagNav || []).findIndex((e) => e.menuName === menuName); + if (closeAll) { + if (findIndex === -1) { + this.tagNav = []; + this.clearKeepAliveIncludes(); + } else { + let tagNavElement = (this.tagNav || [])[findIndex]; + this.tagNav = [tagNavElement]; + this.clearKeepAliveIncludes(tagNavElement.menuName); + } + } else { + (this.tagNav || []).splice(findIndex, 1); + this.deleteKeepAliveIncludes(menuName); + } + } + localSave(localKey.USER_TAG_NAV, JSON.stringify(this.tagNav)); + }, + //关闭页面 + closePage(route, router, path) { + if (!this.getTagNav || _.isEmpty(this.getTagNav)) return; + if (path) { + router.push({ path }); + } else { + // 寻找tagNav + let index = this.getTagNav.findIndex((e) => e.menuName === route.name); + if (index === -1) { + router.push({ name: HOME_PAGE_NAME }); + } else { + let tagNav = this.getTagNav[index]; + if (tagNav.fromMenuName && this.getTagNav.some((e) => e.menuName === tagNav.fromMenuName)) { + router.push({ name: tagNav.fromMenuName, query: tagNav.fromMenuQuery }); + } else { + // 查询左侧tag + let leftTagNav = this.getTagNav[index - 1]; + router.push({ name: leftTagNav.menuName, query: leftTagNav.menuQuery }); + } + } + } + this.closeTagNav(route.name, false); + }, + // 加入缓存 + pushKeepAliveIncludes(val) { + if (!val) { + return; + } + if (!this.keepAliveIncludes) { + this.keepAliveIncludes = []; + } + if (this.keepAliveIncludes.length < 30) { + let number = this.keepAliveIncludes.findIndex((e) => e === val); + if (number === -1) { + this.keepAliveIncludes.push(val); + } + } + }, + // 删除缓存 + deleteKeepAliveIncludes(val) { + if (!this.keepAliveIncludes || !val) { + return; + } + let number = this.keepAliveIncludes.findIndex((e) => e === val); + if (number !== -1) { + this.keepAliveIncludes.splice(number, 1); + } + }, + // 清空缓存 + clearKeepAliveIncludes(val) { + if (!val || !this.keepAliveIncludes.includes(val)) { + this.keepAliveIncludes = []; + return; + } + this.keepAliveIncludes = [val]; + }, + }, +}); + +/** + * 构建菜单父级集合 + */ +function buildMenuParentIdListMap(menuTree) { + let menuParentIdListMap = new Map(); + recursiveBuildMenuParentIdListMap(menuTree, [], menuParentIdListMap); + return menuParentIdListMap; +} + +function recursiveBuildMenuParentIdListMap(menuList, parentMenuList, menuParentIdListMap) { + for (const e of menuList) { + // 顶级parentMenuList清空 + if (e.parentId === 0) { + parentMenuList = []; + } + let menuIdStr = e.menuId.toString(); + let cloneParentMenuList = _.cloneDeep(parentMenuList); + if (!_.isEmpty(e.children) && e.menuName) { + // 递归 + cloneParentMenuList.push({ name: menuIdStr, title: e.menuName }); + recursiveBuildMenuParentIdListMap(e.children, cloneParentMenuList, menuParentIdListMap); + } else { + menuParentIdListMap.set(menuIdStr, cloneParentMenuList); + } + } +} + +/** + * 构建菜单树 + * + * @param menuList + * @returns + */ +function buildMenuTree(menuList) { + //1 获取所有 有效的 目录和菜单 + let catalogAndMenuList = menuList.filter((menu) => menu.menuType !== MENU_TYPE_ENUM.POINTS.value && menu.visibleFlag && !menu.disabledFlag); + + //2 获取顶级目录 + let topCatalogList = catalogAndMenuList.filter((menu) => menu.parentId === 0); + for (const topCatalog of topCatalogList) { + buildMenuChildren(topCatalog, catalogAndMenuList); + } + return topCatalogList; +} + +function buildMenuChildren(menu, allMenuList) { + let children = allMenuList.filter((e) => e.parentId === menu.menuId); + if (children.length === 0) { + return; + } + menu.children = children; + for (const item of children) { + buildMenuChildren(item, allMenuList); + } +} diff --git a/smart-flow-web/src/theme/color.js b/smart-flow-web/src/theme/color.js new file mode 100644 index 0000000..72609ad --- /dev/null +++ b/smart-flow-web/src/theme/color.js @@ -0,0 +1,63 @@ +export const themeColors = [ + // 蓝色 + { + primaryColor: '#1677ff', + activeColor: '#0958d9', + hoverColor: '#4096ff', + }, + // 蓝色2 + { + primaryColor: '#2F54EB', + activeColor: '#1d39c4', + hoverColor: '#597ef7', + }, + // 绿色 + { + primaryColor: '#00b96b', + activeColor: '#00945b', + hoverColor: '#20c77c', + }, + + // 红色 + { + primaryColor: '#F5222D', + activeColor: '#cf1322', + hoverColor: '#ff4d4f', + }, + // 青色 + { + primaryColor: '#13c2c2', + activeColor: '#08979c', + hoverColor: '#36cfc9', + }, + // 粉色 + { + primaryColor: '#EB2F96', + activeColor: '#c41d7f', + hoverColor: '#f759ab', + }, + // 紫色 + { + primaryColor: '#722ED1', + activeColor: '#531dab', + hoverColor: '#9254de', + }, + // 极光绿 + { + primaryColor: '#52c41a', + activeColor: '#389e0d', + hoverColor: '#73d13d', + }, + // 深绿 + { + primaryColor: '#009688', + activeColor: '#007069', + hoverColor: '#1aa391', + }, + // 橙色 + { + primaryColor: '#fa541c', + activeColor: '#d4380d', + hoverColor: '#ff7a45', + }, +]; diff --git a/smart-flow-web/src/theme/custom-variables.js b/smart-flow-web/src/theme/custom-variables.js new file mode 100644 index 0000000..5546e5c --- /dev/null +++ b/smart-flow-web/src/theme/custom-variables.js @@ -0,0 +1,20 @@ +import { theme } from 'ant-design-vue/lib'; +import convertLegacyToken from 'ant-design-vue/lib/theme/convertLegacyToken'; + +const { defaultAlgorithm, defaultSeed } = theme; + +const mapToken = defaultAlgorithm(defaultSeed); +const token = convertLegacyToken.default(mapToken); + +export default { + '@primary-color': token['primary-color'], // 全局主色 + '@base-bg-color': '#fff', + '@hover-bg-color': 'rgba(0, 0, 0, 0.025)', + '@hover-bg-color-night': 'rgba(255, 255, 255, 0.025)', + '@header-light-bg-hover-color': '#f6f6f6', + '@header-height': '80px', + '@header-user-height': '40px', + '@side-logo-height': '76px', + '@page-tag-height': '40px', + '@theme-list': ['light', 'dark', 'night'], +}; diff --git a/smart-flow-web/src/theme/index.less b/smart-flow-web/src/theme/index.less new file mode 100644 index 0000000..34c6f8d --- /dev/null +++ b/smart-flow-web/src/theme/index.less @@ -0,0 +1,117 @@ +/* + * 默认样式的修改 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-12 14:41:59 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +@import 'ant-design-vue/dist/reset.css'; +@import './smart-admin.less'; + +/********************************** 基础样式 **********************************/ +* { + margin: 0; + padding: 0; + box-sizing: border-box; + outline: none !important; +} + +html, +body { + margin: 0; + padding: 0; + width: 100%; + height: 100%; + -webkit-font-smoothing: antialiased; + -webkit-tap-highlight-color: transparent; + background-color: #f8f8f8; + font-size: 14px; + position: relative; +} + +#app { + width: 100%; + height: 100%; +} + +/********************************** ant design spin **********************************/ +.ant-spin-blur{ + opacity: 0.2; +} + +/********************************** ant design table **********************************/ +.ant-table-tbody :deep(.smart-table-striped) { + background-color: #fafafa; +} + +/********************************** ant design form **********************************/ +.ant-form-inline .ant-form-item-with-help { + margin-bottom: 0px !important; +} + +/********************************** ant design spin **********************************/ +.ant-spin-nested-loading { + width: 100%; + height: 100%; +} + +.ant-spin-container { + width: 100%; + height: 100%; +} + +/********************************** 富文本HTML样式 **********************************/ +.ant-modal-root div[aria-hidden="true"] { + display: none !important; +} + +/********************************** 富文本HTML样式 **********************************/ +.html-content { + /* table 样式 */ + table { + border-top: 1px solid #ccc; + border-left: 1px solid #ccc; + } + table td, + table th { + border-bottom: 1px solid #ccc; + border-right: 1px solid #ccc; + padding: 3px 5px; + } + table th { + border-bottom: 2px solid #ccc; + text-align: center; + } + + /* blockquote 样式 */ + blockquote { + display: block; + border-left: 8px solid #d0e5f2; + padding: 5px 10px; + margin: 10px 0; + line-height: 1.4; + font-size: 100%; + background-color: #f1f1f1; + } + + /* code 样式 */ + code { + display: inline-block; + background-color: #f1f1f1; + border-radius: 3px; + padding: 3px 5px; + margin: 0 3px; + } + pre code { + display: block; + } + + /* ul ol 样式 */ + ul, + ol { + margin: 10px 0 10px 20px; + } +} diff --git a/smart-flow-web/src/theme/smart-admin.less b/smart-flow-web/src/theme/smart-admin.less new file mode 100644 index 0000000..d2bd8ba --- /dev/null +++ b/smart-flow-web/src/theme/smart-admin.less @@ -0,0 +1,114 @@ +/* + * SmartAdmin 独有的样式 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-12 14:43:01 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +/********************************** 宽度 **********************************/ +.smart-width-100 { + width: 100%; +} + +/********************************** 左间距 **********************************/ +.smart-margin-left5 { + margin-left: 5px; +} + +.smart-margin-left10 { + margin-left: 10px; +} + +.smart-margin-left15 { + margin-left: 15px; +} + +.smart-margin-left20 { + margin-left: 20px; +} + +/********************************** 右间距 **********************************/ +.smart-margin-right5 { + margin-right: 5px; +} + +.smart-margin-right10 { + margin-right: 10px; +} + +.smart-margin-right15 { + margin-right: 15px; +} + +.smart-margin-right20 { + margin-right: 20px; +} + +/******************************** 上间距 ********************************/ +.smart-margin-top5 { + margin-top: 5px; +} + +.smart-margin-top10 { + margin-top: 10px; +} + +/******************************** 下间距 ********************************/ +.smart-margin-bottom5 { + margin-bottom: 5px; +} + +.smart-margin-bottom10 { + margin-bottom: 10px; +} +/******************************** 查询表格样式 ********************************/ +.smart-query-form { + background-color: #ffffff; + padding: 5px 10px; + margin-bottom: 10px; +} + +.smart-table-operate { + .ant-btn { + padding: 0 3px !important; + height: auto; + } +} + +.smart-table-column-operate { + float: right; +} + +.smart-query-form-row:not(:first-child) { + margin-top: 8px; +} + +.smart-query-form-row .smart-query-form-item { + margin-right: 8px; + margin-top: 5px; + margin-bottom: 5px; +} + +.smart-query-table-page { + margin-top: 10px; + display: flex; + justify-content: flex-end; +} + +.smart-table-btn-block { + margin-bottom: 15px; + display: flex; + flex-direction: row; + justify-content: space-between; + .smart-table-operate-block { + .ant-btn { + margin-right: 12px; + } + } + .smart-table-setting-block { + float: right; + } +} diff --git a/smart-flow-web/src/utils/local-util.js b/smart-flow-web/src/utils/local-util.js new file mode 100644 index 0000000..80e8903 --- /dev/null +++ b/smart-flow-web/src/utils/local-util.js @@ -0,0 +1,25 @@ +/* + * localStorage 相关操作 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:58:49 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +export const localSave = (key, value) => { + localStorage.setItem(key, value); +}; + +export const localRead = (key) => { + return localStorage.getItem(key) || ''; +}; + +export const localClear = () => { + localStorage.clear(); +}; + +export const localRemove = (key) => { + localStorage.removeItem(key); +}; diff --git a/smart-flow-web/src/utils/ployfill.js b/smart-flow-web/src/utils/ployfill.js new file mode 100644 index 0000000..90923f6 --- /dev/null +++ b/smart-flow-web/src/utils/ployfill.js @@ -0,0 +1,14 @@ +//去除谷歌浏览器的scroll、wheel等事件警告 +(function () { + if (typeof EventTarget !== 'undefined') { + let func = EventTarget.prototype.addEventListener; + EventTarget.prototype.addEventListener = function (type, fn, capture) { + this.func = func; + if (typeof capture !== 'boolean') { + capture = capture || {}; + capture.passive = false; + } + this.func(type, fn, capture); + }; + } +})(); diff --git a/smart-flow-web/src/utils/str-util.js b/smart-flow-web/src/utils/str-util.js new file mode 100644 index 0000000..6d4b59b --- /dev/null +++ b/smart-flow-web/src/utils/str-util.js @@ -0,0 +1,46 @@ +/* + * 字符串 相关操作 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-09-06 20:58:49 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +/** + * 转为 小写中划线 + */ +export function convertLowerHyphen(str) { + if (!str) { + return ''; + } + + return str + .replace(/([A-Z])/g, '-$1') + .toLowerCase() + .substring(1); +} +/** + * 转为驼峰 + */ +export function convertUpperCamel(str) { + if (!str) { + return ''; + } + + str = str.replace(/_(\w)/g, (_, letter) => letter.toUpperCase()); + // 首字母大写 + return str[0].toUpperCase() + str.substring(1); +} + +/** + * 转为驼峰 + */ +export function convertLowerCamel(str) { + if (!str) { + return ''; + } + + return str.replace(/_(\w)/g, (_, letter) => letter.toUpperCase()); +} diff --git a/smart-flow-web/src/views/business/erp/catalog/components/category-form-modal.vue b/smart-flow-web/src/views/business/erp/catalog/components/category-form-modal.vue new file mode 100644 index 0000000..e80071c --- /dev/null +++ b/smart-flow-web/src/views/business/erp/catalog/components/category-form-modal.vue @@ -0,0 +1,111 @@ + + + diff --git a/smart-flow-web/src/views/business/erp/catalog/components/category-tree-table.vue b/smart-flow-web/src/views/business/erp/catalog/components/category-tree-table.vue new file mode 100644 index 0000000..86f757f --- /dev/null +++ b/smart-flow-web/src/views/business/erp/catalog/components/category-tree-table.vue @@ -0,0 +1,164 @@ + + + diff --git a/smart-flow-web/src/views/business/erp/catalog/custom-catalog.vue b/smart-flow-web/src/views/business/erp/catalog/custom-catalog.vue new file mode 100644 index 0000000..b1e6ee1 --- /dev/null +++ b/smart-flow-web/src/views/business/erp/catalog/custom-catalog.vue @@ -0,0 +1,18 @@ + + + diff --git a/smart-flow-web/src/views/business/erp/catalog/goods-catalog.vue b/smart-flow-web/src/views/business/erp/catalog/goods-catalog.vue new file mode 100644 index 0000000..4fa02ef --- /dev/null +++ b/smart-flow-web/src/views/business/erp/catalog/goods-catalog.vue @@ -0,0 +1,18 @@ + + + diff --git a/smart-flow-web/src/views/business/erp/goods/components/goods-form-modal.vue b/smart-flow-web/src/views/business/erp/goods/components/goods-form-modal.vue new file mode 100644 index 0000000..3ff7757 --- /dev/null +++ b/smart-flow-web/src/views/business/erp/goods/components/goods-form-modal.vue @@ -0,0 +1,153 @@ + + + diff --git a/smart-flow-web/src/views/business/erp/goods/goods-list.vue b/smart-flow-web/src/views/business/erp/goods/goods-list.vue new file mode 100644 index 0000000..c4be733 --- /dev/null +++ b/smart-flow-web/src/views/business/erp/goods/goods-list.vue @@ -0,0 +1,526 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-bank-list.vue b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-bank-list.vue new file mode 100644 index 0000000..283bd81 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-bank-list.vue @@ -0,0 +1,246 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-bank-operate-modal.vue b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-bank-operate-modal.vue new file mode 100644 index 0000000..dcd33c1 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-bank-operate-modal.vue @@ -0,0 +1,131 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-employee-list.vue b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-employee-list.vue new file mode 100644 index 0000000..d238a36 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-employee-list.vue @@ -0,0 +1,293 @@ + + + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-invoice-list.vue b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-invoice-list.vue new file mode 100644 index 0000000..b2e6029 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-invoice-list.vue @@ -0,0 +1,250 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-invoice-operate-modal.vue b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-invoice-operate-modal.vue new file mode 100644 index 0000000..f3c306f --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-invoice-operate-modal.vue @@ -0,0 +1,127 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-operate-modal.vue b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-operate-modal.vue new file mode 100644 index 0000000..f7b00da --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/components/enterprise-operate-modal.vue @@ -0,0 +1,267 @@ + + + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/enterprise-detail.vue b/smart-flow-web/src/views/business/oa/enterprise/enterprise-detail.vue new file mode 100644 index 0000000..92a9534 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/enterprise-detail.vue @@ -0,0 +1,134 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/enterprise/enterprise-list.vue b/smart-flow-web/src/views/business/oa/enterprise/enterprise-list.vue new file mode 100644 index 0000000..c945ca4 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/enterprise/enterprise-list.vue @@ -0,0 +1,285 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/leave/leave-approve-form.vue b/smart-flow-web/src/views/business/oa/leave/leave-approve-form.vue new file mode 100644 index 0000000..6dfa428 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/leave/leave-approve-form.vue @@ -0,0 +1,151 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/leave/leave-form.vue b/smart-flow-web/src/views/business/oa/leave/leave-form.vue new file mode 100644 index 0000000..2885c80 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/leave/leave-form.vue @@ -0,0 +1,194 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/leave/leave-list.vue b/smart-flow-web/src/views/business/oa/leave/leave-list.vue new file mode 100644 index 0000000..8166603 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/leave/leave-list.vue @@ -0,0 +1,325 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/notice/components/notice-approve-drawer.vue b/smart-flow-web/src/views/business/oa/notice/components/notice-approve-drawer.vue new file mode 100644 index 0000000..d903851 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/components/notice-approve-drawer.vue @@ -0,0 +1,340 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/components/notice-form-drawer.vue b/smart-flow-web/src/views/business/oa/notice/components/notice-form-drawer.vue new file mode 100644 index 0000000..a51fec4 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/components/notice-form-drawer.vue @@ -0,0 +1,371 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-modal.vue b/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-modal.vue new file mode 100644 index 0000000..bae638b --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-modal.vue @@ -0,0 +1,71 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-transfer-department.vue b/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-transfer-department.vue new file mode 100644 index 0000000..4d22b87 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-transfer-department.vue @@ -0,0 +1,204 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-transfer-employee.vue b/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-transfer-employee.vue new file mode 100644 index 0000000..7b6b7d3 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/components/notice-form-visible-transfer-employee.vue @@ -0,0 +1,252 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/components/notice-view-record-list.vue b/smart-flow-web/src/views/business/oa/notice/components/notice-view-record-list.vue new file mode 100644 index 0000000..de4eb52 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/components/notice-view-record-list.vue @@ -0,0 +1,161 @@ + + + diff --git a/smart-flow-web/src/views/business/oa/notice/notice-detail.vue b/smart-flow-web/src/views/business/oa/notice/notice-detail.vue new file mode 100644 index 0000000..cd9d82b --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/notice-detail.vue @@ -0,0 +1,144 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/notice-employee-detail.vue b/smart-flow-web/src/views/business/oa/notice/notice-employee-detail.vue new file mode 100644 index 0000000..cf65f43 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/notice-employee-detail.vue @@ -0,0 +1,145 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/notice-employee-list.vue b/smart-flow-web/src/views/business/oa/notice/notice-employee-list.vue new file mode 100644 index 0000000..2749e2e --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/notice-employee-list.vue @@ -0,0 +1,212 @@ + + + + + + diff --git a/smart-flow-web/src/views/business/oa/notice/notice-list.vue b/smart-flow-web/src/views/business/oa/notice/notice-list.vue new file mode 100644 index 0000000..02274a3 --- /dev/null +++ b/smart-flow-web/src/views/business/oa/notice/notice-list.vue @@ -0,0 +1,375 @@ + + + + + + + diff --git a/smart-flow-web/src/views/flow/components/department-mitt.js b/smart-flow-web/src/views/flow/components/department-mitt.js new file mode 100644 index 0000000..982f955 --- /dev/null +++ b/smart-flow-web/src/views/flow/components/department-mitt.js @@ -0,0 +1,11 @@ +/* + * 部门event bus + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-07-12 23:32:48 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import mitt from 'mitt'; +export default mitt(); diff --git a/smart-flow-web/src/views/flow/components/department-tree/index.vue b/smart-flow-web/src/views/flow/components/department-tree/index.vue new file mode 100644 index 0000000..0f2c42a --- /dev/null +++ b/smart-flow-web/src/views/flow/components/department-tree/index.vue @@ -0,0 +1,245 @@ + + + + diff --git a/smart-flow-web/src/views/flow/components/employee-list/index-1.vue b/smart-flow-web/src/views/flow/components/employee-list/index-1.vue new file mode 100644 index 0000000..d6f09d7 --- /dev/null +++ b/smart-flow-web/src/views/flow/components/employee-list/index-1.vue @@ -0,0 +1,268 @@ + + + + diff --git a/smart-flow-web/src/views/flow/components/employee-list/index.vue b/smart-flow-web/src/views/flow/components/employee-list/index.vue new file mode 100644 index 0000000..dacc516 --- /dev/null +++ b/smart-flow-web/src/views/flow/components/employee-list/index.vue @@ -0,0 +1,268 @@ + + + + diff --git a/smart-flow-web/src/views/flow/components/flow-done/index.vue b/smart-flow-web/src/views/flow/components/flow-done/index.vue new file mode 100644 index 0000000..d9e22ad --- /dev/null +++ b/smart-flow-web/src/views/flow/components/flow-done/index.vue @@ -0,0 +1,58 @@ + + \ No newline at end of file diff --git a/smart-flow-web/src/views/flow/components/select-user.vue b/smart-flow-web/src/views/flow/components/select-user.vue new file mode 100644 index 0000000..986caad --- /dev/null +++ b/smart-flow-web/src/views/flow/components/select-user.vue @@ -0,0 +1,106 @@ + + + + diff --git a/smart-flow-web/src/views/flow/definition/definition-form.vue b/smart-flow-web/src/views/flow/definition/definition-form.vue new file mode 100644 index 0000000..6f76776 --- /dev/null +++ b/smart-flow-web/src/views/flow/definition/definition-form.vue @@ -0,0 +1,262 @@ + + + + diff --git a/smart-flow-web/src/views/flow/definition/definition-list.vue b/smart-flow-web/src/views/flow/definition/definition-list.vue new file mode 100644 index 0000000..5d16800 --- /dev/null +++ b/smart-flow-web/src/views/flow/definition/definition-list.vue @@ -0,0 +1,591 @@ + + + + + + diff --git a/smart-flow-web/src/views/flow/task/done/index.vue b/smart-flow-web/src/views/flow/task/done/index.vue new file mode 100644 index 0000000..7b86788 --- /dev/null +++ b/smart-flow-web/src/views/flow/task/done/index.vue @@ -0,0 +1,256 @@ + + + diff --git a/smart-flow-web/src/views/system/home/home-notice.vue b/smart-flow-web/src/views/system/home/home-notice.vue new file mode 100644 index 0000000..47bd2bf --- /dev/null +++ b/smart-flow-web/src/views/system/home/home-notice.vue @@ -0,0 +1,121 @@ + + + + diff --git a/smart-flow-web/src/views/system/home/index.less b/smart-flow-web/src/views/system/home/index.less new file mode 100644 index 0000000..5996f4f --- /dev/null +++ b/smart-flow-web/src/views/system/home/index.less @@ -0,0 +1,65 @@ +.no-footer { + :deep(.ant-card-body) { + padding-bottom: 0; + } +} +.content { + height: 150px; + + &.large { + height: 360px; + } + + &.statistice { + display: flex; + flex-direction: column; + justify-content: space-between; + } + &.app { + display: flex; + align-items: center; + padding-bottom: 24px; + .app-qr { + display: flex; + align-items: center; + flex-direction: column; + margin-right: 40px; + > img { + height: 120px; + } + > span { + font-size: 14px; + } + } + } + + &.gauge { + display: flex; + align-items: center; + } + + &.wait-handle { + padding-bottom: 24px; + overflow-y: auto; + > p { + font-size: 18px; + } + :deep(.ant-tag) { + padding: 1px 8px; + font-size: 15px; + } + } + + .count { + font-size: 30px; + font-weight: 700; + margin-bottom: 10px; + } +} +.footer { + width: 100%; + border-top: 1px solid #e9e9e9; + padding: 10px 0; + background: #fff; + z-index: 1; +} diff --git a/smart-flow-web/src/views/system/home/index.vue b/smart-flow-web/src/views/system/home/index.vue new file mode 100644 index 0000000..13e0dbc --- /dev/null +++ b/smart-flow-web/src/views/system/home/index.vue @@ -0,0 +1,87 @@ + + + + diff --git a/smart-flow-web/src/views/system/login/login.less b/smart-flow-web/src/views/system/login/login.less new file mode 100644 index 0000000..f6f95fe --- /dev/null +++ b/smart-flow-web/src/views/system/login/login.less @@ -0,0 +1,214 @@ +.login-container { + width: 100%; + height: 100%; + background: url(/@/assets/images/login/login-bg.png) no-repeat center; + background-size: cover; + display: flex; + align-items: center; + justify-content: center; + .box-item { + width: 444px; + height: 600px; + &.desc { + background: #003b94; + border-radius: 12px 0px 0px 12px; + box-shadow: 0px 16px 73px 8px rgba(203, 203, 203, 0.2); + padding: 23px 25px; + } + &.login { + background: #ffffff; + border-radius: 0px 12px 12px 0px; + padding: 34px 42px; + position: relative; + border: solid 1px #efefef; + } + .login-qr { + position: absolute; + top: 0; + right: 0; + width: 66px; + height: 66px; + } + .logo { + width: 180px; + height: 42px; + align-self: start; + } + .welcome { + margin-top: 12px; + font-size: 26px; + font-weight: bold; + color: #ffffff; + p { + margin-bottom: 0; + } + .desc { + font-size: 15px; + font-weight: 500; + margin: 40px 0 60px 0; + line-height: 21px; + + .setence { + font-size: 13px; + // text-decoration: underline; + font-style: italic; + } + .author { + float: right; + font-size: 13px; + margin-top: 10px; + text-decoration: underline; + font-style: italic; + } + } + } + .app-qr-box { + display: flex; + align-items: center; + justify-content: space-around; + margin-top: 20px; + .app-qr { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + width: 50%; + > img { + width: 112px; + height: 112px; + } + + .qr-desc { + display: flex; + align-items: center; + margin-top: 11px; + font-size: 12px; + font-weight: 500; + text-align: center; + color: #ffffff; + > img { + width: 15px; + height: 18px; + margin-right: 9px; + } + } + + .qr-desc-marquee { + width: 100%; + display: flex; + align-items: center; + margin-top: 11px; + font-size: 12px; + font-weight: 500; + text-align: center; + color: #ffffff; + + @keyframes marquee { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(-30%); + } + } + + .marquee { + flex: 1; + overflow: hidden; + span { + display: inline-block; + width: 100%; + white-space: nowrap; + animation: marquee 5s linear infinite; + } + } + } + } + } + .login-title { + font-size: 30px; + font-weight: 700; + text-align: center; + color: #1e1e1e; + margin-bottom: 35px; + } + .login-form { + .captcha-input { + width: 60%; + } + + .captcha-img { + cursor: pointer; + } + } + .ant-input, + .ant-input-affix-wrapper { + height: 44px; + border: 1px solid #ededed; + border-radius: 4px; + } + + .code-btn{ + height: 44px; + padding: 4px 5px; + width: 108px; + } + + .eye-box { + position: absolute; + right: 15px; + top: 10px; + .eye-icon { + width: 20px; + height: 20px; + cursor: pointer; + } + } + .btn { + width: 350px; + height: 50px; + background: #1748FD; + border-radius: 4px; + font-size: 16px; + font-weight: 700; + text-align: center; + color: #ffffff; + line-height: 50px; + cursor: pointer; + } + } + + .more { + margin-top: 30px; + .title-box { + display: flex; + align-items: center; + justify-content: center; + > p { + margin-bottom: 0; + } + } + .line { + width: 114px; + height: 1px; + background: #e6e6e6; + } + .title { + font-size: 14px; + font-weight: 500; + color: #a1aebe; + margin: 0 19px; + } + .login-type { + padding: 0 5px; + margin-top: 25px; + display: flex; + align-items: center; + justify-content: space-between; + > img { + width: 30px; + height: 30px; + } + } + } +} diff --git a/smart-flow-web/src/views/system/login/login.vue b/smart-flow-web/src/views/system/login/login.vue new file mode 100644 index 0000000..0dd8efa --- /dev/null +++ b/smart-flow-web/src/views/system/login/login.vue @@ -0,0 +1,285 @@ + + + + diff --git a/smart-flow-web/src/views/system/login2/login.less b/smart-flow-web/src/views/system/login2/login.less new file mode 100644 index 0000000..f3d17ac --- /dev/null +++ b/smart-flow-web/src/views/system/login2/login.less @@ -0,0 +1,201 @@ +.login-container { + width: 100%; + height: 100%; + background: url(/@/assets/images/login/login-bg.png) no-repeat center; + background-size: cover; + display: flex; + align-items: center; + justify-content: center; + .box-item { + width: 444px; + height: 600px; + &.desc { + background: #ffffff; + border-radius: 12px 0px 0px 12px; + box-shadow: 0px 16px 73px 8px rgba(203, 203, 203, 0.2); + padding: 23px 25px; + } + &.login { + background: #ffffff; + border-radius: 0px 12px 12px 0px; + padding: 34px 42px; + position: relative; + } + .login-qr { + position: absolute; + top: 0; + right: 0; + width: 66px; + height: 66px; + } + .welcome { + background: url(/@/assets/images/login/left-bg1.png) no-repeat center; + background-size: cover; + height: 100%; + border-radius: 8px; + box-shadow: 0px 6px 20px 0px rgba(33,47,117,0.10); + padding-top: 35px; + p{ + color: #333333; + line-height: 25px; + letter-spacing: 0.26px; + text-align: center; + font-weight: 700; + font-size: 26px; + } + .sub-welcome{ + color: #333333; + line-height: 25px; + letter-spacing: 0.26px; + font-weight: 700; + font-size: 20px; + } + } + .app-qr-box { + display: flex; + align-items: center; + justify-content: space-around; + margin-top: 20px; + .app-qr { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + width: 50%; + > img { + width: 112px; + height: 112px; + } + + .qr-desc { + display: flex; + align-items: center; + margin-top: 11px; + font-size: 12px; + font-weight: 500; + text-align: center; + color: #ffffff; + > img { + width: 15px; + height: 18px; + margin-right: 9px; + } + } + + .qr-desc-marquee { + width: 100%; + display: flex; + align-items: center; + margin-top: 11px; + font-size: 12px; + font-weight: 500; + text-align: center; + color: #ffffff; + + @keyframes marquee { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(-30%); + } + } + + .marquee { + flex: 1; + overflow: hidden; + span { + display: inline-block; + width: 100%; + white-space: nowrap; + animation: marquee 5s linear infinite; + } + } + } + } + } + .login-title { + font-size: 20px; + text-align: center; + color: #1e1e1e; + margin-bottom: 35px; + } + .login-form { + .captcha-input { + width: 60%; + } + + .captcha-img { + cursor: pointer; + } + } + .ant-input, + .ant-input-affix-wrapper { + height: 44px; + border: 1px solid #ededed; + border-radius: 4px; + } + .code-btn{ + height: 44px; + padding: 4px 5px; + width: 108px; + } + + .eye-box { + position: absolute; + right: 15px; + top: 10px; + .eye-icon { + width: 20px; + height: 20px; + cursor: pointer; + } + } + .btn { + width: 350px; + height: 50px; + background: #1748FD; + border-radius: 4px; + font-size: 16px; + font-weight: 700; + text-align: center; + color: #ffffff; + line-height: 50px; + cursor: pointer; + } + } + + .more { + margin-top: 30px; + .title-box { + display: flex; + align-items: center; + justify-content: center; + > p { + margin-bottom: 0; + } + } + .line { + width: 114px; + height: 1px; + background: #e6e6e6; + } + .title { + font-size: 14px; + font-weight: 500; + color: #a1aebe; + margin: 0 19px; + } + .login-type { + padding: 0 5px; + margin-top: 25px; + display: flex; + align-items: center; + justify-content: space-between; + > img { + width: 30px; + height: 30px; + } + } + } +} diff --git a/smart-flow-web/src/views/system/login2/login.vue b/smart-flow-web/src/views/system/login2/login.vue new file mode 100644 index 0000000..69240dc --- /dev/null +++ b/smart-flow-web/src/views/system/login2/login.vue @@ -0,0 +1,246 @@ + + + + diff --git a/smart-flow-web/src/views/system/login3/login.less b/smart-flow-web/src/views/system/login3/login.less new file mode 100644 index 0000000..580bbba --- /dev/null +++ b/smart-flow-web/src/views/system/login3/login.less @@ -0,0 +1,208 @@ +.login-container { + width: 100%; + height: 100%; + background: url(/@/assets/images/login/login-bg.png) no-repeat center; + background-size: cover; + display: flex; + align-items: center; + justify-content: center; + .box-item { + width: 460px; + height: 600px; + &.desc { + background: #ffffff; + border-radius: 12px 0px 0px 12px; + box-shadow: 0px 16px 73px 8px rgba(203, 203, 203, 0.2); + padding: 23px 25px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: flex-start; + } + &.login { + background: #ffffff; + border-radius: 0px 12px 12px 0px; + padding: 34px 42px; + position: relative; + } + .login-qr { + position: absolute; + top: 0; + right: 0; + width: 66px; + height: 66px; + } + .welcome { + padding-top: 35px; + p{ + color: #333333; + line-height: 25px; + letter-spacing: 0.26px; + text-align: center; + font-weight: 700; + font-size: 26px; + } + .sub-welcome{ + padding: 10px; + font-size: 18px; + font-weight: 700; + text-align: center; + color: #ffffff; + line-height: 25px; + letter-spacing: 0.26px; + opacity: 0.96; + background: #1748fd; + border-radius: 22px 22px 2px 22px; + } + } + .welcome-img{ + width: 350px; + height: 350px; + } + .app-qr-box { + display: flex; + align-items: center; + justify-content: space-around; + margin-top: 20px; + .app-qr { + display: flex; + align-items: center; + justify-content: center; + flex-direction: column; + width: 50%; + > img { + width: 112px; + height: 112px; + } + + .qr-desc { + display: flex; + align-items: center; + margin-top: 11px; + font-size: 12px; + font-weight: 500; + text-align: center; + color: #ffffff; + > img { + width: 15px; + height: 18px; + margin-right: 9px; + } + } + + .qr-desc-marquee { + width: 100%; + display: flex; + align-items: center; + margin-top: 11px; + font-size: 12px; + font-weight: 500; + text-align: center; + color: #ffffff; + + @keyframes marquee { + 0% { + transform: translateX(0); + } + 100% { + transform: translateX(-30%); + } + } + + .marquee { + flex: 1; + overflow: hidden; + span { + display: inline-block; + width: 100%; + white-space: nowrap; + animation: marquee 5s linear infinite; + } + } + } + } + } + .login-title { + font-size: 20px; + text-align: center; + color: #1e1e1e; + margin-bottom: 35px; + } + .login-form { + .captcha-input { + width: 60%; + } + + .captcha-img { + cursor: pointer; + } + } + .ant-input, + .ant-input-affix-wrapper { + height: 44px; + border: 1px solid #ededed; + border-radius: 4px; + } + .code-btn{ + height: 44px; + padding: 4px 5px; + width: 108px; + } + .eye-box { + position: absolute; + right: 15px; + top: 10px; + .eye-icon { + width: 20px; + height: 20px; + cursor: pointer; + } + } + .btn { + width: 350px; + height: 50px; + background: #1748FD; + border-radius: 4px; + font-size: 16px; + font-weight: 700; + text-align: center; + color: #ffffff; + line-height: 50px; + cursor: pointer; + } + } + + .more { + margin-top: 30px; + .title-box { + display: flex; + align-items: center; + justify-content: center; + > p { + margin-bottom: 0; + } + } + .line { + width: 114px; + height: 1px; + background: #e6e6e6; + } + .title { + font-size: 14px; + font-weight: 500; + color: #a1aebe; + margin: 0 19px; + } + .login-type { + padding: 0 5px; + margin-top: 25px; + display: flex; + align-items: center; + justify-content: space-between; + > img { + width: 30px; + height: 30px; + } + } + } +} diff --git a/smart-flow-web/src/views/system/login3/login.vue b/smart-flow-web/src/views/system/login3/login.vue new file mode 100644 index 0000000..b1504fa --- /dev/null +++ b/smart-flow-web/src/views/system/login3/login.vue @@ -0,0 +1,249 @@ + + + + diff --git a/smart-flow-web/src/views/system/menu/components/menu-operate-modal.vue b/smart-flow-web/src/views/system/menu/components/menu-operate-modal.vue new file mode 100644 index 0000000..d87d338 --- /dev/null +++ b/smart-flow-web/src/views/system/menu/components/menu-operate-modal.vue @@ -0,0 +1,297 @@ + + + + diff --git a/smart-flow-web/src/views/system/menu/components/menu-tree-select.vue b/smart-flow-web/src/views/system/menu/components/menu-tree-select.vue new file mode 100644 index 0000000..15f15c8 --- /dev/null +++ b/smart-flow-web/src/views/system/menu/components/menu-tree-select.vue @@ -0,0 +1,49 @@ + + + diff --git a/smart-flow-web/src/views/system/menu/menu-data-handler.js b/smart-flow-web/src/views/system/menu/menu-data-handler.js new file mode 100644 index 0000000..2aadb7b --- /dev/null +++ b/smart-flow-web/src/views/system/menu/menu-data-handler.js @@ -0,0 +1,151 @@ +/* + * 此文件是处理 菜单数据的类,主要用于: + * 1、菜单树形表格的构造 + * 2、菜单的前端过滤 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-06-15 16:47:20 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ + +import _ from 'lodash'; +/** + * 过滤菜单 + * @param {*} menuList + * @param {*} queryForm + * @returns + */ +export const filterMenuByQueryForm = (menuList, queryForm) => { + if (!menuList || menuList.length === 0) { + return []; + } + + let filterResult = []; + for (const menu of menuList) { + if (isMenuExistKeywords(menu, queryForm.keywords) && isMenuExistMenuType(menu, queryForm.menuType) && isMenuExistMenuFlag(menu, queryForm)) { + filterResult.push(menu); + } + } + return filterResult; +}; + +/** + * 构建菜单表格树形数据 + */ +export const buildMenuTableTree = (menuList) => { + let topMenuList = []; + const menuIdSet = new Set(); + for (const menu of menuList) { + menuIdSet.add(menu.menuId); + } + + for (const menu of menuList) { + const parentId = menu.parentId; + // 不存在父节点,则为顶级菜单 + if (!menuIdSet.has(parentId)) { + topMenuList.push(menu); + } + } + + recursiveMenuTree(menuList, topMenuList); + return topMenuList; +}; + +/** + * 递归遍历菜单树形数据 + * @param {*} menuList + * @param {*} parentArray + */ +function recursiveMenuTree(menuList, parentArray) { + for (const parent of parentArray) { + const children = menuList.filter((e) => e.parentId === parent.menuId); + if (children.length > 0) { + parent.children = children; + recursiveMenuTree(menuList, parent.children); + } + } +} + +/** + * 过滤菜单状态 + * @param {*} menu + * @param {*} queryForm + * @returns + */ +function isMenuExistMenuFlag(menu, queryForm) { + let frameFlagCondition = false; + if (!_.isNil(queryForm.frameFlag)) { + frameFlagCondition = !_.isNil(menu.frameFlag) && menu.frameFlag === (queryForm.frameFlag === 1); + } else { + frameFlagCondition = true; + } + + let cacheFlagCondition = false; + if (!_.isNil(queryForm.cacheFlag)) { + cacheFlagCondition = !_.isNil(menu.cacheFlag) && menu.cacheFlag === (queryForm.cacheFlag === 1); + } else { + cacheFlagCondition = true; + } + + let visibleFlagCondition = false; + if (!_.isNil(queryForm.visibleFlag)) { + visibleFlagCondition = !_.isNil(menu.visibleFlag) && menu.visibleFlag === (queryForm.visibleFlag === 1); + } else { + visibleFlagCondition = true; + } + + let disabledFlagCondition = false; + if (!_.isNil(queryForm.disabledFlag)) { + disabledFlagCondition = !_.isNil(menu.disabledFlag) && menu.disabledFlag === (queryForm.disabledFlag === 1); + } else { + disabledFlagCondition = true; + } + + return frameFlagCondition && cacheFlagCondition && visibleFlagCondition && disabledFlagCondition; +} + +/** + * 过滤菜单类型 + * @param {*} menu + * @param {*} menuType + * @returns + */ +function isMenuExistMenuType(menu, menuType) { + if (!menuType) { + return true; + } + + if (menu.menuType && menu.menuType === menuType) { + return true; + } + return false; +} + +/** + * 过滤关键字 + */ +function isMenuExistKeywords(menu, keywords) { + if (!keywords) { + return true; + } + + if (menu.component && menu.component.indexOf(keywords) > -1) { + return true; + } + + if (menu.menuName && menu.menuName.indexOf(keywords) > -1) { + return true; + } + if (menu.path && menu.path.indexOf(keywords) > -1) { + return true; + } + if (menu.apiPerms && menu.apiPerms.indexOf(keywords) > -1) { + return true; + } + if (menu.webPerms && menu.webPerms.indexOf(keywords) > -1) { + return true; + } + return false; +} diff --git a/smart-flow-web/src/views/system/menu/menu-list-table-columns.js b/smart-flow-web/src/views/system/menu/menu-list-table-columns.js new file mode 100644 index 0000000..effc5ad --- /dev/null +++ b/smart-flow-web/src/views/system/menu/menu-list-table-columns.js @@ -0,0 +1,60 @@ +/* + * 菜单表格列 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-05-12 19:46:11 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { ref } from 'vue'; +export const columns = ref([ + { + title: '名称', + dataIndex: 'menuName', + key: 'ID', + width: 220, + }, + { + title: '类型', + dataIndex: 'menuType', + width: 100, + align: "center" + }, + { + title: '图标', + dataIndex: 'icon', + width: 50, + }, + { + title: '路径', + dataIndex: 'path', + ellipsis: true, + }, + { + title: '组件', + dataIndex: 'component', + ellipsis: true, + }, + { + title: '后端权限', + dataIndex: 'apiPerms', + ellipsis: true, + }, + { + title: '前端权限', + dataIndex: 'webPerms', + ellipsis: true, + }, + { + title: '顺序', + dataIndex: 'sort', + width: 80, + }, + { + title: '操作', + dataIndex: 'operate', + width: 170, + align: "center" + }, +]); diff --git a/smart-flow-web/src/views/system/menu/menu-list.vue b/smart-flow-web/src/views/system/menu/menu-list.vue new file mode 100644 index 0000000..e1aca08 --- /dev/null +++ b/smart-flow-web/src/views/system/menu/menu-list.vue @@ -0,0 +1,278 @@ + + + diff --git a/smart-flow-web/src/views/system/position/position-form.vue b/smart-flow-web/src/views/system/position/position-form.vue new file mode 100644 index 0000000..4d77921 --- /dev/null +++ b/smart-flow-web/src/views/system/position/position-form.vue @@ -0,0 +1,138 @@ + + + diff --git a/smart-flow-web/src/views/system/position/position-list.vue b/smart-flow-web/src/views/system/position/position-list.vue new file mode 100644 index 0000000..f7b0c44 --- /dev/null +++ b/smart-flow-web/src/views/system/position/position-list.vue @@ -0,0 +1,262 @@ + + + diff --git a/smart-flow-web/src/views/system/role/components/role-data-scope/index.vue b/smart-flow-web/src/views/system/role/components/role-data-scope/index.vue new file mode 100644 index 0000000..5280dd8 --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-data-scope/index.vue @@ -0,0 +1,157 @@ + + + + diff --git a/smart-flow-web/src/views/system/role/components/role-employee-list/index.vue b/smart-flow-web/src/views/system/role/components/role-employee-list/index.vue new file mode 100644 index 0000000..6a7b93d --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-employee-list/index.vue @@ -0,0 +1,274 @@ + + + + + diff --git a/smart-flow-web/src/views/system/role/components/role-form-modal/index.vue b/smart-flow-web/src/views/system/role/components/role-form-modal/index.vue new file mode 100644 index 0000000..aa19737 --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-form-modal/index.vue @@ -0,0 +1,116 @@ + + + + + + diff --git a/smart-flow-web/src/views/system/role/components/role-list/index.vue b/smart-flow-web/src/views/system/role/components/role-list/index.vue new file mode 100644 index 0000000..8c97c16 --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-list/index.vue @@ -0,0 +1,116 @@ + + + + diff --git a/smart-flow-web/src/views/system/role/components/role-setting/index.vue b/smart-flow-web/src/views/system/role/components/role-setting/index.vue new file mode 100644 index 0000000..31c16db --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-setting/index.vue @@ -0,0 +1,44 @@ + + + + diff --git a/smart-flow-web/src/views/system/role/components/role-tree/index.less b/smart-flow-web/src/views/system/role/components/role-tree/index.less new file mode 100644 index 0000000..680af9f --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-tree/index.less @@ -0,0 +1,78 @@ +:deep(.ant-checkbox-group) { + width: 100%; +} +.tree-header { + display: flex; + align-items: center; + justify-content: space-between; + margin: 20px 0; +} +.col-desc { + margin: 20px 0; + font-size: 15px; + color: #95a5a6; + padding: 0 20px; +} +.button-style { + margin: 20px 0 20px 0; + padding-left: 20px; + text-align: right; +} +.check-right { + margin-right: 20px; +} +.row-border { + border: 1px solid #f0f0f0; +} +.col-border { + line-height: 50px; + padding-left: 20px; + border-right: 1px solid #f0f0f0; +} +.col-left { + line-height: 50px; + padding-left: 40px; + border-right: 1px solid #f0f0f0; +} +.col-right { + padding-left: 20px; + border-right: 1px solid #f0f0f0; +} +.checked-box { + padding: 0 15px; + :deep(ul li::marker) { + content: ''; + } + :deep(ul) { + padding: 0; + margin: 0; + + li { + list-style: none; + padding: 0; + margin: 10px 0; + + .menu { + border-bottom: 1px solid rgb(240, 240, 240); + display: flex; + align-items: center; + line-height: 25px; + } + + .point { + display: flex; + align-items: center; + + .point-label { + flex: 1; + padding-left: 40px; + border-left: 1px rgb(240, 240, 240) solid; + } + } + + .checked-box-label { + min-width: 150px; + } + } + } +} diff --git a/smart-flow-web/src/views/system/role/components/role-tree/index.vue b/smart-flow-web/src/views/system/role/components/role-tree/index.vue new file mode 100644 index 0000000..5f05d85 --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-tree/index.vue @@ -0,0 +1,74 @@ + + + + diff --git a/smart-flow-web/src/views/system/role/components/role-tree/role-tree-checkbox.vue b/smart-flow-web/src/views/system/role/components/role-tree/role-tree-checkbox.vue new file mode 100644 index 0000000..c253a88 --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-tree/role-tree-checkbox.vue @@ -0,0 +1,49 @@ + + + + diff --git a/smart-flow-web/src/views/system/role/components/role-tree/role-tree-menu.vue b/smart-flow-web/src/views/system/role/components/role-tree/role-tree-menu.vue new file mode 100644 index 0000000..4f3bc74 --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-tree/role-tree-menu.vue @@ -0,0 +1,64 @@ + + + diff --git a/smart-flow-web/src/views/system/role/components/role-tree/role-tree-point.vue b/smart-flow-web/src/views/system/role/components/role-tree/role-tree-point.vue new file mode 100644 index 0000000..ace0a5a --- /dev/null +++ b/smart-flow-web/src/views/system/role/components/role-tree/role-tree-point.vue @@ -0,0 +1,33 @@ + + + + diff --git a/smart-flow-web/src/views/system/role/index.vue b/smart-flow-web/src/views/system/role/index.vue new file mode 100644 index 0000000..3666cc6 --- /dev/null +++ b/smart-flow-web/src/views/system/role/index.vue @@ -0,0 +1,48 @@ + + + + diff --git a/smart-flow-web/vite.config.js b/smart-flow-web/vite.config.js new file mode 100644 index 0000000..a9eeaa3 --- /dev/null +++ b/smart-flow-web/vite.config.js @@ -0,0 +1,90 @@ +/* + * vite配置 + * + * @Author: 1024创新实验室-主任:卓大 + * @Date: 2022-05-02 23:44:56 + * @Wechat: zhuda1024 + * @Email: lab1024@163.com + * @Copyright 1024创新实验室 ( https://1024lab.net ),Since 2012 + */ +import { resolve } from 'path'; +import vue from '@vitejs/plugin-vue'; +import customVariables from '/@/theme/custom-variables.js'; + +const pathResolve = (dir) => { + return resolve(__dirname, '.', dir); +}; +export default { + base: process.env.NODE_ENV === 'production' ? '/' : '/', + root: process.cwd(), + resolve: { + alias: [ + // 国际化替换 + { + find: 'vue-i18n', + replacement: 'vue-i18n/dist/vue-i18n.cjs.js', + }, + // 绝对路径重命名:/@/xxxx => src/xxxx + { + find: /\/@\//, + replacement: pathResolve('src') + '/', + }, + { + find: /^~/, + replacement: '', + }, + ], + }, + // 服务端渲染 + server: { + host: '0.0.0.0', + port: 8181, + }, + plugins: [vue()], + optimizeDeps: { + include: ['ant-design-vue/es/locale/zh_CN', 'dayjs/locale/zh-cn', 'ant-design-vue/es/locale/en_US'], + exclude: ['vue-demi'], + }, + build: { + // 清除console和debugger + terserOptions: { + compress: { + drop_console: true, + drop_debugger: true, + }, + }, + rollupOptions: { + output: { + //配置这个是让不同类型文件放在不同文件夹,不会显得太乱 + chunkFileNames: 'js/[name]-[hash].js', + entryFileNames: 'js/[name]-[hash].js', + assetFileNames: '[ext]/[name]-[hash].[ext]', + manualChunks(id) { + //静态资源分拆打包 + if (id.includes('node_modules')) { + return id.toString().split('node_modules/')[1].split('/')[0].toString(); + } + }, + }, + }, + target: 'modules', + outDir: 'dist', // 指定输出路径 + assetsDir: 'assets', // 指定生成静态文件目录 + assetsInlineLimit: '4096', // 小于此阈值的导入或引用资源将内联为 base64 编码 + chunkSizeWarningLimit: 500, // chunk 大小警告的限制 + minify: 'terser', // 混淆器,terser构建后文件体积更小 + emptyOutDir: true, //打包前先清空原有打包文件 + }, + css: { + preprocessorOptions: { + less: { + modifyVars: customVariables, + javascriptEnabled: true, + }, + }, + }, + define: { + __INTLIFY_PROD_DEVTOOLS__: false, + 'process.env': process.env, + }, +}; diff --git a/smart-flow-web/vite.config.js.timestamp-1748825926850-419454ebc4df4.mjs b/smart-flow-web/vite.config.js.timestamp-1748825926850-419454ebc4df4.mjs new file mode 100644 index 0000000..7bf316b --- /dev/null +++ b/smart-flow-web/vite.config.js.timestamp-1748825926850-419454ebc4df4.mjs @@ -0,0 +1,111 @@ +// vite.config.js +import { resolve } from "path"; +import vue from "file:///D:/dev/flow/smart-flow/smart-flow-web/node_modules/@vitejs/plugin-vue/dist/index.mjs"; + +// src/theme/custom-variables.js +import { theme } from "file:///D:/dev/flow/smart-flow/smart-flow-web/node_modules/ant-design-vue/lib/index.js"; +import convertLegacyToken from "file:///D:/dev/flow/smart-flow/smart-flow-web/node_modules/ant-design-vue/lib/theme/convertLegacyToken.js"; +var { defaultAlgorithm, defaultSeed } = theme; +var mapToken = defaultAlgorithm(defaultSeed); +var token = convertLegacyToken.default(mapToken); +var custom_variables_default = { + "@primary-color": token["primary-color"], + // 全局主色 + "@base-bg-color": "#fff", + "@hover-bg-color": "rgba(0, 0, 0, 0.025)", + "@hover-bg-color-night": "rgba(255, 255, 255, 0.025)", + "@header-light-bg-hover-color": "#f6f6f6", + "@header-height": "80px", + "@header-user-height": "40px", + "@page-tag-height": "40px", + "@theme-list": ["light", "dark", "night"] +}; + +// vite.config.js +var __vite_injected_original_dirname = "D:\\dev\\flow\\smart-flow\\smart-flow-web"; +var pathResolve = (dir) => { + return resolve(__vite_injected_original_dirname, ".", dir); +}; +var vite_config_default = { + base: process.env.NODE_ENV === "production" ? "/" : "/", + root: process.cwd(), + resolve: { + alias: [ + // 国际化替换 + { + find: "vue-i18n", + replacement: "vue-i18n/dist/vue-i18n.cjs.js" + }, + // 绝对路径重命名:/@/xxxx => src/xxxx + { + find: /\/@\//, + replacement: pathResolve("src") + "/" + }, + { + find: /^~/, + replacement: "" + } + ] + }, + // 服务端渲染 + server: { + host: "0.0.0.0", + port: 8181 + }, + plugins: [vue()], + optimizeDeps: { + include: ["ant-design-vue/es/locale/zh_CN", "dayjs/locale/zh-cn", "ant-design-vue/es/locale/en_US"], + exclude: ["vue-demi"] + }, + build: { + // 清除console和debugger + terserOptions: { + compress: { + drop_console: true, + drop_debugger: true + } + }, + rollupOptions: { + output: { + //配置这个是让不同类型文件放在不同文件夹,不会显得太乱 + chunkFileNames: "js/[name]-[hash].js", + entryFileNames: "js/[name]-[hash].js", + assetFileNames: "[ext]/[name]-[hash].[ext]", + manualChunks(id) { + if (id.includes("node_modules")) { + return id.toString().split("node_modules/")[1].split("/")[0].toString(); + } + } + } + }, + target: "modules", + outDir: "dist", + // 指定输出路径 + assetsDir: "assets", + // 指定生成静态文件目录 + assetsInlineLimit: "4096", + // 小于此阈值的导入或引用资源将内联为 base64 编码 + chunkSizeWarningLimit: 500, + // chunk 大小警告的限制 + minify: "terser", + // 混淆器,terser构建后文件体积更小 + emptyOutDir: true + //打包前先清空原有打包文件 + }, + css: { + preprocessorOptions: { + less: { + modifyVars: custom_variables_default, + javascriptEnabled: true + } + } + }, + define: { + __INTLIFY_PROD_DEVTOOLS__: false, + "process.env": process.env + } +}; +export { + vite_config_default as default +}; +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsidml0ZS5jb25maWcuanMiLCAic3JjL3RoZW1lL2N1c3RvbS12YXJpYWJsZXMuanMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImNvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9kaXJuYW1lID0gXCJEOlxcXFxkZXZcXFxcZmxvd1xcXFxzbWFydC1mbG93XFxcXHNtYXJ0LWZsb3ctd2ViXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCJEOlxcXFxkZXZcXFxcZmxvd1xcXFxzbWFydC1mbG93XFxcXHNtYXJ0LWZsb3ctd2ViXFxcXHZpdGUuY29uZmlnLmpzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9EOi9kZXYvZmxvdy9zbWFydC1mbG93L3NtYXJ0LWZsb3ctd2ViL3ZpdGUuY29uZmlnLmpzXCI7LypcclxuICogdml0ZVx1OTE0RFx1N0Y2RVxyXG4gKlxyXG4gKiBAQXV0aG9yOiAgICAxMDI0XHU1MjFCXHU2NUIwXHU1QjlFXHU5QThDXHU1QkE0LVx1NEUzQlx1NEVGQlx1RkYxQVx1NTM1M1x1NTkyN1xyXG4gKiBARGF0ZTogICAgICAyMDIyLTA1LTAyIDIzOjQ0OjU2XHJcbiAqIEBXZWNoYXQ6ICAgIHpodWRhMTAyNFxyXG4gKiBARW1haWw6ICAgICBsYWIxMDI0QDE2My5jb21cclxuICogQENvcHlyaWdodCAgMTAyNFx1NTIxQlx1NjVCMFx1NUI5RVx1OUE4Q1x1NUJBNCBcdUZGMDggaHR0cHM6Ly8xMDI0bGFiLm5ldCBcdUZGMDlcdUZGMENTaW5jZSAyMDEyXHJcbiAqL1xyXG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSAncGF0aCc7XHJcbmltcG9ydCB2dWUgZnJvbSAnQHZpdGVqcy9wbHVnaW4tdnVlJztcclxuaW1wb3J0IGN1c3RvbVZhcmlhYmxlcyBmcm9tICcvQC90aGVtZS9jdXN0b20tdmFyaWFibGVzLmpzJztcclxuXHJcbmNvbnN0IHBhdGhSZXNvbHZlID0gKGRpcikgPT4ge1xyXG4gIHJldHVybiByZXNvbHZlKF9fZGlybmFtZSwgJy4nLCBkaXIpO1xyXG59O1xyXG5leHBvcnQgZGVmYXVsdCB7XHJcbiAgYmFzZTogcHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdwcm9kdWN0aW9uJyA/ICcvJyA6ICcvJyxcclxuICByb290OiBwcm9jZXNzLmN3ZCgpLFxyXG4gIHJlc29sdmU6IHtcclxuICAgIGFsaWFzOiBbXHJcbiAgICAgIC8vIFx1NTZGRFx1OTY0NVx1NTMxNlx1NjZGRlx1NjM2MlxyXG4gICAgICB7XHJcbiAgICAgICAgZmluZDogJ3Z1ZS1pMThuJyxcclxuICAgICAgICByZXBsYWNlbWVudDogJ3Z1ZS1pMThuL2Rpc3QvdnVlLWkxOG4uY2pzLmpzJyxcclxuICAgICAgfSxcclxuICAgICAgLy8gXHU3RUREXHU1QkY5XHU4REVGXHU1Rjg0XHU5MUNEXHU1NDdEXHU1NDBEXHVGRjFBL0AveHh4eCA9PiBzcmMveHh4eFxyXG4gICAgICB7XHJcbiAgICAgICAgZmluZDogL1xcL0BcXC8vLFxyXG4gICAgICAgIHJlcGxhY2VtZW50OiBwYXRoUmVzb2x2ZSgnc3JjJykgKyAnLycsXHJcbiAgICAgIH0sXHJcbiAgICAgIHtcclxuICAgICAgICBmaW5kOiAvXn4vLFxyXG4gICAgICAgIHJlcGxhY2VtZW50OiAnJyxcclxuICAgICAgfSxcclxuICAgIF0sXHJcbiAgfSxcclxuICAvLyBcdTY3MERcdTUyQTFcdTdBRUZcdTZFMzJcdTY3RDNcclxuICBzZXJ2ZXI6IHtcclxuICAgIGhvc3Q6ICcwLjAuMC4wJyxcclxuICAgIHBvcnQ6IDgxODEsXHJcbiAgfSxcclxuICBwbHVnaW5zOiBbdnVlKCldLFxyXG4gIG9wdGltaXplRGVwczoge1xyXG4gICAgaW5jbHVkZTogWydhbnQtZGVzaWduLXZ1ZS9lcy9sb2NhbGUvemhfQ04nLCAnZGF5anMvbG9jYWxlL3poLWNuJywgJ2FudC1kZXNpZ24tdnVlL2VzL2xvY2FsZS9lbl9VUyddLFxyXG4gICAgZXhjbHVkZTogWyd2dWUtZGVtaSddLFxyXG4gIH0sXHJcbiAgYnVpbGQ6IHtcclxuICAgIC8vIFx1NkUwNVx1OTY2NGNvbnNvbGVcdTU0OENkZWJ1Z2dlclxyXG4gICAgdGVyc2VyT3B0aW9uczoge1xyXG4gICAgICBjb21wcmVzczoge1xyXG4gICAgICAgIGRyb3BfY29uc29sZTogdHJ1ZSxcclxuICAgICAgICBkcm9wX2RlYnVnZ2VyOiB0cnVlLFxyXG4gICAgICB9LFxyXG4gICAgfSxcclxuICAgIHJvbGx1cE9wdGlvbnM6IHtcclxuICAgICAgb3V0cHV0OiB7XHJcbiAgICAgICAgLy9cdTkxNERcdTdGNkVcdThGRDlcdTRFMkFcdTY2MkZcdThCQTlcdTRFMERcdTU0MENcdTdDN0JcdTU3OEJcdTY1ODdcdTRFRjZcdTY1M0VcdTU3MjhcdTRFMERcdTU0MENcdTY1ODdcdTRFRjZcdTU5MzlcdUZGMENcdTRFMERcdTRGMUFcdTY2M0VcdTVGOTdcdTU5MkFcdTRFNzFcclxuICAgICAgICBjaHVua0ZpbGVOYW1lczogJ2pzL1tuYW1lXS1baGFzaF0uanMnLFxyXG4gICAgICAgIGVudHJ5RmlsZU5hbWVzOiAnanMvW25hbWVdLVtoYXNoXS5qcycsXHJcbiAgICAgICAgYXNzZXRGaWxlTmFtZXM6ICdbZXh0XS9bbmFtZV0tW2hhc2hdLltleHRdJyxcclxuICAgICAgICBtYW51YWxDaHVua3MoaWQpIHtcclxuICAgICAgICAgIC8vXHU5NzU5XHU2MDAxXHU4RDQ0XHU2RTkwXHU1MjA2XHU2MkM2XHU2MjUzXHU1MzA1XHJcbiAgICAgICAgICBpZiAoaWQuaW5jbHVkZXMoJ25vZGVfbW9kdWxlcycpKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBpZC50b1N0cmluZygpLnNwbGl0KCdub2RlX21vZHVsZXMvJylbMV0uc3BsaXQoJy8nKVswXS50b1N0cmluZygpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0sXHJcbiAgICAgIH0sXHJcbiAgICB9LFxyXG4gICAgdGFyZ2V0OiAnbW9kdWxlcycsXHJcbiAgICBvdXREaXI6ICdkaXN0JywgLy8gXHU2MzA3XHU1QjlBXHU4RjkzXHU1MUZBXHU4REVGXHU1Rjg0XHJcbiAgICBhc3NldHNEaXI6ICdhc3NldHMnLCAvLyBcdTYzMDdcdTVCOUFcdTc1MUZcdTYyMTBcdTk3NTlcdTYwMDFcdTY1ODdcdTRFRjZcdTc2RUVcdTVGNTVcclxuICAgIGFzc2V0c0lubGluZUxpbWl0OiAnNDA5NicsIC8vIFx1NUMwRlx1NEU4RVx1NkI2NFx1OTYwOFx1NTAzQ1x1NzY4NFx1NUJGQ1x1NTE2NVx1NjIxNlx1NUYxNVx1NzUyOFx1OEQ0NFx1NkU5MFx1NUMwNlx1NTE4NVx1ODA1NFx1NEUzQSBiYXNlNjQgXHU3RjE2XHU3ODAxXHJcbiAgICBjaHVua1NpemVXYXJuaW5nTGltaXQ6IDUwMCwgLy8gY2h1bmsgXHU1OTI3XHU1QzBGXHU4QjY2XHU1NDRBXHU3Njg0XHU5NjUwXHU1MjM2XHJcbiAgICBtaW5pZnk6ICd0ZXJzZXInLCAvLyBcdTZERjdcdTZEQzZcdTU2NjhcdUZGMEN0ZXJzZXJcdTY3ODRcdTVFRkFcdTU0MEVcdTY1ODdcdTRFRjZcdTRGNTNcdTc5RUZcdTY2RjRcdTVDMEZcclxuICAgIGVtcHR5T3V0RGlyOiB0cnVlLCAvL1x1NjI1M1x1NTMwNVx1NTI0RFx1NTE0OFx1NkUwNVx1N0E3QVx1NTM5Rlx1NjcwOVx1NjI1M1x1NTMwNVx1NjU4N1x1NEVGNlxyXG4gIH0sXHJcbiAgY3NzOiB7XHJcbiAgICBwcmVwcm9jZXNzb3JPcHRpb25zOiB7XHJcbiAgICAgIGxlc3M6IHtcclxuICAgICAgICBtb2RpZnlWYXJzOiBjdXN0b21WYXJpYWJsZXMsXHJcbiAgICAgICAgamF2YXNjcmlwdEVuYWJsZWQ6IHRydWUsXHJcbiAgICAgIH0sXHJcbiAgICB9LFxyXG4gIH0sXHJcbiAgZGVmaW5lOiB7XHJcbiAgICBfX0lOVExJRllfUFJPRF9ERVZUT09MU19fOiBmYWxzZSxcclxuICAgICdwcm9jZXNzLmVudic6IHByb2Nlc3MuZW52LFxyXG4gIH0sXHJcbn07XHJcbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiRDpcXFxcZGV2XFxcXGZsb3dcXFxcc21hcnQtZmxvd1xcXFxzbWFydC1mbG93LXdlYlxcXFxzcmNcXFxcdGhlbWVcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZmlsZW5hbWUgPSBcIkQ6XFxcXGRldlxcXFxmbG93XFxcXHNtYXJ0LWZsb3dcXFxcc21hcnQtZmxvdy13ZWJcXFxcc3JjXFxcXHRoZW1lXFxcXGN1c3RvbS12YXJpYWJsZXMuanNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL0Q6L2Rldi9mbG93L3NtYXJ0LWZsb3cvc21hcnQtZmxvdy13ZWIvc3JjL3RoZW1lL2N1c3RvbS12YXJpYWJsZXMuanNcIjtpbXBvcnQgeyB0aGVtZSB9IGZyb20gJ2FudC1kZXNpZ24tdnVlL2xpYic7XHJcbmltcG9ydCBjb252ZXJ0TGVnYWN5VG9rZW4gZnJvbSAnYW50LWRlc2lnbi12dWUvbGliL3RoZW1lL2NvbnZlcnRMZWdhY3lUb2tlbic7XHJcblxyXG5jb25zdCB7IGRlZmF1bHRBbGdvcml0aG0sIGRlZmF1bHRTZWVkIH0gPSB0aGVtZTtcclxuXHJcbmNvbnN0IG1hcFRva2VuID0gZGVmYXVsdEFsZ29yaXRobShkZWZhdWx0U2VlZCk7XHJcbmNvbnN0IHRva2VuID0gY29udmVydExlZ2FjeVRva2VuLmRlZmF1bHQobWFwVG9rZW4pO1xyXG5cclxuZXhwb3J0IGRlZmF1bHQge1xyXG4gICdAcHJpbWFyeS1jb2xvcic6IHRva2VuWydwcmltYXJ5LWNvbG9yJ10sIC8vIFx1NTE2OFx1NUM0MFx1NEUzQlx1ODI3MlxyXG4gICdAYmFzZS1iZy1jb2xvcic6ICcjZmZmJyxcclxuICAnQGhvdmVyLWJnLWNvbG9yJzogJ3JnYmEoMCwgMCwgMCwgMC4wMjUpJyxcclxuICAnQGhvdmVyLWJnLWNvbG9yLW5pZ2h0JzogJ3JnYmEoMjU1LCAyNTUsIDI1NSwgMC4wMjUpJyxcclxuICAnQGhlYWRlci1saWdodC1iZy1ob3Zlci1jb2xvcic6ICcjZjZmNmY2JyxcclxuICAnQGhlYWRlci1oZWlnaHQnOiAnODBweCcsXHJcbiAgJ0BoZWFkZXItdXNlci1oZWlnaHQnOiAnNDBweCcsXHJcbiAgJ0BwYWdlLXRhZy1oZWlnaHQnOiAnNDBweCcsXHJcbiAgJ0B0aGVtZS1saXN0JzogWydsaWdodCcsICdkYXJrJywgJ25pZ2h0J10sXHJcbn07XHJcbiJdLAogICJtYXBwaW5ncyI6ICI7QUFTQSxTQUFTLGVBQWU7QUFDeEIsT0FBTyxTQUFTOzs7QUNWdVUsU0FBUyxhQUFhO0FBQzdXLE9BQU8sd0JBQXdCO0FBRS9CLElBQU0sRUFBRSxrQkFBa0IsWUFBWSxJQUFJO0FBRTFDLElBQU0sV0FBVyxpQkFBaUIsV0FBVztBQUM3QyxJQUFNLFFBQVEsbUJBQW1CLFFBQVEsUUFBUTtBQUVqRCxJQUFPLDJCQUFRO0FBQUEsRUFDYixrQkFBa0IsTUFBTSxlQUFlO0FBQUE7QUFBQSxFQUN2QyxrQkFBa0I7QUFBQSxFQUNsQixtQkFBbUI7QUFBQSxFQUNuQix5QkFBeUI7QUFBQSxFQUN6QixnQ0FBZ0M7QUFBQSxFQUNoQyxrQkFBa0I7QUFBQSxFQUNsQix1QkFBdUI7QUFBQSxFQUN2QixvQkFBb0I7QUFBQSxFQUNwQixlQUFlLENBQUMsU0FBUyxRQUFRLE9BQU87QUFDMUM7OztBRGxCQSxJQUFNLG1DQUFtQztBQWF6QyxJQUFNLGNBQWMsQ0FBQyxRQUFRO0FBQzNCLFNBQU8sUUFBUSxrQ0FBVyxLQUFLLEdBQUc7QUFDcEM7QUFDQSxJQUFPLHNCQUFRO0FBQUEsRUFDYixNQUFNLFFBQVEsSUFBSSxhQUFhLGVBQWUsTUFBTTtBQUFBLEVBQ3BELE1BQU0sUUFBUSxJQUFJO0FBQUEsRUFDbEIsU0FBUztBQUFBLElBQ1AsT0FBTztBQUFBO0FBQUEsTUFFTDtBQUFBLFFBQ0UsTUFBTTtBQUFBLFFBQ04sYUFBYTtBQUFBLE1BQ2Y7QUFBQTtBQUFBLE1BRUE7QUFBQSxRQUNFLE1BQU07QUFBQSxRQUNOLGFBQWEsWUFBWSxLQUFLLElBQUk7QUFBQSxNQUNwQztBQUFBLE1BQ0E7QUFBQSxRQUNFLE1BQU07QUFBQSxRQUNOLGFBQWE7QUFBQSxNQUNmO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFBQTtBQUFBLEVBRUEsUUFBUTtBQUFBLElBQ04sTUFBTTtBQUFBLElBQ04sTUFBTTtBQUFBLEVBQ1I7QUFBQSxFQUNBLFNBQVMsQ0FBQyxJQUFJLENBQUM7QUFBQSxFQUNmLGNBQWM7QUFBQSxJQUNaLFNBQVMsQ0FBQyxrQ0FBa0Msc0JBQXNCLGdDQUFnQztBQUFBLElBQ2xHLFNBQVMsQ0FBQyxVQUFVO0FBQUEsRUFDdEI7QUFBQSxFQUNBLE9BQU87QUFBQTtBQUFBLElBRUwsZUFBZTtBQUFBLE1BQ2IsVUFBVTtBQUFBLFFBQ1IsY0FBYztBQUFBLFFBQ2QsZUFBZTtBQUFBLE1BQ2pCO0FBQUEsSUFDRjtBQUFBLElBQ0EsZUFBZTtBQUFBLE1BQ2IsUUFBUTtBQUFBO0FBQUEsUUFFTixnQkFBZ0I7QUFBQSxRQUNoQixnQkFBZ0I7QUFBQSxRQUNoQixnQkFBZ0I7QUFBQSxRQUNoQixhQUFhLElBQUk7QUFFZixjQUFJLEdBQUcsU0FBUyxjQUFjLEdBQUc7QUFDL0IsbUJBQU8sR0FBRyxTQUFTLEVBQUUsTUFBTSxlQUFlLEVBQUUsQ0FBQyxFQUFFLE1BQU0sR0FBRyxFQUFFLENBQUMsRUFBRSxTQUFTO0FBQUEsVUFDeEU7QUFBQSxRQUNGO0FBQUEsTUFDRjtBQUFBLElBQ0Y7QUFBQSxJQUNBLFFBQVE7QUFBQSxJQUNSLFFBQVE7QUFBQTtBQUFBLElBQ1IsV0FBVztBQUFBO0FBQUEsSUFDWCxtQkFBbUI7QUFBQTtBQUFBLElBQ25CLHVCQUF1QjtBQUFBO0FBQUEsSUFDdkIsUUFBUTtBQUFBO0FBQUEsSUFDUixhQUFhO0FBQUE7QUFBQSxFQUNmO0FBQUEsRUFDQSxLQUFLO0FBQUEsSUFDSCxxQkFBcUI7QUFBQSxNQUNuQixNQUFNO0FBQUEsUUFDSixZQUFZO0FBQUEsUUFDWixtQkFBbUI7QUFBQSxNQUNyQjtBQUFBLElBQ0Y7QUFBQSxFQUNGO0FBQUEsRUFDQSxRQUFRO0FBQUEsSUFDTiwyQkFBMkI7QUFBQSxJQUMzQixlQUFlLFFBQVE7QUFBQSxFQUN6QjtBQUNGOyIsCiAgIm5hbWVzIjogW10KfQo= diff --git a/update_all_comments.py b/update_all_comments.py new file mode 100644 index 0000000..8244141 --- /dev/null +++ b/update_all_comments.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +""" +批量更新Java文件注释格式 +将所有@Author 1024创新实验室相关的注释统一改为 @Author wzh +""" + +import os +import re +from pathlib import Path + +def update_java_comments(file_path): + """更新单个Java文件的注释""" + try: + with open(file_path, 'r', encoding='utf-8') as f: + content = f.read() + + # 匹配并替换注释块 + # 模式1: 多行注释包含 @Author 1024创新实验室... + pattern = r'/\*\*\s*\n(\s*\*.*?\n)*?\s*\*\s*@Author\s+1024创新实验室[^\n]*\n(\s*\*.*?\n)*?\s*\*/' + + def replace_comment(match): + comment_block = match.group(0) + + # 提取功能说明(第一行) + desc_match = re.search(r'/\*\*\s*\n\s*\*\s*(.+?)\s*\n', comment_block) + if not desc_match: + return comment_block + description = desc_match.group(1) + + # 提取@Date + date_match = re.search(r'\*\s*@Date\s+(.+?)\s*\n', comment_block) + if not date_match: + return comment_block + date_value = date_match.group(1) + + # 构建新的注释 + new_comment = f"/**\n * {description}\n *\n * @Date {date_value}\n * @Author wzh\n */" + return new_comment + + new_content = re.sub(pattern, replace_comment, content, flags=re.MULTILINE | re.DOTALL) + + if new_content != content: + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_content) + return True + return False + except Exception as e: + print(f"Error processing {file_path}: {e}") + return False + +def main(): + """主函数""" + base_dir = Path('/Users/wang/wang/space/frameworkSpace/smart-flow-master/smart-flow-api') + + # 查找所有Java文件 + java_files = list(base_dir.rglob('*.java')) + + updated_count = 0 + total_count = len(java_files) + + print(f"Found {total_count} Java files") + + for i, java_file in enumerate(java_files, 1): + if update_java_comments(java_file): + updated_count += 1 + print(f"[{i}/{total_count}] Updated: {java_file.relative_to(base_dir)}") + + print(f"\nCompleted! Updated {updated_count} files out of {total_count}") + +if __name__ == '__main__': + main()