Преглед изворни кода

开发环境配置 日志整理

wangmeng пре 1 месец
родитељ
комит
0840d90d94
100 измењених фајлова са 9459 додато и 154121 уклоњено
  1. 40 0
      README-配置保护.md
  2. 17 0
      backup_database.sh
  3. 1 1
      nacos/nacos/conf/application.properties
  4. 1 1
      nacos/nacos/data/protocol/raft/naming_instance_metadata/log/IDENTITY
  5. 2000 38420
      nacos/nacos/data/protocol/raft/naming_instance_metadata/log/LOG
  6. BIN
      nacos/nacos/data/protocol/raft/naming_instance_metadata/snapshot/snapshot_1/__raft_snapshot_meta
  7. 1 1
      nacos/nacos/data/protocol/raft/naming_persistent_service/log/IDENTITY
  8. 2111 38531
      nacos/nacos/data/protocol/raft/naming_persistent_service/log/LOG
  9. 1 1
      nacos/nacos/data/protocol/raft/naming_persistent_service_v2/log/IDENTITY
  10. 2080 38500
      nacos/nacos/data/protocol/raft/naming_persistent_service_v2/log/LOG
  11. BIN
      nacos/nacos/data/protocol/raft/naming_persistent_service_v2/snapshot/snapshot_1/__raft_snapshot_meta
  12. 1 1
      nacos/nacos/data/protocol/raft/naming_service_metadata/log/IDENTITY
  13. 2094 38514
      nacos/nacos/data/protocol/raft/naming_service_metadata/log/LOG
  14. BIN
      nacos/nacos/data/protocol/raft/naming_service_metadata/snapshot/snapshot_1/__raft_snapshot_meta
  15. 2 1
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/enums/OperateTypeEnum.java
  16. 5 3
      xdz-framework/xdz-spring-boot-starter-security/src/main/java/com/xindazhou/framework/security/core/filter/TokenAuthenticationFilter.java
  17. 34 0
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/config/ApiAccessLogProperties.java
  18. 33 3
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/config/XdzApiLogAutoConfiguration.java
  19. 1 1
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/annotation/ApiAccessLog.java
  20. 7 7
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/filter/ApiAccessLogFilter.java
  21. 20 0
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/service/ApiAccessLogStorageStrategy.java
  22. 25 0
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/service/impl/DirectStorageStrategy.java
  23. 80 0
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/service/impl/LogOnlyStorageStrategy.java
  24. 4 2
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/web/core/filter/CacheRequestBodyFilter.java
  25. 18 2
      xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/web/core/util/WebFrameworkUtils.java
  26. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/agreement/AgreementController.java
  27. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/auth/AuthController.java
  28. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/captcha/CaptchaController.java
  29. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/codegen/CodegenController.java
  30. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/activity/ActivityController.java
  31. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/ban/BanController.java
  32. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/banner/BannerController.java
  33. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/comment/CommentController.java
  34. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/post/PostController.java
  35. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/report/ReportController.java
  36. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/sensitive/SensitiveWordController.java
  37. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/topic/TopicController.java
  38. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/config/ConfigController.java
  39. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/db/DataSourceConfigController.java
  40. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dept/DeptController.java
  41. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dept/PostController.java
  42. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dict/DictDataController.java
  43. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dict/DictTypeController.java
  44. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/file/FileConfigController.java
  45. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/file/FileController.java
  46. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/ip/AreaController.java
  47. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/ApiAccessLogController.java
  48. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/ApiErrorLogController.java
  49. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/LoginLogController.java
  50. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/OperateLogController.java
  51. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/mail/MailAccountController.java
  52. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/mail/MailLogController.java
  53. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/mail/MailTemplateController.java
  54. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/message/ServiceMessageController.java
  55. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/notice/NoticeController.java
  56. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/notify/NotifyMessageController.java
  57. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/notify/NotifyTemplateController.java
  58. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2ClientController.java
  59. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2OpenController.java
  60. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2TokenController.java
  61. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2UserController.java
  62. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/redis/RedisController.java
  63. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/service/evaluation/EvaluationProxyController.java
  64. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/service/feedback/FeedbackController.java
  65. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/service/maintenance/MaintenanceOrderProxyController.java
  66. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsCallbackController.java
  67. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsChannelController.java
  68. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsLogController.java
  69. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsTemplateController.java
  70. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/socail/SocialClientController.java
  71. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/socail/SocialUserController.java
  72. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/tenant/TenantController.java
  73. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/tenant/TenantPackageController.java
  74. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/user/UserController.java
  75. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/user/UserProfileController.java
  76. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/vehicle/VehicleAlarmController.java
  77. 2 2
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/version/VersionController.java
  78. 6 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/community/post/vo/PostPageReqVO.java
  79. 42 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/community/topic/TopicController.java
  80. 172 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/VehicleController.java
  81. 60 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/convert/VehicleConvert.java
  82. 42 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleBindReqVO.java
  83. 43 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleDetailRespVO.java
  84. 46 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleListRespVO.java
  85. 47 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleStatusRespVO.java
  86. 22 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleUpdateReqVO.java
  87. 10 0
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/dal/community/dataobject/post/PostDO.java
  88. 3 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/dal/community/mysql/post/CommunityPostMapper.java
  89. 2 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/dal/dataobject/logger/ApiAccessLogDO.java
  90. 3 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/framework/rpc/config/RpcConfiguration.java
  91. 1 1
      xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/service/codegen/inner/CodegenEngine.java
  92. 4 33
      xdz-module-business/xdz-module-business-server/src/main/resources/application-prod.yaml
  93. 114 30
      xdz-module-business/xdz-module-business-server/src/main/resources/application.yaml
  94. 62 0
      xdz-module-business/xdz-module-business-server/src/main/resources/sql/grant_banner_permissions.sql
  95. 12 0
      xdz-module-gateway/xdz-module-gateway-server/pom.xml
  96. 21 0
      xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/config/GatewayConfig.java
  97. 36 0
      xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/config/GatewayJwtConfiguration.java
  98. 21 0
      xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/config/GatewayPublicEndpointsProperties.java
  99. 49 0
      xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/core/LoginUser.java
  100. 0 0
      xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/core/jwt/GatewayJwtUtil.java

+ 40 - 0
README-配置保护.md

@@ -0,0 +1,40 @@
+# 配置保护说明
+
+## 问题
+从 Git 拉取代码时,本地配置文件会被覆盖。
+
+## 原因
+Git pull 会合并远程更改,如果本地有未提交的修改,可能会被覆盖。
+
+## 解决方案
+
+### 方案1:使用 Git Stash(推荐)
+```bash
+# 拉取前先保存本地配置
+git stash push -m "保存本地配置" -- "**/application-local.yaml" "**/application-dev.yaml"
+
+# 拉取代码
+git pull
+
+# 恢复本地配置
+git stash pop
+```
+
+### 方案2:使用 .git/info/exclude(已配置)
+已在 `.git/info/exclude` 中添加了忽略规则,但只对当前仓库有效。
+这些文件不会被 Git 跟踪,但也不会被提交。
+
+### 方案3:使用 Nacos 配置中心(最佳实践)
+将本地配置放到 Nacos 配置中心,这样:
+- 不会被 Git 覆盖
+- 可以动态切换环境
+- 团队共享配置
+
+### 方案4:使用环境变量
+在配置文件中使用环境变量,通过环境变量来区分本地和服务器配置。
+
+## 当前配置状态
+- `application-dev.yaml` = 本地数据库(127.0.0.1:3306/xdz-pro)
+- `application-local.yaml` = 本地数据库(127.0.0.1:3306/xdz-pro)✅ 已修改
+- `application-prod.yaml` = 服务器数据库(119.45.95.228:10022/xdz_crm)✅ 已修改
+

+ 17 - 0
backup_database.sh

@@ -129,3 +129,20 @@ echo "=========================================="
 
 
 
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+

+ 1 - 1
nacos/nacos/conf/application.properties

@@ -286,6 +286,6 @@ nacos.istio.mcp.server.enabled=false
 #nacos.console.ui.enabled=truenacos.core.auth.plugin.nacos.token.secret.key=TvCaAg/QEdP7eMd6xpl1gQgc0XcoQeYQePmGnw+IaUo=
 spring.datasource.platform=mysql
 spring.sql.init.platform=mysql
-nacos.core.auth.plugin.nacos.token.secret.key=N2Q3NGI4MmVhMGU4MjEyNDY5NThmYmE4MWNkNzUzMGY4ZDUxMGZjY2MwMzk3OTExMjNhZTM2YWQ4ZmRmOTg5Ng==
+nacos.core.auth.plugin.nacos.token.secret.key=YjJhMDY3ZWUzNTU3YjEyYjRiYjk5N2ExODFmODMyMmIyODU5ZDdmMmEwYjk0ZWQ1NTYzNThjYjdlYzAwMDZjZg==
 nacos.core.auth.server.identity.key=serverIdentity
 nacos.core.auth.server.identity.value=security

+ 1 - 1
nacos/nacos/data/protocol/raft/naming_instance_metadata/log/IDENTITY

@@ -1 +1 @@
-6e40f8a7-a529-42f8-bc6e-db3511985b3e
+2f85e1a0-ea7a-49da-839a-294be0b00cf2

Разлика између датотеке није приказан због своје велике величине
+ 2000 - 38420
nacos/nacos/data/protocol/raft/naming_instance_metadata/log/LOG


BIN
nacos/nacos/data/protocol/raft/naming_instance_metadata/snapshot/snapshot_1/__raft_snapshot_meta


+ 1 - 1
nacos/nacos/data/protocol/raft/naming_persistent_service/log/IDENTITY

@@ -1 +1 @@
-5cf44a8f-af1e-4af2-969a-8dea3e33113a
+8ccb91f0-ff9a-4e15-b5e4-0f2ce63bd131

Разлика између датотеке није приказан због своје велике величине
+ 2111 - 38531
nacos/nacos/data/protocol/raft/naming_persistent_service/log/LOG


+ 1 - 1
nacos/nacos/data/protocol/raft/naming_persistent_service_v2/log/IDENTITY

@@ -1 +1 @@
-ac074df2-acb1-46de-b849-f964c574339a
+24134727-74cc-47e6-b7bb-db14ed613051

Разлика између датотеке није приказан због своје велике величине
+ 2080 - 38500
nacos/nacos/data/protocol/raft/naming_persistent_service_v2/log/LOG


BIN
nacos/nacos/data/protocol/raft/naming_persistent_service_v2/snapshot/snapshot_1/__raft_snapshot_meta


+ 1 - 1
nacos/nacos/data/protocol/raft/naming_service_metadata/log/IDENTITY

@@ -1 +1 @@
-5abec3ce-48c2-4332-9e5a-c80f7be3fba4
+f59685ea-60cc-44d3-ae1d-e2caf1fd7e29

Разлика између датотеке није приказан због своје велике величине
+ 2094 - 38514
nacos/nacos/data/protocol/raft/naming_service_metadata/log/LOG


BIN
nacos/nacos/data/protocol/raft/naming_service_metadata/snapshot/snapshot_1/__raft_snapshot_meta


+ 2 - 1
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/enums/OperateTypeEnum.java

@@ -1,4 +1,4 @@
-package com.xindazhou.framework.apilog.core.enums;
+package com.xindazhou.framework.common.enums;
 
 import lombok.AllArgsConstructor;
 import lombok.Getter;
@@ -49,3 +49,4 @@ public enum OperateTypeEnum {
     private final Integer type;
 
 }
+

+ 5 - 3
xdz-framework/xdz-spring-boot-starter-security/src/main/java/com/xindazhou/framework/security/core/filter/TokenAuthenticationFilter.java

@@ -49,13 +49,15 @@ public class TokenAuthenticationFilter extends OncePerRequestFilter {
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
             throws ServletException, IOException {
         // 情况一,基于 header[login-user] 获得用户,例如说来自 Gateway 或者其它服务透传
+        // 优先使用 Gateway 传递的用户信息,避免重复验证 Token 和调用 user-server
         LoginUser loginUser = buildLoginUserByHeader(request);
         if (loginUser != null) {
-            log.debug("[TokenAuthenticationFilter] 通过 header[login-user] 获取到用户: userId={}", loginUser.getId());
+            log.debug("[TokenAuthenticationFilter] 通过 header[login-user] 获取到用户: userId={},跳过 Token 验证", loginUser.getId());
         }
 
-        // 情况二,基于 Token 获得用户
-        // 注意,这里主要满足直接使用 Nginx 直接转发到 Spring Cloud 服务的场景。
+        // 情况二,基于 Token 获得用户(降级方案)
+        // 注意:当请求直接访问业务服务(不经过 Gateway)时,才需要验证 Token
+        // 正常情况下,请求应经过 Gateway,Gateway 已验证 Token 并设置 header
         if (loginUser == null) {
             String token = SecurityFrameworkUtils.obtainAuthorization(request,
                     securityProperties.getTokenHeader(), securityProperties.getTokenParameter());

+ 34 - 0
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/config/ApiAccessLogProperties.java

@@ -0,0 +1,34 @@
+package com.xindazhou.framework.apilog.config;
+
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+
+/**
+ * API 访问日志配置属性
+ *
+ * @author xdz
+ */
+@ConfigurationProperties(prefix = "xdz.access-log")
+@Data
+public class ApiAccessLogProperties {
+
+    /**
+     * 是否启用 API 访问日志
+     */
+    private Boolean enable = true;
+
+    /**
+     * 存储模式
+     * - log-only: 只记录到日志文件,不存储到数据库(默认)
+     * - direct: 直接写入数据库
+     */
+    private String mode = "log-only";
+
+    /**
+     * 日志文件路径(仅 log-only 模式使用)
+     * 默认:${user.home}/logs/${spring.application.name}-access.log
+     */
+    private String logFilePath;
+
+}
+

+ 33 - 3
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/config/XdzApiLogAutoConfiguration.java

@@ -2,31 +2,61 @@ package com.xindazhou.framework.apilog.config;
 
 import com.xindazhou.framework.apilog.core.filter.ApiAccessLogFilter;
 import com.xindazhou.framework.apilog.core.interceptor.ApiAccessLogInterceptor;
-import com.xindazhou.framework.common.biz.infra.logger.ApiAccessLogCommonApi;
+import com.xindazhou.framework.apilog.core.service.ApiAccessLogStorageStrategy;
+import com.xindazhou.framework.apilog.core.service.impl.LogOnlyStorageStrategy;
 import com.xindazhou.framework.common.enums.WebFilterOrderEnum;
 import com.xindazhou.framework.web.config.WebProperties;
 import com.xindazhou.framework.web.config.XdzWebAutoConfiguration;
 import jakarta.servlet.Filter;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.AutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.boot.web.servlet.FilterRegistrationBean;
 import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.annotation.EnableAsync;
 import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
 import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 
+import java.io.File;
+
 @AutoConfiguration(after = XdzWebAutoConfiguration.class)
+@EnableConfigurationProperties(ApiAccessLogProperties.class)
+@EnableAsync
 public class XdzApiLogAutoConfiguration implements WebMvcConfigurer {
 
     /**
+     * 创建 LogOnlyStorageStrategy Bean(log-only 模式,默认)
+     */
+    @Bean
+    @ConditionalOnMissingBean(ApiAccessLogStorageStrategy.class)
+    @ConditionalOnProperty(prefix = "xdz.access-log", name = "mode", havingValue = "log-only", matchIfMissing = true)
+    public LogOnlyStorageStrategy logOnlyStorageStrategy(
+            @Value("${spring.application.name}") String applicationName,
+            ApiAccessLogProperties properties) {
+        String logFilePath = properties.getLogFilePath();
+        if (logFilePath == null || logFilePath.isEmpty()) {
+            // 默认路径:${user.home}/logs/${spring.application.name}-access.log
+            String userHome = System.getProperty("user.home");
+            logFilePath = userHome + File.separator + "logs" + File.separator + applicationName + "-access.log";
+        }
+        return new LogOnlyStorageStrategy(applicationName, logFilePath);
+    }
+
+    /**
      * 创建 ApiAccessLogFilter Bean,记录 API 请求日志
      */
     @Bean
     @ConditionalOnProperty(prefix = "xdz.access-log", value = "enable", matchIfMissing = true) // 允许使用 xdz.access-log.enable=false 禁用访问日志
+    @ConditionalOnBean(ApiAccessLogStorageStrategy.class)
     public FilterRegistrationBean<ApiAccessLogFilter> apiAccessLogFilter(WebProperties webProperties,
                                                                          @Value("${spring.application.name}") String applicationName,
-                                                                         ApiAccessLogCommonApi apiAccessLogApi) {
-        ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, apiAccessLogApi);
+                                                                         ApiAccessLogStorageStrategy storageStrategy) {
+        ApiAccessLogFilter filter = new ApiAccessLogFilter(webProperties, applicationName, storageStrategy);
         return createFilterBean(filter, WebFilterOrderEnum.API_ACCESS_LOG_FILTER);
     }
 

+ 1 - 1
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/annotation/ApiAccessLog.java

@@ -1,6 +1,6 @@
 package com.xindazhou.framework.apilog.core.annotation;
 
-import com.xindazhou.framework.apilog.core.enums.OperateTypeEnum;
+import com.xindazhou.framework.common.enums.OperateTypeEnum;
 
 import java.lang.annotation.ElementType;
 import java.lang.annotation.Retention;

+ 7 - 7
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/filter/ApiAccessLogFilter.java

@@ -8,8 +8,8 @@ import cn.hutool.core.util.ArrayUtil;
 import cn.hutool.core.util.BooleanUtil;
 import cn.hutool.core.util.StrUtil;
 import com.xindazhou.framework.apilog.core.annotation.ApiAccessLog;
-import com.xindazhou.framework.apilog.core.enums.OperateTypeEnum;
-import com.xindazhou.framework.common.biz.infra.logger.ApiAccessLogCommonApi;
+import com.xindazhou.framework.common.enums.OperateTypeEnum;
+import com.xindazhou.framework.apilog.core.service.ApiAccessLogStorageStrategy;
 import com.xindazhou.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
 import com.xindazhou.framework.common.exception.enums.GlobalErrorCodeConstants;
 import com.xindazhou.framework.common.pojo.CommonResult;
@@ -42,7 +42,7 @@ import static com.xindazhou.framework.common.util.json.JsonUtils.toJsonString;
 /**
  * API 访问日志 Filter
  *
- * 目的:记录 API 访问日志到数据库中
+ * 目的:记录 API 访问日志(支持直接写数据库或只写日志文件)
  *
  * @author xdz
  */
@@ -53,12 +53,12 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
 
     private final String applicationName;
 
-    private final ApiAccessLogCommonApi apiAccessLogApi;
+    private final ApiAccessLogStorageStrategy storageStrategy;
 
-    public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogCommonApi apiAccessLogApi) {
+    public ApiAccessLogFilter(WebProperties webProperties, String applicationName, ApiAccessLogStorageStrategy storageStrategy) {
         super(webProperties);
         this.applicationName = applicationName;
-        this.apiAccessLogApi = apiAccessLogApi;
+        this.storageStrategy = storageStrategy;
     }
 
     @Override
@@ -91,7 +91,7 @@ public class ApiAccessLogFilter extends ApiRequestFilter {
             if (!enable) {
                 return;
             }
-            apiAccessLogApi.createApiAccessLogAsync(accessLog);
+            storageStrategy.save(accessLog);
         } catch (Throwable th) {
             log.error("[createApiAccessLog][url({}) log({}) 发生异常]", request.getRequestURI(), toJsonString(accessLog), th);
         }

+ 20 - 0
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/service/ApiAccessLogStorageStrategy.java

@@ -0,0 +1,20 @@
+package com.xindazhou.framework.apilog.core.service;
+
+import com.xindazhou.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
+
+/**
+ * API 访问日志存储策略接口
+ *
+ * @author xdz
+ */
+public interface ApiAccessLogStorageStrategy {
+
+    /**
+     * 保存 API 访问日志
+     *
+     * @param createDTO 日志创建请求 DTO
+     */
+    void save(ApiAccessLogCreateReqDTO createDTO);
+
+}
+

+ 25 - 0
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/service/impl/DirectStorageStrategy.java

@@ -0,0 +1,25 @@
+package com.xindazhou.framework.apilog.core.service.impl;
+
+import com.xindazhou.framework.apilog.core.service.ApiAccessLogStorageStrategy;
+import com.xindazhou.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+
+/**
+ * 直接数据库存储策略(需要由各服务模块自己实现)
+ * 这个类只是一个标记,实际的 Bean 会由各服务模块创建
+ *
+ * @author xdz
+ */
+@Slf4j
+public class DirectStorageStrategy implements ApiAccessLogStorageStrategy {
+
+    @Override
+    @Async
+    public void save(ApiAccessLogCreateReqDTO createDTO) {
+        // 这个方法不会被调用,实际的实现在各服务模块中
+        log.warn("[save][DirectStorageStrategy 不应该被直接使用]");
+    }
+
+}
+

+ 80 - 0
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/apilog/core/service/impl/LogOnlyStorageStrategy.java

@@ -0,0 +1,80 @@
+package com.xindazhou.framework.apilog.core.service.impl;
+
+import com.xindazhou.framework.apilog.core.service.ApiAccessLogStorageStrategy;
+import com.xindazhou.framework.common.biz.infra.logger.dto.ApiAccessLogCreateReqDTO;
+import com.xindazhou.framework.common.util.json.JsonUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.FileWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.time.format.DateTimeFormatter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 只记录日志文件存储策略
+ *
+ * @author xdz
+ */
+@Slf4j
+@RequiredArgsConstructor
+public class LogOnlyStorageStrategy implements ApiAccessLogStorageStrategy {
+
+    private final String applicationName;
+    private final String logFilePath;
+
+    @Override
+    public void save(ApiAccessLogCreateReqDTO createDTO) {
+        try {
+            // 构建 JSON 日志对象
+            Map<String, Object> logMap = new HashMap<>();
+            logMap.put("type", "api-access-log");
+            logMap.put("timestamp", createDTO.getBeginTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
+            logMap.put("traceId", createDTO.getTraceId());
+            logMap.put("applicationName", applicationName);
+            logMap.put("requestMethod", createDTO.getRequestMethod());
+            logMap.put("requestUrl", createDTO.getRequestUrl());
+            logMap.put("requestParams", createDTO.getRequestParams());
+            logMap.put("userId", createDTO.getUserId());
+            logMap.put("userType", createDTO.getUserType());
+            logMap.put("userIp", createDTO.getUserIp());
+            logMap.put("userAgent", createDTO.getUserAgent());
+            logMap.put("operateModule", createDTO.getOperateModule());
+            logMap.put("operateName", createDTO.getOperateName());
+            logMap.put("operateType", createDTO.getOperateType());
+            logMap.put("beginTime", createDTO.getBeginTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
+            logMap.put("endTime", createDTO.getEndTime().format(DateTimeFormatter.ISO_LOCAL_DATE_TIME));
+            logMap.put("duration", createDTO.getDuration());
+            logMap.put("resultCode", createDTO.getResultCode());
+            logMap.put("resultMsg", createDTO.getResultMsg());
+
+            // 转换为 JSON 字符串
+            String jsonLog = JsonUtils.toJsonString(logMap);
+
+            // 写入日志文件
+            writeToFile(jsonLog);
+        } catch (Throwable th) {
+            log.error("[save][保存 API 访问日志到文件失败,log({})]", createDTO, th);
+        }
+    }
+
+    private void writeToFile(String jsonLog) throws IOException {
+        Path path = Paths.get(logFilePath);
+        Path parent = path.getParent();
+        if (parent != null && !Files.exists(parent)) {
+            Files.createDirectories(parent);
+        }
+
+        try (FileWriter writer = new FileWriter(logFilePath, true)) {
+            writer.write(jsonLog);
+            writer.write(System.lineSeparator());
+            writer.flush();
+        }
+    }
+
+}
+

+ 4 - 2
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/web/core/filter/CacheRequestBodyFilter.java

@@ -21,8 +21,10 @@ public class CacheRequestBodyFilter extends OncePerRequestFilter {
      * 需要排除的 URI
      *
      * 1. 排除 Spring Boot Admin 相关请求,避免客户端连接中断导致的异常。
+     *    注意:只排除 Spring Boot Admin 的实际路径(如 /admin/actuator/),而不是所有 /admin/ 开头的业务接口
+     * 2. 排除 Actuator 端点
      */
-    private static final String[] IGNORE_URIS = {"/admin/", "/actuator/"};
+    private static final String[] IGNORE_URIS = {"/admin/actuator/", "/actuator/"};
 
     @Override
     protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
@@ -32,7 +34,7 @@ public class CacheRequestBodyFilter extends OncePerRequestFilter {
 
     @Override
     protected boolean shouldNotFilter(HttpServletRequest request) {
-        // 1. 校验是否为排除的 URL
+        // 1. 校验是否为排除的 URL(只排除 Spring Boot Admin 和 Actuator 的实际路径)
         String requestURI = request.getRequestURI();
         if (StrUtil.startWithAny(requestURI, IGNORE_URIS)) {
             return true;

+ 18 - 2
xdz-framework/xdz-spring-boot-starter-web/src/main/java/com/xindazhou/framework/web/core/util/WebFrameworkUtils.java

@@ -112,12 +112,28 @@ public class WebFrameworkUtils {
             return userType;
         }
         // 2. 其次,基于 URL 前缀的约定
-        if (request.getServletPath().startsWith(properties.getAdminApi().getPrefix())) {
+        String servletPath = request.getServletPath();
+        String adminPrefix = properties.getAdminApi().getPrefix();
+        String appPrefix = properties.getAppApi().getPrefix();
+        
+        // 如果 prefix 为空字符串,则根据路径中的 /app/ 或 /admin/ 判断
+        // 注意:空字符串的 startsWith 总是返回 true,所以需要特殊处理
+        if (adminPrefix != null && !adminPrefix.isEmpty() && servletPath.startsWith(adminPrefix)) {
             return UserTypeEnum.ADMIN.getValue();
         }
-        if (request.getServletPath().startsWith(properties.getAppApi().getPrefix())) {
+        if (appPrefix != null && !appPrefix.isEmpty() && servletPath.startsWith(appPrefix)) {
             return UserTypeEnum.MEMBER.getValue();
         }
+        
+        // 当 prefix 为空时,根据路径前缀判断(Gateway StripPrefix 后的路径)
+        // /app/... 表示 APP 端,/admin/... 或 /system/... 表示 Admin 端
+        if (servletPath.startsWith("/app/")) {
+            return UserTypeEnum.MEMBER.getValue();
+        }
+        if (servletPath.startsWith("/admin/") || servletPath.startsWith("/system/")) {
+            return UserTypeEnum.ADMIN.getValue();
+        }
+        
         return null;
     }
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/agreement/AgreementController.java

@@ -21,7 +21,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - APP协议管理")
 @RestController
-@RequestMapping("/system")
+@RequestMapping("/admin/system")
 @Validated
 public class AgreementController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/auth/AuthController.java

@@ -41,7 +41,7 @@ import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.
 
 @Tag(name = "管理后台 - 认证")
 @RestController
-@RequestMapping("/system/auth")
+@RequestMapping("/admin/system/auth")
 @Validated
 @Slf4j
 public class AuthController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/captcha/CaptchaController.java

@@ -18,7 +18,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 @Tag(name = "管理后台 - 验证码")
 @RestController("adminCaptchaController")
-@RequestMapping("/system/captcha")
+@RequestMapping("/admin/system/captcha")
 public class CaptchaController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/codegen/CodegenController.java

@@ -39,7 +39,7 @@ import static com.xindazhou.business.framework.file.core.utils.FileTypeUtils.wri
 
 @Tag(name = "管理后台 - 代码生成器")
 @RestController
-@RequestMapping("/infra/codegen")
+@RequestMapping("/admin/infra/codegen")
 @Validated
 public class CodegenController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/activity/ActivityController.java

@@ -26,7 +26,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 活动管理")
 @RestController("communityActivityController")
-@RequestMapping("/community/activity")
+@RequestMapping("/admin/community/activity")
 @Validated
 @Slf4j
 public class ActivityController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/ban/BanController.java

@@ -24,7 +24,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 封禁管理")
 @RestController("communityBanController")
-@RequestMapping("/community/ban")
+@RequestMapping("/admin/community/ban")
 @Validated
 @Slf4j
 public class BanController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/banner/BannerController.java

@@ -25,7 +25,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - Banner管理")
 @RestController("communityBannerController")
-@RequestMapping("/community/banner")
+@RequestMapping("/admin/community/banner")
 @Validated
 @Slf4j
 public class BannerController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/comment/CommentController.java

@@ -24,7 +24,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 评论管理")
 @RestController("communityCommentController")
-@RequestMapping("/community/comment")
+@RequestMapping("/admin/community/comment")
 @Validated
 @Slf4j
 public class CommentController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/post/PostController.java

@@ -29,7 +29,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 帖子管理")
 @RestController("communityPostController")
-@RequestMapping("/community/post")
+@RequestMapping("/admin/community/post")
 @Validated
 @Slf4j
 public class PostController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/report/ReportController.java

@@ -25,7 +25,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 举报管理")
 @RestController("communityReportController")
-@RequestMapping("/community/report")
+@RequestMapping("/admin/community/report")
 @Validated
 @Slf4j
 public class ReportController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/sensitive/SensitiveWordController.java

@@ -25,7 +25,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 敏感词管理")
 @RestController("communitySensitiveWordController")
-@RequestMapping("/community/sensitiveWord")
+@RequestMapping("/admin/community/sensitiveWord")
 @Validated
 @Slf4j
 public class SensitiveWordController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/community/topic/TopicController.java

@@ -27,7 +27,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 话题管理")
 @RestController("communityTopicController")
-@RequestMapping("/community/topic")
+@RequestMapping("/admin/community/topic")
 @Validated
 @Slf4j
 public class TopicController {

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/config/ConfigController.java

@@ -25,13 +25,13 @@ import org.springframework.web.bind.annotation.*;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 参数配置")
 @RestController
-@RequestMapping("/infra/config")
+@RequestMapping("/admin/infra/config")
 @Validated
 public class ConfigController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/db/DataSourceConfigController.java

@@ -21,7 +21,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 数据源配置")
 @RestController
-@RequestMapping("/infra/data-source-config")
+@RequestMapping("/admin/infra/data-source-config")
 @Validated
 public class DataSourceConfigController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dept/DeptController.java

@@ -24,7 +24,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 部门")
 @RestController
-@RequestMapping("/system/dept")
+@RequestMapping("/admin/system/dept")
 @Validated
 public class DeptController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dept/PostController.java

@@ -28,12 +28,12 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 岗位")
 @RestController
-@RequestMapping("/system/post")
+@RequestMapping("/admin/system/post")
 @Validated
 public class PostController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dict/DictDataController.java

@@ -26,12 +26,12 @@ import org.springframework.web.bind.annotation.*;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 字典数据")
 @RestController
-@RequestMapping("/system/dict-data")
+@RequestMapping("/admin/system/dict-data")
 @Validated
 public class DictDataController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/dict/DictTypeController.java

@@ -25,12 +25,12 @@ import org.springframework.web.bind.annotation.*;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 字典类型")
 @RestController
-@RequestMapping("/system/dict-type")
+@RequestMapping("/admin/system/dict-type")
 @Validated
 public class DictTypeController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/file/FileConfigController.java

@@ -23,7 +23,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 文件配置")
 @RestController
-@RequestMapping("/infra/file-config")
+@RequestMapping("/admin/infra/file-config")
 @Validated
 public class FileConfigController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/file/FileController.java

@@ -35,7 +35,7 @@ import static com.xindazhou.business.framework.file.core.utils.FileTypeUtils.wri
 
 @Tag(name = "管理后台 - 文件存储")
 @RestController
-@RequestMapping("/system/file")
+@RequestMapping("/admin/system/file")
 @Validated
 @Slf4j
 public class FileController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/ip/AreaController.java

@@ -22,7 +22,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 地区")
 @RestController
-@RequestMapping("/system/area")
+@RequestMapping("/admin/system/area")
 @Validated
 public class AreaController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/ApiAccessLogController.java

@@ -26,12 +26,12 @@ import org.springframework.web.bind.annotation.RestController;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - API 访问日志")
 @RestController
-@RequestMapping("/infra/api-access-log")
+@RequestMapping("/admin/infra/api-access-log")
 @Validated
 public class ApiAccessLogController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/ApiErrorLogController.java

@@ -24,13 +24,13 @@ import org.springframework.web.bind.annotation.*;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
 
 @Tag(name = "管理后台 - API 错误日志")
 @RestController
-@RequestMapping("/infra/api-error-log")
+@RequestMapping("/admin/infra/api-error-log")
 @Validated
 public class ApiErrorLogController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/LoginLogController.java

@@ -24,12 +24,12 @@ import org.springframework.web.bind.annotation.RestController;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 登录日志")
 @RestController
-@RequestMapping("/system/login-log")
+@RequestMapping("/admin/system/login-log")
 @Validated
 public class LoginLogController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/logger/OperateLogController.java

@@ -28,12 +28,12 @@ import org.springframework.web.bind.annotation.RestController;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 操作日志")
 @RestController
-@RequestMapping("/system/operate-log")
+@RequestMapping("/admin/system/operate-log")
 @Validated
 public class OperateLogController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/mail/MailAccountController.java

@@ -24,7 +24,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 邮箱账号")
 @RestController
-@RequestMapping("/system/mail-account")
+@RequestMapping("/admin/system/mail-account")
 public class MailAccountController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/mail/MailLogController.java

@@ -23,7 +23,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 邮件日志")
 @RestController
-@RequestMapping("/system/mail-log")
+@RequestMapping("/admin/system/mail-log")
 public class MailLogController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/mail/MailTemplateController.java

@@ -22,7 +22,7 @@ import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.
 
 @Tag(name = "管理后台 - 邮件模版")
 @RestController
-@RequestMapping("/system/mail-template")
+@RequestMapping("/admin/system/mail-template")
 public class MailTemplateController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/message/ServiceMessageController.java

@@ -21,7 +21,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 服务消息")
 @RestController
-@RequestMapping("/service")
+@RequestMapping("/admin/service")
 @Validated
 public class ServiceMessageController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/notice/NoticeController.java

@@ -26,7 +26,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 通知公告")
 @RestController
-@RequestMapping("/system/notice")
+@RequestMapping("/admin/system/notice")
 @Validated
 public class NoticeController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/notify/NotifyMessageController.java

@@ -26,7 +26,7 @@ import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.
 
 @Tag(name = "管理后台 - 我的站内信")
 @RestController
-@RequestMapping("/system/notify-message")
+@RequestMapping("/admin/system/notify-message")
 @Validated
 public class NotifyMessageController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/notify/NotifyTemplateController.java

@@ -26,7 +26,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 站内信模版")
 @RestController
-@RequestMapping("/system/notify-template")
+@RequestMapping("/admin/system/notify-template")
 @Validated
 public class NotifyTemplateController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2ClientController.java

@@ -23,7 +23,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - OAuth2 客户端")
 @RestController
-@RequestMapping("/system/oauth2-client")
+@RequestMapping("/admin/system/oauth2-client")
 @Validated
 public class OAuth2ClientController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2OpenController.java

@@ -56,7 +56,7 @@ import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.
  */
 @Tag(name = "管理后台 - OAuth2.0 授权")
 @RestController
-@RequestMapping("/system/oauth2")
+@RequestMapping("/admin/system/oauth2")
 @Validated
 @Slf4j
 public class OAuth2OpenController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2TokenController.java

@@ -23,7 +23,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - OAuth2.0 令牌")
 @RestController
-@RequestMapping("/system/oauth2-token")
+@RequestMapping("/admin/system/oauth2-token")
 public class OAuth2TokenController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/oauth2/OAuth2UserController.java

@@ -36,7 +36,7 @@ import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.
  */
 @Tag(name = "管理后台 - OAuth2.0 用户")
 @RestController
-@RequestMapping("/system/oauth2/user")
+@RequestMapping("/admin/system/oauth2/user")
 @Validated
 @Slf4j
 public class OAuth2UserController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/redis/RedisController.java

@@ -20,7 +20,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - Redis 监控")
 @RestController
-@RequestMapping("/infra/redis")
+@RequestMapping("/admin/infra/redis")
 public class RedisController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/service/evaluation/EvaluationProxyController.java

@@ -27,7 +27,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 服务评价管理")
 @RestController("serviceEvaluationProxyController")
-@RequestMapping("/service/evaluation")
+@RequestMapping("/admin/service/evaluation")
 @Validated
 @Slf4j
 public class EvaluationProxyController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/service/feedback/FeedbackController.java

@@ -25,7 +25,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - APP意见反馈")
 @RestController("serviceFeedbackController")
-@RequestMapping("/service/feedback")
+@RequestMapping("/admin/service/feedback")
 @Validated
 @Slf4j
 public class FeedbackController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/service/maintenance/MaintenanceOrderProxyController.java

@@ -29,7 +29,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
  */
 @Tag(name = "管理后台 - 维保管理")
 @RestController("serviceMaintenanceOrderProxyController")
-@RequestMapping("/service/maintenance/order")
+@RequestMapping("/admin/service/maintenance/order")
 @Validated
 @Slf4j
 public class MaintenanceOrderProxyController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsCallbackController.java

@@ -17,7 +17,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 短信回调")
 @RestController
-@RequestMapping("/system/sms/callback")
+@RequestMapping("/admin/system/sms/callback")
 public class SmsCallbackController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsChannelController.java

@@ -24,7 +24,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 短信渠道")
 @RestController
-@RequestMapping("system/sms-channel")
+@RequestMapping("/admin/system/sms-channel")
 public class SmsChannelController {
 
     @Resource

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsLogController.java

@@ -26,12 +26,12 @@ import org.springframework.web.bind.annotation.RestController;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 短信日志")
 @RestController
-@RequestMapping("/system/sms-log")
+@RequestMapping("/admin/system/sms-log")
 @Validated
 public class SmsLogController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/sms/SmsTemplateController.java

@@ -25,12 +25,12 @@ import org.springframework.web.bind.annotation.*;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 短信模板")
 @RestController
-@RequestMapping("/system/sms-template")
+@RequestMapping("/admin/system/sms-template")
 public class SmsTemplateController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/socail/SocialClientController.java

@@ -25,7 +25,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 社交客户端")
 @RestController
-@RequestMapping("/system/social-client")
+@RequestMapping("/admin/system/social-client")
 @Validated
 public class SocialClientController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/socail/SocialUserController.java

@@ -28,7 +28,7 @@ import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.
 
 @Tag(name = "管理后台 - 社交用户")
 @RestController
-@RequestMapping("/system/social-user")
+@RequestMapping("/admin/system/social-user")
 @Validated
 public class SocialUserController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/tenant/TenantController.java

@@ -28,13 +28,13 @@ import org.springframework.web.bind.annotation.*;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 import static com.xindazhou.framework.common.util.collection.CollectionUtils.convertList;
 
 @Tag(name = "管理后台 - 租户")
 @RestController
-@RequestMapping("/system/tenant")
+@RequestMapping("/admin/system/tenant")
 public class TenantController {
 
     @Resource

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/tenant/TenantPackageController.java

@@ -25,7 +25,7 @@ import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 租户套餐")
 @RestController
-@RequestMapping("/system/tenant-package")
+@RequestMapping("/admin/system/tenant-package")
 @Validated
 public class TenantPackageController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/user/UserController.java

@@ -31,13 +31,13 @@ import java.util.Arrays;
 import java.util.List;
 import java.util.Map;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 import static com.xindazhou.framework.common.util.collection.CollectionUtils.convertList;
 
 @Tag(name = "管理后台 - 用户")
 @RestController
-@RequestMapping("/system/user")
+@RequestMapping("/admin/system/user")
 @Validated
 public class UserController {
 

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/user/UserProfileController.java

@@ -31,7 +31,7 @@ import static com.xindazhou.framework.security.core.util.SecurityFrameworkUtils.
 
 @Tag(name = "管理后台 - 用户个人中心")
 @RestController
-@RequestMapping("/system/user/profile")
+@RequestMapping("/admin/system/user/profile")
 @Validated
 @Slf4j
 public class UserProfileController {

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/vehicle/VehicleAlarmController.java

@@ -21,7 +21,7 @@ import java.util.Map;
  */
 @Tag(name = "管理后台 - 车辆报警")
 @RestController
-@RequestMapping("/vehicle/alarm")
+@RequestMapping("/admin/vehicle/alarm")
 @Validated
 public class VehicleAlarmController {
 

+ 2 - 2
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/admin/version/VersionController.java

@@ -24,12 +24,12 @@ import org.springframework.web.bind.annotation.*;
 import java.io.IOException;
 import java.util.List;
 
-import static com.xindazhou.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
+import static com.xindazhou.framework.common.enums.OperateTypeEnum.EXPORT;
 import static com.xindazhou.framework.common.pojo.CommonResult.success;
 
 @Tag(name = "管理后台 - 版本管理")
 @RestController
-@RequestMapping("/system/version")
+@RequestMapping("/admin/system/version")
 @Validated
 public class VersionController {
 

+ 6 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/community/post/vo/PostPageReqVO.java

@@ -29,5 +29,11 @@ public class PostPageReqVO extends PageParam {
     @Schema(description = "排序方式:time-按时间,popularity-按热度", example = "time")
     private String sort;
 
+    @Schema(description = "城市", example = "上海")
+    private String city;
+
+    @Schema(description = "话题ID", example = "1")
+    private Long topicId;
+
 }
 

+ 42 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/community/topic/TopicController.java

@@ -0,0 +1,42 @@
+package com.xindazhou.business.controller.app.community.topic;
+
+import com.xindazhou.business.controller.admin.community.topic.vo.TopicRespVO;
+import com.xindazhou.business.service.community.topic.TopicService;
+import com.xindazhou.framework.common.pojo.CommonResult;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+import static com.xindazhou.framework.common.pojo.CommonResult.success;
+
+/**
+ * 移动端 - 话题 Controller
+ *
+ * @author xindazhou
+ */
+@Tag(name = "移动端 - 话题管理")
+@RestController("appCommunityTopicController")
+@RequestMapping("/app/community/topic")
+@Validated
+@Slf4j
+public class TopicController {
+
+    @Resource
+    private TopicService topicService;
+
+    @GetMapping("/listEnabled")
+    @Operation(summary = "获得启用的话题列表")
+    public CommonResult<List<TopicRespVO>> getEnabledTopicList() {
+        List<TopicRespVO> topics = topicService.getEnabledTopicList();
+        return success(topics);
+    }
+
+}
+

+ 172 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/VehicleController.java

@@ -0,0 +1,172 @@
+package com.xindazhou.business.controller.app.vehicle;
+
+import com.xindazhou.business.controller.app.vehicle.convert.VehicleConvert;
+import com.xindazhou.business.controller.app.vehicle.vo.*;
+import com.xindazhou.framework.common.pojo.CommonResult;
+import com.xindazhou.framework.common.pojo.PageResult;
+import com.xindazhou.framework.common.pojo.PageParam;
+import com.xindazhou.framework.security.core.util.SecurityFrameworkUtils;
+import com.xindazhou.vehicle.api.VehicleApi;
+import com.xindazhou.vehicle.api.VehicleBindApi;
+import com.xindazhou.vehicle.api.VehicleStatusApi;
+import com.xindazhou.vehicle.api.dto.VehicleRespDTO;
+import com.xindazhou.vehicle.api.dto.bind.VehicleCreateAndBindReqDTO;
+import com.xindazhou.vehicle.api.dto.bind.VehicleBindRespDTO;
+import com.xindazhou.vehicle.api.dto.status.VehicleStatusRespDTO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import static com.xindazhou.framework.common.pojo.CommonResult.success;
+
+/**
+ * 移动端 - 车辆管理 Controller
+ *
+ * @author xindazhou
+ */
+@Tag(name = "移动端 - 车辆管理")
+@RestController("appVehicleController")
+@RequestMapping("/app/vehicle")
+@Validated
+@Slf4j
+public class VehicleController {
+
+    @Resource
+    private VehicleApi vehicleApi;
+
+    @Resource
+    private VehicleBindApi vehicleBindApi;
+
+    @Resource
+    private VehicleStatusApi vehicleStatusApi;
+
+    @GetMapping("/list")
+    @Operation(summary = "查询用户绑定的车辆列表")
+    public CommonResult<PageResult<VehicleListRespVO>> getVehicleList(@Valid PageParam pageParam) {
+        Long userId = SecurityFrameworkUtils.getLoginUserId();
+        // 默认用户类型为1(会员用户)
+        Integer userType = 1;
+        
+        // 查询用户绑定的车辆列表
+        CommonResult<List<VehicleRespDTO>> vehiclesResult = vehicleApi.listVehicleByUserId(userId, userType);
+        List<VehicleRespDTO> vehicles = vehiclesResult.getData();
+        
+        // 查询用户的所有绑定关系
+        CommonResult<List<VehicleBindRespDTO>> bindingsResult = vehicleBindApi.listBindByUserId(userId, userType);
+        List<VehicleBindRespDTO> bindings = bindingsResult.getData();
+        
+        // 构建vehicleId到binding的映射
+        Map<Long, VehicleBindRespDTO> bindingMap = bindings.stream()
+                .collect(Collectors.toMap(VehicleBindRespDTO::getVehicleId, b -> b, (b1, b2) -> b1));
+        
+        // 转换为VehicleListRespVO
+        List<VehicleListRespVO> list = vehicles.stream()
+                .map(vehicle -> {
+                    VehicleListRespVO vo = new VehicleListRespVO();
+                    vo.setId(vehicle.getId());
+                    vo.setVin(vehicle.getVin());
+                    vo.setName(vehicle.getName());
+                    vo.setBluetoothMac(vehicle.getBluetoothMac());
+                    vo.setStatus(vehicle.getStatus());
+                    
+                    VehicleBindRespDTO binding = bindingMap.get(vehicle.getId());
+                    if (binding != null) {
+                        vo.setIsDefault(binding.getIsDefault() != null ? binding.getIsDefault() : 0);
+                        vo.setUserType(binding.getUserType());
+                        vo.setBindTime(binding.getBindTime());
+                    }
+                    return vo;
+                })
+                .collect(Collectors.toList());
+        
+        return success(new PageResult<>(list, (long) list.size()));
+    }
+
+    @GetMapping("/get")
+    @Operation(summary = "查询车辆详情")
+    @Parameter(name = "id", description = "车辆ID", required = true, example = "1")
+    public CommonResult<VehicleDetailRespVO> getVehicle(@RequestParam("id") Long id) {
+        CommonResult<VehicleRespDTO> result = vehicleApi.getVehicle(id);
+        VehicleDetailRespVO vehicle = VehicleConvert.INSTANCE.convert(result.getData());
+        return success(vehicle);
+    }
+
+    @PostMapping("/bind")
+    @Operation(summary = "绑定车辆")
+    public CommonResult<VehicleDetailRespVO> bindVehicle(@Valid @RequestBody VehicleBindReqVO bindReqVO) {
+        Long userId = SecurityFrameworkUtils.getLoginUserId();
+        
+        // 构建创建并绑定请求
+        VehicleCreateAndBindReqDTO reqDTO = new VehicleCreateAndBindReqDTO();
+        reqDTO.setVin(bindReqVO.getVin());
+        reqDTO.setDeviceSn(bindReqVO.getDeviceSn());
+        reqDTO.setName(bindReqVO.getName());
+        reqDTO.setBluetoothMac(bindReqVO.getBluetoothMac());
+        reqDTO.setImageUrl(bindReqVO.getImageUrl());
+        reqDTO.setModelId(bindReqVO.getModelId());
+        reqDTO.setFirmwareVersion(bindReqVO.getFirmwareVersion());
+        reqDTO.setUserId(userId);
+        reqDTO.setUserType(bindReqVO.getUserType());
+        
+        // 调用创建并绑定接口
+        CommonResult<VehicleRespDTO> result = vehicleBindApi.createVehicleAndBind(reqDTO);
+        VehicleDetailRespVO vehicle = VehicleConvert.INSTANCE.convert(result.getData());
+        return success(vehicle);
+    }
+
+    @DeleteMapping("/unbind")
+    @Operation(summary = "解绑车辆")
+    @Parameter(name = "vehicleId", description = "车辆ID", required = true, example = "1")
+    public CommonResult<Boolean> unbindVehicle(@RequestParam("vehicleId") Long vehicleId) {
+        Long userId = SecurityFrameworkUtils.getLoginUserId();
+        CommonResult<Boolean> result = vehicleBindApi.unbindVehicle(userId, vehicleId);
+        return success(result.getData());
+    }
+
+    @PutMapping("/update")
+    @Operation(summary = "更新车辆信息")
+    public CommonResult<Boolean> updateVehicle(@Valid @RequestBody VehicleUpdateReqVO updateReqVO) {
+        Long userId = SecurityFrameworkUtils.getLoginUserId();
+        
+        // 构建更新请求DTO
+        com.xindazhou.vehicle.api.dto.VehicleUpdateReqDTO reqDTO = new com.xindazhou.vehicle.api.dto.VehicleUpdateReqDTO();
+        reqDTO.setId(updateReqVO.getId());
+        reqDTO.setName(updateReqVO.getName());
+        reqDTO.setImageUrl(updateReqVO.getImageUrl());
+        
+        // TODO: 验证用户权限(只有车主或授权用户可修改)
+        // 可以调用vehicleBindApi.listBindByUserId检查用户是否有权限
+        
+        CommonResult<Boolean> result = vehicleApi.updateVehicle(reqDTO);
+        return success(result.getData());
+    }
+
+    @PutMapping("/set-default")
+    @Operation(summary = "设置默认车辆")
+    @Parameter(name = "vehicleId", description = "车辆ID", required = true, example = "1")
+    public CommonResult<Boolean> setDefaultVehicle(@RequestParam("vehicleId") Long vehicleId) {
+        Long userId = SecurityFrameworkUtils.getLoginUserId();
+        CommonResult<Boolean> result = vehicleBindApi.setDefaultVehicle(userId, vehicleId);
+        return success(result.getData());
+    }
+
+    @GetMapping("/status")
+    @Operation(summary = "查询车辆状态")
+    @Parameter(name = "vehicleId", description = "车辆ID", required = true, example = "1")
+    public CommonResult<VehicleStatusRespVO> getVehicleStatus(@RequestParam("vehicleId") Long vehicleId) {
+        CommonResult<VehicleStatusRespDTO> result = vehicleStatusApi.getVehicleStatus(vehicleId);
+        VehicleStatusRespVO status = VehicleConvert.INSTANCE.convertStatus(result.getData());
+        return success(status);
+    }
+
+}
+

+ 60 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/convert/VehicleConvert.java

@@ -0,0 +1,60 @@
+package com.xindazhou.business.controller.app.vehicle.convert;
+
+import com.xindazhou.business.controller.app.vehicle.vo.*;
+import com.xindazhou.vehicle.api.dto.VehicleRespDTO;
+import com.xindazhou.vehicle.api.dto.bind.VehicleBindRespDTO;
+import com.xindazhou.vehicle.api.dto.status.VehicleStatusRespDTO;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.factory.Mappers;
+
+/**
+ * 车辆 Convert
+ *
+ * @author xindazhou
+ */
+@Mapper
+public interface VehicleConvert {
+
+    VehicleConvert INSTANCE = Mappers.getMapper(VehicleConvert.class);
+
+    @Mapping(target = "name", source = "plateNumber")
+    @Mapping(target = "deviceSn", ignore = true)
+    @Mapping(target = "bluetoothMac", ignore = true)
+    @Mapping(target = "imageUrl", ignore = true)
+    @Mapping(target = "modelId", ignore = true)
+    @Mapping(target = "firmwareVersion", ignore = true)
+    @Mapping(target = "bindTime", ignore = true)
+    VehicleDetailRespVO convert(VehicleRespDTO dto);
+
+    @Mapping(target = "defenseStatus", ignore = true)
+    @Mapping(target = "powerStatus", ignore = true)
+    @Mapping(target = "doorLockStatus", ignore = true)
+    @Mapping(target = "signalStrength", ignore = true)
+    @Mapping(target = "bluetoothStatus", ignore = true)
+    @Mapping(target = "range", source = "remainingMileage")
+    @Mapping(target = "frontTirePressure", ignore = true)
+    @Mapping(target = "rearTirePressure", ignore = true)
+    VehicleStatusRespVO convertStatus(VehicleStatusRespDTO dto);
+
+    /**
+     * 将VehicleRespDTO和VehicleBindRespDTO合并转换为VehicleListRespVO
+     */
+    default VehicleListRespVO convertList(VehicleRespDTO vehicle, VehicleBindRespDTO binding) {
+        VehicleListRespVO vo = new VehicleListRespVO();
+        if (vehicle != null) {
+            vo.setId(vehicle.getId());
+            vo.setVin(vehicle.getVin());
+            vo.setBluetoothMac(null); // VehicleRespDTO中没有bluetoothMac,需要从vehicle表查询
+            vo.setStatus(vehicle.getStatus());
+        }
+        if (binding != null) {
+            vo.setIsDefault(binding.getBindType() != null && binding.getBindType().equals("OWNER") ? 1 : 0);
+            vo.setUserType(binding.getUserType());
+            vo.setBindTime(binding.getBindTime());
+        }
+        return vo;
+    }
+
+}
+

+ 42 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleBindReqVO.java

@@ -0,0 +1,42 @@
+package com.xindazhou.business.controller.app.vehicle.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "移动端 - 绑定车辆 Request VO")
+@Data
+public class VehicleBindReqVO {
+
+    @Schema(description = "车架号", requiredMode = Schema.RequiredMode.REQUIRED, example = "VIN20250126001")
+    @NotBlank(message = "车架号不能为空")
+    private String vin;
+
+    @Schema(description = "设备序列号", requiredMode = Schema.RequiredMode.REQUIRED, example = "SN20250126001")
+    @NotBlank(message = "设备序列号不能为空")
+    private String deviceSn;
+
+    @Schema(description = "车辆名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "我的小摩托")
+    @NotBlank(message = "车辆名称不能为空")
+    private String name;
+
+    @Schema(description = "蓝牙MAC地址", requiredMode = Schema.RequiredMode.REQUIRED, example = "AA:BB:CC:DD:EE:FF")
+    @NotBlank(message = "蓝牙MAC地址不能为空")
+    private String bluetoothMac;
+
+    @Schema(description = "车辆图片URL", example = "https://...")
+    private String imageUrl;
+
+    @Schema(description = "车辆型号ID", example = "1")
+    private Long modelId;
+
+    @Schema(description = "固件版本", example = "1.0.0")
+    private String firmwareVersion;
+
+    @Schema(description = "用户类型(1-最高权限,2-车主,3-分享用户)", requiredMode = Schema.RequiredMode.REQUIRED, example = "2")
+    @NotNull(message = "用户类型不能为空")
+    private Integer userType;
+
+}
+

+ 43 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleDetailRespVO.java

@@ -0,0 +1,43 @@
+package com.xindazhou.business.controller.app.vehicle.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "移动端 - 车辆详情 Response VO")
+@Data
+public class VehicleDetailRespVO {
+
+    @Schema(description = "车辆ID", example = "1")
+    private Long id;
+
+    @Schema(description = "车架号", example = "VIN20250126001")
+    private String vin;
+
+    @Schema(description = "设备序列号", example = "SN20250126001")
+    private String deviceSn;
+
+    @Schema(description = "车辆名称", example = "我的小摩托")
+    private String name;
+
+    @Schema(description = "蓝牙MAC地址", example = "AA:BB:CC:DD:EE:FF")
+    private String bluetoothMac;
+
+    @Schema(description = "车辆图片URL", example = "https://...")
+    private String imageUrl;
+
+    @Schema(description = "车辆型号ID", example = "1")
+    private Long modelId;
+
+    @Schema(description = "固件版本", example = "1.0.0")
+    private String firmwareVersion;
+
+    @Schema(description = "状态:0-禁用,1-启用", example = "1")
+    private Integer status;
+
+    @Schema(description = "绑定时间")
+    private LocalDateTime bindTime;
+
+}
+

+ 46 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleListRespVO.java

@@ -0,0 +1,46 @@
+package com.xindazhou.business.controller.app.vehicle.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.time.LocalDateTime;
+
+@Schema(description = "移动端 - 车辆列表 Response VO")
+@Data
+public class VehicleListRespVO {
+
+    @Schema(description = "车辆ID", example = "1")
+    private Long id;
+
+    @Schema(description = "车架号", example = "VIN20250126001")
+    private String vin;
+
+    @Schema(description = "车辆名称", example = "我的小摩托")
+    private String name;
+
+    @Schema(description = "蓝牙MAC地址", example = "AA:BB:CC:DD:EE:FF")
+    private String bluetoothMac;
+
+    @Schema(description = "车辆图片URL", example = "https://...")
+    private String imageUrl;
+
+    @Schema(description = "状态:0-离线,1-在线,2-故障", example = "1")
+    private Integer status;
+
+    @Schema(description = "电池电量(0-100)", example = "80")
+    private Integer batteryLevel;
+
+    @Schema(description = "续航里程(km)", example = "370")
+    private Integer range;
+
+    @Schema(description = "是否默认车辆(0-否,1-是)", example = "1")
+    private Integer isDefault;
+
+    @Schema(description = "用户类型(1-最高权限,2-车主,3-分享用户)", example = "2")
+    private Integer userType;
+
+    @Schema(description = "绑定时间")
+    private LocalDateTime bindTime;
+
+}
+

+ 47 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleStatusRespVO.java

@@ -0,0 +1,47 @@
+package com.xindazhou.business.controller.app.vehicle.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+@Schema(description = "移动端 - 车辆状态 Response VO")
+@Data
+public class VehicleStatusRespVO {
+
+    @Schema(description = "车辆ID", example = "1")
+    private Long vehicleId;
+
+    @Schema(description = "设防状态(0-撤防,1-设防)", example = "1")
+    private Integer defenseStatus;
+
+    @Schema(description = "上电状态(0-下电,1-上电)", example = "0")
+    private Integer powerStatus;
+
+    @Schema(description = "门锁状态(0-开,1-关)", example = "1")
+    private Integer doorLockStatus;
+
+    @Schema(description = "电池电量(0-100)", example = "80")
+    private Integer batteryLevel;
+
+    @Schema(description = "信号强度(0-4)", example = "3")
+    private Integer signalStrength;
+
+    @Schema(description = "蓝牙连接状态(0-未连接,1-已连接)", example = "1")
+    private Integer bluetoothStatus;
+
+    @Schema(description = "续航里程(km)", example = "370")
+    private Integer range;
+
+    @Schema(description = "前轮胎压(kPa)", example = "124.0")
+    private BigDecimal frontTirePressure;
+
+    @Schema(description = "后轮胎压(kPa)", example = "120.0")
+    private BigDecimal rearTirePressure;
+
+    @Schema(description = "更新时间")
+    private LocalDateTime updateTime;
+
+}
+

+ 22 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/controller/app/vehicle/vo/VehicleUpdateReqVO.java

@@ -0,0 +1,22 @@
+package com.xindazhou.business.controller.app.vehicle.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+@Schema(description = "移动端 - 更新车辆信息 Request VO")
+@Data
+public class VehicleUpdateReqVO {
+
+    @Schema(description = "车辆ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+    @NotNull(message = "车辆ID不能为空")
+    private Long id;
+
+    @Schema(description = "车辆名称", example = "我的小摩托(新名称)")
+    private String name;
+
+    @Schema(description = "车辆图片URL", example = "https://...")
+    private String imageUrl;
+
+}
+

+ 10 - 0
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/dal/community/dataobject/post/PostDO.java

@@ -92,5 +92,15 @@ public class PostDO extends BaseDO {
      */
     private String pendingReviewReason;
 
+    /**
+     * 话题ID
+     */
+    private Long topicId;
+
+    /**
+     * 城市
+     */
+    private String city;
+
 }
 

+ 3 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/dal/community/mysql/post/CommunityPostMapper.java

@@ -19,7 +19,9 @@ public interface CommunityPostMapper extends BaseMapperX<PostDO> {
         LambdaQueryWrapperX<PostDO> wrapper = new LambdaQueryWrapperX<PostDO>()
                 .eq(PostDO::getStatus, 1) // 只查询正常状态的帖子
                 .eqIfPresent(PostDO::getUserId, reqVO.getUserId())
-                .likeIfPresent(PostDO::getTitle, reqVO.getTitle());
+                .likeIfPresent(PostDO::getTitle, reqVO.getTitle())
+                .eqIfPresent(PostDO::getTopicId, reqVO.getTopicId())
+                .eqIfPresent(PostDO::getCity, reqVO.getCity());
         
         // 关键词搜索(使用全文索引 MATCH...AGAINST)
         if (reqVO.getKeyword() != null && !reqVO.getKeyword().trim().isEmpty()) {

+ 2 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/dal/dataobject/logger/ApiAccessLogDO.java

@@ -1,6 +1,6 @@
 package com.xindazhou.business.dal.dataobject.logger;
 
-import com.xindazhou.framework.apilog.core.enums.OperateTypeEnum;
+import com.xindazhou.framework.common.enums.OperateTypeEnum;
 import com.xindazhou.framework.common.enums.UserTypeEnum;
 import com.xindazhou.framework.common.pojo.CommonResult;
 import com.xindazhou.framework.mybatis.core.dataobject.BaseDO;
@@ -138,3 +138,4 @@ public class ApiAccessLogDO extends BaseDO {
     private String resultMsg;
 
 }
+

+ 3 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/framework/rpc/config/RpcConfiguration.java

@@ -15,6 +15,8 @@ import com.xindazhou.user.api.permission.RoleApi;
 import com.xindazhou.message.api.MessageSendApi;
 import com.xindazhou.vehicle.api.VehicleApi;
 import com.xindazhou.vehicle.api.VehicleAlarmApi;
+import com.xindazhou.vehicle.api.VehicleBindApi;
+import com.xindazhou.vehicle.api.VehicleStatusApi;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.cloud.openfeign.EnableFeignClients;
 import org.springframework.context.annotation.Bean;
@@ -26,7 +28,7 @@ import org.springframework.context.annotation.Configuration;
         com.xindazhou.business.api.service.MaintenanceOrderApi.class, 
         MemberTagApi.class, MemberLevelApi.class, MemberGroupApi.class, MemberUserApi.class,
         com.xindazhou.user.api.user.MemberUserApi.class, OAuth2TokenCommonApi.class, PermissionCommonApi.class, 
-        MenuApi.class, RoleApi.class, VehicleApi.class, VehicleAlarmApi.class, MessageSendApi.class}) // 添加用户服务的 RPC 客户端(权限、菜单、角色)
+        MenuApi.class, RoleApi.class, VehicleApi.class, VehicleAlarmApi.class, VehicleBindApi.class, VehicleStatusApi.class, MessageSendApi.class}) // 添加用户服务的 RPC 客户端(权限、菜单、角色)
 public class RpcConfiguration {
 
     /**

+ 1 - 1
xdz-module-business/xdz-module-business-server/src/main/java/com/xindazhou/business/service/codegen/inner/CodegenEngine.java

@@ -9,7 +9,7 @@ import cn.hutool.extra.template.TemplateEngine;
 import cn.hutool.extra.template.engine.velocity.VelocityEngine;
 import cn.hutool.system.SystemUtil;
 import com.xindazhou.framework.apilog.core.annotation.ApiAccessLog;
-import com.xindazhou.framework.apilog.core.enums.OperateTypeEnum;
+import com.xindazhou.framework.common.enums.OperateTypeEnum;
 import com.xindazhou.framework.common.exception.util.ServiceExceptionUtil;
 import com.xindazhou.framework.common.pojo.CommonResult;
 import com.xindazhou.framework.common.pojo.PageParam;

+ 4 - 33
xdz-module-business/xdz-module-business-server/src/main/resources/application-prod.yaml

@@ -68,14 +68,14 @@ spring:
       datasource:
         master:
           # 生产环境数据库配置应该通过 Nacos 配置中心或环境变量管理
-          url: ${DB_URL:jdbc:mysql://127.0.0.1:3306/xdz_crm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8}
+          url: ${DB_URL:jdbc:mysql://119.45.95.228:10022/xdz_crm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8}
           username: ${DB_USERNAME:root}
-          password: ${DB_PASSWORD:}
+          password: ${DB_PASSWORD:xdz@123!}
         slave: # 模拟从库,可根据自己需要修改
           lazy: true # 开启懒加载,保证启动速度
-          url: ${DB_SLAVE_URL:jdbc:mysql://127.0.0.1:3306/xdz_crm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8}
+          url: ${DB_SLAVE_URL:jdbc:mysql://119.45.95.228:10022/xdz_crm?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true&useUnicode=true&characterEncoding=UTF-8}
           username: ${DB_SLAVE_USERNAME:root}
-          password: ${DB_SLAVE_PASSWORD:}
+          password: ${DB_SLAVE_PASSWORD:xdz@123!}
 
   # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
   data:
@@ -109,35 +109,6 @@ xxl:
     admin:
       addresses: ${XXL_JOB_ADMIN_ADDRESSES:http://127.0.0.1:9090/xxl-job-admin} # 调度中心部署跟地址(支持环境变量)
 
---- #################### 服务保障相关配置 ####################
-
-# Lock4j 配置项
-lock4j:
-  acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
-  expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
-
---- #################### 监控相关配置 ####################
-
-# Actuator 监控端点的配置项
-management:
-  endpoints:
-    web:
-      base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
-      exposure:
-        include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点
-
-# Spring Boot Admin 配置项
-spring:
-  boot:
-    admin:
-      # Spring Boot Admin Client 客户端的相关配置
-      client:
-        instance:
-          service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
-        username: admin
-        password: admin
-      # Spring Boot Admin Server 服务端的相关配置
-      context-path: /admin # 配置 Spring
 
 # 日志文件配置
 logging:

+ 114 - 30
xdz-module-business/xdz-module-business-server/src/main/resources/application.yaml

@@ -3,7 +3,7 @@ spring:
     name: xdz-business
 
   profiles:
-    active: local
+    active: ${SPRING_PROFILES_ACTIVE:dev}  # 通过环境变量 SPRING_PROFILES_ACTIVE 切换,可选值:local, dev, prod,默认 dev
 
   main:
     allow-circular-references: true # 允许循环依赖,因为项目是三层架构,无法避免这个情况。
@@ -35,6 +35,73 @@ spring:
     redis:
       time-to-live: 1h # 设置过期时间为 1 小时
 
+  cloud:
+    inetutils:
+      ignored-interfaces:
+        - ^VirtualBox.*
+  
+  # 数据源配置项
+  autoconfigure:
+    exclude:
+      - com.xindazhou.framework.apilog.config.XdzApiLogRpcAutoConfiguration # 禁用 Feign 客户端自动配置,使用本地实现
+      # 禁用 XdzSecurityRpcAutoConfiguration,避免 OAuth2TokenCommonApi 的 Feign 客户端与本地实现冲突
+      # LoginUserRequestInterceptor 已在 RpcConfiguration 中手动注册
+      - com.xindazhou.framework.security.config.XdzSecurityRpcAutoConfiguration
+  datasource:
+    druid: # Druid 【监控】相关的全局配置(所有环境相同)
+      web-stat-filter:
+        enabled: true
+      stat-view-servlet:
+        enabled: true
+        allow: # 设置白名单,不填则允许所有访问
+        url-pattern: /druid/*
+        login-username: # 控制台管理用户名和密码
+        login-password:
+      filter:
+        stat:
+          enabled: true
+          log-slow-sql: true # 慢 SQL 记录
+          slow-sql-millis: 100
+          merge-sql: true
+        wall:
+          config:
+            multi-statement-allow: true
+    dynamic: # 多数据源配置(连接池配置在环境配置文件中)
+      primary: master
+
+  data:
+    redis:
+      repositories:
+        enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度
+
+  # Kafka 配置项,对应 KafkaProperties 配置类
+  kafka:
+    # Kafka Producer 配置项
+    producer:
+      acks: 1 # 0-不应答。1-leader 应答。all-所有 leader 和 follower 应答。
+      retries: 3 # 发送失败时,重试发送的次数
+      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer # 消息的 value 的序列化
+    # Kafka Consumer 配置项
+    consumer:
+      auto-offset-reset: earliest # 设置消费者分组最初的消费进度为 earliest 。可参考博客 https://blog.csdn.net/lishuangzhe7047/article/details/74530417 理解
+      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
+      properties:
+        spring.json.trusted.packages: '*'
+    # Kafka Consumer Listener 监听器配置
+    listener:
+      missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错
+
+  boot:
+    admin:
+      # Spring Boot Admin Client 客户端的相关配置
+      client:
+        instance:
+          service-host-type: IP # 注册实例时,优先使用 IP [IP, HOST_NAME, CANONICAL_HOST_NAME]
+        username: admin
+        password: admin
+      # Spring Boot Admin Server 服务端的相关配置
+      context-path: /admin # 配置 Spring Boot Admin 的上下文路径
+
 server:
   port: 18081
 
@@ -64,7 +131,7 @@ mybatis-plus:
     map-underscore-to-camel-case: true # 虽然默认为 true ,但是还是显示去指定下。
   global-config:
     db-config:
-      id-type: NONE # “智能”模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。
+      id-type: NONE # "智能"模式,基于 IdTypeEnvironmentPostProcessor + 数据源的类型,自动适配成 AUTO、INPUT 模式。
       #      id-type: AUTO # 自增 ID,适合 MySQL 等直接自增的数据库
       #      id-type: INPUT # 用户输入 ID,适合 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库
       #      id-type: ASSIGN_ID # 分配 ID,默认使用雪花算法。注意,Oracle、PostgreSQL、Kingbase、DB2、H2 数据库时,需要去除实体类上的 @KeySequence 注解
@@ -78,12 +145,7 @@ mybatis-plus:
 mybatis-plus-join:
   banner: false # 关闭控制台的 Banner 打印
 
-# Spring Data Redis 配置
-spring:
-  data:
-    redis:
-      repositories:
-        enabled: false # 项目未使用到 Spring Data Redis 的 Repository,所以直接禁用,保证启动速度
+--- #################### 数据库相关配置(公共配置)####################
 
 # VO 转换(数据翻译)相关
 easy-trans:
@@ -99,24 +161,6 @@ rocketmq:
   producer:
     group: ${spring.application.name}_PRODUCER # 生产者分组
 
-spring:
-  # Kafka 配置项,对应 KafkaProperties 配置类
-  kafka:
-    # Kafka Producer 配置项
-    producer:
-      acks: 1 # 0-不应答。1-leader 应答。all-所有 leader 和 follower 应答。
-      retries: 3 # 发送失败时,重试发送的次数
-      value-serializer: org.springframework.kafka.support.serializer.JsonSerializer # 消息的 value 的序列化
-    # Kafka Consumer 配置项
-    consumer:
-      auto-offset-reset: earliest # 设置消费者分组最初的消费进度为 earliest 。可参考博客 https://blog.csdn.net/lishuangzhe7047/article/details/74530417 理解
-      value-deserializer: org.springframework.kafka.support.serializer.JsonDeserializer
-      properties:
-        spring.json.trusted.packages: '*'
-    # Kafka Consumer Listener 监听器配置
-    listener:
-      missing-topics-fatal: false # 消费监听接口监听的主题不存在时,默认会报错。所以通过设置为 false ,解决报错
-
 --- #################### 定时任务相关配置 ####################
 
 xxl:
@@ -126,9 +170,31 @@ xxl:
       logpath: ${user.home}/logs/xxl-job/${spring.application.name} # 执行器运行日志文件存储磁盘路径
     accessToken: default_token # 执行器通讯TOKEN
 
+--- #################### 服务保障相关配置(公共配置)####################
+
+# Lock4j 配置项(所有环境相同)
+lock4j:
+  acquire-timeout: 3000 # 获取分布式锁超时时间,默认为 3000 毫秒
+  expire: 30000 # 分布式锁的超时时间,默认为 30 毫秒
+
+--- #################### 监控相关配置(公共配置)####################
+
+# Actuator 监控端点的配置项(所有环境相同)
+management:
+  endpoints:
+    web:
+      base-path: /actuator # Actuator 提供的 API 接口的根目录。默认为 /actuator
+      exposure:
+        include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
+
 --- #################### 新大洲相关配置 ####################
 
 xdz:
+  # API 访问日志配置
+  access-log:
+    enable: true # 是否启用 API 访问日志
+    mode: log-only # 存储模式:log-only(默认,只记录日志文件)| direct(直接写数据库)
+
   info:
     version: 1.0.0
     base-package: com.xindazhou.business
@@ -147,11 +213,29 @@ xdz:
       enabled: false  # 禁用业务服务的 CORS 配置,由 Gateway 统一处理
   security:
     # 免登录的 URL 列表(补充 @PermitAll 注解识别的路径)
-    # 注意:这些路径是业务服务接收到的路径(Gateway StripPrefix=3 后的路径)
+    # Gateway 使用 StripPrefix=2(去掉 /api/v1),转发路径是 /admin/system/...
+    # Controller 路径统一为 /admin/system/...,匹配 Gateway 转发的路径
     # 理论上 @PermitAll 注解应该被自动识别,但如果自动识别失败,可以在这里手动添加
-    # permit-all-urls:
-    #   - /system/captcha/get
-    #   - /system/captcha/check
+    permit-all-urls:
+      - /admin/system/captcha/get
+      - /admin/system/captcha/check
+      - /admin/system/auth/login
+      - /admin/system/auth/logout
+      - /admin/system/auth/refreshToken
+      - /admin/system/auth/register
+      - /admin/system/auth/smsLogin
+      - /admin/system/auth/sendSmsCode
+      - /admin/system/auth/resetPassword
+      - /admin/system/auth/socialAuthRedirect
+      - /admin/system/auth/socialLogin
+      - /admin/system/tenant/getIdByName
+      - /admin/system/tenant/simpleList
+      - /admin/system/tenant/getByWebsite
+      - /admin/system/file/**
+      - /admin/system/oauth2/token
+      - /admin/system/oauth2/token/delete
+      - /admin/system/oauth2/checkToken
+      - /admin/system/sms/callback/**
   xss:
     enable: false
     exclude-urls: # 如下两个 url,仅仅是为了演示,去掉配置也没关系

+ 62 - 0
xdz-module-business/xdz-module-business-server/src/main/resources/sql/grant_banner_permissions.sql

@@ -0,0 +1,62 @@
+SET NAMES utf8mb4;
+SET FOREIGN_KEY_CHECKS = 0;
+
+-- ----------------------------
+-- 为 Banner 管理添加权限并分配给超级管理员角色
+-- ----------------------------
+BEGIN;
+
+-- 1. 确保 Banner 相关权限存在(如果不存在则插入)
+INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES 
+(2084, 'Banner创建', 'community:banner:create', 3, 1, 2063, '', '', NULL, NULL, 0, b'0', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'),
+(2085, 'Banner更新', 'community:banner:update', 3, 2, 2063, '', '', NULL, NULL, 0, b'0', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0'),
+(2086, 'Banner删除', 'community:banner:delete', 3, 3, 2063, '', '', NULL, NULL, 0, b'0', b'1', b'1', 'admin', NOW(), 'admin', NOW(), b'0')
+ON DUPLICATE KEY UPDATE 
+  `name` = VALUES(`name`),
+  `permission` = VALUES(`permission`),
+  `status` = 0,
+  `deleted` = b'0';
+
+-- 2. 将 Banner 权限分配给超级管理员角色(role_id = 1)
+-- 先删除可能存在的旧记录,避免重复
+DELETE FROM `system_role_menu` 
+WHERE `role_id` = 1 
+AND `menu_id` IN (2084, 2085, 2086);
+
+-- 插入权限关联(role_id = 1 是超级管理员)
+INSERT INTO `system_role_menu` (`role_id`, `menu_id`) 
+SELECT 1, `id` 
+FROM `system_menu` 
+WHERE `id` IN (2084, 2085, 2086)
+AND `deleted` = b'0'
+AND NOT EXISTS (
+  SELECT 1 FROM `system_role_menu` 
+  WHERE `role_id` = 1 AND `menu_id` = `system_menu`.`id`
+);
+
+-- 3. 如果 Banner 查询权限(2063)还没有分配给超级管理员,也一并分配
+INSERT INTO `system_role_menu` (`role_id`, `menu_id`) 
+SELECT 1, 2063
+WHERE NOT EXISTS (
+  SELECT 1 FROM `system_role_menu` 
+  WHERE `role_id` = 1 AND `menu_id` = 2063
+);
+
+COMMIT;
+
+SET FOREIGN_KEY_CHECKS = 1;
+
+-- 验证:查询超级管理员角色的 Banner 权限
+SELECT 
+  rm.role_id,
+  r.name AS role_name,
+  rm.menu_id,
+  m.name AS menu_name,
+  m.permission
+FROM `system_role_menu` rm
+INNER JOIN `system_role` r ON rm.role_id = r.id
+INNER JOIN `system_menu` m ON rm.menu_id = m.id
+WHERE rm.role_id = 1
+AND m.permission LIKE 'community:banner:%'
+ORDER BY m.sort;
+

+ 12 - 0
xdz-module-gateway/xdz-module-gateway-server/pom.xml

@@ -36,6 +36,18 @@
 
         <!-- 注意:Gateway 使用 WebFlux,不能使用基于 Servlet 的 security starter -->
         <!-- Gateway 的认证使用 WebFlux 的 GlobalFilter -->
+        
+        <!-- JWT 工具类依赖(用于 Token 验证) -->
+        <dependency>
+            <groupId>com.auth0</groupId>
+            <artifactId>java-jwt</artifactId>
+        </dependency>
+        
+        <!-- 框架 Common(包含 JWT 工具类) -->
+        <dependency>
+            <groupId>com.xindazhou</groupId>
+            <artifactId>xdz-common</artifactId>
+        </dependency>
 
         <!-- Redis(用于 Token 验证,第二阶段使用) -->
         <!-- <dependency>

+ 21 - 0
xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/config/GatewayConfig.java

@@ -0,0 +1,21 @@
+package com.xindazhou.gateway.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * Gateway 配置类
+ *
+ * @author xindazhou
+ */
+@Configuration
+public class GatewayConfig {
+
+    @Bean
+    @ConfigurationProperties(prefix = "gateway")
+    public GatewayPublicEndpointsProperties gatewayPublicEndpointsProperties() {
+        return new GatewayPublicEndpointsProperties();
+    }
+}
+

+ 36 - 0
xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/config/GatewayJwtConfiguration.java

@@ -0,0 +1,36 @@
+package com.xindazhou.gateway.config;
+
+import com.xindazhou.gateway.core.jwt.GatewayJwtUtil;
+import jakarta.annotation.PostConstruct;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.core.io.ResourceLoader;
+
+/**
+ * Gateway JWT 配置
+ * 初始化 JWT 工具类,用于验证 Token
+ *
+ * @author xindazhou
+ */
+@Slf4j
+@Configuration
+public class GatewayJwtConfiguration {
+
+    @Value("${xdz.security.oauth2-jwt.public-key-path:}")
+    private String publicKeyPath;
+
+    private final ResourceLoader resourceLoader;
+
+    public GatewayJwtConfiguration(ResourceLoader resourceLoader) {
+        this.resourceLoader = resourceLoader;
+    }
+
+    @PostConstruct
+    public void init() {
+        // Gateway 只需要公钥验证 Token,不需要私钥
+        GatewayJwtUtil.init(publicKeyPath, resourceLoader);
+        log.info("Gateway JWT 初始化完成: publicKeyPath={}", publicKeyPath);
+    }
+}
+

+ 21 - 0
xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/config/GatewayPublicEndpointsProperties.java

@@ -0,0 +1,21 @@
+package com.xindazhou.gateway.config;
+
+import lombok.Data;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Gateway 公开接口配置属性
+ *
+ * @author xindazhou
+ */
+@Data
+public class GatewayPublicEndpointsProperties {
+
+    /**
+     * 公开接口路径列表(支持 Ant 路径模式)
+     */
+    private List<String> publicEndpoints = new ArrayList<>();
+}
+

+ 49 - 0
xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/core/LoginUser.java

@@ -0,0 +1,49 @@
+package com.xindazhou.gateway.core;
+
+import lombok.Data;
+
+import java.time.LocalDateTime;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 登录用户信息(Gateway 专用简化版本)
+ * 用于在 Gateway 和下游服务之间传递用户信息
+ *
+ * @author xindazhou
+ */
+@Data
+public class LoginUser {
+
+    /**
+     * 用户编号
+     */
+    private Long id;
+
+    /**
+     * 用户类型
+     * 1=C端用户,2=管理后台用户
+     */
+    private Integer userType;
+
+    /**
+     * 额外的用户信息
+     */
+    private Map<String, String> info;
+
+    /**
+     * 租户编号
+     */
+    private Long tenantId;
+
+    /**
+     * 授权范围
+     */
+    private List<String> scopes;
+
+    /**
+     * 过期时间
+     */
+    private LocalDateTime expiresTime;
+}
+

+ 0 - 0
xdz-module-gateway/xdz-module-gateway-server/src/main/java/com/xindazhou/gateway/core/jwt/GatewayJwtUtil.java


Неке датотеке нису приказане због велике количине промена