From 33c138c839b1dbf865c6041b2f1225a69f799391 Mon Sep 17 00:00:00 2001 From: ylweng Date: Thu, 11 Sep 2025 23:23:51 +0800 Subject: [PATCH] =?UTF-8?q?feat(user-center):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E6=94=B6=E8=B4=A7=E5=9C=B0=E5=9D=80=E7=AE=A1=E7=90=86=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加收货地址实体类、控制器、服务类和数据访问接口 - 实现收货地址创建、获取列表、获取详情、更新和删除功能- 集成JWT认证,确保操作的安全性 - 新增相关API文档 --- backend-java/services/ai-service/pom.xml | 53 + .../com/xlxumu/ai/AIServiceApplication.java | 11 + .../src/main/resources/application.properties | 10 + .../services/data-platform-service/pom.xml | 53 + .../DataPlatformServiceApplication.java | 11 + .../src/main/resources/application.properties | 10 + backend-java/services/finance-service/pom.xml | 53 + .../finance/FinanceServiceApplication.java | 11 + .../src/main/resources/application.properties | 10 + .../services/government-service/pom.xml | 53 + .../GovernmentServiceApplication.java | 11 + .../src/main/resources/application.properties | 10 + backend-java/services/mall-service/pom.xml | 53 + .../xlxumu/mall/MallServiceApplication.java | 11 + .../src/main/resources/application.properties | 10 + backend-java/services/trade-service/pom.xml | 53 + .../xlxumu/trade/TradeServiceApplication.java | 11 + .../src/main/resources/application.properties | 10 + .../xlxumu/user/config/JwtInterceptor.java | 47 + .../com/xlxumu/user/config/WebConfig.java | 22 + .../user/controller/AddressController.java | 175 +++ .../user/controller/FeedbackController.java | 90 ++ .../user/controller/LevelController.java | 19 + .../user/controller/MessageController.java | 109 ++ .../user/controller/PointsController.java | 123 ++ .../user/controller/UserController.java | 165 +++ .../java/com/xlxumu/user/entity/Address.java | 151 ++ .../java/com/xlxumu/user/entity/Feedback.java | 137 ++ .../java/com/xlxumu/user/entity/Level.java | 117 ++ .../java/com/xlxumu/user/entity/Message.java | 126 ++ .../com/xlxumu/user/entity/PointsRecord.java | 84 ++ .../java/com/xlxumu/user/entity/User.java | 180 +++ .../com/xlxumu/user/entity/UserLevel.java | 86 ++ .../exception/GlobalExceptionHandler.java | 56 + .../xlxumu/user/exception/UserException.java | 26 + .../user/repository/AddressRepository.java | 32 + .../user/repository/FeedbackRepository.java | 24 + .../user/repository/LevelRepository.java | 24 + .../user/repository/MessageRepository.java | 32 + .../repository/PointsRecordRepository.java | 24 + .../user/repository/UserLevelRepository.java | 24 + .../user/repository/UserRepository.java | 46 + .../xlxumu/user/service/AddressService.java | 150 ++ .../xlxumu/user/service/FeedbackService.java | 64 + .../com/xlxumu/user/service/LevelService.java | 57 + .../xlxumu/user/service/MessageService.java | 67 + .../xlxumu/user/service/PointsService.java | 96 ++ .../com/xlxumu/user/service/UserService.java | 201 +++ .../com/xlxumu/user/util/JwtTokenUtil.java | 29 + .../java/com/xlxumu/user/util/JwtUtil.java | 114 ++ .../com/xlxumu/user/util/PasswordUtil.java | 73 + .../src/main/resources/api/address-api.yaml | 335 +++++ .../src/main/resources/api/feedback-api.yaml | 156 +++ .../src/main/resources/api/message-api.yaml | 190 +++ .../src/main/resources/api/openapi.yaml | 69 + .../src/main/resources/api/points-api.yaml | 213 +++ .../src/main/resources/api/user-api.yaml | 413 ++++++ .../src/main/resources/application.properties | 15 +- docs/design/api/ai_service_api_design.md | 467 +++++++ .../api/data_platform_service_api_design.md | 762 ++++++++++ docs/design/api/farming_service_api_design.md | 900 ++++++++++++ docs/design/api/finance_service_api_design.md | 535 +++++++ .../api/government_service_api_design.md | 883 ++++++++++++ docs/design/api/iot_service_api_design.md | 812 +++++++++++ docs/design/api/mall_service_api_design.md | 1233 +++++++++++++++++ docs/design/api/trade_service_api_design.md | 501 +++++++ .../api/user_center_service_api_design.md | 1162 ++++++++++++++++ docs/design/database/ai_service_db_design.md | 121 ++ .../data_platform_service_db_design.md | 263 ++++ .../database/farming_service_db_design.md | 157 +++ .../database/finance_service_db_design.md | 321 +++++ .../database/government_service_db_design.md | 193 +++ docs/design/database/iot_service_db_design.md | 159 +++ .../design/database/mall_service_db_design.md | 274 ++++ .../database/trade_service_db_design.md | 239 ++++ .../database/user_center_service_db_design.md | 367 +++++ .../backend_api_development_plan.md | 234 ++-- 77 files changed, 14049 insertions(+), 139 deletions(-) create mode 100644 backend-java/services/ai-service/pom.xml create mode 100644 backend-java/services/ai-service/src/main/java/com/xlxumu/ai/AIServiceApplication.java create mode 100644 backend-java/services/ai-service/src/main/resources/application.properties create mode 100644 backend-java/services/data-platform-service/pom.xml create mode 100644 backend-java/services/data-platform-service/src/main/java/com/xlxumu/dataplatform/DataPlatformServiceApplication.java create mode 100644 backend-java/services/data-platform-service/src/main/resources/application.properties create mode 100644 backend-java/services/finance-service/pom.xml create mode 100644 backend-java/services/finance-service/src/main/java/com/xlxumu/finance/FinanceServiceApplication.java create mode 100644 backend-java/services/finance-service/src/main/resources/application.properties create mode 100644 backend-java/services/government-service/pom.xml create mode 100644 backend-java/services/government-service/src/main/java/com/xlxumu/government/GovernmentServiceApplication.java create mode 100644 backend-java/services/government-service/src/main/resources/application.properties create mode 100644 backend-java/services/mall-service/pom.xml create mode 100644 backend-java/services/mall-service/src/main/java/com/xlxumu/mall/MallServiceApplication.java create mode 100644 backend-java/services/mall-service/src/main/resources/application.properties create mode 100644 backend-java/services/trade-service/pom.xml create mode 100644 backend-java/services/trade-service/src/main/java/com/xlxumu/trade/TradeServiceApplication.java create mode 100644 backend-java/services/trade-service/src/main/resources/application.properties create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/JwtInterceptor.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/WebConfig.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/AddressController.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/FeedbackController.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/LevelController.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/MessageController.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/PointsController.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/UserController.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Address.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Feedback.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Level.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Message.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/PointsRecord.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/User.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/UserLevel.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/GlobalExceptionHandler.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/UserException.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/AddressRepository.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/FeedbackRepository.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/LevelRepository.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/MessageRepository.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/PointsRecordRepository.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserLevelRepository.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserRepository.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/AddressService.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/FeedbackService.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/LevelService.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/MessageService.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/PointsService.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/UserService.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtTokenUtil.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtUtil.java create mode 100644 backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/PasswordUtil.java create mode 100644 backend-java/services/user-center-service/src/main/resources/api/address-api.yaml create mode 100644 backend-java/services/user-center-service/src/main/resources/api/feedback-api.yaml create mode 100644 backend-java/services/user-center-service/src/main/resources/api/message-api.yaml create mode 100644 backend-java/services/user-center-service/src/main/resources/api/openapi.yaml create mode 100644 backend-java/services/user-center-service/src/main/resources/api/points-api.yaml create mode 100644 backend-java/services/user-center-service/src/main/resources/api/user-api.yaml create mode 100644 docs/design/api/ai_service_api_design.md create mode 100644 docs/design/api/data_platform_service_api_design.md create mode 100644 docs/design/api/farming_service_api_design.md create mode 100644 docs/design/api/finance_service_api_design.md create mode 100644 docs/design/api/government_service_api_design.md create mode 100644 docs/design/api/iot_service_api_design.md create mode 100644 docs/design/api/mall_service_api_design.md create mode 100644 docs/design/api/trade_service_api_design.md create mode 100644 docs/design/api/user_center_service_api_design.md create mode 100644 docs/design/database/ai_service_db_design.md create mode 100644 docs/design/database/data_platform_service_db_design.md create mode 100644 docs/design/database/farming_service_db_design.md create mode 100644 docs/design/database/finance_service_db_design.md create mode 100644 docs/design/database/government_service_db_design.md create mode 100644 docs/design/database/iot_service_db_design.md create mode 100644 docs/design/database/mall_service_db_design.md create mode 100644 docs/design/database/trade_service_db_design.md create mode 100644 docs/design/database/user_center_service_db_design.md diff --git a/backend-java/services/ai-service/pom.xml b/backend-java/services/ai-service/pom.xml new file mode 100644 index 0000000..8019334 --- /dev/null +++ b/backend-java/services/ai-service/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.xlxumu + backend-java + 1.0.0 + + + + 1.0.0 + jar + + + AI能力服务 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + mysql + mysql-connector-java + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/backend-java/services/ai-service/src/main/java/com/xlxumu/ai/AIServiceApplication.java b/backend-java/services/ai-service/src/main/java/com/xlxumu/ai/AIServiceApplication.java new file mode 100644 index 0000000..94a4bb9 --- /dev/null +++ b/backend-java/services/ai-service/src/main/java/com/xlxumu/ai/AIServiceApplication.java @@ -0,0 +1,11 @@ +package com.xlxumu.ai; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class AIServiceApplication { + public static void main(String[] args) { + SpringApplication.run(AIServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/backend-java/services/ai-service/src/main/resources/application.properties b/backend-java/services/ai-service/src/main/resources/application.properties new file mode 100644 index 0000000..fbc1166 --- /dev/null +++ b/backend-java/services/ai-service/src/main/resources/application.properties @@ -0,0 +1,10 @@ +server.port=8089 + +spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_ai?useSSL=false&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file diff --git a/backend-java/services/data-platform-service/pom.xml b/backend-java/services/data-platform-service/pom.xml new file mode 100644 index 0000000..b67b39b --- /dev/null +++ b/backend-java/services/data-platform-service/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.xlxumu + backend-java + 1.0.0 + + + data-platform-service + 1.0.0 + jar + + data-platform-service + 数据平台服务 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + mysql + mysql-connector-java + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/backend-java/services/data-platform-service/src/main/java/com/xlxumu/dataplatform/DataPlatformServiceApplication.java b/backend-java/services/data-platform-service/src/main/java/com/xlxumu/dataplatform/DataPlatformServiceApplication.java new file mode 100644 index 0000000..27707ec --- /dev/null +++ b/backend-java/services/data-platform-service/src/main/java/com/xlxumu/dataplatform/DataPlatformServiceApplication.java @@ -0,0 +1,11 @@ +package com.xlxumu.dataplatform; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class DataPlatformServiceApplication { + public static void main(String[] args) { + SpringApplication.run(DataPlatformServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/backend-java/services/data-platform-service/src/main/resources/application.properties b/backend-java/services/data-platform-service/src/main/resources/application.properties new file mode 100644 index 0000000..68630ea --- /dev/null +++ b/backend-java/services/data-platform-service/src/main/resources/application.properties @@ -0,0 +1,10 @@ +server.port=8085 + +spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_data?useSSL=false&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file diff --git a/backend-java/services/finance-service/pom.xml b/backend-java/services/finance-service/pom.xml new file mode 100644 index 0000000..44c2f4c --- /dev/null +++ b/backend-java/services/finance-service/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.xlxumu + backend-java + 1.0.0 + + + finance-service + 1.0.0 + jar + + finance-service + 金融服务 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + mysql + mysql-connector-java + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/backend-java/services/finance-service/src/main/java/com/xlxumu/finance/FinanceServiceApplication.java b/backend-java/services/finance-service/src/main/java/com/xlxumu/finance/FinanceServiceApplication.java new file mode 100644 index 0000000..7d39ff6 --- /dev/null +++ b/backend-java/services/finance-service/src/main/java/com/xlxumu/finance/FinanceServiceApplication.java @@ -0,0 +1,11 @@ +package com.xlxumu.finance; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class FinanceServiceApplication { + public static void main(String[] args) { + SpringApplication.run(FinanceServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/backend-java/services/finance-service/src/main/resources/application.properties b/backend-java/services/finance-service/src/main/resources/application.properties new file mode 100644 index 0000000..25df0d3 --- /dev/null +++ b/backend-java/services/finance-service/src/main/resources/application.properties @@ -0,0 +1,10 @@ +server.port=8084 + +spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_finance?useSSL=false&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file diff --git a/backend-java/services/government-service/pom.xml b/backend-java/services/government-service/pom.xml new file mode 100644 index 0000000..16be42d --- /dev/null +++ b/backend-java/services/government-service/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.xlxumu + backend-java + 1.0.0 + + + + 1.0.0 + jar + + + 政务服务 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + mysql + mysql-connector-java + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/backend-java/services/government-service/src/main/java/com/xlxumu/government/GovernmentServiceApplication.java b/backend-java/services/government-service/src/main/java/com/xlxumu/government/GovernmentServiceApplication.java new file mode 100644 index 0000000..4bb079a --- /dev/null +++ b/backend-java/services/government-service/src/main/java/com/xlxumu/government/GovernmentServiceApplication.java @@ -0,0 +1,11 @@ +package com.xlxumu.government; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class GovernmentServiceApplication { + public static void main(String[] args) { + SpringApplication.run(GovernmentServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/backend-java/services/government-service/src/main/resources/application.properties b/backend-java/services/government-service/src/main/resources/application.properties new file mode 100644 index 0000000..4bbeccb --- /dev/null +++ b/backend-java/services/government-service/src/main/resources/application.properties @@ -0,0 +1,10 @@ +server.port=8086 + +spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_government?useSSL=false&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file diff --git a/backend-java/services/mall-service/pom.xml b/backend-java/services/mall-service/pom.xml new file mode 100644 index 0000000..d296788 --- /dev/null +++ b/backend-java/services/mall-service/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.xlxumu + backend-java + 1.0.0 + + + + 1.0.0 + jar + + + 商城服务 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + mysql + mysql-connector-java + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/backend-java/services/mall-service/src/main/java/com/xlxumu/mall/MallServiceApplication.java b/backend-java/services/mall-service/src/main/java/com/xlxumu/mall/MallServiceApplication.java new file mode 100644 index 0000000..6e3a6a6 --- /dev/null +++ b/backend-java/services/mall-service/src/main/java/com/xlxumu/mall/MallServiceApplication.java @@ -0,0 +1,11 @@ +package com.xlxumu.mall; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class MallServiceApplication { + public static void main(String[] args) { + SpringApplication.run(MallServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/backend-java/services/mall-service/src/main/resources/application.properties b/backend-java/services/mall-service/src/main/resources/application.properties new file mode 100644 index 0000000..4a1bc8f --- /dev/null +++ b/backend-java/services/mall-service/src/main/resources/application.properties @@ -0,0 +1,10 @@ +server.port=8088 + +spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_mall?useSSL=false&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file diff --git a/backend-java/services/trade-service/pom.xml b/backend-java/services/trade-service/pom.xml new file mode 100644 index 0000000..8bfa45c --- /dev/null +++ b/backend-java/services/trade-service/pom.xml @@ -0,0 +1,53 @@ + + + 4.0.0 + + + com.xlxumu + backend-java + 1.0.0 + + + trade-service + 1.0.0 + jar + + trade-service + 交易服务 + + + + org.springframework.boot + spring-boot-starter-web + + + + org.springframework.boot + spring-boot-starter-data-jpa + + + + mysql + mysql-connector-java + runtime + + + + org.springframework.boot + spring-boot-starter-test + test + + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + \ No newline at end of file diff --git a/backend-java/services/trade-service/src/main/java/com/xlxumu/trade/TradeServiceApplication.java b/backend-java/services/trade-service/src/main/java/com/xlxumu/trade/TradeServiceApplication.java new file mode 100644 index 0000000..8cf2e59 --- /dev/null +++ b/backend-java/services/trade-service/src/main/java/com/xlxumu/trade/TradeServiceApplication.java @@ -0,0 +1,11 @@ +package com.xlxumu.trade; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class TradeServiceApplication { + public static void main(String[] args) { + SpringApplication.run(TradeServiceApplication.class, args); + } +} \ No newline at end of file diff --git a/backend-java/services/trade-service/src/main/resources/application.properties b/backend-java/services/trade-service/src/main/resources/application.properties new file mode 100644 index 0000000..5c26d1f --- /dev/null +++ b/backend-java/services/trade-service/src/main/resources/application.properties @@ -0,0 +1,10 @@ +server.port=8083 + +spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_trade?useSSL=false&serverTimezone=UTC +spring.datasource.username=root +spring.datasource.password= +spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver + +spring.jpa.hibernate.ddl-auto=update +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/JwtInterceptor.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/JwtInterceptor.java new file mode 100644 index 0000000..37562bd --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/JwtInterceptor.java @@ -0,0 +1,47 @@ +package com.xlxumu.user.config; + +import com.xlxumu.user.util.JwtUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +@Component +public class JwtInterceptor implements HandlerInterceptor { + + @Autowired + private JwtUtil jwtUtil; + + @Override + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException { + // 获取请求头中的Authorization字段 + String authorizationHeader = request.getHeader("Authorization"); + + // 检查Authorization字段是否存在且以"Bearer "开头 + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { + // 提取JWT令牌 + String token = authorizationHeader.substring(7); + + try { + // 验证令牌 + Long userId = jwtUtil.getUserIdFromToken(token); + // 将用户ID添加到请求属性中,以便在控制器中使用 + request.setAttribute("userId", userId); + return true; + } catch (Exception e) { + // 令牌无效 + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.getWriter().write("{\"code\": 401, \"message\": \"无效的访问令牌\"}"); + return false; + } + } else { + // 缺少Authorization字段或格式不正确 + response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); + response.getWriter().write("{\"code\": 401, \"message\": \"缺少访问令牌\"}"); + return false; + } + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/WebConfig.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/WebConfig.java new file mode 100644 index 0000000..429c8e7 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/config/WebConfig.java @@ -0,0 +1,22 @@ +package com.xlxumu.user.config; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.servlet.config.annotation.InterceptorRegistry; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class WebConfig implements WebMvcConfigurer { + + @Autowired + private JwtInterceptor jwtInterceptor; + + @Override + public void addInterceptors(InterceptorRegistry registry) { + // 注册JWT拦截器,拦截除了注册和登录之外的所有API请求 + registry.addInterceptor(jwtInterceptor) + .addPathPatterns("/api/**") + .excludePathPatterns("/api/users/register") + .excludePathPatterns("/api/users/login"); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/AddressController.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/AddressController.java new file mode 100644 index 0000000..34ff191 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/AddressController.java @@ -0,0 +1,175 @@ +package com.xlxumu.user.controller; + +import com.xlxumu.user.entity.Address; +import com.xlxumu.user.service.AddressService; +import com.xlxumu.user.util.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 收货地址控制器 + * 处理收货地址相关的HTTP请求 + * + * @author xlxumu + * @since 2024-01-15 + */ +@RestController +@RequestMapping("/api/addresses") +public class AddressController { + + @Autowired + private AddressService addressService; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + /** + * 创建收货地址接口 + */ + @PostMapping + public ResponseEntity> createAddress( + HttpServletRequest request, + @RequestBody Map requestData) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + String name = (String) requestData.get("name"); + String phone = (String) requestData.get("phone"); + String province = (String) requestData.get("province"); + String city = (String) requestData.get("city"); + String district = (String) requestData.get("district"); + String detailAddress = (String) requestData.get("detailAddress"); + Boolean isDefault = (Boolean) requestData.get("isDefault"); + + Address address = addressService.createAddress(userId, name, phone, province, city, district, detailAddress, isDefault); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "地址创建成功"); + response.put("data", address); + + return ResponseEntity.ok(response); + } + + /** + * 获取收货地址列表接口 + */ + @GetMapping + public ResponseEntity> getAddressList(HttpServletRequest request) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + List
addresses = addressService.getAddressList(userId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", addresses); + + return ResponseEntity.ok(response); + } + + /** + * 获取收货地址详情接口 + */ + @GetMapping("/{addressId}") + public ResponseEntity> getAddressDetail( + HttpServletRequest request, + @PathVariable Long addressId) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + Address address = addressService.getAddressDetail(userId, addressId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", address); + + return ResponseEntity.ok(response); + } + + /** + * 更新收货地址接口 + */ + @PutMapping("/{addressId}") + public ResponseEntity> updateAddress( + HttpServletRequest request, + @PathVariable Long addressId, + @RequestBody Map requestData) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + String name = (String) requestData.get("name"); + String phone = (String) requestData.get("phone"); + String province = (String) requestData.get("province"); + String city = (String) requestData.get("city"); + String district = (String) requestData.get("district"); + String detailAddress = (String) requestData.get("detailAddress"); + Boolean isDefault = (Boolean) requestData.get("isDefault"); + + Address address = addressService.updateAddress(userId, addressId, name, phone, province, city, district, detailAddress, isDefault); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "地址更新成功"); + response.put("data", address); + + return ResponseEntity.ok(response); + } + + /** + * 删除收货地址接口 + */ + @DeleteMapping("/{addressId}") + public ResponseEntity> deleteAddress( + HttpServletRequest request, + @PathVariable Long addressId) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + addressService.deleteAddress(userId, addressId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "地址删除成功"); + + return ResponseEntity.ok(response); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/FeedbackController.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/FeedbackController.java new file mode 100644 index 0000000..45a7967 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/FeedbackController.java @@ -0,0 +1,90 @@ +package com.xlxumu.user.controller; + +import com.xlxumu.user.entity.Feedback; +import com.xlxumu.user.service.FeedbackService; +import com.xlxumu.user.service.PointsService; +import com.xlxumu.user.util.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 用户反馈控制器 + * 处理用户反馈相关的HTTP请求 + * + * @author xlxumu + * @since 2024-01-15 + */ +@RestController +@RequestMapping("/api/feedback") +public class FeedbackController { + + @Autowired + private FeedbackService feedbackService; + + @Autowired + private PointsService pointsService; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + /** + * 提交反馈接口 + */ + @PostMapping + public ResponseEntity> submitFeedback( + HttpServletRequest request, + @RequestBody Map requestData) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + String title = requestData.get("title"); + String content = requestData.get("content"); + String type = requestData.get("type"); + String contactInfo = requestData.get("contactInfo"); + + Feedback feedback = feedbackService.submitFeedback(userId, title, content, type, contactInfo); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "反馈提交成功"); + response.put("data", feedback); + + return ResponseEntity.ok(response); + } + + /** + * 获取反馈列表接口 + */ + @GetMapping + public ResponseEntity> getFeedbackList(HttpServletRequest request) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + List feedbacks = feedbackService.getFeedbackList(userId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", feedbacks); + + return ResponseEntity.ok(response); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/LevelController.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/LevelController.java new file mode 100644 index 0000000..cc75b21 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/LevelController.java @@ -0,0 +1,19 @@ +package com.xlxumu.user.controller; + +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * 等级管理控制器 + * 提供用户等级查询、等级列表查询等API接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@RestController +@RequestMapping("/api/v1/users") +public class LevelController { + + // TODO: 实现获取用户当前等级接口 + // TODO: 实现获取等级列表接口 +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/MessageController.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/MessageController.java new file mode 100644 index 0000000..445892f --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/MessageController.java @@ -0,0 +1,109 @@ +package com.xlxumu.user.controller; + +import com.xlxumu.user.entity.Message; +import com.xlxumu.user.service.MessageService; +import com.xlxumu.user.service.PointsService; +import com.xlxumu.user.util.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 消息通知控制器 + * 处理用户消息相关的HTTP请求 + * + * @author xlxumu + * @since 2024-01-15 + */ +@RestController +@RequestMapping("/api/messages") +public class MessageController { + + @Autowired + private MessageService messageService; + + @Autowired + private PointsService pointsService; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + /** + * 获取消息列表接口 + */ + @GetMapping + public ResponseEntity> getMessageList(HttpServletRequest request) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + List messages = messageService.getMessageList(userId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", messages); + + return ResponseEntity.ok(response); + } + + /** + * 标记消息为已读接口 + */ + @PutMapping("/{messageId}/read") + public ResponseEntity> markMessageAsRead( + HttpServletRequest request, + @PathVariable Long messageId) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + messageService.markMessageAsRead(messageId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "标记成功"); + + return ResponseEntity.ok(response); + } + + /** + * 删除消息接口 + */ + @DeleteMapping("/{messageId}") + public ResponseEntity> deleteMessage( + HttpServletRequest request, + @PathVariable Long messageId) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + messageService.deleteMessage(messageId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "删除成功"); + + return ResponseEntity.ok(response); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/PointsController.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/PointsController.java new file mode 100644 index 0000000..e1314c0 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/PointsController.java @@ -0,0 +1,123 @@ +package com.xlxumu.user.controller; + +import com.xlxumu.user.entity.Level; +import com.xlxumu.user.entity.PointsRecord; +import com.xlxumu.user.service.LevelService; +import com.xlxumu.user.service.PointsService; +import com.xlxumu.user.util.JwtTokenUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 积分管理控制器 + * 处理用户积分相关的HTTP请求 + * + * @author xlxumu + * @since 2024-01-15 + */ +@RestController +@RequestMapping("/api/points") +public class PointsController { + + @Autowired + private PointsService pointsService; + + @Autowired + private LevelService levelService; + + @Autowired + private JwtTokenUtil jwtTokenUtil; + + /** + * 获取用户积分余额接口 + */ + @GetMapping("/balance") + public ResponseEntity> getUserPointsBalance(HttpServletRequest request) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + Integer balance = pointsService.getUserPointsBalance(userId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", Map.of("balance", balance)); + + return ResponseEntity.ok(response); + } + + /** + * 获取积分记录列表接口 + */ + @GetMapping("/records") + public ResponseEntity> getPointsRecordList(HttpServletRequest request) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + List records = pointsService.getPointsRecordList(userId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", records); + + return ResponseEntity.ok(response); + } + + /** + * 获取用户当前等级接口 + */ + @GetMapping("/level") + public ResponseEntity> getUserCurrentLevel(HttpServletRequest request) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + if (userId == null) { + Map errorResponse = new HashMap<>(); + errorResponse.put("code", 401); + errorResponse.put("message", "无效的访问令牌"); + return ResponseEntity.status(401).body(errorResponse); + } + + Level level = levelService.getUserCurrentLevel(userId); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", level); + + return ResponseEntity.ok(response); + } + + /** + * 获取等级列表接口 + */ + @GetMapping("/levels") + public ResponseEntity> getLevelList() { + List levels = levelService.getLevelList(); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", levels); + + return ResponseEntity.ok(response); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/UserController.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/UserController.java new file mode 100644 index 0000000..e5d1066 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/controller/UserController.java @@ -0,0 +1,165 @@ +package com.xlxumu.user.controller; + +import com.xlxumu.user.entity.User; +import com.xlxumu.user.service.UserService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * 用户管理控制器 + * 处理用户相关的HTTP请求 + * + * @author xlxumu + * @since 2024-01-15 + */ +@RestController +@RequestMapping("/api/users") +public class UserController { + + @Autowired + private UserService userService; + + /** + * 用户注册接口 + */ + @PostMapping("/register") + public ResponseEntity> register(@RequestBody Map request) { + String username = request.get("username"); + String password = request.get("password"); + String email = request.get("email"); + String phone = request.get("phone"); + + User user = userService.register(username, password, email, phone); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "注册成功"); + response.put("data", user); + + return ResponseEntity.ok(response); + } + + /** + * 用户登录接口 + */ + @PostMapping("/login") + public ResponseEntity> login(@RequestBody Map request) { + String username = request.get("username"); + String password = request.get("password"); + + String token = userService.login(username, password); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "登录成功"); + response.put("data", Map.of("token", token)); + + return ResponseEntity.ok(response); + } + + /** + * 获取用户信息 + * @param request HTTP请求 + * @return 用户信息 + */ + @GetMapping("/info") + public ResponseEntity> getUserInfo(HttpServletRequest request) { + // 从JWT令牌中获取用户ID + Long userId = jwtTokenUtil.getUserIdFromRequest(request); + + if (userId == null) { + return ResponseEntity.status(HttpStatus.UNAUTHORIZED) + .body(new ApiResponse<>(401, "无效的访问令牌", null)); + } + + try { + User user = userService.getUserById(userId); + return ResponseEntity.ok(new ApiResponse<>(200, "获取成功", user)); + } catch (UserException e) { + return ResponseEntity.badRequest().body(new ApiResponse<>(e.getCode(), e.getMessage(), null)); + } + } + + /** + * 更新用户信息接口 + */ + @PutMapping("/info") + public ResponseEntity> updateUserInfo( + @RequestHeader("Authorization") String token, + @RequestBody Map request) { + String nickname = request.get("nickname"); + String avatar = request.get("avatar"); + String gender = request.get("gender"); + String birthday = request.get("birthday"); + + User user = userService.updateUserInfo(token, nickname, avatar, gender, birthday); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "更新成功"); + response.put("data", user); + + return ResponseEntity.ok(response); + } + + /** + * 修改密码接口 + */ + @PutMapping("/password") + public ResponseEntity> changePassword( + @RequestHeader("Authorization") String token, + @RequestBody Map request) { + String oldPassword = request.get("oldPassword"); + String newPassword = request.get("newPassword"); + + userService.changePassword(token, oldPassword, newPassword); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "密码修改成功"); + + return ResponseEntity.ok(response); + } + + /** + * 管理员获取用户列表接口 + */ + @GetMapping("/list") + public ResponseEntity> getUserList( + @RequestHeader("Authorization") String token, + @RequestParam(defaultValue = "1") Integer page, + @RequestParam(defaultValue = "10") Integer size) { + List users = userService.getUserList(token, page, size); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "获取成功"); + response.put("data", users); + + return ResponseEntity.ok(response); + } + + /** + * 管理员更新用户状态接口 + */ + @PutMapping("/{userId}/status") + public ResponseEntity> updateUserStatus( + @RequestHeader("Authorization") String token, + @PathVariable Long userId, + @RequestBody Map request) { + Integer status = request.get("status"); + + userService.updateUserStatus(token, userId, status); + + Map response = new HashMap<>(); + response.put("code", 200); + response.put("message", "状态更新成功"); + + return ResponseEntity.ok(response); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Address.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Address.java new file mode 100644 index 0000000..5bf7e5c --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Address.java @@ -0,0 +1,151 @@ +package com.xlxumu.user.entity; + +import javax.persistence.*; +import java.time.LocalDateTime; + +/** + * 收货地址实体类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Entity +@Table(name = "addresses") +public class Address { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "user_id", nullable = false) + private Long userId; + + @Column(name = "receiver_name", nullable = false) + private String receiverName; + + @Column(name = "receiver_phone", nullable = false) + private String receiverPhone; + + @Column(name = "province", nullable = false) + private String province; + + @Column(name = "city", nullable = false) + private String city; + + @Column(name = "district", nullable = false) + private String district; + + @Column(name = "detail_address", nullable = false) + private String detailAddress; + + @Column(name = "is_default") + private Boolean isDefault = false; + + private Integer status = 1; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; + + // Constructors + public Address() {} + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getReceiverName() { + return receiverName; + } + + public void setReceiverName(String receiverName) { + this.receiverName = receiverName; + } + + public String getReceiverPhone() { + return receiverPhone; + } + + public void setReceiverPhone(String receiverPhone) { + this.receiverPhone = receiverPhone; + } + + public String getProvince() { + return province; + } + + public void setProvince(String province) { + this.province = province; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + public String getDistrict() { + return district; + } + + public void setDistrict(String district) { + this.district = district; + } + + public String getDetailAddress() { + return detailAddress; + } + + public void setDetailAddress(String detailAddress) { + this.detailAddress = detailAddress; + } + + public Boolean getIsDefault() { + return isDefault; + } + + public void setIsDefault(Boolean isDefault) { + this.isDefault = isDefault; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Feedback.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Feedback.java new file mode 100644 index 0000000..65f9f24 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Feedback.java @@ -0,0 +1,137 @@ +package com.xlxumu.user.entity; + +import javax.persistence.*; +import java.time.LocalDateTime; + +/** + * 用户反馈实体类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Entity +@Table(name = "feedbacks") +public class Feedback { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "user_id", nullable = false) + private Long userId; + + private String title; + + private String content; + + private Integer type; + + @Column(name = "contact_info") + private String contactInfo; + + private Integer status = 1; + + @Column(name = "reply_content") + private String replyContent; + + @Column(name = "replied_at") + private LocalDateTime repliedAt; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; + + // Constructors + public Feedback() {} + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public String getContactInfo() { + return contactInfo; + } + + public void setContactInfo(String contactInfo) { + this.contactInfo = contactInfo; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public String getReplyContent() { + return replyContent; + } + + public void setReplyContent(String replyContent) { + this.replyContent = replyContent; + } + + public LocalDateTime getRepliedAt() { + return repliedAt; + } + + public void setRepliedAt(LocalDateTime repliedAt) { + this.repliedAt = repliedAt; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Level.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Level.java new file mode 100644 index 0000000..8b816a0 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Level.java @@ -0,0 +1,117 @@ +package com.xlxumu.user.entity; + +import javax.persistence.*; +import java.time.LocalDateTime; + +/** + * 等级定义实体类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Entity +@Table(name = "levels") +public class Level { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, unique = true) + private String name; + + private String description; + + @Column(name = "min_points", nullable = false) + private Integer minPoints; + + @Column(name = "max_points") + private Integer maxPoints; + + @Column(name = "benefits") + private String benefits; + + private Integer status = 1; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; + + // Constructors + public Level() {} + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public Integer getMinPoints() { + return minPoints; + } + + public void setMinPoints(Integer minPoints) { + this.minPoints = minPoints; + } + + public Integer getMaxPoints() { + return maxPoints; + } + + public void setMaxPoints(Integer maxPoints) { + this.maxPoints = maxPoints; + } + + public String getBenefits() { + return benefits; + } + + public void setBenefits(String benefits) { + this.benefits = benefits; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Message.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Message.java new file mode 100644 index 0000000..2295c17 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/Message.java @@ -0,0 +1,126 @@ +package com.xlxumu.user.entity; + +import javax.persistence.*; +import java.time.LocalDateTime; + +/** + * 用户消息实体类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Entity +@Table(name = "messages") +public class Message { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "user_id", nullable = false) + private Long userId; + + @Column(name = "sender_id") + private Long senderId; + + private String title; + + private String content; + + private Integer type; + + @Column(name = "is_read") + private Boolean isRead = false; + + private Integer status = 1; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @Column(name = "read_at") + private LocalDateTime readAt; + + // Constructors + public Message() {} + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getSenderId() { + return senderId; + } + + public void setSenderId(Long senderId) { + this.senderId = senderId; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Integer getType() { + return type; + } + + public void setType(Integer type) { + this.type = type; + } + + public Boolean getIsRead() { + return isRead; + } + + public void setIsRead(Boolean isRead) { + this.isRead = isRead; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getReadAt() { + return readAt; + } + + public void setReadAt(LocalDateTime readAt) { + this.readAt = readAt; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/PointsRecord.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/PointsRecord.java new file mode 100644 index 0000000..7977b8a --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/PointsRecord.java @@ -0,0 +1,84 @@ +package com.xlxumu.user.entity; + +import javax.persistence.*; +import java.time.LocalDateTime; + +/** + * 积分记录实体类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Entity +@Table(name = "points_records") +public class PointsRecord { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "user_id", nullable = false) + private Long userId; + + private Integer points; + + @Column(name = "change_type", nullable = false) + private String changeType; + + private String description; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + // Constructors + public PointsRecord() {} + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Integer getPoints() { + return points; + } + + public void setPoints(Integer points) { + this.points = points; + } + + public String getChangeType() { + return changeType; + } + + public void setChangeType(String changeType) { + this.changeType = changeType; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/User.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/User.java new file mode 100644 index 0000000..4a1df71 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/User.java @@ -0,0 +1,180 @@ +package com.xlxumu.user.entity; + +import javax.persistence.*; +import java.time.LocalDateTime; + +/** + * 用户基本信息实体类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Entity +@Table(name = "users") +public class User { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(nullable = false, unique = true) + private String username; + + @Column(nullable = false, unique = true) + private String email; + + private String phone; + + @Column(name = "password_hash", nullable = false) + private String passwordHash; + + private String nickname; + + @Column(name = "avatar_url") + private String avatarUrl; + + private Integer gender; + + private LocalDateTime birthday; + + @Column(name = "real_name") + private String realName; + + @Column(name = "id_card_number") + private String idCardNumber; + + private Integer status = 1; + + @Column(name = "last_login_at") + private LocalDateTime lastLoginAt; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; + + // Constructors + public User() {} + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getEmail() { + return email; + } + + public void setEmail(String email) { + this.email = email; + } + + public String getPhone() { + return phone; + } + + public void setPhone(String phone) { + this.phone = phone; + } + + public String getPasswordHash() { + return passwordHash; + } + + public void setPasswordHash(String passwordHash) { + this.passwordHash = passwordHash; + } + + public String getNickname() { + return nickname; + } + + public void setNickname(String nickname) { + this.nickname = nickname; + } + + public String getAvatarUrl() { + return avatarUrl; + } + + public void setAvatarUrl(String avatarUrl) { + this.avatarUrl = avatarUrl; + } + + public Integer getGender() { + return gender; + } + + public void setGender(Integer gender) { + this.gender = gender; + } + + public LocalDateTime getBirthday() { + return birthday; + } + + public void setBirthday(LocalDateTime birthday) { + this.birthday = birthday; + } + + public String getRealName() { + return realName; + } + + public void setRealName(String realName) { + this.realName = realName; + } + + public String getIdCardNumber() { + return idCardNumber; + } + + public void setIdCardNumber(String idCardNumber) { + this.idCardNumber = idCardNumber; + } + + public Integer getStatus() { + return status; + } + + public void setStatus(Integer status) { + this.status = status; + } + + public LocalDateTime getLastLoginAt() { + return lastLoginAt; + } + + public void setLastLoginAt(LocalDateTime lastLoginAt) { + this.lastLoginAt = lastLoginAt; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/UserLevel.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/UserLevel.java new file mode 100644 index 0000000..a584421 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/entity/UserLevel.java @@ -0,0 +1,86 @@ +package com.xlxumu.user.entity; + +import javax.persistence.*; +import java.time.LocalDateTime; + +/** + * 用户等级实体类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Entity +@Table(name = "user_levels") +public class UserLevel { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Long id; + + @Column(name = "user_id", nullable = false, unique = true) + private Long userId; + + @Column(name = "level_id", nullable = false) + private Long levelId; + + @Column(name = "current_points") + private Integer currentPoints = 0; + + @Column(name = "created_at", nullable = false) + private LocalDateTime createdAt; + + @Column(name = "updated_at", nullable = false) + private LocalDateTime updatedAt; + + // Constructors + public UserLevel() {} + + // Getters and Setters + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public Long getLevelId() { + return levelId; + } + + public void setLevelId(Long levelId) { + this.levelId = levelId; + } + + public Integer getCurrentPoints() { + return currentPoints; + } + + public void setCurrentPoints(Integer currentPoints) { + this.currentPoints = currentPoints; + } + + public LocalDateTime getCreatedAt() { + return createdAt; + } + + public void setCreatedAt(LocalDateTime createdAt) { + this.createdAt = createdAt; + } + + public LocalDateTime getUpdatedAt() { + return updatedAt; + } + + public void setUpdatedAt(LocalDateTime updatedAt) { + this.updatedAt = updatedAt; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/GlobalExceptionHandler.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/GlobalExceptionHandler.java new file mode 100644 index 0000000..c773b0e --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/GlobalExceptionHandler.java @@ -0,0 +1,56 @@ +package com.xlxumu.user.exception; + +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.ControllerAdvice; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.context.request.WebRequest; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +/** + * 全局异常处理类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@ControllerAdvice +public class GlobalExceptionHandler { + + /** + * 处理用户相关异常 + * @param ex 异常对象 + * @param request 请求对象 + * @return 错误响应 + */ + @ExceptionHandler(UserException.class) + public ResponseEntity handleUserException(UserException ex, WebRequest request) { + Map body = new HashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", ex.getStatus()); + body.put("error", ex.getMessage()); + body.put("path", request.getDescription(false).replace("uri=", "")); + + return new ResponseEntity<>(body, HttpStatus.valueOf(ex.getStatus())); + } + + /** + * 处理通用异常 + * @param ex 异常对象 + * @param request 请求对象 + * @return 错误响应 + */ + @ExceptionHandler(Exception.class) + public ResponseEntity handleGenericException(Exception ex, WebRequest request) { + Map body = new HashMap<>(); + body.put("timestamp", LocalDateTime.now()); + body.put("status", HttpStatus.INTERNAL_SERVER_ERROR.value()); + body.put("error", "Internal Server Error"); + body.put("message", ex.getMessage()); + body.put("path", request.getDescription(false).replace("uri=", "")); + + return new ResponseEntity<>(body, HttpStatus.INTERNAL_SERVER_ERROR); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/UserException.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/UserException.java new file mode 100644 index 0000000..99242cf --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/exception/UserException.java @@ -0,0 +1,26 @@ +package com.xlxumu.user.exception; + +/** + * 用户相关自定义异常类 + * + * @author xlxumu + * @since 2024-01-15 + */ +public class UserException extends RuntimeException { + + private int status; + + public UserException(String message, int status) { + super(message); + this.status = status; + } + + public UserException(String message, Throwable cause, int status) { + super(message, cause); + this.status = status; + } + + public int getStatus() { + return status; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/AddressRepository.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/AddressRepository.java new file mode 100644 index 0000000..e03dd2a --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/AddressRepository.java @@ -0,0 +1,32 @@ +package com.xlxumu.user.repository; + +import com.xlxumu.user.entity.Address; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 收货地址数据访问接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Repository +public interface AddressRepository extends JpaRepository { + + /** + * 根据用户ID查找收货地址列表 + * @param userId 用户ID + * @return 收货地址列表 + */ + List
findByUserId(Long userId); + + /** + * 根据用户ID和默认地址标识查找默认收货地址 + * @param userId 用户ID + * @param isDefault 是否默认地址 + * @return 收货地址 + */ + Address findByUserIdAndIsDefault(Long userId, Boolean isDefault); +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/FeedbackRepository.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/FeedbackRepository.java new file mode 100644 index 0000000..0ddbe66 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/FeedbackRepository.java @@ -0,0 +1,24 @@ +package com.xlxumu.user.repository; + +import com.xlxumu.user.entity.Feedback; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 用户反馈数据访问接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Repository +public interface FeedbackRepository extends JpaRepository { + + /** + * 根据用户ID查找反馈列表 + * @param userId 用户ID + * @return 反馈列表 + */ + List findByUserIdOrderByCreatedAtDesc(Long userId); +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/LevelRepository.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/LevelRepository.java new file mode 100644 index 0000000..92920a6 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/LevelRepository.java @@ -0,0 +1,24 @@ +package com.xlxumu.user.repository; + +import com.xlxumu.user.entity.Level; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 等级定义数据访问接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Repository +public interface LevelRepository extends JpaRepository { + + /** + * 根据状态查找等级列表 + * @param status 状态 + * @return 等级列表 + */ + List findByStatusOrderByMinPointsAsc(Integer status); +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/MessageRepository.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/MessageRepository.java new file mode 100644 index 0000000..e80130b --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/MessageRepository.java @@ -0,0 +1,32 @@ +package com.xlxumu.user.repository; + +import com.xlxumu.user.entity.Message; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 用户消息数据访问接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Repository +public interface MessageRepository extends JpaRepository { + + /** + * 根据用户ID查找消息列表 + * @param userId 用户ID + * @return 消息列表 + */ + List findByUserIdOrderByCreatedAtDesc(Long userId); + + /** + * 根据用户ID和已读状态查找消息列表 + * @param userId 用户ID + * @param isRead 是否已读 + * @return 消息列表 + */ + List findByUserIdAndIsReadOrderByCreatedAtDesc(Long userId, Boolean isRead); +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/PointsRecordRepository.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/PointsRecordRepository.java new file mode 100644 index 0000000..a2360cb --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/PointsRecordRepository.java @@ -0,0 +1,24 @@ +package com.xlxumu.user.repository; + +import com.xlxumu.user.entity.PointsRecord; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.List; + +/** + * 积分记录数据访问接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Repository +public interface PointsRecordRepository extends JpaRepository { + + /** + * 根据用户ID查找积分记录列表 + * @param userId 用户ID + * @return 积分记录列表 + */ + List findByUserIdOrderByCreatedAtDesc(Long userId); +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserLevelRepository.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserLevelRepository.java new file mode 100644 index 0000000..2c18705 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserLevelRepository.java @@ -0,0 +1,24 @@ +package com.xlxumu.user.repository; + +import com.xlxumu.user.entity.UserLevel; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +/** + * 用户等级数据访问接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Repository +public interface UserLevelRepository extends JpaRepository { + + /** + * 根据用户ID查找用户等级信息 + * @param userId 用户ID + * @return 用户等级信息 + */ + Optional findByUserId(Long userId); +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserRepository.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserRepository.java new file mode 100644 index 0000000..900caeb --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/repository/UserRepository.java @@ -0,0 +1,46 @@ +package com.xlxumu.user.repository; + +import com.xlxumu.user.entity.User; +import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.stereotype.Repository; + +import java.util.Optional; + +/** + * 用户信息数据访问接口 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Repository +public interface UserRepository extends JpaRepository { + + /** + * 根据用户名查找用户 + * @param username 用户名 + * @return 用户信息 + */ + Optional findByUsername(String username); + + /** + * 根据邮箱查找用户 + * @param email 邮箱 + * @return 用户信息 + */ + Optional findByEmail(String email); + + /** + * 根据手机号查找用户 + * @param phone 手机号 + * @return 用户信息 + */ + Optional findByPhone(String phone); + + /** + * 根据用户名和密码查找用户 + * @param username 用户名 + * @param passwordHash 密码哈希值 + * @return 用户信息 + */ + Optional findByUsernameAndPasswordHash(String username, String passwordHash); +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/AddressService.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/AddressService.java new file mode 100644 index 0000000..fe35841 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/AddressService.java @@ -0,0 +1,150 @@ +package com.xlxumu.user.service; + +import com.xlxumu.user.entity.Address; +import com.xlxumu.user.exception.UserException; +import com.xlxumu.user.repository.AddressRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +/** + * 收货地址服务类 + * 提供收货地址相关的业务逻辑处理 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Service +public class AddressService { + + @Autowired + private AddressRepository addressRepository; + + /** + * 创建收货地址 + * @param userId 用户ID + * @param receiverName 收货人姓名 + * @param receiverPhone 收货人电话 + * @param province 省 + * @param city 市 + * @param district 区 + * @param detailAddress 详细地址 + * @param isDefault 是否默认地址 + * @return 创建的地址信息 + */ + public Address createAddress(Long userId, String receiverName, String receiverPhone, + String province, String city, String district, String detailAddress, + Boolean isDefault) { + // 如果设置为默认地址,需要将其他地址设为非默认 + if (isDefault != null && isDefault) { + Address defaultAddress = addressRepository.findByUserIdAndIsDefault(userId, true); + if (defaultAddress != null) { + defaultAddress.setIsDefault(false); + addressRepository.save(defaultAddress); + } + } + + Address address = new Address(); + address.setUserId(userId); + address.setReceiverName(receiverName); + address.setReceiverPhone(receiverPhone); + address.setProvince(province); + address.setCity(city); + address.setDistrict(district); + address.setDetailAddress(detailAddress); + address.setIsDefault(isDefault != null ? isDefault : false); + address.setStatus(1); + address.setCreatedAt(LocalDateTime.now()); + address.setUpdatedAt(LocalDateTime.now()); + + return addressRepository.save(address); + } + + /** + * 获取收货地址列表 + * @param userId 用户ID + * @return 地址列表 + */ + public List
getAddressList(Long userId) { + return addressRepository.findByUserId(userId); + } + + /** + * 获取收货地址详情 + * @param addressId 地址ID + * @return 地址信息 + */ + public Address getAddressDetail(Long addressId) { + Optional
addressOptional = addressRepository.findById(addressId); + if (!addressOptional.isPresent()) { + throw new UserException("地址不存在", 404); + } + + return addressOptional.get(); + } + + /** + * 更新收货地址 + * @param addressId 地址ID + * @param receiverName 收货人姓名 + * @param receiverPhone 收货人电话 + * @param province 省 + * @param city 市 + * @param district 区 + * @param detailAddress 详细地址 + * @param isDefault 是否默认地址 + * @return 更新后的地址信息 + */ + public Address updateAddress(Long addressId, String receiverName, String receiverPhone, + String province, String city, String district, String detailAddress, + Boolean isDefault) { + Optional
addressOptional = addressRepository.findById(addressId); + if (!addressOptional.isPresent()) { + throw new UserException("地址不存在", 404); + } + + Address address = addressOptional.get(); + + // 如果设置为默认地址,需要将其他地址设为非默认 + if (isDefault != null && isDefault) { + Address defaultAddress = addressRepository.findByUserIdAndIsDefault(address.getUserId(), true); + if (defaultAddress != null && !defaultAddress.getId().equals(addressId)) { + defaultAddress.setIsDefault(false); + addressRepository.save(defaultAddress); + } + } + + address.setReceiverName(receiverName); + address.setReceiverPhone(receiverPhone); + address.setProvince(province); + address.setCity(city); + address.setDistrict(district); + address.setDetailAddress(detailAddress); + if (isDefault != null) { + address.setIsDefault(isDefault); + } + address.setUpdatedAt(LocalDateTime.now()); + + return addressRepository.save(address); + } + + /** + * 删除收货地址 + * @param addressId 地址ID + */ + public void deleteAddress(Long addressId) { + Optional
addressOptional = addressRepository.findById(addressId); + if (!addressOptional.isPresent()) { + throw new UserException("地址不存在", 404); + } + + Address address = addressOptional.get(); + address.setStatus(0); // 软删除 + address.setUpdatedAt(LocalDateTime.now()); + + addressRepository.save(address); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/FeedbackService.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/FeedbackService.java new file mode 100644 index 0000000..b41d243 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/FeedbackService.java @@ -0,0 +1,64 @@ +package com.xlxumu.user.service; + +import com.xlxumu.user.entity.Feedback; +import com.xlxumu.user.exception.UserException; +import com.xlxumu.user.repository.FeedbackRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 用户反馈服务类 + * 提供用户反馈相关的业务逻辑处理 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Service +public class FeedbackService { + + @Autowired + private FeedbackRepository feedbackRepository; + + /** + * 提交反馈 + * @param userId 用户ID + * @param title 反馈标题 + * @param content 反馈内容 + * @param type 反馈类型 + * @param contactInfo 联系方式 + * @return 提交的反馈对象 + */ + public Feedback submitFeedback(Long userId, String title, String content, String type, String contactInfo) { + if (title == null || title.trim().isEmpty()) { + throw new UserException("反馈标题不能为空", 400); + } + + if (content == null || content.trim().isEmpty()) { + throw new UserException("反馈内容不能为空", 400); + } + + Feedback feedback = new Feedback(); + feedback.setUserId(userId); + feedback.setTitle(title); + feedback.setContent(content); + feedback.setType(type); + feedback.setContactInfo(contactInfo); + feedback.setStatus(1); // 1-待处理 + feedback.setCreatedAt(LocalDateTime.now()); + feedback.setUpdatedAt(LocalDateTime.now()); + + return feedbackRepository.save(feedback); + } + + /** + * 获取反馈列表 + * @param userId 用户ID + * @return 反馈列表 + */ + public List getFeedbackList(Long userId) { + return feedbackRepository.findByUserIdOrderByCreatedAtDesc(userId); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/LevelService.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/LevelService.java new file mode 100644 index 0000000..8a3e3f0 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/LevelService.java @@ -0,0 +1,57 @@ +package com.xlxumu.user.service; + +import com.xlxumu.user.entity.Level; +import com.xlxumu.user.entity.UserLevel; +import com.xlxumu.user.exception.UserException; +import com.xlxumu.user.repository.LevelRepository; +import com.xlxumu.user.repository.UserLevelRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; +import java.util.Optional; + +/** + * 等级管理服务类 + * 提供用户等级相关的业务逻辑处理 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Service +public class LevelService { + + @Autowired + private UserLevelRepository userLevelRepository; + + @Autowired + private LevelRepository levelRepository; + + /** + * 获取用户当前等级 + * @param userId 用户ID + * @return 用户等级信息 + */ + public Level getUserCurrentLevel(Long userId) { + Optional userLevelOptional = userLevelRepository.findByUserId(userId); + if (!userLevelOptional.isPresent()) { + throw new UserException("用户等级信息不存在", 404); + } + + Long levelId = userLevelOptional.get().getLevelId(); + Optional levelOptional = levelRepository.findById(levelId); + if (!levelOptional.isPresent()) { + throw new UserException("等级信息不存在", 404); + } + + return levelOptional.get(); + } + + /** + * 获取等级列表 + * @return 等级列表 + */ + public List getLevelList() { + return levelRepository.findByStatusOrderByMinPointsAsc(1); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/MessageService.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/MessageService.java new file mode 100644 index 0000000..d9b3d31 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/MessageService.java @@ -0,0 +1,67 @@ +package com.xlxumu.user.service; + +import com.xlxumu.user.entity.Message; +import com.xlxumu.user.exception.UserException; +import com.xlxumu.user.repository.MessageRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +/** + * 消息通知服务类 + * 提供用户消息相关的业务逻辑处理 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Service +public class MessageService { + + @Autowired + private MessageRepository messageRepository; + + /** + * 获取消息列表 + * @param userId 用户ID + * @return 消息列表 + */ + public List getMessageList(Long userId) { + return messageRepository.findByUserIdOrderByCreatedAtDesc(userId); + } + + /** + * 标记消息为已读 + * @param messageId 消息ID + */ + public void markMessageAsRead(Long messageId) { + Optional messageOptional = messageRepository.findById(messageId); + if (!messageOptional.isPresent()) { + throw new UserException("消息不存在", 404); + } + + Message message = messageOptional.get(); + if (!message.getIsRead()) { + message.setIsRead(true); + message.setReadAt(LocalDateTime.now()); + messageRepository.save(message); + } + } + + /** + * 删除消息 + * @param messageId 消息ID + */ + public void deleteMessage(Long messageId) { + Optional messageOptional = messageRepository.findById(messageId); + if (!messageOptional.isPresent()) { + throw new UserException("消息不存在", 404); + } + + Message message = messageOptional.get(); + message.setStatus(0); // 软删除 + messageRepository.save(message); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/PointsService.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/PointsService.java new file mode 100644 index 0000000..c6fe65c --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/PointsService.java @@ -0,0 +1,96 @@ +package com.xlxumu.user.service; + +import com.xlxumu.user.entity.PointsRecord; +import com.xlxumu.user.entity.UserLevel; +import com.xlxumu.user.exception.UserException; +import com.xlxumu.user.repository.PointsRecordRepository; +import com.xlxumu.user.repository.UserLevelRepository; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +/** + * 积分管理服务类 + * 提供用户积分相关的业务逻辑处理 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Service +public class PointsService { + + @Autowired + private UserLevelRepository userLevelRepository; + + @Autowired + private PointsRecordRepository pointsRecordRepository; + + /** + * 获取用户积分余额 + * @param userId 用户ID + * @return 积分余额 + */ + public Integer getUserPointsBalance(Long userId) { + Optional userLevelOptional = userLevelRepository.findByUserId(userId); + if (!userLevelOptional.isPresent()) { + throw new UserException("用户等级信息不存在", 404); + } + + return userLevelOptional.get().getCurrentPoints(); + } + + /** + * 获取积分记录列表 + * @param userId 用户ID + * @return 积分记录列表 + */ + public List getPointsRecordList(Long userId) { + return pointsRecordRepository.findByUserIdOrderByCreatedAtDesc(userId); + } + + /** + * 添加积分记录 + * @param userId 用户ID + * @param points 积分数量(正数表示增加,负数表示减少) + * @param changeType 变更类型 + * @param description 描述 + * @return 更新后的积分余额 + */ + public Integer addPointsRecord(Long userId, Integer points, String changeType, String description) { + // 更新用户积分余额 + Optional userLevelOptional = userLevelRepository.findByUserId(userId); + UserLevel userLevel; + + if (!userLevelOptional.isPresent()) { + // 创建新的用户等级记录 + userLevel = new UserLevel(); + userLevel.setUserId(userId); + userLevel.setLevelId(1L); // 默认等级ID + userLevel.setCurrentPoints(points > 0 ? points : 0); + userLevel.setCreatedAt(LocalDateTime.now()); + userLevel.setUpdatedAt(LocalDateTime.now()); + } else { + userLevel = userLevelOptional.get(); + int newPoints = userLevel.getCurrentPoints() + points; + userLevel.setCurrentPoints(newPoints > 0 ? newPoints : 0); + userLevel.setUpdatedAt(LocalDateTime.now()); + } + + userLevelRepository.save(userLevel); + + // 记录积分变更 + PointsRecord pointsRecord = new PointsRecord(); + pointsRecord.setUserId(userId); + pointsRecord.setPoints(points); + pointsRecord.setChangeType(changeType); + pointsRecord.setDescription(description); + pointsRecord.setCreatedAt(LocalDateTime.now()); + + pointsRecordRepository.save(pointsRecord); + + return userLevel.getCurrentPoints(); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/UserService.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/UserService.java new file mode 100644 index 0000000..9ecaea4 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/service/UserService.java @@ -0,0 +1,201 @@ +package com.xlxumu.user.service; + +import com.xlxumu.user.entity.User; +import com.xlxumu.user.exception.UserException; +import com.xlxumu.user.repository.UserRepository; +import com.xlxumu.user.util.JwtUtil; +import com.xlxumu.user.util.PasswordUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Optional; + +/** + * 用户服务类 + * 提供用户相关的业务逻辑处理 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Service +public class UserService { + + @Autowired + private UserRepository userRepository; + + @Autowired + private PasswordUtil passwordUtil; + + @Autowired + private JwtUtil jwtUtil; + + /** + * 用户注册 + * @param username 用户名 + * @param email 邮箱 + * @param phone 手机号 + * @param password 密码 + * @return JWT token + */ + public String register(String username, String email, String phone, String password) { + // 检查用户名是否已存在 + if (userRepository.findByUsername(username).isPresent()) { + throw new UserException("用户名已存在", 400); + } + + // 检查邮箱是否已存在 + if (userRepository.findByEmail(email).isPresent()) { + throw new UserException("邮箱已被注册", 400); + } + + // 检查手机号是否已存在 + if (userRepository.findByPhone(phone).isPresent()) { + throw new UserException("手机号已被注册", 400); + } + + // 创建新用户 + User user = new User(); + user.setUsername(username); + user.setEmail(email); + user.setPhone(phone); + + // 密码加密 + String salt = passwordUtil.generateSalt(); + String hashedPassword = passwordUtil.hashPassword(password, salt); + user.setPasswordHash(hashedPassword); + + user.setCreatedAt(LocalDateTime.now()); + user.setUpdatedAt(LocalDateTime.now()); + + userRepository.save(user); + + // 生成JWT token + return jwtUtil.generateToken(username); + } + + /** + * 用户登录 + * @param username 用户名 + * @param password 密码 + * @return JWT token + */ + public String login(String username, String password) { + Optional userOptional = userRepository.findByUsername(username); + if (!userOptional.isPresent()) { + throw new UserException("用户不存在", 400); + } + + User user = userOptional.get(); + + // 验证密码 + if (!passwordUtil.verifyPassword(password, "", user.getPasswordHash())) { + throw new UserException("密码错误", 400); + } + + // 更新最后登录时间 + user.setLastLoginAt(LocalDateTime.now()); + userRepository.save(user); + + // 生成JWT token + return jwtUtil.generateToken(username); + } + + /** + * 获取用户信息 + * @param userId 用户ID + * @return 用户信息 + */ + public User getUserInfo(Long userId) { + Optional userOptional = userRepository.findById(userId); + if (!userOptional.isPresent()) { + throw new UserException("用户不存在", 404); + } + + return userOptional.get(); + } + + /** + * 更新用户信息 + * @param userId 用户ID + * @param nickname 昵称 + * @param avatarUrl 头像URL + * @param gender 性别 + * @param birthday 生日 + * @param realName 真实姓名 + * @return 更新后的用户信息 + */ + public User updateUserInfo(Long userId, String nickname, String avatarUrl, Integer gender, + LocalDateTime birthday, String realName) { + Optional userOptional = userRepository.findById(userId); + if (!userOptional.isPresent()) { + throw new UserException("用户不存在", 404); + } + + User user = userOptional.get(); + user.setNickname(nickname); + user.setAvatarUrl(avatarUrl); + user.setGender(gender); + user.setBirthday(birthday); + user.setRealName(realName); + user.setUpdatedAt(LocalDateTime.now()); + + return userRepository.save(user); + } + + /** + * 修改用户密码 + * @param userId 用户ID + * @param oldPassword 旧密码 + * @param newPassword 新密码 + */ + public void changePassword(Long userId, String oldPassword, String newPassword) { + Optional userOptional = userRepository.findById(userId); + if (!userOptional.isPresent()) { + throw new UserException("用户不存在", 404); + } + + User user = userOptional.get(); + + // 验证旧密码 + if (!passwordUtil.verifyPassword(oldPassword, "", user.getPasswordHash())) { + throw new UserException("旧密码错误", 400); + } + + // 加密新密码 + String salt = passwordUtil.generateSalt(); + String hashedPassword = passwordUtil.hashPassword(newPassword, salt); + user.setPasswordHash(hashedPassword); + user.setUpdatedAt(LocalDateTime.now()); + + userRepository.save(user); + } + + /** + * 管理员获取用户列表 + * @return 用户列表 + */ + public List getUserList() { + return userRepository.findAll(); + } + + /** + * 管理员更新用户状态 + * @param userId 用户ID + * @param status 状态 + * @return 更新后的用户信息 + */ + public User updateUserStatus(Long userId, Integer status) { + Optional userOptional = userRepository.findById(userId); + if (!userOptional.isPresent()) { + throw new UserException("用户不存在", 404); + } + + User user = userOptional.get(); + user.setStatus(status); + user.setUpdatedAt(LocalDateTime.now()); + + return userRepository.save(user); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtTokenUtil.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtTokenUtil.java new file mode 100644 index 0000000..fc9df1a --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtTokenUtil.java @@ -0,0 +1,29 @@ +package com.xlxumu.user.util; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; + +@Component +public class JwtTokenUtil { + + @Autowired + private JwtUtil jwtUtil; + + /** + * 从请求中获取用户ID + * @param request HTTP请求 + * @return 用户ID + */ + public Long getUserIdFromRequest(HttpServletRequest request) { + String authorizationHeader = request.getHeader("Authorization"); + + if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { + String token = authorizationHeader.substring(7); + return jwtUtil.getUserIdFromToken(token); + } + + return null; + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtUtil.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtUtil.java new file mode 100644 index 0000000..155b5f5 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/JwtUtil.java @@ -0,0 +1,114 @@ +package com.xlxumu.user.util; + +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Function; + +/** + * JWT工具类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Component +public class JwtUtil { + + @Value("${jwt.secret}") + private String secret; + + @Value("${jwt.expiration}") + private Long expiration; + + /** + * 从token中获取用户ID + * @param token JWT token + * @return 用户ID + */ + public Long getUserIdFromToken(String token) { + return Long.parseLong(getClaimFromToken(token, Claims::getSubject)); + } + + /** + * 从token中获取过期时间 + * @param token JWT token + * @return 过期时间 + */ + public Date getExpirationDateFromToken(String token) { + return getClaimFromToken(token, Claims::getExpiration); + } + + /** + * 从token中获取自定义声明 + * @param token JWT token + * @param claimsResolver 声明解析器 + * @param 声明类型 + * @return 声明值 + */ + public T getClaimFromToken(String token, Function claimsResolver) { + final Claims claims = getAllClaimsFromToken(token); + return claimsResolver.apply(claims); + } + + /** + * 解析token中的所有声明 + * @param token JWT token + * @return 所有声明 + */ + private Claims getAllClaimsFromToken(String token) { + return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody(); + } + + /** + * 检查token是否过期 + * @param token JWT token + * @return 是否过期 + */ + private Boolean isTokenExpired(String token) { + final Date expiration = getExpirationDateFromToken(token); + return expiration.before(new Date()); + } + + /** + * 生成token + * @param userId 用户ID + * @return JWT token + */ + public String generateToken(Long userId) { + Map claims = new HashMap<>(); + return doGenerateToken(claims, userId.toString()); + } + + /** + * 创建token + * @param claims 声明 + * @param subject 主题(用户ID) + * @return JWT token + */ + private String doGenerateToken(Map claims, String subject) { + return Jwts.builder() + .setClaims(claims) + .setSubject(subject) + .setIssuedAt(new Date(System.currentTimeMillis())) + .setExpiration(new Date(System.currentTimeMillis() + expiration)) + .signWith(SignatureAlgorithm.HS512, secret) + .compact(); + } + + /** + * 验证token + * @param token JWT token + * @param userId 用户ID + * @return 是否有效 + */ + public Boolean validateToken(String token, Long userId) { + final Long tokenUserId = getUserIdFromToken(token); + return (tokenUserId.equals(userId) && !isTokenExpired(token)); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/PasswordUtil.java b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/PasswordUtil.java new file mode 100644 index 0000000..9b605e1 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/java/com/xlxumu/user/util/PasswordUtil.java @@ -0,0 +1,73 @@ +package com.xlxumu.user.util; + +import org.springframework.stereotype.Component; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.SecureRandom; + +/** + * 密码工具类 + * + * @author xlxumu + * @since 2024-01-15 + */ +@Component +public class PasswordUtil { + + private static final String ALGORITHM = "SHA-256"; + private static final int SALT_LENGTH = 32; + + /** + * 生成随机盐值 + * @return 盐值 + */ + public String generateSalt() { + SecureRandom random = new SecureRandom(); + byte[] salt = new byte[SALT_LENGTH]; + random.nextBytes(salt); + return bytesToHex(salt); + } + + /** + * 对密码进行哈希处理 + * @param password 密码 + * @param salt 盐值 + * @return 哈希值 + */ + public String hashPassword(String password, String salt) { + try { + MessageDigest md = MessageDigest.getInstance(ALGORITHM); + md.update(salt.getBytes()); + byte[] hashedPassword = md.digest(password.getBytes()); + return bytesToHex(hashedPassword); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException("Error hashing password", e); + } + } + + /** + * 验证密码 + * @param password 密码 + * @param salt 盐值 + * @param hashedPassword 哈希值 + * @return 是否匹配 + */ + public boolean verifyPassword(String password, String salt, String hashedPassword) { + String newHash = hashPassword(password, salt); + return newHash.equals(hashedPassword); + } + + /** + * 将字节数组转换为十六进制字符串 + * @param bytes 字节数组 + * @return 十六进制字符串 + */ + private String bytesToHex(byte[] bytes) { + StringBuilder result = new StringBuilder(); + for (byte b : bytes) { + result.append(String.format("%02x", b)); + } + return result.toString(); + } +} \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/resources/api/address-api.yaml b/backend-java/services/user-center-service/src/main/resources/api/address-api.yaml new file mode 100644 index 0000000..89c41c2 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/resources/api/address-api.yaml @@ -0,0 +1,335 @@ +openapi: 3.0.3 +info: + title: 用户中心服务 - 收货地址管理API + description: 用户收货地址管理接口 + version: 1.0.0 + +paths: + /api/addresses: + post: + summary: 创建收货地址 + description: 创建新的收货地址 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: 收货人姓名 + phone: + type: string + description: 收货人电话 + province: + type: string + description: 省份 + city: + type: string + description: 城市 + district: + type: string + description: 区县 + detailAddress: + type: string + description: 详细地址 + isDefault: + type: boolean + description: 是否默认地址 + required: + - name + - phone + - province + - city + - district + - detailAddress + responses: + '200': + description: 地址创建成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "地址创建成功" + data: + $ref: '#/components/schemas/Address' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + get: + summary: 获取收货地址列表 + description: 获取当前用户的所有收货地址 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + type: array + items: + $ref: '#/components/schemas/Address' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/addresses/{addressId): + get: + summary: 获取收货地址详情 + description: 获取指定收货地址的详细信息 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + - name: addressId + in: path + required: true + schema: + type: integer + format: int64 + description: 地址ID + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + $ref: '#/components/schemas/Address' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: 地址不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + summary: 更新收货地址 + description: 更新指定收货地址的信息 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + - name: addressId + in: path + required: true + schema: + type: integer + format: int64 + description: 地址ID + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + name: + type: string + description: 收货人姓名 + phone: + type: string + description: 收货人电话 + province: + type: string + description: 省份 + city: + type: string + description: 城市 + district: + type: string + description: 区县 + detailAddress: + type: string + description: 详细地址 + isDefault: + type: boolean + description: 是否默认地址 + responses: + '200': + description: 地址更新成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "地址更新成功" + data: + $ref: '#/components/schemas/Address' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: 地址不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + delete: + summary: 删除收货地址 + description: 删除指定收货地址 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + - name: addressId + in: path + required: true + schema: + type: integer + format: int64 + description: 地址ID + responses: + '200': + description: 地址删除成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "地址删除成功" + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: 地址不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + Address: + type: object + properties: + id: + type: integer + format: int64 + description: 地址ID + userId: + type: integer + format: int64 + description: 用户ID + name: + type: string + description: 收货人姓名 + phone: + type: string + description: 收货人电话 + province: + type: string + description: 省份 + city: + type: string + description: 城市 + district: + type: string + description: 区县 + detailAddress: + type: string + description: 详细地址 + isDefault: + type: boolean + description: 是否默认地址 + status: + type: integer + description: 地址状态 (1-正常, 0-删除) + createdAt: + type: string + format: date-time + description: 创建时间 + updatedAt: + type: string + format: date-time + description: 更新时间 + + ErrorResponse: + type: object + properties: + timestamp: + type: string + format: date-time + description: 错误时间戳 + status: + type: integer + description: HTTP状态码 + error: + type: string + description: 错误信息 + path: + type: string + description: 请求路径 \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/resources/api/feedback-api.yaml b/backend-java/services/user-center-service/src/main/resources/api/feedback-api.yaml new file mode 100644 index 0000000..6fb1c2f --- /dev/null +++ b/backend-java/services/user-center-service/src/main/resources/api/feedback-api.yaml @@ -0,0 +1,156 @@ +openapi: 3.0.3 +info: + title: 用户中心服务 - 用户反馈API + description: 用户反馈提交、查询等接口 + version: 1.0.0 + +paths: + /api/feedback: + post: + summary: 提交反馈 + description: 用户提交反馈意见 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + title: + type: string + description: 反馈标题 + content: + type: string + description: 反馈内容 + type: + type: string + description: 反馈类型 + contactInfo: + type: string + description: 联系方式 + required: + - title + - content + responses: + '200': + description: 反馈提交成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "反馈提交成功" + data: + $ref: '#/components/schemas/Feedback' + '400': + description: 请求参数错误 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + get: + summary: 获取反馈列表 + description: 获取当前用户的反馈列表 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + type: array + items: + $ref: '#/components/schemas/Feedback' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + Feedback: + type: object + properties: + id: + type: integer + format: int64 + description: 反馈ID + userId: + type: integer + format: int64 + description: 用户ID + title: + type: string + description: 反馈标题 + content: + type: string + description: 反馈内容 + type: + type: string + description: 反馈类型 + contactInfo: + type: string + description: 联系方式 + status: + type: integer + description: 反馈状态 (1-待处理, 2-处理中, 3-已处理) + createdAt: + type: string + format: date-time + description: 创建时间 + updatedAt: + type: string + format: date-time + description: 更新时间 + + ErrorResponse: + type: object + properties: + timestamp: + type: string + format: date-time + description: 错误时间戳 + status: + type: integer + description: HTTP状态码 + error: + type: string + description: 错误信息 + path: + type: string + description: 请求路径 \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/resources/api/message-api.yaml b/backend-java/services/user-center-service/src/main/resources/api/message-api.yaml new file mode 100644 index 0000000..00bc238 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/resources/api/message-api.yaml @@ -0,0 +1,190 @@ +openapi: 3.0.3 +info: + title: 用户中心服务 - 消息通知API + description: 用户消息查询、标记已读、删除等接口 + version: 1.0.0 + +paths: + /api/messages: + get: + summary: 获取消息列表 + description: 获取当前用户的消息列表 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + type: array + items: + $ref: '#/components/schemas/Message' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/messages/{messageId}/read: + put: + summary: 标记消息为已读 + description: 将指定消息标记为已读状态 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + - name: messageId + in: path + required: true + schema: + type: integer + format: int64 + description: 消息ID + responses: + '200': + description: 标记成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "标记成功" + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: 消息不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/messages/{messageId}: + delete: + summary: 删除消息 + description: 删除指定消息 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + - name: messageId + in: path + required: true + schema: + type: integer + format: int64 + description: 消息ID + responses: + '200': + description: 删除成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "删除成功" + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: 消息不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + Message: + type: object + properties: + id: + type: integer + format: int64 + description: 消息ID + userId: + type: integer + format: int64 + description: 用户ID + title: + type: string + description: 消息标题 + content: + type: string + description: 消息内容 + type: + type: string + description: 消息类型 + isRead: + type: boolean + description: 是否已读 + readAt: + type: string + format: date-time + description: 阅读时间 + status: + type: integer + description: 消息状态 (1-正常, 0-删除) + createdAt: + type: string + format: date-time + description: 创建时间 + updatedAt: + type: string + format: date-time + description: 更新时间 + + ErrorResponse: + type: object + properties: + timestamp: + type: string + format: date-time + description: 错误时间戳 + status: + type: integer + description: HTTP状态码 + error: + type: string + description: 错误信息 + path: + type: string + description: 请求路径 \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/resources/api/openapi.yaml b/backend-java/services/user-center-service/src/main/resources/api/openapi.yaml new file mode 100644 index 0000000..4604ed7 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/resources/api/openapi.yaml @@ -0,0 +1,69 @@ +openapi: 3.0.3 +info: + title: 用户中心服务API + description: 用户中心服务提供用户管理、收货地址、积分、消息通知、用户反馈等核心功能的RESTful API接口 + version: 1.0.0 + +servers: + - url: http://localhost:8080 + description: 本地开发环境 + +paths: + # 用户管理相关接口 + /api/users/register: + $ref: './user-api.yaml#/paths/~1api~1users~1register' + /api/users/login: + $ref: './user-api.yaml#/paths/~1api~1users~1login' + /api/users/info: + $ref: './user-api.yaml#/paths/~1api~1users~1info' + /api/users/password: + $ref: './user-api.yaml#/paths/~1api~1users~1password' + /api/users/list: + $ref: './user-api.yaml#/paths/~1api~1users~1list' + /api/users/{userId}/status: + $ref: './user-api.yaml#/paths/~1api~1users~1{userId}~1status' + + # 收货地址相关接口 + /api/addresses: + $ref: './address-api.yaml#/paths/~1api~1addresses' + /api/addresses/{addressId}: + $ref: './address-api.yaml#/paths/~1api~1addresses~1{addressId}' + + # 积分管理相关接口 + /api/points/balance: + $ref: './points-api.yaml#/paths/~1api~1points~1balance' + /api/points/records: + $ref: './points-api.yaml#/paths/~1api~1points~1records' + /api/points/level: + $ref: './points-api.yaml#/paths/~1api~1points~1level' + /api/points/levels: + $ref: './points-api.yaml#/paths/~1api~1points~1levels' + + # 消息通知相关接口 + /api/messages: + $ref: './message-api.yaml#/paths/~1api~1messages' + /api/messages/{messageId}/read: + $ref: './message-api.yaml#/paths/~1api~1messages~1{messageId}~1read' + /api/messages/{messageId}: + $ref: './message-api.yaml#/paths/~1api~1messages~1{messageId}' + + # 用户反馈相关接口 + /api/feedback: + $ref: './feedback-api.yaml#/paths/~1api~1feedback' + +components: + schemas: + User: + $ref: './user-api.yaml#/components/schemas/User' + Address: + $ref: './address-api.yaml#/components/schemas/Address' + PointsRecord: + $ref: './points-api.yaml#/components/schemas/PointsRecord' + Level: + $ref: './points-api.yaml#/components/schemas/Level' + Message: + $ref: './message-api.yaml#/components/schemas/Message' + Feedback: + $ref: './feedback-api.yaml#/components/schemas/Feedback' + ErrorResponse: + $ref: './user-api.yaml#/components/schemas/ErrorResponse' \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/resources/api/points-api.yaml b/backend-java/services/user-center-service/src/main/resources/api/points-api.yaml new file mode 100644 index 0000000..f2cbac7 --- /dev/null +++ b/backend-java/services/user-center-service/src/main/resources/api/points-api.yaml @@ -0,0 +1,213 @@ +openapi: 3.0.3 +info: + title: 用户中心服务 - 积分管理API + description: 用户积分查询、积分记录查询等接口 + version: 1.0.0 + +paths: + /api/points/balance: + get: + summary: 获取用户积分余额 + description: 获取当前用户的积分余额 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + type: object + properties: + balance: + type: integer + description: 积分余额 + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/points/records: + get: + summary: 获取积分记录列表 + description: 获取当前用户的积分变动记录列表 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + type: array + items: + $ref: '#/components/schemas/PointsRecord' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/points/level: + get: + summary: 获取用户当前等级 + description: 获取当前用户的等级信息 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + $ref: '#/components/schemas/Level' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/points/levels: + get: + summary: 获取等级列表 + description: 获取所有可用的用户等级列表 + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + type: array + items: + $ref: '#/components/schemas/Level' + +components: + schemas: + PointsRecord: + type: object + properties: + id: + type: integer + format: int64 + description: 记录ID + userId: + type: integer + format: int64 + description: 用户ID + changeType: + type: string + description: 变动类型 (earn-获得, consume-消费) + points: + type: integer + description: 积分数量 + description: + type: string + description: 描述 + createdAt: + type: string + format: date-time + description: 创建时间 + + Level: + type: object + properties: + id: + type: integer + format: int64 + description: 等级ID + name: + type: string + description: 等级名称 + minPoints: + type: integer + description: 最小积分要求 + maxPoints: + type: integer + description: 最大积分要求 + discountRate: + type: number + format: double + description: 折扣率 + status: + type: integer + description: 状态 (1-启用, 0-禁用) + createdAt: + type: string + format: date-time + description: 创建时间 + updatedAt: + type: string + format: date-time + description: 更新时间 + + ErrorResponse: + type: object + properties: + timestamp: + type: string + format: date-time + description: 错误时间戳 + status: + type: integer + description: HTTP状态码 + error: + type: string + description: 错误信息 + path: + type: string + description: 请求路径 \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/resources/api/user-api.yaml b/backend-java/services/user-center-service/src/main/resources/api/user-api.yaml new file mode 100644 index 0000000..a1af83a --- /dev/null +++ b/backend-java/services/user-center-service/src/main/resources/api/user-api.yaml @@ -0,0 +1,413 @@ +openapi: 3.0.3 +info: + title: 用户中心服务 - 用户管理API + description: 用户注册、登录、信息管理等接口 + version: 1.0.0 + +paths: + /api/users/register: + post: + summary: 用户注册 + description: 用户注册接口,创建新用户账户 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: 用户名 + password: + type: string + description: 密码 + email: + type: string + description: 邮箱 + phone: + type: string + description: 手机号 + required: + - username + - password + responses: + '200': + description: 注册成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "注册成功" + data: + $ref: '#/components/schemas/User' + '400': + description: 请求参数错误 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/users/login: + post: + summary: 用户登录 + description: 用户登录接口,获取访问令牌 + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + username: + type: string + description: 用户名 + password: + type: string + description: 密码 + required: + - username + - password + responses: + '200': + description: 登录成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "登录成功" + data: + type: object + properties: + token: + type: string + description: JWT访问令牌 + '401': + description: 用户名或密码错误 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/users/info: + get: + summary: 获取用户信息 + description: 获取当前登录用户的详细信息 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + $ref: '#/components/schemas/User' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + put: + summary: 更新用户信息 + description: 更新当前登录用户的个人信息 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + nickname: + type: string + description: 昵称 + avatar: + type: string + description: 头像URL + gender: + type: string + description: 性别 + birthday: + type: string + format: date + description: 生日 + responses: + '200': + description: 更新成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "更新成功" + data: + $ref: '#/components/schemas/User' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/users/password: + put: + summary: 修改密码 + description: 修改用户登录密码 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + oldPassword: + type: string + description: 旧密码 + newPassword: + type: string + description: 新密码 + required: + - oldPassword + - newPassword + responses: + '200': + description: 密码修改成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "密码修改成功" + '401': + description: 未授权访问或旧密码错误 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/users/list: + get: + summary: 获取用户列表 + description: 管理员获取用户列表(分页) + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + - name: page + in: query + schema: + type: integer + default: 1 + description: 页码 + - name: size + in: query + schema: + type: integer + default: 10 + description: 每页数量 + responses: + '200': + description: 获取成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "获取成功" + data: + type: array + items: + $ref: '#/components/schemas/User' + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: 权限不足 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + + /api/users/{userId}/status: + put: + summary: 更新用户状态 + description: 管理员更新用户状态 + parameters: + - name: Authorization + in: header + required: true + schema: + type: string + description: JWT访问令牌 (Bearer token) + - name: userId + in: path + required: true + schema: + type: integer + format: int64 + description: 用户ID + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + status: + type: integer + description: 用户状态 (1-正常, 0-禁用) + required: + - status + responses: + '200': + description: 状态更新成功 + content: + application/json: + schema: + type: object + properties: + code: + type: integer + example: 200 + message: + type: string + example: "状态更新成功" + '401': + description: 未授权访问 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '403': + description: 权限不足 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + '404': + description: 用户不存在 + content: + application/json: + schema: + $ref: '#/components/schemas/ErrorResponse' + +components: + schemas: + User: + type: object + properties: + id: + type: integer + format: int64 + description: 用户ID + username: + type: string + description: 用户名 + email: + type: string + description: 邮箱 + phone: + type: string + description: 手机号 + nickname: + type: string + description: 昵称 + avatar: + type: string + description: 头像URL + gender: + type: string + description: 性别 + birthday: + type: string + format: date + description: 生日 + status: + type: integer + description: 用户状态 (1-正常, 0-禁用) + createdAt: + type: string + format: date-time + description: 创建时间 + updatedAt: + type: string + format: date-time + description: 更新时间 + + ErrorResponse: + type: object + properties: + timestamp: + type: string + format: date-time + description: 错误时间戳 + status: + type: integer + description: HTTP状态码 + error: + type: string + description: 错误信息 + path: + type: string + description: 请求路径 \ No newline at end of file diff --git a/backend-java/services/user-center-service/src/main/resources/application.properties b/backend-java/services/user-center-service/src/main/resources/application.properties index b9ed493..d40e846 100644 --- a/backend-java/services/user-center-service/src/main/resources/application.properties +++ b/backend-java/services/user-center-service/src/main/resources/application.properties @@ -1,10 +1,17 @@ -server.port=8082 +spring.application.name=user-center-service +server.port=8080 -spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_user?useSSL=false&serverTimezone=UTC +# 数据库配置 +spring.datasource.url=jdbc:mysql://localhost:3306/xlxumu_user?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai spring.datasource.username=root -spring.datasource.password= +spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver +# JPA配置 spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true -spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect \ No newline at end of file +spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect + +# JWT配置 +jwt.secret=xlxumu_user_center_secret_key_2024 +jwt.expiration=86400000 \ No newline at end of file diff --git a/docs/design/api/ai_service_api_design.md b/docs/design/api/ai_service_api_design.md new file mode 100644 index 0000000..fb22b7c --- /dev/null +++ b/docs/design/api/ai_service_api_design.md @@ -0,0 +1,467 @@ +# AI服务API设计文档 + +## 1. 概述 + +本文档详细描述了AI服务(ai-service)提供的API接口,包括智能问答、图像识别、数据分析等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/ai` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 40001, + "message": "错误描述", + "data": null +} +``` + +## 5. 智能问答接口 + +### 5.1 提问 + +**接口地址**: `POST /qa/ask` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| question | string | 是 | 用户问题 | +| context | object | 否 | 上下文信息 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 问答记录ID | +| question | string | 用户问题 | +| answer | string | AI回答 | +| model_version | string | 使用的模型版本 | +| processing_time | integer | 处理耗时(毫秒) | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "question": "如何防治小麦赤霉病?", + "context": { + "crop": "小麦", + "region": "华北地区" + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "question": "如何防治小麦赤霉病?", + "answer": "小麦赤霉病防治方法:1.选用抗病品种;2.合理施肥,避免氮肥过量;3.及时排水,降低田间湿度;4.药剂防治,在抽穗扬花期喷施多菌灵等杀菌剂。", + "model_version": "v1.2.0", + "processing_time": 1200, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.2 获取问答历史 + +**接口地址**: `GET /qa/history` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 问答记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 5, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "question": "如何防治小麦赤霉病?", + "answer": "小麦赤霉病防治方法:1.选用抗病品种;2.合理施肥,避免氮肥过量;3.及时排水,降低田间湿度;4.药剂防治,在抽穗扬花期喷施多菌灵等杀菌剂。", + "model_version": "v1.2.0", + "processing_time": 1200, + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +## 6. 图像识别接口 + +### 6.1 上传图片进行识别 + +**接口地址**: `POST /image/recognize` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| image_url | string | 是 | 图片URL | +| recognition_type | string | 是 | 识别类型(PestAndDisease/Plant/Crop等) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 识别记录ID | +| image_url | string | 图片URL | +| recognition_type | string | 识别类型 | +| result | object | 识别结果 | +| confidence | number | 置信度 | +| processing_time | integer | 处理耗时(毫秒) | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "image_url": "https://example.com/image1.jpg", + "recognition_type": "PestAndDisease" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "image_url": "https://example.com/image1.jpg", + "recognition_type": "PestAndDisease", + "result": { + "name": "小麦赤霉病", + "description": "一种常见的小麦病害,主要危害小麦的穗部", + "prevention": "1.选用抗病品种;2.合理施肥;3.及时排水;4.药剂防治" + }, + "confidence": 0.9567, + "processing_time": 2500, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.2 获取识别历史 + +**接口地址**: `GET /image/history` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| recognition_type | string | 否 | 识别类型筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 识别记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 3, + "page": 1, + "size": 10, + "items": [ + { + "id": 2001, + "image_url": "https://example.com/image1.jpg", + "recognition_type": "PestAndDisease", + "result": { + "name": "小麦赤霉病", + "description": "一种常见的小麦病害,主要危害小麦的穗部" + }, + "confidence": 0.9567, + "processing_time": 2500, + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +## 7. 数据分析接口 + +### 7.1 创建分析任务 + +**接口地址**: `POST /analysis/tasks` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| task_name | string | 是 | 任务名称 | +| task_type | string | 是 | 任务类型(YieldPrediction/PriceAnalysis等) | +| input_data | object | 是 | 输入数据 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 任务ID | +| task_name | string | 任务名称 | +| task_type | string | 任务类型 | +| status | string | 任务状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "task_name": "2024年小麦产量预测", + "task_type": "YieldPrediction", + "input_data": { + "crop": "小麦", + "region": "华北地区", + "planting_area": 10000, + "historical_data": [ + {"year": 2021, "yield": 500}, + {"year": 2022, "yield": 520}, + {"year": 2023, "yield": 510} + ] + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "task_name": "2024年小麦产量预测", + "task_type": "YieldPrediction", + "status": "PENDING", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 7.2 查询任务状态 + +**接口地址**: `GET /analysis/tasks/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 任务ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 任务ID | +| task_name | string | 任务名称 | +| task_type | string | 任务类型 | +| input_data | object | 输入数据 | +| result | object | 分析结果 | +| status | string | 任务状态 | +| processing_time | integer | 处理耗时(毫秒) | +| error_message | string | 错误信息 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "task_name": "2024年小麦产量预测", + "task_type": "YieldPrediction", + "input_data": { + "crop": "小麦", + "region": "华北地区", + "planting_area": 10000, + "historical_data": [ + {"year": 2021, "yield": 500}, + {"year": 2022, "yield": 520}, + {"year": 2023, "yield": 510} + ] + }, + "result": { + "predicted_yield": 515, + "confidence": 0.85, + "factors": ["气候条件", "土壤质量", "种植技术"] + }, + "status": "COMPLETED", + "processing_time": 5000, + "error_message": null, + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:05Z" + } +} +``` + +### 7.3 获取任务列表 + +**接口地址**: `GET /analysis/tasks` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| task_type | string | 否 | 任务类型筛选 | +| status | string | 否 | 任务状态筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 任务列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 2, + "page": 1, + "size": 10, + "items": [ + { + "id": 3001, + "task_name": "2024年小麦产量预测", + "task_type": "YieldPrediction", + "status": "COMPLETED", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +## 8. 用户反馈接口 + +### 8.1 提交反馈 + +**接口地址**: `POST /feedback` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| service_type | string | 是 | 服务类型(QA/IMAGE_RECOGNITION/ANALYSIS) | +| record_id | integer | 是 | 相关记录ID | +| rating | integer | 是 | 评分(1-5星) | +| feedback | string | 否 | 反馈内容 | +| is_helpful | boolean | 是 | 是否有帮助 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 反馈ID | +| service_type | string | 服务类型 | +| record_id | integer | 相关记录ID | +| rating | integer | 评分 | +| feedback | string | 反馈内容 | +| is_helpful | boolean | 是否有帮助 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "service_type": "QA", + "record_id": 1001, + "rating": 5, + "feedback": "回答很详细,很有帮助", + "is_helpful": true +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 4001, + "service_type": "QA", + "record_id": 1001, + "rating": 5, + "feedback": "回答很详细,很有帮助", + "is_helpful": true, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +## 9. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 40001 | 参数错误 | 请求参数不合法 | +| 40002 | 问答记录不存在 | 指定的问答记录不存在 | +| 40003 | 图像识别记录不存在 | 指定的图像识别记录不存在 | +| 40004 | 分析任务不存在 | 指定的分析任务不存在 | +| 40005 | 不支持的识别类型 | 指定的识别类型不被支持 | +| 40006 | 不支持的任务类型 | 指定的任务类型不被支持 | +| 40007 | 任务状态不允许此操作 | 当前任务状态不允许执行该操作 | +| 50001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 50002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/data_platform_service_api_design.md b/docs/design/api/data_platform_service_api_design.md new file mode 100644 index 0000000..3e561d2 --- /dev/null +++ b/docs/design/api/data_platform_service_api_design.md @@ -0,0 +1,762 @@ +# 数据平台服务API设计文档 + +## 1. 概述 + +本文档详细描述了数据平台服务(data-platform-service)提供的API接口,包括数据统计、报表生成、数据分析等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/data` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 40001, + "message": "错误描述", + "data": null +} +``` + +## 5. 数据统计接口 + +### 5.1 获取统计数据 + +**接口地址**: `GET /statistics` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| stat_type | string | 是 | 统计类型(USER_COUNT, PRODUCT_COUNT, ORDER_COUNT, REVENUE等) | +| start_date | string | 否 | 开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 结束日期(YYYY-MM-DD) | +| dimension1 | string | 否 | 维度1(如地区、品类等) | +| dimension2 | string | 否 | 维度2 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 统计数据列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 30, + "page": 1, + "size": 10, + "items": [ + { + "id": 1, + "stat_type": "USER_COUNT", + "stat_value": 12500.00, + "stat_date": "2024-01-15", + "dimension1": "北京", + "dimension2": null, + "created_at": "2024-01-15T00:00:00Z" + } + ] + } +} +``` + +### 5.2 批量获取统计数据 + +**接口地址**: `POST /statistics/batch` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| queries | array | 是 | 查询条件列表 | + +**queries元素结构**: + +| 字段名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| stat_type | string | 是 | 统计类型 | +| start_date | string | 否 | 开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 结束日期(YYYY-MM-DD) | +| dimension1 | string | 否 | 维度1 | +| dimension2 | string | 否 | 维度2 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| results | array | 查询结果列表 | + +**示例请求**: +```json +{ + "queries": [ + { + "stat_type": "USER_COUNT", + "start_date": "2024-01-01", + "end_date": "2024-01-31" + }, + { + "stat_type": "ORDER_COUNT", + "start_date": "2024-01-01", + "end_date": "2024-01-31" + } + ] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "results": [ + { + "stat_type": "USER_COUNT", + "data": [ + { + "stat_value": 12500.00, + "stat_date": "2024-01-31" + } + ] + }, + { + "stat_type": "ORDER_COUNT", + "data": [ + { + "stat_value": 3500.00, + "stat_date": "2024-01-31" + } + ] + } + ] + } +} +``` + +## 6. 报表管理接口 + +### 6.1 获取报表模板列表 + +**接口地址**: `GET /reports/templates` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| template_type | string | 否 | 模板类型(DAILY, WEEKLY, MONTHLY等) | +| data_source | string | 否 | 数据源 | +| status | string | 否 | 模板状态(ACTIVE/INACTIVE) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 报表模板列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 5, + "page": 1, + "size": 10, + "items": [ + { + "id": 1, + "name": "用户增长日报", + "description": "每日用户增长情况统计报表", + "template_type": "DAILY", + "data_source": "user_center_service", + "status": "ACTIVE", + "created_at": "2024-01-01T00:00:00Z" + } + ] + } +} +``` + +### 6.2 创建报表模板 + +**接口地址**: `POST /reports/templates` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| name | string | 是 | 报表名称 | +| description | string | 否 | 报表描述 | +| template_type | string | 是 | 模板类型 | +| data_source | string | 是 | 数据源 | +| query_sql | string | 是 | 查询SQL | +| columns_config | object | 否 | 列配置信息 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 模板ID | +| name | string | 报表名称 | +| description | string | 报表描述 | +| template_type | string | 模板类型 | +| data_source | string | 数据源 | +| query_sql | string | 查询SQL | +| columns_config | object | 列配置信息 | +| status | string | 模板状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "name": "交易统计月报", + "description": "每月交易情况统计报表", + "template_type": "MONTHLY", + "data_source": "trade_service", + "query_sql": "SELECT DATE_FORMAT(created_at, '%Y-%m') as month, COUNT(*) as order_count, SUM(total_amount) as total_revenue FROM orders WHERE created_at >= :startDate AND created_at <= :endDate GROUP BY month", + "columns_config": { + "month": "月份", + "order_count": "订单数量", + "total_revenue": "总收入" + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2, + "name": "交易统计月报", + "description": "每月交易情况统计报表", + "template_type": "MONTHLY", + "data_source": "trade_service", + "query_sql": "SELECT DATE_FORMAT(created_at, '%Y-%m') as month, COUNT(*) as order_count, SUM(total_amount) as total_revenue FROM orders WHERE created_at >= :startDate AND created_at <= :endDate GROUP BY month", + "columns_config": { + "month": "月份", + "order_count": "订单数量", + "total_revenue": "总收入" + }, + "status": "ACTIVE", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.3 生成报表 + +**接口地址**: `POST /reports/generate` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| template_id | integer | 是 | 报表模板ID | +| start_date | string | 否 | 统计开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 统计结束日期(YYYY-MM-DD) | +| report_format | string | 否 | 报表格式(PDF/EXCEL/CSV),默认PDF | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 生成记录ID | +| template_id | integer | 报表模板ID | +| report_name | string | 报表文件名 | +| report_format | string | 报表格式 | +| status | string | 生成状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "template_id": 2, + "start_date": "2024-01-01", + "end_date": "2024-01-31", + "report_format": "PDF" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "template_id": 2, + "report_name": "交易统计月报_2024-01.pdf", + "report_format": "PDF", + "status": "GENERATING", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.4 查询报表生成状态 + +**接口地址**: `GET /reports/generations/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 生成记录ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 生成记录ID | +| template_id | integer | 报表模板ID | +| report_name | string | 报表文件名 | +| report_path | string | 报表文件路径 | +| report_format | string | 报表格式 | +| start_date | string | 统计开始日期 | +| end_date | string | 统计结束日期 | +| status | string | 生成状态 | +| generated_at | string | 生成完成时间 | +| created_at | string | 创建时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "template_id": 2, + "report_name": "交易统计月报_2024-01.pdf", + "report_path": "/reports/交易统计月报_2024-01.pdf", + "report_format": "PDF", + "start_date": "2024-01-01", + "end_date": "2024-01-31", + "status": "SUCCESS", + "generated_at": "2024-01-15T10:35:00Z", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.5 下载报表 + +**接口地址**: `GET /reports/download/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 生成记录ID | + +**响应**: +- 成功:返回报表文件流 +- 失败:返回错误信息 + +## 7. 数据分析接口 + +### 7.1 创建分析任务 + +**接口地址**: `POST /analysis/tasks` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| name | string | 是 | 任务名称 | +| description | string | 否 | 任务描述 | +| analysis_type | string | 是 | 分析类型(TREND, CORRELATION, CLUSTER等) | +| data_source | string | 是 | 数据源 | +| parameters | object | 否 | 分析参数 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 任务ID | +| name | string | 任务名称 | +| description | string | 任务描述 | +| analysis_type | string | 分析类型 | +| data_source | string | 数据源 | +| parameters | object | 分析参数 | +| status | string | 任务状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "name": "用户增长趋势分析", + "description": "分析近一年用户增长趋势", + "analysis_type": "TREND", + "data_source": "user_center_service", + "parameters": { + "period": "YEARLY", + "metric": "user_count" + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "name": "用户增长趋势分析", + "description": "分析近一年用户增长趋势", + "analysis_type": "TREND", + "data_source": "user_center_service", + "parameters": { + "period": "YEARLY", + "metric": "user_count" + }, + "status": "PENDING", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 7.2 查询分析任务列表 + +**接口地址**: `GET /analysis/tasks` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| analysis_type | string | 否 | 分析类型 | +| status | string | 否 | 任务状态 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 分析任务列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 2001, + "name": "用户增长趋势分析", + "description": "分析近一年用户增长趋势", + "analysis_type": "TREND", + "data_source": "user_center_service", + "status": "SUCCESS", + "started_at": "2024-01-15T10:31:00Z", + "completed_at": "2024-01-15T10:35:00Z", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 7.3 查询分析任务详情 + +**接口地址**: `GET /analysis/tasks/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 任务ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 任务ID | +| name | string | 任务名称 | +| description | string | 任务描述 | +| analysis_type | string | 分析类型 | +| data_source | string | 数据源 | +| parameters | object | 分析参数 | +| result_data | object | 分析结果数据 | +| status | string | 任务状态 | +| started_at | string | 开始执行时间 | +| completed_at | string | 完成时间 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "name": "用户增长趋势分析", + "description": "分析近一年用户增长趋势", + "analysis_type": "TREND", + "data_source": "user_center_service", + "parameters": { + "period": "YEARLY", + "metric": "user_count" + }, + "result_data": { + "trend_data": [ + { + "date": "2023-01", + "value": 8500 + }, + { + "date": "2023-02", + "value": 8750 + } + ], + "trend_chart": "base64_encoded_image_data" + }, + "status": "SUCCESS", + "started_at": "2024-01-15T10:31:00Z", + "completed_at": "2024-01-15T10:35:00Z", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:35:00Z" + } +} +``` + +## 8. 数据看板接口 + +### 8.1 创建看板配置 + +**接口地址**: `POST /dashboards` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| name | string | 是 | 看板名称 | +| description | string | 否 | 看板描述 | +| layout_config | object | 是 | 布局配置 | +| widgets_config | object | 是 | 组件配置 | +| access_permissions | object | 否 | 访问权限配置 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 配置ID | +| name | string | 看板名称 | +| description | string | 看板描述 | +| layout_config | object | 布局配置 | +| widgets_config | object | 组件配置 | +| access_permissions | object | 访问权限配置 | +| status | string | 配置状态 | +| created_by | integer | 创建人用户ID | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "name": "运营数据看板", + "description": "展示核心运营数据", + "layout_config": { + "grid_columns": 12, + "widgets": [ + { + "id": "widget1", + "x": 0, + "y": 0, + "width": 6, + "height": 4 + } + ] + }, + "widgets_config": { + "widget1": { + "type": "statistic", + "title": "用户总数", + "data_source": "USER_COUNT", + "time_range": "today" + } + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "name": "运营数据看板", + "description": "展示核心运营数据", + "layout_config": { + "grid_columns": 12, + "widgets": [ + { + "id": "widget1", + "x": 0, + "y": 0, + "width": 6, + "height": 4 + } + ] + }, + "widgets_config": { + "widget1": { + "type": "statistic", + "title": "用户总数", + "data_source": "USER_COUNT", + "time_range": "today" + } + }, + "access_permissions": null, + "status": "ACTIVE", + "created_by": 12345, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 8.2 查询看板配置列表 + +**接口地址**: `GET /dashboards` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 配置状态 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 看板配置列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 3001, + "name": "运营数据看板", + "description": "展示核心运营数据", + "status": "ACTIVE", + "created_by": 12345, + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 8.3 获取看板数据 + +**接口地址**: `GET /dashboards/{id}/data` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 看板配置ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 配置ID | +| name | string | 看板名称 | +| widgets_data | object | 各组件数据 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "name": "运营数据看板", + "widgets_data": { + "widget1": { + "title": "用户总数", + "value": 12500, + "change": 150 + } + } + } +} +``` + +## 9. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 40001 | 参数错误 | 请求参数不合法 | +| 40002 | 统计数据不存在 | 指定的统计数据不存在 | +| 40003 | 报表模板不存在 | 指定的报表模板不存在 | +| 40004 | 报表生成记录不存在 | 指定的报表生成记录不存在 | +| 40005 | 分析任务不存在 | 指定的分析任务不存在 | +| 40006 | 看板配置不存在 | 指定的看板配置不存在 | +| 40007 | 报表生成失败 | 报表生成过程中发生错误 | +| 40008 | 数据分析失败 | 数据分析过程中发生错误 | +| 40009 | 报表文件不存在 | 指定的报表文件不存在 | +| 40010 | SQL查询错误 | 报表模板中的SQL查询存在错误 | +| 50001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 50002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/farming_service_api_design.md b/docs/design/api/farming_service_api_design.md new file mode 100644 index 0000000..2866c1c --- /dev/null +++ b/docs/design/api/farming_service_api_design.md @@ -0,0 +1,900 @@ +# 农业服务API设计文档 + +## 1. 概述 + +本文档详细描述了农业服务(farming-service)提供的API接口,包括农田管理、农事活动记录、作物生长监测、病虫害防治、环境数据监测、收获管理等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/farming` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 40001, + "message": "错误描述", + "data": null +} +``` + +## 5. 农田管理接口 + +### 5.1 创建农田 + +**接口地址**: `POST /farmlands` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| name | string | 是 | 农田名称 | +| location | string | 是 | 地理位置 | +| area | number | 是 | 面积(亩) | +| crop_type | string | 是 | 作物类型 | +| planting_date | string | 否 | 种植日期(YYYY-MM-DD) | +| description | string | 否 | 描述 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 农田ID | +| user_id | integer | 用户ID | +| name | string | 农田名称 | +| location | string | 地理位置 | +| area | number | 面积(亩) | +| crop_type | string | 作物类型 | +| planting_date | string | 种植日期 | +| status | string | 状态 | +| description | string | 描述 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "name": "一号小麦田", + "location": "北京市朝阳区某农场", + "area": 100.5, + "crop_type": "小麦", + "planting_date": "2024-01-15", + "description": "春季小麦种植" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "name": "一号小麦田", + "location": "北京市朝阳区某农场", + "area": 100.5, + "crop_type": "小麦", + "planting_date": "2024-01-15", + "status": "ACTIVE", + "description": "春季小麦种植", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.2 获取农田列表 + +**接口地址**: `GET /farmlands` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| crop_type | string | 否 | 作物类型筛选 | +| status | string | 否 | 状态筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 农田列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 2, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "name": "一号小麦田", + "location": "北京市朝阳区某农场", + "area": 100.5, + "crop_type": "小麦", + "planting_date": "2024-01-15", + "status": "ACTIVE", + "description": "春季小麦种植", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 5.3 获取农田详情 + +**接口地址**: `GET /farmlands/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 农田ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 农田ID | +| user_id | integer | 用户ID | +| name | string | 农田名称 | +| location | string | 地理位置 | +| area | number | 面积(亩) | +| crop_type | string | 作物类型 | +| planting_date | string | 种植日期 | +| status | string | 状态 | +| description | string | 描述 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "name": "一号小麦田", + "location": "北京市朝阳区某农场", + "area": 100.5, + "crop_type": "小麦", + "planting_date": "2024-01-15", + "status": "ACTIVE", + "description": "春季小麦种植", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.4 更新农田信息 + +**接口地址**: `PUT /farmlands/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 农田ID | +| name | string | 否 | 农田名称 | +| location | string | 否 | 地理位置 | +| area | number | 否 | 面积(亩) | +| crop_type | string | 否 | 作物类型 | +| planting_date | string | 否 | 种植日期(YYYY-MM-DD) | +| status | string | 否 | 状态 | +| description | string | 否 | 描述 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 农田ID | +| user_id | integer | 用户ID | +| name | string | 农田名称 | +| location | string | 地理位置 | +| area | number | 面积(亩) | +| crop_type | string | 作物类型 | +| planting_date | string | 种植日期 | +| status | string | 状态 | +| description | string | 描述 | +| updated_at | string | 更新时间 | + +**示例请求**: +```json +{ + "name": "一号小麦田", + "location": "北京市朝阳区某农场", + "area": 100.5, + "crop_type": "小麦", + "planting_date": "2024-01-15", + "status": "ACTIVE", + "description": "春季小麦种植,已施肥" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "name": "一号小麦田", + "location": "北京市朝阳区某农场", + "area": 100.5, + "crop_type": "小麦", + "planting_date": "2024-01-15", + "status": "ACTIVE", + "description": "春季小麦种植,已施肥", + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +## 6. 农事活动接口 + +### 6.1 记录农事活动 + +**接口地址**: `POST /activities` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 是 | 农田ID | +| activity_type | string | 是 | 活动类型(播种/施肥/除草/收割等) | +| activity_date | string | 是 | 活动日期(YYYY-MM-DD) | +| description | string | 否 | 活动描述 | +| cost | number | 否 | 费用 | +| operator | string | 否 | 操作人员 | +| images | array | 否 | 活动图片URL列表 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 活动记录ID | +| farmland_id | integer | 农田ID | +| activity_type | string | 活动类型 | +| activity_date | string | 活动日期 | +| description | string | 活动描述 | +| cost | number | 费用 | +| operator | string | 操作人员 | +| images | array | 活动图片URL列表 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "farmland_id": 1001, + "activity_type": "施肥", + "activity_date": "2024-01-20", + "description": "施用氮肥", + "cost": 500.00, + "operator": "张三", + "images": ["https://example.com/image1.jpg"] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "farmland_id": 1001, + "activity_type": "施肥", + "activity_date": "2024-01-20", + "description": "施用氮肥", + "cost": 500.00, + "operator": "张三", + "images": ["https://example.com/image1.jpg"], + "created_at": "2024-01-20T10:30:00Z" + } +} +``` + +### 6.2 获取农事活动列表 + +**接口地址**: `GET /activities` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 否 | 农田ID筛选 | +| activity_type | string | 否 | 活动类型筛选 | +| start_date | string | 否 | 开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 活动记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 2001, + "farmland_id": 1001, + "activity_type": "施肥", + "activity_date": "2024-01-20", + "description": "施用氮肥", + "cost": 500.00, + "operator": "张三", + "images": ["https://example.com/image1.jpg"], + "created_at": "2024-01-20T10:30:00Z" + } + ] + } +} +``` + +## 7. 作物生长监测接口 + +### 7.1 记录作物生长情况 + +**接口地址**: `POST /growth-records` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 是 | 农田ID | +| record_date | string | 是 | 记录日期(YYYY-MM-DD) | +| growth_stage | string | 是 | 生长阶段 | +| height | number | 否 | 株高(cm) | +| leaf_count | integer | 否 | 叶片数 | +| health_status | string | 否 | 健康状况 | +| notes | string | 否 | 备注 | +| images | array | 否 | 图片URL列表 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 记录ID | +| farmland_id | integer | 农田ID | +| record_date | string | 记录日期 | +| growth_stage | string | 生长阶段 | +| height | number | 株高(cm) | +| leaf_count | integer | 叶片数 | +| health_status | string | 健康状况 | +| notes | string | 备注 | +| images | array | 图片URL列表 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "farmland_id": 1001, + "record_date": "2024-01-25", + "growth_stage": "分蘖期", + "height": 15.5, + "leaf_count": 6, + "health_status": "健康", + "notes": "生长良好", + "images": ["https://example.com/image2.jpg"] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "farmland_id": 1001, + "record_date": "2024-01-25", + "growth_stage": "分蘖期", + "height": 15.5, + "leaf_count": 6, + "health_status": "健康", + "notes": "生长良好", + "images": ["https://example.com/image2.jpg"], + "created_at": "2024-01-25T10:30:00Z" + } +} +``` + +### 7.2 获取作物生长记录列表 + +**接口地址**: `GET /growth-records` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 否 | 农田ID筛选 | +| growth_stage | string | 否 | 生长阶段筛选 | +| start_date | string | 否 | 开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 生长记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 3001, + "farmland_id": 1001, + "record_date": "2024-01-25", + "growth_stage": "分蘖期", + "height": 15.5, + "leaf_count": 6, + "health_status": "健康", + "notes": "生长良好", + "images": ["https://example.com/image2.jpg"], + "created_at": "2024-01-25T10:30:00Z" + } + ] + } +} +``` + +## 8. 病虫害防治接口 + +### 8.1 记录病虫害情况 + +**接口地址**: `POST /pest-disease-records` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 是 | 农田ID | +| record_date | string | 是 | 记录日期(YYYY-MM-DD) | +| type | string | 是 | 类型(病害/虫害) | +| name | string | 是 | 病虫害名称 | +| severity | string | 是 | 严重程度(轻/中/重) | +| affected_area | number | 否 | 受害面积(亩) | +| control_method | string | 否 | 防治方法 | +| control_date | string | 否 | 防治日期(YYYY-MM-DD) | +| control_result | string | 否 | 防治效果 | +| notes | string | 否 | 备注 | +| images | array | 否 | 图片URL列表 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 记录ID | +| farmland_id | integer | 农田ID | +| record_date | string | 记录日期 | +| type | string | 类型 | +| name | string | 病虫害名称 | +| severity | string | 严重程度 | +| affected_area | number | 受害面积(亩) | +| control_method | string | 防治方法 | +| control_date | string | 防治日期 | +| control_result | string | 防治效果 | +| notes | string | 备注 | +| images | array | 图片URL列表 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "farmland_id": 1001, + "record_date": "2024-01-30", + "type": "病害", + "name": "小麦赤霉病", + "severity": "中", + "affected_area": 20.0, + "control_method": "喷施多菌灵", + "control_date": "2024-01-31", + "control_result": "控制良好", + "notes": "发现较早,及时处理", + "images": ["https://example.com/image3.jpg"] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 4001, + "farmland_id": 1001, + "record_date": "2024-01-30", + "type": "病害", + "name": "小麦赤霉病", + "severity": "中", + "affected_area": 20.0, + "control_method": "喷施多菌灵", + "control_date": "2024-01-31", + "control_result": "控制良好", + "notes": "发现较早,及时处理", + "images": ["https://example.com/image3.jpg"], + "created_at": "2024-01-30T10:30:00Z" + } +} +``` + +### 8.2 获取病虫害记录列表 + +**接口地址**: `GET /pest-disease-records` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 否 | 农田ID筛选 | +| type | string | 否 | 类型筛选 | +| name | string | 否 | 病虫害名称筛选 | +| start_date | string | 否 | 开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 病虫害记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 4001, + "farmland_id": 1001, + "record_date": "2024-01-30", + "type": "病害", + "name": "小麦赤霉病", + "severity": "中", + "affected_area": 20.0, + "control_method": "喷施多菌灵", + "control_date": "2024-01-31", + "control_result": "控制良好", + "notes": "发现较早,及时处理", + "images": ["https://example.com/image3.jpg"], + "created_at": "2024-01-30T10:30:00Z" + } + ] + } +} +``` + +## 9. 环境数据监测接口 + +### 9.1 记录环境数据 + +**接口地址**: `POST /environmental-data` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 是 | 农田ID | +| record_time | string | 否 | 记录时间(ISO8601格式),默认为当前时间 | +| temperature | number | 否 | 温度(℃) | +| humidity | number | 否 | 湿度(%) | +| soil_moisture | number | 否 | 土壤湿度(%) | +| ph_value | number | 否 | 土壤pH值 | +| nitrogen | number | 否 | 氮含量(mg/kg) | +| phosphorus | number | 否 | 磷含量(mg/kg) | +| potassium | number | 否 | 钾含量(mg/kg) | +| notes | string | 否 | 备注 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 记录ID | +| farmland_id | integer | 农田ID | +| record_time | string | 记录时间 | +| temperature | number | 温度(℃) | +| humidity | number | 湿度(%) | +| soil_moisture | number | 土壤湿度(%) | +| ph_value | number | 土壤pH值 | +| nitrogen | number | 氮含量(mg/kg) | +| phosphorus | number | 磷含量(mg/kg) | +| potassium | number | 钾含量(mg/kg) | +| notes | string | 备注 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "farmland_id": 1001, + "record_time": "2024-02-01T10:00:00Z", + "temperature": 15.5, + "humidity": 65.0, + "soil_moisture": 45.0, + "ph_value": 6.8, + "nitrogen": 120.5, + "phosphorus": 45.2, + "potassium": 180.3, + "notes": "环境适宜作物生长" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 5001, + "farmland_id": 1001, + "record_time": "2024-02-01T10:00:00Z", + "temperature": 15.5, + "humidity": 65.0, + "soil_moisture": 45.0, + "ph_value": 6.8, + "nitrogen": 120.5, + "phosphorus": 45.2, + "potassium": 180.3, + "notes": "环境适宜作物生长", + "created_at": "2024-02-01T10:00:00Z" + } +} +``` + +### 9.2 获取环境数据列表 + +**接口地址**: `GET /environmental-data` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 否 | 农田ID筛选 | +| start_time | string | 否 | 开始时间(ISO8601格式) | +| end_time | string | 否 | 结束时间(ISO8601格式) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 环境数据列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 5001, + "farmland_id": 1001, + "record_time": "2024-02-01T10:00:00Z", + "temperature": 15.5, + "humidity": 65.0, + "soil_moisture": 45.0, + "ph_value": 6.8, + "nitrogen": 120.5, + "phosphorus": 45.2, + "potassium": 180.3, + "notes": "环境适宜作物生长", + "created_at": "2024-02-01T10:00:00Z" + } + ] + } +} +``` + +## 10. 收获管理接口 + +### 10.1 记录收获信息 + +**接口地址**: `POST /harvest-records` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 是 | 农田ID | +| harvest_date | string | 是 | 收获日期(YYYY-MM-DD) | +| yield | number | 是 | 产量(公斤) | +| quality | string | 否 | 质量等级 | +| storage_location | string | 否 | 存储位置 | +| selling_price | number | 否 | 销售价格(元/公斤) | +| sold_quantity | number | 否 | 已售数量(公斤) | +| notes | string | 否 | 备注 | +| images | array | 否 | 图片URL列表 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 记录ID | +| farmland_id | integer | 农田ID | +| harvest_date | string | 收获日期 | +| yield | number | 产量(公斤) | +| quality | string | 质量等级 | +| storage_location | string | 存储位置 | +| selling_price | number | 销售价格(元/公斤) | +| sold_quantity | number | 已售数量(公斤) | +| notes | string | 备注 | +| images | array | 图片URL列表 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "farmland_id": 1001, + "harvest_date": "2024-06-15", + "yield": 52000.0, + "quality": "一级", + "storage_location": "一号仓库", + "selling_price": 2.5, + "sold_quantity": 30000.0, + "notes": "丰收年,质量上乘", + "images": ["https://example.com/image4.jpg"] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 6001, + "farmland_id": 1001, + "harvest_date": "2024-06-15", + "yield": 52000.0, + "quality": "一级", + "storage_location": "一号仓库", + "selling_price": 2.5, + "sold_quantity": 30000.0, + "notes": "丰收年,质量上乘", + "images": ["https://example.com/image4.jpg"], + "created_at": "2024-06-15T10:30:00Z" + } +} +``` + +### 10.2 获取收获记录列表 + +**接口地址**: `GET /harvest-records` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| farmland_id | integer | 否 | 农田ID筛选 | +| start_date | string | 否 | 开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 收获记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 6001, + "farmland_id": 1001, + "harvest_date": "2024-06-15", + "yield": 52000.0, + "quality": "一级", + "storage_location": "一号仓库", + "selling_price": 2.5, + "sold_quantity": 30000.0, + "notes": "丰收年,质量上乘", + "images": ["https://example.com/image4.jpg"], + "created_at": "2024-06-15T10:30:00Z" + } + ] + } +} +``` + +## 11. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 40001 | 参数错误 | 请求参数不合法 | +| 40002 | 农田不存在 | 指定的农田不存在 | +| 40003 | 农田状态不允许此操作 | 当前农田状态不允许执行该操作 | +| 40004 | 农事活动记录不存在 | 指定的农事活动记录不存在 | +| 40005 | 作物生长记录不存在 | 指定的作物生长记录不存在 | +| 40006 | 病虫害记录不存在 | 指定的病虫害记录不存在 | +| 40007 | 环境数据记录不存在 | 指定的环境数据记录不存在 | +| 40008 | 收获记录不存在 | 指定的收获记录不存在 | +| 50001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 50002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/finance_service_api_design.md b/docs/design/api/finance_service_api_design.md new file mode 100644 index 0000000..65a8c1c --- /dev/null +++ b/docs/design/api/finance_service_api_design.md @@ -0,0 +1,535 @@ +# 金融服务API设计文档 + +## 1. 概述 + +本文档详细描述了金融服务(finance-service)提供的API接口,包括贷款管理、保险管理等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/finance` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 20001, + "message": "错误描述", + "data": null +} +``` + +## 5. 贷款管理接口 + +### 5.1 获取贷款产品列表 + +**接口地址**: `GET /loans/products` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 产品状态(ACTIVE/INACTIVE) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 贷款产品列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 5, + "page": 1, + "size": 10, + "items": [ + { + "id": 1, + "name": "养殖贷款", + "description": "专为养殖户设计的贷款产品", + "interest_rate": 0.052, + "term_months": 12, + "min_amount": 10000.00, + "max_amount": 1000000.00, + "status": "ACTIVE", + "created_at": "2024-01-01T00:00:00Z" + } + ] + } +} +``` + +### 5.2 提交贷款申请 + +**接口地址**: `POST /loans/applications` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_id | integer | 是 | 贷款产品ID | +| amount | number | 是 | 申请金额 | +| term_months | integer | 是 | 申请期限(月) | +| purpose | string | 否 | 贷款用途 | +| contact_info | object | 是 | 联系信息 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 贷款申请ID | +| user_id | integer | 申请人用户ID | +| product_id | integer | 贷款产品ID | +| amount | number | 申请金额 | +| term_months | integer | 申请期限(月) | +| status | string | 申请状态 | +| purpose | string | 贷款用途 | +| contact_info | object | 联系信息 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "product_id": 1, + "amount": 50000.00, + "term_months": 12, + "purpose": "购买饲料", + "contact_info": { + "phone": "13800138000", + "email": "user@example.com", + "address": "北京市朝阳区xxx街道" + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "product_id": 1, + "amount": 50000.00, + "term_months": 12, + "status": "SUBMITTED", + "purpose": "购买饲料", + "contact_info": { + "phone": "13800138000", + "email": "user@example.com", + "address": "北京市朝阳区xxx街道" + }, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.3 查询贷款申请列表 + +**接口地址**: `GET /loans/applications` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 申请状态 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 贷款申请列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "user_id": 12345, + "product": { + "id": 1, + "name": "养殖贷款" + }, + "amount": 50000.00, + "term_months": 12, + "status": "APPROVED", + "purpose": "购买饲料", + "contact_info": { + "phone": "13800138000", + "email": "user@example.com" + }, + "approval_time": "2024-01-16T09:00:00Z", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 5.4 查询贷款申请详情 + +**接口地址**: `GET /loans/applications/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 贷款申请ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 贷款申请ID | +| user_id | integer | 申请人用户ID | +| product | object | 贷款产品信息 | +| amount | number | 申请金额 | +| term_months | integer | 申请期限(月) | +| status | string | 申请状态 | +| purpose | string | 贷款用途 | +| contact_info | object | 联系信息 | +| credit_score | integer | 信用评分 | +| approval_time | string | 审批时间 | +| disbursement_time | string | 放款时间 | +| settlement_time | string | 结清时间 | +| repayment_schedules | array | 还款计划列表 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "product": { + "id": 1, + "name": "养殖贷款", + "interest_rate": 0.052, + "term_months": 12 + }, + "amount": 50000.00, + "term_months": 12, + "status": "DISBURSED", + "purpose": "购买饲料", + "contact_info": { + "phone": "13800138000", + "email": "user@example.com", + "address": "北京市朝阳区xxx街道" + }, + "credit_score": 750, + "approval_time": "2024-01-16T09:00:00Z", + "disbursement_time": "2024-01-17T10:00:00Z", + "repayment_schedules": [ + { + "id": 1, + "installment_number": 1, + "due_date": "2024-02-17", + "principal_amount": 4166.67, + "interest_amount": 216.67, + "total_amount": 4383.34, + "status": "PENDING" + } + ], + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-17T10:00:00Z" + } +} +``` + +## 6. 保险管理接口 + +### 6.1 获取保险产品列表 + +**接口地址**: `GET /insurance/products` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| type | string | 否 | 保险类型(CATTLE/PROPERTY/LIABILITY) | +| status | string | 否 | 产品状态(ACTIVE/INACTIVE) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 保险产品列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 3, + "page": 1, + "size": 10, + "items": [ + { + "id": 1, + "name": "牲畜保险", + "description": "为牲畜提供全面保障的保险产品", + "premium_rate": 0.005, + "coverage_amount": 10000.00, + "term_months": 12, + "type": "CATTLE", + "status": "ACTIVE", + "created_at": "2024-01-01T00:00:00Z" + } + ] + } +} +``` + +### 6.2 提交保险投保申请 + +**接口地址**: `POST /insurance/policies` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_id | integer | 是 | 保险产品ID | +| insured_amount | number | 是 | 投保金额 | +| start_date | string | 是 | 保险起始日期(YYYY-MM-DD) | +| beneficiary_info | object | 是 | 受益人信息 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 保单ID | +| user_id | integer | 投保人用户ID | +| product_id | integer | 保险产品ID | +| policy_no | string | 保单号 | +| insured_amount | number | 投保金额 | +| premium_amount | number | 保费金额 | +| status | string | 保单状态 | +| start_date | string | 保险起始日期 | +| end_date | string | 保险结束日期 | +| beneficiary_info | object | 受益人信息 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "product_id": 1, + "insured_amount": 50000.00, + "start_date": "2024-02-01", + "beneficiary_info": { + "name": "张三", + "id_card": "110101199001011234", + "phone": "13800138000" + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "user_id": 12345, + "product_id": 1, + "policy_no": "INS202401150001", + "insured_amount": 50000.00, + "premium_amount": 250.00, + "status": "ACTIVE", + "start_date": "2024-02-01", + "end_date": "2025-01-31", + "beneficiary_info": { + "name": "张三", + "id_card": "110101199001011234", + "phone": "13800138000" + }, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.3 查询保险投保列表 + +**接口地址**: `GET /insurance/policies` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 保单状态 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 保险投保列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 2001, + "user_id": 12345, + "policy_no": "INS202401150001", + "product": { + "id": 1, + "name": "牲畜保险" + }, + "insured_amount": 50000.00, + "premium_amount": 250.00, + "status": "ACTIVE", + "start_date": "2024-02-01", + "end_date": "2025-01-31", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 6.4 提交理赔申请 + +**接口地址**: `POST /insurance/claims` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| policy_id | integer | 是 | 保单ID | +| claim_amount | number | 是 | 理赔金额 | +| incident_date | string | 是 | 事故日期(YYYY-MM-DD) | +| incident_description | string | 是 | 事故描述 | +| supporting_documents | array | 否 | 支持文件URL列表 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 理赔申请ID | +| policy_id | integer | 关联保单ID | +| claim_no | string | 理赔编号 | +| claim_amount | number | 理赔金额 | +| status | string | 理赔状态 | +| incident_date | string | 事故日期 | +| incident_description | string | 事故描述 | +| supporting_documents | array | 支持文件URL列表 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "policy_id": 2001, + "claim_amount": 20000.00, + "incident_date": "2024-03-01", + "incident_description": "牲畜因疾病死亡", + "supporting_documents": [ + "http://example.com/document1.jpg", + "http://example.com/document2.jpg" + ] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "policy_id": 2001, + "claim_no": "CLM202403010001", + "claim_amount": 20000.00, + "status": "SUBMITTED", + "incident_date": "2024-03-01", + "incident_description": "牲畜因疾病死亡", + "supporting_documents": [ + "http://example.com/document1.jpg", + "http://example.com/document2.jpg" + ], + "created_at": "2024-03-01T10:30:00Z" + } +} +``` + +## 7. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 20001 | 参数错误 | 请求参数不合法 | +| 20002 | 贷款产品不存在 | 指定的贷款产品不存在 | +| 20003 | 贷款申请不存在 | 指定的贷款申请不存在 | +| 20004 | 保险产品不存在 | 指定的保险产品不存在 | +| 20005 | 保单不存在 | 指定的保单不存在 | +| 20006 | 理赔申请不存在 | 指定的理赔申请不存在 | +| 20007 | 申请金额超出范围 | 贷款申请金额超出产品规定范围 | +| 20008 | 保险金额超出范围 | 保险金额超出产品规定范围 | +| 20009 | 保单已过期 | 保单已过期,无法提交理赔 | +| 20010 | 理赔金额超出保额 | 理赔金额超出保险金额 | +| 20011 | 申请状态错误 | 当前申请状态无法执行该操作 | +| 30001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 30002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/government_service_api_design.md b/docs/design/api/government_service_api_design.md new file mode 100644 index 0000000..c26ad5c --- /dev/null +++ b/docs/design/api/government_service_api_design.md @@ -0,0 +1,883 @@ +# 政府服务API设计文档 + +## 1. 概述 + +本文档详细描述了政府服务(government-service)提供的API接口,包括政策法规查询、补贴申请、合规检查等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/government` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 40001, + "message": "错误描述", + "data": null +} +``` + +## 5. 政策法规接口 + +### 5.1 获取政策法规列表 + +**接口地址**: `GET /policies` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| category | string | 否 | 政策分类 | +| status | string | 否 | 状态(PUBLISHED/DRAFT/EXPIRED) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 政策法规列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 20, + "page": 1, + "size": 10, + "items": [ + { + "id": 1, + "title": "2024年农业补贴政策", + "category": "农业扶持", + "publish_date": "2024-01-15", + "effective_date": "2024-02-01", + "expiry_date": "2024-12-31", + "issuing_authority": "农业农村部", + "status": "PUBLISHED", + "created_at": "2024-01-15T00:00:00Z" + } + ] + } +} +``` + +### 5.2 获取政策法规详情 + +**接口地址**: `GET /policies/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 政策ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 政策ID | +| title | string | 政策标题 | +| content | string | 政策内容 | +| category | string | 政策分类 | +| publish_date | string | 发布日期 | +| effective_date | string | 生效日期 | +| expiry_date | string | 失效日期 | +| issuing_authority | string | 发布机构 | +| policy_number | string | 政策文号 | +| status | string | 状态 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1, + "title": "2024年农业补贴政策", + "content": "详细政策内容...", + "category": "农业扶持", + "publish_date": "2024-01-15", + "effective_date": "2024-02-01", + "expiry_date": "2024-12-31", + "issuing_authority": "农业农村部", + "policy_number": "NYB-2024-001", + "status": "PUBLISHED", + "created_at": "2024-01-15T00:00:00Z", + "updated_at": "2024-01-15T00:00:00Z" + } +} +``` + +## 6. 补贴申请接口 + +### 6.1 提交补贴申请 + +**接口地址**: `POST /subsidies/applications` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| policy_id | integer | 是 | 关联政策ID | +| project_name | string | 是 | 项目名称 | +| project_description | string | 是 | 项目描述 | +| applied_amount | number | 是 | 申请金额 | +| application_date | string | 是 | 申请日期(YYYY-MM-DD) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 申请ID | +| applicant_id | integer | 申请人ID | +| applicant_type | string | 申请人类型 | +| policy_id | integer | 关联政策ID | +| application_number | string | 申请编号 | +| project_name | string | 项目名称 | +| project_description | string | 项目描述 | +| applied_amount | number | 申请金额 | +| application_date | string | 申请日期 | +| status | string | 申请状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "policy_id": 1, + "project_name": "小麦种植补贴申请", + "project_description": "申请2024年度小麦种植补贴", + "applied_amount": 5000.00, + "application_date": "2024-01-15" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "applicant_id": 12345, + "applicant_type": "FARMER", + "policy_id": 1, + "application_number": "SBA-20240115-0001", + "project_name": "小麦种植补贴申请", + "project_description": "申请2024年度小麦种植补贴", + "applied_amount": 5000.00, + "application_date": "2024-01-15", + "status": "SUBMITTED", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.2 查询补贴申请列表 + +**接口地址**: `GET /subsidies/applications` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 申请状态 | +| start_date | string | 否 | 申请开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 申请结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 补贴申请列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 5, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "applicant_id": 12345, + "applicant_type": "FARMER", + "policy_id": 1, + "application_number": "SBA-20240115-0001", + "project_name": "小麦种植补贴申请", + "applied_amount": 5000.00, + "application_date": "2024-01-15", + "status": "REVIEWING", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 6.3 查询补贴申请详情 + +**接口地址**: `GET /subsidies/applications/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 申请ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 申请ID | +| applicant_id | integer | 申请人ID | +| applicant_type | string | 申请人类型 | +| policy | object | 关联政策信息 | +| application_number | string | 申请编号 | +| project_name | string | 项目名称 | +| project_description | string | 项目描述 | +| applied_amount | number | 申请金额 | +| actual_amount | number | 实际发放金额 | +| application_date | string | 申请日期 | +| status | string | 申请状态 | +| review_notes | string | 审核备注 | +| review_date | string | 审核日期 | +| disbursement_date | string | 发放日期 | +| disbursements | array | 发放记录列表 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "applicant_id": 12345, + "applicant_type": "FARMER", + "policy": { + "id": 1, + "title": "2024年农业补贴政策", + "category": "农业扶持" + }, + "application_number": "SBA-20240115-0001", + "project_name": "小麦种植补贴申请", + "project_description": "申请2024年度小麦种植补贴", + "applied_amount": 5000.00, + "actual_amount": 4800.00, + "application_date": "2024-01-15", + "status": "DISBURSED", + "review_notes": "审核通过", + "review_date": "2024-01-20T00:00:00Z", + "disbursement_date": "2024-01-25", + "disbursements": [ + { + "id": 2001, + "disbursement_amount": 4800.00, + "disbursement_date": "2024-01-25", + "payment_method": "BANK_TRANSFER", + "payment_reference": "PAY-20240125-0001", + "recipient_account": "6222********1234", + "status": "SUCCESS" + } + ], + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-25T00:00:00Z" + } +} +``` + +## 7. 合规检查接口 + +### 7.1 提交合规检查记录 + +**接口地址**: `POST /compliance/inspections` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| inspected_entity_id | integer | 是 | 被检查实体ID | +| entity_type | string | 是 | 实体类型(FARMER/COMPANY) | +| inspection_date | string | 是 | 检查日期(YYYY-MM-DD) | +| inspection_type | string | 是 | 检查类型 | +| findings | string | 否 | 检查发现 | +| corrective_actions | string | 否 | 整改措施 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 检查记录ID | +| inspected_entity_id | integer | 被检查实体ID | +| entity_type | string | 实体类型 | +| inspector_id | integer | 检查员ID | +| inspection_date | string | 检查日期 | +| inspection_type | string | 检查类型 | +| inspection_result | string | 检查结果 | +| findings | string | 检查发现 | +| corrective_actions | string | 整改措施 | +| status | string | 状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "inspected_entity_id": 12345, + "entity_type": "FARMER", + "inspection_date": "2024-01-15", + "inspection_type": "环保检查", + "findings": "农药使用记录不完整", + "corrective_actions": "要求完善农药使用记录" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "inspected_entity_id": 12345, + "entity_type": "FARMER", + "inspector_id": 54321, + "inspection_date": "2024-01-15", + "inspection_type": "环保检查", + "inspection_result": "FAIL", + "findings": "农药使用记录不完整", + "corrective_actions": "要求完善农药使用记录", + "status": "COMPLETED", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 7.2 查询合规检查记录列表 + +**接口地址**: `GET /compliance/inspections` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| entity_type | string | 否 | 实体类型 | +| inspection_type | string | 否 | 检查类型 | +| inspection_result | string | 否 | 检查结果 | +| start_date | string | 否 | 检查开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 检查结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 检查记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 3, + "page": 1, + "size": 10, + "items": [ + { + "id": 3001, + "inspected_entity_id": 12345, + "entity_type": "FARMER", + "inspector_id": 54321, + "inspection_date": "2024-01-15", + "inspection_type": "环保检查", + "inspection_result": "FAIL", + "status": "COMPLETED", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 7.3 查询合规检查记录详情 + +**接口地址**: `GET /compliance/inspections/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 检查记录ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 检查记录ID | +| inspected_entity | object | 被检查实体信息 | +| inspector | object | 检查员信息 | +| inspection_date | string | 检查日期 | +| inspection_type | string | 检查类型 | +| inspection_result | string | 检查结果 | +| findings | string | 检查发现 | +| corrective_actions | string | 整改措施 | +| follow_up_date | string | 跟进日期 | +| status | string | 状态 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "inspected_entity": { + "id": 12345, + "name": "张三农场", + "type": "FARMER" + }, + "inspector": { + "id": 54321, + "name": "李四" + }, + "inspection_date": "2024-01-15", + "inspection_type": "环保检查", + "inspection_result": "FAIL", + "findings": "农药使用记录不完整", + "corrective_actions": "要求完善农药使用记录", + "follow_up_date": "2024-02-15", + "status": "FOLLOW_UP_REQUIRED", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +## 8. 土地流转接口 + +### 8.1 提交土地流转信息 + +**接口地址**: `POST /land/transfers` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| land_owner_id | integer | 是 | 土地所有者ID | +| transferee_id | integer | 是 | 受让方ID | +| land_location | string | 是 | 土地位置 | +| land_area | number | 是 | 土地面积(亩) | +| transfer_type | string | 是 | 流转类型(LEASE/SALE/CONTRACT) | +| transfer_term | integer | 是 | 流转期限(年) | +| annual_rent | number | 否 | 年租金(元/亩) | +| total_amount | number | 否 | 总金额 | +| start_date | string | 是 | 开始日期(YYYY-MM-DD) | +| end_date | string | 是 | 结束日期(YYYY-MM-DD) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 流转信息ID | +| land_owner_id | integer | 土地所有者ID | +| transferee_id | integer | 受让方ID | +| land_location | string | 土地位置 | +| land_area | number | 土地面积 | +| transfer_type | string | 流转类型 | +| transfer_term | integer | 流转期限 | +| annual_rent | number | 年租金 | +| total_amount | number | 总金额 | +| start_date | string | 开始日期 | +| end_date | string | 结束日期 | +| contract_number | string | 合同编号 | +| status | string | 状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "land_owner_id": 12345, + "transferee_id": 67890, + "land_location": "北京市朝阳区某村", + "land_area": 50.00, + "transfer_type": "LEASE", + "transfer_term": 5, + "annual_rent": 1000.00, + "start_date": "2024-01-01", + "end_date": "2028-12-31" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 4001, + "land_owner_id": 12345, + "transferee_id": 67890, + "land_location": "北京市朝阳区某村", + "land_area": 50.00, + "transfer_type": "LEASE", + "transfer_term": 5, + "annual_rent": 1000.00, + "total_amount": 50000.00, + "start_date": "2024-01-01", + "end_date": "2028-12-31", + "contract_number": "LTC-20240101-0001", + "status": "ACTIVE", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 8.2 查询土地流转信息列表 + +**接口地址**: `GET /land/transfers` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| land_owner_id | integer | 否 | 土地所有者ID | +| transferee_id | integer | 否 | 受让方ID | +| status | string | 否 | 状态 | +| start_date | string | 否 | 开始日期(YYYY-MM-DD) | +| end_date | string | 否 | 结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 流转信息列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 2, + "page": 1, + "size": 10, + "items": [ + { + "id": 4001, + "land_owner_id": 12345, + "transferee_id": 67890, + "land_location": "北京市朝阳区某村", + "land_area": 50.00, + "transfer_type": "LEASE", + "transfer_term": 5, + "annual_rent": 1000.00, + "total_amount": 50000.00, + "start_date": "2024-01-01", + "end_date": "2028-12-31", + "contract_number": "LTC-20240101-0001", + "status": "ACTIVE", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 8.3 查询土地流转信息详情 + +**接口地址**: `GET /land/transfers/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 流转信息ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 流转信息ID | +| land_owner | object | 土地所有者信息 | +| transferee | object | 受让方信息 | +| land_location | string | 土地位置 | +| land_area | number | 土地面积 | +| transfer_type | string | 流转类型 | +| transfer_term | integer | 流转期限 | +| annual_rent | number | 年租金 | +| total_amount | number | 总金额 | +| start_date | string | 开始日期 | +| end_date | string | 结束日期 | +| contract_number | string | 合同编号 | +| status | string | 状态 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 4001, + "land_owner": { + "id": 12345, + "name": "张三" + }, + "transferee": { + "id": 67890, + "name": "李四农业合作社" + }, + "land_location": "北京市朝阳区某村", + "land_area": 50.00, + "transfer_type": "LEASE", + "transfer_term": 5, + "annual_rent": 1000.00, + "total_amount": 50000.00, + "start_date": "2024-01-01", + "end_date": "2028-12-31", + "contract_number": "LTC-20240101-0001", + "status": "ACTIVE", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +## 9. 农产品质量认证接口 + +### 9.1 提交农产品质量认证申请 + +**接口地址**: `POST /certifications` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_name | string | 是 | 产品名称 | +| certification_type | string | 是 | 认证类型 | +| issuing_authority | string | 是 | 发证机构 | +| issue_date | string | 是 | 发证日期(YYYY-MM-DD) | +| expiry_date | string | 是 | 有效期至(YYYY-MM-DD) | +| inspection_report | string | 否 | 检验报告 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 认证ID | +| producer_id | integer | 生产者ID | +| product_name | string | 产品名称 | +| certification_type | string | 认证类型 | +| certification_number | string | 认证编号 | +| issuing_authority | string | 发证机构 | +| issue_date | string | 发证日期 | +| expiry_date | string | 有效期至 | +| certification_status | string | 认证状态 | +| inspection_report | string | 检验报告 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "product_name": "绿色有机苹果", + "certification_type": "绿色食品", + "issuing_authority": "中国绿色食品发展中心", + "issue_date": "2024-01-01", + "expiry_date": "2025-01-01", + "inspection_report": "检验报告内容..." +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 5001, + "producer_id": 12345, + "product_name": "绿色有机苹果", + "certification_type": "绿色食品", + "certification_number": "GF-20240101-0001", + "issuing_authority": "中国绿色食品发展中心", + "issue_date": "2024-01-01", + "expiry_date": "2025-01-01", + "certification_status": "VALID", + "inspection_report": "检验报告内容...", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 9.2 查询农产品质量认证列表 + +**接口地址**: `GET /certifications` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| certification_type | string | 否 | 认证类型 | +| certification_status | string | 否 | 认证状态 | +| expiry_start_date | string | 否 | 到期开始日期(YYYY-MM-DD) | +| expiry_end_date | string | 否 | 到期结束日期(YYYY-MM-DD) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 认证信息列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 5001, + "producer_id": 12345, + "product_name": "绿色有机苹果", + "certification_type": "绿色食品", + "certification_number": "GF-20240101-0001", + "issuing_authority": "中国绿色食品发展中心", + "issue_date": "2024-01-01", + "expiry_date": "2025-01-01", + "certification_status": "VALID", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 9.3 查询农产品质量认证详情 + +**接口地址**: `GET /certifications/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 认证ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 认证ID | +| producer | object | 生产者信息 | +| product_name | string | 产品名称 | +| certification_type | string | 认证类型 | +| certification_number | string | 认证编号 | +| issuing_authority | string | 发证机构 | +| issue_date | string | 发证日期 | +| expiry_date | string | 有效期至 | +| certification_status | string | 认证状态 | +| inspection_report | string | 检验报告 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 5001, + "producer": { + "id": 12345, + "name": "张三农场" + }, + "product_name": "绿色有机苹果", + "certification_type": "绿色食品", + "certification_number": "GF-20240101-0001", + "issuing_authority": "中国绿色食品发展中心", + "issue_date": "2024-01-01", + "expiry_date": "2025-01-01", + "certification_status": "VALID", + "inspection_report": "检验报告内容...", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +## 10. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 40001 | 参数错误 | 请求参数不合法 | +| 40002 | 政策法规不存在 | 指定的政策法规不存在 | +| 40003 | 补贴申请不存在 | 指定的补贴申请不存在 | +| 40004 | 合规检查记录不存在 | 指定的合规检查记录不存在 | +| 40005 | 土地流转信息不存在 | 指定的土地流转信息不存在 | +| 40006 | 农产品质量认证不存在 | 指定的农产品质量认证不存在 | +| 40007 | 补贴申请提交失败 | 补贴申请提交过程中发生错误 | +| 40008 | 合规检查记录提交失败 | 合规检查记录提交过程中发生错误 | +| 40009 | 土地流转信息提交失败 | 土地流转信息提交过程中发生错误 | +| 40010 | 农产品质量认证提交失败 | 农产品质量认证提交过程中发生错误 | +| 50001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 50002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/iot_service_api_design.md b/docs/design/api/iot_service_api_design.md new file mode 100644 index 0000000..fb8e207 --- /dev/null +++ b/docs/design/api/iot_service_api_design.md @@ -0,0 +1,812 @@ +# 物联网服务API设计文档 + +## 1. 概述 + +本文档详细描述了物联网服务(iot-service)提供的API接口,包括设备管理、传感器数据采集、设备控制、告警管理等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/iot` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 40001, + "message": "错误描述", + "data": null +} +``` + +## 5. 设备管理接口 + +### 5.1 注册设备 + +**接口地址**: `POST /devices` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| device_id | string | 是 | 设备唯一标识 | +| name | string | 是 | 设备名称 | +| type | string | 是 | 设备类型(传感器/控制器等) | +| model | string | 否 | 设备型号 | +| manufacturer | string | 否 | 制造商 | +| location | string | 否 | 设备位置 | +| description | string | 否 | 描述 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 设备ID | +| user_id | integer | 用户ID | +| device_id | string | 设备唯一标识 | +| name | string | 设备名称 | +| type | string | 设备类型 | +| model | string | 设备型号 | +| manufacturer | string | 制造商 | +| location | string | 设备位置 | +| status | string | 设备状态 | +| last_heartbeat | string | 最后心跳时间 | +| firmware_version | string | 固件版本 | +| description | string | 描述 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "device_id": "SENSOR001", + "name": "温湿度传感器001", + "type": "传感器", + "model": "DHT22", + "manufacturer": "某某电子", + "location": "一号小麦田", + "description": "用于监测农田环境温湿度" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "device_id": "SENSOR001", + "name": "温湿度传感器001", + "type": "传感器", + "model": "DHT22", + "manufacturer": "某某电子", + "location": "一号小麦田", + "status": "ACTIVE", + "last_heartbeat": null, + "firmware_version": null, + "description": "用于监测农田环境温湿度", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.2 获取设备列表 + +**接口地址**: `GET /devices` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| type | string | 否 | 设备类型筛选 | +| status | string | 否 | 设备状态筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 设备列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "user_id": 12345, + "device_id": "SENSOR001", + "name": "温湿度传感器001", + "type": "传感器", + "model": "DHT22", + "manufacturer": "某某电子", + "location": "一号小麦田", + "status": "ACTIVE", + "last_heartbeat": null, + "firmware_version": null, + "description": "用于监测农田环境温湿度", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 5.3 获取设备详情 + +**接口地址**: `GET /devices/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 设备ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 设备ID | +| user_id | integer | 用户ID | +| device_id | string | 设备唯一标识 | +| name | string | 设备名称 | +| type | string | 设备类型 | +| model | string | 设备型号 | +| manufacturer | string | 制造商 | +| location | string | 设备位置 | +| status | string | 设备状态 | +| last_heartbeat | string | 最后心跳时间 | +| firmware_version | string | 固件版本 | +| description | string | 描述 | +| configs | array | 设备配置列表 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "device_id": "SENSOR001", + "name": "温湿度传感器001", + "type": "传感器", + "model": "DHT22", + "manufacturer": "某某电子", + "location": "一号小麦田", + "status": "ACTIVE", + "last_heartbeat": "2024-01-15T10:30:00Z", + "firmware_version": "v1.0.0", + "description": "用于监测农田环境温湿度", + "configs": [ + { + "config_key": "sampling_interval", + "config_value": "300", + "description": "采样间隔(秒)" + } + ], + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.4 更新设备信息 + +**接口地址**: `PUT /devices/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 设备ID | +| name | string | 否 | 设备名称 | +| location | string | 否 | 设备位置 | +| status | string | 否 | 设备状态 | +| description | string | 否 | 描述 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 设备ID | +| user_id | integer | 用户ID | +| device_id | string | 设备唯一标识 | +| name | string | 设备名称 | +| type | string | 设备类型 | +| model | string | 设备型号 | +| manufacturer | string | 制造商 | +| location | string | 设备位置 | +| status | string | 设备状态 | +| last_heartbeat | string | 最后心跳时间 | +| firmware_version | string | 固件版本 | +| description | string | 描述 | +| updated_at | string | 更新时间 | + +**示例请求**: +```json +{ + "name": "温湿度传感器001", + "location": "一号小麦田A区", + "status": "ACTIVE", + "description": "用于监测农田环境温湿度,位置已更新" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "device_id": "SENSOR001", + "name": "温湿度传感器001", + "type": "传感器", + "model": "DHT22", + "manufacturer": "某某电子", + "location": "一号小麦田A区", + "status": "ACTIVE", + "last_heartbeat": "2024-01-15T10:30:00Z", + "firmware_version": "v1.0.0", + "description": "用于监测农田环境温湿度,位置已更新", + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +### 5.5 删除设备 + +**接口地址**: `DELETE /devices/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 设备ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 删除结果信息 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "设备删除成功" + } +} +``` + +## 6. 传感器数据接口 + +### 6.1 上报传感器数据 + +**接口地址**: `POST /sensor-data` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| device_id | string | 是 | 设备ID | +| sensor_type | string | 是 | 传感器类型(温度/湿度/光照等) | +| value | number | 是 | 传感器数值 | +| unit | string | 是 | 单位 | +| timestamp | string | 否 | 数据时间戳(ISO8601格式),默认为当前时间 | +| latitude | number | 否 | 纬度 | +| longitude | number | 否 | 经度 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 数据记录ID | +| device_id | string | 设备ID | +| sensor_type | string | 传感器类型 | +| value | number | 传感器数值 | +| unit | string | 单位 | +| timestamp | string | 数据时间戳 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "device_id": "SENSOR001", + "sensor_type": "温度", + "value": 25.6, + "unit": "℃", + "timestamp": "2024-01-15T10:30:00Z", + "latitude": 39.9042, + "longitude": 116.4074 +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "device_id": "SENSOR001", + "sensor_type": "温度", + "value": 25.6, + "unit": "℃", + "timestamp": "2024-01-15T10:30:00Z", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.2 获取传感器数据列表 + +**接口地址**: `GET /sensor-data` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| device_id | string | 否 | 设备ID筛选 | +| sensor_type | string | 否 | 传感器类型筛选 | +| start_time | string | 否 | 开始时间(ISO8601格式) | +| end_time | string | 否 | 结束时间(ISO8601格式) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 传感器数据列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 2001, + "device_id": "SENSOR001", + "sensor_type": "温度", + "value": 25.6, + "unit": "℃", + "timestamp": "2024-01-15T10:30:00Z", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 6.3 获取传感器数据统计 + +**接口地址**: `GET /sensor-data/statistics` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| device_id | string | 是 | 设备ID | +| sensor_type | string | 是 | 传感器类型 | +| aggregation_type | string | 是 | 聚合类型(HOURLY/DAILY/WEEKLY/MONTHLY) | +| start_time | string | 否 | 开始时间(ISO8601格式) | +| end_time | string | 否 | 结束时间(ISO8601格式) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| device_id | string | 设备ID | +| sensor_type | string | 传感器类型 | +| aggregation_type | string | 聚合类型 | +| data | array | 统计数据列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "device_id": "SENSOR001", + "sensor_type": "温度", + "aggregation_type": "DAILY", + "data": [ + { + "timestamp": "2024-01-15T00:00:00Z", + "min_value": 22.1, + "max_value": 26.8, + "avg_value": 24.5, + "count": 24 + } + ] + } +} +``` + +## 7. 设备控制接口 + +### 7.1 发送控制命令 + +**接口地址**: `POST /commands` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| device_id | string | 是 | 设备ID | +| command | string | 是 | 命令名称 | +| parameters | object | 否 | 命令参数 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 命令ID | +| device_id | string | 设备ID | +| command | string | 命令名称 | +| parameters | object | 命令参数 | +| status | string | 命令状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "device_id": "CTRL001", + "command": "开启灌溉", + "parameters": { + "duration": 300, + "flow_rate": 10 + } +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "device_id": "CTRL001", + "command": "开启灌溉", + "parameters": { + "duration": 300, + "flow_rate": 10 + }, + "status": "PENDING", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 7.2 获取命令执行状态 + +**接口地址**: `GET /commands/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 命令ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 命令ID | +| device_id | string | 设备ID | +| command | string | 命令名称 | +| parameters | object | 命令参数 | +| status | string | 命令状态 | +| result | string | 执行结果 | +| sent_at | string | 发送时间 | +| executed_at | string | 执行时间 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "device_id": "CTRL001", + "command": "开启灌溉", + "parameters": { + "duration": 300, + "flow_rate": 10 + }, + "status": "EXECUTED", + "result": "灌溉系统已开启,将持续300秒", + "sent_at": "2024-01-15T10:30:00Z", + "executed_at": "2024-01-15T10:30:05Z", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:05Z" + } +} +``` + +### 7.3 获取命令历史列表 + +**接口地址**: `GET /commands` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| device_id | string | 否 | 设备ID筛选 | +| command | string | 否 | 命令名称筛选 | +| status | string | 否 | 命令状态筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 命令列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 3001, + "device_id": "CTRL001", + "command": "开启灌溉", + "parameters": { + "duration": 300, + "flow_rate": 10 + }, + "status": "EXECUTED", + "result": "灌溉系统已开启,将持续300秒", + "sent_at": "2024-01-15T10:30:00Z", + "executed_at": "2024-01-15T10:30:05Z", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +## 8. 告警管理接口 + +### 8.1 获取告警列表 + +**接口地址**: `GET /alerts` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| device_id | string | 否 | 设备ID筛选 | +| alert_type | string | 否 | 告警类型筛选 | +| alert_level | string | 否 | 告警级别筛选 | +| resolved | boolean | 否 | 是否已解决筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 告警列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 4001, + "device_id": "SENSOR001", + "alert_type": "阈值超限", + "alert_level": "WARNING", + "message": "温度超过阈值35℃", + "value": 36.5, + "threshold": 35.0, + "resolved": false, + "timestamp": "2024-01-15T10:30:00Z", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 8.2 标记告警为已解决 + +**接口地址**: `PUT /alerts/{id}/resolve` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 告警ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 告警ID | +| resolved | boolean | 是否已解决 | +| resolved_at | string | 解决时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 4001, + "resolved": true, + "resolved_at": "2024-01-15T11:00:00Z", + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +## 9. 设备配置接口 + +### 9.1 获取设备配置 + +**接口地址**: `GET /devices/{id}/configs` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 设备ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 配置列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "config_key": "sampling_interval", + "config_value": "300", + "description": "采样间隔(秒)" + } + ] + } +} +``` + +### 9.2 更新设备配置 + +**接口地址**: `PUT /devices/{id}/configs` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 设备ID | +| configs | array | 是 | 配置列表 | + +**configs元素结构**: + +| 字段名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| config_key | string | 是 | 配置键 | +| config_value | string | 是 | 配置值 | +| description | string | 否 | 配置描述 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 更新结果信息 | + +**示例请求**: +```json +{ + "configs": [ + { + "config_key": "sampling_interval", + "config_value": "600", + "description": "采样间隔(秒)" + } + ] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "设备配置更新成功" + } +} +``` + +## 10. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 40001 | 参数错误 | 请求参数不合法 | +| 40002 | 设备不存在 | 指定的设备不存在 | +| 40003 | 设备状态不允许此操作 | 当前设备状态不允许执行该操作 | +| 40004 | 传感器数据记录不存在 | 指定的传感器数据记录不存在 | +| 40005 | 设备命令不存在 | 指定的设备命令不存在 | +| 40006 | 命令状态不允许此操作 | 当前命令状态不允许执行该操作 | +| 40007 | 告警记录不存在 | 指定的告警记录不存在 | +| 50001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 50002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/mall_service_api_design.md b/docs/design/api/mall_service_api_design.md new file mode 100644 index 0000000..16cdd80 --- /dev/null +++ b/docs/design/api/mall_service_api_design.md @@ -0,0 +1,1233 @@ +# 商城服务API设计文档 + +## 1. 概述 + +本文档详细描述了商城服务(mall-service)提供的API接口,包括商品管理、购物车、订单、优惠券等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/mall` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 40001, + "message": "错误描述", + "data": null +} +``` + +## 5. 商品管理接口 + +### 5.1 获取商品分类列表 + +**接口地址**: `GET /categories` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| parent_id | integer | 否 | 父分类ID,0表示获取顶级分类 | +| status | string | 否 | 状态(ACTIVE/INACTIVE) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 分类列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "id": 1, + "name": "农资", + "parent_id": 0, + "level": 1, + "sort_order": 1, + "icon": "https://example.com/icon1.png", + "description": "农资产品分类", + "status": "ACTIVE", + "created_at": "2024-01-01T00:00:00Z" + } + ] + } +} +``` + +### 5.2 获取商品列表 + +**接口地址**: `GET /products` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| category_id | integer | 否 | 分类ID | +| keyword | string | 否 | 搜索关键词 | +| is_featured | boolean | 否 | 是否推荐 | +| is_new | boolean | 否 | 是否新品 | +| status | string | 否 | 商品状态(ACTIVE等) | +| sort_by | string | 否 | 排序字段(price_asc/price_desc/sales_count) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 商品列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 100, + "page": 1, + "size": 10, + "items": [ + { + "id": 1, + "category_id": 1, + "seller_id": 12345, + "name": "优质小麦种子", + "subtitle": "高产抗病小麦品种", + "cover_image": "https://example.com/image1.jpg", + "price": 25.00, + "original_price": 30.00, + "stock_quantity": 1000, + "sales_count": 50, + "status": "ACTIVE", + "is_featured": true, + "is_new": true, + "created_at": "2024-01-01T00:00:00Z" + } + ] + } +} +``` + +### 5.3 获取商品详情 + +**接口地址**: `GET /products/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 商品ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 商品ID | +| category | object | 分类信息 | +| seller | object | 卖家信息 | +| name | string | 商品名称 | +| subtitle | string | 商品副标题 | +| description | string | 商品描述 | +| cover_image | string | 封面图片URL | +| images | array | 商品图片URL列表 | +| price | number | 商品价格 | +| original_price | number | 原价 | +| cost_price | number | 成本价 | +| stock_quantity | integer | 库存数量 | +| sales_count | integer | 销售数量 | +| status | string | 商品状态 | +| is_featured | boolean | 是否推荐 | +| is_new | boolean | 是否新品 | +| tags | array | 商品标签 | +| attributes | object | 商品属性 | +| specifications | object | 商品规格 | +| reviews | array | 商品评价列表 | +| created_at | string | 创建时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1, + "category": { + "id": 1, + "name": "农资" + }, + "seller": { + "id": 12345, + "name": "张三种子店" + }, + "name": "优质小麦种子", + "subtitle": "高产抗病小麦品种", + "description": "详细商品描述...", + "cover_image": "https://example.com/image1.jpg", + "images": [ + "https://example.com/image1.jpg", + "https://example.com/image2.jpg" + ], + "price": 25.00, + "original_price": 30.00, + "cost_price": 20.00, + "stock_quantity": 1000, + "sales_count": 50, + "status": "ACTIVE", + "is_featured": true, + "is_new": true, + "tags": ["高产", "抗病"], + "attributes": { + "品种": "鲁麦2号", + "净含量": "1公斤" + }, + "specifications": { + "包装规格": "1公斤/袋" + }, + "reviews": [ + { + "id": 1, + "user": { + "id": 54321, + "name": "李四" + }, + "rating": 5, + "content": "种子质量很好,发芽率高", + "images": [], + "created_at": "2024-01-10T00:00:00Z" + } + ], + "created_at": "2024-01-01T00:00:00Z" + } +} +``` + +## 6. 购物车接口 + +### 6.1 添加商品到购物车 + +**接口地址**: `POST /cart/items` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_id | integer | 是 | 商品ID | +| quantity | integer | 是 | 商品数量 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 购物车项ID | +| user_id | integer | 用户ID | +| product | object | 商品信息 | +| quantity | integer | 商品数量 | +| selected | boolean | 是否选中 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "product_id": 1, + "quantity": 2 +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "product": { + "id": 1, + "name": "优质小麦种子", + "price": 25.00, + "cover_image": "https://example.com/image1.jpg" + }, + "quantity": 2, + "selected": true, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.2 获取购物车列表 + +**接口地址**: `GET /cart/items` + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 购物车项列表 | +| total_amount | number | 总金额 | +| selected_amount | number | 选中商品总金额 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "id": 1001, + "product": { + "id": 1, + "name": "优质小麦种子", + "price": 25.00, + "cover_image": "https://example.com/image1.jpg" + }, + "quantity": 2, + "selected": true, + "created_at": "2024-01-15T10:30:00Z" + } + ], + "total_amount": 50.00, + "selected_amount": 50.00 + } +} +``` + +### 6.3 更新购物车项 + +**接口地址**: `PUT /cart/items/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 购物车项ID | +| quantity | integer | 否 | 商品数量 | +| selected | boolean | 否 | 是否选中 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 购物车项ID | +| product | object | 商品信息 | +| quantity | integer | 商品数量 | +| selected | boolean | 是否选中 | +| updated_at | string | 更新时间 | + +**示例请求**: +```json +{ + "quantity": 3, + "selected": true +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "product": { + "id": 1, + "name": "优质小麦种子", + "price": 25.00, + "cover_image": "https://example.com/image1.jpg" + }, + "quantity": 3, + "selected": true, + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +### 6.4 删除购物车项 + +**接口地址**: `DELETE /cart/items/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 购物车项ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 删除结果信息 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "购物车项删除成功" + } +} +``` + +## 7. 订单接口 + +### 7.1 创建订单 + +**接口地址**: `POST /orders` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| shipping_address_id | integer | 是 | 收货地址ID | +| coupon_id | integer | 否 | 优惠券ID | +| remark | string | 否 | 订单备注 | +| items | array | 是 | 订单项列表 | + +**items元素结构**: + +| 字段名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_id | integer | 是 | 商品ID | +| quantity | integer | 是 | 商品数量 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 订单ID | +| order_number | string | 订单编号 | +| total_amount | number | 订单总金额 | +| discount_amount | number | 优惠金额 | +| shipping_amount | number | 运费 | +| actual_amount | number | 实际支付金额 | +| status | string | 订单状态 | +| shipping_address | object | 收货地址 | +| items | array | 订单项列表 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "shipping_address_id": 1, + "remark": "请尽快发货", + "items": [ + { + "product_id": 1, + "quantity": 2 + } + ] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "order_number": "ORD202401150001", + "total_amount": 50.00, + "discount_amount": 0.00, + "shipping_amount": 0.00, + "actual_amount": 50.00, + "status": "PENDING_PAYMENT", + "shipping_address": { + "id": 1, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某街道某号" + }, + "items": [ + { + "id": 3001, + "product_id": 1, + "product_name": "优质小麦种子", + "product_image": "https://example.com/image1.jpg", + "quantity": 2, + "price": 25.00, + "total_amount": 50.00 + } + ], + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 7.2 获取订单列表 + +**接口地址**: `GET /orders` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 订单状态 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 订单列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 5, + "page": 1, + "size": 10, + "items": [ + { + "id": 2001, + "order_number": "ORD202401150001", + "total_amount": 50.00, + "actual_amount": 50.00, + "status": "PAID", + "shipping_address": { + "name": "张三", + "phone": "13800138000", + "detail_address": "北京市朝阳区某街道某号" + }, + "items": [ + { + "product_name": "优质小麦种子", + "product_image": "https://example.com/image1.jpg", + "quantity": 2, + "price": 25.00 + } + ], + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 7.3 获取订单详情 + +**接口地址**: `GET /orders/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 订单ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 订单ID | +| order_number | string | 订单编号 | +| user | object | 买家信息 | +| seller | object | 卖家信息 | +| total_amount | number | 订单总金额 | +| discount_amount | number | 优惠金额 | +| shipping_amount | number | 运费 | +| actual_amount | number | 实际支付金额 | +| status | string | 订单状态 | +| payment_method | string | 支付方式 | +| payment_time | string | 支付时间 | +| shipping_address | object | 收货地址 | +| shipping_company | string | 物流公司 | +| shipping_number | string | 物流单号 | +| remark | string | 订单备注 | +| items | array | 订单项列表 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "order_number": "ORD202401150001", + "user": { + "id": 12345, + "name": "张三" + }, + "seller": { + "id": 54321, + "name": "张三种子店" + }, + "total_amount": 50.00, + "discount_amount": 0.00, + "shipping_amount": 0.00, + "actual_amount": 50.00, + "status": "SHIPPED", + "payment_method": "微信支付", + "payment_time": "2024-01-15T11:00:00Z", + "shipping_address": { + "id": 1, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某街道某号" + }, + "shipping_company": "顺丰快递", + "shipping_number": "SF1234567890", + "remark": "请尽快发货", + "items": [ + { + "id": 3001, + "product_id": 1, + "product_name": "优质小麦种子", + "product_image": "https://example.com/image1.jpg", + "quantity": 2, + "price": 25.00, + "total_amount": 50.00 + } + ], + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T14:00:00Z" + } +} +``` + +### 7.4 取消订单 + +**接口地址**: `PUT /orders/{id}/cancel` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 订单ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 订单ID | +| status | string | 更新后的订单状态 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "status": "CANCELLED", + "updated_at": "2024-01-15T12:00:00Z" + } +} +``` + +## 8. 收货地址接口 + +### 8.1 添加收货地址 + +**接口地址**: `POST /addresses` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| name | string | 是 | 收货人姓名 | +| phone | string | 是 | 联系电话 | +| province | string | 是 | 省份 | +| city | string | 是 | 城市 | +| district | string | 是 | 区县 | +| detail_address | string | 是 | 详细地址 | +| is_default | boolean | 否 | 是否默认地址 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 地址ID | +| user_id | integer | 用户ID | +| name | string | 收货人姓名 | +| phone | string | 联系电话 | +| province | string | 省份 | +| city | string | 城市 | +| district | string | 区县 | +| detail_address | string | 详细地址 | +| is_default | boolean | 是否默认地址 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某街道某号", + "is_default": true +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1, + "user_id": 12345, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某街道某号", + "is_default": true, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 8.2 获取收货地址列表 + +**接口地址**: `GET /addresses` + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 地址列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "id": 1, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某街道某号", + "is_default": true, + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 8.3 更新收货地址 + +**接口地址**: `PUT /addresses/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 地址ID | +| name | string | 否 | 收货人姓名 | +| phone | string | 否 | 联系电话 | +| province | string | 否 | 省份 | +| city | string | 否 | 城市 | +| district | string | 否 | 区县 | +| detail_address | string | 否 | 详细地址 | +| is_default | boolean | 否 | 是否默认地址 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 地址ID | +| name | string | 收货人姓名 | +| phone | string | 联系电话 | +| province | string | 省份 | +| city | string | 城市 | +| district | string | 区县 | +| detail_address | string | 详细地址 | +| is_default | boolean | 是否默认地址 | +| updated_at | string | 更新时间 | + +**示例请求**: +```json +{ + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某街道某号", + "is_default": true +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某街道某号", + "is_default": true, + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +### 8.4 删除收货地址 + +**接口地址**: `DELETE /addresses/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 地址ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 删除结果信息 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "收货地址删除成功" + } +} +``` + +## 9. 优惠券接口 + +### 9.1 获取可用优惠券列表 + +**接口地址**: `GET /coupons/available` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| amount | number | 否 | 订单金额,用于筛选满足条件的优惠券 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 优惠券列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "id": 1, + "name": "满100减10元", + "type": "FIXED_AMOUNT", + "value": 10.00, + "min_amount": 100.00, + "max_discount_amount": null, + "start_time": "2024-01-01T00:00:00Z", + "end_time": "2024-12-31T23:59:59Z", + "status": "ACTIVE" + } + ] + } +} +``` + +### 9.2 领取优惠券 + +**接口地址**: `POST /coupons/{id}/claim` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 优惠券ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 用户优惠券ID | +| user_id | integer | 用户ID | +| coupon | object | 优惠券信息 | +| status | string | 状态 | +| received_at | string | 领取时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "coupon": { + "id": 1, + "name": "满100减10元", + "type": "FIXED_AMOUNT", + "value": 10.00, + "min_amount": 100.00 + }, + "status": "AVAILABLE", + "received_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 9.3 获取我的优惠券列表 + +**接口地址**: `GET /coupons/mine` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 状态(AVAILABLE/USED/EXPIRED) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 用户优惠券列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "id": 1001, + "coupon": { + "id": 1, + "name": "满100减10元", + "type": "FIXED_AMOUNT", + "value": 10.00, + "min_amount": 100.00, + "start_time": "2024-01-01T00:00:00Z", + "end_time": "2024-12-31T23:59:59Z" + }, + "status": "AVAILABLE", + "received_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +## 10. 商品评价接口 + +### 10.1 添加商品评价 + +**接口地址**: `POST /reviews` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| order_id | integer | 是 | 订单ID | +| product_id | integer | 是 | 商品ID | +| rating | integer | 是 | 评分(1-5星) | +| content | string | 否 | 评价内容 | +| images | array | 否 | 评价图片URL列表 | +| is_anonymous | boolean | 否 | 是否匿名 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 评价ID | +| user | object | 用户信息 | +| product_id | integer | 商品ID | +| order_id | integer | 订单ID | +| rating | integer | 评分 | +| content | string | 评价内容 | +| images | array | 评价图片URL列表 | +| is_anonymous | boolean | 是否匿名 | +| status | string | 审核状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "order_id": 2001, + "product_id": 1, + "rating": 5, + "content": "种子质量很好,发芽率高", + "images": [], + "is_anonymous": false +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1, + "user": { + "id": 12345, + "name": "张三" + }, + "product_id": 1, + "order_id": 2001, + "rating": 5, + "content": "种子质量很好,发芽率高", + "images": [], + "is_anonymous": false, + "status": "PENDING", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 10.2 获取商品评价列表 + +**接口地址**: `GET /reviews` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_id | integer | 是 | 商品ID | +| rating | integer | 否 | 评分筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 评价列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 10, + "page": 1, + "size": 10, + "items": [ + { + "id": 1, + "user": { + "id": 12345, + "name": "张三" + }, + "rating": 5, + "content": "种子质量很好,发芽率高", + "images": [], + "is_anonymous": false, + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +## 11. 商品收藏接口 + +### 11.1 添加商品收藏 + +**接口地址**: `POST /favorites` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_id | integer | 是 | 商品ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 收藏ID | +| user_id | integer | 用户ID | +| product | object | 商品信息 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "product_id": 1 +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "user_id": 12345, + "product": { + "id": 1, + "name": "优质小麦种子", + "price": 25.00, + "cover_image": "https://example.com/image1.jpg" + }, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 11.2 获取商品收藏列表 + +**接口地址**: `GET /favorites` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 收藏列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 5, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "product": { + "id": 1, + "name": "优质小麦种子", + "price": 25.00, + "cover_image": "https://example.com/image1.jpg" + }, + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 11.3 删除商品收藏 + +**接口地址**: `DELETE /favorites/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 收藏ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 删除结果信息 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "商品收藏删除成功" + } +} +``` + +## 12. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 40001 | 参数错误 | 请求参数不合法 | +| 40002 | 商品不存在 | 指定的商品不存在 | +| 40003 | 商品已下架 | 商品已下架,无法购买 | +| 40004 | 库存不足 | 商品库存不足 | +| 40005 | 购物车项不存在 | 指定的购物车项不存在 | +| 40006 | 订单不存在 | 指定的订单不存在 | +| 40007 | 订单状态不允许此操作 | 当前订单状态不允许执行该操作 | +| 40008 | 收货地址不存在 | 指定的收货地址不存在 | +| 40009 | 优惠券不存在 | 指定的优惠券不存在 | +| 40010 | 优惠券不可用 | 优惠券不满足使用条件或已过期 | +| 40011 | 已领取过该优惠券 | 不能重复领取同一张优惠券 | +| 40012 | 商品评价已存在 | 该订单商品已评价 | +| 40013 | 商品收藏已存在 | 该商品已在收藏夹中 | +| 40014 | 商品收藏不存在 | 指定的商品收藏不存在 | +| 50001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 50002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/trade_service_api_design.md b/docs/design/api/trade_service_api_design.md new file mode 100644 index 0000000..de65a43 --- /dev/null +++ b/docs/design/api/trade_service_api_design.md @@ -0,0 +1,501 @@ +# 交易服务API设计文档 + +## 1. 概述 + +本文档详细描述了交易服务(trade-service)提供的API接口,包括商品管理、订单处理、支付和物流等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/trade` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 10001, + "message": "错误描述", + "data": null +} +``` + +## 5. 商品管理接口 + +### 5.1 发布商品 + +**接口地址**: `POST /products` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| title | string | 是 | 商品标题 | +| description | string | 否 | 商品描述 | +| category | string | 是 | 商品分类 | +| price | number | 是 | 商品价格 | +| quantity | integer | 是 | 商品数量 | +| images | array | 否 | 商品图片URL列表 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 商品ID | +| seller_id | integer | 卖家用户ID | +| title | string | 商品标题 | +| description | string | 商品描述 | +| category | string | 商品分类 | +| price | number | 商品价格 | +| quantity | integer | 商品数量 | +| status | string | 商品状态 | +| images | array | 商品图片URL列表 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "title": "优质黄牛", + "description": "3岁健康黄牛,体重500公斤", + "category": "livestock", + "price": 15000.00, + "quantity": 1, + "images": [ + "http://example.com/image1.jpg", + "http://example.com/image2.jpg" + ] +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "seller_id": 12345, + "title": "优质黄牛", + "description": "3岁健康黄牛,体重500公斤", + "category": "livestock", + "price": 15000.00, + "quantity": 1, + "status": "PENDING", + "images": [ + "http://example.com/image1.jpg", + "http://example.com/image2.jpg" + ], + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.2 查询商品列表 + +**接口地址**: `GET /products` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| category | string | 否 | 商品分类 | +| status | string | 否 | 商品状态 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 商品列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 100, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "seller_id": 12345, + "title": "优质黄牛", + "description": "3岁健康黄牛,体重500公斤", + "category": "livestock", + "price": 15000.00, + "quantity": 1, + "status": "APPROVED", + "images": [ + "http://example.com/image1.jpg" + ], + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 5.3 查询商品详情 + +**接口地址**: `GET /products/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 商品ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 商品ID | +| seller_id | integer | 卖家用户ID | +| title | string | 商品标题 | +| description | string | 商品描述 | +| category | string | 商品分类 | +| price | number | 商品价格 | +| quantity | integer | 商品数量 | +| status | string | 商品状态 | +| images | array | 商品图片URL列表 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "seller_id": 12345, + "title": "优质黄牛", + "description": "3岁健康黄牛,体重500公斤", + "category": "livestock", + "price": 15000.00, + "quantity": 1, + "status": "APPROVED", + "images": [ + "http://example.com/image1.jpg", + "http://example.com/image2.jpg" + ], + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +## 6. 订单管理接口 + +### 6.1 创建订单 + +**接口地址**: `POST /orders` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| product_id | integer | 是 | 商品ID | +| quantity | integer | 是 | 购买数量 | +| shipping_address | string | 是 | 收货地址 | +| contact_phone | string | 是 | 联系电话 | +| remark | string | 否 | 买家备注 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 订单ID | +| order_no | string | 订单编号 | +| buyer_id | integer | 买家用户ID | +| seller_id | integer | 卖家用户ID | +| product_id | integer | 商品ID | +| quantity | integer | 购买数量 | +| unit_price | number | 单价 | +| total_amount | number | 总金额 | +| status | string | 订单状态 | +| shipping_address | string | 收货地址 | +| contact_phone | string | 联系电话 | +| remark | string | 买家备注 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "product_id": 1001, + "quantity": 1, + "shipping_address": "北京市朝阳区xxx街道", + "contact_phone": "13800138000", + "remark": "请尽快发货" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "order_no": "ORD20240115103000001", + "buyer_id": 54321, + "seller_id": 12345, + "product_id": 1001, + "quantity": 1, + "unit_price": 15000.00, + "total_amount": 15000.00, + "status": "CREATED", + "shipping_address": "北京市朝阳区xxx街道", + "contact_phone": "13800138000", + "remark": "请尽快发货", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.2 查询订单列表 + +**接口地址**: `GET /orders` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | string | 否 | 订单状态 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 订单列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 50, + "page": 1, + "size": 10, + "items": [ + { + "id": 2001, + "order_no": "ORD20240115103000001", + "buyer_id": 54321, + "seller_id": 12345, + "product_id": 1001, + "quantity": 1, + "unit_price": 15000.00, + "total_amount": 15000.00, + "status": "PAID", + "shipping_address": "北京市朝阳区xxx街道", + "contact_phone": "13800138000", + "remark": "请尽快发货", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 6.3 查询订单详情 + +**接口地址**: `GET /orders/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 订单ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 订单ID | +| order_no | string | 订单编号 | +| buyer_id | integer | 买家用户ID | +| seller_id | integer | 卖家用户ID | +| product | object | 商品信息 | +| quantity | integer | 购买数量 | +| unit_price | number | 单价 | +| total_amount | number | 总金额 | +| status | string | 订单状态 | +| shipping_address | string | 收货地址 | +| contact_phone | string | 联系电话 | +| remark | string | 买家备注 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "order_no": "ORD20240115103000001", + "buyer_id": 54321, + "seller_id": 12345, + "product": { + "id": 1001, + "title": "优质黄牛", + "price": 15000.00, + "images": [ + "http://example.com/image1.jpg" + ] + }, + "quantity": 1, + "unit_price": 15000.00, + "total_amount": 15000.00, + "status": "PAID", + "shipping_address": "北京市朝阳区xxx街道", + "contact_phone": "13800138000", + "remark": "请尽快发货", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +## 7. 支付接口 + +### 7.1 发起支付 + +**接口地址**: `POST /payments` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| order_id | integer | 是 | 订单ID | +| payment_method | string | 是 | 支付方式(WECHAT/ALIPAY/BANK) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 支付ID | +| order_id | integer | 关联订单ID | +| payment_no | string | 支付流水号 | +| amount | number | 支付金额 | +| payment_method | string | 支付方式 | +| status | string | 支付状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "order_id": 2001, + "payment_method": "WECHAT" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "order_id": 2001, + "payment_no": "PAY20240115103000001", + "amount": 15000.00, + "payment_method": "WECHAT", + "status": "PENDING", + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 7.2 查询支付状态 + +**接口地址**: `GET /payments/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 支付ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 支付ID | +| order_id | integer | 关联订单ID | +| payment_no | string | 支付流水号 | +| amount | number | 支付金额 | +| payment_method | string | 支付方式 | +| status | string | 支付状态 | +| transaction_id | string | 第三方支付平台交易ID | +| paid_at | string | 实际支付时间 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 3001, + "order_id": 2001, + "payment_no": "PAY20240115103000001", + "amount": 15000.00, + "payment_method": "WECHAT", + "status": "SUCCESS", + "transaction_id": "wx1234567890", + "paid_at": "2024-01-15T11:00:00Z", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +## 8. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 10001 | 参数错误 | 请求参数不合法 | +| 10002 | 商品不存在 | 指定的商品不存在 | +| 10003 | 订单不存在 | 指定的订单不存在 | +| 10004 | 支付记录不存在 | 指定的支付记录不存在 | +| 10005 | 库存不足 | 商品库存不足 | +| 10006 | 订单状态错误 | 订单状态不正确,无法执行当前操作 | +| 10007 | 支付失败 | 支付处理失败 | +| 20001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 20002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/api/user_center_service_api_design.md b/docs/design/api/user_center_service_api_design.md new file mode 100644 index 0000000..d511ad7 --- /dev/null +++ b/docs/design/api/user_center_service_api_design.md @@ -0,0 +1,1162 @@ +# 用户中心服务API设计文档 + +## 1. 概述 + +本文档详细描述了用户中心服务(user-center-service)提供的API接口,包括用户管理、角色权限、地址管理、积分管理、等级管理、消息通知、反馈等核心功能。 + +## 2. 基础信息 + +- 基础路径: `/api/v1/users` +- 版本: v1 +- 通信协议: HTTP/HTTPS +- 数据格式: JSON +- 状态码: 遵循HTTP状态码规范 + +## 3. 全局Headers + +| Header名称 | 是否必填 | 描述 | +|------------|----------|------| +| Authorization | 是 | Bearer Token认证信息 | +| Content-Type | 是 | application/json | + +## 4. 全局响应格式 + +### 4.1 成功响应 +```json +{ + "code": 0, + "message": "success", + "data": {} +} +``` + +### 4.2 错误响应 +```json +{ + "code": 40001, + "message": "错误描述", + "data": null +} +``` + +## 5. 用户管理接口 + +### 5.1 用户注册 + +**接口地址**: `POST /register` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| username | string | 是 | 用户名 | +| email | string | 是 | 邮箱 | +| password | string | 是 | 密码 | +| phone | string | 否 | 手机号 | +| nickname | string | 否 | 昵称 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 用户ID | +| username | string | 用户名 | +| email | string | 邮箱 | +| phone | string | 手机号 | +| nickname | string | 昵称 | +| avatar_url | string | 头像URL | +| gender | integer | 性别 | +| birthday | string | 生日 | +| real_name | string | 真实姓名 | +| status | integer | 状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "username": "testuser", + "email": "test@example.com", + "password": "password123", + "phone": "13800138000", + "nickname": "测试用户" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "username": "testuser", + "email": "test@example.com", + "phone": "13800138000", + "nickname": "测试用户", + "avatar_url": null, + "gender": 0, + "birthday": null, + "real_name": null, + "status": 1, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 5.2 用户登录 + +**接口地址**: `POST /login` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| username | string | 是 | 用户名或邮箱 | +| password | string | 是 | 密码 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| user | object | 用户信息 | +| token | string | 访问令牌 | +| refresh_token | string | 刷新令牌 | + +**示例请求**: +```json +{ + "username": "testuser", + "password": "password123" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "user": { + "id": 1001, + "username": "testuser", + "email": "test@example.com", + "phone": "13800138000", + "nickname": "测试用户", + "avatar_url": null, + "gender": 0, + "birthday": null, + "real_name": null, + "status": 1, + "last_login_at": "2024-01-15T10:30:00Z", + "created_at": "2024-01-15T10:30:00Z" + }, + "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", + "refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." + } +} +``` + +### 5.3 获取当前用户信息 + +**接口地址**: `GET /me` + +**请求参数**: 无 + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 用户ID | +| username | string | 用户名 | +| email | string | 邮箱 | +| phone | string | 手机号 | +| nickname | string | 昵称 | +| avatar_url | string | 头像URL | +| gender | integer | 性别 | +| birthday | string | 生日 | +| real_name | string | 真实姓名 | +| id_card_number | string | 身份证号 | +| status | integer | 状态 | +| last_login_at | string | 最后登录时间 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | +| roles | array | 用户角色列表 | +| permissions | array | 用户权限列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "username": "testuser", + "email": "test@example.com", + "phone": "13800138000", + "nickname": "测试用户", + "avatar_url": null, + "gender": 0, + "birthday": null, + "real_name": null, + "id_card_number": null, + "status": 1, + "last_login_at": "2024-01-15T10:30:00Z", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z", + "roles": [ + { + "id": 1, + "name": "普通用户", + "description": "普通注册用户" + } + ], + "permissions": [ + { + "id": 101, + "name": "查看个人信息", + "code": "user:profile:view", + "description": "查看个人基本信息" + } + ] + } +} +``` + +### 5.4 更新用户信息 + +**接口地址**: `PUT /me` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| nickname | string | 否 | 昵称 | +| avatar_url | string | 否 | 头像URL | +| gender | integer | 否 | 性别(0-未知,1-男,2-女) | +| birthday | string | 否 | 生日(YYYY-MM-DD) | +| real_name | string | 否 | 真实姓名 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 用户ID | +| username | string | 用户名 | +| email | string | 邮箱 | +| phone | string | 手机号 | +| nickname | string | 昵称 | +| avatar_url | string | 头像URL | +| gender | integer | 性别 | +| birthday | string | 生日 | +| real_name | string | 真实姓名 | +| updated_at | string | 更新时间 | + +**示例请求**: +```json +{ + "nickname": "新昵称", + "gender": 1, + "birthday": "1990-01-01", + "real_name": "张三" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "username": "testuser", + "email": "test@example.com", + "phone": "13800138000", + "nickname": "新昵称", + "avatar_url": null, + "gender": 1, + "birthday": "1990-01-01", + "real_name": "张三", + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +### 5.5 修改密码 + +**接口地址**: `PUT /me/password` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| old_password | string | 是 | 旧密码 | +| new_password | string | 是 | 新密码 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 操作结果信息 | + +**示例请求**: +```json +{ + "old_password": "password123", + "new_password": "newpassword456" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "密码修改成功" + } +} +``` + +### 5.6 获取用户列表(管理员) + +**接口地址**: `GET /` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| username | string | 否 | 用户名筛选 | +| email | string | 否 | 邮箱筛选 | +| status | integer | 否 | 状态筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 用户列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 1001, + "username": "testuser", + "email": "test@example.com", + "phone": "13800138000", + "nickname": "测试用户", + "avatar_url": null, + "gender": 0, + "birthday": null, + "real_name": null, + "status": 1, + "last_login_at": "2024-01-15T10:30:00Z", + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 5.7 获取用户详情(管理员) + +**接口地址**: `GET /{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 用户ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 用户ID | +| username | string | 用户名 | +| email | string | 邮箱 | +| phone | string | 手机号 | +| nickname | string | 昵称 | +| avatar_url | string | 头像URL | +| gender | integer | 性别 | +| birthday | string | 生日 | +| real_name | string | 真实姓名 | +| id_card_number | string | 身份证号 | +| status | integer | 状态 | +| last_login_at | string | 最后登录时间 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | +| roles | array | 用户角色列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "username": "testuser", + "email": "test@example.com", + "phone": "13800138000", + "nickname": "测试用户", + "avatar_url": null, + "gender": 0, + "birthday": null, + "real_name": null, + "id_card_number": null, + "status": 1, + "last_login_at": "2024-01-15T10:30:00Z", + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z", + "roles": [ + { + "id": 1, + "name": "普通用户", + "description": "普通注册用户" + } + ] + } +} +``` + +### 5.8 更新用户状态(管理员) + +**接口地址**: `PUT /{id}/status` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 用户ID | +| status | integer | 是 | 状态(1-正常,2-禁用) | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 用户ID | +| status | integer | 状态 | +| updated_at | string | 更新时间 | + +**示例请求**: +```json +{ + "status": 2 +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 1001, + "status": 2, + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +## 6. 地址管理接口 + +### 6.1 创建收货地址 + +**接口地址**: `POST /me/addresses` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| name | string | 是 | 收货人姓名 | +| phone | string | 是 | 收货人电话 | +| province | string | 是 | 省份 | +| city | string | 是 | 城市 | +| district | string | 是 | 区/县 | +| detail_address | string | 是 | 详细地址 | +| is_default | boolean | 否 | 是否默认地址,默认false | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 地址ID | +| user_id | integer | 用户ID | +| name | string | 收货人姓名 | +| phone | string | 收货人电话 | +| province | string | 省份 | +| city | string | 城市 | +| district | string | 区/县 | +| detail_address | string | 详细地址 | +| is_default | boolean | 是否默认地址 | +| status | integer | 状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某某街道某某号", + "is_default": true +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "user_id": 1001, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某某街道某某号", + "is_default": true, + "status": 1, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.2 获取收货地址列表 + +**接口地址**: `GET /me/addresses` + +**请求参数**: 无 + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 地址列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "id": 2001, + "user_id": 1001, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某某街道某某号", + "is_default": true, + "status": 1, + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 6.3 获取收货地址详情 + +**接口地址**: `GET /me/addresses/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 地址ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 地址ID | +| user_id | integer | 用户ID | +| name | string | 收货人姓名 | +| phone | string | 收货人电话 | +| province | string | 省份 | +| city | string | 城市 | +| district | string | 区/县 | +| detail_address | string | 详细地址 | +| is_default | boolean | 是否默认地址 | +| status | integer | 状态 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "user_id": 1001, + "name": "张三", + "phone": "13800138000", + "province": "北京市", + "city": "北京市", + "district": "朝阳区", + "detail_address": "某某街道某某号", + "is_default": true, + "status": 1, + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 6.4 更新收货地址 + +**接口地址**: `PUT /me/addresses/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 地址ID | +| name | string | 否 | 收货人姓名 | +| phone | string | 否 | 收货人电话 | +| province | string | 否 | 省份 | +| city | string | 否 | 城市 | +| district | string | 否 | 区/县 | +| detail_address | string | 否 | 详细地址 | +| is_default | boolean | 否 | 是否默认地址 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 地址ID | +| user_id | integer | 用户ID | +| name | string | 收货人姓名 | +| phone | string | 收货人电话 | +| province | string | 省份 | +| city | string | 城市 | +| district | string | 区/县 | +| detail_address | string | 详细地址 | +| is_default | boolean | 是否默认地址 | +| status | integer | 状态 | +| updated_at | string | 更新时间 | + +**示例请求**: +```json +{ + "name": "李四", + "phone": "13900139000", + "province": "上海市", + "city": "上海市", + "district": "浦东新区", + "detail_address": "某某路某某号", + "is_default": true +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 2001, + "user_id": 1001, + "name": "李四", + "phone": "13900139000", + "province": "上海市", + "city": "上海市", + "district": "浦东新区", + "detail_address": "某某路某某号", + "is_default": true, + "status": 1, + "updated_at": "2024-01-15T11:00:00Z" + } +} +``` + +### 6.5 删除收货地址 + +**接口地址**: `DELETE /me/addresses/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 地址ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 删除结果信息 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "地址删除成功" + } +} +``` + +## 7. 积分管理接口 + +### 7.1 获取用户积分余额 + +**接口地址**: `GET /me/points/balance` + +**请求参数**: 无 + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| user_id | integer | 用户ID | +| points | integer | 积分余额 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "user_id": 1001, + "points": 1500 + } +} +``` + +### 7.2 获取积分记录列表 + +**接口地址**: `GET /me/points/records` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 积分记录列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 2, + "page": 1, + "size": 10, + "items": [ + { + "id": 3001, + "user_id": 1001, + "change_type": 1, + "points": 100, + "balance": 1500, + "description": "签到奖励", + "related_id": null, + "created_at": "2024-01-15T10:00:00Z" + }, + { + "id": 3002, + "user_id": 1001, + "change_type": 2, + "points": 50, + "balance": 1400, + "description": "兑换优惠券", + "related_id": 4001, + "created_at": "2024-01-14T15:30:00Z" + } + ] + } +} +``` + +## 8. 等级管理接口 + +### 8.1 获取用户当前等级 + +**接口地址**: `GET /me/level` + +**请求参数**: 无 + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| user_id | integer | 用户ID | +| level | integer | 等级 | +| level_name | string | 等级名称 | +| min_points | integer | 所需最低积分 | +| discount_rate | number | 折扣率 | +| current_points | integer | 当前积分 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "user_id": 1001, + "level": 3, + "level_name": "银卡会员", + "min_points": 1000, + "discount_rate": 0.95, + "current_points": 1500 + } +} +``` + +### 8.2 获取等级列表 + +**接口地址**: `GET /levels` + +**请求参数**: 无 + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| items | array | 等级列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "items": [ + { + "id": 1, + "level": 1, + "name": "普通会员", + "min_points": 0, + "discount_rate": 1.00, + "description": "注册即成为普通会员" + }, + { + "id": 2, + "level": 2, + "name": "铜卡会员", + "min_points": 500, + "discount_rate": 0.98, + "description": "积分达到500即可升级" + }, + { + "id": 3, + "level": 3, + "name": "银卡会员", + "min_points": 1000, + "discount_rate": 0.95, + "description": "积分达到1000即可升级" + } + ] + } +} +``` + +## 9. 消息通知接口 + +### 9.1 获取消息列表 + +**接口地址**: `GET /me/messages` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| message_type | integer | 否 | 消息类型筛选(1-系统消息,2-通知,3-营销) | +| is_read | boolean | 否 | 是否已读筛选 | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 消息列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 4001, + "user_id": 1001, + "title": "系统维护通知", + "content": "系统将于今晚00:00-02:00进行维护,请提前做好准备。", + "message_type": 1, + "is_read": false, + "created_at": "2024-01-15T09:00:00Z" + } + ] + } +} +``` + +### 9.2 标记消息为已读 + +**接口地址**: `PUT /me/messages/{id}/read` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 消息ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 消息ID | +| is_read | boolean | 是否已读 | +| read_at | string | 阅读时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 4001, + "is_read": true, + "read_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 9.3 删除消息 + +**接口地址**: `DELETE /me/messages/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 消息ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| message | string | 删除结果信息 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "message": "消息删除成功" + } +} +``` + +## 10. 反馈接口 + +### 10.1 提交反馈 + +**接口地址**: `POST /me/feedbacks` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| title | string | 是 | 反馈标题 | +| content | string | 是 | 反馈内容 | +| contact_info | string | 否 | 联系方式 | +| category | string | 否 | 反馈分类 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 反馈ID | +| user_id | integer | 用户ID | +| title | string | 反馈标题 | +| content | string | 反馈内容 | +| contact_info | string | 联系方式 | +| category | string | 反馈分类 | +| status | integer | 状态 | +| created_at | string | 创建时间 | + +**示例请求**: +```json +{ + "title": "功能建议", + "content": "建议增加夜间模式功能", + "contact_info": "test@example.com", + "category": "功能建议" +} +``` + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 5001, + "user_id": 1001, + "title": "功能建议", + "content": "建议增加夜间模式功能", + "contact_info": "test@example.com", + "category": "功能建议", + "status": 1, + "created_at": "2024-01-15T10:30:00Z" + } +} +``` + +### 10.2 获取反馈列表 + +**接口地址**: `GET /me/feedbacks` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| status | integer | 否 | 状态筛选(1-待处理,2-处理中,3-已解决,4-已关闭) | +| page | integer | 否 | 页码,默认1 | +| size | integer | 否 | 每页数量,默认10 | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| total | integer | 总记录数 | +| page | integer | 当前页码 | +| size | integer | 每页数量 | +| items | array | 反馈列表 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "total": 1, + "page": 1, + "size": 10, + "items": [ + { + "id": 5001, + "user_id": 1001, + "title": "功能建议", + "content": "建议增加夜间模式功能", + "contact_info": "test@example.com", + "category": "功能建议", + "status": 1, + "reply_content": null, + "replied_at": null, + "created_at": "2024-01-15T10:30:00Z" + } + ] + } +} +``` + +### 10.3 获取反馈详情 + +**接口地址**: `GET /me/feedbacks/{id}` + +**请求参数**: + +| 参数名 | 类型 | 必填 | 描述 | +|--------|------|------|------| +| id | integer | 是 | 反馈ID | + +**响应数据**: + +| 字段名 | 类型 | 描述 | +|--------|------|------| +| id | integer | 反馈ID | +| user_id | integer | 用户ID | +| title | string | 反馈标题 | +| content | string | 反馈内容 | +| contact_info | string | 联系方式 | +| category | string | 反馈分类 | +| status | integer | 状态 | +| reply_content | string | 回复内容 | +| replied_at | string | 回复时间 | +| created_at | string | 创建时间 | +| updated_at | string | 更新时间 | + +**示例响应**: +```json +{ + "code": 0, + "message": "success", + "data": { + "id": 5001, + "user_id": 1001, + "title": "功能建议", + "content": "建议增加夜间模式功能", + "contact_info": "test@example.com", + "category": "功能建议", + "status": 1, + "reply_content": null, + "replied_at": null, + "created_at": "2024-01-15T10:30:00Z", + "updated_at": "2024-01-15T10:30:00Z" + } +} +``` + +## 11. 错误码定义 + +| 错误码 | 错误信息 | 描述 | +|--------|----------|------| +| 0 | success | 请求成功 | +| 40001 | 参数错误 | 请求参数不合法 | +| 40002 | 用户名已存在 | 用户名已被其他用户使用 | +| 40003 | 邮箱已存在 | 邮箱已被其他用户使用 | +| 40004 | 用户不存在 | 指定的用户不存在 | +| 40005 | 密码错误 | 用户名或密码错误 | +| 40006 | 用户状态异常 | 用户状态不允许此操作 | +| 40007 | 地址不存在 | 指定的地址不存在 | +| 40008 | 积分不足 | 用户积分不足以完成操作 | +| 40009 | 等级条件不满足 | 用户不满足升级条件 | +| 40010 | 消息不存在 | 指定的消息不存在 | +| 40011 | 反馈不存在 | 指定的反馈不存在 | +| 40012 | 反馈状态不允许此操作 | 当前反馈状态不允许执行该操作 | +| 50001 | 权限不足 | 用户权限不足,无法访问该资源 | +| 50002 | 认证失败 | 用户认证失败 | +| 99999 | 系统错误 | 服务器内部错误 | \ No newline at end of file diff --git a/docs/design/database/ai_service_db_design.md b/docs/design/database/ai_service_db_design.md new file mode 100644 index 0000000..297072d --- /dev/null +++ b/docs/design/database/ai_service_db_design.md @@ -0,0 +1,121 @@ +# AI服务数据库设计文档 + +## 1. 数据库环境说明 + +- 数据库名称: xlxumu_ai +- 字符集: utf8mb4 +- 排序规则: utf8mb4_unicode_ci + +## 2. 数据表设计 + +### 2.1 智能问答记录表 (ai_qa_records) + +存储用户与AI的问答记录。 + +```sql +CREATE TABLE `ai_qa_records` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `question` TEXT NOT NULL COMMENT '用户问题', + `answer` TEXT NOT NULL COMMENT 'AI回答', + `model_version` VARCHAR(50) NOT NULL COMMENT '使用的模型版本', + `processing_time` INT NOT NULL COMMENT '处理耗时(毫秒)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='智能问答记录表'; +``` + +### 2.2 图像识别记录表 (image_recognition_records) + +存储图像识别请求和结果。 + +```sql +CREATE TABLE `image_recognition_records` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `image_url` VARCHAR(500) NOT NULL COMMENT '图像URL', + `recognition_type` VARCHAR(50) NOT NULL COMMENT '识别类型(病虫害识别/作物识别等)', + `result` JSON NOT NULL COMMENT '识别结果(JSON格式)', + `confidence` DECIMAL(5,4) NOT NULL COMMENT '置信度', + `processing_time` INT NOT NULL COMMENT '处理耗时(毫秒)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_recognition_type` (`recognition_type`), + KEY `idx_created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='图像识别记录表'; +``` + +### 2.3 数据分析任务表 (analysis_tasks) + +存储数据分析任务信息。 + +```sql +CREATE TABLE `analysis_tasks` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `task_name` VARCHAR(200) NOT NULL COMMENT '任务名称', + `task_type` VARCHAR(50) NOT NULL COMMENT '任务类型(产量预测/价格分析等)', + `input_data` JSON NOT NULL COMMENT '输入数据(JSON格式)', + `result` JSON COMMENT '分析结果(JSON格式)', + `status` VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '任务状态(PENDING/PROCESSING/COMPLETED/FAILED)', + `processing_time` INT COMMENT '处理耗时(毫秒)', + `error_message` TEXT COMMENT '错误信息', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_task_type` (`task_type`), + KEY `idx_status` (`status`), + KEY `idx_created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='数据分析任务表'; +``` + +### 2.4 模型版本表 (model_versions) + +存储AI模型版本信息。 + +```sql +CREATE TABLE `model_versions` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `model_name` VARCHAR(100) NOT NULL COMMENT '模型名称', + `version` VARCHAR(50) NOT NULL COMMENT '版本号', + `description` TEXT COMMENT '版本描述', + `file_path` VARCHAR(500) NOT NULL COMMENT '模型文件路径', + `accuracy` DECIMAL(5,4) COMMENT '模型准确率', + `is_active` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否为当前活跃版本', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_model_version` (`model_name`, `version`), + KEY `idx_model_name` (`model_name`), + KEY `idx_is_active` (`is_active`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='模型版本表'; +``` + +### 2.5 用户反馈表 (user_feedbacks) + +存储用户对AI服务的反馈。 + +```sql +CREATE TABLE `user_feedbacks` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `service_type` VARCHAR(50) NOT NULL COMMENT '服务类型(QA/IMAGE_RECOGNITION/ANALYSIS)', + `record_id` BIGINT UNSIGNED NOT NULL COMMENT '相关记录ID(问答记录ID/识别记录ID等)', + `rating` TINYINT NOT NULL COMMENT '评分(1-5星)', + `feedback` TEXT COMMENT '反馈内容', + `is_helpful` TINYINT(1) NOT NULL COMMENT '是否有帮助', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_service_type` (`service_type`), + KEY `idx_record_id` (`record_id`), + KEY `idx_created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户反馈表'; +``` \ No newline at end of file diff --git a/docs/design/database/data_platform_service_db_design.md b/docs/design/database/data_platform_service_db_design.md new file mode 100644 index 0000000..47855b9 --- /dev/null +++ b/docs/design/database/data_platform_service_db_design.md @@ -0,0 +1,263 @@ +# 数据平台服务数据库设计文档 + +## 1. 概述 + +本文档详细描述了数据平台服务(data-platform-service)的数据库设计,包括数据统计、报表生成、数据分析等核心业务数据表结构。 + +## 2. 数据库环境 + +- 数据库类型:MySQL 8.0 +- 字符集:utf8mb4 +- 排序规则:utf8mb4_unicode_ci +- 数据库名:xlxumu_data + +## 3. 表结构设计 + +### 3.1 数据统计表 (data_statistics) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 统计记录ID | +| stat_type | VARCHAR(50) | NOT NULL | 统计类型(USER_COUNT, PRODUCT_COUNT, ORDER_COUNT, REVENUE等) | +| stat_value | DECIMAL(15,2) | NOT NULL | 统计值 | +| stat_date | DATE | NOT NULL | 统计日期 | +| dimension1 | VARCHAR(100) | | 维度1(如地区、品类等) | +| dimension2 | VARCHAR(100) | | 维度2 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_stat_type (stat_type) +- INDEX idx_stat_date (stat_date) +- INDEX idx_dimension1 (dimension1) +- INDEX idx_dimension2 (dimension2) + +### 3.2 报表模板表 (report_templates) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 模板ID | +| name | VARCHAR(100) | NOT NULL | 报表名称 | +| description | TEXT | | 报表描述 | +| template_type | VARCHAR(50) | NOT NULL | 模板类型(DAILY, WEEKLY, MONTHLY, QUARTERLY, YEARLY) | +| data_source | VARCHAR(100) | NOT NULL | 数据源(user_service, trade_service, finance_service等) | +| query_sql | TEXT | NOT NULL | 查询SQL | +| columns_config | JSON | | 列配置信息 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'ACTIVE' | 模板状态(ACTIVE:启用, INACTIVE:停用) | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_template_type (template_type) +- INDEX idx_data_source (data_source) +- INDEX idx_status (status) + +### 3.3 报表生成记录表 (report_generations) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 生成记录ID | +| template_id | BIGINT | NOT NULL | 报表模板ID | +| report_name | VARCHAR(200) | NOT NULL | 报表文件名 | +| report_path | VARCHAR(500) | NOT NULL | 报表文件路径 | +| report_format | VARCHAR(20) | NOT NULL | 报表格式(PDF, EXCEL, CSV) | +| start_date | DATE | | 统计开始日期 | +| end_date | DATE | | 统计结束日期 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'GENERATING' | 生成状态(GENERATING:生成中, SUCCESS:成功, FAILED:失败) | +| generated_at | DATETIME | | 生成完成时间 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_template_id (template_id) +- INDEX idx_report_format (report_format) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.4 数据分析任务表 (analysis_tasks) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 任务ID | +| name | VARCHAR(100) | NOT NULL | 任务名称 | +| description | TEXT | | 任务描述 | +| analysis_type | VARCHAR(50) | NOT NULL | 分析类型(TREND, CORRELATION, CLUSTER等) | +| data_source | VARCHAR(100) | NOT NULL | 数据源 | +| parameters | JSON | | 分析参数 | +| result_data | JSON | | 分析结果数据 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'PENDING' | 任务状态(PENDING:待处理, RUNNING:运行中, SUCCESS:成功, FAILED:失败) | +| started_at | DATETIME | | 开始执行时间 | +| completed_at | DATETIME | | 完成时间 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_analysis_type (analysis_type) +- INDEX idx_data_source (data_source) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.5 数据看板配置表 (dashboard_configs) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 配置ID | +| name | VARCHAR(100) | NOT NULL | 看板名称 | +| description | TEXT | | 看板描述 | +| layout_config | JSON | NOT NULL | 布局配置 | +| widgets_config | JSON | NOT NULL | 组件配置 | +| access_permissions | JSON | | 访问权限配置 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'ACTIVE' | 配置状态(ACTIVE:启用, INACTIVE:停用) | +| created_by | BIGINT | NOT NULL | 创建人用户ID | +| updated_by | BIGINT | | 更新人用户ID | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_created_by (created_by) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +## 4. 表关系说明 + +1. 报表模板与报表生成记录是一对多关系 +2. 数据分析任务独立存在,结果存储在任务记录中 +3. 数据看板配置与用户通过创建人ID关联 + +## 5. 数据初始化 + +### 5.1 统计类型枚举值 +- USER_COUNT: 用户数量统计 +- PRODUCT_COUNT: 商品数量统计 +- ORDER_COUNT: 订单数量统计 +- REVENUE: 收入统计 +- LOAN_COUNT: 贷款申请数量统计 +- INSURANCE_COUNT: 保险投保数量统计 + +### 5.2 报表模板类型枚举值 +- DAILY: 日报 +- WEEKLY: 周报 +- MONTHLY: 月报 +- QUARTERLY: 季报 +- YEARLY: 年报 + +### 5.3 报表生成状态枚举值 +- GENERATING: 生成中 +- SUCCESS: 成功 +- FAILED: 失败 + +### 5.4 分析任务状态枚举值 +- PENDING: 待处理 +- RUNNING: 运行中 +- SUCCESS: 成功 +- FAILED: 失败 + +### 5.5 看板配置状态枚举值 +- ACTIVE: 启用 +- INACTIVE: 停用 + +## 6. SQL脚本 + +```sql +-- 创建数据库 +CREATE DATABASE IF NOT EXISTS xlxumu_data + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +USE xlxumu_data; + +-- 数据统计表 +CREATE TABLE data_statistics ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + stat_type VARCHAR(50) NOT NULL, + stat_value DECIMAL(15,2) NOT NULL, + stat_date DATE NOT NULL, + dimension1 VARCHAR(100), + dimension2 VARCHAR(100), + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_stat_type (stat_type), + INDEX idx_stat_date (stat_date), + INDEX idx_dimension1 (dimension1), + INDEX idx_dimension2 (dimension2) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 报表模板表 +CREATE TABLE report_templates ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL, + description TEXT, + template_type VARCHAR(50) NOT NULL, + data_source VARCHAR(100) NOT NULL, + query_sql TEXT NOT NULL, + columns_config JSON, + status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_template_type (template_type), + INDEX idx_data_source (data_source), + INDEX idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 报表生成记录表 +CREATE TABLE report_generations ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + template_id BIGINT NOT NULL, + report_name VARCHAR(200) NOT NULL, + report_path VARCHAR(500) NOT NULL, + report_format VARCHAR(20) NOT NULL, + start_date DATE, + end_date DATE, + status VARCHAR(20) NOT NULL DEFAULT 'GENERATING', + generated_at DATETIME, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_template_id (template_id), + INDEX idx_report_format (report_format), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 数据分析任务表 +CREATE TABLE analysis_tasks ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL, + description TEXT, + analysis_type VARCHAR(50) NOT NULL, + data_source VARCHAR(100) NOT NULL, + parameters JSON, + result_data JSON, + status VARCHAR(20) NOT NULL DEFAULT 'PENDING', + started_at DATETIME, + completed_at DATETIME, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_analysis_type (analysis_type), + INDEX idx_data_source (data_source), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 数据看板配置表 +CREATE TABLE dashboard_configs ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL, + description TEXT, + layout_config JSON NOT NULL, + widgets_config JSON NOT NULL, + access_permissions JSON, + status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + created_by BIGINT NOT NULL, + updated_by BIGINT, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_created_by (created_by), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +``` \ No newline at end of file diff --git a/docs/design/database/farming_service_db_design.md b/docs/design/database/farming_service_db_design.md new file mode 100644 index 0000000..744f6b9 --- /dev/null +++ b/docs/design/database/farming_service_db_design.md @@ -0,0 +1,157 @@ +# 农业服务数据库设计文档 + +## 1. 数据库环境说明 + +- 数据库名称: xlxumu_farming +- 字符集: utf8mb4 +- 排序规则: utf8mb4_unicode_ci + +## 2. 数据表设计 + +### 2.1 农田信息表 (farmlands) + +存储农田基本信息。 + +```sql +CREATE TABLE `farmlands` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `name` VARCHAR(100) NOT NULL COMMENT '农田名称', + `location` VARCHAR(200) NOT NULL COMMENT '地理位置', + `area` DECIMAL(10,2) NOT NULL COMMENT '面积(亩)', + `crop_type` VARCHAR(50) NOT NULL COMMENT '作物类型', + `planting_date` DATE COMMENT '种植日期', + `status` VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '状态(ACTIVE/INACTIVE)', + `description` TEXT COMMENT '描述', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_crop_type` (`crop_type`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='农田信息表'; +``` + +### 2.2 农事活动记录表 (farming_activities) + +存储农事活动记录。 + +```sql +CREATE TABLE `farming_activities` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `farmland_id` BIGINT UNSIGNED NOT NULL COMMENT '农田ID', + `activity_type` VARCHAR(50) NOT NULL COMMENT '活动类型(播种/施肥/除草/收割等)', + `activity_date` DATE NOT NULL COMMENT '活动日期', + `description` TEXT COMMENT '活动描述', + `cost` DECIMAL(10,2) COMMENT '费用', + `operator` VARCHAR(50) COMMENT '操作人员', + `images` JSON COMMENT '活动图片URL列表', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_farmland_id` (`farmland_id`), + KEY `idx_activity_type` (`activity_type`), + KEY `idx_activity_date` (`activity_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='农事活动记录表'; +``` + +### 2.3 作物生长记录表 (crop_growth_records) + +存储作物生长情况记录。 + +```sql +CREATE TABLE `crop_growth_records` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `farmland_id` BIGINT UNSIGNED NOT NULL COMMENT '农田ID', + `record_date` DATE NOT NULL COMMENT '记录日期', + `growth_stage` VARCHAR(50) NOT NULL COMMENT '生长阶段', + `height` DECIMAL(5,2) COMMENT '株高(cm)', + `leaf_count` INT COMMENT '叶片数', + `health_status` VARCHAR(50) COMMENT '健康状况', + `notes` TEXT COMMENT '备注', + `images` JSON COMMENT '图片URL列表', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_farmland_id` (`farmland_id`), + KEY `idx_record_date` (`record_date`), + KEY `idx_growth_stage` (`growth_stage`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='作物生长记录表'; +``` + +### 2.4 病虫害记录表 (pest_disease_records) + +存储病虫害发生及防治记录。 + +```sql +CREATE TABLE `pest_disease_records` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `farmland_id` BIGINT UNSIGNED NOT NULL COMMENT '农田ID', + `record_date` DATE NOT NULL COMMENT '记录日期', + `type` VARCHAR(20) NOT NULL COMMENT '类型(病害/虫害)', + `name` VARCHAR(100) NOT NULL COMMENT '病虫害名称', + `severity` VARCHAR(20) NOT NULL COMMENT '严重程度(轻/中/重)', + `affected_area` DECIMAL(5,2) COMMENT '受害面积(亩)', + `control_method` TEXT COMMENT '防治方法', + `control_date` DATE COMMENT '防治日期', + `control_result` TEXT COMMENT '防治效果', + `notes` TEXT COMMENT '备注', + `images` JSON COMMENT '图片URL列表', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_farmland_id` (`farmland_id`), + KEY `idx_record_date` (`record_date`), + KEY `idx_type` (`type`), + KEY `idx_name` (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='病虫害记录表'; +``` + +### 2.5 农田环境数据表 (environmental_data) + +存储农田环境监测数据。 + +```sql +CREATE TABLE `environmental_data` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `farmland_id` BIGINT UNSIGNED NOT NULL COMMENT '农田ID', + `record_time` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '记录时间', + `temperature` DECIMAL(5,2) COMMENT '温度(℃)', + `humidity` DECIMAL(5,2) COMMENT '湿度(%)', + `soil_moisture` DECIMAL(5,2) COMMENT '土壤湿度(%)', + `ph_value` DECIMAL(4,2) COMMENT '土壤pH值', + `nitrogen` DECIMAL(8,2) COMMENT '氮含量(mg/kg)', + `phosphorus` DECIMAL(8,2) COMMENT '磷含量(mg/kg)', + `potassium` DECIMAL(8,2) COMMENT '钾含量(mg/kg)', + `notes` TEXT COMMENT '备注', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_farmland_id` (`farmland_id`), + KEY `idx_record_time` (`record_time`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='农田环境数据表'; +``` + +### 2.6 收获记录表 (harvest_records) + +存储农作物收获记录。 + +```sql +CREATE TABLE `harvest_records` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `farmland_id` BIGINT UNSIGNED NOT NULL COMMENT '农田ID', + `harvest_date` DATE NOT NULL COMMENT '收获日期', + `yield` DECIMAL(10,2) NOT NULL COMMENT '产量(公斤)', + `quality` VARCHAR(50) COMMENT '质量等级', + `storage_location` VARCHAR(200) COMMENT '存储位置', + `selling_price` DECIMAL(10,2) COMMENT '销售价格(元/公斤)', + `sold_quantity` DECIMAL(10,2) COMMENT '已售数量(公斤)', + `notes` TEXT COMMENT '备注', + `images` JSON COMMENT '图片URL列表', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_farmland_id` (`farmland_id`), + KEY `idx_harvest_date` (`harvest_date`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收获记录表'; +``` \ No newline at end of file diff --git a/docs/design/database/finance_service_db_design.md b/docs/design/database/finance_service_db_design.md new file mode 100644 index 0000000..09eb686 --- /dev/null +++ b/docs/design/database/finance_service_db_design.md @@ -0,0 +1,321 @@ +# 金融服务数据库设计文档 + +## 1. 概述 + +本文档详细描述了金融服务(finance-service)的数据库设计,包括贷款管理、保险管理、金融产品等核心业务数据表结构。 + +## 2. 数据库环境 + +- 数据库类型:MySQL 8.0 +- 字符集:utf8mb4 +- 排序规则:utf8mb4_unicode_ci +- 数据库名:xlxumu_finance + +## 3. 表结构设计 + +### 3.1 贷款产品表 (loan_products) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 贷款产品ID | +| name | VARCHAR(100) | NOT NULL | 产品名称 | +| description | TEXT | | 产品描述 | +| interest_rate | DECIMAL(5,4) | NOT NULL | 年利率 | +| term_months | INT | NOT NULL | 贷款期限(月) | +| min_amount | DECIMAL(12,2) | NOT NULL | 最小贷款金额 | +| max_amount | DECIMAL(12,2) | NOT NULL | 最大贷款金额 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'ACTIVE' | 产品状态(ACTIVE:启用, INACTIVE:停用) | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.2 贷款申请表 (loan_applications) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 贷款申请ID | +| user_id | BIGINT | NOT NULL | 申请人用户ID | +| product_id | BIGINT | NOT NULL | 贷款产品ID | +| amount | DECIMAL(12,2) | NOT NULL | 申请金额 | +| term_months | INT | NOT NULL | 申请期限(月) | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'SUBMITTED' | 申请状态(SUBMITTED:已提交, APPROVED:已批准, REJECTED:已拒绝, DISBURSED:已放款, SETTLED:已结清, OVERDUE:已逾期) | +| purpose | VARCHAR(200) | | 贷款用途 | +| contact_info | JSON | | 联系信息 | +| credit_score | INT | | 信用评分 | +| approval_time | DATETIME | | 审批时间 | +| disbursement_time | DATETIME | | 放款时间 | +| settlement_time | DATETIME | | 结清时间 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_user_id (user_id) +- INDEX idx_product_id (product_id) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.3 贷款还款计划表 (loan_repayment_schedules) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 还款计划ID | +| loan_id | BIGINT | NOT NULL | 贷款申请ID | +| installment_number | INT | NOT NULL | 期数 | +| due_date | DATE | NOT NULL | 应还日期 | +| principal_amount | DECIMAL(12,2) | NOT NULL | 应还本金 | +| interest_amount | DECIMAL(12,2) | NOT NULL | 应还利息 | +| total_amount | DECIMAL(12,2) | NOT NULL | 应还总额 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'PENDING' | 还款状态(PENDING:待还款, PAID:已还款, OVERDUE:已逾期) | +| paid_date | DATE | | 实际还款日期 | +| paid_amount | DECIMAL(12,2) | | 实际还款金额 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_loan_id (loan_id) +- INDEX idx_due_date (due_date) +- INDEX idx_status (status) +- UNIQUE INDEX uk_loan_installment (loan_id, installment_number) + +### 3.4 保险产品表 (insurance_products) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 保险产品ID | +| name | VARCHAR(100) | NOT NULL | 产品名称 | +| description | TEXT | | 产品描述 | +| premium_rate | DECIMAL(5,4) | NOT NULL | 保险费率 | +| coverage_amount | DECIMAL(12,2) | NOT NULL | 保险金额 | +| term_months | INT | NOT NULL | 保险期限(月) | +| type | VARCHAR(50) | NOT NULL | 保险类型(CATTLE:牲畜保险, PROPERTY:财产保险, LIABILITY:责任保险) | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'ACTIVE' | 产品状态(ACTIVE:启用, INACTIVE:停用) | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_type (type) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.5 保险投保表 (insurance_policies) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 保单ID | +| user_id | BIGINT | NOT NULL | 投保人用户ID | +| product_id | BIGINT | NOT NULL | 保险产品ID | +| policy_no | VARCHAR(50) | UNIQUE, NOT NULL | 保单号 | +| insured_amount | DECIMAL(12,2) | NOT NULL | 投保金额 | +| premium_amount | DECIMAL(12,2) | NOT NULL | 保费金额 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'ACTIVE' | 保单状态(ACTIVE:有效, EXPIRED:已过期, CLAIMED:已理赔, CANCELLED:已取消) | +| start_date | DATE | NOT NULL | 保险起始日期 | +| end_date | DATE | NOT NULL | 保险结束日期 | +| beneficiary_info | JSON | | 受益人信息 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- UNIQUE INDEX uk_policy_no (policy_no) +- INDEX idx_user_id (user_id) +- INDEX idx_product_id (product_id) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.6 理赔申请表 (claims) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 理赔申请ID | +| policy_id | BIGINT | NOT NULL | 关联保单ID | +| claim_no | VARCHAR(50) | UNIQUE, NOT NULL | 理赔编号 | +| claim_amount | DECIMAL(12,2) | NOT NULL | 理赔金额 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'SUBMITTED' | 理赔状态(SUBMITTED:已提交, APPROVED:已批准, REJECTED:已拒绝, SETTLED:已赔付) | +| incident_date | DATE | NOT NULL | 事故日期 | +| incident_description | TEXT | NOT NULL | 事故描述 | +| supporting_documents | JSON | | 支持文件 | +| approval_time | DATETIME | | 审批时间 | +| settlement_time | DATETIME | | 赔付时间 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- UNIQUE INDEX uk_claim_no (claim_no) +- INDEX idx_policy_id (policy_id) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +## 4. 表关系说明 + +1. 贷款产品与贷款申请是一对多关系 +2. 贷款申请与还款计划是一对多关系 +3. 保险产品与保险投保是一对多关系 +4. 保险投保与理赔申请是一对多关系 +5. 用户与贷款申请、保险投保等通过用户ID关联 + +## 5. 数据初始化 + +### 5.1 贷款产品状态枚举值 +- ACTIVE: 启用 +- INACTIVE: 停用 + +### 5.2 贷款申请状态流转 +- SUBMITTED -> APPROVED -> DISBURSED -> SETTLED +- SUBMITTED -> REJECTED +- DISBURSED -> OVERDUE (特殊情况下) + +### 5.3 还款状态枚举值 +- PENDING: 待还款 +- PAID: 已还款 +- OVERDUE: 已逾期 + +### 5.4 保险产品状态枚举值 +- ACTIVE: 启用 +- INACTIVE: 停用 + +### 5.5 保单状态枚举值 +- ACTIVE: 有效 +- EXPIRED: 已过期 +- CLAIMED: 已理赔 +- CANCELLED: 已取消 + +### 5.6 理赔状态枚举值 +- SUBMITTED: 已提交 +- APPROVED: 已批准 +- REJECTED: 已拒绝 +- SETTLED: 已赔付 + +## 6. SQL脚本 + +```sql +-- 创建数据库 +CREATE DATABASE IF NOT EXISTS xlxumu_finance + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +USE xlxumu_finance; + +-- 贷款产品表 +CREATE TABLE loan_products ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL, + description TEXT, + interest_rate DECIMAL(5,4) NOT NULL, + term_months INT NOT NULL, + min_amount DECIMAL(12,2) NOT NULL, + max_amount DECIMAL(12,2) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 贷款申请表 +CREATE TABLE loan_applications ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + user_id BIGINT NOT NULL, + product_id BIGINT NOT NULL, + amount DECIMAL(12,2) NOT NULL, + term_months INT NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'SUBMITTED', + purpose VARCHAR(200), + contact_info JSON, + credit_score INT, + approval_time DATETIME, + disbursement_time DATETIME, + settlement_time DATETIME, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_user_id (user_id), + INDEX idx_product_id (product_id), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 贷款还款计划表 +CREATE TABLE loan_repayment_schedules ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + loan_id BIGINT NOT NULL, + installment_number INT NOT NULL, + due_date DATE NOT NULL, + principal_amount DECIMAL(12,2) NOT NULL, + interest_amount DECIMAL(12,2) NOT NULL, + total_amount DECIMAL(12,2) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'PENDING', + paid_date DATE, + paid_amount DECIMAL(12,2), + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_loan_id (loan_id), + INDEX idx_due_date (due_date), + INDEX idx_status (status), + UNIQUE INDEX uk_loan_installment (loan_id, installment_number) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 保险产品表 +CREATE TABLE insurance_products ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL, + description TEXT, + premium_rate DECIMAL(5,4) NOT NULL, + coverage_amount DECIMAL(12,2) NOT NULL, + term_months INT NOT NULL, + type VARCHAR(50) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_type (type), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 保险投保表 +CREATE TABLE insurance_policies ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + user_id BIGINT NOT NULL, + product_id BIGINT NOT NULL, + policy_no VARCHAR(50) UNIQUE NOT NULL, + insured_amount DECIMAL(12,2) NOT NULL, + premium_amount DECIMAL(12,2) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', + start_date DATE NOT NULL, + end_date DATE NOT NULL, + beneficiary_info JSON, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE INDEX uk_policy_no (policy_no), + INDEX idx_user_id (user_id), + INDEX idx_product_id (product_id), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 理赔申请表 +CREATE TABLE claims ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + policy_id BIGINT NOT NULL, + claim_no VARCHAR(50) UNIQUE NOT NULL, + claim_amount DECIMAL(12,2) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'SUBMITTED', + incident_date DATE NOT NULL, + incident_description TEXT NOT NULL, + supporting_documents JSON, + approval_time DATETIME, + settlement_time DATETIME, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE INDEX uk_claim_no (claim_no), + INDEX idx_policy_id (policy_id), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +``` \ No newline at end of file diff --git a/docs/design/database/government_service_db_design.md b/docs/design/database/government_service_db_design.md new file mode 100644 index 0000000..3a74716 --- /dev/null +++ b/docs/design/database/government_service_db_design.md @@ -0,0 +1,193 @@ +# 政府服务数据库设计文档 + +## 1. 数据库环境说明 + +- 数据库名称: xlxumu_government +- 字符集: utf8mb4 +- 排序规则: utf8mb4_unicode_ci + +## 2. 政策法规表(government_policies) + +存储政府发布的政策法规信息。 + +```sql +CREATE TABLE government_policies ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + title VARCHAR(255) NOT NULL COMMENT '政策标题', + content TEXT NOT NULL COMMENT '政策内容', + category VARCHAR(100) NOT NULL COMMENT '政策分类(农业扶持/小微企业/科技创新等)', + publish_date DATE NOT NULL COMMENT '发布日期', + effective_date DATE COMMENT '生效日期', + expiry_date DATE COMMENT '失效日期', + issuing_authority VARCHAR(255) NOT NULL COMMENT '发布机构', + policy_number VARCHAR(100) UNIQUE COMMENT '政策文号', + status ENUM('DRAFT', 'PUBLISHED', 'EXPIRED') NOT NULL DEFAULT 'DRAFT' COMMENT '状态', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_category (category), + INDEX idx_publish_date (publish_date), + INDEX idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='政策法规表'; +``` + +## 3. 补贴申请表(subsidy_applications) + +存储农户或企业提交的政府补贴申请信息。 + +```sql +CREATE TABLE subsidy_applications ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + applicant_id BIGINT UNSIGNED NOT NULL COMMENT '申请人ID(关联user_center_service的用户ID)', + applicant_type ENUM('FARMER', 'COMPANY') NOT NULL COMMENT '申请人类型', + policy_id BIGINT UNSIGNED NOT NULL COMMENT '关联政策ID', + application_number VARCHAR(50) UNIQUE NOT NULL COMMENT '申请编号', + project_name VARCHAR(255) NOT NULL COMMENT '项目名称', + project_description TEXT NOT NULL COMMENT '项目描述', + applied_amount DECIMAL(15,2) NOT NULL COMMENT '申请金额', + actual_amount DECIMAL(15,2) COMMENT '实际发放金额', + application_date DATE NOT NULL COMMENT '申请日期', + status ENUM('SUBMITTED', 'REVIEWING', 'APPROVED', 'REJECTED', 'DISBURSED') NOT NULL DEFAULT 'SUBMITTED' COMMENT '申请状态', + reviewer_id BIGINT UNSIGNED COMMENT '审核人ID', + review_notes TEXT COMMENT '审核备注', + review_date TIMESTAMP NULL COMMENT '审核日期', + disbursement_date DATE COMMENT '发放日期', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_applicant_id (applicant_id), + INDEX idx_policy_id (policy_id), + INDEX idx_status (status), + INDEX idx_application_date (application_date) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='补贴申请表'; +``` + +## 4. 补贴发放记录表(subsidy_disbursements) + +记录补贴发放的具体信息。 + +```sql +CREATE TABLE subsidy_disbursements ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + application_id BIGINT UNSIGNED NOT NULL COMMENT '关联申请ID', + disbursement_amount DECIMAL(15,2) NOT NULL COMMENT '发放金额', + disbursement_date DATE NOT NULL COMMENT '发放日期', + payment_method ENUM('BANK_TRANSFER', 'CASH', 'OTHER') NOT NULL COMMENT '发放方式', + payment_reference VARCHAR(255) COMMENT '支付凭证号', + recipient_account VARCHAR(255) COMMENT '收款账户', + status ENUM('PENDING', 'SUCCESS', 'FAILED') NOT NULL DEFAULT 'PENDING' COMMENT '发放状态', + failure_reason TEXT COMMENT '失败原因', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_application_id (application_id), + INDEX idx_disbursement_date (disbursement_date), + INDEX idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='补贴发放记录表'; +``` + +## 5. 农业补贴标准表(agricultural_subsidy_standards) + +存储各类农业补贴的发放标准。 + +```sql +CREATE TABLE agricultural_subsidy_standards ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + policy_id BIGINT UNSIGNED NOT NULL COMMENT '关联政策ID', + crop_type VARCHAR(100) NOT NULL COMMENT '作物类型', + subsidy_type ENUM('PER_AREA', 'PER_UNIT', 'FIXED_AMOUNT') NOT NULL COMMENT '补贴方式', + subsidy_amount DECIMAL(10,2) NOT NULL COMMENT '补贴金额(元/亩或元/单位)', + unit VARCHAR(50) COMMENT '单位(亩/头/只等)', + effective_date DATE NOT NULL COMMENT '生效日期', + expiry_date DATE COMMENT '失效日期', + description TEXT COMMENT '标准描述', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_policy_id (policy_id), + INDEX idx_crop_type (crop_type), + INDEX idx_effective_date (effective_date) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='农业补贴标准表'; +``` + +## 6. 合规检查记录表(compliance_inspection_records) + +记录对农户或企业进行的合规检查信息。 + +```sql +CREATE TABLE compliance_inspection_records ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + inspected_entity_id BIGINT UNSIGNED NOT NULL COMMENT '被检查实体ID(关联user_center_service的用户ID)', + entity_type ENUM('FARMER', 'COMPANY') NOT NULL COMMENT '实体类型', + inspector_id BIGINT UNSIGNED NOT NULL COMMENT '检查员ID', + inspection_date DATE NOT NULL COMMENT '检查日期', + inspection_type VARCHAR(100) NOT NULL COMMENT '检查类型(环保检查/质量检查/安全检查等)', + inspection_result ENUM('PASS', 'FAIL', 'PENDING') NOT NULL DEFAULT 'PENDING' COMMENT '检查结果', + findings TEXT COMMENT '检查发现', + corrective_actions TEXT COMMENT '整改措施', + follow_up_date DATE COMMENT '跟进日期', + status ENUM('COMPLETED', 'FOLLOW_UP_REQUIRED', 'CLOSED') NOT NULL DEFAULT 'COMPLETED' COMMENT '状态', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_entity_id (inspected_entity_id), + INDEX idx_inspector_id (inspector_id), + INDEX idx_inspection_date (inspection_date), + INDEX idx_result (inspection_result) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='合规检查记录表'; +``` + +## 7. 土地流转信息表(land_transfer_info) + +记录农村土地流转的相关信息。 + +```sql +CREATE TABLE land_transfer_info ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + land_owner_id BIGINT UNSIGNED NOT NULL COMMENT '土地所有者ID(关联user_center_service的用户ID)', + transferee_id BIGINT UNSIGNED NOT NULL COMMENT '受让方ID(关联user_center_service的用户ID)', + land_location VARCHAR(255) NOT NULL COMMENT '土地位置', + land_area DECIMAL(10,2) NOT NULL COMMENT '土地面积(亩)', + transfer_type ENUM('LEASE', 'SALE', 'CONTRACT') NOT NULL COMMENT '流转类型', + transfer_term INT NOT NULL COMMENT '流转期限(年)', + annual_rent DECIMAL(10,2) COMMENT '年租金(元/亩)', + total_amount DECIMAL(15,2) COMMENT '总金额', + start_date DATE NOT NULL COMMENT '开始日期', + end_date DATE NOT NULL COMMENT '结束日期', + contract_number VARCHAR(100) UNIQUE COMMENT '合同编号', + status ENUM('ACTIVE', 'EXPIRED', 'TERMINATED') NOT NULL DEFAULT 'ACTIVE' COMMENT '状态', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_land_owner_id (land_owner_id), + INDEX idx_transferee_id (transferee_id), + INDEX idx_status (status), + INDEX idx_start_date (start_date) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='土地流转信息表'; +``` + +## 8. 农产品质量认证表(agricultural_product_certifications) + +记录农产品的质量认证信息。 + +```sql +CREATE TABLE agricultural_product_certifications ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + producer_id BIGINT UNSIGNED NOT NULL COMMENT '生产者ID(关联user_center_service的用户ID)', + product_name VARCHAR(255) NOT NULL COMMENT '产品名称', + certification_type VARCHAR(100) NOT NULL COMMENT '认证类型(绿色食品/有机产品/地理标志等)', + certification_number VARCHAR(100) UNIQUE COMMENT '认证编号', + issuing_authority VARCHAR(255) NOT NULL COMMENT '发证机构', + issue_date DATE NOT NULL COMMENT '发证日期', + expiry_date DATE NOT NULL COMMENT '有效期至', + certification_status ENUM('VALID', 'EXPIRED', 'REVOKED') NOT NULL DEFAULT 'VALID' COMMENT '认证状态', + inspection_report TEXT COMMENT '检验报告', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_producer_id (producer_id), + INDEX idx_certification_type (certification_type), + INDEX idx_expiry_date (expiry_date), + INDEX idx_status (certification_status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='农产品质量认证表'; +``` \ No newline at end of file diff --git a/docs/design/database/iot_service_db_design.md b/docs/design/database/iot_service_db_design.md new file mode 100644 index 0000000..62c093f --- /dev/null +++ b/docs/design/database/iot_service_db_design.md @@ -0,0 +1,159 @@ +# 物联网服务数据库设计文档 + +## 1. 数据库环境说明 + +- 数据库名称: xlxumu_iot +- 字符集: utf8mb4 +- 排序规则: utf8mb4_unicode_ci + +## 2. 数据表设计 + +### 2.1 设备信息表 (devices) + +存储物联网设备基本信息。 + +```sql +CREATE TABLE `devices` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `device_id` VARCHAR(100) NOT NULL COMMENT '设备唯一标识', + `name` VARCHAR(100) NOT NULL COMMENT '设备名称', + `type` VARCHAR(50) NOT NULL COMMENT '设备类型(传感器/控制器等)', + `model` VARCHAR(100) COMMENT '设备型号', + `manufacturer` VARCHAR(100) COMMENT '制造商', + `location` VARCHAR(200) COMMENT '设备位置', + `status` VARCHAR(20) NOT NULL DEFAULT 'ACTIVE' COMMENT '设备状态(ACTIVE/INACTIVE/FAULT)', + `last_heartbeat` TIMESTAMP NULL COMMENT '最后心跳时间', + `firmware_version` VARCHAR(50) COMMENT '固件版本', + `description` TEXT COMMENT '描述', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_device_id` (`device_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_type` (`type`), + KEY `idx_status` (`status`), + KEY `idx_last_heartbeat` (`last_heartbeat`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备信息表'; +``` + +### 2.2 传感器数据表 (sensor_data) + +存储传感器采集的数据。 + +```sql +CREATE TABLE `sensor_data` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `device_id` VARCHAR(100) NOT NULL COMMENT '设备ID', + `sensor_type` VARCHAR(50) NOT NULL COMMENT '传感器类型(温度/湿度/光照等)', + `value` DECIMAL(10,4) NOT NULL COMMENT '传感器数值', + `unit` VARCHAR(20) NOT NULL COMMENT '单位', + `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '数据时间戳', + `location` POINT COMMENT '地理位置', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_sensor_type` (`sensor_type`), + KEY `idx_timestamp` (`timestamp`), + SPATIAL KEY `idx_location` (`location`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='传感器数据表'; +``` + +### 2.3 设备告警表 (device_alerts) + +存储设备告警信息。 + +```sql +CREATE TABLE `device_alerts` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `device_id` VARCHAR(100) NOT NULL COMMENT '设备ID', + `alert_type` VARCHAR(50) NOT NULL COMMENT '告警类型(故障/阈值超限等)', + `alert_level` VARCHAR(20) NOT NULL COMMENT '告警级别(INFO/WARNING/ERROR/CRITICAL)', + `message` TEXT NOT NULL COMMENT '告警信息', + `value` DECIMAL(10,4) COMMENT '触发告警的数值', + `threshold` DECIMAL(10,4) COMMENT '告警阈值', + `resolved` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否已解决', + `resolved_at` TIMESTAMP NULL COMMENT '解决时间', + `resolved_by` BIGINT UNSIGNED COMMENT '解决人ID', + `timestamp` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '告警时间', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_alert_type` (`alert_type`), + KEY `idx_alert_level` (`alert_level`), + KEY `idx_resolved` (`resolved`), + KEY `idx_timestamp` (`timestamp`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备告警表'; +``` + +### 2.4 设备控制命令表 (device_commands) + +存储发送给设备的控制命令。 + +```sql +CREATE TABLE `device_commands` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `device_id` VARCHAR(100) NOT NULL COMMENT '设备ID', + `command` VARCHAR(100) NOT NULL COMMENT '命令名称', + `parameters` JSON COMMENT '命令参数', + `status` VARCHAR(20) NOT NULL DEFAULT 'PENDING' COMMENT '命令状态(PENDING/SENT/EXECUTED/FAILED)', + `result` TEXT COMMENT '执行结果', + `sent_at` TIMESTAMP NULL COMMENT '发送时间', + `executed_at` TIMESTAMP NULL COMMENT '执行时间', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_device_id` (`device_id`), + KEY `idx_command` (`command`), + KEY `idx_status` (`status`), + KEY `idx_created_at` (`created_at`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备控制命令表'; +``` + +### 2.5 设备配置表 (device_configs) + +存储设备配置信息。 + +```sql +CREATE TABLE `device_configs` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `device_id` VARCHAR(100) NOT NULL COMMENT '设备ID', + `config_key` VARCHAR(100) NOT NULL COMMENT '配置键', + `config_value` TEXT NOT NULL COMMENT '配置值', + `description` TEXT COMMENT '配置描述', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_device_config` (`device_id`, `config_key`), + KEY `idx_device_id` (`device_id`), + KEY `idx_config_key` (`config_key`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='设备配置表'; +``` + +### 2.6 数据聚合表 (data_aggregations) + +存储传感器数据的聚合统计信息。 + +```sql +CREATE TABLE `data_aggregations` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `device_id` VARCHAR(100) NOT NULL COMMENT '设备ID', + `sensor_type` VARCHAR(50) NOT NULL COMMENT '传感器类型', + `aggregation_type` VARCHAR(20) NOT NULL COMMENT '聚合类型(HOURLY/DAILY/WEEKLY/MONTHLY)', + `timestamp` TIMESTAMP NOT NULL COMMENT '时间戳', + `min_value` DECIMAL(10,4) COMMENT '最小值', + `max_value` DECIMAL(10,4) COMMENT '最大值', + `avg_value` DECIMAL(10,4) COMMENT '平均值', + `sum_value` DECIMAL(10,4) COMMENT '总和', + `count` INT NOT NULL DEFAULT '0' COMMENT '数据点数量', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_aggregation` (`device_id`, `sensor_type`, `aggregation_type`, `timestamp`), + KEY `idx_device_id` (`device_id`), + KEY `idx_sensor_type` (`sensor_type`), + KEY `idx_aggregation_type` (`aggregation_type`), + KEY `idx_timestamp` (`timestamp`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='数据聚合表'; +``` \ No newline at end of file diff --git a/docs/design/database/mall_service_db_design.md b/docs/design/database/mall_service_db_design.md new file mode 100644 index 0000000..f04e9c3 --- /dev/null +++ b/docs/design/database/mall_service_db_design.md @@ -0,0 +1,274 @@ +# 商城服务数据库设计文档 + +## 1. 数据库环境说明 + +- 数据库名称: xlxumu_mall +- 字符集: utf8mb4 +- 排序规则: utf8mb4_unicode_ci + +## 2. 商品分类表(product_categories) + +存储商城商品的分类信息。 + +```sql +CREATE TABLE product_categories ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + name VARCHAR(100) NOT NULL COMMENT '分类名称', + parent_id BIGINT UNSIGNED DEFAULT NULL COMMENT '父分类ID', + level TINYINT NOT NULL DEFAULT 1 COMMENT '分类层级', + sort_order INT NOT NULL DEFAULT 0 COMMENT '排序', + icon VARCHAR(255) COMMENT '分类图标', + description TEXT COMMENT '分类描述', + status ENUM('ACTIVE', 'INACTIVE') NOT NULL DEFAULT 'ACTIVE' COMMENT '状态', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_parent_id (parent_id), + INDEX idx_level (level), + INDEX idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品分类表'; +``` + +## 3. 商品信息表(products) + +存储商城商品的基本信息。 + +```sql +CREATE TABLE products ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + category_id BIGINT UNSIGNED NOT NULL COMMENT '分类ID', + seller_id BIGINT UNSIGNED NOT NULL COMMENT '卖家ID(关联user_center_service的用户ID)', + name VARCHAR(255) NOT NULL COMMENT '商品名称', + subtitle VARCHAR(255) COMMENT '商品副标题', + description TEXT COMMENT '商品描述', + cover_image VARCHAR(255) NOT NULL COMMENT '封面图片URL', + images JSON COMMENT '商品图片URL列表', + price DECIMAL(10,2) NOT NULL COMMENT '商品价格', + original_price DECIMAL(10,2) COMMENT '原价', + cost_price DECIMAL(10,2) COMMENT '成本价', + stock_quantity INT NOT NULL DEFAULT 0 COMMENT '库存数量', + sales_count INT NOT NULL DEFAULT 0 COMMENT '销售数量', + status ENUM('DRAFT', 'PENDING', 'ACTIVE', 'INACTIVE', 'DELETED') NOT NULL DEFAULT 'DRAFT' COMMENT '商品状态', + is_featured BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否推荐', + is_new BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否新品', + tags JSON COMMENT '商品标签', + attributes JSON COMMENT '商品属性', + specifications JSON COMMENT '商品规格', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_category_id (category_id), + INDEX idx_seller_id (seller_id), + INDEX idx_status (status), + INDEX idx_is_featured (is_featured), + INDEX idx_is_new (is_new), + FULLTEXT idx_name (name) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品信息表'; +``` + +## 4. 购物车表(shopping_carts) + +存储用户的购物车信息。 + +```sql +CREATE TABLE shopping_carts ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(关联user_center_service的用户ID)', + product_id BIGINT UNSIGNED NOT NULL COMMENT '商品ID', + quantity INT NOT NULL DEFAULT 1 COMMENT '商品数量', + selected BOOLEAN NOT NULL DEFAULT TRUE COMMENT '是否选中', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + UNIQUE KEY uk_user_product (user_id, product_id), + INDEX idx_user_id (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='购物车表'; +``` + +## 5. 订单表(orders) + +存储用户的订单信息。 + +```sql +CREATE TABLE orders ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + order_number VARCHAR(50) UNIQUE NOT NULL COMMENT '订单编号', + user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(关联user_center_service的用户ID)', + seller_id BIGINT UNSIGNED NOT NULL COMMENT '卖家ID(关联user_center_service的用户ID)', + total_amount DECIMAL(10,2) NOT NULL COMMENT '订单总金额', + discount_amount DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '优惠金额', + shipping_amount DECIMAL(10,2) NOT NULL DEFAULT 0.00 COMMENT '运费', + actual_amount DECIMAL(10,2) NOT NULL COMMENT '实际支付金额', + status ENUM('PENDING_PAYMENT', 'PAID', 'SHIPPED', 'DELIVERED', 'COMPLETED', 'CANCELLED', 'REFUNDED') NOT NULL DEFAULT 'PENDING_PAYMENT' COMMENT '订单状态', + payment_method VARCHAR(50) COMMENT '支付方式', + payment_time TIMESTAMP NULL COMMENT '支付时间', + shipping_address JSON NOT NULL COMMENT '收货地址', + shipping_company VARCHAR(100) COMMENT '物流公司', + shipping_number VARCHAR(100) COMMENT '物流单号', + remark TEXT COMMENT '订单备注', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + UNIQUE KEY uk_order_number (order_number), + INDEX idx_user_id (user_id), + INDEX idx_seller_id (seller_id), + INDEX idx_status (status), + INDEX idx_payment_time (payment_time) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单表'; +``` + +## 6. 订单项表(order_items) + +存储订单中的具体商品信息。 + +```sql +CREATE TABLE order_items ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + order_id BIGINT UNSIGNED NOT NULL COMMENT '订单ID', + product_id BIGINT UNSIGNED NOT NULL COMMENT '商品ID', + product_name VARCHAR(255) NOT NULL COMMENT '商品名称', + product_image VARCHAR(255) COMMENT '商品图片URL', + quantity INT NOT NULL COMMENT '商品数量', + price DECIMAL(10,2) NOT NULL COMMENT '商品单价', + total_amount DECIMAL(10,2) NOT NULL COMMENT '商品总价', + attributes JSON COMMENT '商品属性', + specifications JSON COMMENT '商品规格', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_order_id (order_id), + INDEX idx_product_id (product_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='订单项表'; +``` + +## 7. 收货地址表(shipping_addresses) + +存储用户的收货地址信息。 + +```sql +CREATE TABLE shipping_addresses ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(关联user_center_service的用户ID)', + name VARCHAR(50) NOT NULL COMMENT '收货人姓名', + phone VARCHAR(20) NOT NULL COMMENT '联系电话', + province VARCHAR(50) NOT NULL COMMENT '省份', + city VARCHAR(50) NOT NULL COMMENT '城市', + district VARCHAR(50) NOT NULL COMMENT '区县', + detail_address VARCHAR(255) NOT NULL COMMENT '详细地址', + is_default BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否默认地址', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_user_id (user_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='收货地址表'; +``` + +## 8. 优惠券表(coupons) + +存储商城的优惠券信息。 + +```sql +CREATE TABLE coupons ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + name VARCHAR(100) NOT NULL COMMENT '优惠券名称', + type ENUM('DISCOUNT', 'FIXED_AMOUNT') NOT NULL COMMENT '优惠券类型', + value DECIMAL(10,2) NOT NULL COMMENT '优惠值(折扣率或固定金额)', + min_amount DECIMAL(10,2) COMMENT '使用最低金额', + max_discount_amount DECIMAL(10,2) COMMENT '最大折扣金额', + total_quantity INT NOT NULL COMMENT '总发行量', + issued_quantity INT NOT NULL DEFAULT 0 COMMENT '已发行数量', + used_quantity INT NOT NULL DEFAULT 0 COMMENT '已使用数量', + start_time TIMESTAMP NOT NULL COMMENT '生效开始时间', + end_time TIMESTAMP NOT NULL COMMENT '生效结束时间', + 适用范围 JSON COMMENT '适用范围(商品ID列表或分类ID列表)', + status ENUM('ACTIVE', 'INACTIVE', 'EXPIRED') NOT NULL DEFAULT 'ACTIVE' COMMENT '状态', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_status (status), + INDEX idx_start_time (start_time), + INDEX idx_end_time (end_time) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='优惠券表'; +``` + +## 9. 用户优惠券表(user_coupons) + +存储用户领取的优惠券信息。 + +```sql +CREATE TABLE user_coupons ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(关联user_center_service的用户ID)', + coupon_id BIGINT UNSIGNED NOT NULL COMMENT '优惠券ID', + status ENUM('AVAILABLE', 'USED', 'EXPIRED') NOT NULL DEFAULT 'AVAILABLE' COMMENT '状态', + received_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '领取时间', + used_at TIMESTAMP NULL COMMENT '使用时间', + order_id BIGINT UNSIGNED NULL COMMENT '使用的订单ID', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_user_id (user_id), + INDEX idx_coupon_id (coupon_id), + INDEX idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户优惠券表'; +``` + +## 10. 商品评价表(product_reviews) + +存储用户对商品的评价信息。 + +```sql +CREATE TABLE product_reviews ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + product_id BIGINT UNSIGNED NOT NULL COMMENT '商品ID', + user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(关联user_center_service的用户ID)', + order_id BIGINT UNSIGNED NOT NULL COMMENT '订单ID', + rating TINYINT NOT NULL COMMENT '评分(1-5星)', + content TEXT COMMENT '评价内容', + images JSON COMMENT '评价图片URL列表', + is_anonymous BOOLEAN NOT NULL DEFAULT FALSE COMMENT '是否匿名', + status ENUM('PENDING', 'APPROVED', 'REJECTED') NOT NULL DEFAULT 'PENDING' COMMENT '审核状态', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (id), + INDEX idx_product_id (product_id), + INDEX idx_user_id (user_id), + INDEX idx_order_id (order_id), + INDEX idx_rating (rating), + INDEX idx_status (status) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品评价表'; +``` + +## 11. 商品收藏表(product_favorites) + +存储用户收藏的商品信息。 + +```sql +CREATE TABLE product_favorites ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(关联user_center_service的用户ID)', + product_id BIGINT UNSIGNED NOT NULL COMMENT '商品ID', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (id), + UNIQUE KEY uk_user_product (user_id, product_id), + INDEX idx_user_id (user_id), + INDEX idx_product_id (product_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品收藏表'; +``` + +## 12. 商品浏览记录表(product_views) + +存储用户浏览商品的记录。 + +```sql +CREATE TABLE product_views ( + id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + user_id BIGINT UNSIGNED NOT NULL COMMENT '用户ID(关联user_center_service的用户ID)', + product_id BIGINT UNSIGNED NOT NULL COMMENT '商品ID', + view_time TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '浏览时间', + PRIMARY KEY (id), + INDEX idx_user_id (user_id), + INDEX idx_product_id (product_id), + INDEX idx_view_time (view_time) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='商品浏览记录表'; +``` \ No newline at end of file diff --git a/docs/design/database/trade_service_db_design.md b/docs/design/database/trade_service_db_design.md new file mode 100644 index 0000000..3b9ab41 --- /dev/null +++ b/docs/design/database/trade_service_db_design.md @@ -0,0 +1,239 @@ +# 交易服务数据库设计文档 + +## 1. 概述 + +本文档详细描述了交易服务(trade-service)的数据库设计,包括商品信息、订单管理、支付记录等核心业务数据表结构。 + +## 2. 数据库环境 + +- 数据库类型:MySQL 8.0 +- 字符集:utf8mb4 +- 排序规则:utf8mb4_unicode_ci +- 数据库名:xlxumu_trade + +## 3. 表结构设计 + +### 3.1 商品信息表 (products) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 商品ID | +| seller_id | BIGINT | NOT NULL | 卖家用户ID | +| title | VARCHAR(200) | NOT NULL | 商品标题 | +| description | TEXT | | 商品描述 | +| category | VARCHAR(50) | NOT NULL | 商品分类 | +| price | DECIMAL(10,2) | NOT NULL | 商品价格 | +| quantity | INT | NOT NULL, DEFAULT 0 | 商品数量 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'PENDING' | 商品状态(PENDING:待审核, APPROVED:已上架, REJECTED:已拒绝, SOLD_OUT:已售罄) | +| images | JSON | | 商品图片URL列表 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- INDEX idx_seller_id (seller_id) +- INDEX idx_category (category) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.2 订单表 (orders) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 订单ID | +| order_no | VARCHAR(32) | UNIQUE, NOT NULL | 订单编号 | +| buyer_id | BIGINT | NOT NULL | 买家用户ID | +| seller_id | BIGINT | NOT NULL | 卖家用户ID | +| product_id | BIGINT | NOT NULL | 商品ID | +| quantity | INT | NOT NULL | 购买数量 | +| unit_price | DECIMAL(10,2) | NOT NULL | 单价 | +| total_amount | DECIMAL(10,2) | NOT NULL | 总金额 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'CREATED' | 订单状态(CREATED:已创建, PAID:已支付, SHIPPED:已发货, DELIVERED:已送达, COMPLETED:已完成, CANCELLED:已取消) | +| shipping_address | TEXT | NOT NULL | 收货地址 | +| contact_phone | VARCHAR(20) | NOT NULL | 联系电话 | +| remark | TEXT | | 买家备注 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- UNIQUE INDEX uk_order_no (order_no) +- INDEX idx_buyer_id (buyer_id) +- INDEX idx_seller_id (seller_id) +- INDEX idx_product_id (product_id) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.3 支付记录表 (payments) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 支付ID | +| order_id | BIGINT | NOT NULL | 关联订单ID | +| payment_no | VARCHAR(64) | UNIQUE, NOT NULL | 支付流水号 | +| amount | DECIMAL(10,2) | NOT NULL | 支付金额 | +| payment_method | VARCHAR(20) | NOT NULL | 支付方式(WECHAT:微信支付, ALIPAY:支付宝, BANK:银行转账) | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'PENDING' | 支付状态(PENDING:待支付, SUCCESS:支付成功, FAILED:支付失败, REFUNDED:已退款) | +| transaction_id | VARCHAR(100) | | 第三方支付平台交易ID | +| paid_at | DATETIME | | 实际支付时间 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- UNIQUE INDEX uk_payment_no (payment_no) +- INDEX idx_order_id (order_id) +- INDEX idx_transaction_id (transaction_id) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +### 3.4 物流信息表 (logistics) + +| 字段名 | 类型 | 约束 | 描述 | +|--------|------|------|------| +| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | 物流ID | +| order_id | BIGINT | UNIQUE, NOT NULL | 关联订单ID | +| logistics_no | VARCHAR(50) | UNIQUE, NOT NULL | 物流单号 | +| company | VARCHAR(50) | NOT NULL | 物流公司 | +| status | VARCHAR(20) | NOT NULL, DEFAULT 'PREPARING' | 物流状态(PREPARING:备货中, SHIPPED:已发货, IN_TRANSIT:运输中, DELIVERED:已送达) | +| sender_info | TEXT | NOT NULL | 发货人信息 | +| receiver_info | TEXT | NOT NULL | 收货人信息 | +| shipped_at | DATETIME | | 发货时间 | +| delivered_at | DATETIME | | 送达时间 | +| tracking_info | JSON | | 物流跟踪信息 | +| created_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP | 创建时间 | +| updated_at | DATETIME | NOT NULL, DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | 更新时间 | + +索引: +- UNIQUE INDEX uk_order_id (order_id) +- UNIQUE INDEX uk_logistics_no (logistics_no) +- INDEX idx_company (company) +- INDEX idx_status (status) +- INDEX idx_created_at (created_at) + +## 4. 表关系说明 + +1. 一个商品可以对应多个订单项(一对多) +2. 一个订单对应一个支付记录(一对一) +3. 一个订单对应一个物流信息(一对一) +4. 用户与商品、订单等通过用户ID关联 + +## 5. 数据初始化 + +### 5.1 商品状态枚举值 +- PENDING: 待审核 +- APPROVED: 已上架 +- REJECTED: 已拒绝 +- SOLD_OUT: 已售罄 + +### 5.2 订单状态流转 +- CREATED -> PAID -> SHIPPED -> DELIVERED -> COMPLETED +- CREATED -> CANCELLED +- PAID -> CANCELLED (特殊情况下) + +### 5.3 支付状态枚举值 +- PENDING: 待支付 +- SUCCESS: 支付成功 +- FAILED: 支付失败 +- REFUNDED: 已退款 + +### 5.4 物流状态枚举值 +- PREPARING: 备货中 +- SHIPPED: 已发货 +- IN_TRANSIT: 运输中 +- DELIVERED: 已送达 + +## 6. SQL脚本 + +```sql +-- 创建数据库 +CREATE DATABASE IF NOT EXISTS xlxumu_trade + CHARACTER SET utf8mb4 + COLLATE utf8mb4_unicode_ci; + +USE xlxumu_trade; + +-- 商品信息表 +CREATE TABLE products ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + seller_id BIGINT NOT NULL, + title VARCHAR(200) NOT NULL, + description TEXT, + category VARCHAR(50) NOT NULL, + price DECIMAL(10,2) NOT NULL, + quantity INT NOT NULL DEFAULT 0, + status VARCHAR(20) NOT NULL DEFAULT 'PENDING', + images JSON, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + INDEX idx_seller_id (seller_id), + INDEX idx_category (category), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 订单表 +CREATE TABLE orders ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + order_no VARCHAR(32) UNIQUE NOT NULL, + buyer_id BIGINT NOT NULL, + seller_id BIGINT NOT NULL, + product_id BIGINT NOT NULL, + quantity INT NOT NULL, + unit_price DECIMAL(10,2) NOT NULL, + total_amount DECIMAL(10,2) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'CREATED', + shipping_address TEXT NOT NULL, + contact_phone VARCHAR(20) NOT NULL, + remark TEXT, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE INDEX uk_order_no (order_no), + INDEX idx_buyer_id (buyer_id), + INDEX idx_seller_id (seller_id), + INDEX idx_product_id (product_id), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 支付记录表 +CREATE TABLE payments ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + order_id BIGINT NOT NULL, + payment_no VARCHAR(64) UNIQUE NOT NULL, + amount DECIMAL(10,2) NOT NULL, + payment_method VARCHAR(20) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'PENDING', + transaction_id VARCHAR(100), + paid_at DATETIME, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE INDEX uk_payment_no (payment_no), + INDEX idx_order_id (order_id), + INDEX idx_transaction_id (transaction_id), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 物流信息表 +CREATE TABLE logistics ( + id BIGINT PRIMARY KEY AUTO_INCREMENT, + order_id BIGINT UNIQUE NOT NULL, + logistics_no VARCHAR(50) UNIQUE NOT NULL, + company VARCHAR(50) NOT NULL, + status VARCHAR(20) NOT NULL DEFAULT 'PREPARING', + sender_info TEXT NOT NULL, + receiver_info TEXT NOT NULL, + shipped_at DATETIME, + delivered_at DATETIME, + tracking_info JSON, + created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE INDEX uk_order_id (order_id), + UNIQUE INDEX uk_logistics_no (logistics_no), + INDEX idx_company (company), + INDEX idx_status (status), + INDEX idx_created_at (created_at) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +``` \ No newline at end of file diff --git a/docs/design/database/user_center_service_db_design.md b/docs/design/database/user_center_service_db_design.md new file mode 100644 index 0000000..1cc7566 --- /dev/null +++ b/docs/design/database/user_center_service_db_design.md @@ -0,0 +1,367 @@ +# 用户中心服务数据库设计文档 + +## 1. 数据库环境说明 + +- 数据库名称: xlxumu_user +- 字符集: utf8mb4 +- 排序规则: utf8mb4_unicode_ci + +## 2. 表结构设计 + +### 2.1 用户基本信息表(users) + +存储用户的基本信息。 + +```sql +CREATE TABLE `users` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '用户ID', + `username` VARCHAR(50) NOT NULL COMMENT '用户名', + `email` VARCHAR(100) NOT NULL COMMENT '邮箱', + `phone` VARCHAR(20) DEFAULT NULL COMMENT '手机号', + `password_hash` VARCHAR(255) NOT NULL COMMENT '密码哈希值', + `nickname` VARCHAR(100) DEFAULT NULL COMMENT '昵称', + `avatar_url` VARCHAR(255) DEFAULT NULL COMMENT '头像URL', + `gender` TINYINT DEFAULT NULL COMMENT '性别(0-未知,1-男,2-女)', + `birthday` DATE DEFAULT NULL COMMENT '生日', + `real_name` VARCHAR(100) DEFAULT NULL COMMENT '真实姓名', + `id_card_number` VARCHAR(50) DEFAULT NULL COMMENT '身份证号', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-禁用)', + `last_login_at` TIMESTAMP NULL DEFAULT NULL COMMENT '最后登录时间', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_username` (`username`), + UNIQUE KEY `uk_email` (`email`), + KEY `idx_phone` (`phone`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户基本信息表'; +``` + +### 2.2 用户角色表(roles) + +存储系统中的角色信息。 + +```sql +CREATE TABLE `roles` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '角色ID', + `name` VARCHAR(50) NOT NULL COMMENT '角色名称', + `description` VARCHAR(255) DEFAULT NULL COMMENT '角色描述', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-禁用)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_name` (`name`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户角色表'; +``` + +### 2.3 用户角色关联表(user_roles) + +存储用户与角色的关联关系。 + +```sql +CREATE TABLE `user_roles` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `role_id` BIGINT UNSIGNED NOT NULL COMMENT '角色ID', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_role` (`user_id`, `role_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_role_id` (`role_id`), + CONSTRAINT `fk_user_roles_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_user_roles_role_id` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户角色关联表'; +``` + +### 2.4 权限表(permissions) + +存储系统中的权限信息。 + +```sql +CREATE TABLE `permissions` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '权限ID', + `name` VARCHAR(100) NOT NULL COMMENT '权限名称', + `code` VARCHAR(100) NOT NULL COMMENT '权限编码', + `description` VARCHAR(255) DEFAULT NULL COMMENT '权限描述', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-禁用)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='权限表'; +``` + +### 2.5 角色权限关联表(role_permissions) + +存储角色与权限的关联关系。 + +```sql +CREATE TABLE `role_permissions` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主键ID', + `role_id` BIGINT UNSIGNED NOT NULL COMMENT '角色ID', + `permission_id` BIGINT UNSIGNED NOT NULL COMMENT '权限ID', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_role_permission` (`role_id`, `permission_id`), + KEY `idx_role_id` (`role_id`), + KEY `idx_permission_id` (`permission_id`), + CONSTRAINT `fk_role_permissions_role_id` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_role_permissions_permission_id` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='角色权限关联表'; +``` + +### 2.6 用户地址表(user_addresses) + +存储用户的收货地址信息。 + +```sql +CREATE TABLE `user_addresses` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '地址ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `name` VARCHAR(50) NOT NULL COMMENT '收货人姓名', + `phone` VARCHAR(20) NOT NULL COMMENT '收货人电话', + `province` VARCHAR(50) NOT NULL COMMENT '省份', + `city` VARCHAR(50) NOT NULL COMMENT '城市', + `district` VARCHAR(50) NOT NULL COMMENT '区/县', + `detail_address` VARCHAR(255) NOT NULL COMMENT '详细地址', + `is_default` TINYINT NOT NULL DEFAULT '0' COMMENT '是否默认地址(0-否,1-是)', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-删除)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_status` (`status`), + CONSTRAINT `fk_user_addresses_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户地址表'; +``` + +### 2.7 用户积分记录表(user_points_records) + +存储用户的积分变动记录。 + +```sql +CREATE TABLE `user_points_records` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '记录ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `change_type` TINYINT NOT NULL COMMENT '变动类型(1-增加,2-减少)', + `points` INT NOT NULL COMMENT '积分数量', + `balance` INT NOT NULL COMMENT '变动后余额', + `description` VARCHAR(255) DEFAULT NULL COMMENT '描述', + `related_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '关联ID(如订单ID)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_created_at` (`created_at`), + CONSTRAINT `fk_user_points_records_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户积分记录表'; +``` + +### 2.8 用户等级表(user_levels) + +存储用户等级信息。 + +```sql +CREATE TABLE `user_levels` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '等级ID', + `level` INT NOT NULL COMMENT '等级', + `name` VARCHAR(50) NOT NULL COMMENT '等级名称', + `min_points` INT NOT NULL COMMENT '所需最低积分', + `discount_rate` DECIMAL(3,2) NOT NULL DEFAULT '1.00' COMMENT '折扣率(如0.95表示95折)', + `description` VARCHAR(255) DEFAULT NULL COMMENT '等级描述', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-禁用)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_level` (`level`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户等级表'; +``` + +### 2.9 用户等级记录表(user_level_records) + +存储用户等级变更记录。 + +```sql +CREATE TABLE `user_level_records` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '记录ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `from_level` INT DEFAULT NULL COMMENT '原等级', + `to_level` INT NOT NULL COMMENT '新等级', + `change_reason` VARCHAR(255) DEFAULT NULL COMMENT '变更原因', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_created_at` (`created_at`), + CONSTRAINT `fk_user_level_records_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户等级记录表'; +``` + +### 2.10 登录日志表(login_logs) + +存储用户登录日志。 + +```sql +CREATE TABLE `login_logs` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '日志ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `ip_address` VARCHAR(45) NOT NULL COMMENT 'IP地址', + `user_agent` TEXT DEFAULT NULL COMMENT '用户代理', + `login_status` TINYINT NOT NULL DEFAULT '1' COMMENT '登录状态(1-成功,2-失败)', + `failure_reason` VARCHAR(255) DEFAULT NULL COMMENT '失败原因', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_ip_address` (`ip_address`), + KEY `idx_created_at` (`created_at`), + CONSTRAINT `fk_login_logs_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='登录日志表'; +``` + +### 2.11 操作日志表(operation_logs) + +存储用户操作日志。 + +```sql +CREATE TABLE `operation_logs` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '日志ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `module` VARCHAR(50) NOT NULL COMMENT '操作模块', + `operation` VARCHAR(50) NOT NULL COMMENT '操作类型', + `resource_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '资源ID', + `request_method` VARCHAR(10) NOT NULL COMMENT '请求方法', + `request_url` VARCHAR(255) NOT NULL COMMENT '请求URL', + `request_params` TEXT DEFAULT NULL COMMENT '请求参数', + `ip_address` VARCHAR(45) NOT NULL COMMENT 'IP地址', + `user_agent` TEXT DEFAULT NULL COMMENT '用户代理', + `execution_time` INT NOT NULL COMMENT '执行时间(毫秒)', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '操作状态(1-成功,2-失败)', + `error_message` TEXT DEFAULT NULL COMMENT '错误信息', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_module` (`module`), + KEY `idx_created_at` (`created_at`), + CONSTRAINT `fk_operation_logs_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='操作日志表'; +``` + +### 2.12 用户认证信息表(user_auths) + +存储用户的第三方认证信息。 + +```sql +CREATE TABLE `user_auths` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '认证ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `auth_type` VARCHAR(20) NOT NULL COMMENT '认证类型(wechat,alipay,qq等)', + `auth_id` VARCHAR(100) NOT NULL COMMENT '第三方用户ID', + `auth_name` VARCHAR(100) DEFAULT NULL COMMENT '第三方用户名', + `auth_avatar` VARCHAR(255) DEFAULT NULL COMMENT '第三方用户头像', + `access_token` TEXT DEFAULT NULL COMMENT '访问令牌', + `refresh_token` TEXT DEFAULT NULL COMMENT '刷新令牌', + `expires_at` TIMESTAMP NULL DEFAULT NULL COMMENT '过期时间', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_auth_type_auth_id` (`auth_type`, `auth_id`), + KEY `idx_user_id` (`user_id`), + CONSTRAINT `fk_user_auths_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户认证信息表'; +``` + +### 2.13 用户设备表(user_devices) + +存储用户绑定的设备信息。 + +```sql +CREATE TABLE `user_devices` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '设备ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `device_id` VARCHAR(100) NOT NULL COMMENT '设备ID', + `device_type` VARCHAR(50) NOT NULL COMMENT '设备类型', + `device_name` VARCHAR(100) DEFAULT NULL COMMENT '设备名称', + `push_token` VARCHAR(255) DEFAULT NULL COMMENT '推送令牌', + `last_login_at` TIMESTAMP NULL DEFAULT NULL COMMENT '最后登录时间', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-禁用)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_user_device` (`user_id`, `device_id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_device_id` (`device_id`), + CONSTRAINT `fk_user_devices_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户设备表'; +``` + +### 2.14 用户消息表(user_messages) + +存储用户的消息。 + +```sql +CREATE TABLE `user_messages` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '消息ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `title` VARCHAR(255) NOT NULL COMMENT '消息标题', + `content` TEXT NOT NULL COMMENT '消息内容', + `message_type` TINYINT NOT NULL DEFAULT '1' COMMENT '消息类型(1-系统消息,2-通知,3-营销)', + `is_read` TINYINT NOT NULL DEFAULT '0' COMMENT '是否已读(0-未读,1-已读)', + `read_at` TIMESTAMP NULL DEFAULT NULL COMMENT '阅读时间', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-删除)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_is_read` (`is_read`), + KEY `idx_status` (`status`), + CONSTRAINT `fk_user_messages_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户消息表'; +``` + +### 2.15 用户消息模板表(message_templates) + +存储消息模板。 + +```sql +CREATE TABLE `message_templates` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '模板ID', + `code` VARCHAR(50) NOT NULL COMMENT '模板编码', + `name` VARCHAR(100) NOT NULL COMMENT '模板名称', + `title` VARCHAR(255) NOT NULL COMMENT '消息标题', + `content` TEXT NOT NULL COMMENT '消息内容', + `message_type` TINYINT NOT NULL DEFAULT '1' COMMENT '消息类型(1-系统消息,2-通知,3-营销)', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-正常,2-禁用)', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + UNIQUE KEY `uk_code` (`code`), + KEY `idx_status` (`status`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户消息模板表'; +``` + +### 2.16 用户反馈表(user_feedbacks) + +存储用户的反馈信息。 + +```sql +CREATE TABLE `user_feedbacks` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '反馈ID', + `user_id` BIGINT UNSIGNED NOT NULL COMMENT '用户ID', + `title` VARCHAR(255) NOT NULL COMMENT '反馈标题', + `content` TEXT NOT NULL COMMENT '反馈内容', + `contact_info` VARCHAR(255) DEFAULT NULL COMMENT '联系方式', + `category` VARCHAR(50) DEFAULT NULL COMMENT '反馈分类', + `status` TINYINT NOT NULL DEFAULT '1' COMMENT '状态(1-待处理,2-处理中,3-已解决,4-已关闭)', + `reply_content` TEXT DEFAULT NULL COMMENT '回复内容', + `reply_user_id` BIGINT UNSIGNED DEFAULT NULL COMMENT '回复用户ID', + `replied_at` TIMESTAMP NULL DEFAULT NULL COMMENT '回复时间', + `created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', + `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', + PRIMARY KEY (`id`), + KEY `idx_user_id` (`user_id`), + KEY `idx_status` (`status`), + CONSTRAINT `fk_user_feedbacks_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE, + CONSTRAINT `fk_user_feedbacks_reply_user_id` FOREIGN KEY (`reply_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='用户反馈表'; +``` \ No newline at end of file diff --git a/docs/development_plans/backend_api_development_plan.md b/docs/development_plans/backend_api_development_plan.md index 78466a0..21a846e 100644 --- a/docs/development_plans/backend_api_development_plan.md +++ b/docs/development_plans/backend_api_development_plan.md @@ -1,58 +1,44 @@ # 后端API开发计划 -## 1. 概述 - -本项目采用双技术栈架构,后端服务基于Java Spring Boot和Node.js两种技术栈构建。Java技术栈作为主要后端技术,采用微服务架构设计;Node.js技术栈作为辅助技术,用于特定业务场景。 - -## 2. 技术栈架构 - -### 2.1 Java技术栈(主要) -- **核心框架**: Spring Boot 2.7.x, Spring Cloud 2021.x -- **服务注册与发现**: Eureka -- **配置中心**: Spring Cloud Config -- **API网关**: Spring Cloud Gateway -- **数据库**: MySQL 8.0, Spring Data JPA +## 1. 技术栈架构 +- **主要后端技术栈**: Java (Spring Boot + Spring Cloud) +- **辅助后端技术栈**: Node.js +- **数据库**: MySQL 8.0 - **缓存**: Redis - **消息队列**: RabbitMQ -- **安全框架**: Spring Security + JWT -- **构建工具**: Maven 3.8.x +- **API文档**: Swagger/OpenAPI 3.0 +- **容器化**: Docker +- **编排**: Kubernetes -### 2.2 Node.js技术栈(辅助) -- **运行环境**: Node.js 16.x -- **Web框架**: Express.js -- **数据库**: MySQL 8.0 -- **ORM**: Sequelize -- **构建工具**: NPM/Yarn +## 2. Java后端开发计划 -## 3. Java后端开发计划 - -### 3.1 已完成模块 +### 2.1 已完成模块 1. **养殖管理服务 (farming-service:8081)** - - 功能:养殖场管理、牲畜档案、饲养记录等 - - 状态:已完成开发和部署 + - 功能:牛只管理、饲喂记录、防疫记录等 + - 状态:已完成 - 负责人:Java开发团队 2. **用户中心服务 (user-center-service:8082)** - - 功能:用户管理、权限控制、认证授权等 - - 状态:已完成开发和部署 + - 功能:用户注册、登录、权限管理等 + - 状态:已完成 - 负责人:Java开发团队 -### 3.2 开发中模块 +### 2.2 开发中模块 1. **交易服务 (trade-service:8083)** - - 功能:活牛交易、订单管理、支付处理等 + - 功能:商品发布、订单管理、物流跟踪等 - 状态:开发中 - - 进度:60% + - 进度:10% - 预计完成时间:2024年2月15日 - 负责人:Java开发团队 2. **金融服务 (finance-service:8084)** - 功能:贷款申请、保险购买、金融产品等 - 状态:开发中 - - 进度:40% + - 进度:5% - 预计完成时间:2024年2月28日 - 负责人:Java开发团队 -### 3.3 待开发模块 +### 2.3 待开发模块 1. **数据平台服务 (data-platform-service:8085)** - 功能:数据统计、报表生成、数据分析等 - 状态:待开发 @@ -81,134 +67,112 @@ - 预计完成时间:2024年4月20日 - 负责人:Java开发团队 -## 4. Node.js后端开发计划 +## 3. Node.js后端开发计划 -### 4.1 已完成模块 -1. **AI能力服务 (ai-service:3001)** +### 3.1 已完成模块 +1. **AI能力服务 (ai-service:8089)** - 功能:图像识别、智能分析等AI相关功能 - 状态:已完成基础框架搭建 - 负责人:Node.js开发团队 -### 4.2 开发中模块 +### 3.2 开发中模块 1. **部分遗留服务 (legacy-service:3002)** - - 功能:部分原有系统功能的兼容 + - 功能:部分原有系统功能迁移 - 状态:重构中 - - 进度:30% - - 预计完成时间:2024年2月20日 + - 预计完成时间:2024年3月15日 - 负责人:Node.js开发团队 -### 4.3 待开发模块 -1. **其他辅助服务** - - 功能:根据业务需求开发的辅助功能 - - 状态:待规划 - - 预计开始时间:2024年3月1日 - - 预计完成时间:根据需求确定 - - 负责人:Node.js开发团队 +## 4. 微服务架构规划 -## 5. 微服务架构规划 +### 4.1 核心业务服务(Java) +| 服务名称 | 端口 | 功能描述 | +|---------|------|----------| +| farming-service | 8081 | 养殖管理服务 | +| user-center-service | 8082 | 用户中心服务 | +| trade-service | 8083 | 交易服务 | +| finance-service | 8084 | 金融服务 | +| data-platform-service | 8085 | 数据平台服务 | +| government-service | 8086 | 政府服务 | +| dashboard-service | 8087 | 大屏服务 | +| mall-service | 8088 | 商城服务 | -### 5.1 核心服务端口分配 -| 服务名称 | 端口号 | 技术栈 | 状态 | -|---------|--------|--------|------| -| farming-service | 8081 | Java | 已完成 | -| user-center-service | 8082 | Java | 已完成 | -| trade-service | 8083 | Java | 开发中 | -| finance-service | 8084 | Java | 开发中 | -| data-platform-service | 8085 | Java | 待开发 | -| government-service | 8086 | Java | 待开发 | -| dashboard-service | 8087 | Java | 待开发 | -| mall-service | 8088 | Java | 待开发 | +### 4.2 基础设施服务(Java) +| 服务名称 | 端口 | 功能描述 | +|---------|------|----------| +| gateway | 8000 | 网关服务 | +| registry | 8761 | 服务注册中心 | +| config-server | 8888 | 配置服务器 | -### 5.2 基础设施服务端口分配 -| 服务名称 | 端口号 | 技术栈 | 状态 | -|---------|--------|--------|------| -| gateway | 8080 | Java | 待开发 | -| registry | 8761 | Java | 待开发 | -| config-server | 8888 | Java | 待开发 | +### 4.3 辅助服务(Node.js) +| 服务名称 | 端口 | 功能描述 | +|---------|------|----------| +| ai-service | 8089 | AI能力服务 | +| legacy-service | 3002 | 部分遗留服务 | -### 5.3 Node.js服务端口分配 -| 服务名称 | 端口号 | 技术栈 | 状态 | -|---------|--------|--------|------| -| ai-service | 3001 | Node.js | 已完成基础框架 | -| legacy-service | 3002 | Node.js | 重构中 | +## 5. 技术迁移策略 -## 6. 技术迁移策略 +### 5.1 迁移原则 +1. 核心业务优先迁移至Java技术栈 +2. 保持现有Node.js服务的稳定性 +3. 逐步替换遗留系统功能 -### 6.1 迁移原则 -1. **渐进式迁移**: 逐步将Node.js服务迁移到Java微服务架构 -2. **业务优先**: 优先迁移核心业务服务 -3. **兼容性保证**: 确保迁移过程中不影响现有业务 -4. **数据一致性**: 保证数据迁移的完整性和一致性 +### 5.2 迁移步骤 +1. 完成核心业务服务的Java版本开发 +2. 部署并测试微服务架构 +3. 逐步迁移现有Node.js功能 +4. 最终统一到Java微服务架构 -### 6.2 迁移步骤 -1. **评估阶段**: 评估现有Node.js服务的复杂度和迁移难度 -2. **设计阶段**: 设计Java微服务架构和接口规范 -3. **开发阶段**: 开发新的Java微服务 -4. **测试阶段**: 进行全面的功能测试和性能测试 -5. **部署阶段**: 逐步替换现有Node.js服务 -6. **监控阶段**: 监控新服务的运行状态和性能表现 +## 6. 开发规范 -## 7. 开发规范 +### 6.1 代码规范 +- 遵循阿里巴巴Java开发手册 +- 使用Checkstyle进行代码检查 +- 所有接口遵循RESTful设计规范 -### 7.1 代码规范 -1. **Java代码规范**: 遵循阿里巴巴Java开发手册 -2. **Node.js代码规范**: 遵循JavaScript Standard Style -3. **API设计规范**: 遵循RESTful API设计原则 -4. **数据库设计规范**: 遵循数据库设计范式 +### 6.2 文档规范 +- 所有API接口必须提供Swagger文档 +- 数据库设计需提供ER图和说明文档 +- 重要业务逻辑需提供流程图和说明 -### 7.2 文档规范 -1. **API文档**: 每个接口必须提供详细的API文档 -2. **设计文档**: 每个服务必须提供架构设计文档 -3. **部署文档**: 每个服务必须提供部署说明文档 +### 6.3 测试规范 +- 单元测试覆盖率不低于80% +- 接口测试覆盖所有业务场景 +- 性能测试满足系统设计要求 -### 7.3 测试规范 -1. **单元测试**: 每个模块必须提供单元测试 -2. **集成测试**: 服务间接口必须提供集成测试 -3. **性能测试**: 关键服务必须提供性能测试报告 +## 7. 测试策略 -## 8. 测试策略 +### 7.1 测试类型 +- 单元测试:验证各模块功能正确性 +- 集成测试:验证服务间交互正确性 +- 接口测试:验证API接口功能和性能 +- 压力测试:验证系统在高并发下的稳定性 -### 8.1 测试类型 -1. **单元测试**: 验证每个模块的功能正确性 -2. **集成测试**: 验证服务间的接口调用 -3. **性能测试**: 验证系统的性能表现 -4. **安全测试**: 验证系统的安全性 +### 7.2 测试工具 +- JUnit 5:Java单元测试框架 +- Mockito:Java Mock框架 +- Postman:API接口测试工具 +- JMeter:性能测试工具 -### 8.2 测试工具 -1. **Java测试**: JUnit, Mockito -2. **Node.js测试**: Jest, Mocha -3. **API测试**: Postman, JMeter -4. **性能测试**: JMeter, Gatling +## 8. 部署策略 -## 9. 部署策略 +### 8.1 部署环境 +- 开发环境:本地Docker容器 +- 测试环境:专用测试服务器 +- 生产环境:Kubernetes集群 -### 9.1 部署环境 -1. **开发环境**: 本地开发环境 -2. **测试环境**: 内部测试环境 -3. **预生产环境**: 预生产验证环境 -4. **生产环境**: 正式生产环境 +### 8.2 部署方式 +- 使用Docker容器化部署 +- 通过Kubernetes进行服务编排 +- 使用CI/CD流水线自动化部署 -### 9.2 部署方式 -1. **容器化部署**: 使用Docker容器化部署 -2. **自动化部署**: 使用Jenkins实现CI/CD -3. **蓝绿部署**: 关键服务采用蓝绿部署策略 -4. **滚动更新**: 普通服务采用滚动更新策略 +## 9. 风险控制 -## 10. 风险控制 +### 9.1 技术风险 +- 微服务间通信复杂性:使用Spring Cloud Gateway统一管理 +- 数据一致性问题:引入分布式事务解决方案 +- 高并发场景下的数据库性能瓶颈:引入读写分离和分库分表策略 -### 10.1 技术风险 -1. **技术栈切换风险**: 开发团队需要适应新的技术栈 -2. **性能风险**: 微服务架构可能带来性能损耗 -3. **数据一致性风险**: 分布式系统中的数据一致性问题 - -### 10.2 管理风险 -1. **进度风险**: 多个服务并行开发可能影响整体进度 -2. **沟通风险**: 不同技术团队间的沟通协调问题 -3. **质量风险**: 快速开发可能影响代码质量 - -### 10.3 应对措施 -1. **技术培训**: 组织技术培训帮助团队适应新技术 -2. **性能优化**: 通过缓存、异步等手段优化性能 -3. **监控告警**: 建立完善的监控告警机制 -4. **代码审查**: 严格执行代码审查制度 -5. **定期评审**: 定期进行项目进度评审 \ No newline at end of file +### 9.2 管理风险 +- 团队需要适应新的Java技术栈:提供技术培训和指导 +- 微服务架构增加了系统复杂性:制定详细的架构设计文档 +- 多团队协作可能存在的沟通问题:建立定期沟通机制 \ No newline at end of file