From ff9d7626b5e376b7348621e6031e43c33308891e Mon Sep 17 00:00:00 2001 From: wdt <2134772300@qq.com> Date: Mon, 16 Dec 2024 17:19:29 +0800 Subject: [PATCH] w_sky_server --- .../java/com/sky/aspectj/AutoFillAspect.java | 97 +++++++ .../controller/admin/CategoryController.java | 134 +++++++++ .../sky/controller/admin/OrderController.java | 153 +++++++++++ .../controller/admin/WorkSpaceController.java | 94 +++++++ .../sky/controller/user/DishController.java | 75 +++++ .../user/ShoppingCartController.java | 99 +++++++ .../interceptor/JwtTokenUserInterceptor.java | 68 +++++ .../java/com/sky/mapper/EmployeeMapper.java | 59 ++++ .../java/com/sky/mapper/SetmealMapper.java | 116 ++++++++ .../java/com/sky/service/CommonService.java | 25 ++ .../java/com/sky/service/ReportService.java | 66 +++++ .../com/sky/service/WorkspaceService.java | 48 ++++ .../sky/service/impl/CategoryServiceImpl.java | 115 ++++++++ .../sky/service/impl/OrderServiceImpl.java | 260 ++++++++++++++++++ .../com/sky/service/impl/UserServiceImpl.java | 86 ++++++ 15 files changed, 1495 insertions(+) create mode 100644 sky/sky-server/src/main/java/com/sky/aspectj/AutoFillAspect.java create mode 100644 sky/sky-server/src/main/java/com/sky/controller/admin/CategoryController.java create mode 100644 sky/sky-server/src/main/java/com/sky/controller/admin/OrderController.java create mode 100644 sky/sky-server/src/main/java/com/sky/controller/admin/WorkSpaceController.java create mode 100644 sky/sky-server/src/main/java/com/sky/controller/user/DishController.java create mode 100644 sky/sky-server/src/main/java/com/sky/controller/user/ShoppingCartController.java create mode 100644 sky/sky-server/src/main/java/com/sky/interceptor/JwtTokenUserInterceptor.java create mode 100644 sky/sky-server/src/main/java/com/sky/mapper/EmployeeMapper.java create mode 100644 sky/sky-server/src/main/java/com/sky/mapper/SetmealMapper.java create mode 100644 sky/sky-server/src/main/java/com/sky/service/CommonService.java create mode 100644 sky/sky-server/src/main/java/com/sky/service/ReportService.java create mode 100644 sky/sky-server/src/main/java/com/sky/service/WorkspaceService.java create mode 100644 sky/sky-server/src/main/java/com/sky/service/impl/CategoryServiceImpl.java create mode 100644 sky/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java create mode 100644 sky/sky-server/src/main/java/com/sky/service/impl/UserServiceImpl.java diff --git a/sky/sky-server/src/main/java/com/sky/aspectj/AutoFillAspect.java b/sky/sky-server/src/main/java/com/sky/aspectj/AutoFillAspect.java new file mode 100644 index 0000000..3483f11 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/aspectj/AutoFillAspect.java @@ -0,0 +1,97 @@ +// 定义包名,表示该类属于com.sky.aspectj包 +package com.sky.aspectj; + +// 导入所需的类和接口 +import com.sky.annotation.AutoFill; +import com.sky.constant.AutoFillConstant; +import com.sky.context.BaseContext; +import com.sky.enumeration.OperationType; +import lombok.extern.slf4j.Slf4j; +import org.aspectj.lang.JoinPoint; +import org.aspectj.lang.Signature; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.lang.annotation.Before; +import org.aspectj.lang.annotation.Pointcut; +import org.aspectj.lang.reflect.MethodSignature; +import org.springframework.stereotype.Component; + +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.time.LocalDateTime; +import java.util.*; + +// 使用@Aspect注解声明一个切面 +@Aspect +// 使用@Slf4j注解为类自动注入一个日志对象 +@Slf4j +// 使用@Component注解声明一个Spring组件,使其可以被Spring容器管理 +@Component +public class AutoFillAspect { + + // 定义一个切入点,匹配所有标记了@AutoFill注解的com.sky.mapper包下的方法 + @Pointcut("@annotation(com.sky.annotation.AutoFill)" + "&& execution(* com.sky.mapper.*.*(..))") + public void pointCount() { + } + + // 前置通知,执行切入点匹配的方法之前 + @Before("pointCount()") + public void beforeAutoFillAspect(JoinPoint joinPoint) throws InvocationTargetException, IllegalAccessException { + // 获取方法签名 + MethodSignature signature = (MethodSignature) joinPoint.getSignature(); + // 获取当前执行的方法 + Method method = signature.getMethod(); + // 获取方法参数 + Object[] args = joinPoint.getArgs(); + // 获取方法上的@AutoFill注解 + AutoFill autoFill = method.getAnnotation(AutoFill.class); + // 从注解中获取操作类型 + OperationType value = autoFill.value(); + + // 存放每个参数对象及其所有方法的映射 + HashMap methodHashMap = new HashMap<>(); + // 遍历参数对象,获取每个对象的所有方法 + for (Object arg : args) { + Class argClass = arg.getClass(); + Method[] methods = argClass.getDeclaredMethods(); + methodHashMap.put(arg, methods); + } + + // 根据操作类型进行不同的字段填充 + if (value.equals(OperationType.INSERT)) { + // 插入操作,填充创建时间和创建用户 + for (Map.Entry entry : methodHashMap.entrySet()) { + Object key = entry.getKey(); + for (Method method1 : entry.getValue()) { + // 填充创建时间和更新时间 + if (method1.getName().equals(AutoFillConstant.SET_UPDATE_TIME) || method.getName().equals(AutoFillConstant.SET_CREATE_TIME)) { + method1.invoke(key, LocalDateTime.now()); + } + // 填充创建用户和更新用户 + if (method1.getName().equals(AutoFillConstant.SET_CREATE_USER) || method.getName().equals(AutoFillConstant.SET_UPDATE_USER)) { + method1.invoke(key, BaseContext.getCurrentId()); + } + } + } + } else if (value.equals(OperationType.UPDATE)) { + // 更新操作,填充更新时间和更新用户 + for (Map.Entry entry : methodHashMap.entrySet()) { + Object key = entry.getKey(); + for (Method method1 : entry.getValue()) { + // 填充更新时间 + if (method1.getName().equals(AutoFillConstant.SET_UPDATE_TIME)) { + method1.invoke(key, LocalDateTime.now()); + } + // 填充更新用户 + if (method1.getName().equals(AutoFillConstant.SET_UPDATE_USER)) { + method1.invoke(key, BaseContext.getCurrentId()); + } + } + } + } else { + // 非法操作类型,抛出异常 + throw new IllegalArgumentException("自动填充操作类型参数异常!"); + } + } + +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/admin/CategoryController.java b/sky/sky-server/src/main/java/com/sky/controller/admin/CategoryController.java new file mode 100644 index 0000000..75c8fec --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/admin/CategoryController.java @@ -0,0 +1,134 @@ +// 定义包名,表示该类属于com.sky.controller.admin包 +package com.sky.controller.admin; + +// 导入所需的类和接口 +import com.sky.dto.CategoryDTO; +import com.sky.dto.CategoryPageQueryDTO; +import com.sky.entity.Category; +import com.sky.result.PageResult; +import com.sky.result.Result; +import com.sky.service.CategoryService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +// 使用@RestController注解声明这是一个REST控制器,返回的数据会自动转换为JSON格式 +@RestController +// 使用@RequestMapping注解定义类级别的路由,所有的请求都会以"/admin/category"作为前缀 +@RequestMapping("/admin/category") +// 使用@Slf4j注解为类自动注入一个日志对象 +@Slf4j +// 使用@Api注解标记这个控制器属于哪个API分类 +@Api(tags = "分类相关接口") +public class CategoryController { + // 自动注入CategoryService服务 + @Autowired + CategoryService categoryService; + + /** + * 分类分页查询接口 + * + * @param categoryPageQueryDTO 分页查询参数 + * @return 分页查询结果 + */ + @GetMapping({"/page"}) + @ApiOperation("分类分页查询") + public Result pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) { + // 记录日志 + log.info("分类分页查询:{}", categoryPageQueryDTO); + // 调用服务层进行分页查询 + PageResult pageResult = categoryService.pageQuery(categoryPageQueryDTO); + // 返回查询结果 + return Result.success(pageResult); + } + + /** + * 根据类型查询分类接口 + * + * @param type 分类类型 + * @return 分类列表 + */ + @GetMapping("/list") + @ApiOperation("根据类型查询分类") + public Result query(Integer type) { + // 记录日志 + log.info("根据类型查询分类:{}", type); + // 调用服务层根据类型查询分类 + List result = categoryService.query(type); + // 返回查询结果 + return Result.success(result); + } + + /** + * 删除分类接口 + * + * @param id 要删除的分类ID + * @return 操作结果 + */ + @DeleteMapping + @ApiOperation("删除分类") + public Result deleteCategory(Long id) { + // 记录日志 + log.info("删除分类:{}", id); + // 调用服务层删除分类 + categoryService.delete(id); + // 返回操作结果 + return Result.success(); + } + + /** + * 修改分类接口 + * + * @param categoryDTO 包含修改信息的分类DTO + * @return 操作结果 + */ + @PutMapping + @ApiOperation("修改分类") + public Result updateCategory(@RequestBody CategoryDTO categoryDTO) { + // 记录日志 + log.info("修改分类:{}", categoryDTO); + // 调用服务层修改分类 + categoryService.updateCategory(categoryDTO); + // 返回操作结果 + return Result.success(); + } + + /** + * 启用或禁用分类接口 + * + * @param status 状态值,用于标识启用或禁用 + * @param id 要修改状态的分类ID + * @return 操作结果 + */ + @PostMapping("/status/{status}") + @ApiOperation("启用禁用分类") + public Result startOrStop(@PathVariable Integer status, Long id) { + // 记录日志 + log.info("启用禁用分类status:{},id:{}", status, id); + // 调用服务层启用或禁用分类 + categoryService.startOrStop(status, id); + // 返回操作结果 + return Result.success(); + } + + /** + * 新增分类接口 + * + * @param categoryDTO 包含新增信息的分类DTO + * @return 操作结果 + */ + @PostMapping + @ApiOperation("新增分类") + public Result save(@RequestBody CategoryDTO categoryDTO) { + // 记录日志 + log.info("新增分类:{}", categoryDTO); + // 调用服务层新增分类 + categoryService.save(categoryDTO); + // 返回操作结果 + return Result.success(); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/admin/OrderController.java b/sky/sky-server/src/main/java/com/sky/controller/admin/OrderController.java new file mode 100644 index 0000000..6bd0e08 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/admin/OrderController.java @@ -0,0 +1,153 @@ +// 定义包名,表示该类属于com.sky.controller.admin包 +package com.sky.controller.admin; + +// 导入所需的类和接口 +import com.sky.dto.OrdersCancelDTO; +import com.sky.dto.OrdersConfirmDTO; +import com.sky.dto.OrdersPageQueryDTO; +import com.sky.dto.OrdersRejectionDTO; +import com.sky.result.PageResult; +import com.sky.result.Result; +import com.sky.service.OrderService; +import com.sky.vo.OrderStatisticsVO; +import com.sky.vo.OrderVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +/** + * 订单管理控制器类,提供了一系列的接口用于订单管理。 + */ +@RestController("adminOrderController") +@RequestMapping("/admin/order") +@Slf4j +@Api(tags = "订单管理接口") +public class OrderController { + + // 自动注入OrderService服务 + @Autowired + private OrderService orderService; + + /** + * 完成订单接口 + * + * @param id 订单ID + * @return 操作结果 + */ + @PutMapping("/complete/{id}") + @ApiOperation("完成订单") + public Result complete(@PathVariable("id") Long id) { + // 调用服务层完成订单 + orderService.complete(id); + // 返回操作结果 + return Result.success(); + } + + /** + * 派送订单接口 + * + * @param id 订单ID + * @return 操作结果 + */ + @PutMapping("/delivery/{id}") + @ApiOperation("派送订单") + public Result delivery(@PathVariable("id") Long id) { + // 调用服务层派送订单 + orderService.delivery(id); + // 返回操作结果 + return Result.success(); + } + + /** + * 订单搜索接口 + * + * @param ordersPageQueryDTO 订单搜索参数 + * @return 订单搜索结果 + */ + @GetMapping("/conditionSearch") + @ApiOperation("订单搜索") + public Result conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) { + // 调用服务层进行订单搜索 + PageResult pageResult = orderService.conditionSearch(ordersPageQueryDTO); + // 返回搜索结果 + return Result.success(pageResult); + } + + /** + * 各个状态的订单数量统计接口 + * + * @return 订单数量统计结果 + */ + @GetMapping("/statistics") + @ApiOperation("各个状态的订单数量统计") + public Result statistics() { + // 调用服务层获取订单数量统计 + OrderStatisticsVO orderStatisticsVO = orderService.statistics(); + // 返回统计结果 + return Result.success(orderStatisticsVO); + } + + /** + * 查询订单详情接口 + * + * @param id 订单ID + * @return 订单详情 + */ + @GetMapping("/details/{id}") + @ApiOperation("查询订单详情") + public Result details(@PathVariable("id") Long id) { + // 调用服务层查询订单详情 + OrderVO orderVO = orderService.details(id); + // 返回订单详情 + return Result.success(orderVO); + } + + /** + * 接单接口 + * + * @param ordersConfirmDTO 接单参数 + * @return 操作结果 + */ + @PutMapping("/confirm") + @ApiOperation("接单") + public Result confirm(@RequestBody OrdersConfirmDTO ordersConfirmDTO) { + // 调用服务层接单 + orderService.confirm(ordersConfirmDTO); + // 返回操作结果 + return Result.success(); + } + + /** + * 拒单接口 + * + * @param ordersRejectionDTO 拒单参数 + * @return 操作结果 + * @throws Exception 可能抛出的异常 + */ + @PutMapping("/rejection") + @ApiOperation("拒单") + public Result rejection(@RequestBody OrdersRejectionDTO ordersRejectionDTO) throws Exception { + // 调用服务层拒单 + orderService.rejection(ordersRejectionDTO); + // 返回操作结果 + return Result.success(); + } + + /** + * 取消订单接口 + * + * @param ordersCancelDTO 取消订单参数 + * @return 操作结果 + * @throws Exception 可能抛出的异常 + */ + @PutMapping("/cancel") + @ApiOperation("取消订单") + public Result cancel(@RequestBody OrdersCancelDTO ordersCancelDTO) throws Exception { + // 调用服务层取消订单 + orderService.cancel(ordersCancelDTO); + // 返回操作结果 + return Result.success(); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/admin/WorkSpaceController.java b/sky/sky-server/src/main/java/com/sky/controller/admin/WorkSpaceController.java new file mode 100644 index 0000000..d3cb4ce --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/admin/WorkSpaceController.java @@ -0,0 +1,94 @@ +// 定义包名,表示该类属于com.sky.controller.admin包 +package com.sky.controller.admin; + +// 导入所需的类和接口 +import com.sky.result.Result; +import com.sky.service.WorkspaceService; +import com.sky.vo.BusinessDataVO; +import com.sky.vo.DishOverViewVO; +import com.sky.vo.OrderOverViewVO; +import com.sky.vo.SetmealOverViewVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import java.time.LocalDateTime; +import java.time.LocalTime; + +/** + * 工作台控制器类,提供了一系列的接口用于工作台数据的查询。 + */ +@RestController +@RequestMapping("/admin/workspace") +@Slf4j +@Api(tags = "工作台相关接口") +public class WorkSpaceController { + + // 自动注入WorkspaceService服务 + @Autowired + private WorkspaceService workspaceService; + + /** + * 工作台今日数据查询接口 + * + * @return 工作台今日数据视图对象 + */ + @GetMapping("/businessData") + @ApiOperation("工作台今日数据查询") + public Result businessData(){ + // 获得当天的开始时间(00:00:00) + LocalDateTime begin = LocalDateTime.now().with(LocalTime.MIN); + // 获得当天的结束时间(23:59:59) + LocalDateTime end = LocalDateTime.now().with(LocalTime.MAX); + + // 调用服务层获取工作台今日数据 + BusinessDataVO businessDataVO = workspaceService.getBusinessData(begin, end); + // 返回工作台今日数据 + return Result.success(businessDataVO); + } + + /** + * 查询订单管理数据接口 + * + * @return 订单管理数据视图对象 + */ + @GetMapping("/overviewOrders") + @ApiOperation("查询订单管理数据") + public Result orderOverView(){ + // 调用服务层获取订单管理数据 + OrderOverViewVO orderOverViewVO = workspaceService.getOrderOverView(); + // 返回订单管理数据 + return Result.success(orderOverViewVO); + } + + /** + * 查询菜品总览接口 + * + * @return 菜品总览视图对象 + */ + @GetMapping("/overviewDishes") + @ApiOperation("查询菜品总览") + public Result dishOverView(){ + // 调用服务层获取菜品总览数据 + DishOverViewVO dishOverViewVO = workspaceService.getDishOverView(); + // 返回菜品总览数据 + return Result.success(dishOverViewVO); + } + + /** + * 查询套餐总览接口 + * + * @return 套餐总览视图对象 + */ + @GetMapping("/overviewSetmeals") + @ApiOperation("查询套餐总览") + public Result setmealOverView(){ + // 调用服务层获取套餐总览数据 + SetmealOverViewVO setmealOverViewVO = workspaceService.getSetmealOverView(); + // 返回套餐总览数据 + return Result.success(setmealOverViewVO); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/user/DishController.java b/sky/sky-server/src/main/java/com/sky/controller/user/DishController.java new file mode 100644 index 0000000..d16cb35 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/user/DishController.java @@ -0,0 +1,75 @@ +// 定义包名,表示该类属于com.sky.controller.user包 +package com.sky.controller.user; + +// 导入所需的类和接口 +import com.sky.constant.StatusConstant; +import com.sky.entity.Dish; +import com.sky.result.Result; +import com.sky.service.DishService; +import com.sky.vo.DishVO; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.ValueOperations; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +// 使用@RestController注解声明这是一个REST控制器,返回的数据会自动转换为JSON格式 +@RestController("userDishController") +// 使用@RequestMapping注解定义类级别的路由,所有的请求都会以"/user/dish"作为前缀 +@RequestMapping("/user/dish") +// 使用@Slf4j注解为类自动注入一个日志对象 +@Slf4j +// 使用@Api注解标记这个控制器属于哪个API分类 +@Api(tags = "C端-菜品浏览接口") +public class DishController { + + // 自动注入DishService服务 + @Autowired + private DishService dishService; + + // 自动注入RedisTemplate,用于操作Redis缓存 + @Autowired + private RedisTemplate redisTemplate; + + /** + * 根据分类id查询菜品接口 + * + * @param categoryId 分类ID + * @return 菜品列表 + */ + @GetMapping("/list") + @ApiOperation("根据分类id查询菜品") + public Result> list(Long categoryId) { + // 记录日志,输出查询的分类ID + log.info("根据分类id查询菜品:{}", categoryId); + // 定义Redis缓存的键 + String key = "dish_" + categoryId; + + // 从缓存中获取菜品列表 + ValueOperations valueOperations = redisTemplate.opsForValue(); + List dishVOList = (List) valueOperations.get(key); + + // 如果缓存中存在菜品列表,直接返回 + if (dishVOList != null && dishVOList.size() > 0) { + return Result.success(dishVOList); + } + + // 如果缓存中不存在,则从数据库中查询 + Dish dish = new Dish(); + dish.setCategoryId(categoryId); // 设置查询条件为分类ID + dish.setStatus(StatusConstant.ENABLE); // 查询起售中的菜品 + + // 从数据库中获取菜品列表,并存入缓存 + List list = dishService.listWithFlavor(dish); + valueOperations.set(key, list); // 将查询结果存入Redis缓存 + + // 返回查询结果 + return Result.success(list); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/user/ShoppingCartController.java b/sky/sky-server/src/main/java/com/sky/controller/user/ShoppingCartController.java new file mode 100644 index 0000000..1d1e5eb --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/user/ShoppingCartController.java @@ -0,0 +1,99 @@ +// 定义包名,表示该类属于com.sky.controller.user包 +package com.sky.controller.user; + +// 导入所需的类和接口 +import com.sky.dto.ShoppingCartDTO; +import com.sky.entity.ShoppingCart; +import com.sky.result.Result; +import com.sky.service.ShoppingCartService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +// 使用@RestController注解声明这是一个REST控制器,返回的数据会自动转换为JSON格式 +@RestController +// 使用@Api注解标记这个控制器属于哪个API分类 +@Api("C端购物车相关接口") +// 使用@Slf4j注解为类自动注入一个日志对象 +@Slf4j +// 使用@RequestMapping注解定义类级别的路由,所有的请求都会以"/user/shoppingCart"作为前缀 +@RequestMapping("/user/shoppingCart") +public class ShoppingCartController { + // 自动注入ShoppingCartService服务 + @Autowired + ShoppingCartService shoppingCartService; + + /** + * 添加商品到购物车接口 + * + * @param shoppingCartDTO 包含商品信息的购物车DTO对象 + * @return 操作结果 + */ + @PostMapping("/add") + @ApiOperation("添加购物车") + public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO) { + // 记录日志,输出添加到购物车的商品信息 + log.info("添加购物车:购物车信息:{}", shoppingCartDTO); + + // 调用服务层添加商品到购物车 + shoppingCartService.add(shoppingCartDTO); + // 返回操作成功的结果 + return Result.success(); + } + + /** + * 查看用户购物车数据接口 + * + * @return 用户购物车中的商品列表 + */ + @GetMapping("/list") + @ApiOperation("查看购物车") + public Result> list() { + // 记录日志,标记查看购物车数据的操作 + log.info("查看购物车数据"); + + // 调用服务层获取用户购物车中的商品列表 + List shoppingCartList = shoppingCartService.list(); + // 返回购物车商品列表 + return Result.success(shoppingCartList); + } + + /** + * 删除购物车中的一个商品接口 + * + * @param shoppingCartDTO 包含商品信息的购物车DTO对象 + * @return 操作结果 + */ + @PostMapping("/sub") + @ApiOperation("删除购物车中的商品") + public Result delete(@RequestBody ShoppingCartDTO shoppingCartDTO){ + // 记录日志,输出删除的商品信息 + log.info("删除购物车中的商品:{}",shoppingCartDTO); + // 调用服务层删除购物车中的一个商品 + shoppingCartService.delete(shoppingCartDTO); + + // 返回操作成功的结果 + return Result.success(); + } + + /** + * 清空购物车接口 + * + * @return 操作结果 + */ + @DeleteMapping("/clean") + @ApiOperation("清空购物车") + public Result clean(){ + // 记录日志,标记清空购物车的操作 + log.info("清空购物车"); + // 调用服务层清空购物车 + shoppingCartService.clean(); + + // 返回操作成功的结果 + return Result.success(); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/interceptor/JwtTokenUserInterceptor.java b/sky/sky-server/src/main/java/com/sky/interceptor/JwtTokenUserInterceptor.java new file mode 100644 index 0000000..29a11fc --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/interceptor/JwtTokenUserInterceptor.java @@ -0,0 +1,68 @@ +// 定义包名,表示该类属于com.sky.interceptor包 +package com.sky.interceptor; + +// 导入所需的类和接口 +import com.sky.constant.JwtClaimsConstant; +import com.sky.constant.MessageConstant; +import com.sky.context.BaseContext; +import com.sky.properties.JwtProperties; +import com.sky.utils.JwtUtil; +import io.jsonwebtoken.Claims; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.HandlerInterceptor; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +/** + * JWT令牌校验的拦截器,用于在Spring MVC应用中拦截请求并验证JWT令牌的有效性。 + */ +@Component +@Slf4j +public class JwtTokenUserInterceptor implements HandlerInterceptor { + + // 自动注入JwtProperties,用于获取JWT配置属性 + @Autowired + private JwtProperties jwtProperties; + + /** + * preHandle方法在请求处理之前进行调用,除非抛出异常,否则总是被调用。 + * + * @param request 当前请求对象 + * @param response 当前响应对象 + * @param handler HandlerMethod对象,如果当前拦截的是Controller的方法,则handler是非空的 + * @return true表示继续流程(如调用下一个拦截器或处理器);返回false表示流程中断,返回false后,不会继续调用其他的拦截器或处理器,此时需要通过response向客户返回响应内容 + * @throws Exception 可能抛出的异常 + */ + public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){ + // 判断当前拦截到的是Controller的方法还是其他资源 + if (!(handler instanceof HandlerMethod)) { + // 当前拦截到的不是动态方法,直接放行 + return true; + } + HandlerMethod handlerMethod= (HandlerMethod) handler; + // 1、从请求头中获取令牌 + String token = request.getHeader(jwtProperties.getUserTokenName()); + + // 2、校验令牌 + try { + log.info("jwt校验:{}", token); + // 使用JwtUtil解析JWT令牌 + Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token); + // 从claims中获取用户ID,并设置到BaseContext中,供后续使用 + Long empId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString()); + BaseContext.setCurrentId(empId); + log.info("当前用户id:{}", empId); + // 3、通过,放行 + return true; + } catch (Exception ex) { + // 4、不通过,响应401状态码 + log.error(MessageConstant.USER_NOT_LOGIN); + response.setStatus(401); + return false; + } + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/mapper/EmployeeMapper.java b/sky/sky-server/src/main/java/com/sky/mapper/EmployeeMapper.java new file mode 100644 index 0000000..3cc3b42 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/mapper/EmployeeMapper.java @@ -0,0 +1,59 @@ +// 定义包名,表示该类属于com.sky.mapper包 +package com.sky.mapper; + +// 导入所需的类和注解 +import com.github.pagehelper.Page; +import com.sky.annotation.AutoFill; +import com.sky.dto.EmployeePageQueryDTO; +import com.sky.entity.Employee; +import com.sky.enumeration.OperationType; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +// 使用@Mapper注解标记这是一个MyBatis的Mapper接口 +@Mapper +public interface EmployeeMapper { + + /** + * 根据用户名查询员工信息 + * + * @param username 用户名 + * @return 返回匹配的员工对象 + */ + @Select("select * from employee where username = #{username}") + Employee getByUsername(String username); + + /** + * 插入员工数据,并自动填充创建相关的字段(如创建时间和创建用户等) + * + * @param employee 员工对象,包含要插入的数据 + */ + @AutoFill(OperationType.INSERT) + @Insert("insert into employee(name,username,password,phone,sex,id_number,create_time,update_time,create_user,update_user,status)" + + " values(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})") + void save(Employee employee); + + /** + * 分页查询员工数据 + * + * @param employeePageQueryDTO 分页查询参数 + * @return 返回分页包装的员工对象列表 + */ + Page pageQuery(EmployeePageQueryDTO employeePageQueryDTO); + + /** + * 更新员工信息,并自动填充更新相关的字段(如更新时间和更新用户等) + */ + @AutoFill(OperationType.UPDATE) + void update(Employee employee); + + /** + * 通过id查询员工信息 + * + * @param id 员工的ID + * @return 返回匹配的员工对象 + */ + @Select("select * from employee where id=#{id}") + Employee getById(Long id); +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/mapper/SetmealMapper.java b/sky/sky-server/src/main/java/com/sky/mapper/SetmealMapper.java new file mode 100644 index 0000000..aa63ee6 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/mapper/SetmealMapper.java @@ -0,0 +1,116 @@ +// 定义包名,表示该类属于com.sky.mapper包 +package com.sky.mapper; + +// 导入所需的类和注解 +import com.github.pagehelper.Page; +import com.sky.annotation.AutoFill; +import com.sky.dto.SetmealDTO; +import com.sky.entity.SetmealDish; +import com.sky.enumeration.OperationType; +import com.sky.dto.SetmealPageQueryDTO; +import com.sky.entity.Setmeal; +import com.sky.vo.DishItemVO; +import com.sky.vo.SetmealVO; +import org.apache.ibatis.annotations.Delete; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +// 使用@Mapper注解标记这是一个MyBatis的Mapper接口 +@Mapper +public interface SetmealMapper { + + /** + * 根据条件统计套餐数量 + * + * @param map 条件参数 + * @return 返回套餐数量 + */ + Integer countByMap(Map map); + + /** + * 动态条件查询套餐 + * + * @param setmeal 套餐对象,包含查询条件 + * @return 返回套餐列表 + */ + List list(Setmeal setmeal); + + /** + * 根据套餐id查询该套餐的菜品 + * + * @param setmealId 套餐ID + * @return 返回套餐包含的菜品项视图对象列表 + */ + @Select("select sd.name, sd.copies, d.image, d.description " + + "from setmeal_dish sd left join dish d on sd.dish_id = d.id " + + "where sd.setmeal_id = #{setmealId}") + List getDishItemBySetmealId(Long setmealId); + + /** + * 分页查询套餐 + * + * @param setmealPageQueryDTO 分页查询参数 + * @return 返回分页包装的套餐对象列表 + */ + Page pageQuery(SetmealPageQueryDTO setmealPageQueryDTO); + + /** + * 更新套餐信息,并自动填充更新相关的字段(如更新时间和更新用户等) + * + * @param setmeal 套餐对象,包含要更新的数据 + */ + @AutoFill(OperationType.UPDATE) + void updateSetmeal(Setmeal setmeal); + + /** + * 根据套餐id删除绑定在套餐上的菜品 + * + * @param id 套餐ID + */ + @Delete("delete from setmeal_dish where setmeal_id=#{id}") + void deleteSetmealDish(Long id); + + /** + * 批量插入套餐绑定的菜品 + * + * @param setmealDishes 套餐菜品绑定关系列表 + */ + void insertBatchSetmealDish(List setmealDishes); + + /** + * 根据套餐id获取套餐 + * + * @param id 套餐ID + * @return 返回套餐对象 + */ + @Select("select * from setmeal where id=#{id}") + Setmeal getBySetmealId(Long id); + + /** + * 根据套餐id获取套餐菜品绑定关系 + * + * @param id 套餐ID + * @return 返回套餐菜品绑定关系列表 + */ + @Select("select * from setmeal_dish where setmeal_id=#{id}") + List getSetmealDishById(Long id); + + /** + * 根据套餐id批量删除套餐 + * + * @param ids 套餐ID列表 + */ + void batchDeleteSetmeal(ArrayList ids); + + /** + * 插入套餐信息,并自动填充创建相关的字段(如创建时间和创建用户等) + * + * @param setmeal 套餐对象,包含要插入的数据 + */ + @AutoFill(OperationType.INSERT) + void insertSetmeal(Setmeal setmeal); +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/CommonService.java b/sky/sky-server/src/main/java/com/sky/service/CommonService.java new file mode 100644 index 0000000..a231602 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/CommonService.java @@ -0,0 +1,25 @@ +// 定义一个名为com.sky.service的包,用于存放服务相关的类和接口 +package com.sky.service; + +// 导入Spring框架中的@Service注解,用于声明一个服务组件 +import org.springframework.stereotype.Service; +// 导入MultipartFile接口,用于处理上传的文件 +import org.springframework.web.multipart.MultipartFile; + +// 导入Java的IOException类,用于处理可能发生的IO异常 +import java.io.IOException; + +// 使用@Service注解标记这个接口,表明它是一个Spring管理的服务组件 +@Service +// 声明一个名为CommonService的接口 +public interface CommonService { + + /** + * 上传文件的方法。 + * + * @param file 要上传的文件对象,类型为MultipartFile,它包含了文件的二进制数据以及文件的元数据(如文件名、文件大小等)。 + * @return 一个字符串,表示上传操作的结果,可能是文件的存储路径或者上传成功的确认信息。 + * @throws IOException 如果在文件上传过程中发生IO异常,则抛出IOException。 + */ + String upload(MultipartFile file) throws IOException; +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/ReportService.java b/sky/sky-server/src/main/java/com/sky/service/ReportService.java new file mode 100644 index 0000000..0d31727 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/ReportService.java @@ -0,0 +1,66 @@ +// 定义一个名为com.sky.service的包,用于存放服务相关的类和接口 +package com.sky.service; + +// 导入com.sky.result.Result类,用于封装方法的返回结果 +import com.sky.result.Result; +// 导入com.sky.vo包下的各种VO(Value Object)类,这些类用于封装数据传输对象 +import com.sky.vo.*; +// 导入org.apache.http.HttpResponse类,用于处理HTTP响应 +import org.apache.http.HttpResponse; +// 导入org.apache.poi.openxml4j.exceptions.InvalidFormatException类,用于处理Excel文件格式无效的异常 +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; + +import javax.servlet.http.HttpServletResponse; // 导入HttpServletResponse类,用于处理HTTP响应 +import java.io.FileNotFoundException; // 导入FileNotFoundException类,用于处理文件未找到的异常 +import java.io.IOException; // 导入IOException类,用于处理IO异常 +import java.time.LocalDate; // 导入LocalDate类,用于表示没有时间的日期 +import java.time.LocalDateTime; // 导入LocalDateTime类,用于表示日期和时间 + +// 声明一个名为ReportService的接口 +public interface ReportService { + + /** + * 统计营业额的方法。 + * + * @param begin 开始日期,类型为LocalDate,表示统计的起始日期。 + * @param end 结束日期,类型为LocalDate,表示统计的结束日期。 + * @return 返回一个Result对象,其中包含TurnoverReportVO类型的数据,VO中封装了营业额统计的相关信息。 + */ + Result getTurnoverStatistics(LocalDate begin, LocalDate end); + + /** + * 用户统计的方法。 + * + * @param begin 开始日期,类型为LocalDate,表示统计的起始日期。 + * @param end 结束日期,类型为LocalDate,表示统计的结束日期。 + * @return 返回一个UserReportVO对象,其中封装了用户统计的相关信息。 + */ + UserReportVO userStatistics(LocalDate begin, LocalDate end); + + /** + * 订单统计的方法。 + * + * @param begin 开始日期,类型为LocalDate,表示统计的起始日期。 + * @param end 结束日期,类型为LocalDate,表示统计的结束日期。 + * @return 返回一个OrderReportVO对象,其中封装了订单统计的相关信息。 + */ + OrderReportVO orderStatistics(LocalDate begin, LocalDate end); + + /** + * 获取销量排行前十的方法。 + * + * @param begin 开始日期,类型为LocalDate,表示统计的起始日期。 + * @param end 结束日期,类型为LocalDate,表示统计的结束日期。 + * @return 返回一个SalesTop10ReportVO对象,其中封装了销量排行前十的相关信息。 + */ + SalesTop10ReportVO salesTop10Report(LocalDate begin, LocalDate end); + + /** + * 导出excel表格的方法。 + * + * @param httpResponse HttpServletResponse对象,用于将生成的Excel文件写入HTTP响应中,以便客户端下载。 + * @throws IOException 如果在文件导出过程中发生IO异常,则抛出IOException。 + * @throws InvalidFormatException 如果生成的Excel文件格式无效,则抛出InvalidFormatException。 + */ + void export(HttpServletResponse httpResponse) throws IOException, InvalidFormatException; +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/WorkspaceService.java b/sky/sky-server/src/main/java/com/sky/service/WorkspaceService.java new file mode 100644 index 0000000..52901fd --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/WorkspaceService.java @@ -0,0 +1,48 @@ +// 定义一个名为com.sky.service的包,用于存放服务相关的类和接口 +package com.sky.service; + +// 导入com.sky.vo包下的BusinessDataVO类,用于封装业务数据 +import com.sky.vo.BusinessDataVO; +// 导入com.sky.vo包下的DishOverViewVO类,用于封装菜品总览数据 +import com.sky.vo.DishOverViewVO; +// 导入com.sky.vo包下的OrderOverViewVO类,用于封装订单总览数据 +import com.sky.vo.OrderOverViewVO; +// 导入com.sky.vo包下的SetmealOverViewVO类,用于封装套餐总览数据 +import com.sky.vo.SetmealOverViewVO; +// 导入java.time.LocalDateTime类,用于表示日期和时间 +import java.time.LocalDateTime; + +// 声明一个名为WorkspaceService的接口 +public interface WorkspaceService { + + /** + * 根据时间段统计营业数据的方法。 + * + * @param begin 开始时间,类型为LocalDateTime,表示统计的起始时间点。 + * @param end 结束时间,类型为LocalDateTime,表示统计的结束时间点。 + * @return 返回一个BusinessDataVO对象,其中封装了根据时间段统计的营业数据。 + */ + BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end); + + /** + * 查询订单管理数据的方法。 + * + * @return 返回一个OrderOverViewVO对象,其中封装了订单管理的总览数据。 + */ + OrderOverViewVO getOrderOverView(); + + /** + * 查询菜品总览的方法。 + * + * @return 返回一个DishOverViewVO对象,其中封装了菜品的总览数据。 + */ + DishOverViewVO getDishOverView(); + + /** + * 查询套餐总览的方法。 + * + * @return 返回一个SetmealOverViewVO对象,其中封装了套餐的总览数据。 + */ + SetmealOverViewVO getSetmealOverView(); + +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/impl/CategoryServiceImpl.java b/sky/sky-server/src/main/java/com/sky/service/impl/CategoryServiceImpl.java new file mode 100644 index 0000000..797015f --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/impl/CategoryServiceImpl.java @@ -0,0 +1,115 @@ +// 定义包名,表示该类属于com.sky.service.impl包 +package com.sky.service.impl; + +// 导入所需的类和接口 +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import com.sky.constant.StatusConstant; +import com.sky.dto.CategoryDTO; +import com.sky.dto.CategoryPageQueryDTO; +import com.sky.entity.Category; +import com.sky.mapper.CategoryMapper; +import com.sky.result.PageResult; +import com.sky.service.CategoryService; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +// 使用@Service注解标记这是一个Spring服务组件 +@Service +public class CategoryServiceImpl implements CategoryService { + // 自动注入CategoryMapper + @Autowired + CategoryMapper categoryMapper; + + /** + * 分类分页查询 + * + * @param categoryPageQueryDTO 分页查询参数 + * @return 分页查询结果 + */ + public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) { + PageResult pageResult = new PageResult(); + // 使用PageHelper开始分页查询 + PageHelper.startPage(categoryPageQueryDTO.getPage(), categoryPageQueryDTO.getPageSize()); + // 调用mapper进行分页查询 + Page pageQuery = categoryMapper.pageQuery(categoryPageQueryDTO); + // 设置查询结果和总记录数 + pageResult.setRecords(pageQuery.getResult()); + pageResult.setTotal(pageQuery.getTotal()); + + return pageResult; + } + + /** + * 根据分类类型查询分类 + * + * @param type 分类类型 + * @return 分类列表 + */ + public List query(Integer type) { + ArrayList result; + CategoryDTO categoryDTO = new CategoryDTO(); + categoryDTO.setType(type); + // 调用mapper查询分类 + result = (ArrayList) categoryMapper.query(categoryDTO); + + return result; + } + + /** + * 删除分类 + * + * @param id 要删除的分类ID + */ + public void delete(Long id) { + // 调用mapper删除分类 + categoryMapper.delete(id); + } + + /** + * 修改分类 + * + * @param categoryDTO 包含修改信息的分类DTO + */ + public void updateCategory(CategoryDTO categoryDTO) { + Category category = new Category(); + // 使用BeanUtils复制属性 + BeanUtils.copyProperties(categoryDTO, category); + // 调用mapper更新分类 + categoryMapper.updateCategory(category); + } + + /** + * 启用或禁用分类 + * + * @param status 状态值 + * @param id 分类ID + */ + public void startOrStop(Integer status, Long id) { + Category category = Category.builder() + .status(status) + .id(id) + .build(); + // 调用mapper更新分类状态 + categoryMapper.updateCategory(category); + } + + /** + * 新增分类 + * + * @param categoryDTO 包含新增信息的分类DTO + */ + public void save(CategoryDTO categoryDTO) { + Category category = new Category(); + // 使用BeanUtils复制属性 + BeanUtils.copyProperties(categoryDTO, category); + // 设置分类状态为禁用 + category.setStatus(StatusConstant.DISABLE); + // 调用mapper保存分类 + categoryMapper.save(category); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java b/sky/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java new file mode 100644 index 0000000..e4f6e90 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/impl/OrderServiceImpl.java @@ -0,0 +1,260 @@ +// 定义包名,表示该类属于com.sky.service.impl包 +package com.sky.service.impl; + +// 导入所需的类和接口 +import com.alibaba.druid.support.json.JSONUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.github.pagehelper.Page; +import com.github.pagehelper.PageHelper; +import com.sky.constant.MessageConstant; +import com.sky.context.BaseContext; +import com.sky.dto.*; +import com.sky.entity.*; +import com.sky.exception.AddressBookBusinessException; +import com.sky.exception.OrderBusinessException; +import com.sky.exception.ShoppingCartBusinessException; +import com.sky.mapper.*; +import com.sky.result.PageResult; +import com.sky.service.OrderService; +import com.sky.utils.WeChatPayUtil; +import com.sky.vo.OrderPaymentVO; +import com.sky.vo.OrderStatisticsVO; +import com.sky.vo.OrderSubmitVO; +import com.sky.vo.OrderVO; +import com.sky.webSocket.WebSocketServer; +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.util.CollectionUtils; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +// 使用@Service注解标记这是一个Spring服务组件 +@Service +public class OrderServiceImpl implements OrderService { + // 自动注入OrderMapper + @Autowired + private OrderMapper orderMapper; + // 自动注入OrderDetailMapper + @Autowired + private OrderDetailMapper orderDetailMapper; + // 自动注入AddressBookMapper + @Autowired + private AddressBookMapper addressBookMapper; + // 自动注入ShoppingCartMapper + @Autowired + private ShoppingCartMapper shoppingCartMapper; + // 自动注入UserMapper + @Autowired + private UserMapper userMapper; + // 自动注入WeChatPayUtil + @Autowired + private WeChatPayUtil weChatPayUtil; + // 自动注入WebSocketServer + @Autowired + private WebSocketServer webSocketServer; + + /** + * 完成订单 + * + * @param id 订单ID + */ + public void complete(Long id) { + // 根据id查询订单 + Orders ordersDB = orderMapper.getById(id); + + // 校验订单是否存在,并且状态为派送中 + if (ordersDB == null || !ordersDB.getStatus().equals(Orders.DELIVERY_IN_PROGRESS)) { + throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR); + } + + Orders orders = new Orders(); + orders.setId(ordersDB.getId()); + // 更新订单状态,状态转为完成 + orders.setStatus(Orders.COMPLETED); + orders.setDeliveryTime(LocalDateTime.now()); + + orderMapper.update(orders); + } + + /** + * 派送订单 + * + * @param id 订单ID + */ + public void delivery(Long id) { + // 根据id查询订单 + Orders ordersDB = orderMapper.getById(id); + + // 校验订单是否存在,并且状态为已接单 + if (ordersDB == null || !ordersDB.getStatus().equals(Orders.CONFIRMED)) { + throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR); + } + + Orders orders = new Orders(); + orders.setId(ordersDB.getId()); + // 更新订单状态,状态转为派送中 + orders.setStatus(Orders.DELIVERY_IN_PROGRESS); + + orderMapper.update(orders); + } + + /** + * 取消订单 + * + * @param ordersCancelDTO 包含取消订单信息的DTO + */ + public void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception { + // 根据id查询订单 + Orders ordersDB = orderMapper.getById(ordersCancelDTO.getId()); + + // 支付状态 + Integer payStatus = ordersDB.getPayStatus(); + if (payStatus == 1) { + // 用户已支付,需要退款 + // 调用微信支付退款接口 + // String refund = weChatPayUtil.refund( + // ordersDB.getNumber(), + // ordersDB.getNumber(), + // new BigDecimal(0.01), + // new BigDecimal(0.01)); + } + + // 管理端取消订单需要退款,根据订单id更新订单状态、取消原因、取消时间 + Orders orders = new Orders(); + orders.setId(ordersCancelDTO.getId()); + orders.setStatus(Orders.CANCELLED); + orders.setCancelReason(ordersCancelDTO.getCancelReason()); + orders.setCancelTime(LocalDateTime.now()); + orderMapper.update(orders); + } + + /** + * 拒单 + * + * @param ordersRejectionDTO 包含拒单信息的DTO + */ + public void rejection(OrdersRejectionDTO ordersRejectionDTO) throws Exception { + // 根据id查询订单 + Orders ordersDB = orderMapper.getById(ordersRejectionDTO.getId()); + + // 订单只有存在且状态为待接单才可以拒单 + if (ordersDB == null || !ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) { + throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR); + } + + // 支付状态 + Integer payStatus = ordersDB.getPayStatus(); + if (Objects.equals(payStatus, Orders.PAID)) { + // 用户已支付,需要退款 + // 调用微信支付退款接口 + // String refund = weChatPayUtil.refund( + // ordersDB.getNumber(), + // ordersDB.getNumber(), + // new BigDecimal(0.01), + // new BigDecimal(0.01)); + } + + // 拒单需要退款,根据订单id更新订单状态、拒单原因、取消时间 + Orders orders = new Orders(); + orders.setId(ordersDB.getId()); + orders.setStatus(Orders.CANCELLED); + orders.setRejectionReason(ordersRejectionDTO.getRejectionReason()); + orders.setCancelTime(LocalDateTime.now()); + + orderMapper.update(orders); + } + + /** + * 接单 + * + * @param ordersConfirmDTO 包含接单信息的DTO + */ + public void confirm(OrdersConfirmDTO ordersConfirmDTO) { + Orders orders = Orders.builder() + .id(ordersConfirmDTO.getId()) + .status(Orders.CONFIRMED) + .build(); + + orderMapper.update(orders); + } + + /** + * 各个状态的订单数量统计 + * + * @return 订单统计视图对象 + */ + public OrderStatisticsVO statistics() { + // 根据状态,分别查询出待接单、待派送、派送中的订单数量 + Integer toBeConfirmed = orderMapper.countStatus(Orders.TO_BE_CONFIRMED); + Integer confirmed = orderMapper.countStatus(Orders.CONFIRMED); + Integer deliveryInProgress = orderMapper.countStatus(Orders.DELIVERY_IN_PROGRESS); + + // 将查询出的数据封装到orderStatisticsVO中响应 + OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO(); + orderStatisticsVO.setToBeConfirmed(toBeConfirmed); + orderStatisticsVO.setConfirmed(confirmed); + orderStatisticsVO.setDeliveryInProgress(deliveryInProgress); + return orderStatisticsVO; + } + + /** + * 订单搜索 + * + * @param ordersPageQueryDTO 分页查询参数 + * @return 分页查询结果 + */ + public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) { + PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize()); + + Page page = orderMapper.pageQuery(ordersPageQueryDTO); + + // 部分订单状态,需要额外返回订单菜品信息,将Orders转化为OrderVO + List orderVOList = getOrderVOList(page); + + return new PageResult(page.getTotal(), orderVOList); + } + + private List getOrderVOList(Page page) { + // 需要返回订单菜品信息,自定义OrderVO响应结果 + List orderVOList = new ArrayList<>(); + + List ordersList = page.getResult(); + if (!CollectionUtils.isEmpty(ordersList)) { + for (Orders orders : ordersList) { + // 将共同字段复制到OrderVO + OrderVO orderVO = new OrderVO(); + BeanUtils.copyProperties(orders, orderVO); + String orderDishes = getOrderDishesStr(orders); + + // 将订单菜品信息封装到orderVO中,并添加到orderVOList + orderVO.setOrderDishes(orderDishes); + orderVOList.add(orderVO); + } + } + return orderVOList; + } + + /** + * 根据订单id获取菜品信息字符串 + * + * @param orders 订单对象 + * @return 订单菜品信息字符串 + */ + private String getOrderDishesStr(Orders orders) { + // 查询订单菜品详情信息(订单中的菜品和数量) + List orderDetailList = orderDetailMapper.getByOrderId(orders.getId()); + + // 将每一条订单菜品信息拼接为字符串(格式:宫保鸡丁*3;) + List orderDishList = orderDetailList.stream().map(x -> { + String orderDish = x.getName() + "*" + x.getNumber() + ";"; + return orderDish; + }).collect \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/impl/UserServiceImpl.java b/sky/sky-server/src/main/java/com/sky/service/impl/UserServiceImpl.java new file mode 100644 index 0000000..d92c003 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/impl/UserServiceImpl.java @@ -0,0 +1,86 @@ +// 定义包名,表示该类属于com.sky.service.impl包 +package com.sky.service.impl; + +// 导入所需的类和接口 +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import com.sky.constant.MessageConstant; +import com.sky.dto.UserLoginDTO; +import com.sky.entity.User; +import com.sky.exception.LoginFailedException; +import com.sky.mapper.UserMapper; +import com.sky.properties.WeChatProperties; +import com.sky.service.UserService; +import com.sky.utils.HttpClientUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.Map; + +// 使用@Service注解标记这是一个Spring服务组件 +@Service +public class UserServiceImpl implements UserService { + + // 自动注入UserMapper + @Autowired + UserMapper userMapper; + // 自动注入WeChatProperties + @Autowired + WeChatProperties weChatProperties; + + // 微信登录接口的URL + private static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session"; + + /** + * 微信登录 + * + * @param userLoginDTO 包含登录信息的DTO + * @return 用户对象 + */ + public User wxLogin(UserLoginDTO userLoginDTO) { + // 通过code获取openid + String openid = getOpenid(userLoginDTO.getCode()); + + // 判断openid是否存在 + if (openid == null || openid.equals("")) { + throw new LoginFailedException(MessageConstant.LOGIN_FAILED); + } + // 当前用户为新用户,完成自动注册 + User user = userMapper.getByOpenId(openid); + if (user == null) { + // 创建新用户对象 + user = User.builder() + .openid(openid) + .createTime(LocalDateTime.now()).build(); + // 插入新用户到数据库 + userMapper.insertUser(user); + } + return user; + } + + /** + * 通过code获取openid + * + * @param code 微信登录code + * @return openid字符串 + */ + private String getOpenid(String code) { + // 参数映射 + Map paramMap = new HashMap<>(); + paramMap.put("appid", weChatProperties.getAppid()); + paramMap.put("secret", weChatProperties.getSecret()); + paramMap.put("js_code", code); + paramMap.put("grant_type", "authorization_code"); + // 发起HTTP GET请求 + String result = HttpClientUtil.doGet(WX_LOGIN, paramMap); + + // 获取请求结果 + JSONObject jsonObject = JSON.parseObject(result); + // 从结果中获取openid + String openid = jsonObject.getString("openid"); + + return openid; + } +} \ No newline at end of file