docs(deployment): 更新部署文档并添加自动化部署脚本
- 更新了 DEPLOYMENT.md 文档,增加了更多部署细节和说明 - 添加了 Linux 和 Windows 平台的自动化部署脚本 - 更新了 README.md,增加了部署相关说明 - 调整了 .env 文件配置,以适应新的部署流程 - 移除了部分不必要的代码和配置
This commit is contained in:
56
backend-java/order-service/pom.xml
Normal file
56
backend-java/order-service/pom.xml
Normal file
@@ -0,0 +1,56 @@
|
||||
<?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.jiebanke</groupId>
|
||||
<artifactId>backend-java</artifactId>
|
||||
<version>1.0.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>order-service</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<!-- Spring Boot Web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Eureka Client -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MyBatis Plus -->
|
||||
<dependency>
|
||||
<groupId>com.baomidou</groupId>
|
||||
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- MySQL -->
|
||||
<dependency>
|
||||
<groupId>mysql</groupId>
|
||||
<artifactId>mysql-connector-java</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- 结伴客公共模块 -->
|
||||
<dependency>
|
||||
<groupId>com.jiebanke</groupId>
|
||||
<artifactId>common</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,19 @@
|
||||
package com.jiebanke.order;
|
||||
|
||||
import org.mybatis.spring.annotation.MapperScan;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
|
||||
import org.springframework.cloud.openfeign.EnableFeignClients;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
|
||||
@SpringBootApplication
|
||||
@EnableDiscoveryClient
|
||||
@EnableFeignClients
|
||||
@MapperScan("com.jiebanke.order.mapper")
|
||||
@ComponentScan(basePackages = "com.jiebanke")
|
||||
public class OrderApplication {
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(OrderApplication.class, args);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
package com.jiebanke.order.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.jiebanke.common.vo.ApiResponse;
|
||||
import com.jiebanke.order.entity.Order;
|
||||
import com.jiebanke.order.service.OrderService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/orders")
|
||||
public class OrderController {
|
||||
|
||||
@Autowired
|
||||
private OrderService orderService;
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
*/
|
||||
@PostMapping
|
||||
public ApiResponse<Map<String, Object>> createOrder(
|
||||
@RequestHeader("userId") Long userId,
|
||||
@RequestBody Order order) {
|
||||
|
||||
Long orderId = orderService.createOrder(order, userId);
|
||||
Order createdOrder = orderService.getOrderById(orderId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("order", createdOrder);
|
||||
result.put("message", "订单创建成功");
|
||||
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单详情
|
||||
*/
|
||||
@GetMapping("/{orderId}")
|
||||
public ApiResponse<Order> getOrder(@PathVariable Long orderId) {
|
||||
Order order = orderService.getOrderById(orderId);
|
||||
return ApiResponse.success(order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户订单列表
|
||||
*/
|
||||
@GetMapping
|
||||
public ApiResponse<Map<String, Object>> getUserOrders(
|
||||
@RequestHeader("userId") Long userId,
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String status) {
|
||||
|
||||
IPage<Order> orders = orderService.getUserOrders(userId, page, pageSize, status);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("orders", orders.getRecords());
|
||||
result.put("pagination", Map.of(
|
||||
"page", orders.getCurrent(),
|
||||
"pageSize", orders.getSize(),
|
||||
"total", orders.getTotal(),
|
||||
"totalPages", orders.getPages()
|
||||
));
|
||||
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新订单状态
|
||||
*/
|
||||
@PutMapping("/{orderId}/status")
|
||||
public ApiResponse<Map<String, Object>> updateOrderStatus(
|
||||
@PathVariable Long orderId,
|
||||
@RequestBody Map<String, String> requestBody,
|
||||
@RequestHeader("userId") Long userId) {
|
||||
|
||||
String status = requestBody.get("status");
|
||||
Order updatedOrder = orderService.updateOrderStatus(orderId, status, userId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("order", updatedOrder);
|
||||
result.put("message", "订单状态更新成功");
|
||||
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除订单
|
||||
*/
|
||||
@DeleteMapping("/{orderId}")
|
||||
public ApiResponse<Map<String, Object>> deleteOrder(
|
||||
@PathVariable Long orderId,
|
||||
@RequestHeader("userId") Long userId) {
|
||||
|
||||
boolean deleted = orderService.deleteOrder(orderId, userId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("message", "订单删除成功");
|
||||
result.put("orderId", orderId);
|
||||
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取订单统计信息
|
||||
*/
|
||||
@GetMapping("/statistics")
|
||||
public ApiResponse<Map<String, Object>> getOrderStatistics(@RequestHeader("merchantId") Long merchantId) {
|
||||
Map<String, Object> statistics = orderService.getOrderStats(merchantId);
|
||||
return ApiResponse.success(statistics);
|
||||
}
|
||||
|
||||
/**
|
||||
* 管理员获取所有订单
|
||||
*/
|
||||
@GetMapping("/admin")
|
||||
public ApiResponse<Map<String, Object>> getAllOrders(
|
||||
@RequestParam(defaultValue = "1") Integer page,
|
||||
@RequestParam(defaultValue = "10") Integer pageSize,
|
||||
@RequestParam(required = false) String status,
|
||||
@RequestParam(required = false) Long merchantId,
|
||||
@RequestParam(required = false) Long userId) {
|
||||
|
||||
IPage<Order> orders = orderService.getAllOrders(page, pageSize, status, merchantId, userId);
|
||||
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("orders", orders.getRecords());
|
||||
result.put("pagination", Map.of(
|
||||
"page", orders.getCurrent(),
|
||||
"pageSize", orders.getSize(),
|
||||
"total", orders.getTotal(),
|
||||
"totalPages", orders.getPages()
|
||||
));
|
||||
|
||||
return ApiResponse.success(result);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.jiebanke.order.entity;
|
||||
|
||||
import com.jiebanke.common.entity.BaseEntity;
|
||||
import lombok.Data;
|
||||
import lombok.EqualsAndHashCode;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
public class Order extends BaseEntity {
|
||||
private Long userId;
|
||||
private String orderNo;
|
||||
private BigDecimal amount;
|
||||
private String status;
|
||||
private String type;
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package com.jiebanke.order.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.jiebanke.order.entity.Order;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
import org.apache.ibatis.annotations.Select;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Mapper
|
||||
public interface OrderMapper extends BaseMapper<Order> {
|
||||
|
||||
/**
|
||||
* 根据用户ID获取订单列表
|
||||
* @param userId 用户ID
|
||||
* @return 订单列表
|
||||
*/
|
||||
@Select("SELECT * FROM orders WHERE user_id = #{userId} ORDER BY created_at DESC")
|
||||
List<Order> selectByUserId(@Param("userId") Long userId);
|
||||
|
||||
/**
|
||||
* 根据状态获取订单列表
|
||||
* @param status 状态
|
||||
* @return 订单列表
|
||||
*/
|
||||
@Select("SELECT * FROM orders WHERE status = #{status} ORDER BY created_at DESC")
|
||||
List<Order> selectByStatus(@Param("status") String status);
|
||||
|
||||
/**
|
||||
* 根据订单号获取订单
|
||||
* @param orderNo 订单号
|
||||
* @return 订单
|
||||
*/
|
||||
@Select("SELECT * FROM orders WHERE order_no = #{orderNo}")
|
||||
Order selectByOrderNo(@Param("orderNo") String orderNo);
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package com.jiebanke.order.service;
|
||||
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.jiebanke.order.entity.Order;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public interface OrderService extends IService<Order> {
|
||||
|
||||
/**
|
||||
* 创建订单
|
||||
* @param order 订单信息
|
||||
* @param userId 用户ID
|
||||
* @return 创建的订单ID
|
||||
*/
|
||||
Long createOrder(Order order, Long userId);
|
||||
|
||||
/**
|
||||
* 根据ID获取订单
|
||||
* @param orderId 订单ID
|
||||
* @return 订单信息
|
||||
*/
|
||||
Order getOrderById(Long orderId);
|
||||
|
||||
/**
|
||||
* 获取用户订单列表
|
||||
* @param userId 用户ID
|
||||
* @param page 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param status 状态
|
||||
* @return 订单分页列表
|
||||
*/
|
||||
IPage<Order> getUserOrders(Long userId, Integer page, Integer pageSize, String status);
|
||||
|
||||
/**
|
||||
* 更新订单状态
|
||||
* @param orderId 订单ID
|
||||
* @param status 新状态
|
||||
* @param userId 操作人ID
|
||||
* @return 更新后的订单
|
||||
*/
|
||||
Order updateOrderStatus(Long orderId, String status, Long userId);
|
||||
|
||||
/**
|
||||
* 删除订单(软删除)
|
||||
* @param orderId 订单ID
|
||||
* @param userId 用户ID
|
||||
* @return 是否删除成功
|
||||
*/
|
||||
boolean deleteOrder(Long orderId, Long userId);
|
||||
|
||||
/**
|
||||
* 获取订单统计信息
|
||||
* @param merchantId 商家ID
|
||||
* @return 统计信息
|
||||
*/
|
||||
Map<String, Object> getOrderStats(Long merchantId);
|
||||
|
||||
/**
|
||||
* 获取所有订单(管理员)
|
||||
* @param page 页码
|
||||
* @param pageSize 每页数量
|
||||
* @param status 状态
|
||||
* @param merchantId 商家ID
|
||||
* @param userId 用户ID
|
||||
* @return 订单分页列表
|
||||
*/
|
||||
IPage<Order> getAllOrders(Integer page, Integer pageSize, String status, Long merchantId, Long userId);
|
||||
}
|
||||
@@ -0,0 +1,159 @@
|
||||
package com.jiebanke.order.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.jiebanke.common.exception.BusinessException;
|
||||
import com.jiebanke.order.entity.Order;
|
||||
import com.jiebanke.order.mapper.OrderMapper;
|
||||
import com.jiebanke.order.service.OrderService;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
@Service
|
||||
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements OrderService {
|
||||
|
||||
@Override
|
||||
public Long createOrder(Order order, Long userId) {
|
||||
// 生成订单号
|
||||
String orderNo = "ORD" + System.currentTimeMillis() + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
|
||||
order.setOrderNo(orderNo);
|
||||
order.setUserId(userId);
|
||||
|
||||
// 设置默认状态
|
||||
if (order.getStatus() == null) {
|
||||
order.setStatus("pending");
|
||||
}
|
||||
|
||||
this.save(order);
|
||||
return order.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Order getOrderById(Long orderId) {
|
||||
Order order = this.getById(orderId);
|
||||
if (order == null) {
|
||||
throw new BusinessException("订单不存在");
|
||||
}
|
||||
return order;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<Order> getUserOrders(Long userId, Integer page, Integer pageSize, String status) {
|
||||
QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("user_id", userId);
|
||||
|
||||
if (status != null && !status.isEmpty()) {
|
||||
queryWrapper.eq("status", status);
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc("created_at");
|
||||
|
||||
Page<Order> pageObj = new Page<>(page != null ? page : 1, pageSize != null ? pageSize : 10);
|
||||
return this.page(pageObj, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Order updateOrderStatus(Long orderId, String status, Long userId) {
|
||||
Order existingOrder = this.getById(orderId);
|
||||
if (existingOrder == null) {
|
||||
throw new BusinessException("订单不存在");
|
||||
}
|
||||
|
||||
// 验证状态是否有效
|
||||
String[] validStatuses = {"pending", "processing", "completed", "cancelled", "failed"};
|
||||
boolean isValidStatus = false;
|
||||
for (String validStatus : validStatuses) {
|
||||
if (validStatus.equals(status)) {
|
||||
isValidStatus = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValidStatus) {
|
||||
throw new BusinessException("无效的订单状态");
|
||||
}
|
||||
|
||||
existingOrder.setStatus(status);
|
||||
this.updateById(existingOrder);
|
||||
return existingOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deleteOrder(Long orderId, Long userId) {
|
||||
return this.removeById(orderId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Object> getOrderStats(Long merchantId) {
|
||||
QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
|
||||
queryWrapper.eq("merchant_id", merchantId);
|
||||
|
||||
int totalOrders = Math.toIntExact(this.count(queryWrapper));
|
||||
|
||||
QueryWrapper<Order> pendingWrapper = new QueryWrapper<>();
|
||||
pendingWrapper.eq("merchant_id", merchantId).eq("status", "pending");
|
||||
int pendingOrders = Math.toIntExact(this.count(pendingWrapper));
|
||||
|
||||
QueryWrapper<Order> processingWrapper = new QueryWrapper<>();
|
||||
processingWrapper.eq("merchant_id", merchantId).eq("status", "processing");
|
||||
int processingOrders = Math.toIntExact(this.count(processingWrapper));
|
||||
|
||||
QueryWrapper<Order> completedWrapper = new QueryWrapper<>();
|
||||
completedWrapper.eq("merchant_id", merchantId).eq("status", "completed");
|
||||
int completedOrders = Math.toIntExact(this.count(completedWrapper));
|
||||
|
||||
QueryWrapper<Order> cancelledWrapper = new QueryWrapper<>();
|
||||
cancelledWrapper.eq("merchant_id", merchantId).eq("status", "cancelled");
|
||||
int cancelledOrders = Math.toIntExact(this.count(cancelledWrapper));
|
||||
|
||||
QueryWrapper<Order> failedWrapper = new QueryWrapper<>();
|
||||
failedWrapper.eq("merchant_id", merchantId).eq("status", "failed");
|
||||
int failedOrders = Math.toIntExact(this.count(failedWrapper));
|
||||
|
||||
// 计算总收入
|
||||
QueryWrapper<Order> revenueWrapper = new QueryWrapper<>();
|
||||
revenueWrapper.eq("merchant_id", merchantId).select("SUM(amount) as totalRevenue");
|
||||
Map<String, Object> revenueMap = this.getMap(revenueWrapper);
|
||||
BigDecimal totalRevenue = revenueMap != null && revenueMap.get("totalRevenue") != null ?
|
||||
new BigDecimal(revenueMap.get("totalRevenue").toString()) : BigDecimal.ZERO;
|
||||
|
||||
Map<String, Object> stats = new HashMap<>();
|
||||
stats.put("totalOrders", totalOrders);
|
||||
stats.put("pendingOrders", pendingOrders);
|
||||
stats.put("processingOrders", processingOrders);
|
||||
stats.put("completedOrders", completedOrders);
|
||||
stats.put("cancelledOrders", cancelledOrders);
|
||||
stats.put("failedOrders", failedOrders);
|
||||
stats.put("totalRevenue", totalRevenue);
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPage<Order> getAllOrders(Integer page, Integer pageSize, String status, Long merchantId, Long userId) {
|
||||
QueryWrapper<Order> queryWrapper = new QueryWrapper<>();
|
||||
|
||||
if (status != null && !status.isEmpty()) {
|
||||
queryWrapper.eq("status", status);
|
||||
}
|
||||
|
||||
if (merchantId != null) {
|
||||
queryWrapper.eq("merchant_id", merchantId);
|
||||
}
|
||||
|
||||
if (userId != null) {
|
||||
queryWrapper.eq("user_id", userId);
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc("created_at");
|
||||
|
||||
Page<Order> pageObj = new Page<>(page != null ? page : 1, pageSize != null ? pageSize : 10);
|
||||
return this.page(pageObj, queryWrapper);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
server:
|
||||
port: 8085
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: order-service
|
||||
datasource:
|
||||
url: jdbc:mysql://localhost:3306/jiebanke?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=Asia/Shanghai
|
||||
username: root
|
||||
password: root
|
||||
driver-class-name: com.mysql.cj.jdbc.Driver
|
||||
redis:
|
||||
host: localhost
|
||||
port: 6379
|
||||
database: 0
|
||||
rabbitmq:
|
||||
host: localhost
|
||||
port: 5672
|
||||
username: guest
|
||||
password: guest
|
||||
|
||||
eureka:
|
||||
client:
|
||||
service-url:
|
||||
defaultZone: http://localhost:8761/eureka/
|
||||
|
||||
mybatis-plus:
|
||||
configuration:
|
||||
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
||||
global-config:
|
||||
db-config:
|
||||
id-type: auto
|
||||
Reference in New Issue
Block a user