diff --git a/.idea/code.iml b/.idea/code.iml new file mode 100644 index 0000000..d6ebd48 --- /dev/null +++ b/.idea/code.iml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..be2f45c --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,10 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 0000000..712ab9d --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/sky/sky-common/src/main/java/com/sky/constant/MessageConstant.java b/sky/sky-common/src/main/java/com/sky/constant/MessageConstant.java new file mode 100644 index 0000000..4617ce2 --- /dev/null +++ b/sky/sky-common/src/main/java/com/sky/constant/MessageConstant.java @@ -0,0 +1,103 @@ +package com.sky.constant; + +/** + * 信息提示常量类,用于存储系统中可能出现的各种错误或状态信息的文本描述。 + * 这些信息主要用于向用户展示友好的提示信息,或者在日志记录时提供明确的上下文。 + */ +public class MessageConstant { + + /** + * 用户提供的密码与系统记录不符时的提示信息。 + */ + public static final String PASSWORD_ERROR = "密码错误"; + + /** + * 当尝试访问不存在的账户时返回的提示信息。 + */ + public static final String ACCOUNT_NOT_FOUND = "账号不存在"; + + /** + * 账户由于违反规则或其他原因被系统锁定时的提示信息。 + */ + public static final String ACCOUNT_LOCKED = "账号被锁定"; + + /** + * 尝试创建或修改的数据项已经存在于系统中时的提示信息。 + */ + public static final String ALREADY_EXISTS = "已存在"; + + /** + * 系统内部发生未预见的问题时的通用提示信息。 + */ + public static final String UNKNOWN_ERROR = "未知错误"; + + /** + * 当前操作需要用户登录,但检测到用户尚未登录时的提示信息。 + */ + public static final String USER_NOT_LOGIN = "用户未登录"; + + /** + * 当尝试删除一个分类时,如果该分类已被套餐关联,则返回此提示信息,表示不能删除。 + */ + public static final String CATEGORY_BE_RELATED_BY_SETMEAL = "当前分类关联了套餐,不能删除"; + + /** + * 当尝试删除一个分类时,如果该分类已被菜品关联,则返回此提示信息,表示不能删除。 + */ + public static final String CATEGORY_BE_RELATED_BY_DISH = "当前分类关联了菜品,不能删除"; + + /** + * 当购物车中没有数据,而用户试图进行下单操作时返回的提示信息。 + */ + public static final String SHOPPING_CART_IS_NULL = "购物车数据为空,不能下单"; + + /** + * 如果用户地址簿为空,不允许进行下单操作时的提示信息。 + */ + public static final String ADDRESS_BOOK_IS_NULL = "用户地址为空,不能下单"; + + /** + * 用户名和密码组合不正确导致登录失败时的提示信息。 + */ + public static final String LOGIN_FAILED = "登录失败"; + + /** + * 文件上传过程中出现问题时的提示信息。 + */ + public static final String UPLOAD_FAILED = "文件上传失败"; + + /** + * 当尝试启售一个包含有未启售菜品的套餐时返回的提示信息。 + */ + public static final String SETMEAL_ENABLE_FAILED = "套餐内包含未启售菜品,无法启售"; + + /** + * 密码修改操作未能成功完成时的提示信息。 + */ + public static final String PASSWORD_EDIT_FAILED = "密码修改失败"; + + /** + * 尝试删除起售中的菜品时返回的提示信息,表示不能删除。 + */ + public static final String DISH_ON_SALE = "起售中的菜品不能删除"; + + /** + * 尝试删除起售中的套餐时返回的提示信息,表示不能删除。 + */ + public static final String SETMEAL_ON_SALE = "起售中的套餐不能删除"; + + /** + * 当前菜品已被套餐关联,因此不能直接删除时的提示信息。 + */ + public static final String DISH_BE_RELATED_BY_SETMEAL = "当前菜品关联了套餐,不能删除"; + + /** + * 订单的状态不符合预期操作要求时返回的提示信息。 + */ + public static final String ORDER_STATUS_ERROR = "订单状态错误"; + + /** + * 指定的订单ID对应的数据在系统中找不到时的提示信息。 + */ + public static final String ORDER_NOT_FOUND = "订单不存在"; +} \ No newline at end of file diff --git a/sky/sky-common/src/main/java/com/sky/enumeration/OperationType.java b/sky/sky-common/src/main/java/com/sky/enumeration/OperationType.java new file mode 100644 index 0000000..63f5510 --- /dev/null +++ b/sky/sky-common/src/main/java/com/sky/enumeration/OperationType.java @@ -0,0 +1,20 @@ +package com.sky.enumeration; + +/** + * 数据库操作类型枚举,用于定义在应用程序中可能执行的不同类型的数据库操作。 + * 这些操作类型主要用于标识SQL语句的性质,例如是更新现有记录还是插入新记录。 + */ +public enum OperationType { + + /** + * 更新操作,表示对数据库中已存在的记录进行修改。 + * 该操作通常涉及使用SQL UPDATE语句来更改一个或多个字段的值。 + */ + UPDATE, + + /** + * 插入操作,表示向数据库中添加新的记录。 + * 该操作通常涉及使用SQL INSERT语句将新数据行插入到指定的表中。 + */ + INSERT; +} \ No newline at end of file diff --git a/sky/sky-common/src/main/java/com/sky/exception/BaseException.java b/sky/sky-common/src/main/java/com/sky/exception/BaseException.java new file mode 100644 index 0000000..71e7e44 --- /dev/null +++ b/sky/sky-common/src/main/java/com/sky/exception/BaseException.java @@ -0,0 +1,34 @@ +package com.sky.exception; + +/** + * 业务异常类,用于表示应用程序在处理业务逻辑时发生的异常情况。 + *

+ * 这个类继承自 {@link RuntimeException},因此它是一个非检查型异常(unchecked exception), + * 不需要在调用处显式地进行捕获或声明抛出。它主要用于处理那些由于业务规则违反或其他业务逻辑错误导致的问题。 + *

+ * 使用场景: + * - 当业务逻辑验证失败时,例如参数无效、数据不一致等; + * - 当执行某些操作不符合业务流程时,比如尝试对一个已关闭的订单进行修改; + * - 在服务层中,当遇到不可恢复的业务错误时,可以通过抛出此异常来快速返回错误信息给调用者。 + */ +public class BaseException extends RuntimeException { + + /** + * 构造一个没有详细消息的业务异常,默认构造函数。 + *

+ * 此构造函数通常用于不需要提供具体原因的情况下,或者在后续代码中会补充更详细的错误信息时使用。 + */ + public BaseException() { + super(); + } + + /** + * 构造一个带有指定详细消息的业务异常。 + * + * @param msg 异常的详细消息,描述了发生的具体问题或错误情况。 + * 这个消息可以被用来向用户展示错误提示,也可以记录到日志中供调试和分析。 + */ + public BaseException(String msg) { + super(msg); + } +} \ No newline at end of file diff --git a/sky/sky-common/src/main/java/com/sky/exception/PasswordEditFailedException.java b/sky/sky-common/src/main/java/com/sky/exception/PasswordEditFailedException.java new file mode 100644 index 0000000..b47a0fd --- /dev/null +++ b/sky/sky-common/src/main/java/com/sky/exception/PasswordEditFailedException.java @@ -0,0 +1,19 @@ +package com.sky.exception; + +/** + * PasswordEditFailedException类用于表示密码修改操作失败时所抛出的特定异常情况。 + * 它继承自BaseException,这样可以复用BaseException中定义的与异常处理相关的通用逻辑(例如可能包含的统一的错误消息记录、日志打印等功能)。 + * 当在系统中进行密码修改的相关业务逻辑出现问题,导致修改无法成功完成时,就可以抛出该异常来清晰地传达错误信息,方便上层调用者进行针对性的异常处理。 + */ +public class PasswordEditFailedException extends BaseException { + + /** + * 构造函数,用于创建PasswordEditFailedException类的实例。 + * + * @param msg 传递进来的表示具体错误消息的字符串,这个消息将被传递给父类BaseException的构造函数, + * 以便后续在处理该异常时可以获取到详细的错误原因说明。例如,msg可能是像"密码长度不符合要求导致修改失败"之类的具体提示信息。 + */ + public PasswordEditFailedException(String msg) { + super(msg); + } +} diff --git a/sky/sky-common/src/main/java/com/sky/exception/UserNotLoginException.java b/sky/sky-common/src/main/java/com/sky/exception/UserNotLoginException.java new file mode 100644 index 0000000..fe26906 --- /dev/null +++ b/sky/sky-common/src/main/java/com/sky/exception/UserNotLoginException.java @@ -0,0 +1,30 @@ +package com.sky.exception; + +/** + * UserNotLoginException类是一个自定义的异常类,用于表示用户未登录的异常情况。 + * 在应用程序中,当需要判断用户是否登录并且发现用户未登录而某些操作又需要用户处于登录状态才能执行时, + * 就可以抛出这个异常来明确地告知调用者出现了用户未登录的问题,以便进行相应的异常处理,比如提示用户登录、重定向到登录页面等操作。 + * 该类继承自BaseException,这样可以借助BaseException中已有的与异常处理相关的通用机制,例如可能存在的统一记录异常日志、 + * 按特定格式处理错误消息等功能,方便在整个项目中对异常进行标准化管理。 + */ +public class UserNotLoginException extends BaseException { + + /** + * 默认构造函数,无参构造函数。 + * 当不需要传递具体的错误消息,只是想单纯抛出表示用户未登录这个异常情况时,可以使用该构造函数来创建异常实例。 + * 不过通常情况下,使用带有具体错误消息的构造函数能提供更详细准确的异常信息,方便后续处理。 + */ + public UserNotLoginException() { + } + + /** + * 带有具体错误消息的构造函数。 + * + * @param msg 一个表示具体错误消息的字符串参数,它将被传递给父类BaseException的构造函数, + * 进而可以在后续处理该异常时获取到详细的错误提示信息。 + * 例如,msg可以是"用户未登录,无法访问个人资料页面"之类明确指出因未登录导致具体操作受限的提示内容。 + */ + public UserNotLoginException(String msg) { + super(msg); + } +} diff --git a/sky/sky-common/src/main/java/com/sky/properties/ReportExcelProperties.java b/sky/sky-common/src/main/java/com/sky/properties/ReportExcelProperties.java new file mode 100644 index 0000000..ad3f3aa --- /dev/null +++ b/sky/sky-common/src/main/java/com/sky/properties/ReportExcelProperties.java @@ -0,0 +1,37 @@ +package com.sky.properties; + +import lombok.Data; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.Arrays; + +/** + * ReportExcelProperties类用于配置与Excel相关的属性信息。 + * 它在Spring Boot项目中扮演着重要角色,通过将配置文件中的相关属性值绑定到该类的成员变量上,方便在程序中使用这些配置数据。 + * 例如,配置Excel文件的路径以及相关工作表(sheet)的信息等。 + */ +@Component +// 使用@Component注解将该类标记为Spring的组件,这样Spring容器能够扫描并管理它,使其可以在项目的其他地方通过依赖注入等方式使用。 +@ConfigurationProperties(prefix = "sky.excel") +// @ConfigurationProperties注解用于指定配置属性的前缀,Spring Boot会自动将配置文件中以"sky.excel"为前缀的属性值绑定到该类对应的成员变量上。 +@Data +// 使用Lombok的@Data注解,它会自动为类生成常用的方法,比如Getter、Setter、toString、equals和hashCode等方法,简化代码编写,提高开发效率。 +public class ReportExcelProperties { + /** + * 用于存储Excel文件的路径。 + * 这个路径可以是相对路径(相对于项目的某个基准目录)或者绝对路径,具体取决于项目的配置和需求。 + * Spring Boot会根据配置文件中对应的"sky.excel.filePath"属性值来自动填充这个变量。 + */ + private String filePath; + + /** + * 用于存储Excel文件中工作表(sheet)的名称数组。 + * 可以通过配置文件中以"sky.excel.sheet"开头的多个属性值来填充这个数组,这些值将被解析并转换为字符串数组,方便后续在操作Excel文件时指定要处理的工作表。 + * 例如,配置文件中可以配置像"sky.excel.sheet[0]=Sheet1"、"sky.excel.sheet[1]=Sheet2"这样的属性来定义多个工作表名称,它们会被绑定到这个数组中,对应的数组形式为{"Sheet1", "Sheet2"}。 + */ + private String[] sheet; + +} diff --git a/sky/sky-common/src/main/java/com/sky/utils/AliOssUtil.java b/sky/sky-common/src/main/java/com/sky/utils/AliOssUtil.java new file mode 100644 index 0000000..c95e72f --- /dev/null +++ b/sky/sky-common/src/main/java/com/sky/utils/AliOssUtil.java @@ -0,0 +1,113 @@ +package com.sky.utils; + +import com.aliyun.oss.ClientException; +import com.aliyun.oss.OSS; +import com.aliyun.oss.OSSClientBuilder; +import com.aliyun.oss.OSSException; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayInputStream; + +/** + * AliOssUtil类是一个工具类,主要用于与阿里云对象存储服务(OSS)进行交互,实现文件上传的功能。 + * 它利用了阿里云OSS的Java SDK,方便在Spring Boot项目中将本地文件以字节数组的形式上传到指定的OSS存储桶中,并返回文件在OSS上的访问路径。 + */ +@Data +// 使用Lombok的@Data注解,会自动为类中的私有成员变量生成对应的Getter、Setter方法,以及toString、equals和hashCode等方法,简化代码编写。 +@Slf4j +// 使用Lombok的@Slf4j注解,会在类中自动生成一个名为log的Slf4j日志记录器,方便在代码中记录相关的操作信息、异常等情况,便于调试和监控。 +@Component +// 使用@Component注解将该类标记为Spring框架中的一个组件,这样Spring容器能够自动扫描并管理它,使得该类可以在项目的其他地方通过依赖注入等方式被使用。 +@AllArgsConstructor +// 使用Lombok的@AllArgsConstructor注解,会自动生成一个包含所有成员变量的构造函数,方便在创建类实例时进行参数注入等操作。 +@NoArgsConstructor +// 使用Lombok的@NoArgsConstructor注解,会自动生成一个无参构造函数,满足某些场景下需要默认构造函数的需求,例如在一些框架进行对象实例化时可能会调用无参构造函数。 +public class AliOssUtil { + + /** + * 阿里云OSS服务的访问端点(Endpoint)。 + * 它指定了与阿里云OSS进行通信的网络地址,不同的地域对应的Endpoint是不同的,通过配置该属性可以准确连接到对应的OSS服务区域。 + * 例如:"oss-cn-hangzhou.aliyuncs.com"表示阿里云杭州地域的OSS端点,该属性的值通常会从项目的配置文件(如application.properties或application.yml)中获取并注入到这个变量中。 + */ + private String endpoint; + + /** + * 阿里云OSS服务的访问密钥ID(Access Key ID)。 + * 它是用于身份验证的重要凭据之一,与Access Key Secret一起,用于确认调用OSS服务的合法性,相当于用户在阿里云OSS服务中的账号标识,只有拥有正确的Access Key ID和Access Key Secret才能进行相应的操作,如上传、下载文件等。 + * 同样,该值也是从项目的配置文件中安全地获取并注入到此变量中的。 + */ + private String accessKeyId; + + /** + * 阿里云OSS服务的访问密钥(Access Key Secret)。 + * 与Access Key ID配合使用,用于对请求进行签名验证,确保请求的安全性和合法性,是访问OSS服务的重要安全凭证,需要妥善保管,防止泄露。 + * 其值通过配置文件注入到该变量中。 + */ + private String accessKeySecret; + + /** + * 阿里云OSS存储桶(Bucket)的名称。 + * 存储桶是OSS中用于存储对象(如文件等)的容器,类似于文件系统中的文件夹概念,但功能更强大,所有上传到OSS的文件都要存放在某个特定的存储桶中,通过指定该名称,就能确定文件上传的目标存储位置。 + * 其名称由用户在阿里云控制台创建存储桶时定义,并且在项目配置中指定,以便在代码中使用。 + */ + private String bucketName; + + /** + * 文件上传方法,用于将给定的字节数组形式的文件内容上传到阿里云OSS指定的存储桶中,并返回文件在OSS上的访问路径。 + * + * @param bytes 文件字节码,即代表要上传文件的内容以字节数组的形式传入,例如可以通过读取本地文件并转换为字节数组后传递进来,以便将该文件上传到OSS中。 + * @param objectName 文件名字,它是文件在OSS存储桶中的对象名称,也就是文件在OSS中的唯一标识,类似于文件在本地文件系统中的文件名,需要注意命名的唯一性和合法性,遵循OSS的命名规范。 + * @return 返回文件上传路径,即文件上传成功后在阿里云OSS上可通过网络访问的完整URL地址,格式通常为"https://BucketName.Endpoint/ObjectName",方便后续在项目中使用该路径进行文件的访问、展示等操作。 + */ + public String upload(byte[] bytes, String objectName) { + + // 创建OSSClient实例。 + // 通过OSSClientBuilder构建器,使用传入的endpoint、accessKeyId和accessKeySecret来创建一个与阿里云OSS服务进行交互的客户端实例, + // 该客户端实例将用于后续的文件上传等操作,它封装了与OSS服务通信的底层细节,提供了一系列方便的方法来操作OSS资源。 + OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret); + try { + // 创建PutObject请求。 + // 使用ossClient的putObject方法创建一个文件上传请求,将指定的字节数组内容(通过ByteArrayInputStream包装后)上传到指定的bucketName存储桶中,以objectName作为对象名称。 + // 这个操作实际上就是向OSS服务发送请求,将本地的文件数据传输到云端存储桶里,如果上传过程中出现OSS相关的异常情况,会被相应的异常处理机制捕获。 + ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(bytes)); + } catch (OSSException oe) { + // 捕获OSSException异常,该异常表示请求已经发送到OSS服务端,但由于某些原因(如权限问题、资源不存在等)被服务端拒绝,并返回了错误响应信息。 + // 下面的代码主要是将OSS服务端返回的详细错误信息打印出来,方便开发人员定位问题,例如错误消息、错误代码、请求ID以及主机ID等信息都有助于排查问题所在。 + System.out.println("Caught an OSSException, which means your request made it to OSS, " + + "but was rejected with an error response for some reason."); + System.out.println("Error Message:" + oe.getErrorMessage()); + System.out.println("Error Code:" + oe.getErrorCode()); + System.out.println("Request ID:" + oe.getRequestId()); + System.out.println("Host ID:" + oe.getHostId()); + } catch (ClientException ce) { + // 捕获ClientException异常,该异常表示客户端在尝试与OSS服务进行通信时遇到了严重的内部问题,比如无法访问网络等情况, + // 通常是客户端自身环境或者配置方面的问题导致无法正常连接到OSS服务,这里同样打印出错误消息,以便分析是哪里出现了通信故障。 + System.out.println("Caught an ClientException, which means the client encountered " + + "a serious internal problem while trying to communicate with OSS, " + + "such as not being able to access the network."); + System.out.println("Error Message:" + ce.getMessage()); + } finally { + if (ossClient!= null) { + // 无论文件上传是否成功,都需要关闭OSSClient实例,释放相关的资源,避免资源泄露,保证程序的稳定性和性能。 + ossClient.shutdown(); + } + } + + // 文件访问路径规则 https://BucketName.Endpoint/ObjectName + StringBuilder stringBuilder = new StringBuilder("https://"); + stringBuilder + .append(bucketName) + .append(".") + .append(endpoint) + .append("/") + .append(objectName); + + log.info("文件上传到:{}", stringBuilder); + + return stringBuilder.toString(); + } +} diff --git a/sky/sky-pojo/src/main/java/com/sky/dto/DataOverViewQueryDTO.java b/sky/sky-pojo/src/main/java/com/sky/dto/DataOverViewQueryDTO.java new file mode 100644 index 0000000..38b9807 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/dto/DataOverViewQueryDTO.java @@ -0,0 +1,17 @@ +// 定义了一个名为DataOverViewQueryDTO的类,它位于com.sky.dto包中。 +// 这个类实现了Serializable接口,这意味着它可以被序列化,通常用于网络传输或持久化到文件中。 + +// 使用Lombok提供的注解@Data,这个注解自动为类生成getter和setter方法,以及equals、hashCode和toString方法。 +// 使用@Builder注解,这个注解自动为类生成一个Builder模式的构建器,用于创建类的实例。 +// 使用@NoArgsConstructor注解,这个注解自动为类生成一个无参的构造函数。 +// 使用@AllArgsConstructor注解,这个注解自动为类生成一个包含所有成员变量的构造函数。 + +public class DataOverViewQueryDTO implements Serializable { + + // 成员变量begin,类型为LocalDateTime,表示查询的开始时间。 + private LocalDateTime begin; + + // 成员变量end,类型为LocalDateTime,表示查询的结束时间。 + private LocalDateTime end; + +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/dto/EmployeeLoginDTO.java b/sky/sky-pojo/src/main/java/com/sky/dto/EmployeeLoginDTO.java new file mode 100644 index 0000000..424e5bc --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/dto/EmployeeLoginDTO.java @@ -0,0 +1,29 @@ +// 导入所需的包 +package com.sky.dto; + +// 导入Swagger注解,用于生成API文档 +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +// 导入Lombok注解,用于简化Java对象的创建 +import lombok.Data; +// 导入Serializable接口,使得类可以被序列化 +import java.io.Serializable; + +// 使用@Data注解,Lombok会自动为这个类生成getter和setter方法,以及equals、hashCode和toString方法。 +@Data +// 使用@ApiModel注解,指定这个类是Swagger文档中的一个模型,并提供模型的描述。 +@ApiModel(description = "员工登录时传递的数据模型") +// 声明这个类实现了Serializable接口,这意味着它可以被序列化,通常用于网络传输或持久化到文件中。 +public class EmployeeLoginDTO implements Serializable { + + // 使用@ApiModelProperty注解,为username字段提供API文档中的描述。 + @ApiModelProperty("用户名") + // 定义一个私有字段username,类型为String,用于存储员工的用户名。 + private String username; + + // 使用@ApiModelProperty注解,为password字段提供API文档中的描述。 + @ApiModelProperty("密码") + // 定义一个私有字段password,类型为String,用于存储员工的密码。 + private String password; + +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/dto/OrdersConfirmDTO.java b/sky/sky-pojo/src/main/java/com/sky/dto/OrdersConfirmDTO.java new file mode 100644 index 0000000..b6aa2aa --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/dto/OrdersConfirmDTO.java @@ -0,0 +1,28 @@ +// 导入所需的包 +package com.sky.dto; + +// 导入Lombok注解,用于简化Java对象的创建 +import lombok.Data; +// 导入Serializable接口,使得类可以被序列化 +import java.io.Serializable; + +// 使用@Data注解,Lombok会自动为这个类生成getter和setter方法,以及equals、hashCode和toString方法。 +@Data +// 声明这个类实现了Serializable接口,这意味着它可以被序列化,通常用于网络传输或持久化到文件中。 +public class OrdersConfirmDTO implements Serializable { + + // 定义一个私有字段id,类型为Long,用于存储订单的唯一标识符。 + private Long id; + + // 定义一个私有字段status,类型为Integer,用于存储订单的状态。 + // 订单状态的不同值代表不同的订单处理阶段: + // 1 - 待付款 + // 2 - 待接单 + // 3 - 已接单 + // 4 - 派送中 + // 5 - 已完成 + // 6 - 已取消 + // 7 - 退款 + private Integer status; + +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/dto/OrdersRejectionDTO.java b/sky/sky-pojo/src/main/java/com/sky/dto/OrdersRejectionDTO.java new file mode 100644 index 0000000..16a51d3 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/dto/OrdersRejectionDTO.java @@ -0,0 +1,21 @@ +// 导入所需的包 +package com.sky.dto; + +// 导入Lombok注解,用于简化Java对象的创建 +import lombok.Data; +// 导入Serializable接口,使得类可以被序列化 +import java.io.Serializable; + +// 使用@Data注解,Lombok会自动为这个类生成getter和setter方法,以及equals、hashCode和toString方法。 +@Data +// 声明这个类实现了Serializable接口,这意味着它可以被序列化,通常用于网络传输或持久化到文件中。 +public class OrdersRejectionDTO implements Serializable { + + // 定义一个私有字段id,类型为Long,用于存储订单的唯一标识符。 + private Long id; + + // 定义一个私有字段rejectionReason,类型为String,用于存储订单被拒绝的原因。 + // 这个字段用于在订单被拒绝时提供详细的解释或理由。 + private String rejectionReason; + +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/dto/SetmealPageQueryDTO.java b/sky/sky-pojo/src/main/java/com/sky/dto/SetmealPageQueryDTO.java new file mode 100644 index 0000000..85d5346 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/dto/SetmealPageQueryDTO.java @@ -0,0 +1,31 @@ +// 导入所需的包 +package com.sky.dto; + +// 导入Lombok注解,用于简化Java对象的创建 +import lombok.Data; +// 导入Serializable接口,使得类可以被序列化 +import java.io.Serializable; + +// 使用@Data注解,Lombok会自动为这个类生成getter和setter方法,以及equals、hashCode和toString方法。 +@Data +// 声明这个类实现了Serializable接口,这意味着它可以被序列化,通常用于网络传输或持久化到文件中。 +public class SetmealPageQueryDTO implements Serializable { + + // 定义一个私有字段page,类型为int,用于存储分页查询的当前页码。 + private int page; + + // 定义一个私有字段pageSize,类型为int,用于存储分页查询中每页显示的记录数。 + private int pageSize; + + // 定义一个私有字段name,类型为String,用于存储套餐名称的查询条件。 + private String name; + + // 定义一个私有字段categoryId,类型为Integer,用于存储分类id的查询条件。 + // 分类id用于筛选特定分类下的套餐。 + private Integer categoryId; + + // 定义一个私有字段status,类型为Integer,用于存储状态的查询条件。 + // 状态字段的值0表示禁用,1表示启用,用于筛选启用或禁用的套餐。 + private Integer status; + +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/entity/Category.java b/sky/sky-pojo/src/main/java/com/sky/entity/Category.java new file mode 100644 index 0000000..6b648e5 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/entity/Category.java @@ -0,0 +1,56 @@ +// 定义了一个名为com.sky.entity的包,用于存放实体类 +package com.sky.entity; + +// 导入了Lombok库中的注解,用于简化实体类的编写 +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +// 导入了Serializable接口,使得Category类的对象可以被序列化,用于网络传输或文件存储 +import java.io.Serializable; + +// 导入了LocalDateTime类,用于存储日期和时间 +import java.time.LocalDateTime; + +// 使用@Data注解自动生成getter和setter方法,以及equals、hashCode和toString方法 +@Data +// 使用@Builder注解自动生成builder模式代码,方便对象的构建 +@Builder +// 使用@NoArgsConstructor注解自动生成无参构造方法 +@NoArgsConstructor +// 使用@AllArgsConstructor注解自动生成包含所有属性的构造方法 +@AllArgsConstructor +// 声明Category类,实现了Serializable接口,表示该类的对象可以被序列化 +public class Category implements Serializable { + + // 定义了一个serialVersionUID,用于在序列化时保持版本的一致性 + private static final long serialVersionUID = 1L; + + // 定义了一个id属性,类型为Long,表示分类的唯一标识 + private Long id; + + // 定义了一个type属性,类型为Integer,表示分类的类型:1表示菜品分类,2表示套餐分类 + private Integer type; + + // 定义了一个name属性,类型为String,表示分类的名称 + private String name; + + // 定义了一个sort属性,类型为Integer,表示分类的顺序 + private Integer sort; + + // 定义了一个status属性,类型为Integer,表示分类的状态:0表示禁用,1表示启用 + private Integer status; + + // 定义了一个createTime属性,类型为LocalDateTime,表示分类的创建时间 + private LocalDateTime createTime; + + // 定义了一个updateTime属性,类型为LocalDateTime,表示分类的更新时间 + private LocalDateTime updateTime; + + // 定义了一个createUser属性,类型为Long,表示创建分类的用户ID + private Long createUser; + + // 定义了一个updateUser属性,类型为Long,表示更新分类的用户ID + private Long updateUser; +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/entity/OrderDetail.java b/sky/sky-pojo/src/main/java/com/sky/entity/OrderDetail.java new file mode 100644 index 0000000..fe99814 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/entity/OrderDetail.java @@ -0,0 +1,59 @@ +// 定义了一个名为com.sky.entity的包,用于存放实体类 +package com.sky.entity; + +// 导入了Lombok库中的注解,用于简化实体类的编写 +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +// 导入了Serializable接口,使得OrderDetail类的对象可以被序列化,用于网络传输或文件存储 +import java.io.Serializable; + +// 导入了BigDecimal类,用于精确表示货币金额 +import java.math.BigDecimal; + +/** + * 订单明细 + */ +// 使用@Data注解自动生成getter和setter方法,以及equals、hashCode和toString方法 +@Data +// 使用@Builder注解自动生成builder模式代码,方便对象的构建 +@Builder +// 使用@NoArgsConstructor注解自动生成无参构造方法 +@NoArgsConstructor +// 使用@AllArgsConstructor注解自动生成包含所有属性的构造方法 +@AllArgsConstructor +// 声明OrderDetail类,实现了Serializable接口,表示该类的对象可以被序列化 +public class OrderDetail implements Serializable { + + // 定义了一个serialVersionUID,用于在序列化时保持版本的一致性 + private static final long serialVersionUID = 1L; + + // 定义了一个id属性,类型为Long,表示订单明细的唯一标识 + private Long id; + + // 定义了一个name属性,类型为String,表示订单明细的名称 + private String name; + + // 定义了一个orderId属性,类型为Long,表示所属订单的ID + private Long orderId; + + // 定义了一个dishId属性,类型为Long,表示菜品的ID + private Long dishId; + + // 定义了一个setmealId属性,类型为Long,表示套餐的ID + private Long setmealId; + + // 定义了一个dishFlavor属性,类型为String,表示菜品的口味 + private String dishFlavor; + + // 定义了一个number属性,类型为Integer,表示订单明细的数量 + private Integer number; + + // 定义了一个amount属性,类型为BigDecimal,表示订单明细的金额 + private BigDecimal amount; + + // 定义了一个image属性,类型为String,表示订单明细的图片路径或URL + private String image; +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/entity/ShoppingCart.java b/sky/sky-pojo/src/main/java/com/sky/entity/ShoppingCart.java new file mode 100644 index 0000000..3d27ff8 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/entity/ShoppingCart.java @@ -0,0 +1,65 @@ +// 定义了一个名为com.sky.entity的包,用于存放实体类 +package com.sky.entity; + +// 导入了Lombok库中的注解,用于简化实体类的编写 +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +// 导入了Serializable接口,使得ShoppingCart类的对象可以被序列化,用于网络传输或文件存储 +import java.io.Serializable; + +// 导入了BigDecimal类,用于精确表示货币金额 +import java.math.BigDecimal; + +// 导入了LocalDateTime类,用于存储日期和时间 +import java.time.LocalDateTime; + +/** + * 购物车实体类,用于存储购物车中的商品信息 + */ +// 使用@Data注解自动生成getter和setter方法,以及equals、hashCode和toString方法 +@Data +// 使用@Builder注解自动生成builder模式代码,方便对象的构建 +@Builder +// 使用@NoArgsConstructor注解自动生成无参构造方法 +@NoArgsConstructor +// 使用@AllArgsConstructor注解自动生成包含所有属性的构造方法 +@AllArgsConstructor +// 声明ShoppingCart类,实现了Serializable接口,表示该类的对象可以被序列化 +public class ShoppingCart implements Serializable { + + // 定义了一个serialVersionUID,用于在序列化时保持版本的一致性 + private static final long serialVersionUID = 1L; + + // 定义了一个id属性,类型为Long,表示购物车的唯一标识 + private Long id; + + // 定义了一个name属性,类型为String,表示购物车的名称或描述 + private String name; + + // 定义了一个userId属性,类型为Long,表示用户的ID + private Long userId; + + // 定义了一个dishId属性,类型为Long,表示菜品的ID + private Long dishId; + + // 定义了一个setmealId属性,类型为Long,表示套餐的ID + private Long setmealId; + + // 定义了一个dishFlavor属性,类型为String,表示菜品的口味 + private String dishFlavor; + + // 定义了一个number属性,类型为Integer,表示商品的数量 + private Integer number; + + // 定义了一个amount属性,类型为BigDecimal,表示商品的总金额 + private BigDecimal amount; + + // 定义了一个image属性,类型为String,表示商品的图片路径或URL + private String image; + + // 定义了一个createTime属性,类型为LocalDateTime,表示购物车创建的时间 + private LocalDateTime createTime; +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/vo/DishOverViewVO.java b/sky/sky-pojo/src/main/java/com/sky/vo/DishOverViewVO.java new file mode 100644 index 0000000..f1c5e3d --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/vo/DishOverViewVO.java @@ -0,0 +1,31 @@ +// 定义了一个名为com.sky.vo的包,用于存放视图对象类 +package com.sky.vo; + +// 导入了Lombok库中的注解,用于简化类的编写 +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +// 导入了Serializable接口,使得DishOverViewVO类的对象可以被序列化,用于网络传输或文件存储 +import java.io.Serializable; + +/** + * 菜品总览视图对象,用于展示菜品的总体信息,如已启售和已停售的数量。 + */ +// 使用@Data注解自动生成getter和setter方法,以及equals、hashCode和toString方法 +@Data +// 使用@Builder注解自动生成builder模式代码,方便对象的构建 +@Builder +// 使用@NoArgsConstructor注解自动生成无参构造方法 +@NoArgsConstructor +// 使用@AllArgsConstructor注解自动生成包含所有属性的构造方法 +@AllArgsConstructor +// 声明DishOverViewVO类,实现了Serializable接口,表示该类的对象可以被序列化 +public class DishOverViewVO implements Serializable { + // 定义了一个sold属性,类型为Integer,表示已启售的菜品数量 + private Integer sold; + + // 定义了一个discontinued属性,类型为Integer,表示已停售的菜品数量 + private Integer discontinued; +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/vo/OrderPaymentVO.java b/sky/sky-pojo/src/main/java/com/sky/vo/OrderPaymentVO.java new file mode 100644 index 0000000..1db1165 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/vo/OrderPaymentVO.java @@ -0,0 +1,40 @@ +// 定义了一个名为com.sky.vo的包,用于存放视图对象类 +package com.sky.vo; + +// 导入了Lombok库中的注解,用于简化类的编写 +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +// 导入了Serializable接口,使得OrderPaymentVO类的对象可以被序列化,用于网络传输或文件存储 +import java.io.Serializable; + +/** + * 订单支付视图对象,用于封装支付过程中需要的数据。 + */ +// 使用@Data注解自动生成getter和setter方法,以及equals、hashCode和toString方法 +@Data +// 使用@Builder注解自动生成builder模式代码,方便对象的构建 +@Builder +// 使用@NoArgsConstructor注解自动生成无参构造方法 +@NoArgsConstructor +// 使用@AllArgsConstructor注解自动生成包含所有属性的构造方法 +@AllArgsConstructor +// 声明OrderPaymentVO类,实现了Serializable接口,表示该类的对象可以被序列化 +public class OrderPaymentVO implements Serializable { + // 定义了一个nonceStr属性,类型为String,表示随机字符串,用于支付过程中的随机性 + private String nonceStr; + + // 定义了一个paySign属性,类型为String,表示签名,用于验证支付请求的合法性 + private String paySign; + + // 定义了一个timeStamp属性,类型为String,表示时间戳,用于记录支付请求的时间 + private String timeStamp; + + // 定义了一个signType属性,类型为String,表示签名算法,用于指定签名的算法类型 + private String signType; + + // 定义了一个packageStr属性,类型为String,表示统一下单接口返回的prepay_id参数值,用于后续支付流程 + private String packageStr; +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/vo/OrderVO.java b/sky/sky-pojo/src/main/java/com/sky/vo/OrderVO.java new file mode 100644 index 0000000..2272684 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/vo/OrderVO.java @@ -0,0 +1,36 @@ +// 定义了一个名为com.sky.vo的包,用于存放视图对象类 +package com.sky.vo; + +// 导入了实体类Orders和OrderDetail,以便在视图对象中使用 +import com.sky.entity.OrderDetail; +import com.sky.entity.Orders; + +// 导入了Lombok库中的注解,用于简化类的编写 +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +// 导入了Serializable接口,使得OrderVO类的对象可以被序列化,用于网络传输或文件存储 +import java.io.Serializable; + +// 导入了List接口,用于存储订单详情列表 +import java.util.List; + +/** + * 订单视图对象,扩展自Orders实体类,用于展示订单的详细信息。 + */ +// 使用@Data注解自动生成getter和setter方法,以及equals、hashCode和toString方法 +@Data +// 使用@NoArgsConstructor注解自动生成无参构造方法 +@NoArgsConstructor +// 使用@AllArgsConstructor注解自动生成包含所有属性的构造方法 +@AllArgsConstructor +// 声明OrderVO类,继承自Orders实体类,并实现了Serializable接口,表示该类的对象可以被序列化 +public class OrderVO extends Orders implements Serializable { + + // 定义了一个orderDishes属性,类型为String,表示订单中的菜品信息,通常用于展示订单中包含的所有菜品的名称或描述 + private String orderDishes; + + // 定义了一个orderDetailList属性,类型为List,表示订单详情列表,包含了订单中每个商品的详细信息 + private List orderDetailList; +} \ No newline at end of file diff --git a/sky/sky-pojo/src/main/java/com/sky/vo/TurnoverReportVO.java b/sky/sky-pojo/src/main/java/com/sky/vo/TurnoverReportVO.java new file mode 100644 index 0000000..3bb4ec2 --- /dev/null +++ b/sky/sky-pojo/src/main/java/com/sky/vo/TurnoverReportVO.java @@ -0,0 +1,38 @@ +// 定义了一个名为com.sky.vo的包,用于存放视图对象类 +package com.sky.vo; + +// 导入了Lombok库中的注解,用于简化类的编写 +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; + +// 导入了Serializable接口,使得TurnoverReportVO类的对象可以被序列化,用于网络传输或文件存储 +import java.io.Serializable; + +/** + * 营业额报告视图对象,用于展示特定日期范围内的营业额数据。 + */ +// 使用@Data注解自动生成getter和setter方法,以及equals、hashCode和toString方法 +@Data +// 使用@Builder注解自动生成builder模式代码,方便对象的构建 +@Builder +// 使用@NoArgsConstructor注解自动生成无参构造方法 +@NoArgsConstructor +// 使用@AllArgsConstructor注解自动生成包含所有属性的构造方法 +@AllArgsConstructor +// 声明TurnoverReportVO类,实现了Serializable接口,表示该类的对象可以被序列化 +public class TurnoverReportVO implements Serializable { + + /** + * 表示日期的字符串,日期之间以逗号分隔。 + * 例如:"2022-10-01,2022-10-02,2022-10-03",用于展示营业额报告的日期范围。 + */ + private String dateList; + + /** + * 表示营业额的字符串,营业额之间以逗号分隔。 + * 例如:"406.0,1520.0,75.0",用于展示对应日期的营业额数据。 + */ + private String turnoverList; +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/config/RedisConfiguration.java b/sky/sky-server/src/main/java/com/sky/config/RedisConfiguration.java new file mode 100644 index 0000000..10dd9af --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/config/RedisConfiguration.java @@ -0,0 +1,35 @@ +// 导入所需的包 +package com.sky.config; + +// 导入Lombok提供的@Slf4j注解,用于自动注入一个日志对象 +import lombok.extern.slf4j.Slf4j; +// 导入Spring框架的配置注解,用于声明这是一个配置类 +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +// 导入Spring Data Redis的连接工厂接口 +import org.springframework.data.redis.connection.RedisConnectionFactory; +// 导入Spring Data Redis的核心组件,用于操作Redis +import org.springframework.data.redis.core.RedisTemplate; +// 导入Spring Data Redis的字符串序列化器 +import org.springframework.data.redis.serializer.StringRedisSerializer; + +// 使用@Configuration注解,声明这个类是一个Spring配置类,其中的Bean会被Spring容器自动扫描和管理。 +@Configuration +// 使用@Slf4j注解,自动为这个类注入一个日志对象,方便记录日志信息。 +@Slf4j +public class RedisConfiguration { + // 使用@Bean注解,声明一个Bean,Spring容器会调用这个方法来创建Bean,并将其加入到容器中。 + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) { + // 记录日志信息,表示开始创建Redis模板对象。 + log.info("开始创建redis模版对象..."); + // 创建RedisTemplate实例,泛型参数为Object,表示键和值都可以是任意类型的对象。 + RedisTemplate redisTemplate = new RedisTemplate<>(); + // 设置连接工厂对象,这个对象负责与Redis服务器建立连接。 + redisTemplate.setConnectionFactory(redisConnectionFactory); + // 设置Redis key的序列化器,这里使用StringRedisSerializer,表示key会被序列化为String类型。 + redisTemplate.setKeySerializer(new StringRedisSerializer()); + // 返回配置好的RedisTemplate对象,它将被Spring容器管理。 + return redisTemplate; + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/admin/CommonController.java b/sky/sky-server/src/main/java/com/sky/controller/admin/CommonController.java new file mode 100644 index 0000000..4b7320b --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/admin/CommonController.java @@ -0,0 +1,68 @@ +// 导入所需的包 +package com.sky.controller.admin; + +// 导入项目中定义的消息常量类 +import com.sky.constant.MessageConstant; +// 导入项目中定义的结果封装类 +import com.sky.result.Result; +// 导入项目中定义的通用服务接口 +import com.sky.service.CommonService; +// 导入Swagger注解,用于生成API文档 +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +// 导入Lombok提供的@Slf4j注解,用于自动注入一个日志对象 +import lombok.extern.slf4j.Slf4j; +// 导入Spring框架的自动注入注解 +import org.springframework.beans.factory.annotation.Autowired; +// 导入Spring框架的映射注解 +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +// 导入Spring框架的文件上传组件 +import org.springframework.web.multipart.MultipartFile; + +// 导入Java IO异常类 +import java.io.IOException; + +// 使用@RestController注解,声明这个类是一个Spring MVC的控制器,并且返回的数据会自动以JSON格式响应。 +@RestController +// 使用@RequestMapping注解,声明这个控制器处理请求的基本路径。 +@RequestMapping("/admin/common") +// 使用@Api注解,指定这个控制器是Swagger文档中的一个API,并提供API的描述。 +@Api("通用接口") +// 使用@Slf4j注解,自动为这个类注入一个日志对象,方便记录日志信息。 +@Slf4j +public class CommonController { + + // 使用@Autowired注解,自动注入CommonService服务。 + @Autowired + // 定义CommonService类型的变量commmonService,注意这里有一个拼写错误,应该是commonService。 + CommonService commmonService; + + /** + * 文件上传的处理方法。 + * + * @param file 前端传过来的文件,使用MultipartFile类型表示。 + * @return 返回一个Result对象,其中包含操作结果和消息。 + */ + // 使用@ApiOperation注解,为Swagger文档提供文件上传操作的描述。 + @ApiOperation("文件上传") + // 使用@PostMapping注解,指定这个方法处理POST请求。 + @PostMapping("/upload") + public Result upload(MultipartFile file) { + // 记录日志信息,包括文件上传的操作和传入的文件对象。 + log.info("文件上传{}", file); + // 定义一个String类型的变量filePath,用于存储文件上传后的路径。 + String filePath; + try { + // 调用commmonService的upload方法,上传文件,并返回文件路径。 + filePath = commmonService.upload(file); + } catch (IOException e) { + // 如果发生IOException异常,返回错误结果,使用MessageConstant中的UPLOAD_FAILED常量作为错误消息。 + return Result.error(MessageConstant.UPLOAD_FAILED); + } + + // 如果文件上传成功,返回成功结果,包含文件路径。 + return Result.success(filePath); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/admin/ReportController.java b/sky/sky-server/src/main/java/com/sky/controller/admin/ReportController.java new file mode 100644 index 0000000..a404bd2 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/admin/ReportController.java @@ -0,0 +1,134 @@ +// 定义了一个名为com.sky.controller.admin的包,用于存放控制器类 +package com.sky.controller.admin; + +// 导入了项目中定义的结果类 +import com.sky.result.Result; +// 导入了项目中定义的报告服务接口 +import com.sky.service.ReportService; +// 导入了项目中定义的视图对象类 +import com.sky.vo.*; +// 导入了Swagger注解,用于API文档的生成 +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +// 导入了Lombok提供的@Slf4j注解,用于简化日志操作 +import lombok.extern.slf4j.Slf4j; +// 导入了HttpServletResponse类,用于处理HTTP响应 +import javax.servlet.http.HttpServletResponse; +// 导入了IOException类,用于处理可能发生的IO异常 +import java.io.IOException; +// 导入了LocalDate类,用于处理日期 +import java.time.LocalDate; +// 导入了InvalidFormatException类,用于处理可能发生格式无效的异常 +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; + +/** + * 报告控制器,提供营业额、用户统计、订单统计、销量排行等报告接口服务。 + */ +// 使用@RestController注解声明这是一个控制器类,并且返回的数据会自动以JSON格式响应 +@RestController +// 使用@RequestMapping注解定义这个控制器类的基础请求映射路径 +@RequestMapping("/admin/report") +// 使用@Slf4j注解提供日志功能 +@Slf4j +// 使用@Api注解为这个控制器类添加Swagger文档的描述 +@Api("营业额相关接口") +public class ReportController { + + // 自动注入ReportService + @Autowired + ReportService reportService; + + /** + * 营业额统计接口。 + * + * @param begin 开始日期 + * @param end 结束日期 + * @return 返回营业额统计的结果 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("营业额相关接口") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/turnoverStatistics") + public Result turnoverStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) { + // 使用日志记录营业额统计的操作 + log.info("营业额统计:{},{}", begin, end); + // 调用ReportService的getTurnoverStatistics方法获取营业额统计结果 + return reportService.getTurnoverStatistics(begin, end); + } + + /** + * 用户统计接口。 + * + * @param begin 开始日期 + * @param end 结束日期 + * @return 返回用户统计的结果 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("用户统计") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/userStatistics") + public Result userStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) { + // 使用日志记录用户统计的操作 + log.info("用户统计:{},{}", begin, end); + // 调用ReportService的userStatistics方法获取用户统计结果,并包装成成功的响应 + return Result.success(reportService.userStatistics(begin, end)); + } + + /** + * 订单统计接口。 + * + * @param begin 开始日期 + * @param end 结束日期 + * @return 返回订单统计的结果 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("订单统计") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/ordersStatistics") + public Result orderStatistics(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) { + // 使用日志记录订单统计的操作 + log.info("订单统计{},{}", begin, end); + // 调用ReportService的orderStatistics方法获取订单统计结果,并包装成成功的响应 + return Result.success(reportService.orderStatistics(begin, end)); + } + + /** + * 销量排名前十接口。 + * + * @param begin 开始日期 + * @param end 结束日期 + * @return 返回销量排名前十的结果 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("销量排行前十") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/top10") + public Result salesTop10Report(@DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate begin, @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate end) { + // 使用日志记录销量排名前十的操作 + log.info("销售排名前10:{},{}", begin, end); + // 调用ReportService的salesTop10Report方法获取销量排名前十的结果,并包装成成功的响应 + return Result.success(reportService.salesTop10Report(begin, end)); + } + + /** + * 导出excel表格接口。 + * + * @param httpResponse HTTP响应对象 + * @return 返回操作结果 + * @throws IOException 如果发生IO异常 + * @throws InvalidFormatException 如果发生格式无效的异常 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("导出excel表格") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/export") + public Result export(HttpServletResponse httpResponse) throws IOException, InvalidFormatException { + // 使用日志记录导出Excel表格的操作 + log.info("导出Excel表格"); + // 调用ReportService的export方法导出Excel表格 + reportService.export(httpResponse); + // 返回操作成功的结果 + return Result.success("OK"); + } + +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/notify/PayNotifyController.java b/sky/sky-server/src/main/java/com/sky/controller/notify/PayNotifyController.java new file mode 100644 index 0000000..1205ec4 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/notify/PayNotifyController.java @@ -0,0 +1,135 @@ +// 定义了一个名为com.sky.controller.notify的包,用于存放支付回调相关的控制器类 +package com.sky.controller.notify; + +// 导入了JSON处理相关的类 +import com.alibaba.druid.support.json.JSONUtils; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +// 导入了项目中定义的微信支付属性类 +import com.sky.properties.WeChatProperties; +// 导入了项目中定义的订单服务接口 +import com.sky.service.OrderService; +// 导入了微信支付加解密工具类 +import com.wechat.pay.contrib.apache.httpclient.util.AesUtil; +// 导入了Lombok提供的@Slf4j注解,用于简化日志操作 +import lombok.extern.slf4j.Slf4j; +// 导入了HTTP相关的类 +import org.apache.http.entity.ContentType; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; + +/** + * 支付回调相关接口,用于处理微信支付的异步通知。 + */ +// 使用@RestController注解声明这是一个控制器类,并且返回的数据会自动以JSON格式响应 +@RestController +// 使用@RequestMapping注解定义这个控制器类的基础请求映射路径 +@RequestMapping("/notify") +// 使用@Slf4j注解提供日志功能 +@Slf4j +public class PayNotifyController { + // 自动注入OrderService + @Autowired + private OrderService orderService; + // 自动注入WeChatProperties + @Autowired + private WeChatProperties weChatProperties; + + /** + * 支付成功回调接口。 + * + * @param request HTTP请求对象 + * @param response HTTP响应对象 + * @throws Exception 可能抛出的异常 + */ + @RequestMapping("/paySuccess") + public void paySuccessNotify(HttpServletRequest request, HttpServletResponse response) throws Exception { + // 读取数据 + String body = readData(request); + log.info("支付成功回调:{}", body); + + // 数据解密 + String plainText = decryptData(body); + log.info("解密后的文本:{}", plainText); + + JSONObject jsonObject = JSON.parseObject(plainText); + // 商户平台订单号 + String outTradeNo = jsonObject.getString("out_trade_no"); + // 微信支付交易号 + String transactionId = jsonObject.getString("transaction_id"); + + log.info("商户平台订单号:{}", outTradeNo); + log.info("微信支付交易号:{}", transactionId); + + // 业务处理,修改订单状态、来单提醒 + orderService.paySuccess(outTradeNo); + + // 给微信响应 + responseToWeixin(response); + } + + /** + * 读取数据方法,从HTTP请求中读取数据。 + * + * @param request HTTP请求对象 + * @return 读取到的数据字符串 + * @throws Exception 可能抛出的异常 + */ + private String readData(HttpServletRequest request) throws Exception { + BufferedReader reader = request.getReader(); + StringBuilder result = new StringBuilder(); + String line = null; + while ((line = reader.readLine()) != null) { + if (result.length() > 0) { + result.append("\n"); + } + result.append(line); + } + return result.toString(); + } + + /** + * 数据解密方法,用于解密微信支付回调的数据。 + * + * @param body 需要解密的数据字符串 + * @return 解密后的字符串 + * @throws Exception 可能抛出的异常 + */ + private String decryptData(String body) throws Exception { + JSONObject resultObject = JSON.parseObject(body); + JSONObject resource = resultObject.getJSONObject("resource"); + String ciphertext = resource.getString("ciphertext"); + String nonce = resource.getString("nonce"); + String associatedData = resource.getString("associated_data"); + + AesUtil aesUtil = new AesUtil(weChatProperties.getApiV3Key().getBytes(StandardCharsets.UTF_8)); + // 密文解密 + String plainText = aesUtil.decryptToString(associatedData.getBytes(StandardCharsets.UTF_8), + nonce.getBytes(StandardCharsets.UTF_8), + ciphertext); + + return plainText; + } + + /** + * 给微信响应方法,用于向微信服务器返回处理结果。 + * + * @param response HTTP响应对象 + * @throws Exception 可能抛出的异常 + */ + private void responseToWeixin(HttpServletResponse response) throws Exception{ + response.setStatus(200); + HashMap map = new HashMap<>(); + map.put("code", "SUCCESS"); + map.put("message", "SUCCESS"); + response.setHeader("Content-type", ContentType.APPLICATION_JSON.toString()); + response.getOutputStream().write(JSONUtils.toJSONString(map).getBytes(StandardCharsets.UTF_8)); + response.flushBuffer(); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/user/OrderController.java b/sky/sky-server/src/main/java/com/sky/controller/user/OrderController.java new file mode 100644 index 0000000..6f7e33e --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/user/OrderController.java @@ -0,0 +1,159 @@ +// 定义了一个名为com.sky.controller.user的包,用于存放用户端订单控制器类 +package com.sky.controller.user; + +// 导入了项目中定义的数据传输对象(DTO)类 +import com.sky.dto.OrdersDTO; +import com.sky.dto.OrdersPageQueryDTO; +import com.sky.dto.OrdersPaymentDTO; +// 导入了项目中定义的实体类 +import com.sky.entity.Orders; +// 导入了项目中定义的结果类 +import com.sky.result.PageResult; +import com.sky.result.Result; +// 导入了项目中定义的服务接口 +import com.sky.service.OrderService; +// 导入了项目中定义的视图对象(VO)类 +import com.sky.vo.OrderPaymentVO; +import com.sky.vo.OrderSubmitVO; +import com.sky.vo.OrderVO; +// 导入了Swagger注解,用于API文档的生成 +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +// 导入了Lombok提供的@Slf4j注解,用于简化日志操作 +import lombok.extern.slf4j.Slf4j; +// 导入了Spring框架中的@Autowired注解,用于自动注入Spring管理的Bean +import org.springframework.beans.factory.annotation.Autowired; +// 导入了Spring框架中的@RequestMapping注解,用于定义请求映射 +import org.springframework.web.bind.annotation.*; + +/** + * 用户端订单控制器,提供用户下单、订单支付、订单查询等接口服务。 + */ +// 使用@RestController注解声明这是一个控制器类,并且返回的数据会自动以JSON格式响应 +@RestController +// 使用@RequestMapping注解定义这个控制器类的基础请求映射路径 +@RequestMapping("/user/order") +// 使用@Slf4j注解提供日志功能 +@Slf4j +// 使用@Api注解为这个控制器类添加Swagger文档的描述 +@Api(tags = "C端-订单接口") +public class OrderController { + + // 自动注入OrderService + @Autowired + OrderService orderService; + + /** + * 再来一单接口。 + * + * @param id 订单ID + * @return 操作结果 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("再来一单") + // 使用@PostMapping注解定义POST请求映射 + @PostMapping("/repetition/{id}") + public Result repetition(@PathVariable Long id) { + orderService.repetition(id); + return Result.success(); + } + + /** + * 用户取消订单接口。 + * + * @param id 订单ID + * @return 操作结果 + * @throws Exception 可能抛出的异常 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("取消订单") + // 使用@PutMapping注解定义PUT请求映射 + @PutMapping("/cancel/{id}") + public Result cancel(@PathVariable("id") Long id) throws Exception { + orderService.userCancelById(id); + return Result.success(); + } + + /** + * 用户下单接口。 + * + * @param ordersDTO 订单数据传输对象 + * @return 订单提交视图对象 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("用户下单") + // 使用@RequestMapping注解定义请求映射 + @RequestMapping("/submit") + public Result submitOrder(@RequestBody OrdersDTO ordersDTO) { + log.info("用户下单,订单信息:{}", ordersDTO); + OrderSubmitVO order = orderService.submit(ordersDTO); + + return Result.success(order); + } + + /** + * 订单支付接口。 + * + * @param ordersPaymentDTO 订单支付数据传输对象 + * @return 操作结果 + * @throws Exception 可能抛出的异常 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("订单支付") + // 使用@PutMapping注解定义PUT请求映射 + @PutMapping("/payment") + public Result payment(@RequestBody OrdersPaymentDTO ordersPaymentDTO) throws Exception { + log.info("订单支付:{}", ordersPaymentDTO); + orderService.paySuccess(ordersPaymentDTO.getOrderNumber()); + return Result.success(); + } + + /** + * 催单接口。 + * + * @param id 订单ID + * @return 操作结果 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("催单") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/reminder/{id}") + public Result reminder(@PathVariable Long id) { + log.info("用户催单orderId:{}", id); + orderService.reminder(id); + + return Result.success(); + } + + /** + * 历史订单查询接口。 + * + * @param page 当前页码 + * @param pageSize 每页显示数量 + * @param status 订单状态 + * @return 分页结果 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("历史订单查询") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/historyOrders") + public Result page(int page, int pageSize, Integer status) { + PageResult pageResult = orderService.pageQuery4User(page, pageSize, status); + return Result.success(pageResult); + } + + /** + * 查询订单详情接口。 + * + * @param id 订单ID + * @return 订单视图对象 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("查询订单详情") + // 使用@GetMapping注解定义GET请求映射 + @GetMapping("/orderDetail/{id}") + public Result details(@PathVariable("id") Long id) { + OrderVO orderVO = orderService.details(id); + return Result.success(orderVO); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/controller/user/UserController.java b/sky/sky-server/src/main/java/com/sky/controller/user/UserController.java new file mode 100644 index 0000000..ad39e0b --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/controller/user/UserController.java @@ -0,0 +1,80 @@ +// 定义了一个名为com.sky.controller.user的包,用于存放用户控制器类 +package com.sky.controller.user; + +// 导入了项目中定义的常量类 +import com.sky.constant.JwtClaimsConstant; +// 导入了项目中定义的用户登录数据传输对象(DTO)类 +import com.sky.dto.UserLoginDTO; +// 导入了项目中定义的实体类 +import com.sky.entity.User; +// 导入了项目中定义的JWT属性类 +import com.sky.properties.JwtProperties; +// 导入了项目中定义的结果类 +import com.sky.result.Result; +// 导入了项目中定义的服务接口 +import com.sky.service.UserService; +// 导入了项目中定义的JWT工具类 +import com.sky.utils.JwtUtil; +// 导入了项目中定义的视图对象(VO)类 +import com.sky.vo.UserLoginVO; +// 导入了Swagger注解,用于API文档的生成 +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +// 导入了Lombok提供的@Slf4j注解,用于简化日志操作 +import lombok.extern.slf4j.Slf4j; +// 导入了Spring框架中的@Autowired注解,用于自动注入Spring管理的Bean +import org.springframework.beans.factory.annotation.Autowired; +// 导入了Spring框架中的@RequestMapping注解,用于定义请求映射 +import org.springframework.web.bind.annotation.*; + +/** + * 用户控制器,提供用户登录等接口服务。 + */ +// 使用@RestController注解声明这是一个控制器类,并且返回的数据会自动以JSON格式响应 +@RestController +// 使用@RequestMapping注解定义这个控制器类的基础请求映射路径 +@RequestMapping("/user/user") +// 使用@Slf4j注解提供日志功能 +@Slf4j +// 使用@Api注解为这个控制器类添加Swagger文档的描述 +@Api("C端用户相关接口") +public class UserController { + // 自动注入UserService + @Autowired + UserService userService; + // 自动注入JwtProperties + @Autowired + JwtProperties jwtProperties; + + /** + * 用户登录接口。 + * + * @param userLoginDTO 用户登录数据传输对象 + * @return 用户登录视图对象,包含JWT令牌等信息 + */ + // 使用@ApiOperation注解为这个接口方法添加Swagger文档的描述 + @ApiOperation("用户登录") + // 使用@PostMapping注解定义POST请求映射 + @PostMapping("/login") + public Result login(@RequestBody UserLoginDTO userLoginDTO){ + // 使用日志记录用户登录的操作 + log.info("微信登录:{}",userLoginDTO); + // 调用UserService的wxLogin方法进行微信登录 + User user = userService.wxLogin(userLoginDTO); + + // 生成JWT令牌 + Map claims = new HashMap<>(); + claims.put(JwtClaimsConstant.USER_ID, user.getId()); + String jwt = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims); + + // 构建用户登录视图对象 + UserLoginVO userLoginVO = UserLoginVO.builder() + .id(user.getId()) + .token(jwt) + .openid(user.getOpenid()) + .build(); + + // 返回成功的结果,包含用户登录视图对象 + return Result.success(userLoginVO); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/mapper/AddressBookMapper.java b/sky/sky-server/src/main/java/com/sky/mapper/AddressBookMapper.java new file mode 100644 index 0000000..ef02c66 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/mapper/AddressBookMapper.java @@ -0,0 +1,71 @@ +// 定义了一个名为com.sky.mapper的包,用于存放MyBatis Mapper接口 +package com.sky.mapper; + +// 导入了项目中定义的AddressBook实体类 +import com.sky.entity.AddressBook; +// 导入了MyBatis相关注解 +import org.apache.ibatis.annotations.*; +// 导入了Java.util.List接口,用于定义返回列表类型 +import java.util.List; + +// 使用@Mapper注解标记这是一个MyBatis Mapper接口 +@Mapper +public interface AddressBookMapper { + + /** + * 条件查询方法,根据传入的AddressBook对象条件查询地址簿信息。 + * + * @param addressBook 条件对象 + * @return 返回符合条件的AddressBook对象列表 + */ + List list(AddressBook addressBook); + + /** + * 新增方法,将一个新的地址簿信息插入到数据库中。 + * + * @param addressBook 要插入的AddressBook对象 + */ + // 使用@Insert注解标记这是一个插入操作,并提供SQL语句 + @Insert("insert into address_book" + + " (user_id, consignee, phone, sex, province_code, province_name, city_code, city_name, district_code," + + " district_name, detail, label, is_default)" + + " values (#{userId}, #{consignee}, #{phone}, #{sex}, #{provinceCode}, #{provinceName}, #{cityCode}, #{cityName}," + + " #{districtCode}, #{districtName}, #{detail}, #{label}, #{isDefault})") + void insert(AddressBook addressBook); + + /** + * 根据id查询方法,根据用户ID查询对应的地址簿信息。 + * + * @param id 用户ID + * @return 返回对应的AddressBook对象 + */ + // 使用@Select注解标记这是一个查询操作,并提供SQL语句 + @Select("select * from address_book where user_id = #{id}") + AddressBook getById(Long id); + + /** + * 根据id修改方法,根据传入的AddressBook对象修改数据库中的地址簿信息。 + * + * @param addressBook 要修改的AddressBook对象 + */ + void update(AddressBook addressBook); + + /** + * 根据用户id修改是否默认地址方法,更新指定用户ID的默认地址状态。 + * + * @param addressBook 包含用户ID和是否默认状态的AddressBook对象 + */ + // 使用@Update注解标记这是一个更新操作,并提供SQL语句 + @Update("update address_book set is_default = #{isDefault} where user_id = #{userId}") + void updateIsDefaultByUserId(AddressBook addressBook); + + /** + * 根据id删除地址方法,根据ID删除数据库中的地址簿信息。 + * + * @param id 要删除的地址簿ID + */ + // 使用@Delete注解标记这是一个删除操作,并提供SQL语句 + @Delete("delete from address_book where id = #{id}") + void deleteById(Long id); + +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/mapper/OrderDetailMapper.java b/sky/sky-server/src/main/java/com/sky/mapper/OrderDetailMapper.java new file mode 100644 index 0000000..5755637 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/mapper/OrderDetailMapper.java @@ -0,0 +1,35 @@ +// 定义了一个名为com.sky.mapper的包,用于存放MyBatis Mapper接口 +package com.sky.mapper; + +// 导入了项目中定义的OrderDetail实体类 +import com.sky.entity.OrderDetail; +// 导入了MyBatis相关注解 +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; +// 导入了Java.util.List接口,用于定义返回列表类型 +import java.util.List; +// 导入了Java.util.ArrayList类,用于定义批量插入的数据类型 +import java.util.ArrayList; + +// 使用@Mapper注解标记这是一个MyBatis Mapper接口 +@Mapper +public interface OrderDetailMapper { + + /** + * 插入多条订单明细数据方法,用于将多条订单明细信息批量插入到数据库中。 + * + * @param orderDetails 要插入的订单明细对象列表 + */ + // 此方法的具体实现需要在MyBatis的映射文件中定义,通常使用标签,并设置typeHandler进行批量插入 + void insertBatch(ArrayList orderDetails); + + /** + * 根据订单id查询订单明细方法,根据订单ID查询对应的订单明细信息。 + * + * @param orderId 订单ID + * @return 返回对应的订单明细对象列表 + */ + // 使用@Select注解标记这是一个查询操作,并提供SQL语句 + @Select("select * from order_detail where order_id = #{orderId}") + List getByOrderId(Long orderId); +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/mapper/ShoppingCartMapper.java b/sky/sky-server/src/main/java/com/sky/mapper/ShoppingCartMapper.java new file mode 100644 index 0000000..726d9ae --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/mapper/ShoppingCartMapper.java @@ -0,0 +1,57 @@ +// 定义了一个名为com.sky.mapper的包,用于存放MyBatis Mapper接口 +package com.sky.mapper; + +// 导入了项目中定义的ShoppingCart实体类 +import com.sky.entity.ShoppingCart; +// 导入了MyBatis相关注解 +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Update; +// 导入了Java.util.List接口,用于定义返回列表类型 +import java.util.List; + +// 使用@Mapper注解标记这是一个MyBatis Mapper接口 +@Mapper +public interface ShoppingCartMapper { + + /** + * 批量插入购物车数据方法,用于将多个购物车记录批量插入到数据库中。 + * + * @param shoppingCartList 要插入的购物车记录列表 + */ + void insertBatch(List shoppingCartList); + + /** + * 查询用户购物车方法,根据传入的ShoppingCart对象条件查询用户的购物车信息。 + * + * @param shoppingCart 条件对象 + * @return 返回符合条件的ShoppingCart对象列表 + */ + List list(ShoppingCart shoppingCart); + + /** + * 根据id修改商品数量方法,用于更新购物车中商品的数量和金额。 + * + * @param shoppingCart 包含更新信息的ShoppingCart对象 + */ + // 使用@Update注解标记这是一个更新操作,并提供SQL语句 + @Update("update shopping_cart set number=#{number},amount=#{amount} where id=#{id}") + void update(ShoppingCart shoppingCart); + + /** + * 插入一个购物车数据方法,用于将单个购物车记录插入到数据库中。 + * + * @param shoppingCart 要插入的ShoppingCart对象 + */ + // 使用@Insert注解标记这是一个插入操作,并提供SQL语句 + @Insert("insert into shopping_cart(name,user_id,dish_id,setmeal_id,dish_flavor,number,amount,image,create_time)" + + "values (#{name},#{userId},#{dishId},#{setmealId},#{dishFlavor},#{number},#{amount},#{image},#{createTime})") + void insert(ShoppingCart shoppingCart); + + /** + * 删除购物车中的一个商品方法,用于根据传入的ShoppingCart对象删除购物车中的一个商品记录。 + * + * @param shoppingCart 包含删除条件的ShoppingCart对象 + */ + void delete(ShoppingCart shoppingCart); +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/DishService.java b/sky/sky-server/src/main/java/com/sky/service/DishService.java new file mode 100644 index 0000000..6357892 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/DishService.java @@ -0,0 +1,87 @@ +package com.sky.service; + +import com.sky.dto.DishDTO; +import com.sky.dto.DishPageQueryDTO; +import com.sky.entity.Dish; +import com.sky.result.PageResult; +import com.sky.vo.DishVO; +import com.sky.vo.SetmealVO; +import org.springframework.stereotype.Service; + +import java.util.ArrayList; +import java.util.List; + +/** + * DishService接口定义了菜品相关的服务方法。 + */ +public interface DishService { + + /** + * 菜品分页查询。 + * 根据DishPageQueryDTO中提供的条件进行分页查询,返回查询结果的分页信息。 + * + * @param dishPageQueryDTO 包含查询条件和分页信息的DTO对象 + * @return 分页结果的PageResult对象 + */ + PageResult pageQuery(DishPageQueryDTO dishPageQueryDTO); + + /** + * 新增菜品和对应的口味数据。 + * 将DishDTO对象中的菜品和口味数据保存到数据库中。 + * + * @param dishDTO 包含菜品和口味信息的DTO对象 + */ + void saveWithFlaver(DishDTO dishDTO); + + /** + * 删除菜品。 + * 根据提供的ID列表批量删除菜品。 + * + * @param ids 要删除的菜品ID列表 + */ + void deleteBatch(ArrayList ids); + + /** + * 修改菜品。 + * 根据DishDTO对象中的信息更新数据库中的菜品数据。 + * + * @param dishDTO 包含菜品信息的DTO对象 + */ + void updateDish(DishDTO dishDTO); + + /** + * 根据id获取菜品数据。 + * 根据提供的ID查询并返回对应的菜品VO对象。 + * + * @param id 菜品的ID + * @return 菜品的DishVO对象 + */ + DishVO getById(Long id); + + /** + * 根据分类id查询菜品。 + * 根据提供的分类ID查询并返回该分类下的所有菜品实体。 + * + * @param categoryId 菜品分类的ID + * @return 菜品实体列表 + */ + ArrayList getByCategoryId(Long categoryId); + + /** + * 起售或停售菜品。 + * 根据提供的ID和状态更新菜品的起售或停售状态。 + * + * @param id 菜品的ID + * @param status 起售或停售状态 + */ + void startOrStop(Long id, Integer status); + + /** + * 条件查询菜品和口味。 + * 根据Dish对象中的条件查询并返回符合条件的菜品VO列表,包含口味信息。 + * + * @param dish 包含查询条件的Dish实体 + * @return 包含口味信息的菜品VO列表 + */ + List listWithFlavor(Dish dish); +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/SetmealService.java b/sky/sky-server/src/main/java/com/sky/service/SetmealService.java new file mode 100644 index 0000000..ac9bff0 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/SetmealService.java @@ -0,0 +1,87 @@ +package com.sky.service; + +import com.sky.dto.CategoryPageQueryDTO; +import com.sky.dto.SetmealDTO; +import com.sky.dto.SetmealPageQueryDTO; +import com.sky.entity.Setmeal; +import com.sky.result.PageResult; +import com.sky.vo.DishItemVO; +import com.sky.vo.SetmealVO; + +import java.util.ArrayList; +import java.util.List; + +/** + * SetmealService接口定义了套餐相关的服务方法。 + */ +public interface SetmealService { + + /** + * 条件查询套餐。 + * 根据Setmeal对象中的条件查询并返回符合条件的套餐实体列表。 + * + * @param setmeal 包含查询条件的Setmeal实体 + * @return 套餐实体列表 + */ + List list(Setmeal setmeal); + + /** + * 根据id查询菜品选项。 + * 根据提供的套餐ID查询并返回该套餐包含的菜品项VO列表。 + * + * @param id 套餐的ID + * @return 菜品项VO列表 + */ + List getDishItemById(Long id); + + /** + * 分页查询套餐。 + * 根据SetmealPageQueryDTO中提供的条件进行分页查询,返回查询结果的分页信息。 + * + * @param setmealPageQueryDTO 包含查询条件和分页信息的DTO对象 + * @return 分页结果的PageResult对象 + */ + PageResult pageQuery(SetmealPageQueryDTO setmealPageQueryDTO); + + /** + * 起售或停售套餐。 + * 根据提供的状态和套餐ID更新套餐的起售或停售状态。 + * + * @param status 起售或停售状态 + * @param id 套餐的ID + */ + void startOrStop(Integer status, Long id); + + /** + * 修改套餐信息。 + * 根据SetmealDTO对象中的信息更新数据库中的套餐数据。 + * + * @param setmealDTO 包含套餐信息的DTO对象 + */ + void updateSetmeal(SetmealDTO setmealDTO); + + /** + * 根据套餐id获取套餐。 + * 根据提供的套餐ID查询并返回对应的套餐VO对象。 + * + * @param id 套餐的ID + * @return 套餐的SetmealVO对象 + */ + SetmealVO getDishById(Long id); + + /** + * 根据套餐id批量删除套餐。 + * 根据提供的ID列表批量删除套餐。 + * + * @param ids 要删除的套餐ID列表 + */ + void batchDeleteById(ArrayList ids); + + /** + * 新增套餐。 + * 将SetmealDTO对象中的套餐数据保存到数据库中。 + * + * @param setmealDTO 包含套餐信息的DTO对象 + */ + void insert(SetmealDTO setmealDTO); +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/impl/CommonServiceImpl.java b/sky/sky-server/src/main/java/com/sky/service/impl/CommonServiceImpl.java new file mode 100644 index 0000000..f24201c --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/impl/CommonServiceImpl.java @@ -0,0 +1,54 @@ +package com.sky.service.impl; + +import com.sky.service.CommonService; +import com.sky.utils.AliOssUtil; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.util.UUID; + +/** + * CommonServiceImpl类是CommonService接口的实现类,提供了通用服务的实现,如文件上传。 + */ +@Service +@Slf4j +public class CommonServiceImpl implements CommonService { + + /** + * AliOssUtil是一个工具类,用于操作阿里云OSS服务。 + * 通过@Autowired注解,Spring会自动注入AliOssUtil的实例。 + */ + @Autowired + private AliOssUtil aliOssUtil; + + /** + * upload方法用于上传文件到OSS。 + * 它接受一个MultipartFile类型的参数,这是Spring MVC处理上传文件的类型。 + * 方法返回上传后的文件路径。 + * + * @param file 要上传的文件 + * @return 返回上传文件后在OSS上的路径 + */ + @Override + public String upload(MultipartFile file) { + String filePath = null; + // 获取原始文件名 + String originalFilename = file.getOriginalFilename(); + // 从原始文件名中截取文件后缀 + String extension = originalFilename.substring(originalFilename.lastIndexOf(".")); + // 构造新的文件名,使用UUID确保唯一性,加上原文件后缀 + String objectName = UUID.randomUUID() + extension; + try { + // 使用aliOssUtil上传文件,并获取文件路径 + filePath = aliOssUtil.upload(file.getBytes(), objectName); + } catch (IOException e) { + // 如果上传过程中发生IO异常,记录错误日志 + log.error("文件上传失败:{}", e); + } + // 返回文件路径 + return filePath; + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/service/impl/ReportServiceImpl.java b/sky/sky-server/src/main/java/com/sky/service/impl/ReportServiceImpl.java new file mode 100644 index 0000000..12a80df --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/impl/ReportServiceImpl.java @@ -0,0 +1,364 @@ +package com.sky.service.impl; + +import com.sky.entity.Orders; +import com.sky.mapper.ReportMapper; +import com.sky.properties.ReportExcelProperties; +import com.sky.result.Result; +import com.sky.service.ReportService; +import com.sky.vo.*; +import io.swagger.models.auth.In; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.StringUtils; +import org.apache.http.HttpResponse; +import org.apache.poi.hssf.usermodel.HSSFSheet; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.opc.OPCPackage; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.ss.extractor.ExcelExtractor; +import org.apache.poi.ss.usermodel.HorizontalAlignment; +import org.apache.poi.xssf.usermodel.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.format.annotation.DateTimeFormat; +import org.springframework.stereotype.Service; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletResponse; +import java.io.*; +import java.math.BigDecimal; +import java.nio.file.Files; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.Period; +import java.time.format.DateTimeFormatter; +import java.time.temporal.TemporalAdjusters; +import java.util.*; + +@Service +@Slf4j +public class ReportServiceImpl implements ReportService { + + @Autowired + ReportMapper reportMapper; + @Autowired + ReportExcelProperties reportExcelProperties; + @Autowired + WorkspaceServiceImpl workspaceService; + + /** + * 营业额统计 + * + * @param begin + * @param end + * @return + */ + @Override + public Result getTurnoverStatistics(LocalDate begin, LocalDate end) { + LocalDate p = begin; + ArrayList dateTimes = new ArrayList<>(); + while (!p.equals(end)) { + dateTimes.add(p); + p = p.plusDays(1); + } + ArrayList count = new ArrayList<>(); + for (LocalDate dateTime : dateTimes) { + HashMap map = new HashMap<>(); + map.put("status", 5); + map.put("begin", LocalDateTime.of(dateTime, LocalTime.MIN)); + map.put("end", LocalDateTime.of(dateTime, LocalTime.MAX)); + Double sum = reportMapper.sumByMap(map); + if (sum == null) { + sum = 0D; + } + count.add(sum); + } + + return Result.success(TurnoverReportVO.builder() + .dateList(StringUtils.join(dateTimes, ",")) + .turnoverList(StringUtils.join(count, ",")) + .build()); + } + + /** + * 用户统计 + * + * @param begin + * @param end + * @return + */ + @Override + public UserReportVO userStatistics(LocalDate begin, LocalDate end) { + LocalDate p = begin; + ArrayList dateTimes = new ArrayList<>(); + while (!p.equals(end)) { + dateTimes.add(p); + p = p.plusDays(1); + } + ArrayList user = new ArrayList<>(); + ArrayList newUser = new ArrayList<>(); + for (LocalDate dateTime : dateTimes) { + HashMap map = new HashMap<>(); + map.put("begin", LocalDateTime.of(dateTime, LocalTime.MIN)); + map.put("end", LocalDateTime.of(dateTime, LocalTime.MAX)); + Integer sum = reportMapper.sumUserByDay(map); + Integer sumUser = reportMapper.sumUser(map); + if (sum == null) { + sum = 0; + } + if (sumUser == null) { + sumUser = 0; + } + newUser.add(sum); + user.add(sumUser); + } + + + return UserReportVO.builder() + .dateList(StringUtils.join(dateTimes, ",")) + .totalUserList(StringUtils.join(user, ",")) + .newUserList(StringUtils.join(newUser, ",")) + .build(); + } + + /** + * 订单统计 + * + * @param begin + * @param end + * @return + */ + @Override + public OrderReportVO orderStatistics(LocalDate begin, LocalDate end) { + // 初始化日期列表,用于存储开始和结束日期之间的每一天 + LocalDate p = begin; + ArrayList dateTimes = new ArrayList<>(); + while (!p.equals(end)) { + dateTimes.add(p); + p = p.plusDays(1); + } + + // 初始化订单数量和新订单数量的列表 + ArrayList order = new ArrayList<>(); + ArrayList newOrder = new ArrayList<>(); + + // 遍历每一天,统计订单数量和新订单数量 + for (LocalDate dateTime : dateTimes) { + HashMap map = new HashMap<>(); + map.put("begin", LocalDateTime.of(dateTime, LocalTime.MIN)); // 当天的最小时间 + map.put("end", LocalDateTime.of(dateTime, LocalTime.MAX)); // 当天的最大时间 + map.put("status", Orders.COMPLETED); // 完成的订单状态 + + // 调用reportMapper查询新订单和订单总数 + Integer sum = reportMapper.sumNewOrder(map); + Integer sumOrder = reportMapper.sumOrder(map); + + // 处理查询结果为null的情况 + if (sum == null) { + sum = 0; + } + if (sumOrder == null) { + sumOrder = 0; + } + + // 将查询结果添加到列表中 + order.add(sumOrder); + newOrder.add(sum); + } + + // 计算订单完成率 + Double rate; + if (sumArrayList(order) == 0) { + rate = 1.0; // 如果订单总数为0,则完成率为1.0 + } else { + rate = sumArrayList(newOrder) / sumArrayList(order) * 1.0; // 计算完成率 + } + + // 构建并返回订单统计报告对象 + return OrderReportVO.builder() + .dateList(StringUtils.join(dateTimes, ",")) + // 日期列表,以逗号分隔 + .orderCountList(StringUtils.join(newOrder, ",")) + // 新订单数量列表,以逗号分隔 + .validOrderCountList(StringUtils.join(order, ",")) + // 订单数量列表,以逗号分隔 + .totalOrderCount(sumArrayList(newOrder)) + // 新订单总数 + .validOrderCount(sumArrayList(order)) + // 订单总数 + .orderCompletionRate(rate) + // 订单完成率 + .build(); + // 构建报告对象 + } + + /** + * 销量排行前十 + * + * @param begin + * @param end + * @return + */ + @Override + public SalesTop10ReportVO salesTop10Report(LocalDate begin, LocalDate end) { + // 初始化商品名称和销售数量的列表 + ArrayList name = new ArrayList<>(); + ArrayList number = new ArrayList<>(); + + // 创建映射,用于传递查询参数 + HashMap map = new HashMap<>(); + // 查询结果集 + ArrayList> result; + + // 设置查询参数 + map.put("begin", LocalDateTime.of(begin, LocalTime.MIN)); // 查询开始时间(当天的最小时间) + map.put("end", LocalDateTime.of(end, LocalTime.MAX)); // 查询结束时间(当天的最大时间) + map.put("status", Orders.COMPLETED); // 订单状态,这里为已完成的订单 + + // 调用reportMapper查询销售排行前十的商品 + result = reportMapper.salesTop10Report(map); + + // 遍历查询结果,提取商品名称和销售数量 + for (HashMap hashMap : result) { + name.add((String) hashMap.get("name")); // 获取商品名称 + number.add(((BigDecimal) hashMap.get("number")).intValue()); // 获取销售数量并转换为整数 + } + + // 构建并返回销售排行报告对象 + return SalesTop10ReportVO.builder() + .nameList(StringUtils.join(name, ",")) // 将商品名称列表转换为逗号分隔的字符串 + .numberList(StringUtils.join(number, ",")) // 将销售数量列表转换为逗号分隔的字符串 + .build(); // 构建报告对象 + } + + /** + * 导出excel表格 + */ + @Override + public void export(HttpServletResponse httpResponse) throws IOException, InvalidFormatException { + File file = new File(reportExcelProperties.getFilePath()); + OPCPackage opcPackage = OPCPackage.open(file); + //获取工作薄 + XSSFWorkbook workbook = new XSSFWorkbook(opcPackage); + String s = reportExcelProperties.getSheet()[0]; + //获取工作表 + XSSFSheet sheet = workbook.getSheet(s); + //填写日期 + XSSFRow row = sheet.getRow(1); + XSSFCellStyle dataStyle = workbook.createCellStyle(); + //设置日期的字体 + XSSFFont font = workbook.createFont(); + font.setFontHeight(16); + font.setFontName("宋体"); + dataStyle.setAlignment(HorizontalAlignment.RIGHT); + XSSFCell cell0 = row.getCell(1); + dataStyle.setFont(font); + cell0.setCellStyle(dataStyle); + + + //获取营业概览数据 + LocalDateTime begin = LocalDateTime.now().with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN); + LocalDateTime end = LocalDateTime.now().with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX); + cell0.setCellValue(begin.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss")) + "——" + end.format(DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss"))); + BusinessDataVO businessData = workspaceService.getBusinessData(begin, end); + XSSFRow row3 = sheet.getRow(3); + //营业额 + XSSFCell cell = row3.getCell(2); + cell.setCellValue(businessData.getTurnover()); + //订单完成率 + XSSFCell cell1 = row3.getCell(4); + cell1.setCellValue(businessData.getOrderCompletionRate()); + //新增用户数 + XSSFCell cell2 = row3.getCell(6); + cell2.setCellValue(businessData.getNewUsers()); + //有效订单 + XSSFRow row1 = sheet.getRow(4); + XSSFCell cell3 = row1.getCell(2); + cell3.setCellValue(businessData.getValidOrderCount()); + //平均客单价 + XSSFCell cell4 = row1.getCell(4); + cell4.setCellValue(businessData.getValidOrderCount()); + int dayOfMonth = Period.between(begin.toLocalDate(), end.toLocalDate()).getDays(); + System.out.println("dayOfMonth:" + dayOfMonth); + //获取明细数据 + + for (int i = 0; i < dayOfMonth; i++) { + XSSFRow row2 = sheet.getRow(i + 7); + LocalDateTime localDateTimeBegin = begin.plusDays(i); + LocalDateTime localDateTimeEnd = localDateTimeBegin.with(LocalTime.MAX); + BusinessDataVO data = workspaceService.getBusinessData(localDateTimeBegin, localDateTimeEnd); + //设置日期 + row2.getCell(1).setCellValue(localDateTimeBegin.toLocalDate().format(DateTimeFormatter.ofPattern("yyyy年MM月dd日"))); + //营业额 + row2.getCell(2).setCellValue(data.getTurnover()); + //有效订单 + row2.getCell(3).setCellValue(data.getValidOrderCount()); + //订单完成率 + row2.getCell(4).setCellValue(data.getOrderCompletionRate()); + //平均客单价 + row2.getCell(5).setCellValue(data.getUnitPrice()); + //新增用户数 + row2.getCell(6).setCellValue(data.getNewUsers()); + } + +/** + * 获取Servlet输出流,用于写入响应数据。 + * 这个输出流允许我们将二进制数据直接写入HTTP响应中。 + */ + ServletOutputStream outputStream = httpResponse.getOutputStream(); + +/** + * 重置HTTP响应状态和头部信息。 + * 调用reset()方法会清除任何存在的响应信息,包括状态码和头部信息, + * 这样我们可以设置新的响应内容和头部信息。 + */ + httpResponse.reset(); + +/** + * 设置响应内容类型为Excel文件。 + * 通过设置ContentType为"application/vnd.ms-excel",我们告诉客户端响应的内容类型是Excel文件。 + */ + httpResponse.setContentType("application/vnd.ms-excel"); + +/** + * 添加响应头部,指示浏览器这是一个附件,并为其指定文件名。 + * Content-disposition头部用于指定响应的用途,这里我们设置为"attachment"表示附件, + * 并指定下载时的默认文件名为"template.xlsx"。 + */ + httpResponse.addHeader("Content-disposition", "attachment;filename=template.xlsx"); + +/** + * 将Excel工作簿写入Servlet输出流。 + * 使用Apache POI库的write方法,我们将Excel工作簿(workbook)的内容写入到前面获取的输出流中。 + */ + workbook.write(outputStream); + +/** + * 刷新输出流,确保所有数据都被写入。 + * 调用flush()方法可以确保输出流中的所有数据都被推送到客户端。 + */ + outputStream.flush(); + +/** + * 关闭输出流,释放资源。 + * 完成数据写入后,我们需要关闭输出流以释放系统资源。 + */ + outputStream.close(); + + } + + /** + * 计算整数列表的总和。 + * 这个方法接受一个ArrayList类型的参数,遍历列表中的每个元素,并将它们相加。 + * + * @param arrayList 要计算总和的整数列表 + * @return 返回列表中所有整数的总和 + */ + private Integer sumArrayList(ArrayList arrayList) { + Integer sum = 0; // 初始化总和为0 + for (Integer integer : arrayList) { // 遍历列表中的每个整数 + sum += integer; // 将当前整数加到总和上 + } + return sum; // 返回计算出的总和 + } +} diff --git a/sky/sky-server/src/main/java/com/sky/service/impl/WorkspaceServiceImpl.java b/sky/sky-server/src/main/java/com/sky/service/impl/WorkspaceServiceImpl.java new file mode 100644 index 0000000..09e096b --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/service/impl/WorkspaceServiceImpl.java @@ -0,0 +1,168 @@ +package com.sky.service.impl; + +import com.sky.constant.StatusConstant; +import com.sky.entity.Orders; +import com.sky.mapper.DishMapper; +import com.sky.mapper.OrderMapper; +import com.sky.mapper.SetmealMapper; +import com.sky.mapper.UserMapper; +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 lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * WorkspaceServiceImpl类是WorkspaceService接口的实现类,提供工作空间相关的服务。 + */ +@Service +@Slf4j +public class WorkspaceServiceImpl implements WorkspaceService { + + // 自动注入OrderMapper,用于操作订单相关的数据库操作 + @Autowired + private OrderMapper orderMapper; + // 自动注入UserMapper,用于操作用户相关的数据库操作 + @Autowired + private UserMapper userMapper; + // 自动注入DishMapper,用于操作菜品相关的数据库操作 + @Autowired + private DishMapper dishMapper; + // 自动注入SetmealMapper,用于操作套餐相关的数据库操作 + @Autowired + private SetmealMapper setmealMapper; + + /** + * 根据时间段统计营业数据。 + * 包括营业额、有效订单数、订单完成率、平均客单价和新增用户数。 + * + * @param begin 查询开始时间 + * @param end 查询结束时间 + * @return 返回营业数据的BusinessDataVO对象 + */ + public BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end) { + // 初始化查询参数的HashMap + HashMap map = new HashMap<>(); + map.put("begin", begin); + map.put("end", end); + map.put("status", null); + + // 查询总订单数 + Integer totalOrderCount = orderMapper.countByMap(map); + + // 设置状态为已完成,查询营业额和有效订单数 + map.put("status", Orders.COMPLETED); + Double turnover = orderMapper.sumByMap(map); + turnover = turnover == null ? 0.0 : turnover; + + Integer validOrderCount = orderMapper.countByMap(map); + + // 计算订单完成率和平均客单价 + Double unitPrice = 0.0; + Double orderCompletionRate = 0.0; + if (totalOrderCount != 0 && validOrderCount != 0) { + orderCompletionRate = validOrderCount.doubleValue() / totalOrderCount; + unitPrice = turnover / validOrderCount; + } + + // 查询新增用户数 + Integer newUsers = userMapper.countByMap(map); + + // 构建并返回营业数据对象 + return BusinessDataVO.builder() + .turnover(turnover) + .validOrderCount(validOrderCount) + .orderCompletionRate(orderCompletionRate) + .unitPrice(unitPrice) + .newUsers(newUsers) + .build(); + } + + /** + * 查询订单管理数据,包括待接单、待派送、已完成、已取消和全部订单的数量。 + * + * @return 返回订单管理数据的OrderOverViewVO对象 + */ + public OrderOverViewVO getOrderOverView() { + Map map = new HashMap(); + map.put("begin", LocalDateTime.now().with(LocalTime.MIN)); + map.put("end", LocalDateTime.now().with(LocalTime.MAX)); + map.put("status", Orders.TO_BE_CONFIRMED); + + // 查询待接单数量 + Integer waitingOrders = orderMapper.countByMap(map); + + // 查询待派送数量 + map.put("status", Orders.CONFIRMED); + Integer deliveredOrders = orderMapper.countByMap(map); + + // 查询已完成数量 + map.put("status", Orders.COMPLETED); + Integer completedOrders = orderMapper.countByMap(map); + + // 查询已取消数量 + map.put("status", Orders.CANCELLED); + Integer cancelledOrders = orderMapper.countByMap(map); + + // 查询全部订单数量 + map.put("status", null); + Integer allOrders = orderMapper.countByMap(map); + + // 构建并返回订单管理数据对象 + return OrderOverViewVO.builder() + .waitingOrders(waitingOrders) + .deliveredOrders(deliveredOrders) + .completedOrders(completedOrders) + .cancelledOrders(cancelledOrders) + .allOrders(allOrders) + .build(); + } + + /** + * 查询菜品总览,包括在售和已下架的菜品数量。 + * + * @return 返回菜品总览数据的DishOverViewVO对象 + */ + public DishOverViewVO getDishOverView() { + Map map = new HashMap(); + map.put("status", StatusConstant.ENABLE); + Integer sold = dishMapper.countByMap(map); + + map.put("status", StatusConstant.DISABLE); + Integer discontinued = dishMapper.countByMap(map); + + // 构建并返回菜品总览数据对象 + return DishOverViewVO.builder() + .sold(sold) + .discontinued(discontinued) + .build(); + } + + /** + * 查询套餐总览,包括在售和已下架的套餐数量。 + * + * @return 返回套餐总览数据的SetmealOverViewVO对象 + */ + public SetmealOverViewVO getSetmealOverView() { + Map map = new HashMap(); + map.put("status", StatusConstant.ENABLE); + Integer sold = setmealMapper.countByMap(map); + + map.put("status", StatusConstant.DISABLE); + Integer discontinued = setmealMapper.countByMap(map); + + // 构建并返回套餐总览数据对象 + return SetmealOverViewVO.builder() + .sold(sold) + .discontinued(discontinued) + .build(); + } +} \ No newline at end of file diff --git a/sky/sky-server/src/main/java/com/sky/task/OrderTask.java b/sky/sky-server/src/main/java/com/sky/task/OrderTask.java new file mode 100644 index 0000000..27329a3 --- /dev/null +++ b/sky/sky-server/src/main/java/com/sky/task/OrderTask.java @@ -0,0 +1,57 @@ +package com.sky.task; + +import com.sky.entity.Orders; +import com.sky.mapper.OrderMapper; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.List; + +/** + * OrderTask类定义了与订单相关的定时任务,用于处理订单超时和一直处于派送中的订单。 + */ +@Component +@Slf4j +public class OrderTask { + @Autowired + private OrderMapper orderMapper; // 注入OrderMapper,用于数据库操作 + + /** + * 处理订单超时的方法,每分钟触发一次。 + * 此方法会查找所有待支付且下单时间超过15分钟的订单,并将它们的状态设置为已取消。 + */ + @Scheduled(cron = "0 * * * * ?") + public void processTimeOrderTask() { + log.info("处理订单超时:{}", LocalDateTime.now()); // 记录当前时间 + LocalDateTime time = LocalDateTime.now().plusMinutes(-15); // 设置15分钟前的时间 + ArrayList ordersList = (ArrayList) orderMapper.getByStatusAndOrderTimeLT(Orders.PENDING_PAYMENT, time); // 查询待支付且下单时间超过15分钟的订单 + if (ordersList != null && ordersList.size() > 0) { // 如果存在这样的订单 + for (int i = 0; i < ordersList.size(); i++) { // 遍历这些订单 + ordersList.get(i).setStatus(Orders.CANCELLED); // 设置状态为已取消 + ordersList.get(i).setCancelReason("订单超时"); // 设置取消原因为订单超时 + } + orderMapper.updateBatchStatus(ordersList, Orders.CANCELLED); // 更新订单状态 + } + } + + /** + * 处理一直处于派送中状态的订单,每天凌晨1点触发一次。 + * 此方法会查找所有一直处于派送中的订单,并将它们的状态设置为已完成。 + */ + @Scheduled(cron = "0 0 1 * * ?") + public void processDeliveryOrder() { + log.info("定时处理处于派送中的订单:{}", LocalDateTime.now()); // 记录当前时间 + + ArrayList ordersList = (ArrayList) orderMapper.getByStatusAndOrderTimeLT(Orders.DELIVERY_IN_PROGRESS, null); // 查询一直处于派送中的订单 + if (ordersList != null && ordersList.size() > 0) { // 如果存在这样的订单 + for (int i = 0; i < ordersList.size(); i++) { // 遍历这些订单 + ordersList.get(i).setStatus(Orders.COMPLETED); // 设置状态为已完成 + } + orderMapper.updateBatchStatus(ordersList, Orders.COMPLETED); // 更新订单状态 + } + } +} \ No newline at end of file