feat(user-center): 新增收货地址管理功能

- 添加收货地址实体类、控制器、服务类和数据访问接口
- 实现收货地址创建、获取列表、获取详情、更新和删除功能- 集成JWT认证,确保操作的安全性
- 新增相关API文档
This commit is contained in:
ylweng
2025-09-11 23:23:51 +08:00
parent 6c22882cb8
commit 33c138c839
77 changed files with 14049 additions and 139 deletions

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.xlxumu</groupId>
<artifactId>backend-java</artifactId>
<version>1.0.0</version>
</parent>
<artifactId=ai-service</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name=ai-service</name>
<description>AI能力服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.xlxumu</groupId>
<artifactId>backend-java</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>data-platform-service</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>data-platform-service</name>
<description>数据平台服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.xlxumu</groupId>
<artifactId>backend-java</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>finance-service</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>finance-service</name>
<description>金融服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.xlxumu</groupId>
<artifactId>backend-java</artifactId>
<version>1.0.0</version>
</parent>
<artifactId=government-service</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name=government-service</name>
<description>政务服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.xlxumu</groupId>
<artifactId>backend-java</artifactId>
<version>1.0.0</version>
</parent>
<artifactId=mall-service</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name=mall-service</name>
<description>商城服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -0,0 +1,53 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.xlxumu</groupId>
<artifactId>backend-java</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>trade-service</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>trade-service</name>
<description>交易服务</description>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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");
}
}

View File

@@ -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<Map<String, Object>> createAddress(
HttpServletRequest request,
@RequestBody Map<String, Object> requestData) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> 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<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "地址创建成功");
response.put("data", address);
return ResponseEntity.ok(response);
}
/**
* 获取收货地址列表接口
*/
@GetMapping
public ResponseEntity<Map<String, Object>> getAddressList(HttpServletRequest request) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
List<Address> addresses = addressService.getAddressList(userId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", addresses);
return ResponseEntity.ok(response);
}
/**
* 获取收货地址详情接口
*/
@GetMapping("/{addressId}")
public ResponseEntity<Map<String, Object>> getAddressDetail(
HttpServletRequest request,
@PathVariable Long addressId) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
Address address = addressService.getAddressDetail(userId, addressId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", address);
return ResponseEntity.ok(response);
}
/**
* 更新收货地址接口
*/
@PutMapping("/{addressId}")
public ResponseEntity<Map<String, Object>> updateAddress(
HttpServletRequest request,
@PathVariable Long addressId,
@RequestBody Map<String, Object> requestData) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> 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<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "地址更新成功");
response.put("data", address);
return ResponseEntity.ok(response);
}
/**
* 删除收货地址接口
*/
@DeleteMapping("/{addressId}")
public ResponseEntity<Map<String, Object>> deleteAddress(
HttpServletRequest request,
@PathVariable Long addressId) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
addressService.deleteAddress(userId, addressId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "地址删除成功");
return ResponseEntity.ok(response);
}
}

View File

@@ -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<Map<String, Object>> submitFeedback(
HttpServletRequest request,
@RequestBody Map<String, String> requestData) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> 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<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "反馈提交成功");
response.put("data", feedback);
return ResponseEntity.ok(response);
}
/**
* 获取反馈列表接口
*/
@GetMapping
public ResponseEntity<Map<String, Object>> getFeedbackList(HttpServletRequest request) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
List<Feedback> feedbacks = feedbackService.getFeedbackList(userId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", feedbacks);
return ResponseEntity.ok(response);
}
}

View File

@@ -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: 实现获取等级列表接口
}

View File

@@ -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<Map<String, Object>> getMessageList(HttpServletRequest request) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
List<Message> messages = messageService.getMessageList(userId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", messages);
return ResponseEntity.ok(response);
}
/**
* 标记消息为已读接口
*/
@PutMapping("/{messageId}/read")
public ResponseEntity<Map<String, Object>> markMessageAsRead(
HttpServletRequest request,
@PathVariable Long messageId) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
messageService.markMessageAsRead(messageId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "标记成功");
return ResponseEntity.ok(response);
}
/**
* 删除消息接口
*/
@DeleteMapping("/{messageId}")
public ResponseEntity<Map<String, Object>> deleteMessage(
HttpServletRequest request,
@PathVariable Long messageId) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
messageService.deleteMessage(messageId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "删除成功");
return ResponseEntity.ok(response);
}
}

View File

@@ -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<Map<String, Object>> getUserPointsBalance(HttpServletRequest request) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
Integer balance = pointsService.getUserPointsBalance(userId);
Map<String, Object> 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<Map<String, Object>> getPointsRecordList(HttpServletRequest request) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
List<PointsRecord> records = pointsService.getPointsRecordList(userId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", records);
return ResponseEntity.ok(response);
}
/**
* 获取用户当前等级接口
*/
@GetMapping("/level")
public ResponseEntity<Map<String, Object>> getUserCurrentLevel(HttpServletRequest request) {
// 从JWT令牌中获取用户ID
Long userId = jwtTokenUtil.getUserIdFromRequest(request);
if (userId == null) {
Map<String, Object> errorResponse = new HashMap<>();
errorResponse.put("code", 401);
errorResponse.put("message", "无效的访问令牌");
return ResponseEntity.status(401).body(errorResponse);
}
Level level = levelService.getUserCurrentLevel(userId);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", level);
return ResponseEntity.ok(response);
}
/**
* 获取等级列表接口
*/
@GetMapping("/levels")
public ResponseEntity<Map<String, Object>> getLevelList() {
List<Level> levels = levelService.getLevelList();
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", levels);
return ResponseEntity.ok(response);
}
}

View File

@@ -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<Map<String, Object>> register(@RequestBody Map<String, String> 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<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "注册成功");
response.put("data", user);
return ResponseEntity.ok(response);
}
/**
* 用户登录接口
*/
@PostMapping("/login")
public ResponseEntity<Map<String, Object>> login(@RequestBody Map<String, String> request) {
String username = request.get("username");
String password = request.get("password");
String token = userService.login(username, password);
Map<String, Object> 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<ApiResponse<User>> 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<Map<String, Object>> updateUserInfo(
@RequestHeader("Authorization") String token,
@RequestBody Map<String, String> 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<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "更新成功");
response.put("data", user);
return ResponseEntity.ok(response);
}
/**
* 修改密码接口
*/
@PutMapping("/password")
public ResponseEntity<Map<String, Object>> changePassword(
@RequestHeader("Authorization") String token,
@RequestBody Map<String, String> request) {
String oldPassword = request.get("oldPassword");
String newPassword = request.get("newPassword");
userService.changePassword(token, oldPassword, newPassword);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "密码修改成功");
return ResponseEntity.ok(response);
}
/**
* 管理员获取用户列表接口
*/
@GetMapping("/list")
public ResponseEntity<Map<String, Object>> getUserList(
@RequestHeader("Authorization") String token,
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size) {
List<User> users = userService.getUserList(token, page, size);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "获取成功");
response.put("data", users);
return ResponseEntity.ok(response);
}
/**
* 管理员更新用户状态接口
*/
@PutMapping("/{userId}/status")
public ResponseEntity<Map<String, Object>> updateUserStatus(
@RequestHeader("Authorization") String token,
@PathVariable Long userId,
@RequestBody Map<String, Integer> request) {
Integer status = request.get("status");
userService.updateUserStatus(token, userId, status);
Map<String, Object> response = new HashMap<>();
response.put("code", 200);
response.put("message", "状态更新成功");
return ResponseEntity.ok(response);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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<Object> handleUserException(UserException ex, WebRequest request) {
Map<String, Object> 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<Object> handleGenericException(Exception ex, WebRequest request) {
Map<String, Object> 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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<Address, Long> {
/**
* 根据用户ID查找收货地址列表
* @param userId 用户ID
* @return 收货地址列表
*/
List<Address> findByUserId(Long userId);
/**
* 根据用户ID和默认地址标识查找默认收货地址
* @param userId 用户ID
* @param isDefault 是否默认地址
* @return 收货地址
*/
Address findByUserIdAndIsDefault(Long userId, Boolean isDefault);
}

View File

@@ -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<Feedback, Long> {
/**
* 根据用户ID查找反馈列表
* @param userId 用户ID
* @return 反馈列表
*/
List<Feedback> findByUserIdOrderByCreatedAtDesc(Long userId);
}

View File

@@ -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<Level, Long> {
/**
* 根据状态查找等级列表
* @param status 状态
* @return 等级列表
*/
List<Level> findByStatusOrderByMinPointsAsc(Integer status);
}

View File

@@ -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<Message, Long> {
/**
* 根据用户ID查找消息列表
* @param userId 用户ID
* @return 消息列表
*/
List<Message> findByUserIdOrderByCreatedAtDesc(Long userId);
/**
* 根据用户ID和已读状态查找消息列表
* @param userId 用户ID
* @param isRead 是否已读
* @return 消息列表
*/
List<Message> findByUserIdAndIsReadOrderByCreatedAtDesc(Long userId, Boolean isRead);
}

View File

@@ -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<PointsRecord, Long> {
/**
* 根据用户ID查找积分记录列表
* @param userId 用户ID
* @return 积分记录列表
*/
List<PointsRecord> findByUserIdOrderByCreatedAtDesc(Long userId);
}

View File

@@ -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<UserLevel, Long> {
/**
* 根据用户ID查找用户等级信息
* @param userId 用户ID
* @return 用户等级信息
*/
Optional<UserLevel> findByUserId(Long userId);
}

View File

@@ -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<User, Long> {
/**
* 根据用户名查找用户
* @param username 用户名
* @return 用户信息
*/
Optional<User> findByUsername(String username);
/**
* 根据邮箱查找用户
* @param email 邮箱
* @return 用户信息
*/
Optional<User> findByEmail(String email);
/**
* 根据手机号查找用户
* @param phone 手机号
* @return 用户信息
*/
Optional<User> findByPhone(String phone);
/**
* 根据用户名和密码查找用户
* @param username 用户名
* @param passwordHash 密码哈希值
* @return 用户信息
*/
Optional<User> findByUsernameAndPasswordHash(String username, String passwordHash);
}

View File

@@ -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<Address> getAddressList(Long userId) {
return addressRepository.findByUserId(userId);
}
/**
* 获取收货地址详情
* @param addressId 地址ID
* @return 地址信息
*/
public Address getAddressDetail(Long addressId) {
Optional<Address> 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<Address> 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<Address> 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);
}
}

View File

@@ -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<Feedback> getFeedbackList(Long userId) {
return feedbackRepository.findByUserIdOrderByCreatedAtDesc(userId);
}
}

View File

@@ -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<UserLevel> userLevelOptional = userLevelRepository.findByUserId(userId);
if (!userLevelOptional.isPresent()) {
throw new UserException("用户等级信息不存在", 404);
}
Long levelId = userLevelOptional.get().getLevelId();
Optional<Level> levelOptional = levelRepository.findById(levelId);
if (!levelOptional.isPresent()) {
throw new UserException("等级信息不存在", 404);
}
return levelOptional.get();
}
/**
* 获取等级列表
* @return 等级列表
*/
public List<Level> getLevelList() {
return levelRepository.findByStatusOrderByMinPointsAsc(1);
}
}

View File

@@ -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<Message> getMessageList(Long userId) {
return messageRepository.findByUserIdOrderByCreatedAtDesc(userId);
}
/**
* 标记消息为已读
* @param messageId 消息ID
*/
public void markMessageAsRead(Long messageId) {
Optional<Message> 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<Message> messageOptional = messageRepository.findById(messageId);
if (!messageOptional.isPresent()) {
throw new UserException("消息不存在", 404);
}
Message message = messageOptional.get();
message.setStatus(0); // 软删除
messageRepository.save(message);
}
}

View File

@@ -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<UserLevel> userLevelOptional = userLevelRepository.findByUserId(userId);
if (!userLevelOptional.isPresent()) {
throw new UserException("用户等级信息不存在", 404);
}
return userLevelOptional.get().getCurrentPoints();
}
/**
* 获取积分记录列表
* @param userId 用户ID
* @return 积分记录列表
*/
public List<PointsRecord> 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<UserLevel> 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();
}
}

View File

@@ -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<User> 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<User> 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<User> 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<User> 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<User> getUserList() {
return userRepository.findAll();
}
/**
* 管理员更新用户状态
* @param userId 用户ID
* @param status 状态
* @return 更新后的用户信息
*/
public User updateUserStatus(Long userId, Integer status) {
Optional<User> 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);
}
}

View File

@@ -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;
}
}

View File

@@ -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 <T> 声明类型
* @return 声明值
*/
public <T> T getClaimFromToken(String token, Function<Claims, T> 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<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userId.toString());
}
/**
* 创建token
* @param claims 声明
* @param subject 主题(用户ID)
* @return JWT token
*/
private String doGenerateToken(Map<String, Object> 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));
}
}

View File

@@ -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();
}
}

View File

@@ -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: 请求路径

View File

@@ -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: 请求路径

View File

@@ -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: 请求路径

View File

@@ -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'

View File

@@ -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: 请求路径

View File

@@ -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: 请求路径

View File

@@ -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
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQL8Dialect
# JWT配置
jwt.secret=xlxumu_user_center_secret_key_2024
jwt.expiration=86400000

View File

@@ -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 | 系统错误 | 服务器内部错误 |

View File

@@ -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 | 系统错误 | 服务器内部错误 |

View File

@@ -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 | 系统错误 | 服务器内部错误 |

View File

@@ -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 | 系统错误 | 服务器内部错误 |

View File

@@ -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 | 系统错误 | 服务器内部错误 |

View File

@@ -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 | 系统错误 | 服务器内部错误 |

File diff suppressed because it is too large Load Diff

View File

@@ -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 | 系统错误 | 服务器内部错误 |

File diff suppressed because it is too large Load Diff

View File

@@ -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='用户反馈表';
```

View File

@@ -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;
```

View File

@@ -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='收获记录表';
```

View File

@@ -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;
```

View File

@@ -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='农产品质量认证表';
```

View File

@@ -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='数据聚合表';
```

View File

@@ -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='商品浏览记录表';
```

View File

@@ -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;
```

View File

@@ -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='用户反馈表';
```

View File

@@ -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 5Java单元测试框架
- MockitoJava Mock框架
- PostmanAPI接口测试工具
- 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. **定期评审**: 定期进行项目进度评审
### 9.2 管理风险
- 团队需要适应新的Java技术栈提供技术培训和指导
- 微服务架构增加了系统复杂性:制定详细的架构设计文档
- 多团队协作可能存在的沟通问题:建立定期沟通机制