second #4

Merged
m4bagu2fl merged 11 commits from develop into main 7 months ago

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

@ -0,0 +1,36 @@
package com.sky.constant;
/**
*
* <p>
*
*/
public class AutoFillConstant {
/**
*
* <p>
* 使
*/
public static final String SET_CREATE_TIME = "setCreateTime";
/**
*
* <p>
* 使
*/
public static final String SET_UPDATE_TIME = "setUpdateTime";
/**
*
* <p>
* 使
*/
public static final String SET_CREATE_USER = "setCreateUser";
/**
*
* <p>
* 使
*/
public static final String SET_UPDATE_USER = "setUpdateUser";
}

@ -0,0 +1,43 @@
/**
* JwtClaimsConstant JWTJSON Web Tokensclaims
* JWT 使
*/
package com.sky.constant;
import java.time.LocalDateTime;
public class JwtClaimsConstant {
/**
* ID
* JWT
*/
public static final String EMP_ID = "empId";
/**
* ID
* JWT
*/
public static final String USER_ID = "userId";
// 下面的常量被注释掉了,如果需要使用,可以取消注释并添加相应的文档注释。
/*
*
* JWT
* public static final String PHONE = "phone";
*/
/*
*
* JWT
* public static final String USERNAME = "username";
*/
/*
*
* JWT
* public static final String NAME = "name";
*/
}

@ -0,0 +1,23 @@
package com.sky.constant;
/**
*
* <p>
* ENABLEDISABLE
*/
public class StatusConstant {
/**
*
* <p>
* 使
*/
public static final Integer ENABLE = 1;
/**
*
* <p>
* 使
*/
public static final Integer DISABLE = 0;
}

@ -0,0 +1,43 @@
package com.sky.context;
/**
* BaseContext ThreadLocal 线
* 线
*/
public class BaseContext {
/**
* threadLocal ThreadLocal 线
* 线线
*/
private static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
/**
* 线ID
* IDIDID
*
* @param id ID
*/
public static void setCurrentId(Long id) {
threadLocal.set(id);
}
/**
* 线ID
* 线ID null
*
* @return 线ID
*/
public static Long getCurrentId() {
return threadLocal.get();
}
/**
* 线ID
* 线
*/
public static void removeCurrentId() {
threadLocal.remove();
}
}

@ -0,0 +1,27 @@
package com.sky.exception;
/**
*
* <p>
* 访
*/
public class AccountNotFoundException extends BaseException {
/**
*
* <p>
* 使
*/
public AccountNotFoundException() {
super();
}
/**
*
*
* @param msg
*/
public AccountNotFoundException(String msg) {
super(msg);
}
}

@ -0,0 +1,19 @@
package com.sky.exception;
/**
* AddressBookBusinessException 簿
* BaseException使簿
*/
public class AddressBookBusinessException extends BaseException {
/**
* AddressBookBusinessException
*
* @param msg
* 便
*/
public AddressBookBusinessException(String msg) {
super(msg); // 调用父类 BaseException 的构造函数,传递错误信息。
}
}

@ -0,0 +1,17 @@
package com.sky.exception;
/**
*
* <p>
*
*/
public class LoginFailedException extends BaseException {
/**
*
*
* @param msg
*/
public LoginFailedException(String msg) {
super(msg);
}
}

@ -0,0 +1,19 @@
package com.sky.exception;
/**
* OrderBusinessException
* BaseException使
*/
public class OrderBusinessException extends BaseException {
/**
* OrderBusinessException
*
* @param msg
* 便
*/
public OrderBusinessException(String msg) {
super(msg); // 调用父类 BaseException 的构造函数,传递错误信息。
}
}

@ -0,0 +1,27 @@
package com.sky.exception;
/**
*
* <p>
*
*/
public class SetmealEnableFailedException extends BaseException {
/**
*
* <p>
* 使
*/
public SetmealEnableFailedException() {
super();
}
/**
*
*
* @param msg
*/
public SetmealEnableFailedException(String msg) {
super(msg);
}
}

@ -0,0 +1,19 @@
package com.sky.exception;
/**
* ShoppingCartBusinessException
* BaseException使
*/
public class ShoppingCartBusinessException extends BaseException {
/**
* ShoppingCartBusinessException
*
* @param msg
*
*/
public ShoppingCartBusinessException(String msg) {
super(msg); // 调用父类 BaseException 的构造函数,并传递错误消息。
}
}

@ -0,0 +1,42 @@
package com.sky.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* OSS
* <p>
* OSS
*/
@Component
@ConfigurationProperties(prefix = "sky.alioss") // 指定配置文件中相关属性的前缀
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
public class AliOssProperties {
/**
* OSS
*/
private String endpoint;
/**
* 访ID
*/
private String accessKeyId;
/**
* 访
*/
private String accessKeySecret;
/**
*
*/
private String bucketName;
/**
*
*/
private String uploadPath;
}

@ -0,0 +1,53 @@
package com.sky.properties;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
/**
* JwtProperties JWTJSON Web Tokens
* Spring Boot @ConfigurationProperties application.properties application.yml
*/
@Component
@ConfigurationProperties(prefix = "sky.jwt") // 指定配置文件中属性的前缀
@Data
public class JwtProperties {
/**
* adminSecretKey JWT
* JWT
*/
private String adminSecretKey;
/**
* adminTtl JWT
*
*/
private long adminTtl;
/**
* adminTokenName JWT
* HTTP JWT
*/
private String adminTokenName;
/**
* userSecretKey JWT
*
* JWT
*/
private String userSecretKey;
/**
* userTtl JWT
*
*/
private long userTtl;
/**
* userTokenName JWT
* HTTP JWT
*/
private String userTokenName;
}

@ -0,0 +1,34 @@
package com.sky.result;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
import java.util.List;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
@AllArgsConstructor // 使用lombok提供的注解来自动生成包含所有参数的构造函数
@NoArgsConstructor // 使用lombok提供的注解来自动生成无参数的构造函数
public class PageResult implements Serializable {
/**
*
* <p>
*
*/
private long total; // 总记录数
/**
*
* <p>
*
*/
private List records; // 当前页数据集合
}

@ -0,0 +1,76 @@
package com.sky.result;
import lombok.Data;
import java.io.Serializable;
/**
* Result
* Serializable 便
*
* @param <T>
*/
@Data
public class Result<T> implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号,用于确保反序列化时的兼容性
/**
* 1 0
*
*/
private Integer code;
/**
*
* 便
*/
private String msg;
/**
*
*
*/
private T data;
/**
* Result
*
* @param <T>
* @return Result 1
*/
public static <T> Result<T> success() {
Result<T> result = new Result<T>();
result.code = 1; // 设置状态码为成功
return result;
}
/**
* Result
*
* @param object
* @param <T>
* @return Result 1
*/
public static <T> Result<T> success(T object) {
Result<T> result = new Result<T>();
result.data = object; // 设置返回的数据
result.code = 1; // 设置状态码为成功
return result;
}
/**
* Result
*
* @param msg
* @param <T>
* @return Result 0
*/
public static <T> Result<T> error(String msg) {
Result<T> result = new Result<T>();
result.msg = msg; // 设置错误信息
result.code = 0; // 设置状态码为失败
return result;
}
}

@ -0,0 +1,70 @@
package com.sky.utils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.Map;
/**
* JWT
* <p>
* JWT
*/
public class JwtUtil {
/**
* JWT
* <p>
* 使HS256使
*
* @param secretKey JWT
* @param ttlMillis JWT()
* @param claims
* @return JWT
*/
public static String createJWT(String secretKey, long ttlMillis, Map<String, Object> claims) {
// 指定签名时使用的签名算法即header部分
SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
// 生成JWT的时间
long expMillis = System.currentTimeMillis() + ttlMillis;
Date exp = new Date(expMillis);
// 设置jwt的body
JwtBuilder builder = Jwts.builder()
// 如果有私有声明一定要先设置这个自己创建的私有的声明这个是给builder的claim赋值一旦写在标准的声明赋值之后就是覆盖了那些标准的声明的
.setClaims(claims)
// 设置签名使用的签名算法和签名使用的秘钥
.signWith(signatureAlgorithm, secretKey.getBytes(StandardCharsets.UTF_8))
// 设置过期时间
.setExpiration(exp);
return builder.compact();
}
/**
* Token
* <p>
* JWTClaims
*
* @param secretKey JWTsign
*
* @param token token
* @return Claims
*/
public static Claims parseJWT(String secretKey, String token) {
// 得到DefaultJwtParser
Claims claims = Jwts.parser()
// 设置签名的秘钥
.setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
// 设置需要解析的jwt
.parseClaimsJws(token)
.getBody();
return claims;
}
}

@ -0,0 +1,233 @@
package com.sky.utils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.properties.WeChatProperties;
import com.wechat.pay.contrib.apache.httpclient.WechatPayHttpClientBuilder;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import org.apache.commons.lang.RandomStringUtils;
import org.apache.http.HttpHeaders;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.math.BigDecimal;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Base64;
import java.util.List;
/**
* 退
*/
@Component
public class WeChatPayUtil {
/**
*
*/
public static final String JSAPI = "https://api.mch.weixin.qq.com/v3/pay/transactions/jsapi";
/**
* 退
*/
public static final String REFUNDS = "https://api.mch.weixin.qq.com/v3/refund/domestic/refunds";
@Autowired
private WeChatProperties weChatProperties;
/**
*
* 使API
*
* @return CloseableHttpClient
*/
private CloseableHttpClient getClient() {
PrivateKey merchantPrivateKey = null;
try {
// 加载商户API私钥
merchantPrivateKey = PemUtil.loadPrivateKey(new FileInputStream(new File(weChatProperties.getPrivateKeyFilePath())));
// 加载微信支付平台证书
X509Certificate x509Certificate = PemUtil.loadCertificate(new FileInputStream(new File(weChatProperties.getWeChatPayCertFilePath())));
List<X509Certificate> wechatPayCertificates = Arrays.asList(x509Certificate);
// 构建HttpClient自动处理签名和验签
WechatPayHttpClientBuilder builder = WechatPayHttpClientBuilder.create()
.withMerchant(weChatProperties.getMchid(), weChatProperties.getMchSerialNo(), merchantPrivateKey)
.withWechatPay(wechatPayCertificates);
CloseableHttpClient httpClient = builder.build();
return httpClient;
} catch (FileNotFoundException e) {
e.printStackTrace();
return null;
}
}
/**
* POSTURL
*
* @param url URL
* @param body JSON
* @return
* @throws Exception
*/
private String post(String url, String body) throws Exception {
CloseableHttpClient httpClient = getClient();
HttpPost httpPost = new HttpPost(url);
httpPost.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
httpPost.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
httpPost.addHeader("Wechatpay-Serial", weChatProperties.getMchSerialNo());
httpPost.setEntity(new StringEntity(body, "UTF-8"));
CloseableHttpResponse response = httpClient.execute(httpPost);
try {
String bodyAsString = EntityUtils.toString(response.getEntity());
return bodyAsString;
} finally {
httpClient.close();
response.close();
}
}
/**
* GETURL
*
* @param url URL
* @return
* @throws Exception
*/
private String get(String url) throws Exception {
CloseableHttpClient httpClient = getClient();
HttpGet httpGet = new HttpGet(url);
httpGet.addHeader(HttpHeaders.ACCEPT, ContentType.APPLICATION_JSON.toString());
httpGet.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_JSON.toString());
httpGet.addHeader("Wechatpay-Serial", weChatProperties.getMchSerialNo());
CloseableHttpResponse response = httpClient.execute(httpGet);
try {
String bodyAsString = EntityUtils.toString(response.getEntity());
return bodyAsString;
} finally {
httpClient.close();
response.close();
}
}
/**
* 使JSAPI
*
* @param orderNum
* @param total
* @param description
* @param openid openid
* @return
* @throws Exception
*/
private String jsapi(String orderNum, BigDecimal total, String description, String openid) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("appid", weChatProperties.getAppid());
jsonObject.put("mchid", weChatProperties.getMchid());
jsonObject.put("description", description);
jsonObject.put("out_trade_no", orderNum);
jsonObject.put("notify_url", weChatProperties.getNotifyUrl());
JSONObject amount = new JSONObject();
amount.put("total", total.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue());
amount.put("currency", "CNY");
jsonObject.put("amount", amount);
JSONObject payer = new JSONObject();
payer.put("openid", openid);
jsonObject.put("payer", payer);
String body = jsonObject.toJSONString();
return post(JSAPI, body);
}
/**
*
*
* @param orderNum
* @param total
* @param description
* @param openid openid
* @return JSONObject
* @throws Exception
*/
public JSONObject pay(String orderNum, BigDecimal total, String description, String openid) throws Exception {
String bodyAsString = jsapi(orderNum, total, description, openid);
JSONObject jsonObject = JSON.parseObject(bodyAsString);
String prepayId = jsonObject.getString("prepay_id");
if (prepayId != null) {
String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
String nonceStr = RandomStringUtils.randomNumeric(32);
ArrayList<Object> list = new ArrayList<>();
list.add(weChatProperties.getAppid());
list.add(timeStamp);
list.add(nonceStr);
list.add("prepay_id=" + prepayId);
StringBuilder stringBuilder = new StringBuilder();
for (Object o : list) {
stringBuilder.append(o).append("\n");
}
String signMessage = stringBuilder.toString();
byte[] message = signMessage.getBytes();
Signature signature = Signature.getInstance("SHA256withRSA");
signature.initSign(PemUtil.loadPrivateKey(new FileInputStream(new File(weChatProperties.getPrivateKeyFilePath()))));
signature.update(message);
String packageSign = Base64.getEncoder().encodeToString(signature.sign());
JSONObject jo = new JSONObject();
jo.put("timeStamp", timeStamp);
jo.put("nonceStr", nonceStr);
jo.put("package", "prepay_id=" + prepayId);
jo.put("signType", "RSA");
jo.put("paySign", packageSign);
return jo;
}
return jsonObject;
}
/**
* 退
*
* @param outTradeNo
* @param outRefundNo 退
* @param refund 退
* @param total
* @return
* @throws Exception
*/
public String refund(String outTradeNo, String outRefundNo, BigDecimal refund, BigDecimal total) throws Exception {
JSONObject jsonObject = new JSONObject();
jsonObject.put("out_trade_no", outTradeNo);
jsonObject.put("out_refund_no", outRefundNo);
JSONObject amount = new JSONObject();
amount.put("refund", refund.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue());
amount.put("total", total.multiply(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_HALF_UP).intValue());
amount.put("currency", "CNY");
jsonObject.put("amount", amount);
jsonObject.put("notify_url", weChatProperties.getRefundNotifyUrl());
String body = jsonObject.toJSONString();
return post(REFUNDS, body);
}
}

@ -0,0 +1,42 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
* <p>
* DTO
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
public class CategoryDTO implements Serializable {
/**
* ID
* <p>
*
*/
private Long id;
/**
*
* <p>
* 12
*/
private Integer type;
/**
*
* <p>
*
*/
private String name;
/**
*
* <p>
*
*/
private Integer sort;
}

@ -0,0 +1,41 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
* CategoryPageQueryDTO
* Serializable 便
*/
@Data
public class CategoryPageQueryDTO implements Serializable {
private static final long serialVersionUID = 1L; // 序列化版本号,用于确保反序列化时的兼容性
/**
*
* 1
*/
private int page;
/**
*
*
*/
private int pageSize;
/**
*
*
*/
private String name;
/**
*
* 1 2
*
*/
private Integer type;
}

@ -0,0 +1,49 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
public class DishPageQueryDTO implements Serializable {
/**
*
* <p>
* 1
*/
private int page;
/**
*
* <p>
*
*/
private int pageSize;
/**
*
* <p>
*
*/
private String name;
/**
* ID
* <p>
* ID
*/
private Integer categoryId;
/**
*
* <p>
* 01
*/
private Integer status;
}

@ -0,0 +1,33 @@
// 定义包名表示该类属于com.sky.dto包
package com.sky.dto;
// 导入Lombok库中的@Data注解用于自动生成getter和setter方法以及toString、equals和hashCode方法
import lombok.Data;
// 导入Serializable接口使得EmployeeDTO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 使用@Data注解自动为类中的字段生成getter和setter方法
@Data
// 声明EmployeeDTO类并且实现Serializable接口使其可以被序列化
public class EmployeeDTO implements Serializable {
// 定义一个私有的Long类型的变量id用于存储员工的唯一标识符
private Long id;
// 定义一个私有的String类型的变量username用于存储员工的用户名
private String username;
// 定义一个私有的String类型的变量name用于存储员工的姓名
private String name;
// 定义一个私有的String类型的变量phone用于存储员工的电话号码
private String phone;
// 定义一个私有的String类型的变量sex用于存储员工的性别
private String sex;
// 定义一个私有的String类型的变量idNumber用于存储员工的身份证号码
private String idNumber;
}

@ -0,0 +1,35 @@
package com.sky.dto;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
@AllArgsConstructor // 使用lombok提供的注解来自动生成包含所有参数的构造函数
@NoArgsConstructor // 使用lombok提供的注解来自动生成无参数的构造函数
@Builder // 使用lombok提供的注解来自动生成builder模式的构建器
public class GoodsSalesDTO implements Serializable {
/**
*
* <p>
*
*/
private String name;
/**
*
* <p>
*
*/
private Integer number;
}

@ -0,0 +1,22 @@
// 定义包名表示该类属于com.sky.dto包
package com.sky.dto;
// 导入Lombok库中的@Data注解用于自动生成getter和setter方法以及toString、equals和hashCode方法
import lombok.Data;
// 导入Serializable接口使得OrdersCancelDTO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 使用@Data注解自动为类中的字段生成getter和setter方法
@Data
// 声明OrdersCancelDTO类并且实现Serializable接口使其可以被序列化
public class OrdersCancelDTO implements Serializable {
// 定义一个私有的Long类型的变量id用于存储订单的唯一标识符
private Long id;
// 定义一个私有的String类型的变量cancelReason用于存储订单取消的原因
// 订单取消原因
private String cancelReason;
}

@ -0,0 +1,74 @@
package com.sky.dto;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
public class OrdersPageQueryDTO implements Serializable {
/**
*
* <p>
* 1
*/
private int page;
/**
*
* <p>
*
*/
private int pageSize;
/**
*
* <p>
*
*/
private String number;
/**
*
* <p>
*
*/
private String phone;
/**
*
* <p>
*
*/
private Integer status;
/**
*
* <p>
* yyyy-MM-dd HH:mm:ss
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime beginTime;
/**
*
* <p>
* yyyy-MM-dd HH:mm:ss
*/
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime endTime;
/**
* ID
* <p>
*
*/
private Long userId;
}

@ -0,0 +1,23 @@
// 定义包名表示该类属于com.sky.dto包
package com.sky.dto;
// 导入Lombok库中的@Data注解用于自动生成getter和setter方法以及toString、equals和hashCode方法
import lombok.Data;
// 导入Serializable接口使得OrdersPaymentDTO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 使用@Data注解自动为类中的字段生成getter和setter方法
@Data
// 声明OrdersPaymentDTO类并且实现Serializable接口使其可以被序列化
public class OrdersPaymentDTO implements Serializable {
// 定义一个私有的String类型的变量orderNumber用于存储订单的编号
// 订单号
private String orderNumber;
// 定义一个私有的Integer类型的变量payMethod用于存储订单的付款方式
// 付款方式
private Integer payMethod;
}

@ -0,0 +1,35 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
public class PasswordEditDTO implements Serializable {
/**
* ID
* <p>
* ID
*/
private Long empId;
/**
*
* <p>
* 使
*/
private String oldPassword;
/**
*
* <p>
*
*/
private String newPassword;
}

@ -0,0 +1,46 @@
// 定义包名表示该类属于com.sky.dto包
package com.sky.dto;
// 导入com.sky.entity.SetmealDish类这个类可能包含了套餐中包含的菜品信息
import com.sky.entity.SetmealDish;
// 导入Lombok库中的@Data注解用于自动生成getter和setter方法以及toString、equals和hashCode方法
import lombok.Data;
// 导入Serializable接口使得SetmealDTO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 导入BigDecimal类用于精确表示货币等需要高精度的场景
import java.math.BigDecimal;
// 导入ArrayList类用于创建动态数组
import java.util.ArrayList;
// 导入List接口用于定义一个动态数组的引用
import java.util.List;
// 使用@Data注解自动为类中的字段生成getter和setter方法
@Data
// 声明SetmealDTO类并且实现Serializable接口使其可以被序列化
public class SetmealDTO implements Serializable {
// 定义一个私有的Long类型的变量id用于存储套餐的唯一标识符
private Long id;
// 分类id用于标识套餐所属的分类
private Long categoryId;
// 套餐名称,用于存储套餐的名称
private String name;
// 套餐价格使用BigDecimal类型以确保价格的精确表示
private BigDecimal price;
// 状态0表示停用1表示启用
private Integer status;
// 描述信息,用于存储套餐的详细描述
private String description;
// 图片,用于存储套餐的图片链接或路径
private String image;
// 套餐菜品关系用于存储套餐中包含的菜品列表初始为空的ArrayList
private List<SetmealDish> setmealDishes = new ArrayList<>();
}

@ -0,0 +1,21 @@
package com.sky.dto;
import lombok.Data;
import java.io.Serializable;
/**
* C
* <p>
* C
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
public class UserLoginDTO implements Serializable {
/**
*
* <p>
*
*/
private String code;
}

@ -0,0 +1,70 @@
// 定义包名表示该类属于com.sky.entity包
package com.sky.entity;
// 导入Lombok库中的注解用于简化Java类的编写
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 导入Serializable接口使得AddressBook类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
/**
* 簿
*/
// 使用@Data注解自动为类中的字段生成getter和setter方法以及toString、equals和hashCode方法
@Data
// 使用@Builder注解提供建造者模式的实现方便对象的构建
@Builder
// 使用@NoArgsConstructor注解生成无参构造方法
@NoArgsConstructor
// 使用@AllArgsConstructor注解生成包含所有属性的构造方法
@AllArgsConstructor
public class AddressBook implements Serializable {
// 定义serialVersionUID用于在序列化和反序列化过程中确保版本一致性
private static final long serialVersionUID = 1L;
// 定义一个私有的Long类型的变量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,51 @@
package com.sky.entity;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
@Builder // 提供builder模式的构建器
@NoArgsConstructor // 提供无参数的构造函数
@AllArgsConstructor // 提供包含所有属性的构造函数
public class DishFlavor implements Serializable {
private static final long serialVersionUID = 1L; // 序列化ID用于序列化和反序列化
/**
* ID
* <p>
*
*/
private Long id;
/**
* ID
* <p>
*
*/
private Long dishId;
/**
*
* <p>
*
*/
private String name;
/**
*
* <p>
*
*/
private String value;
}

@ -0,0 +1,71 @@
// 定义包名表示该类属于com.sky.entity包
package com.sky.entity;
// 导入Lombok库中的注解用于简化Java类的编写
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 导入Serializable接口使得Employee类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 导入LocalDateTime类用于存储日期和时间
import java.time.LocalDateTime;
/**
*
*/
// 使用@Data注解自动为类中的字段生成getter和setter方法以及toString、equals和hashCode方法
@Data
// 使用@Builder注解提供建造者模式的实现方便对象的构建
@Builder
// 使用@NoArgsConstructor注解生成无参构造方法
@NoArgsConstructor
// 使用@AllArgsConstructor注解生成包含所有属性的构造方法
@AllArgsConstructor
public class Employee implements Serializable {
// 定义serialVersionUID用于在序列化和反序列化过程中确保版本一致性
private static final long serialVersionUID = 1L;
// 定义一个私有的Long类型的变量id用于存储员工的唯一标识符
private Long id;
// 用户名,用于存储员工的登录名
private String username;
// 姓名,用于存储员工的真实姓名
private String name;
// 密码,用于存储员工的登录密码
private String password;
// 手机号,用于存储员工的联系电话
private String phone;
// 性别,通常用"男"或"女"表示
private String sex;
// 身份证号码,用于存储员工的身份证信息
private String idNumber;
// 状态,用于标识员工的当前状态,如在职、离职等
private Integer status;
// 创建时间,用于存储记录创建的时间
// 注释掉的@JsonFormat注解用于在JSON序列化时指定日期时间的格式
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;
// 更新时间,用于存储记录最后一次更新的时间
// 注释掉的@JsonFormat注解用于在JSON序列化时指定日期时间的格式
// @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime updateTime;
// 创建用户ID用于标识创建这条记录的用户
private Long createUser;
// 更新用户ID用于标识最后一次更新这条记录的用户
private Long updateUser;
}

@ -0,0 +1,101 @@
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;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
@Builder // 提供builder模式的构建器
@NoArgsConstructor // 提供无参数的构造函数
@AllArgsConstructor // 提供包含所有属性的构造函数
public class Setmeal implements Serializable {
private static final long serialVersionUID = 1L; // 序列化ID用于序列化和反序列化
/**
* ID
* <p>
*
*/
private Long id;
/**
* ID
* <p>
*
*/
private Long categoryId;
/**
*
* <p>
*
*/
private String name;
/**
*
* <p>
*
*/
private BigDecimal price;
/**
*
* <p>
* 01
*/
private Integer status;
/**
*
* <p>
*
*/
private String description;
/**
*
* <p>
*
*/
private String image;
/**
*
* <p>
*
*/
private LocalDateTime createTime;
/**
*
* <p>
*
*/
private LocalDateTime updateTime;
/**
* ID
* <p>
* ID
*/
private Long createUser;
/**
* ID
* <p>
* ID
*/
private Long updateUser;
}

@ -0,0 +1,48 @@
// 定义包名表示该类属于com.sky.entity包
package com.sky.entity;
// 导入Lombok库中的注解用于简化Java类的编写
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 导入Serializable接口使得SetmealDish类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 导入BigDecimal类用于精确表示货币等需要高精度的场景
import java.math.BigDecimal;
/**
*
*/
// 使用@Data注解自动为类中的字段生成getter和setter方法以及toString、equals和hashCode方法
@Data
// 使用@Builder注解提供建造者模式的实现方便对象的构建
@Builder
// 使用@NoArgsConstructor注解生成无参构造方法
@NoArgsConstructor
// 使用@AllArgsConstructor注解生成包含所有属性的构造方法
@AllArgsConstructor
public class SetmealDish implements Serializable {
// 定义serialVersionUID用于在序列化和反序列化过程中确保版本一致性
private static final long serialVersionUID = 1L;
// 定义一个私有的Long类型的变量id用于存储套餐菜品关系的唯一标识符
private Long id;
// 套餐id用于标识套餐的唯一标识符
private Long setmealId;
// 菜品id用于标识菜品的唯一标识符
private Long dishId;
// 菜品名称,冗余字段,用于存储菜品的名称,可能是为了查询方便而存储的额外信息
private String name;
// 菜品原价使用BigDecimal类型以确保价格的精确表示
private BigDecimal price;
// 份数,用于标识套餐中包含的该菜品的份数
private Integer copies;
}

@ -0,0 +1,56 @@
package com.sky.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
* <p>
*
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
@Builder // 提供builder模式的构建器
@NoArgsConstructor // 提供无参数的构造函数
@AllArgsConstructor // 提供包含所有属性的构造函数
public class BusinessDataVO implements Serializable {
/**
*
* <p>
*
*/
private Double turnover;
/**
*
* <p>
*
*/
private Integer validOrderCount;
/**
*
* <p>
*
*/
private Double orderCompletionRate;
/**
*
* <p>
*
*/
private Double unitPrice;
/**
*
* <p>
*
*/
private Integer newUsers;
}

@ -0,0 +1,37 @@
// 定义包名表示该类属于com.sky.vo包
package com.sky.vo;
// 导入Lombok库中的注解用于简化Java类的编写
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 导入Serializable接口使得DishItemVO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
/**
*
*/
// 使用@Data注解自动为类中的字段生成getter和setter方法以及toString、equals和hashCode方法
@Data
// 使用@Builder注解提供建造者模式的实现方便对象的构建
@Builder
// 使用@NoArgsConstructor注解生成无参构造方法
@NoArgsConstructor
// 使用@AllArgsConstructor注解生成包含所有属性的构造方法
@AllArgsConstructor
public class DishItemVO implements Serializable {
// 菜品名称,用于存储菜品的名称
private String name;
// 份数,用于标识菜品的份数
private Integer copies;
// 菜品图片,用于存储菜品的图片链接或路径
private String image;
// 菜品描述,用于存储菜品的详细描述信息
private String description;
}

@ -0,0 +1,56 @@
package com.sky.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
*
* <p>
* JWT
*/
@Data // 使用lombok提供的注解来自动生成getter和setter方法以及toString等方法
@Builder // 提供builder模式的构建器
@NoArgsConstructor // 提供无参数的构造函数
@AllArgsConstructor // 提供包含所有属性的构造函数
@ApiModel(description = "员工登录返回的数据格式") // Swagger注解用于描述这个VO对象
public class EmployeeLoginVO implements Serializable {
/**
*
* <p>
*
*/
@ApiModelProperty("主键值") // Swagger注解用于描述字段
private Long id;
/**
*
* <p>
*
*/
@ApiModelProperty("用户名") // Swagger注解用于描述字段
private String userName;
/**
*
* <p>
*
*/
@ApiModelProperty("姓名") // Swagger注解用于描述字段
private String name;
/**
* JWT
* <p>
* JWT
*/
@ApiModelProperty("jwt令牌") // Swagger注解用于描述字段
private String token;
}

@ -0,0 +1,40 @@
// 定义包名表示该类属于com.sky.vo包
package com.sky.vo;
// 导入Lombok库中的注解用于简化Java类的编写
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 导入Serializable接口使得OrderOverViewVO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
/**
*
*/
// 使用@Data注解自动为类中的字段生成getter和setter方法以及toString、equals和hashCode方法
@Data
// 使用@Builder注解提供建造者模式的实现方便对象的构建
@Builder
// 使用@NoArgsConstructor注解生成无参构造方法
@NoArgsConstructor
// 使用@AllArgsConstructor注解生成包含所有属性的构造方法
@AllArgsConstructor
public class OrderOverViewVO implements Serializable {
// 待接单数量,用于存储待接单的订单数量
private Integer waitingOrders;
// 待派送数量,用于存储待派送的订单数量
private Integer deliveredOrders;
// 已完成数量,用于存储已完成的订单数量
private Integer completedOrders;
// 已取消数量,用于存储已取消的订单数量
private Integer cancelledOrders;
// 全部订单,用于存储总订单数量
private Integer allOrders;
}

@ -0,0 +1,32 @@
package com.sky.vo;
import lombok.Data;
import java.io.Serializable;
/**
* OrderStatisticsVO
* Serializable
* 使 Lombok @Data gettersettertoStringequals hashCode
*/
@Data
public class OrderStatisticsVO implements Serializable {
/**
*
*
*/
private Integer toBeConfirmed;
/**
*
*
*/
private Integer confirmed;
/**
*
*
*/
private Integer deliveryInProgress;
}

@ -0,0 +1,41 @@
// 定义包名表示该类属于com.sky.vo包
package com.sky.vo;
// 导入Lombok库中的注解用于简化Java类的编写
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 导入Serializable接口使得OrderSubmitVO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 导入BigDecimal类用于精确表示货币等需要高精度的场景
import java.math.BigDecimal;
// 导入LocalDateTime类用于存储日期和时间
import java.time.LocalDateTime;
/**
*
*/
// 使用@Data注解自动为类中的字段生成getter和setter方法以及toString、equals和hashCode方法
@Data
// 使用@Builder注解提供建造者模式的实现方便对象的构建
@Builder
// 使用@NoArgsConstructor注解生成无参构造方法
@NoArgsConstructor
// 使用@AllArgsConstructor注解生成包含所有属性的构造方法
@AllArgsConstructor
public class OrderSubmitVO implements Serializable {
// 订单id用于存储订单的唯一标识符
private Long id;
// 订单号,用于存储订单的编号,通常用于客户和商家之间的交流和查询
private String orderNumber;
// 订单金额使用BigDecimal类型以确保金额的精确表示
private BigDecimal orderAmount;
// 下单时间,用于存储订单被提交的时间
private LocalDateTime orderTime;
}

@ -0,0 +1,33 @@
package com.sky.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* SetmealOverViewVO
* Serializable
* 使 Lombok @Data@Builder@NoArgsConstructor @AllArgsConstructor
* 访
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SetmealOverViewVO implements Serializable {
/**
*
*
*/
private Integer sold;
/**
*
*
*/
private Integer discontinued;
}

@ -0,0 +1,66 @@
// 定义包名表示该类属于com.sky.vo包
package com.sky.vo;
// 导入com.sky.entity.SetmealDish类这个类可能包含了套餐中包含的菜品信息
import com.sky.entity.SetmealDish;
// 导入Lombok库中的注解用于简化Java类的编写
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
// 导入Serializable接口使得SetmealVO类的对象可以被序列化即可以被转换成字节序列
import java.io.Serializable;
// 导入BigDecimal类用于精确表示货币等需要高精度的场景
import java.math.BigDecimal;
// 导入LocalDateTime类用于存储日期和时间
import java.time.LocalDateTime;
// 导入ArrayList类用于创建动态数组
import java.util.ArrayList;
// 导入List接口用于定义一个动态数组的引用
import java.util.List;
/**
*
*/
// 使用@Data注解自动为类中的字段生成getter和setter方法以及toString、equals和hashCode方法
@Data
// 使用@Builder注解提供建造者模式的实现方便对象的构建
@Builder
// 使用@NoArgsConstructor注解生成无参构造方法
@NoArgsConstructor
// 使用@AllArgsConstructor注解生成包含所有属性的构造方法
@AllArgsConstructor
public class SetmealVO implements Serializable {
// 定义一个私有的Long类型的变量id用于存储套餐的唯一标识符
private Long id;
// 分类id用于标识套餐所属的分类
private Long categoryId;
// 套餐名称,用于存储套餐的名称
private String name;
// 套餐价格使用BigDecimal类型以确保价格的精确表示
private BigDecimal price;
// 状态0表示停用1表示启用
private Integer status;
// 描述信息,用于存储套餐的详细描述
private String description;
// 图片,用于存储套餐的图片链接或路径
private String image;
// 更新时间,用于存储套餐最后一次更新的时间
private LocalDateTime updateTime;
// 分类名称,用于存储套餐所属分类的名称
private String categoryName;
// 套餐和菜品的关联关系初始为空的ArrayList用于存储套餐中包含的菜品列表
private List<SetmealDish> setmealDishes = new ArrayList<>();
}

@ -0,0 +1,43 @@
package com.sky.vo;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
/**
* UserReportVO
* Serializable
* 使 Lombok @Data@Builder@NoArgsConstructor @AllArgsConstructor
*
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class UserReportVO implements Serializable {
/**
*
* 2022-10-01,2022-10-02,2022-10-03
*
*/
private String dateList;
/**
*
* 200,210,220
* dateList
*/
private String totalUserList;
/**
*
* 20,21,10
* dateList
*/
private String newUserList;
}

@ -0,0 +1,30 @@
package com.sky;
import com.sky.utils.AliOssUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.socket.config.annotation.EnableWebSocket;
@SpringBootApplication() // 启用Spring Boot的自动配置和组件扫描
@EnableTransactionManagement // 开启注解方式的事务管理
@Slf4j // 启用Lombok日志功能自动生成log对象
@EnableConfigurationProperties // 允许@ConfigurationProperties注解使用用于从配置文件加载属性
@EnableCaching // 启用Spring的缓存机制
@EnableScheduling // 启用定时任务功能
public class SkyServerApplication {
// 程序的入口点启动Spring Boot应用
public static void main(String[] args) {
SpringApplication.run(SkyServerApplication.class, args); // 启动Spring Boot应用
log.info("server started"); // 输出应用启动的日志信息
}
}

@ -0,0 +1,33 @@
package com.sky.annotation;
import com.sky.enumeration.OperationType;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* AutoFill
*
*
* -
* - AOP
*
* 使
*
*
* {@code @AutoFill(OperationType.INSERT)}
*/
@Target(ElementType.METHOD) // 指定该注解只能应用于方法上
@Retention(RetentionPolicy.RUNTIME) // 指定该注解在运行时可用(用于运行时动态处理)
public @interface AutoFill {
/**
*
* {@link OperationType} INSERT UPDATE
*
* @return
*/
OperationType value();
}

@ -0,0 +1,97 @@
// 定义包名表示该类属于com.sky.aspectj包
package com.sky.aspectj;
// 导入所需的类和接口
import com.sky.annotation.AutoFill;
import com.sky.constant.AutoFillConstant;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.*;
// 使用@Aspect注解声明一个切面
@Aspect
// 使用@Slf4j注解为类自动注入一个日志对象
@Slf4j
// 使用@Component注解声明一个Spring组件使其可以被Spring容器管理
@Component
public class AutoFillAspect {
// 定义一个切入点,匹配所有标记了@AutoFill注解的com.sky.mapper包下的方法
@Pointcut("@annotation(com.sky.annotation.AutoFill)" + "&& execution(* com.sky.mapper.*.*(..))")
public void pointCount() {
}
// 前置通知,执行切入点匹配的方法之前
@Before("pointCount()")
public void beforeAutoFillAspect(JoinPoint joinPoint) throws InvocationTargetException, IllegalAccessException {
// 获取方法签名
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
// 获取当前执行的方法
Method method = signature.getMethod();
// 获取方法参数
Object[] args = joinPoint.getArgs();
// 获取方法上的@AutoFill注解
AutoFill autoFill = method.getAnnotation(AutoFill.class);
// 从注解中获取操作类型
OperationType value = autoFill.value();
// 存放每个参数对象及其所有方法的映射
HashMap<Object, Method[]> methodHashMap = new HashMap<>();
// 遍历参数对象,获取每个对象的所有方法
for (Object arg : args) {
Class<?> argClass = arg.getClass();
Method[] methods = argClass.getDeclaredMethods();
methodHashMap.put(arg, methods);
}
// 根据操作类型进行不同的字段填充
if (value.equals(OperationType.INSERT)) {
// 插入操作,填充创建时间和创建用户
for (Map.Entry<Object, Method[]> entry : methodHashMap.entrySet()) {
Object key = entry.getKey();
for (Method method1 : entry.getValue()) {
// 填充创建时间和更新时间
if (method1.getName().equals(AutoFillConstant.SET_UPDATE_TIME) || method.getName().equals(AutoFillConstant.SET_CREATE_TIME)) {
method1.invoke(key, LocalDateTime.now());
}
// 填充创建用户和更新用户
if (method1.getName().equals(AutoFillConstant.SET_CREATE_USER) || method.getName().equals(AutoFillConstant.SET_UPDATE_USER)) {
method1.invoke(key, BaseContext.getCurrentId());
}
}
}
} else if (value.equals(OperationType.UPDATE)) {
// 更新操作,填充更新时间和更新用户
for (Map.Entry<Object, Method[]> entry : methodHashMap.entrySet()) {
Object key = entry.getKey();
for (Method method1 : entry.getValue()) {
// 填充更新时间
if (method1.getName().equals(AutoFillConstant.SET_UPDATE_TIME)) {
method1.invoke(key, LocalDateTime.now());
}
// 填充更新用户
if (method1.getName().equals(AutoFillConstant.SET_UPDATE_USER)) {
method1.invoke(key, BaseContext.getCurrentId());
}
}
}
} else {
// 非法操作类型,抛出异常
throw new IllegalArgumentException("自动填充操作类型参数异常!");
}
}
}

@ -0,0 +1,29 @@
package com.sky.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
/**
* WebSocketConfiguration Spring WebSocket
* @Configuration Spring WebSocket Bean
*/
@Configuration
public class WebSocketConfiguration {
/**
* ServerEndpointExporter Bean Bean WebSocket
*
*
* ServerEndpointExporter Spring WebSocket 使 @ServerEndpoint WebSocket
*
* Spring WebSocket
*
* @return ServerEndpointExporter Bean
*/
@Bean
public ServerEndpointExporter serverEndpointExporter(){
// 返回 ServerEndpointExporter 实例Spring 会自动注册 WebSocket 端点
return new ServerEndpointExporter();
}
}

@ -0,0 +1,134 @@
// 定义包名表示该类属于com.sky.controller.admin包
package com.sky.controller.admin;
// 导入所需的类和接口
import com.sky.dto.CategoryDTO;
import com.sky.dto.CategoryPageQueryDTO;
import com.sky.entity.Category;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.CategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
// 使用@RestController注解声明这是一个REST控制器返回的数据会自动转换为JSON格式
@RestController
// 使用@RequestMapping注解定义类级别的路由所有的请求都会以"/admin/category"作为前缀
@RequestMapping("/admin/category")
// 使用@Slf4j注解为类自动注入一个日志对象
@Slf4j
// 使用@Api注解标记这个控制器属于哪个API分类
@Api(tags = "分类相关接口")
public class CategoryController {
// 自动注入CategoryService服务
@Autowired
CategoryService categoryService;
/**
*
*
* @param categoryPageQueryDTO
* @return
*/
@GetMapping({"/page"})
@ApiOperation("分类分页查询")
public Result<PageResult> pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
// 记录日志
log.info("分类分页查询:{}", categoryPageQueryDTO);
// 调用服务层进行分页查询
PageResult pageResult = categoryService.pageQuery(categoryPageQueryDTO);
// 返回查询结果
return Result.success(pageResult);
}
/**
*
*
* @param type
* @return
*/
@GetMapping("/list")
@ApiOperation("根据类型查询分类")
public Result<List> query(Integer type) {
// 记录日志
log.info("根据类型查询分类:{}", type);
// 调用服务层根据类型查询分类
List<Category> result = categoryService.query(type);
// 返回查询结果
return Result.success(result);
}
/**
*
*
* @param id ID
* @return
*/
@DeleteMapping
@ApiOperation("删除分类")
public Result deleteCategory(Long id) {
// 记录日志
log.info("删除分类:{}", id);
// 调用服务层删除分类
categoryService.delete(id);
// 返回操作结果
return Result.success();
}
/**
*
*
* @param categoryDTO DTO
* @return
*/
@PutMapping
@ApiOperation("修改分类")
public Result updateCategory(@RequestBody CategoryDTO categoryDTO) {
// 记录日志
log.info("修改分类:{}", categoryDTO);
// 调用服务层修改分类
categoryService.updateCategory(categoryDTO);
// 返回操作结果
return Result.success();
}
/**
*
*
* @param status
* @param id ID
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("启用禁用分类")
public Result startOrStop(@PathVariable Integer status, Long id) {
// 记录日志
log.info("启用禁用分类status:{},id:{}", status, id);
// 调用服务层启用或禁用分类
categoryService.startOrStop(status, id);
// 返回操作结果
return Result.success();
}
/**
*
*
* @param categoryDTO DTO
* @return
*/
@PostMapping
@ApiOperation("新增分类")
public Result save(@RequestBody CategoryDTO categoryDTO) {
// 记录日志
log.info("新增分类:{}", categoryDTO);
// 调用服务层新增分类
categoryService.save(categoryDTO);
// 返回操作结果
return Result.success();
}
}

@ -0,0 +1,166 @@
package com.sky.controller.admin;
import com.sky.constant.JwtClaimsConstant;
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.properties.JwtProperties;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.EmployeeService;
import com.sky.utils.JwtUtil;
import com.sky.vo.EmployeeLoginVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.DigestUtils;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
/**
*
*
* 使 Swagger API
*/
@RestController
@RequestMapping("/admin/employee")
@Slf4j
@Api(tags = "员工相关接口")
public class EmployeeController {
@Autowired
private EmployeeService employeeService; // 注入员工服务类,用于处理员工相关业务
@Autowired
private JwtProperties jwtProperties; // 注入 JWT 配置类,用于生成 JWT 令牌
/**
*
* JWT
*
* @param employeeLoginDTO
* @return JWT
*/
@PostMapping("/login")
@ApiOperation(value = "员工登录")
public Result<EmployeeLoginVO> login(@RequestBody EmployeeLoginDTO employeeLoginDTO) {
log.info("员工登录:{}", employeeLoginDTO); // 记录登录请求日志
// 调用员工服务进行登录验证
Employee employee = employeeService.login(employeeLoginDTO);
// 登录成功后,生成 JWT 令牌
Map<String, Object> claims = new HashMap<>();
claims.put(JwtClaimsConstant.EMP_ID, employee.getId()); // 将员工ID放入JWT的claims部分
String token = JwtUtil.createJWT(
jwtProperties.getAdminSecretKey(), // 获取密钥
jwtProperties.getAdminTtl(), // 获取有效期
claims); // 设置 JWT claims
// 将登录者的 ID 设置到当前线程上下文中,以便其他地方使用
BaseContext.setCurrentId(employee.getId());
// 构造员工登录响应对象
EmployeeLoginVO employeeLoginVO = EmployeeLoginVO.builder()
.id(employee.getId())
.userName(employee.getUsername())
.name(employee.getName())
.token(token)
.build();
return Result.success(employeeLoginVO); // 返回成功结果
}
/**
* 退
* 退退
*
* @return 退
*/
@PostMapping("/logout")
@ApiOperation("员工退出")
public Result<String> logout() {
return Result.success(); // 直接返回成功
}
/**
*
*
*
* @param employeeDTO
* @return
*/
@PostMapping
@ApiOperation("新增员工")
public Result save(@RequestBody EmployeeDTO employeeDTO) {
log.info("新增员工:{}", employeeDTO); // 记录新增员工请求日志
employeeService.save(employeeDTO); // 调用服务层保存员工数据
return Result.success(); // 返回成功结果
}
/**
*
*
*
* @param employeePageQueryDTO
* @return
*/
@GetMapping("/page")
@ApiOperation("员工分页查询")
public Result<PageResult> pageQuery(EmployeePageQueryDTO employeePageQueryDTO){
log.info("员工分页查询,参数为:{}", employeePageQueryDTO); // 记录分页查询请求日志
PageResult pageResult = employeeService.pageQuery(employeePageQueryDTO); // 调用服务层进行分页查询
return Result.success(pageResult); // 返回分页查询结果
}
/**
*
*
*
* @param status 10
* @param id ID
* @return
*/
@PostMapping("/status/{status}")
@ApiOperation("启用或禁用员工账号")
public Result startOrStop(@PathVariable Integer status, Long id) {
log.info("启用禁用员工账号{},{}", status, id); // 记录启用禁用请求日志
employeeService.startOrStop(status, id); // 调用服务层启用或禁用员工账号
return Result.success(); // 返回成功结果
}
/**
* ID
*
*
* @param id ID
* @return
*/
@GetMapping("/{id}")
@ApiOperation("通过id查询员工信息")
public Result<Employee> getById(@PathVariable Long id) {
Employee employee = employeeService.getById(id); // 调用服务层查询员工
return Result.success(employee); // 返回查询结果
}
/**
*
*
*
* @param employeeDTO
* @return
*/
@PutMapping
@ApiOperation("编辑员工信息")
public Result update(@RequestBody EmployeeDTO employeeDTO) {
log.info("编辑员工信息:{}", employeeDTO); // 记录编辑员工信息请求日志
employeeService.update(employeeDTO); // 调用服务层更新员工信息
return Result.success(); // 返回成功结果
}
}

@ -0,0 +1,153 @@
// 定义包名表示该类属于com.sky.controller.admin包
package com.sky.controller.admin;
// 导入所需的类和接口
import com.sky.dto.OrdersCancelDTO;
import com.sky.dto.OrdersConfirmDTO;
import com.sky.dto.OrdersPageQueryDTO;
import com.sky.dto.OrdersRejectionDTO;
import com.sky.result.PageResult;
import com.sky.result.Result;
import com.sky.service.OrderService;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
/**
*
*/
@RestController("adminOrderController")
@RequestMapping("/admin/order")
@Slf4j
@Api(tags = "订单管理接口")
public class OrderController {
// 自动注入OrderService服务
@Autowired
private OrderService orderService;
/**
*
*
* @param id ID
* @return
*/
@PutMapping("/complete/{id}")
@ApiOperation("完成订单")
public Result complete(@PathVariable("id") Long id) {
// 调用服务层完成订单
orderService.complete(id);
// 返回操作结果
return Result.success();
}
/**
*
*
* @param id ID
* @return
*/
@PutMapping("/delivery/{id}")
@ApiOperation("派送订单")
public Result delivery(@PathVariable("id") Long id) {
// 调用服务层派送订单
orderService.delivery(id);
// 返回操作结果
return Result.success();
}
/**
*
*
* @param ordersPageQueryDTO
* @return
*/
@GetMapping("/conditionSearch")
@ApiOperation("订单搜索")
public Result<PageResult> conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
// 调用服务层进行订单搜索
PageResult pageResult = orderService.conditionSearch(ordersPageQueryDTO);
// 返回搜索结果
return Result.success(pageResult);
}
/**
*
*
* @return
*/
@GetMapping("/statistics")
@ApiOperation("各个状态的订单数量统计")
public Result<OrderStatisticsVO> statistics() {
// 调用服务层获取订单数量统计
OrderStatisticsVO orderStatisticsVO = orderService.statistics();
// 返回统计结果
return Result.success(orderStatisticsVO);
}
/**
*
*
* @param id ID
* @return
*/
@GetMapping("/details/{id}")
@ApiOperation("查询订单详情")
public Result<OrderVO> details(@PathVariable("id") Long id) {
// 调用服务层查询订单详情
OrderVO orderVO = orderService.details(id);
// 返回订单详情
return Result.success(orderVO);
}
/**
*
*
* @param ordersConfirmDTO
* @return
*/
@PutMapping("/confirm")
@ApiOperation("接单")
public Result confirm(@RequestBody OrdersConfirmDTO ordersConfirmDTO) {
// 调用服务层接单
orderService.confirm(ordersConfirmDTO);
// 返回操作结果
return Result.success();
}
/**
*
*
* @param ordersRejectionDTO
* @return
* @throws Exception
*/
@PutMapping("/rejection")
@ApiOperation("拒单")
public Result rejection(@RequestBody OrdersRejectionDTO ordersRejectionDTO) throws Exception {
// 调用服务层拒单
orderService.rejection(ordersRejectionDTO);
// 返回操作结果
return Result.success();
}
/**
*
*
* @param ordersCancelDTO
* @return
* @throws Exception
*/
@PutMapping("/cancel")
@ApiOperation("取消订单")
public Result cancel(@RequestBody OrdersCancelDTO ordersCancelDTO) throws Exception {
// 调用服务层取消订单
orderService.cancel(ordersCancelDTO);
// 返回操作结果
return Result.success();
}
}

@ -0,0 +1,67 @@
package com.sky.controller.admin;
import com.sky.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
/**
*
*
* 使 Redis 便
*/
@RestController("adminShopController")
@Slf4j
@Api("管理员店铺相关接口")
@RequestMapping("/admin/shop")
public class ShopController {
@Autowired
private RedisTemplate redisTemplate; // 注入 RedisTemplate 用于操作 Redis 数据库
private static final String key = "SHOP_STATUS"; // 定义 Redis 中保存店铺状态的键
/**
*
* 1 0
*
* @param status 1: , 0:
* @return
*/
@PutMapping("/{status}")
@ApiOperation("设置店铺营业状态")
public Result setStatus(@PathVariable Integer status) {
// 记录设置店铺状态的日志信息
log.info("设置店铺营业状态为:{}", status == 1 ? "营业中" : "打烊中");
// 获取 Redis 的 ValueOperations 操作对象
ValueOperations valueOperations = redisTemplate.opsForValue();
// 将店铺状态保存到 Redis 中
valueOperations.set(key, status);
return Result.success(); // 返回成功结果
}
/**
*
* 1 0
*
* @return
*/
@GetMapping("/status")
@ApiOperation("查询店铺营业状态")
public Result<Integer> queryStatus() {
// 获取 Redis 的 ValueOperations 操作对象
ValueOperations valueOperations = redisTemplate.opsForValue();
// 从 Redis 中获取店铺状态
Integer status = (Integer) valueOperations.get(key);
// 记录查询店铺状态的日志信息
log.info("店铺状态为:{}", status == 1 ? "营业中" : "打烊中");
return Result.success(status); // 返回查询结果
}
}

@ -0,0 +1,94 @@
// 定义包名表示该类属于com.sky.controller.admin包
package com.sky.controller.admin;
// 导入所需的类和接口
import com.sky.result.Result;
import com.sky.service.WorkspaceService;
import com.sky.vo.BusinessDataVO;
import com.sky.vo.DishOverViewVO;
import com.sky.vo.OrderOverViewVO;
import com.sky.vo.SetmealOverViewVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.time.LocalTime;
/**
*
*/
@RestController
@RequestMapping("/admin/workspace")
@Slf4j
@Api(tags = "工作台相关接口")
public class WorkSpaceController {
// 自动注入WorkspaceService服务
@Autowired
private WorkspaceService workspaceService;
/**
*
*
* @return
*/
@GetMapping("/businessData")
@ApiOperation("工作台今日数据查询")
public Result<BusinessDataVO> businessData(){
// 获得当天的开始时间00:00:00
LocalDateTime begin = LocalDateTime.now().with(LocalTime.MIN);
// 获得当天的结束时间23:59:59
LocalDateTime end = LocalDateTime.now().with(LocalTime.MAX);
// 调用服务层获取工作台今日数据
BusinessDataVO businessDataVO = workspaceService.getBusinessData(begin, end);
// 返回工作台今日数据
return Result.success(businessDataVO);
}
/**
*
*
* @return
*/
@GetMapping("/overviewOrders")
@ApiOperation("查询订单管理数据")
public Result<OrderOverViewVO> orderOverView(){
// 调用服务层获取订单管理数据
OrderOverViewVO orderOverViewVO = workspaceService.getOrderOverView();
// 返回订单管理数据
return Result.success(orderOverViewVO);
}
/**
*
*
* @return
*/
@GetMapping("/overviewDishes")
@ApiOperation("查询菜品总览")
public Result<DishOverViewVO> dishOverView(){
// 调用服务层获取菜品总览数据
DishOverViewVO dishOverViewVO = workspaceService.getDishOverView();
// 返回菜品总览数据
return Result.success(dishOverViewVO);
}
/**
*
*
* @return
*/
@GetMapping("/overviewSetmeals")
@ApiOperation("查询套餐总览")
public Result<SetmealOverViewVO> setmealOverView(){
// 调用服务层获取套餐总览数据
SetmealOverViewVO setmealOverViewVO = workspaceService.getSetmealOverView();
// 返回套餐总览数据
return Result.success(setmealOverViewVO);
}
}

@ -0,0 +1,48 @@
package com.sky.controller.user;
import com.sky.entity.Category;
import com.sky.result.Result;
import com.sky.service.CategoryService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* -
*
*/
@RestController("userCategoryController")
@RequestMapping("/user/category")
@Api(tags = "C端-分类接口")
@Slf4j
public class CategoryController {
@Autowired
private CategoryService categoryService; // 注入 CategoryService 服务,用于查询分类信息
/**
*
* type
*
* @param type
* @return
*/
@GetMapping("/list")
@ApiOperation("查询分类")
public Result<List<Category>> list(Integer type) {
// 记录查询分类操作的日志,输出传入的分类类型参数
log.info("查询分类{}", type);
// 调用 categoryService 查询分类信息
List<Category> list = categoryService.query(type);
// 返回查询结果,封装在 Result 对象中
return Result.success(list);
}
}

@ -0,0 +1,75 @@
// 定义包名表示该类属于com.sky.controller.user包
package com.sky.controller.user;
// 导入所需的类和接口
import com.sky.constant.StatusConstant;
import com.sky.entity.Dish;
import com.sky.result.Result;
import com.sky.service.DishService;
import com.sky.vo.DishVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
// 使用@RestController注解声明这是一个REST控制器返回的数据会自动转换为JSON格式
@RestController("userDishController")
// 使用@RequestMapping注解定义类级别的路由所有的请求都会以"/user/dish"作为前缀
@RequestMapping("/user/dish")
// 使用@Slf4j注解为类自动注入一个日志对象
@Slf4j
// 使用@Api注解标记这个控制器属于哪个API分类
@Api(tags = "C端-菜品浏览接口")
public class DishController {
// 自动注入DishService服务
@Autowired
private DishService dishService;
// 自动注入RedisTemplate用于操作Redis缓存
@Autowired
private RedisTemplate redisTemplate;
/**
* id
*
* @param categoryId ID
* @return
*/
@GetMapping("/list")
@ApiOperation("根据分类id查询菜品")
public Result<List<DishVO>> list(Long categoryId) {
// 记录日志输出查询的分类ID
log.info("根据分类id查询菜品:{}", categoryId);
// 定义Redis缓存的键
String key = "dish_" + categoryId;
// 从缓存中获取菜品列表
ValueOperations valueOperations = redisTemplate.opsForValue();
List<DishVO> dishVOList = (List<DishVO>) valueOperations.get(key);
// 如果缓存中存在菜品列表,直接返回
if (dishVOList != null && dishVOList.size() > 0) {
return Result.success(dishVOList);
}
// 如果缓存中不存在,则从数据库中查询
Dish dish = new Dish();
dish.setCategoryId(categoryId); // 设置查询条件为分类ID
dish.setStatus(StatusConstant.ENABLE); // 查询起售中的菜品
// 从数据库中获取菜品列表,并存入缓存
List<DishVO> list = dishService.listWithFlavor(dish);
valueOperations.set(key, list); // 将查询结果存入Redis缓存
// 返回查询结果
return Result.success(list);
}
}

@ -0,0 +1,48 @@
package com.sky.controller.user;
import com.sky.result.Result;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
/**
* -
*
* 使 Redis 便
*/
@RestController("userShopController")
@Slf4j
@Api("用户店铺相关接口")
@RequestMapping("/user/shop")
public class ShopController {
@Autowired
private RedisTemplate redisTemplate; // 注入 RedisTemplate 用于操作 Redis 数据库
private static final String key = "SHOP_STATUS"; // 定义 Redis 中保存店铺状态的键
/**
*
* 1 0
*
* @return
*/
@GetMapping("/status")
@ApiOperation("查询店铺营业状态")
public Result<Integer> queryStatus() {
// 获取 Redis 的 ValueOperations 操作对象
ValueOperations valueOperations = redisTemplate.opsForValue();
// 从 Redis 中获取店铺状态
Integer status = (Integer) valueOperations.get(key);
// 记录查询店铺状态的日志信息
log.info("店铺状态为:{}", status == 1 ? "营业中" : "打烊中");
// 返回查询结果,封装在 Result 对象中
return Result.success(status);
}
}

@ -0,0 +1,99 @@
// 定义包名表示该类属于com.sky.controller.user包
package com.sky.controller.user;
// 导入所需的类和接口
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.ShoppingCart;
import com.sky.result.Result;
import com.sky.service.ShoppingCartService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
// 使用@RestController注解声明这是一个REST控制器返回的数据会自动转换为JSON格式
@RestController
// 使用@Api注解标记这个控制器属于哪个API分类
@Api("C端购物车相关接口")
// 使用@Slf4j注解为类自动注入一个日志对象
@Slf4j
// 使用@RequestMapping注解定义类级别的路由所有的请求都会以"/user/shoppingCart"作为前缀
@RequestMapping("/user/shoppingCart")
public class ShoppingCartController {
// 自动注入ShoppingCartService服务
@Autowired
ShoppingCartService shoppingCartService;
/**
*
*
* @param shoppingCartDTO DTO
* @return
*/
@PostMapping("/add")
@ApiOperation("添加购物车")
public Result add(@RequestBody ShoppingCartDTO shoppingCartDTO) {
// 记录日志,输出添加到购物车的商品信息
log.info("添加购物车:购物车信息:{}", shoppingCartDTO);
// 调用服务层添加商品到购物车
shoppingCartService.add(shoppingCartDTO);
// 返回操作成功的结果
return Result.success();
}
/**
*
*
* @return
*/
@GetMapping("/list")
@ApiOperation("查看购物车")
public Result<List<ShoppingCart>> list() {
// 记录日志,标记查看购物车数据的操作
log.info("查看购物车数据");
// 调用服务层获取用户购物车中的商品列表
List<ShoppingCart> shoppingCartList = shoppingCartService.list();
// 返回购物车商品列表
return Result.success(shoppingCartList);
}
/**
*
*
* @param shoppingCartDTO DTO
* @return
*/
@PostMapping("/sub")
@ApiOperation("删除购物车中的商品")
public Result delete(@RequestBody ShoppingCartDTO shoppingCartDTO){
// 记录日志,输出删除的商品信息
log.info("删除购物车中的商品:{}",shoppingCartDTO);
// 调用服务层删除购物车中的一个商品
shoppingCartService.delete(shoppingCartDTO);
// 返回操作成功的结果
return Result.success();
}
/**
*
*
* @return
*/
@DeleteMapping("/clean")
@ApiOperation("清空购物车")
public Result clean(){
// 记录日志,标记清空购物车的操作
log.info("清空购物车");
// 调用服务层清空购物车
shoppingCartService.clean();
// 返回操作成功的结果
return Result.success();
}
}

@ -0,0 +1,69 @@
package com.sky.interceptor;
import com.sky.constant.JwtClaimsConstant;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* JWT
* JWT
* 401
*/
@Component
@Slf4j
public class JwtTokenAdminInterceptor implements HandlerInterceptor {
@Autowired
private JwtProperties jwtProperties; // 注入 JWT 配置属性,获取密钥和令牌名称
/**
* JWT
* Controller JWT
*
* @param request
* @param response
* @param handler Controller
* @return true false
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 判断当前拦截到的是 Controller 的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
// 当前拦截到的不是动态方法,直接放行
return true;
}
HandlerMethod handlerMethod = (HandlerMethod) handler;
// 1、从请求头中获取 JWT 令牌
String token = request.getHeader(jwtProperties.getAdminTokenName());
// 2、校验令牌
try {
log.info("JWT 校验: {}", token);
Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token); // 解析 JWT
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.EMP_ID).toString()); // 获取员工 ID
BaseContext.setCurrentId(empId); // 设置当前员工 ID 到上下文中
log.info("当前员工 ID: {}", empId);
// 3、校验通过放行请求
return true;
} catch (Exception ex) {
// 4、校验失败返回 401 状态码,表示未授权
log.error(MessageConstant.USER_NOT_LOGIN); // 打印未登录错误日志
response.setStatus(401); // 设置响应状态为 401
return false; // 拦截请求,不继续执行
}
}
}

@ -0,0 +1,68 @@
// 定义包名表示该类属于com.sky.interceptor包
package com.sky.interceptor;
// 导入所需的类和接口
import com.sky.constant.JwtClaimsConstant;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.properties.JwtProperties;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
/**
* JWTSpring MVCJWT
*/
@Component
@Slf4j
public class JwtTokenUserInterceptor implements HandlerInterceptor {
// 自动注入JwtProperties用于获取JWT配置属性
@Autowired
private JwtProperties jwtProperties;
/**
* preHandle
*
* @param request
* @param response
* @param handler HandlerMethodControllerhandler
* @return truefalsefalseresponse
* @throws Exception
*/
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
// 判断当前拦截到的是Controller的方法还是其他资源
if (!(handler instanceof HandlerMethod)) {
// 当前拦截到的不是动态方法,直接放行
return true;
}
HandlerMethod handlerMethod= (HandlerMethod) handler;
// 1、从请求头中获取令牌
String token = request.getHeader(jwtProperties.getUserTokenName());
// 2、校验令牌
try {
log.info("jwt校验:{}", token);
// 使用JwtUtil解析JWT令牌
Claims claims = JwtUtil.parseJWT(jwtProperties.getUserSecretKey(), token);
// 从claims中获取用户ID并设置到BaseContext中供后续使用
Long empId = Long.valueOf(claims.get(JwtClaimsConstant.USER_ID).toString());
BaseContext.setCurrentId(empId);
log.info("当前用户id:{}", empId);
// 3、通过放行
return true;
} catch (Exception ex) {
// 4、不通过响应401状态码
log.error(MessageConstant.USER_NOT_LOGIN);
response.setStatus(401);
return false;
}
}
}

@ -0,0 +1,115 @@
package com.sky.mapper;
import com.github.pagehelper.Page;
import com.sky.annotation.AutoFill;
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.enumeration.OperationType;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@Mapper // 标记为 MyBatis 的 Mapper 接口,表明这是 MyBatis 对数据库操作的接口
public interface DishMapper {
/**
*
*
* @param dishPageQueryDTO
* @return
*/
Page<Dish> pageQuery(DishPageQueryDTO dishPageQueryDTO);
/**
*
*
* @param dish
*/
@AutoFill(OperationType.INSERT) // 自动填充操作,标记为插入操作
void save(Dish dish);
/**
*
*
* @param flavors
*/
void insertBatchFlavors(List<DishFlavor> flavors);
/**
*
*
* @param ids ID
*/
void deleteBatch(ArrayList<Long> ids);
/**
* ID
*
* @param ids ID
* @return
*/
ArrayList<Dish> getByIdBatch(ArrayList<Long> ids);
/**
* ID
*
* @param ids ID
* @return
*/
Integer countMealDish(ArrayList<Long> ids);
/**
*
*
* @param dish
*/
@AutoFill(OperationType.UPDATE) // 自动填充操作,标记为更新操作
void updateDish(Dish dish);
/**
*
*
* @param flavors
*/
void deleteBatchFlavors(List<DishFlavor> flavors);
/**
* ID
*
* @param id ID
* @return
*/
ArrayList<DishFlavor> getFlavorById(Long id);
/**
* ID
*
* @param categoryId ID
* @param status
* @return
*/
ArrayList<Dish> getByCategoryId(Long categoryId, Integer status);
/**
* ID
*
* @param id ID
* @return
*/
@Select("select * from dish where id=#{id}")
Dish getById(Long id);
/**
*
*
* @param map
* @return
*/
Integer countByMap(Map map);
}

@ -0,0 +1,59 @@
// 定义包名表示该类属于com.sky.mapper包
package com.sky.mapper;
// 导入所需的类和注解
import com.github.pagehelper.Page;
import com.sky.annotation.AutoFill;
import com.sky.dto.EmployeePageQueryDTO;
import com.sky.entity.Employee;
import com.sky.enumeration.OperationType;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
// 使用@Mapper注解标记这是一个MyBatis的Mapper接口
@Mapper
public interface EmployeeMapper {
/**
*
*
* @param username
* @return
*/
@Select("select * from employee where username = #{username}")
Employee getByUsername(String username);
/**
*
*
* @param employee
*/
@AutoFill(OperationType.INSERT)
@Insert("insert into employee(name,username,password,phone,sex,id_number,create_time,update_time,create_user,update_user,status)" +
" values(#{name},#{username},#{password},#{phone},#{sex},#{idNumber},#{createTime},#{updateTime},#{createUser},#{updateUser},#{status})")
void save(Employee employee);
/**
*
*
* @param employeePageQueryDTO
* @return
*/
Page<Employee> pageQuery(EmployeePageQueryDTO employeePageQueryDTO);
/**
*
*/
@AutoFill(OperationType.UPDATE)
void update(Employee employee);
/**
* id
*
* @param id ID
* @return
*/
@Select("select * from employee where id=#{id}")
Employee getById(Long id);
}

@ -0,0 +1,73 @@
package com.sky.mapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
@Mapper // 标记为 MyBatis 的 Mapper 接口,用于与数据库交互
public interface ReportMapper {
/**
*
*
*
* @param map
* @return
*/
@Select("select sum(amount) from orders where status=#{status} and checkout_time>#{begin} and checkout_time<#{end}")
Double sumByMap(HashMap<String, Object> map);
/**
*
*
*
* @param map
* @return
*/
@Select("select count(id) from user where create_time>#{begin} and create_time<#{end}")
Integer sumUserByDay(HashMap<String, Object> map);
/**
*
*
*
* @param map
* @return
*/
@Select("select count(*) from user where create_time<#{end}")
Integer sumUser(HashMap<String, Object> map);
/**
*
*
*
* @param map
* @return
*/
@Select("select count(*) from orders where order_time>#{begin} and order_time<#{end}")
Integer sumNewOrder(HashMap<String, Object> map);
/**
*
*
*
* @param map
* @return
*/
@Select("select count(*) from orders where checkout_time>#{begin} and checkout_time<#{end} and status=#{status}")
Integer sumOrder(HashMap<String, Object> map);
/**
*
*
*
* @param map
* @return
*/
@Select("select od.name name, sum(od.number) number from order_detail od, orders o where od.order_id=o.id and status=#{status} and o.order_time>#{begin} and o.order_time<#{end} " +
"group by name order by number desc")
ArrayList<HashMap<String, Object>> salesTop10Report(HashMap<String, Object> map);
}

@ -0,0 +1,116 @@
// 定义包名表示该类属于com.sky.mapper包
package com.sky.mapper;
// 导入所需的类和注解
import com.github.pagehelper.Page;
import com.sky.annotation.AutoFill;
import com.sky.dto.SetmealDTO;
import com.sky.entity.SetmealDish;
import com.sky.enumeration.OperationType;
import com.sky.dto.SetmealPageQueryDTO;
import com.sky.entity.Setmeal;
import com.sky.vo.DishItemVO;
import com.sky.vo.SetmealVO;
import org.apache.ibatis.annotations.Delete;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
// 使用@Mapper注解标记这是一个MyBatis的Mapper接口
@Mapper
public interface SetmealMapper {
/**
*
*
* @param map
* @return
*/
Integer countByMap(Map map);
/**
*
*
* @param setmeal
* @return
*/
List<Setmeal> list(Setmeal setmeal);
/**
* id
*
* @param setmealId ID
* @return
*/
@Select("select sd.name, sd.copies, d.image, d.description " +
"from setmeal_dish sd left join dish d on sd.dish_id = d.id " +
"where sd.setmeal_id = #{setmealId}")
List<DishItemVO> getDishItemBySetmealId(Long setmealId);
/**
*
*
* @param setmealPageQueryDTO
* @return
*/
Page<Setmeal> pageQuery(SetmealPageQueryDTO setmealPageQueryDTO);
/**
*
*
* @param setmeal
*/
@AutoFill(OperationType.UPDATE)
void updateSetmeal(Setmeal setmeal);
/**
* id
*
* @param id ID
*/
@Delete("delete from setmeal_dish where setmeal_id=#{id}")
void deleteSetmealDish(Long id);
/**
*
*
* @param setmealDishes
*/
void insertBatchSetmealDish(List<SetmealDish> setmealDishes);
/**
* id
*
* @param id ID
* @return
*/
@Select("select * from setmeal where id=#{id}")
Setmeal getBySetmealId(Long id);
/**
* id
*
* @param id ID
* @return
*/
@Select("select * from setmeal_dish where setmeal_id=#{id}")
List<SetmealDish> getSetmealDishById(Long id);
/**
* id
*
* @param ids ID
*/
void batchDeleteSetmeal(ArrayList<Long> ids);
/**
*
*
* @param setmeal
*/
@AutoFill(OperationType.INSERT)
void insertSetmeal(Setmeal setmeal);
}

@ -0,0 +1,68 @@
package com.sky.service;
import com.sky.dto.CategoryDTO;
import com.sky.dto.CategoryPageQueryDTO;
import com.sky.entity.Category;
import com.sky.result.PageResult;
import java.util.List;
public interface CategoryService {
/**
*
*
*
*
* @param categoryPageQueryDTO
* @return
*/
PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO);
/**
*
*
*
*
* @param type 1 2
* @return
*/
List<Category> query(Integer type);
/**
*
*
* ID
*
* @param id ID
*/
void delete(Long id);
/**
*
*
* DTO
*
* @param categoryDTO DTO
*/
void updateCategory(CategoryDTO categoryDTO);
/**
*
*
*
*
* @param status 1 0
* @param id ID
*/
void startOrStop(Integer status, Long id);
/**
*
*
* DTO
*
* @param categoryDTO DTO
*/
void save(CategoryDTO categoryDTO);
}

@ -0,0 +1,25 @@
// 定义一个名为com.sky.service的包用于存放服务相关的类和接口
package com.sky.service;
// 导入Spring框架中的@Service注解用于声明一个服务组件
import org.springframework.stereotype.Service;
// 导入MultipartFile接口用于处理上传的文件
import org.springframework.web.multipart.MultipartFile;
// 导入Java的IOException类用于处理可能发生的IO异常
import java.io.IOException;
// 使用@Service注解标记这个接口表明它是一个Spring管理的服务组件
@Service
// 声明一个名为CommonService的接口
public interface CommonService {
/**
*
*
* @param file MultipartFile
* @return
* @throws IOException IOIOException
*/
String upload(MultipartFile file) throws IOException;
}

@ -0,0 +1,159 @@
package com.sky.service;
import com.sky.dto.*;
import com.sky.result.PageResult;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import java.util.ArrayList;
public interface OrderService {
/**
*
*
*
*
* @param id ID
*/
void complete(Long id);
/**
*
*
*
*
* @param id ID
*/
void delivery(Long id);
/**
*
*
*
*
* @param ordersCancelDTO ID
* @throws Exception
*/
void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception;
/**
*
*
*
*
* @param ordersRejectionDTO ID
* @throws Exception
*/
void rejection(OrdersRejectionDTO ordersRejectionDTO) throws Exception;
/**
*
*
*
*
* @param ordersConfirmDTO ID
*/
void confirm(OrdersConfirmDTO ordersConfirmDTO);
/**
*
*
*
*
* @return
*/
OrderStatisticsVO statistics();
/**
*
*
*
*
* @param ordersPageQueryDTO
* @return
*/
PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO);
/**
*
*
*
*
* @param id ID
* @throws Exception
*/
void userCancelById(Long id) throws Exception;
/**
*
*
*
*
* @param id ID
* @return
*/
OrderVO details(Long id);
/**
*
*
*
*
* @param ordersDTO
* @return ID
*/
OrderSubmitVO submit(OrdersDTO ordersDTO);
/**
*
*
*
*
* @param ordersPaymentDTO DTO
* @return
* @throws Exception
*/
OrderPaymentVO payment(OrdersPaymentDTO ordersPaymentDTO) throws Exception;
/**
*
*
*
*
* @param outTradeNo
*/
void paySuccess(String outTradeNo);
/**
*
*
*
*
* @param id ID
*/
void reminder(Long id);
/**
*
*
*
*
* @param page
* @param pageSize
* @param status
* @return
*/
PageResult pageQuery4User(int page, int pageSize, Integer status);
/**
*
*
*
*
* @param id ID
*/
void repetition(Long id);
}

@ -0,0 +1,66 @@
// 定义一个名为com.sky.service的包用于存放服务相关的类和接口
package com.sky.service;
// 导入com.sky.result.Result类用于封装方法的返回结果
import com.sky.result.Result;
// 导入com.sky.vo包下的各种VOValue Object这些类用于封装数据传输对象
import com.sky.vo.*;
// 导入org.apache.http.HttpResponse类用于处理HTTP响应
import org.apache.http.HttpResponse;
// 导入org.apache.poi.openxml4j.exceptions.InvalidFormatException类用于处理Excel文件格式无效的异常
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import javax.servlet.http.HttpServletResponse; // 导入HttpServletResponse类用于处理HTTP响应
import java.io.FileNotFoundException; // 导入FileNotFoundException类用于处理文件未找到的异常
import java.io.IOException; // 导入IOException类用于处理IO异常
import java.time.LocalDate; // 导入LocalDate类用于表示没有时间的日期
import java.time.LocalDateTime; // 导入LocalDateTime类用于表示日期和时间
// 声明一个名为ReportService的接口
public interface ReportService {
/**
*
*
* @param begin LocalDate
* @param end LocalDate
* @return ResultTurnoverReportVOVO
*/
Result<TurnoverReportVO> getTurnoverStatistics(LocalDate begin, LocalDate end);
/**
*
*
* @param begin LocalDate
* @param end LocalDate
* @return UserReportVO
*/
UserReportVO userStatistics(LocalDate begin, LocalDate end);
/**
*
*
* @param begin LocalDate
* @param end LocalDate
* @return OrderReportVO
*/
OrderReportVO orderStatistics(LocalDate begin, LocalDate end);
/**
*
*
* @param begin LocalDate
* @param end LocalDate
* @return SalesTop10ReportVO
*/
SalesTop10ReportVO salesTop10Report(LocalDate begin, LocalDate end);
/**
* excel
*
* @param httpResponse HttpServletResponseExcelHTTP便
* @throws IOException IOIOException
* @throws InvalidFormatException ExcelInvalidFormatException
*/
void export(HttpServletResponse httpResponse) throws IOException, InvalidFormatException;
}

@ -0,0 +1,19 @@
package com.sky.service;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
public interface UserService {
/**
*
*
*
* openid
*
* @param userLoginDTO
* @return
*/
User wxLogin(UserLoginDTO userLoginDTO);
}

@ -0,0 +1,48 @@
// 定义一个名为com.sky.service的包用于存放服务相关的类和接口
package com.sky.service;
// 导入com.sky.vo包下的BusinessDataVO类用于封装业务数据
import com.sky.vo.BusinessDataVO;
// 导入com.sky.vo包下的DishOverViewVO类用于封装菜品总览数据
import com.sky.vo.DishOverViewVO;
// 导入com.sky.vo包下的OrderOverViewVO类用于封装订单总览数据
import com.sky.vo.OrderOverViewVO;
// 导入com.sky.vo包下的SetmealOverViewVO类用于封装套餐总览数据
import com.sky.vo.SetmealOverViewVO;
// 导入java.time.LocalDateTime类用于表示日期和时间
import java.time.LocalDateTime;
// 声明一个名为WorkspaceService的接口
public interface WorkspaceService {
/**
*
*
* @param begin LocalDateTime
* @param end LocalDateTime
* @return BusinessDataVO
*/
BusinessDataVO getBusinessData(LocalDateTime begin, LocalDateTime end);
/**
*
*
* @return OrderOverViewVO
*/
OrderOverViewVO getOrderOverView();
/**
*
*
* @return DishOverViewVO
*/
DishOverViewVO getDishOverView();
/**
*
*
* @return SetmealOverViewVO
*/
SetmealOverViewVO getSetmealOverView();
}

@ -0,0 +1,94 @@
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 lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
@Service // 该注解表示该类是一个服务层的 Bean
@Slf4j // 提供日志功能
public class AddressBookServiceImpl implements AddressBookService {
@Autowired // 自动注入 AddressBookMapper
private AddressBookMapper addressBookMapper;
/**
*
* AddressBook
*
* @param addressBook
* @return
*/
public List<AddressBook> list(AddressBook addressBook) {
return addressBookMapper.list(addressBook); // 调用 mapper 查询数据库
}
/**
*
* ID
*
* @param addressBook
*/
public void save(AddressBook addressBook) {
addressBook.setUserId(BaseContext.getCurrentId()); // 设置当前用户的 ID
addressBook.setIsDefault(0); // 设置地址为非默认地址
addressBookMapper.insert(addressBook); // 调用 mapper 插入新地址
}
/**
* id
* ID
*
* @param id ID
* @return AddressBook
*/
public AddressBook getById(Long id) {
return addressBookMapper.getById(id); // 调用 mapper 根据 ID 查询地址
}
/**
* id
*
*
* @param addressBook
*/
public void update(AddressBook addressBook) {
addressBookMapper.update(addressBook); // 调用 mapper 更新地址
}
/**
*
* 1. `is_default`
* 2. `is_default`
* 使
*
* @param addressBook
*/
@Transactional // 声明事务,确保操作的原子性
public void setDefault(AddressBook addressBook) {
// 1. 将当前用户的所有地址修改为非默认地址
addressBook.setIsDefault(0);
addressBook.setUserId(BaseContext.getCurrentId());
addressBookMapper.updateIsDefaultByUserId(addressBook); // 更新所有地址为非默认
// 2. 将当前地址改为默认地址
addressBook.setIsDefault(1);
addressBookMapper.update(addressBook); // 更新当前地址为默认
}
/**
* id
* ID
*
* @param id ID
*/
public void deleteById(Long id) {
addressBookMapper.deleteById(id); // 调用 mapper 删除地址
}
}

@ -0,0 +1,115 @@
// 定义包名表示该类属于com.sky.service.impl包
package com.sky.service.impl;
// 导入所需的类和接口
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.StatusConstant;
import com.sky.dto.CategoryDTO;
import com.sky.dto.CategoryPageQueryDTO;
import com.sky.entity.Category;
import com.sky.mapper.CategoryMapper;
import com.sky.result.PageResult;
import com.sky.service.CategoryService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
// 使用@Service注解标记这是一个Spring服务组件
@Service
public class CategoryServiceImpl implements CategoryService {
// 自动注入CategoryMapper
@Autowired
CategoryMapper categoryMapper;
/**
*
*
* @param categoryPageQueryDTO
* @return
*/
public PageResult pageQuery(CategoryPageQueryDTO categoryPageQueryDTO) {
PageResult pageResult = new PageResult();
// 使用PageHelper开始分页查询
PageHelper.startPage(categoryPageQueryDTO.getPage(), categoryPageQueryDTO.getPageSize());
// 调用mapper进行分页查询
Page<Category> pageQuery = categoryMapper.pageQuery(categoryPageQueryDTO);
// 设置查询结果和总记录数
pageResult.setRecords(pageQuery.getResult());
pageResult.setTotal(pageQuery.getTotal());
return pageResult;
}
/**
*
*
* @param type
* @return
*/
public List<Category> query(Integer type) {
ArrayList<Category> result;
CategoryDTO categoryDTO = new CategoryDTO();
categoryDTO.setType(type);
// 调用mapper查询分类
result = (ArrayList<Category>) categoryMapper.query(categoryDTO);
return result;
}
/**
*
*
* @param id ID
*/
public void delete(Long id) {
// 调用mapper删除分类
categoryMapper.delete(id);
}
/**
*
*
* @param categoryDTO DTO
*/
public void updateCategory(CategoryDTO categoryDTO) {
Category category = new Category();
// 使用BeanUtils复制属性
BeanUtils.copyProperties(categoryDTO, category);
// 调用mapper更新分类
categoryMapper.updateCategory(category);
}
/**
*
*
* @param status
* @param id ID
*/
public void startOrStop(Integer status, Long id) {
Category category = Category.builder()
.status(status)
.id(id)
.build();
// 调用mapper更新分类状态
categoryMapper.updateCategory(category);
}
/**
*
*
* @param categoryDTO DTO
*/
public void save(CategoryDTO categoryDTO) {
Category category = new Category();
// 使用BeanUtils复制属性
BeanUtils.copyProperties(categoryDTO, category);
// 设置分类状态为禁用
category.setStatus(StatusConstant.DISABLE);
// 调用mapper保存分类
categoryMapper.save(category);
}
}

@ -0,0 +1,156 @@
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 // 该类标记为服务层的 Bean
public class EmployeeServiceImpl implements EmployeeService {
@Autowired // 自动注入 EmployeeMapper
private EmployeeMapper employeeMapper;
/**
*
*
*
*
* @param employeeLoginDTO
* @return
* @throws AccountNotFoundException
* @throws PasswordErrorException
* @throws AccountLockedException
*/
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);
}
// 密码比对
password = DigestUtils.md5DigestAsHex(password.getBytes()); // 对前端传过来的密码进行 md5 加密
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;
}
/**
*
*
* `employeeDTO`
*
* @param employeeDTO
*/
public void save(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO, employee); // 将 DTO 中的数据复制到 Employee 实体中
employee.setStatus(StatusConstant.ENABLE); // 设置员工的状态为启用
employee.setPassword(DigestUtils.md5DigestAsHex(PasswordConstant.DEFAULT_PASSWORD.getBytes())); // 设置默认密码
employeeMapper.save(employee); // 调用 Mapper 插入员工数据
}
/**
*
*
* 使 PageHelper
*
* @param employeePageQueryDTO
* @return
*/
public PageResult pageQuery(EmployeePageQueryDTO employeePageQueryDTO) {
// 使用 PageHelper 开启分页
PageHelper.startPage(employeePageQueryDTO.getPage(), employeePageQueryDTO.getPageSize());
// 执行分页查询
Page<Employee> pageQuery = employeeMapper.pageQuery(employeePageQueryDTO);
// 构建分页结果
PageResult pageResult = new PageResult();
pageResult.setTotal(pageQuery.getTotal()); // 总记录数
pageResult.setRecords(pageQuery.getResult()); // 当前页的记录
return pageResult;
}
/**
*
*
* ID
*
* @param status
* @param id ID
*/
public void startOrStop(Integer status, Long id) {
Employee employee = Employee.builder()
.status(status) // 设置新的账号状态
.id(id) // 设置员工 ID
.build();
employeeMapper.update(employee); // 调用 Mapper 更新员工状态
}
/**
* ID
*
* 使 `*****`
*
* @param id ID
* @return
*/
public Employee getById(Long id) {
Employee employee = employeeMapper.getById(id); // 根据 ID 查询员工信息
employee.setPassword("*****"); // 隐藏密码
return employee;
}
/**
*
*
*
*
* @param employeeDTO
*/
public void update(EmployeeDTO employeeDTO) {
Employee employee = new Employee();
BeanUtils.copyProperties(employeeDTO, employee); // 将 DTO 转换为实体对象
employeeMapper.update(employee); // 调用 Mapper 更新员工数据
}
}

@ -0,0 +1,260 @@
// 定义包名表示该类属于com.sky.service.impl包
package com.sky.service.impl;
// 导入所需的类和接口
import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.sky.constant.MessageConstant;
import com.sky.context.BaseContext;
import com.sky.dto.*;
import com.sky.entity.*;
import com.sky.exception.AddressBookBusinessException;
import com.sky.exception.OrderBusinessException;
import com.sky.exception.ShoppingCartBusinessException;
import com.sky.mapper.*;
import com.sky.result.PageResult;
import com.sky.service.OrderService;
import com.sky.utils.WeChatPayUtil;
import com.sky.vo.OrderPaymentVO;
import com.sky.vo.OrderStatisticsVO;
import com.sky.vo.OrderSubmitVO;
import com.sky.vo.OrderVO;
import com.sky.webSocket.WebSocketServer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
// 使用@Service注解标记这是一个Spring服务组件
@Service
public class OrderServiceImpl implements OrderService {
// 自动注入OrderMapper
@Autowired
private OrderMapper orderMapper;
// 自动注入OrderDetailMapper
@Autowired
private OrderDetailMapper orderDetailMapper;
// 自动注入AddressBookMapper
@Autowired
private AddressBookMapper addressBookMapper;
// 自动注入ShoppingCartMapper
@Autowired
private ShoppingCartMapper shoppingCartMapper;
// 自动注入UserMapper
@Autowired
private UserMapper userMapper;
// 自动注入WeChatPayUtil
@Autowired
private WeChatPayUtil weChatPayUtil;
// 自动注入WebSocketServer
@Autowired
private WebSocketServer webSocketServer;
/**
*
*
* @param id ID
*/
public void complete(Long id) {
// 根据id查询订单
Orders ordersDB = orderMapper.getById(id);
// 校验订单是否存在,并且状态为派送中
if (ordersDB == null || !ordersDB.getStatus().equals(Orders.DELIVERY_IN_PROGRESS)) {
throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
}
Orders orders = new Orders();
orders.setId(ordersDB.getId());
// 更新订单状态,状态转为完成
orders.setStatus(Orders.COMPLETED);
orders.setDeliveryTime(LocalDateTime.now());
orderMapper.update(orders);
}
/**
*
*
* @param id ID
*/
public void delivery(Long id) {
// 根据id查询订单
Orders ordersDB = orderMapper.getById(id);
// 校验订单是否存在,并且状态为已接单
if (ordersDB == null || !ordersDB.getStatus().equals(Orders.CONFIRMED)) {
throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
}
Orders orders = new Orders();
orders.setId(ordersDB.getId());
// 更新订单状态,状态转为派送中
orders.setStatus(Orders.DELIVERY_IN_PROGRESS);
orderMapper.update(orders);
}
/**
*
*
* @param ordersCancelDTO DTO
*/
public void cancel(OrdersCancelDTO ordersCancelDTO) throws Exception {
// 根据id查询订单
Orders ordersDB = orderMapper.getById(ordersCancelDTO.getId());
// 支付状态
Integer payStatus = ordersDB.getPayStatus();
if (payStatus == 1) {
// 用户已支付,需要退款
// 调用微信支付退款接口
// String refund = weChatPayUtil.refund(
// ordersDB.getNumber(),
// ordersDB.getNumber(),
// new BigDecimal(0.01),
// new BigDecimal(0.01));
}
// 管理端取消订单需要退款根据订单id更新订单状态、取消原因、取消时间
Orders orders = new Orders();
orders.setId(ordersCancelDTO.getId());
orders.setStatus(Orders.CANCELLED);
orders.setCancelReason(ordersCancelDTO.getCancelReason());
orders.setCancelTime(LocalDateTime.now());
orderMapper.update(orders);
}
/**
*
*
* @param ordersRejectionDTO DTO
*/
public void rejection(OrdersRejectionDTO ordersRejectionDTO) throws Exception {
// 根据id查询订单
Orders ordersDB = orderMapper.getById(ordersRejectionDTO.getId());
// 订单只有存在且状态为待接单才可以拒单
if (ordersDB == null || !ordersDB.getStatus().equals(Orders.TO_BE_CONFIRMED)) {
throw new OrderBusinessException(MessageConstant.ORDER_STATUS_ERROR);
}
// 支付状态
Integer payStatus = ordersDB.getPayStatus();
if (Objects.equals(payStatus, Orders.PAID)) {
// 用户已支付,需要退款
// 调用微信支付退款接口
// String refund = weChatPayUtil.refund(
// ordersDB.getNumber(),
// ordersDB.getNumber(),
// new BigDecimal(0.01),
// new BigDecimal(0.01));
}
// 拒单需要退款根据订单id更新订单状态、拒单原因、取消时间
Orders orders = new Orders();
orders.setId(ordersDB.getId());
orders.setStatus(Orders.CANCELLED);
orders.setRejectionReason(ordersRejectionDTO.getRejectionReason());
orders.setCancelTime(LocalDateTime.now());
orderMapper.update(orders);
}
/**
*
*
* @param ordersConfirmDTO DTO
*/
public void confirm(OrdersConfirmDTO ordersConfirmDTO) {
Orders orders = Orders.builder()
.id(ordersConfirmDTO.getId())
.status(Orders.CONFIRMED)
.build();
orderMapper.update(orders);
}
/**
*
*
* @return
*/
public OrderStatisticsVO statistics() {
// 根据状态,分别查询出待接单、待派送、派送中的订单数量
Integer toBeConfirmed = orderMapper.countStatus(Orders.TO_BE_CONFIRMED);
Integer confirmed = orderMapper.countStatus(Orders.CONFIRMED);
Integer deliveryInProgress = orderMapper.countStatus(Orders.DELIVERY_IN_PROGRESS);
// 将查询出的数据封装到orderStatisticsVO中响应
OrderStatisticsVO orderStatisticsVO = new OrderStatisticsVO();
orderStatisticsVO.setToBeConfirmed(toBeConfirmed);
orderStatisticsVO.setConfirmed(confirmed);
orderStatisticsVO.setDeliveryInProgress(deliveryInProgress);
return orderStatisticsVO;
}
/**
*
*
* @param ordersPageQueryDTO
* @return
*/
public PageResult conditionSearch(OrdersPageQueryDTO ordersPageQueryDTO) {
PageHelper.startPage(ordersPageQueryDTO.getPage(), ordersPageQueryDTO.getPageSize());
Page<Orders> page = orderMapper.pageQuery(ordersPageQueryDTO);
// 部分订单状态需要额外返回订单菜品信息将Orders转化为OrderVO
List<OrderVO> orderVOList = getOrderVOList(page);
return new PageResult(page.getTotal(), orderVOList);
}
private List<OrderVO> getOrderVOList(Page<Orders> page) {
// 需要返回订单菜品信息自定义OrderVO响应结果
List<OrderVO> orderVOList = new ArrayList<>();
List<Orders> ordersList = page.getResult();
if (!CollectionUtils.isEmpty(ordersList)) {
for (Orders orders : ordersList) {
// 将共同字段复制到OrderVO
OrderVO orderVO = new OrderVO();
BeanUtils.copyProperties(orders, orderVO);
String orderDishes = getOrderDishesStr(orders);
// 将订单菜品信息封装到orderVO中并添加到orderVOList
orderVO.setOrderDishes(orderDishes);
orderVOList.add(orderVO);
}
}
return orderVOList;
}
/**
* id
*
* @param orders
* @return
*/
private String getOrderDishesStr(Orders orders) {
// 查询订单菜品详情信息(订单中的菜品和数量)
List<OrderDetail> orderDetailList = orderDetailMapper.getByOrderId(orders.getId());
// 将每一条订单菜品信息拼接为字符串(格式:宫保鸡丁*3
List<String> orderDishList = orderDetailList.stream().map(x -> {
String orderDish = x.getName() + "*" + x.getNumber() + ";";
return orderDish;
}).collect

@ -0,0 +1,128 @@
package com.sky.service.impl;
import com.sky.context.BaseContext;
import com.sky.dto.ShoppingCartDTO;
import com.sky.entity.Dish;
import com.sky.entity.Setmeal;
import com.sky.entity.ShoppingCart;
import com.sky.mapper.DishMapper;
import com.sky.mapper.SetmealMapper;
import com.sky.mapper.ShoppingCartMapper;
import com.sky.service.ShoppingCartService;
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 // 标记为服务层的 Bean
public class ShoppingCartServiceImpl implements ShoppingCartService {
@Autowired // 自动注入购物车相关的 Mapper
ShoppingCartMapper shoppingCartMapper;
@Autowired
DishMapper dishMapper;
@Autowired
SetmealMapper setmealMapper;
/**
*
*
* DTO
*
* @param shoppingCartDTO
*/
@Override
public void add(ShoppingCartDTO shoppingCartDTO) {
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO, shoppingCart); // 将 DTO 中的属性复制到 ShoppingCart 实体中
shoppingCart.setUserId(BaseContext.getCurrentId()); // 设置当前用户 ID
// 如果购物车中已经有该商品,则只需要将该商品的数量加 1
List<ShoppingCart> shoppingCarts = shoppingCartMapper.list(shoppingCart);
if (shoppingCarts.size() > 0) {
Integer number = shoppingCarts.get(0).getNumber();
shoppingCarts.get(0).setNumber(number + 1); // 增加商品数量
shoppingCartMapper.update(shoppingCarts.get(0)); // 更新购物车
} else {
// 否则,插入一个新的购物车项
Long dishId = shoppingCartDTO.getDishId();
Long setmealId = shoppingCartDTO.getSetmealId();
// 如果是菜品
if (dishId != null) {
Dish dish = dishMapper.getById(dishId); // 根据菜品 ID 查询菜品信息
shoppingCart.setName(dish.getName()); // 设置商品名称
shoppingCart.setAmount(dish.getPrice()); // 设置商品价格
shoppingCart.setImage(dish.getImage()); // 设置商品图片
} else {
// 如果是套餐
Setmeal bySetmealId = setmealMapper.getBySetmealId(setmealId); // 根据套餐 ID 查询套餐信息
shoppingCart.setAmount(bySetmealId.getPrice()); // 设置套餐价格
shoppingCart.setName(bySetmealId.getName()); // 设置套餐名称
shoppingCart.setImage(shoppingCart.getImage()); // 设置套餐图片
}
shoppingCart.setNumber(1); // 设置商品数量为 1
shoppingCart.setCreateTime(LocalDateTime.now()); // 设置创建时间
shoppingCartMapper.insert(shoppingCart); // 插入新商品到购物车
}
}
/**
*
*
* ID
*
* @return
*/
@Override
public List<ShoppingCart> list() {
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.setUserId(BaseContext.getCurrentId()); // 设置当前用户 ID
return shoppingCartMapper.list(shoppingCart); // 返回购物车数据
}
/**
*
*
* DTO 1 1
*
* @param shoppingCartDTO
*/
@Override
public void delete(ShoppingCartDTO shoppingCartDTO) {
ShoppingCart shoppingCart = new ShoppingCart();
BeanUtils.copyProperties(shoppingCartDTO, shoppingCart); // 将 DTO 中的属性复制到 ShoppingCart 实体中
shoppingCart.setUserId(BaseContext.getCurrentId()); // 设置当前用户 ID
// 查询购物车中的商品
List<ShoppingCart> list = shoppingCartMapper.list(shoppingCart);
Integer number = list.get(0).getNumber(); // 获取商品数量
// 如果数量大于 1则将数量减 1
if (number > 1) {
list.get(0).setNumber(number - 1);
shoppingCartMapper.update(list.get(0)); // 更新购物车
} else {
// 如果数量为 1则从购物车中删除该商品
shoppingCartMapper.delete(list.get(0)); // 删除商品
}
}
/**
*
*
*
*/
@Override
public void clean() {
ShoppingCart shoppingCart = new ShoppingCart();
shoppingCart.setUserId(BaseContext.getCurrentId()); // 设置当前用户 ID
shoppingCartMapper.delete(shoppingCart); // 删除该用户的所有购物车项
}
}

@ -0,0 +1,86 @@
// 定义包名表示该类属于com.sky.service.impl包
package com.sky.service.impl;
// 导入所需的类和接口
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.constant.MessageConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.exception.LoginFailedException;
import com.sky.mapper.UserMapper;
import com.sky.properties.WeChatProperties;
import com.sky.service.UserService;
import com.sky.utils.HttpClientUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
// 使用@Service注解标记这是一个Spring服务组件
@Service
public class UserServiceImpl implements UserService {
// 自动注入UserMapper
@Autowired
UserMapper userMapper;
// 自动注入WeChatProperties
@Autowired
WeChatProperties weChatProperties;
// 微信登录接口的URL
private static final String WX_LOGIN = "https://api.weixin.qq.com/sns/jscode2session";
/**
*
*
* @param userLoginDTO DTO
* @return
*/
public User wxLogin(UserLoginDTO userLoginDTO) {
// 通过code获取openid
String openid = getOpenid(userLoginDTO.getCode());
// 判断openid是否存在
if (openid == null || openid.equals("")) {
throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
}
// 当前用户为新用户,完成自动注册
User user = userMapper.getByOpenId(openid);
if (user == null) {
// 创建新用户对象
user = User.builder()
.openid(openid)
.createTime(LocalDateTime.now()).build();
// 插入新用户到数据库
userMapper.insertUser(user);
}
return user;
}
/**
* codeopenid
*
* @param code code
* @return openid
*/
private String getOpenid(String code) {
// 参数映射
Map<String, String> paramMap = new HashMap<>();
paramMap.put("appid", weChatProperties.getAppid());
paramMap.put("secret", weChatProperties.getSecret());
paramMap.put("js_code", code);
paramMap.put("grant_type", "authorization_code");
// 发起HTTP GET请求
String result = HttpClientUtil.doGet(WX_LOGIN, paramMap);
// 获取请求结果
JSONObject jsonObject = JSON.parseObject(result);
// 从结果中获取openid
String openid = jsonObject.getString("openid");
return openid;
}
}
Loading…
Cancel
Save