Compare commits

..

5 Commits

@ -1,10 +0,0 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Zeppelin 忽略的文件
/ZeppelinRemoteNotebooks/

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="springcache-demo" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="springcache-demo" options="-parameters" />
</option>
</component>
</project>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
</component>
</project>

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://repo.maven.apache.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
</component>
</project>

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK" />
</project>

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$/.." vcs="Git" />
</component>
</project>

@ -1,115 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 定义Maven项目对象模型POM的根元素遵循Maven 4.0.0规范 -->
<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">
<!-- 指定POM的版本为4.0.0 -->
<modelVersion>4.0.0</modelVersion>
<!-- 继承父项目 -->
<parent>
<!-- 指定父项目的groupId、artifactId和version -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.7.3</version>
<!-- 相对路径这里为空表示查找父POM时不使用相对路径 -->
<relativePath/>
</parent>
<!-- 定义项目的groupId、artifactId和version -->
<groupId>com.itheima</groupId>
<artifactId>springcache-demo</artifactId>
<version>1.0-SNAPSHOT</version>
<!-- 定义项目属性 -->
<properties>
<!-- 设置编译的Java版本为11 -->
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
<!-- 定义项目依赖 -->
<dependencies>
<!-- Spring Boot Web启动器依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>compile</scope>
</dependency>
<!-- Lombok依赖用于简化Java对象的getter、setter等方法的编写 -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<!-- Alibaba Fastjson依赖用于JSON处理 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.76</version>
</dependency>
<!-- Apache Commons Lang依赖提供一些常用的工具类 -->
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
<!-- Spring Boot缓存启动器依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Spring Boot Redis启动器依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- MySQL JDBC驱动依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!-- MyBatis Spring Boot启动器依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<!-- Druid Spring Boot启动器依赖用于数据库连接池 -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.2.1</version>
</dependency>
<!-- Knife4j Spring Boot启动器依赖用于API文档生成 -->
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
<version>3.0.2</version>
</dependency>
<!-- Spring Boot测试启动器依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
</dependencies>
<!-- 构建配置 -->
<build>
<!-- 定义Maven插件 -->
<plugins>
<!-- Spring Boot Maven插件用于打包Spring Boot应用 -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.7.3</version>
</plugin>
</plugins>
</build>
</project>

@ -1,14 +0,0 @@
-- 如果存在名为`user`的表,则删除它
DROP TABLE IF EXISTS `user`;
-- 创建一个名为`user`的新表
CREATE TABLE `user` (
-- 定义一个名为`id`的列类型为bigint不允许为空并且自增
`id` bigint NOT NULL AUTO_INCREMENT,
-- 定义一个名为`name`的列类型为varchar(45),允许为空
`name` varchar(45) DEFAULT NULL,
-- 定义一个名为`age`的列类型为int允许为空
`age` int DEFAULT NULL,
-- 将`id`列设置为表的主键
PRIMARY KEY (`id`)
);

@ -1,27 +0,0 @@
// 定义包名
package com.itheima;
// 导入lombok提供的@Slf4j注解用于日志记录
import lombok.extern.slf4j.Slf4j;
// 导入SpringApplication类用于启动Spring Boot应用
import org.springframework.boot.SpringApplication;
// 导入SpringBootApplication注解标识这是一个Spring Boot应用
import org.springframework.boot.autoconfigure.SpringBootApplication;
// 导入EnableCaching注解用于开启缓存支持
import org.springframework.cache.annotation.EnableCaching;
// 使用@Slf4j注解自动注入日志对象
@Slf4j
// 使用@SpringBootApplication注解标识这是一个Spring Boot自动配置的应用
@SpringBootApplication
// 使用@EnableCaching注解开启缓存功能
@EnableCaching
public class CacheDemoApplication {
// 定义main方法作为程序的入口点
public static void main(String[] args) {
// 调用SpringApplication的run方法启动Spring Boot应用
SpringApplication.run(CacheDemoApplication.class, args);
// 使用注入的日志对象记录项目启动成功的信息
log.info("项目启动成功...");
}
}

@ -1,53 +0,0 @@
package com.itheima.config;
import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
/**
*
* @return
*/
@Bean
public Docket docket(){
log.info("准备生成接口文档...");
ApiInfo apiInfo = new ApiInfoBuilder()
.title("接口文档")
.version("2.0")
.description("接口文档")
.build();
Docket docket = new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo)
.select()
//指定生成接口需要扫描的包
.apis(RequestHandlerSelectors.basePackage("com.itheima.controller"))
.paths(PathSelectors.any())
.build();
return docket;
}
/**
*
* @param registry
*/
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
log.info("开始设置静态资源映射...");
registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
}
}

@ -1,83 +0,0 @@
// 定义包名
package com.itheima.controller;
// 导入User实体类
import com.itheima.entity.User;
// 导入UserMapper接口
import com.itheima.mapper.UserMapper;
// 导入Lombok提供的@Slf4j注解用于日志记录
import lombok.extern.slf4j.Slf4j;
// 导入Spring框架的Autowired注解用于自动注入依赖
import org.springframework.beans.factory.annotation.Autowired;
// 导入Spring框架的缓存注解
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
// 导入Spring框架的Web注解
import org.springframework.web.bind.annotation.*;
// 使用RestController注解标识这是一个控制器并且返回的数据直接作为响应体
@RestController
// 使用RequestMapping注解设置这个控制器的基础路径
@RequestMapping("/user")
// 使用@Slf4j注解自动注入日志对象
@Slf4j
public class UserController {
// 使用Autowired注解自动注入UserMapper
@Autowired
private UserMapper userMapper;
/**
*
* @param user
* @return
*/
@PostMapping
// 使用CachePut注解指定在保存用户信息后更新缓存key为用户ID
@CachePut(cacheNames = "userCache",key = "#user.id")
public User save(@RequestBody User user){
// 调用UserMapper的insert方法保存用户信息
userMapper.insert(user);
// 返回保存后的用户对象
return user;
}
/**
* ID
*/
@DeleteMapping
// 使用CacheEvict注解指定在删除用户信息后清除缓存中对应的数据key为用户ID
@CacheEvict(cacheNames = "userCache",key = "#id")
public void deleteById(Long id){
// 调用UserMapper的deleteById方法删除用户信息
userMapper.deleteById(id);
}
/**
*
*/
@DeleteMapping("/delAll")
// 使用CacheEvict注解指定在删除所有用户信息后清除缓存中的所有数据
@CacheEvict(cacheNames = "userCache",allEntries = true)
public void deleteAll(){
// 调用UserMapper的deleteAll方法删除所有用户信息
userMapper.deleteAll();
}
/**
* ID
* @param id ID
* @return
*/
@GetMapping
// 使用Cacheable注解指定在获取用户信息时如果缓存中有则直接返回缓存中的数据key为用户ID
@Cacheable(cacheNames = "userCache",key = "#id")
public User getById(Long id){
// 调用UserMapper的getById方法获取用户信息
User user = userMapper.getById(id);
// 返回用户对象
return user;
}
}

@ -1,26 +0,0 @@
// 定义包名
package com.itheima.entity;
// 导入lombok提供的@Data注解用于简化Java对象的getter、setter、toString等方法的编写
import lombok.Data;
// 导入Serializable接口用于实现对象的序列化
import java.io.Serializable;
// 使用@Data注解自动为类生成getter、setter、toString等方法
@Data
// 声明User类实现Serializable接口以便可以被序列化
public class User implements Serializable {
// 声明serialVersionUID用于在序列化和反序列化过程中保持版本的一致性
private static final long serialVersionUID = 1L;
// 声明id属性用于存储用户的唯一标识
private Long id;
// 声明name属性用于存储用户的姓名
private String name;
// 声明age属性用于存储用户的年龄
private int age;
}

@ -1,21 +0,0 @@
package com.itheima.mapper;
import com.itheima.entity.User;
import org.apache.ibatis.annotations.*;
@Mapper
public interface UserMapper{
@Insert("insert into user(name,age) values (#{name},#{age})")
@Options(useGeneratedKeys = true,keyProperty = "id")
void insert(User user);
@Delete("delete from user where id = #{id}")
void deleteById(Long id);
@Delete("delete from user")
void deleteAll();
@Select("select * from user where id = #{id}")
User getById(Long id);
}

@ -1,39 +0,0 @@
# 定义服务的配置项
server:
# 设置服务的端口号为8888
port: 8888
spring:
# 数据源配置
datasource:
# 配置Druid连接池
druid:
# 指定JDBC驱动类名
driver-class-name: com.mysql.cj.jdbc.Driver
# 指定数据库连接URL
url: jdbc:mysql://localhost:3306/spring_cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
# 指定数据库用户名
username: root
# 指定数据库密码
password: root
# Redis配置
redis:
# 指定Redis服务器地址
host: localhost
# 指定Redis服务器端口
port: 6379
# 指定Redis密码
password: 123456
# 指定Redis数据库索引
database: 1
# 日志配置
logging:
# 设置日志级别
level:
# 设置com.itheima包下的mapper日志级别为debug
com:
itheima:
mapper: debug
# 设置com.itheima包下的service日志级别为info
service: info
# 设置com.itheima包下的controller日志级别为info
controller: info

@ -1,21 +0,0 @@
server:
port: 8888
spring:
datasource:
druid:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/spring_cache_demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&zeroDateTimeBehavior=convertToNull&useSSL=false&allowPublicKeyRetrieval=true
username: root
password: root
redis:
host: localhost
port: 6379
password: 123456
database: 1
logging:
level:
com:
itheima:
mapper: debug
service: info
controller: info

@ -0,0 +1,19 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
*/
@Data
public class OrdersCancelDTO implements Serializable {
// 订单ID
private Long id;
// 订单取消原因
private String cancelReason;
}

@ -0,0 +1,19 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
*/
@Data
public class OrdersConfirmDTO implements Serializable {
// 订单ID
private Long id;
// 订单状态1-待付款2-待接单3-已接单4-派送中5-已完成6-已取消7-退款
private Integer status;
}

@ -0,0 +1,61 @@
package com.sky.dto;
import com.sky.entity.OrderDetail;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.List;
/**
*
*/
@Data
public class OrdersDTO implements Serializable {
// 订单ID
private Long id;
// 订单编号
private String number;
// 订单状态1-待付款2-待派送3-已派送4-已完成5-已取消
private Integer status;
// 下单用户ID
private Long userId;
// 地址簿ID关联用户地址
private Long addressBookId;
// 下单时间
private LocalDateTime orderTime;
// 结账时间
private LocalDateTime checkoutTime;
// 支付方式1-微信2-支付宝
private Integer payMethod;
// 实收金额
private BigDecimal amount;
// 备注信息
private String remark;
// 用户名
private String userName;
// 用户手机号
private String phone;
// 收货地址
private String address;
// 收货人
private String consignee;
// 订单详情列表
private List<OrderDetail> orderDetails;
}

@ -0,0 +1,41 @@
package com.sky.dto;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
*/
@Data
public class OrdersPageQueryDTO implements Serializable {
// 当前页码
private int page;
// 每页显示记录数
private int pageSize;
// 订单编号
private String number;
// 用户手机号
private String phone;
// 订单状态
private Integer status;
// 查询开始时间格式yyyy-MM-dd HH:mm:ss
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime beginTime;
// 查询结束时间格式yyyy-MM-dd HH:mm:ss
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
// 用户ID
private Long userId;
}

@ -0,0 +1,14 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class OrdersPaymentDTO implements Serializable {
//订单号
private String orderNumber;
//付款方式
private Integer payMethod;
}

@ -0,0 +1,19 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
*/
@Data
public class OrdersRejectionDTO implements Serializable {
// 订单ID
private Long id;
// 订单拒绝原因
private String rejectionReason;
}

@ -0,0 +1,31 @@
package com.sky.dto;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
@Data
public class OrdersSubmitDTO implements Serializable {
//地址簿id
private Long addressBookId;
//付款方式
private int payMethod;
//备注
private String remark;
//预计送达时间
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime estimatedDeliveryTime;
//配送状态 1立即送出 0选择具体时间
private Integer deliveryStatus;
//餐具数量
private Integer tablewareNumber;
//餐具数量状态 1按餐量提供 0选择具体数量
private Integer tablewareStatus;
//打包费
private Integer packAmount;
//总金额
private BigDecimal amount;
}

@ -0,0 +1,19 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
@Data
public class PasswordEditDTO implements Serializable {
//员工id
private Long empId;
//旧密码
private String oldPassword;
//新密码
private String newPassword;
}

@ -0,0 +1,40 @@
package com.sky.dto;
import com.sky.entity.SetmealDish;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
@Data
public class SetmealDTO implements Serializable {
// 套餐ID
private Long id;
// 分类ID
private Long categoryId;
// 套餐名称
private String name;
// 套餐价格
private BigDecimal price;
// 套餐状态0-停用1-启用
private Integer status;
// 套餐描述信息
private String description;
// 套餐图片
private String image;
// 套餐与菜品的关系
private List<SetmealDish> setmealDishes = new ArrayList<>();
}

@ -0,0 +1,28 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
*/
@Data
public class SetmealPageQueryDTO implements Serializable {
// 当前页码
private int page;
// 每页显示的记录数
private int pageSize;
// 套餐名称(支持模糊查询)
private String name;
// 分类ID
private Integer categoryId;
// 套餐状态0-禁用1-启用
private Integer status;
}

@ -0,0 +1,21 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
*/
@Data
public class ShoppingCartDTO implements Serializable {
// 菜品ID
private Long dishId;
// 套餐ID
private Long setmealId;
// 菜品口味
private String dishFlavor;
}

@ -0,0 +1,16 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
* C
*/
@Data
public class UserLoginDTO implements Serializable {
// 登录凭证(如微信登录时的授权码)
private String code;
}

@ -0,0 +1,63 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* 簿
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class AddressBook implements Serializable {
private static final long serialVersionUID = 1L;
// 地址ID
private Long id;
// 用户ID
private Long userId;
// 收货人姓名
private String consignee;
// 收货人手机号
private String phone;
// 性别0-女1-男
private String sex;
// 省级行政区划编号
private String provinceCode;
// 省级名称
private String provinceName;
// 市级行政区划编号
private String cityCode;
// 市级名称
private String cityName;
// 区级行政区划编号
private String districtCode;
// 区级名称
private String districtName;
// 详细地址
private String detail;
// 地址标签(如家、公司)
private String label;
// 是否为默认地址0-否1-是
private Integer isDefault;
}

@ -0,0 +1,48 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Category implements Serializable {
private static final long serialVersionUID = 1L;
// 分类ID
private Long id;
// 类型1-菜品分类2-套餐分类
private Integer type;
// 分类名称
private String name;
// 排序优先级
private Integer sort;
// 分类状态0-禁用1-启用
private Integer status;
// 创建时间
private LocalDateTime createTime;
// 更新时间
private LocalDateTime updateTime;
// 创建人ID
private Long createUser;
// 修改人ID
private Long updateUser;
}

@ -0,0 +1,55 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
*
* /
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Dish implements Serializable {
private static final long serialVersionUID = 1L;
// 菜品ID
private Long id;
// 菜品名称
private String name;
// 菜品所属分类的ID
private Long categoryId;
// 菜品价格
private BigDecimal price;
// 菜品图片URL
private String image;
// 菜品描述信息
private String description;
// 菜品状态0-停售1-起售
private Integer status;
// 创建时间
private LocalDateTime createTime;
// 更新时间
private LocalDateTime updateTime;
// 创建人ID
private Long createUser;
// 修改人ID
private Long updateUser;
}

@ -0,0 +1,33 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class DishFlavor implements Serializable {
private static final long serialVersionUID = 1L;
// 唯一标识ID
private Long id;
// 对应的菜品ID
private Long dishId;
// 口味名称,例如:辣、微辣、不辣
private String name;
// 口味数据以JSON格式存储列表值如[“微辣”,“加辣”,“原味”]
private String value;
}

@ -0,0 +1,60 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
// 唯一标识员工ID
private Long id;
// 登录用户名
private String username;
// 员工姓名
private String name;
// 登录密码(建议存储加密后的密码)
private String password;
// 手机号
private String phone;
// 性别,建议采用"0"代表女,"1"代表男
private String sex;
// 身份证号码
private String idNumber;
// 状态0表示禁用1表示启用
private Integer status;
// 创建时间
//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
// 更新时间
//@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
// 创建记录的用户ID
private Long createUser;
// 更新记录的用户ID
private Long updateUser;
}

@ -0,0 +1,49 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
*
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class OrderDetail implements Serializable {
private static final long serialVersionUID = 1L;
// 订单明细ID唯一标识
private Long id;
// 菜品或套餐名称
private String name;
// 所属订单ID
private Long orderId;
// 菜品ID若为菜品则有值
private Long dishId;
// 套餐ID若为套餐则有值
private Long setmealId;
// 菜品口味(仅适用于菜品)
private String dishFlavor;
// 数量
private Integer number;
// 单项金额
private BigDecimal amount;
// 图片URL
private String image;
}

@ -0,0 +1,87 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Orders implements Serializable {
/**
* 1 2 3 4 5 6
*/
public static final Integer PENDING_PAYMENT = 1; // 待付款
public static final Integer TO_BE_CONFIRMED = 2; // 待接单
public static final Integer CONFIRMED = 3; // 已接单
public static final Integer DELIVERY_IN_PROGRESS = 4; // 派送中
public static final Integer COMPLETED = 5; // 已完成
public static final Integer CANCELLED = 6; // 已取消
/**
* 0 1 2退
*/
public static final Integer UN_PAID = 0; // 未支付
public static final Integer PAID = 1; // 已支付
public static final Integer REFUND = 2; // 已退款
private static final long serialVersionUID = 1L; // 序列化版本号
private Long id; // 订单ID主键
private String number; // 订单号,通常为唯一值
private Integer status; // 订单状态,值范围由上方静态常量定义
private Long userId; // 下单用户ID
private Long addressBookId; // 收货地址ID
private LocalDateTime orderTime; // 下单时间
private LocalDateTime checkoutTime; // 结账时间
private Integer payMethod; // 支付方式 1微信 2支付宝
private Integer payStatus; // 支付状态 0未支付 1已支付 2退款
private BigDecimal amount; // 实收金额
private String remark; // 用户备注
private String userName; // 用户名
private String phone; // 用户手机号
private String address; // 收货地址
private String consignee; // 收货人姓名
private String cancelReason; // 订单取消原因
private String rejectionReason; // 订单拒绝原因
private LocalDateTime cancelTime; // 订单取消时间
private LocalDateTime estimatedDeliveryTime; // 预计送达时间
private Integer deliveryStatus; // 配送状态 1立即送出 0选择具体配送时间
private LocalDateTime deliveryTime; // 实际送达时间
private int packAmount; // 打包费
private int tablewareNumber; // 餐具数量
private Integer tablewareStatus; // 餐具数量状态 1按餐量提供 0选择具体数量
}

@ -0,0 +1,43 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class Setmeal implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号
private Long id; // 套餐ID主键
private Long categoryId; // 分类ID关联分类表的主键
private String name; // 套餐名称
private BigDecimal price; // 套餐价格,单位通常为元
private Integer status; // 套餐状态0为停用1为启用
private String description; // 套餐描述信息,通常用于说明内容或特点
private String image; // 套餐图片路径或URL
private LocalDateTime createTime; // 创建时间
private LocalDateTime updateTime; // 更新时间
private Long createUser; // 创建人ID通常为员工ID
private Long updateUser; // 更新人ID通常为员工ID
}

@ -0,0 +1,34 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
/**
*
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SetmealDish implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号
private Long id; // 套餐菜品关系表的主键ID
private Long setmealId; // 套餐ID关联Setmeal表的主键
private Long dishId; // 菜品ID关联Dish表的主键
private String name; // 菜品名称,冗余字段,存储菜品的名称
private BigDecimal price; // 菜品原价,记录菜品的原始价格
private Integer copies; // 份数,表示该套餐中该菜品的份数
}

@ -0,0 +1,43 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDateTime;
/**
*
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ShoppingCart implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号
private Long id; // 购物车项的唯一标识符
private String name; // 菜品或套餐的名称
private Long userId; // 用户ID标识属于哪个用户的购物车
private Long dishId; // 菜品ID关联Dish表的主键
private Long setmealId; // 套餐ID关联Setmeal表的主键
private String dishFlavor; // 菜品的口味,如果是套餐,则可能为空
private Integer number; // 该菜品或套餐在购物车中的数量
private BigDecimal amount; // 该菜品或套餐的总金额(即数量 * 单价)
private String image; // 菜品或套餐的图片地址
private LocalDateTime createTime; // 记录该购物车项的创建时间
}

@ -0,0 +1,39 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.time.LocalDate;
import java.time.LocalDateTime;
/**
*
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号
private Long id; // 用户的唯一标识符
private String openid; // 微信用户唯一标识,系统用此标识识别用户
private String name; // 用户的姓名
private String phone; // 用户的手机号,用于用户联系和身份验证
private String sex; // 用户性别0表示女1表示男
private String idNumber; // 用户的身份证号,用于身份验证
private String avatar; // 用户的头像URL存储用户头像图片的地址
private LocalDateTime createTime; // 用户的注册时间,记录用户注册的时间点
}

@ -0,0 +1,132 @@
<?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">
<parent>
<artifactId>sky-take-out</artifactId>
<groupId>com.sky</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>sky-server</artifactId>
<dependencies>
<dependency>
<groupId>com.sky</groupId>
<artifactId>sky-common</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.sky</groupId>
<artifactId>sky-pojo</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjrt</artifactId>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
<dependency>
<groupId>com.github.xiaoymin</groupId>
<artifactId>knife4j-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-websocket</artifactId>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<!-- poi -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

@ -0,0 +1,82 @@
package com.sky.service.impl;
import com.sky.context.BaseContext;
import com.sky.entity.AddressBook;
import com.sky.mapper.AddressBookMapper;
import com.sky.service.AddressBookService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class AddressBookServiceImpl implements AddressBookService {
@Autowired
private AddressBookMapper addressBookMapper;
/**
*
* @param addressBook
* @return
*/
@Override
public List<AddressBook> list(AddressBook addressBook) {
return addressBookMapper.list(addressBook);
}
/**
*
* @param addressBook
*/
@Override
public void save(AddressBook addressBook) {
addressBook.setUserId(BaseContext.getCurrentId());
addressBook.setIsDefault(0);
addressBookMapper.insert(addressBook);
}
/**
* id
* @param id
* @return
*/
@Override
public AddressBook getById(Long id) {
return addressBookMapper.getById(id);
}
/**
* id
* @param addressBook
*/
@Override
public void update(AddressBook addressBook) {
addressBookMapper.update(addressBook);
}
/**
*
* @param addressBook
*/
@Override
public void setDefault(AddressBook addressBook) {
//1、将当前用户的所有地址修改为非默认地址 update address_book set is_default = ? where user_id = ?
addressBook.setIsDefault(0);
addressBook.setUserId(BaseContext.getCurrentId());
addressBookMapper.updateIsDefaultByUserId(addressBook);
//2、将当前地址改为默认地址 update address_book set is_default = ? where id = ?
addressBook.setIsDefault(1);
addressBookMapper.update(addressBook);
}
/**
* id
* @param id
*/
@Override
public void deleteById(Long id) {
addressBookMapper.deleteById(id);
}
}

@ -0,0 +1,132 @@
package com.sky.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.CategoryDTO;
import com.sky.dto.CategoryPageQueryDTO;
import com.sky.entity.Category;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.CategoryMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.CategoryService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
/**
*
*/
@Service
@Slf4j
public class CategoryServiceImpl implements CategoryService {
@Autowired
private CategoryMapper categoryMapper;
@Autowired
private DishMapper dishMapper;
@Autowired
private SetmealMapper setmealMapper;
/**
*
* @param categoryDTO
*/
public void save(CategoryDTO categoryDTO) {
Category category = new Category();
//属性拷贝
BeanUtils.copyProperties(categoryDTO, category);
//分类状态默认为禁用状态0
category.setStatus(StatusConstant.DISABLE);
//设置创建时间、修改时间、创建人、修改人
// category.setCreateTime(LocalDateTime.now());
// category.setUpdateTime(LocalDateTime.now());
// category.setCreateUser(BaseContext.getCurrentId());
// category.setUpdateUser(BaseContext.getCurrentId());
categoryMapper.insert(category);
}
/**
*
* @param categoryPageQueryDTO
* @return
*/
public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
PageHelper.startPage(categoryPageQueryDTO.getPage(),categoryPageQueryDTO.getPageSize());
//下一条sql进行分页自动加入limit关键字分页
Page<Category> page = categoryMapper.pageQuery(categoryPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
/**
* id
* @param id
*/
public void deleteById(Long id) {
//查询当前分类是否关联了菜品,如果关联了就抛出业务异常
Integer count = dishMapper.countByCategoryId(id);
if(count > 0){
//当前分类下有菜品,不能删除
throw new DeletionNotAllowedException(MessageConstant.CATEGORY_BE_RELATED_BY_DISH);
}
//查询当前分类是否关联了套餐,如果关联了就抛出业务异常
count = setmealMapper.countByCategoryId(id);
if(count > 0){
//当前分类下有菜品,不能删除
throw new DeletionNotAllowedException(MessageConstant.CATEGORY_BE_RELATED_BY_SETMEAL);
}
//删除分类数据
categoryMapper.deleteById(id);
}
/**
*
* @param categoryDTO
*/
public void update(CategoryDTO categoryDTO) {
Category category = new Category();
BeanUtils.copyProperties(categoryDTO,category);
//设置修改时间、修改人
// category.setUpdateTime(LocalDateTime.now());
// category.setUpdateUser(BaseContext.getCurrentId());
categoryMapper.update(category);
}
/**
*
* @param status
* @param id
*/
public void startOrStop(Integer status, Long id) {
Category category = Category.builder()
.id(id)
.status(status)
.updateTime(LocalDateTime.now())
.updateUser(BaseContext.getCurrentId())
.build();
categoryMapper.update(category);
}
/**
*
* @param type
* @return
*/
public List<Category> list(Integer type) {
return categoryMapper.list(type);
}
}

@ -0,0 +1,231 @@
package com.sky.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.StatusConstant;
import com.sky.dto.DishDTO;
import com.sky.dto.DishPageQueryDTO;
import com.sky.entity.Dish;
import com.sky.entity.DishFlavor;
import com.sky.entity.Setmeal;
import com.sky.entity.SetmealDish;
import com.sky.exception.DeletionNotAllowedException;
import com.sky.mapper.DishFlavorMapper;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealDishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.result.PageResult;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
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.util.ArrayList;
import java.util.List;
@Service
public class DishServiceImpl implements DishService {
@Autowired
private DishMapper dishMapper;
@Autowired
private DishFlavorMapper dishFlavorMapper;
@Autowired
private SetmealDishMapper setmealDishMapper;
@Autowired
private SetmealMapper setmealMapper;
/**
*
* @param dishDTO
*/
@Override
@Transactional
public void saveWithFlavor(DishDTO dishDTO) {
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO, dish);
// 向菜品表插入1条数据
dishMapper.insert(dish);
// 获取insert语句生成的主键值
Long dishId = dish.getId();
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors != null && flavors.size() > 0) {
flavors.forEach(dishFlavor -> dishFlavor.setDishId(dishId));
// 向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}
}
/**
*
* @param dishPageQueryDTO
* @return
*/
@Override
public PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO) {
PageHelper.startPage(dishPageQueryDTO.getPage(), dishPageQueryDTO.getPageSize());
Page<DishVO> page=dishMapper.pageQuery(dishPageQueryDTO);
return new PageResult(page.getTotal(), page.getResult());
}
/**
*
* @param ids
*/
@Override
@Transactional
public void deleteBatch(List<Long> ids) {
// 判断当前菜品是否能够删除---是否存在起售中的菜品??
ids.forEach(id->{
Dish dish = dishMapper.getById(id);
if (dish.getStatus() == StatusConstant.ENABLE) {
// 当前菜品处于起售中,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_ON_SALE);
}
});
// 判断当前菜品是否能够删除---是否被套餐关联了??
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(ids);
if (setmealIds != null && setmealIds.size() > 0) {
// 当前菜品被套餐关联了,不能删除
throw new DeletionNotAllowedException(MessageConstant.DISH_BE_RELATED_BY_SETMEAL);
}
// 删除菜品表中的菜品数据
ids.forEach(id->{
dishMapper.deleteById(id);
// 删除菜单关联的口味数据
dishFlavorMapper.deleteByDishId(id);
});
}
/**
* id
* @param id
* @return
*/
@Override
public DishVO getByIdWithFlavor(Long id) {
// 根据id查询菜品数据
Dish dish = dishMapper.getById(id);
// 根据菜品id查询口味数据
List<DishFlavor> dishFlavorList = dishFlavorMapper.getByDishId(id);
// 将查询到的数据封装到vo
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(dish, dishVO);
dishVO.setFlavors(dishFlavorList);
return dishVO;
}
/**
*
* @param dishDTO
*/
@Override
public void updateWithFlavor(DishDTO dishDTO) {
Dish dish = new Dish();
BeanUtils.copyProperties(dishDTO, dish);
// 修改菜品基本信息
dishMapper.update(dish);
// 删除原有的口味信息
dishFlavorMapper.deleteByDishId(dishDTO.getId());
// 重新插入口味数据
List<DishFlavor> flavors = dishDTO.getFlavors();
if (flavors != null && flavors.size() > 0) {
flavors.forEach(dishFlavor -> dishFlavor.setDishId(dishDTO.getId()));
// 向口味表插入n条数据
dishFlavorMapper.insertBatch(flavors);
}
}
/**
* id
* @param categoryId
* @return
*/
@Override
public List<Dish> list(Long categoryId) {
Dish dish = Dish.builder()
.categoryId(categoryId)
.status(StatusConstant.ENABLE)
.build();
return dishMapper.list(dish);
}
/**
*
* @param dish
* @return
*/
@Override
public List<DishVO> listWithFlavor(Dish dish) {
List<Dish> dishList = dishMapper.list(dish);
ArrayList<DishVO> dishVOArrayList = new ArrayList<>();
dishList.forEach(d->{
DishVO dishVO = new DishVO();
BeanUtils.copyProperties(d, dishVO);
// 根据菜品id查询对应的口味
List<DishFlavor> flavors = dishFlavorMapper.getByDishId(d.getId());
dishVO.setFlavors(flavors);
dishVOArrayList.add(dishVO);
});
return dishVOArrayList;
}
/**
*
* @param status
* @param id
*/
@Override
@Transactional
public void startOrStop(Integer status, Long id) {
Dish dish = Dish.builder()
.id(id)
.status(status)
.build();
dishMapper.update(dish);
if (status == StatusConstant.DISABLE) {
// 如果是停售操作,还需要将包含当前菜品的套餐也停售
List<Long> dishIds = new ArrayList<>();
dishIds.add(id);
// select setmeal_id from setmeal_dish where dish_id in (?,?,?)
List<Long> setmealIds = setmealDishMapper.getSetmealIdsByDishIds(dishIds);
if (setmealIds != null && setmealIds.size() > 0) {
for (Long setmealId : setmealIds) {
Setmeal setmeal = Setmeal.builder()
.id(setmealId)
.status(StatusConstant.DISABLE)
.build();
setmealMapper.update(setmeal);
}
}
}
}
}

@ -0,0 +1,158 @@
package com.sky.service.impl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.constant.PasswordConstant;
import com.sky.constant.StatusConstant;
import com.sky.context.BaseContext;
import com.sky.dto.EmployeeDTO;
import com.sky.dto.EmployeeLoginDTO;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.exception.AccountLockedException;
import com.sky.exception.AccountNotFoundException;
import com.sky.exception.PasswordErrorException;
import com.sky.mapper.EmployeeMapper;
import com.sky.result.PageResult;
import com.sky.service.EmployeeService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import java.time.LocalDateTime;
import java.util.List;
@Service
public class EmployeeServiceImpl implements EmployeeService {
@Autowired
private EmployeeMapper employeeMapper;
/**
*
*
* @param employeeLoginDTO
* @return
*/
public Employee login(EmployeeLoginDTO employeeLoginDTO) {
String username = employeeLoginDTO.getUsername();
String password = employeeLoginDTO.getPassword();
//1、根据用户名查询数据库中的数据
Employee employee = employeeMapper.getByUsername(username);
//2、处理各种异常情况用户名不存在、密码不对、账号被锁定
if (employee == null) {
//账号不存在
throw new AccountNotFoundException(MessageConstant.ACCOUNT_NOT_FOUND);
}
//密码比对
// TODO 后期需要进行md5加密然后再进行比对
password = DigestUtils.md5DigestAsHex(password.getBytes());
if (!password.equals(employee.getPassword())) {
//密码错误
throw new PasswordErrorException(MessageConstant.PASSWORD_ERROR);
}
if (employee.getStatus() == StatusConstant.DISABLE) {
//账号被锁定
throw new AccountLockedException(MessageConstant.ACCOUNT_LOCKED);
}
//3、返回实体对象
return employee;
}
/**
*
* @param employeeDTO
*/
@Override
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
//对象属性拷贝
BeanUtils.copyProperties(employeeDTO, employee);
//设置账号的状态,默认正常状态 1表示正常 0表示锁定
employee.setStatus(StatusConstant.ENABLE);
//设置密码默认密码123456
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes()));
//设置当前记录的创建时间和修改时间
employee.setCreateTime(LocalDateTime.now());
employee.setUpdateTime(LocalDateTime.now());
// 通过ThreadLocal获取用户信息
Long currentId = BaseContext.getCurrentId();
//设置当前记录创建人id和修改人id
employee.setCreateUser(currentId);//目前写个假数据,后期修改
employee.setUpdateUser(currentId);
employeeMapper.insert(employee);//后续步骤定义
}
/**
*
* @param employeePageQueryDTO
* @return
*/
@Override
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
// 开始分页查询
PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());
Page<Employee> page = employeeMapper.pageQuery(employeePageQueryDTO);
long total = page.getTotal();
List<Employee> records = page.getResult();
return new PageResult(total, records);
}
/**
*
* @param status
* @param id
*/
@Override
public void startOrStop(Integer status, Long id) {
Employee employee = Employee.builder()
.status(status)
.id(id)
.build();
employeeMapper.update(employee);
}
/**
* iD
* @param id
* @return
*/
@Override
public Employee getById(Long id) {
Employee employee = employeeMapper.getById(id);
employee.setPassword("****");
return employee;
}
/**
*
* @param employeeDTO
*/
@Override
public void update(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO, employee);
employee.setUpdateTime(LocalDateTime.now());
employee.setUpdateUser(BaseContext.getCurrentId());
employeeMapper.update(employee);
}
}

@ -0,0 +1,619 @@
package com.sky.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
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.HttpClientUtil;
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.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.stream.Collectors;
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderMapper orderMapper;
@Autowired
private OrderDetailMapper orderDetailMapper;
@Autowired
private ShoppingCartMapper shoppingCartMapper;
@Autowired
private AddressBookMapper addressBookMapper;
@Autowired
private UserMapper userMapper;
@Autowired
private WeChatPayUtil weChatPayUtil;
@Value("${sky.shop.address}")
private String shopAddress;
@Value("${sky.baidu.ak}")
private String ak;
@Autowired
private WebSocketServer webSocketServer;
/**
*
* @param ordersSubmitDTO
* @return
*/
@Override
public OrderSubmitVO submitOrder(OrdersSubmitDTO ordersSubmitDTO) {
// 异常情况的处理(收货地址为空、超出配送氛围、购物车为空)
AddressBook addressBook = addressBookMapper.getById(ordersSubmitDTO.getAddressBookId());
if (addressBook == null) {
throw new AddressBookBusinessException(MessageConstant.ADDRESS_BOOK_IS_NULL);
}
// 检查用户的收货地址是否超出配送范围
checkOutOfRange(addressBook.getCityName() + addressBook.getDistrictName() + addressBook.getDetail());
Long currentId = BaseContext.getCurrentId();
ShoppingCart shoppingCart = new ShoppingCart();
// 只能查询当前用户数据
shoppingCart.setUserId(currentId);
// 查询当前用户的购物车数据
List<ShoppingCart> shoppingCartList = shoppingCartMapper.list(shoppingCart);
if (shoppingCartList == null || shoppingCartList.size() == 0) {
throw new ShoppingCartBusinessException(MessageConstant.SHOPPING_CART_IS_NULL);
}
//构造订单数据
Orders order = new Orders();
BeanUtils.copyProperties(ordersSubmitDTO,order);
order.setPhone(addressBook.getPhone());
order.setAddress(addressBook.getDetail());
order.setConsignee(addressBook.getConsignee());
order.setNumber(String.valueOf(System.currentTimeMillis()));
order.setUserId(currentId);
order.setStatus(Orders.PENDING_PAYMENT);
order.setPayStatus(Orders.UN_PAID);
order.setOrderTime(LocalDateTime.now());
orderMapper.insert(order);
// 订单明细数据
ArrayList<OrderDetail> orderDetailList = new ArrayList<>();
shoppingCartList.forEach(cart->{
OrderDetail orderDetail = new OrderDetail();
BeanUtils.copyProperties(cart, orderDetail);
orderDetail.setOrderId(order.getId());
orderDetailList.add(orderDetail);
});
// 向明细表中查询n条数据
orderDetailMapper.insertBatch(orderDetailList);
// 清理购物车中的数据
shoppingCartMapper.deleteByUserId(currentId);
// 封装返回结果
OrderSubmitVO submitVO = OrderSubmitVO.builder()
.id(order.getId())
.orderNumber(order.getNumber())
.orderAmount(order.getAmount())
.orderTime(order.getOrderTime())
.build();
return submitVO;
}
/**
*
* @param ordersPaymentDTO
* @return
* @throws Exception
*/
@Override
public OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception {
// 当前登录用户id
Long userId = BaseContext.getCurrentId();
User user = userMapper.getById(String.valueOf(userId));
String orderNumber = ordersPaymentDTO.getOrderNumber();
Orders orders = orderMapper.getByNumberAndUserId(orderNumber, userId);
// 调用微信支付接口,生成预支付交易单
JSONObject jsonObject = weChatPayUtil.pay(
ordersPaymentDTO.getOrderNumber(),
orders.getAmount(),
"苍穹外卖订单" + orders.getId(),
user.getOpenid()
);
if (jsonObject.getString("code") != null && jsonObject.getString("code").equals("ORDERPAID")) {
throw new OrderBusinessException("该订单已支付");
}
OrderPaymentVO vo = jsonObject.toJavaObject(OrderPaymentVO.class);
vo.setPackageStr(jsonObject.getString("package"));
return vo;
}
/**
*
* @param outTradeNo
*/
@Override
public void paySuccess(String outTradeNo) {
// 当前登录用户id
Long userId = BaseContext.getCurrentId();
// 根据订单号查询当前用户的订单
Orders orderDB = orderMapper.getByNumberAndUserId(outTradeNo, userId);
// 根据订单id更新订单的状态、支付方式、支付状态、结账时间
Orders orders = Orders.builder()
.id(orderDB.getId())
.status(Orders.TO_BE_CONFIRMED)
.payStatus(Orders.PAID)
.checkoutTime(LocalDateTime.now())
.build();
orderMapper.update(orders);
HashMap map = new HashMap();
map.put("type", 1);
map.put("orderId", orders.getId());
map.put("content", "订单号:" + outTradeNo);
// 通过WebSocket实现来电提醒向客户端浏览器推送消息
webSocketServer.sendToAllClient(JSON.toJSONString(map));
}
/**
*
*
* @param pageNum
* @param pageSize
* @param status 1 2 3 4 5 6
* @return
*/
@Override
public PageResult pageQueryForUser(int pageNum, int pageSize, Integer status) {
// 设置分页
PageHelper.startPage(pageNum, pageSize);
OrdersPageQueryDTO ordersPageQueryDTO = new OrdersPageQueryDTO();
ordersPageQueryDTO.setUserId(BaseContext.getCurrentId());
ordersPageQueryDTO.setStatus(status);
// 分页条件查询
Page<Orders> page = orderMapper.pageQuery(ordersPageQueryDTO);
ArrayList<OrderVO> list = new ArrayList<>();
// 查询出订单明细并封装入OrderVo进行响应
if (page != null && page.getTotal() > 0) {
page.forEach(orders -> {
Long ordersId = orders.getId();
// 查询订单明细
List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(ordersId);
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(orders, orderVO);
orderVO.setOrderDetailList(orderDetailList);
list.add(orderVO);
});
}
return new PageResult(page.getTotal(), list);
}
/**
*
* @param id
* @return
*/
@Override
public OrderVO details(Long id) {
// 根据id查询订单
Orders orders = orderMapper.getById(id);
// 查询该订单对应的菜品/套餐明细
List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);
// 将订单及其详情封装到OrderVo并返回
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(orders, orderVO);
orderVO.setOrderDetailList(orderDetailList);
return orderVO;
}
/**
*
* @param id
*/
@Override
public void userCancelById(Long id) throws Exception {
// 根据id查询订单
Orders orderDB = orderMapper.getById(id);
// 校验订单是否存在
if (orderDB == null) {
throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
}
// 订单状态 1待付款 2待接单 3已接单 4派送中 5已完成 6已取消
if (orderDB.getStatus() > 2) {
throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
}
Orders orders = new Orders();
orders.setId(orderDB.getId());
// 订单处于待接单的状态下取消,需要进行退款
if (orderDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
// 调用微信支付退款接口
weChatPayUtil.refund(
orderDB.getNumber(),
orderDB.getNumber(),
orders.getAmount(),
orders.getAmount()
);
// 支付状态修改为 退款
orders.setPayStatus(Orders.REFUND);
}
// 更新订单状态,取消原因、时间
orders.setStatus(Orders.CANCELLED);
orders.setCancelReason("用户取消");
orders.setCancelTime(LocalDateTime.now());
orderMapper.update(orders);
}
/**
*
* @param id
*/
@Override
public void repetition(Long id) {
// 查询当前用户id
Long userId = BaseContext.getCurrentId();
// 根据订单id查询当前订单详情
List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(id);
// 将订单详情对象转为购物车对象
List<ShoppingCart> shoppingCartList = orderDetailList.stream().map(orderDetail -> {
ShoppingCart shoppingCart = new ShoppingCart();
// 将原订单详情里面的菜品信息重新复制到购物车对象中
BeanUtils.copyProperties(orderDetail, shoppingCart, "id");
shoppingCart.setUserId(userId);
shoppingCart.setCreateTime(LocalDateTime.now());
return shoppingCart;
}).collect(Collectors.toList());
// 将购物车对象批量添加到购物车
shoppingCartMapper.insertBatch(shoppingCartList);
}
/**
*
* @param ordersPageQueryDTO
* @return
*/
@Override
public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
Page<Orders> pageQuery = orderMapper.pageQuery(ordersPageQueryDTO);
// 部分订单状态需要额外返回订单菜品信息将orders转化为orderVo
List<OrderVO> orderVoList = getOrderVoList(pageQuery);
return new PageResult(pageQuery.getTotal(), orderVoList);
}
/**
*
* @return
*/
@Override
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 = new OrderStatisticsVO();
orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
orderStatisticsVO.setConfirmed(confirmed);
orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);
return orderStatisticsVO;
}
/**
*
* @param ordersCancelDTO
*/
@Override
public void confirm(OrdersCancelDTO ordersCancelDTO) {
Orders orders = Orders.builder()
.id(ordersCancelDTO.getId())
.status(Orders.CONFIRMED)
.build();
orderMapper.update(orders);
}
/**
*
* @param ordersRejectionDTO
*/
@Override
public void rejection(OrdersRejectionDTO ordersRejectionDTO) throws Exception {
// 根据id查询订单
Orders ordersDB = orderMapper.getById(ordersRejectionDTO.getId());
// 订单只有存在且状态为2待接单才可以拒单
if (ordersDB == null || !ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
}
// 支付状态
Integer payStatus = ordersDB.getPayStatus();
if (payStatus == Orders.PAID) {
// 用户已支付,需要退款
String refund = weChatPayUtil.refund(
ordersDB.getNumber(),
ordersDB.getNumber(),
ordersDB.getAmount(),
ordersDB.getAmount()
);
log.info("申请退款:{}", refund);
}
// 拒单需要退款根据订单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 ordersCancelDTO
*/
@Override
public void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception {
// 根据id查询订单
Orders orderDB = orderMapper.getById(ordersCancelDTO.getId());
// 支付状态
Integer payStatus = orderDB.getPayStatus();
if (payStatus == 1) {
// 用于已支付,需要退款
String refund = weChatPayUtil.refund(
orderDB.getNumber(),
orderDB.getNumber(),
orderDB.getAmount(),
orderDB.getAmount()
);
log.info("申请退款:{}", refund);
}
// 管理端取消订单需要退款根据订单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 id
*/
@Override
public void delivery(Long id) {
// 根据id查询订单
Orders orderDB = orderMapper.getById(id);
// 校验订单是否存在并且状态为3
if (orderDB == null || !orderDB.getStatus().equals(Orders.CONFIRMED)) {
throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
}
Orders orders = new Orders();
orders.setId(orderDB.getId());
// 更新订单状态,状态转为派送中
orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
orderMapper.update(orders);
}
/**
*
* @param id
*/
@Override
public void complete(Long id) {
// 根据id查询订单
Orders orderDB = orderMapper.getById(id);
// 校验订单是否存在并且状态为4
if (orderDB == null || !orderDB.getStatus().equals(Orders.DELIVERY_IN_PROGRESS)) {
throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
}
Orders orders = new Orders();
orders.setId(orders.getId());
// 更新订单状态,状态转为完成
orders.setStatus(Orders.CONFIRMED);
orders.setDeliveryTime(LocalDateTime.now());
orderMapper.update(orders);
}
/**
*
* @param id
*/
@Override
public void reminder(Long id) {
// 查询订单是否存在
Orders orders = orderMapper.getById(id);
if (orders == null) {
throw new OrderBusinessException(MessageConstant.ORDER_NOT_FOUND);
}
// 基于WebSocket实现催单
HashMap map = new HashMap();
map.put("type", 2);
map.put("orderId", id);
map.put("content", "订单号:" + orders.getNumber());
webSocketServer.sendToAllClient(JSON.toJSONString(map));
}
/**
* ordersorderVo
* @param page
* @return
*/
private List<OrderVO> getOrderVoList(Page<Orders> page) {
// 需要返回订单菜品信息自定义OrderVo响应结果
ArrayList<OrderVO> orderVOArrayList = new ArrayList<>();
List<Orders> ordersList = page.getResult();
if (!CollectionUtils.isEmpty(ordersList)) {
ordersList.forEach(orders -> {
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(orders, orderVO);
String orderDishStr = getOrderDishStr(orders);
orderVO.setOrderDishes(orderDishStr);
orderVOArrayList.add(orderVO);
});
}
return orderVOArrayList;
}
/**
* id
* @param orders
* @return
*/
private String getOrderDishStr(Orders orders) {
// 查询订单菜品详情信息(订单中的菜品和数量)
List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orders.getId());
// 将每一条订单菜品信息拼接为字符串(格式:宫保鸡丁*3
List<String> ordewrDishList = orderDetailList.stream().map(orderDetail -> orderDetail.getName() + "*" + orderDetail.getNumber() + ";").collect(Collectors.toList());
// 将该订单对应的所有菜品信息拼接在一起
return String.join("", ordewrDishList);
}
/**
*
* @param address
*/
private void checkOutOfRange(String address) {
HashMap map = new HashMap();
map.put("address", shopAddress);
map.put("output", "json");
map.put("ak", ak);
// 获取店铺的经纬度坐标
String shopCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", map);
JSONObject jsonObject = JSON.parseObject(shopCoordinate);
if (!jsonObject.getString("status").equals("0")) {
throw new OrderBusinessException("店铺地址解析失败");
}
// 数据解析
JSONObject location = jsonObject.getJSONObject("result").getJSONObject("location");
String lat = location.getString("lat");
String lng = location.getString("lng");
// 店铺经纬度坐标
String shopLngLat = lat + "," + lng;
map.put("address", address);
// 获取用户地址的经纬度坐标
String userCoordinate = HttpClientUtil.doGet("https://api.map.baidu.com/geocoding/v3", map);
// 数据解析
location = JSON.parseObject("result").getJSONObject("location");
lat = location.getString("lat");
lng = location.getString("lng");
// 用户收货地址经纬度坐标
String userLngLat = lat + "," + lng;
map.put("orgin", shopLngLat);
map.put("destination", userLngLat);
map.put("steps_info", "0");
//路线规划
String json = HttpClientUtil.doGet("https://api.map.baidu.com/directionlite/v1/driving", map);
jsonObject = JSON.parseObject(json);
if (!jsonObject.getString("status").equals("0")) {
throw new OrderBusinessException("配送线路规划失败");
}
// 数据解析
JSONObject result = jsonObject.getJSONObject("result");
JSONArray jsonArray = (JSONArray) result.get("routes");
Integer distance = (Integer) ((JSONObject) jsonArray.get(0)).get("distance");
if(distance > 5000){
//配送距离超过5000米
throw new OrderBusinessException("超出配送范围");
}
}
}
Loading…
Cancel
Save