完成了用户地址的增加修改删除功能,完成了订单模块:创建订单、订单分页查询、订单状态更新...

This commit is contained in:
puzvv
2025-12-18 21:13:05 +08:00
parent 696757da21
commit 3ef4454356
16 changed files with 957 additions and 1 deletions

View File

@@ -24,4 +24,7 @@ public class MessageConstant {
public static final String CART_ITEM_NOT_FOUND = "购物车记录不存在";
public static final String STOCK_INSUFFICIENT = "库存不足,无法添加";
public static final String NO_PERMISSION = "没有权限";
public static final String CART_ITEM_EMPTY = "购物车为空";
public static final String ADDRESS_ID_NULL = "地址ID不能为空";
public static final String ADDRESS_NOT_FOUND = "地址不存在";
}

View File

@@ -0,0 +1,85 @@
// OrderController.java
package icu.sunway.ai_spring_example.Controllers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import icu.sunway.ai_spring_example.Common.Response.ResponseEntity;
import icu.sunway.ai_spring_example.Service.OrderService;
import icu.sunway.ai_spring_example.pojo.Dto.OrderDTO;
import icu.sunway.ai_spring_example.pojo.Dto.OrderStatusDTO;
import icu.sunway.ai_spring_example.pojo.Vo.OrderListVO;
import icu.sunway.ai_spring_example.pojo.Vo.OrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
@RestController
@RequestMapping("/order")
@Slf4j
public class OrderController {
@Autowired
private OrderService orderService;
/**
* 创建订单
*/
@PostMapping
public ResponseEntity createOrder(@Validated @RequestBody OrderDTO orderDTO) {
log.info("创建订单: {}", orderDTO);
Long orderId = orderService.createOrder(orderDTO);
Map<String, Object> result = new HashMap<>();
result.put("orderId", orderId);
return ResponseEntity.success("订单创建成功", result);
}
/**
* 分页查询订单列表
*/
@GetMapping("/page")
public ResponseEntity<Map<String, Object>> getOrderPage(
@RequestParam(defaultValue = "1") Integer page,
@RequestParam(defaultValue = "10") Integer size,
@RequestParam Long userId,
@RequestParam(required = false) Integer status
) {
log.info("查询订单列表: page={}, size={}, userId={}, status={}",
page, size, userId, status);
Page<OrderListVO> orderPage = orderService.getOrderPage(page, size, userId, status);
Map<String, Object> result = new HashMap<>();
result.put("list", orderPage.getRecords());
result.put("total", orderPage.getTotal());
result.put("page", page);
result.put("size", size);
return ResponseEntity.success(result);
}
/**
* 查询订单详情
*/
@GetMapping("/{id}")
public ResponseEntity<OrderVO> getOrderDetail(
@PathVariable Long id,
@RequestParam Long userId
) {
log.info("查询订单详情: id={}, userId={}", id, userId);
OrderVO orderVO = orderService.getOrderDetail(id, userId);
return ResponseEntity.success(orderVO);
}
/**
* 更新订单状态
*/
@PutMapping("/status")
public ResponseEntity updateOrderStatus(@Validated @RequestBody OrderStatusDTO statusDTO) {
log.info("更新订单状态: {}", statusDTO);
orderService.updateOrderStatus(statusDTO);
return ResponseEntity.success("订单状态更新成功");
}
}

View File

@@ -6,17 +6,22 @@ import icu.sunway.ai_spring_example.Common.Constant.StatusConstant;
import icu.sunway.ai_spring_example.Common.Properties.JwtProperties;
import icu.sunway.ai_spring_example.Common.Response.ResponseEntity;
import icu.sunway.ai_spring_example.Common.Utils.JwtUtil;
import icu.sunway.ai_spring_example.Service.UserAddressService;
import icu.sunway.ai_spring_example.Service.UserService;
import icu.sunway.ai_spring_example.pojo.Dto.UserAddressDTO;
import icu.sunway.ai_spring_example.pojo.Dto.UserDTO;
import icu.sunway.ai_spring_example.pojo.Entity.User;
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
import icu.sunway.ai_spring_example.pojo.Vo.UserLoginVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@@ -29,6 +34,9 @@ public class UserController {
@Autowired
private JwtProperties jwtProperties;
@Autowired
private UserAddressService userAddressService;
@PostMapping("/login")
public ResponseEntity<UserLoginVO> login(@RequestBody UserDTO userDTO){
log.info("用户登录:{}",userDTO);
@@ -76,4 +84,64 @@ public class UserController {
userService.update(userDTO);
return ResponseEntity.success("更新成功");
}
/**
* 添加地址
*/
@PostMapping("/address")
public ResponseEntity addAddress(@Validated @RequestBody UserAddressDTO addressDTO) {
log.info("添加用户地址: {}", addressDTO);
userAddressService.addAddress(addressDTO);
return ResponseEntity.success("地址添加成功");
}
/**
* 更新地址
*/
@PutMapping("/address")
public ResponseEntity updateAddress(@Validated @RequestBody UserAddressDTO addressDTO) {
log.info("更新用户地址: {}", addressDTO);
userAddressService.updateAddress(addressDTO);
return ResponseEntity.success("地址更新成功");
}
/**
* 删除地址
*/
@DeleteMapping("/address/{id}")
public ResponseEntity deleteAddress(@PathVariable Long id, @RequestParam Long userId) {
log.info("删除用户地址: id={}, userId={}", id, userId);
userAddressService.deleteAddress(id, userId);
return ResponseEntity.success("地址删除成功");
}
/**
* 查询用户地址列表
*/
@GetMapping("/address")
public ResponseEntity<List<UserAddress>> getAddressList(@RequestParam Long userId) {
log.info("查询用户地址列表: userId={}", userId);
List<UserAddress> addressList = userAddressService.getAddressListByUserId(userId);
return ResponseEntity.success(addressList);
}
/**
* 查询地址详情
*/
@GetMapping("/address/{id}")
public ResponseEntity<UserAddress> getAddressDetail(@PathVariable Long id, @RequestParam Long userId) {
log.info("查询地址详情: id={}, userId={}", id, userId);
UserAddress address = userAddressService.getAddressById(id, userId);
return ResponseEntity.success(address);
}
/**
* 设置默认地址
*/
@PutMapping("/address/{id}/default")
public ResponseEntity setDefaultAddress(@PathVariable Long id, @RequestParam Long userId) {
log.info("设置默认地址: id={}, userId={}", id, userId);
userAddressService.setDefaultAddress(id, userId);
return ResponseEntity.success("默认地址设置成功");
}
}

View File

@@ -0,0 +1,10 @@
// OrderInfoMapper.java
package icu.sunway.ai_spring_example.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import icu.sunway.ai_spring_example.pojo.Entity.OrderInfo;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderInfoMapper extends BaseMapper<OrderInfo> {
}

View File

@@ -0,0 +1,10 @@
// OrderItemMapper.java
package icu.sunway.ai_spring_example.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import icu.sunway.ai_spring_example.pojo.Entity.OrderItem;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface OrderItemMapper extends BaseMapper<OrderItem> {
}

View File

@@ -0,0 +1,11 @@
// UserAddressMapper.java
package icu.sunway.ai_spring_example.Mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface UserAddressMapper extends BaseMapper<UserAddress> {
}

View File

@@ -0,0 +1,278 @@
// OrderServiceImpl.java
package icu.sunway.ai_spring_example.Service.Impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import icu.sunway.ai_spring_example.Common.Exception.BusinessException;
import icu.sunway.ai_spring_example.Common.Constant.MessageConstant;
import icu.sunway.ai_spring_example.Mapper.*;
import icu.sunway.ai_spring_example.Service.OrderService;
import icu.sunway.ai_spring_example.pojo.Dto.OrderDTO;
import icu.sunway.ai_spring_example.pojo.Dto.OrderStatusDTO;
import icu.sunway.ai_spring_example.pojo.Entity.*;
import icu.sunway.ai_spring_example.pojo.Vo.OrderListVO;
import icu.sunway.ai_spring_example.pojo.Vo.OrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
@Service
@Slf4j
public class OrderServiceImpl extends ServiceImpl<OrderInfoMapper, OrderInfo> implements OrderService {
@Autowired
private OrderInfoMapper orderInfoMapper;
@Autowired
private OrderItemMapper orderItemMapper;
@Autowired
private ShoppingCartMapper shoppingCartMapper;
@Autowired
private ProductSkuMapper productSkuMapper;
@Autowired
private ProductMapper productMapper;
/**
* 生成唯一订单编号
*/
private String generateOrderNo() {
// 格式: 年月日时分秒 + 3位随机数
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
String dateStr = LocalDateTime.now().format(formatter);
Random random = new Random();
int randomNum = random.nextInt(900) + 100; // 100-999的随机数
return "ORDER" + dateStr + randomNum;
}
@Override
@Transactional
public Long createOrder(OrderDTO orderDTO) {
// 1. 查询用户购物车中已勾选的商品
LambdaQueryWrapper<ShoppingCart> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ShoppingCart::getUserId, orderDTO.getUserId())
.eq(ShoppingCart::getChecked, 1) // 只查询已勾选的商品
.eq(ShoppingCart::getIsDeleted, 0);
List<ShoppingCart> cartList = shoppingCartMapper.selectList(queryWrapper);
if (cartList == null || cartList.isEmpty()) {
throw new BusinessException(MessageConstant.CART_ITEM_EMPTY);
}
// 2. 验证库存并计算总金额
BigDecimal totalAmount = BigDecimal.ZERO;
//TODO 改运费
BigDecimal freightAmount = new BigDecimal("0.00"); // 假设运费0元
for (ShoppingCart cart : cartList) {
ProductSku sku = productSkuMapper.selectById(cart.getSkuId());
if (sku == null) {
throw new BusinessException("商品规格不存在: " + cart.getSkuId());
}
if (sku.getStock() < cart.getCount()) {
throw new BusinessException("商品 " + sku.getSkuName() + " 库存不足");
}
// 计算商品总价
BigDecimal itemTotal = sku.getPrice().multiply(new BigDecimal(cart.getCount()));
totalAmount = totalAmount.add(itemTotal);
}
// 3. 创建订单主表记录
OrderInfo orderInfo = new OrderInfo();
BeanUtils.copyProperties(orderDTO, orderInfo);
String orderNo = generateOrderNo();
orderInfo.setOrderNo(orderNo);
orderInfo.setTotalAmount(totalAmount);
orderInfo.setFreightAmount(freightAmount);
orderInfo.setPayAmount(totalAmount.add(freightAmount)); // 实付金额 = 商品总价 + 运费
orderInfo.setStatus(0); // 初始状态:待付款
orderInfo.setCreateTime(LocalDateTime.now());
orderInfo.setUpdateTime(LocalDateTime.now());
orderInfo.setIsDeleted(0);
orderInfoMapper.insert(orderInfo);
// 4. 创建订单项记录
for (ShoppingCart cart : cartList) {
ProductSku sku = productSkuMapper.selectById(cart.getSkuId());
Product product = productMapper.selectById(cart.getProductId());
OrderItem orderItem = new OrderItem();
orderItem.setOrderId(orderInfo.getId());
orderItem.setOrderNo(orderNo);
orderItem.setProductId(cart.getProductId());
orderItem.setSkuId(cart.getSkuId());
orderItem.setProductName(product.getName());
orderItem.setSkuName(sku.getSkuName());
orderItem.setProductImage(product.getMainImage());
orderItem.setPrice(sku.getPrice());
orderItem.setQuantity(cart.getCount());
orderItem.setTotalPrice(sku.getPrice().multiply(new BigDecimal(cart.getCount())));
orderItem.setCreateTime(LocalDateTime.now());
orderItem.setUpdateTime(LocalDateTime.now());
orderItem.setIsDeleted(0);
orderItemMapper.insert(orderItem);
// 5. 扣减库存
sku.setStock(sku.getStock() - cart.getCount());
productSkuMapper.updateById(sku);
}
// 6. 清空购物车中已下单的商品
shoppingCartMapper.delete(queryWrapper);
log.info("创建订单成功: {}", orderNo);
return orderInfo.getId();
}
@Override
public Page<OrderListVO> getOrderPage(Integer page, Integer size, Long userId, Integer status) {
// 构造查询条件
QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_deleted", 0); // 排除逻辑删除的记录
if (userId != null) {
queryWrapper.eq("user_id", userId);
}
if (status != null) {
queryWrapper.eq("status", status);
}
queryWrapper.orderByDesc("create_time");
// 使用MyBatis-Plus分页查询
Page<OrderInfo> pageInfo = new Page<>(page, size);
Page<OrderInfo> orderPage = orderInfoMapper.selectPage(pageInfo, queryWrapper);
// 转换为VO对象
Page<OrderListVO> voPage = new Page<>(page, size, orderPage.getTotal());
List<OrderListVO> voList = orderPage.getRecords().stream().map(orderInfo -> {
OrderListVO vo = new OrderListVO();
BeanUtils.copyProperties(orderInfo, vo);
QueryWrapper<OrderItem> itemQueryWrapper = new QueryWrapper<>();
itemQueryWrapper.eq("order_id", orderInfo.getId());
List<OrderItem> itemList = orderItemMapper.selectList(itemQueryWrapper);
Integer count = 0;
for (OrderItem item : itemList) {
count += item.getQuantity();
}
vo.setProductCount(count);
return vo;
}).collect(Collectors.toList());
voPage.setRecords(voList);
// 转换状态码为文本
voPage.getRecords().forEach(vo -> {
switch (vo.getStatus()) {
case 0: vo.setStatusText("待付款"); break;
case 1: vo.setStatusText("待发货"); break;
case 2: vo.setStatusText("待收货"); break;
case 3: vo.setStatusText("已完成"); break;
case 4: vo.setStatusText("已取消"); break;
default: vo.setStatusText("未知状态");
}
});
return voPage;
}
@Override
public OrderVO getOrderDetail(Long orderId, Long userId) {
// 查询订单主信息
OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
if (orderInfo == null || orderInfo.getIsDeleted() == 1) {
throw new BusinessException(MessageConstant.ORDER_NOT_FOUND);
}
// 验证订单归属
if (!orderInfo.getUserId().equals(userId)) {
throw new BusinessException(MessageConstant.NO_PERMISSION);
}
// 查询订单项
LambdaQueryWrapper<OrderItem> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(OrderItem::getOrderId, orderId)
.eq(OrderItem::getIsDeleted, 0);
List<OrderItem> orderItems = orderItemMapper.selectList(queryWrapper);
// 转换为VO
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(orderInfo, orderVO);
orderVO.setOrderItems(orderItems);
return orderVO;
}
@Override
@Transactional
public void updateOrderStatus(OrderStatusDTO statusDTO) {
QueryWrapper<OrderInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", statusDTO.getOrderId())
.eq("is_deleted", 0);
OrderInfo orderInfo = orderInfoMapper.selectOne(queryWrapper);
// 验证状态转换的合法性
Integer currentStatus = orderInfo.getStatus();
Integer newStatus = statusDTO.getStatus();
// 状态转换规则校验
if (!isValidStatusTransition(currentStatus, newStatus)) {
throw new BusinessException("不允许从状态 " + currentStatus + " 转换到 " + newStatus);
}
// 更新状态和相关时间
orderInfo.setStatus(newStatus);
orderInfo.setUpdateTime(LocalDateTime.now());
// 根据状态设置相应的时间
if (newStatus == 1) { // 待发货 -> 支付时间
orderInfo.setPayTime(LocalDateTime.now());
} else if (newStatus == 2) { // 待收货 -> 发货时间
orderInfo.setDeliveryTime(LocalDateTime.now());
} else if (newStatus == 3) { // 已完成 -> 收货时间
orderInfo.setReceiveTime(LocalDateTime.now());
}
orderInfoMapper.updateById(orderInfo);
log.info("订单 {} 状态更新为: {}", orderInfo.getOrderNo(), newStatus);
}
/**
* 验证状态转换是否合法
*/
private boolean isValidStatusTransition(Integer currentStatus, Integer newStatus) {
// 状态转换规则:
// 0-待付款 -> 1-待发货 或 4-已取消
// 1-待发货 -> 2-待收货 或 4-已取消
// 2-待收货 -> 3-已完成 或 4-已取消
// 3-已完成 -> 不能转换
// 4-已取消 -> 不能转换
if (currentStatus == 0) {
return newStatus == 1 || newStatus == 4;
} else if (currentStatus == 1) {
return newStatus == 2 || newStatus == 4;
} else if (currentStatus == 2) {
return newStatus == 3 || newStatus == 4;
} else { // 3或4状态不能再转换
return false;
}
}
}

View File

@@ -0,0 +1,183 @@
// UserAddressServiceImpl.java
package icu.sunway.ai_spring_example.Service.Impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import icu.sunway.ai_spring_example.Common.Exception.BusinessException;
import icu.sunway.ai_spring_example.Common.Constant.MessageConstant;
import icu.sunway.ai_spring_example.Mapper.UserAddressMapper;
import icu.sunway.ai_spring_example.Service.UserAddressService;
import icu.sunway.ai_spring_example.pojo.Dto.UserAddressDTO;
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.List;
@Service
@Slf4j
public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserAddress> implements UserAddressService {
private final UserAddressMapper userAddressMapper;
public UserAddressServiceImpl(UserAddressMapper userAddressMapper) {
this.userAddressMapper = userAddressMapper;
}
@Override
@Transactional
public void addAddress(UserAddressDTO addressDTO) {
log.info("新增用户地址: {}", addressDTO);
UserAddress address = new UserAddress();
BeanUtils.copyProperties(addressDTO, address);
// 如果设置为默认地址,先取消该用户其他默认地址
if (address.getIsDefault() != null && address.getIsDefault() == 1) {
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserAddress::getUserId, address.getUserId())
.eq(UserAddress::getIsDefault, 1);
UserAddress defaultAddress = userAddressMapper.selectOne(queryWrapper);
if (defaultAddress != null) {
defaultAddress.setIsDefault(0);
userAddressMapper.updateById(defaultAddress);
}
} else {
// 如果是首次添加地址,默认设为默认地址
LambdaQueryWrapper<UserAddress> countWrapper = new LambdaQueryWrapper<>();
countWrapper.eq(UserAddress::getUserId, address.getUserId());
long count = userAddressMapper.selectCount(countWrapper);
if (count == 0) {
address.setIsDefault(1);
} else {
address.setIsDefault(0); // 非首次添加且未指定默认,设为非默认
}
}
userAddressMapper.insert(address);
}
@Override
@Transactional
public void updateAddress(UserAddressDTO addressDTO) {
log.info("更新用户地址: {}", addressDTO);
if (addressDTO.getId() == null) {
throw new BusinessException(MessageConstant.ADDRESS_ID_NULL);
}
// 验证地址是否存在且属于当前用户
UserAddress address = userAddressMapper.selectById(addressDTO.getId());
if (address == null || !address.getUserId().equals(addressDTO.getUserId())) {
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
}
BeanUtils.copyProperties(addressDTO, address);
// 如果设置为默认地址,先取消该用户其他默认地址
if (address.getIsDefault() != null && address.getIsDefault() == 1) {
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserAddress::getUserId, address.getUserId())
.eq(UserAddress::getIsDefault, 1)
.ne(UserAddress::getId, address.getId()); // 排除当前地址
UserAddress defaultAddress = userAddressMapper.selectOne(queryWrapper);
if (defaultAddress != null) {
defaultAddress.setIsDefault(0);
userAddressMapper.updateById(defaultAddress);
}
}
address.setUpdateTime(LocalDateTime.now());
userAddressMapper.updateById(address);
}
@Override
@Transactional
public void deleteAddress(Long id, Long userId) {
log.info("删除用户地址: id={}, userId={}", id, userId);
if (id == null || userId == null) {
throw new BusinessException(MessageConstant.PARAM_ERROR);
}
UserAddress address = userAddressMapper.selectById(id);
if (address == null || !address.getUserId().equals(userId)) {
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
}
// 如果删除的是默认地址,需要将其他地址设为默认
if (address.getIsDefault() == 1) {
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserAddress::getUserId, userId)
.ne(UserAddress::getId, id)
.eq(UserAddress::getIsDeleted, 0);
List<UserAddress> otherAddresses = userAddressMapper.selectList(queryWrapper);
if (!otherAddresses.isEmpty()) {
UserAddress newDefault = otherAddresses.get(0);
newDefault.setIsDefault(1);
userAddressMapper.updateById(newDefault);
}
}
// 逻辑删除
QueryWrapper<UserAddress> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("id", id);
userAddressMapper.delete(queryWrapper);
}
@Override
public List<UserAddress> getAddressListByUserId(Long userId) {
log.info("查询用户地址列表: userId={}", userId);
if (userId == null) {
throw new BusinessException(MessageConstant.PARAM_ERROR);
}
QueryWrapper<UserAddress> queryWrapper = new QueryWrapper<>();
return userAddressMapper.selectList(queryWrapper);
}
@Override
public UserAddress getAddressById(Long id, Long userId) {
log.info("查询地址详情: id={}, userId={}", id, userId);
if (id == null || userId == null) {
throw new BusinessException(MessageConstant.PARAM_ERROR);
}
UserAddress address = userAddressMapper.selectById(id);
if (address == null || address.getIsDeleted() == 1 || !address.getUserId().equals(userId)) {
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
}
return address;
}
@Override
@Transactional
public void setDefaultAddress(Long id, Long userId) {
log.info("设置默认地址: id={}, userId={}", id, userId);
if (id == null || userId == null) {
throw new BusinessException(MessageConstant.PARAM_ERROR);
}
// 验证地址是否存在且属于当前用户
UserAddress address = userAddressMapper.selectById(id);
if (address == null || address.getIsDeleted() == 1 || !address.getUserId().equals(userId)) {
throw new BusinessException(MessageConstant.ADDRESS_NOT_FOUND);
}
// 取消其他默认地址
LambdaQueryWrapper<UserAddress> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(UserAddress::getUserId, userId)
.eq(UserAddress::getIsDefault, 1)
.ne(UserAddress::getId, id);
UserAddress defaultAddress = userAddressMapper.selectOne(queryWrapper);
if (defaultAddress != null) {
defaultAddress.setIsDefault(0);
userAddressMapper.updateById(defaultAddress);
}
// 设置当前地址为默认
address.setIsDefault(1);
address.setUpdateTime(LocalDateTime.now());
userAddressMapper.updateById(address);
}
}

View File

@@ -0,0 +1,44 @@
// OrderService.java
package icu.sunway.ai_spring_example.Service;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import icu.sunway.ai_spring_example.pojo.Dto.OrderDTO;
import icu.sunway.ai_spring_example.pojo.Dto.OrderStatusDTO;
import icu.sunway.ai_spring_example.pojo.Entity.OrderInfo;
import icu.sunway.ai_spring_example.pojo.Vo.OrderListVO;
import icu.sunway.ai_spring_example.pojo.Vo.OrderVO;
public interface OrderService extends IService<OrderInfo> {
/**
* 创建订单
* @param orderDTO 订单信息
* @return 订单ID
*/
Long createOrder(OrderDTO orderDTO);
/**
* 分页查询订单列表
* @param page 页码
* @param size 每页条数
* @param userId 用户ID
* @param status 订单状态
* @return 订单列表
*/
Page<OrderListVO> getOrderPage(Integer page, Integer size, Long userId, Integer status);
/**
* 查询订单详情
* @param orderId 订单ID
* @param userId 用户ID
* @return 订单详情
*/
OrderVO getOrderDetail(Long orderId, Long userId);
/**
* 更新订单状态
* @param statusDTO 订单状态信息
*/
void updateOrderStatus(OrderStatusDTO statusDTO);
}

View File

@@ -0,0 +1,52 @@
// UserAddressService.java
package icu.sunway.ai_spring_example.Service;
import com.baomidou.mybatisplus.extension.service.IService;
import icu.sunway.ai_spring_example.pojo.Dto.UserAddressDTO;
import icu.sunway.ai_spring_example.pojo.Entity.UserAddress;
import java.util.List;
public interface UserAddressService extends IService<UserAddress> {
/**
* 添加用户地址
* @param addressDTO 地址信息
*/
void addAddress(UserAddressDTO addressDTO);
/**
* 更新用户地址
* @param addressDTO 地址信息
*/
void updateAddress(UserAddressDTO addressDTO);
/**
* 删除用户地址
* @param id 地址ID
* @param userId 用户ID
*/
void deleteAddress(Long id, Long userId);
/**
* 根据用户ID查询地址列表
* @param userId 用户ID
* @return 地址列表
*/
List<UserAddress> getAddressListByUserId(Long userId);
/**
* 根据地址ID查询地址详情
* @param id 地址ID
* @param userId 用户ID
* @return 地址详情
*/
UserAddress getAddressById(Long id, Long userId);
/**
* 设置默认地址
* @param id 地址ID
* @param userId 用户ID
*/
void setDefaultAddress(Long id, Long userId);
}

View File

@@ -0,0 +1,38 @@
// OrderDTO.java
package icu.sunway.ai_spring_example.pojo.Dto;
import lombok.Data;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
@Data
public class OrderDTO {
/**
* 用户ID
*/
@NotNull(message = "用户ID不能为空")
private Long userId;
/**
* 收货人姓名
*/
@NotBlank(message = "收货人姓名不能为空")
private String receiverName;
/**
* 收货人手机号
*/
@NotBlank(message = "收货人手机号不能为空")
private String receiverPhone;
/**
* 收货人地址
*/
@NotBlank(message = "收货人地址不能为空")
private String receiverAddress;
/**
* 支付方式 0-未支付 1-微信 2-支付宝
*/
private Integer payType = 0;
}

View File

@@ -0,0 +1,20 @@
// OrderStatusDTO.java
package icu.sunway.ai_spring_example.pojo.Dto;
import lombok.Data;
import jakarta.validation.constraints.NotNull;
@Data
public class OrderStatusDTO {
/**
* 订单ID
*/
@NotNull(message = "订单ID不能为空")
private Long orderId;
/**
* 订单状态 0-待付款 1-待发货 2-待收货 3-已完成 4-已取消
*/
@NotNull(message = "订单状态不能为空")
private Integer status;
}

View File

@@ -0,0 +1,34 @@
// UserAddressDTO.java
package icu.sunway.ai_spring_example.pojo.Dto;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
@Data
public class UserAddressDTO {
private Long id; // 地址ID新增时可不传修改时必传
@NotNull(message = "用户ID不能为空")
private Long userId; // 用户ID
@NotBlank(message = "收货人姓名不能为空")
private String receiverName; // 收货人姓名
@NotBlank(message = "收货人手机号不能为空")
private String receiverPhone; // 收货人手机号
@NotBlank(message = "省份不能为空")
private String province; // 省
@NotBlank(message = "城市不能为空")
private String city; // 市
@NotBlank(message = "区县不能为空")
private String district; // 区/县
@NotBlank(message = "详细地址不能为空")
private String detailAddress; // 详细地址
private Integer isDefault; // 是否默认0-非默认1-默认)
}

View File

@@ -7,7 +7,7 @@ import java.time.LocalDateTime;
/**
* 用户地址表实体类
*
* @author ZhiWei
* @author PuZhiWei
* @since 2025-12-17
*/
@Data

View File

@@ -0,0 +1,49 @@
// OrderListVO.java
package icu.sunway.ai_spring_example.pojo.Vo;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class OrderListVO {
/**
* 订单ID
*/
private Long id;
/**
* 订单编号
*/
private String orderNo;
/**
* 订单总金额
*/
private BigDecimal totalAmount;
/**
* 实付金额
*/
private BigDecimal payAmount;
/**
* 订单状态 0-待付款 1-待发货 2-待收货 3-已完成 4-已取消
*/
private Integer status;
/**
* 订单状态文本
*/
private String statusText;
/**
* 创建时间
*/
private LocalDateTime createTime;
/**
* 商品数量
*/
private Integer productCount;
}

View File

@@ -0,0 +1,71 @@
// OrderVO.java
package icu.sunway.ai_spring_example.pojo.Vo;
import icu.sunway.ai_spring_example.pojo.Entity.OrderItem;
import lombok.Data;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
@Data
public class OrderVO {
/**
* 订单ID
*/
private Long id;
/**
* 订单编号
*/
private String orderNo;
/**
* 用户ID
*/
private Long userId;
/**
* 订单总金额
*/
private BigDecimal totalAmount;
/**
* 实付金额
*/
private BigDecimal payAmount;
/**
* 运费
*/
private BigDecimal freightAmount;
/**
* 支付方式 0-未支付 1-微信 2-支付宝
*/
private Integer payType;
/**
* 订单状态 0-待付款 1-待发货 2-待收货 3-已完成 4-已取消
*/
private Integer status;
/**
* 收货人信息
*/
private String receiverName;
private String receiverPhone;
private String receiverAddress;
/**
* 时间信息
*/
private LocalDateTime payTime;
private LocalDateTime deliveryTime;
private LocalDateTime receiveTime;
private LocalDateTime createTime;
/**
* 订单项列表
*/
private List<OrderItem> orderItems;
}