Compare commits

...

27 Commits
master ... dev

Author SHA1 Message Date
bunny 3a79c3ded3 feat(打包): 项目打包 2024-04-12 12:36:39 +08:00
bunny b3a2d42e24 feat(新增): 完成 2024-04-11 12:32:11 +08:00
bunny abdd193d2d feat(新增): 生成订单,获取订单详情 2024-04-11 10:50:12 +08:00
bunny e5e132a9cb feat(新增): 确认订单 2024-04-11 10:05:12 +08:00
bunny f70211ce62 feat(新增): order模块初始化 2024-04-10 23:14:10 +08:00
bunny 6ace927de5 feat(新增): 更新选中状态,更新全部选中,批量选择购物车 2024-04-10 22:59:20 +08:00
bunny 493d91a515 feat(新增): 获取优惠券信息 2024-04-10 19:15:00 +08:00
bunny d92705d68b feat(新增): 查询购物车列表 2024-04-10 13:26:28 +08:00
bunny 5b6a1a910c feat(新增): 删除购物车内容,清空购物车,批量删除购物车 2024-04-10 13:06:41 +08:00
bunny 6fd45be415 feat(新增): 添加购物车 2024-04-10 12:53:25 +08:00
bunny 4a5477af0f feat(新增): 购物车模块初始化 2024-04-10 10:11:37 +08:00
bunny b7b252294f feat(新增): 购物车模块初始化 2024-04-10 10:08:40 +08:00
bunny f9fc1053df feat(新增): 根据skuId获取促销与优惠券信息 2024-04-10 10:01:20 +08:00
bunny ee1c005f44 feat(新增): 线程练习 2024-04-09 21:18:52 +08:00
bunny ef0035dd5f feat(新增): 修复主页接受数据错误,修复购物车数据不显示 2024-04-09 14:30:54 +08:00
bunny 178f2d04fb feat(新增): 搜索商品 2024-04-09 10:06:56 +08:00
bunny 619f774f52 feat(新增): 首页数据显示 2024-04-08 23:05:20 +08:00
bunny b53976500a feat(新增): 小程序登录接口 2024-04-06 21:50:03 +08:00
bunny 2fa9b39d14 feat(新增): 秒杀场次管理,SeckillSku管理 2024-04-06 18:00:50 +08:00
bunny a80af36879 feat(新增): SecKill管理 2024-04-06 17:32:35 +08:00
bunny 757ed89c1a feat(新增): SecKill管理 2024-04-06 16:35:50 +08:00
bunny 92c76e578c feat(新增): 用户端环境搭建 2024-04-06 00:01:14 +08:00
bunny cd90d93f3e feat(新增): 优惠卷相关接口 2024-04-05 22:23:48 +08:00
bunny afc144c350 feat(修复): 修改部分bug 2024-04-05 15:57:16 +08:00
bunny 5d1ac9432b feat(修复): 报错,MP枚举类无法识别 2024-04-05 03:17:04 +08:00
bunny a6db5a7600 feat(新增): 新增活动规则,根据关键字获取sku列表,活动使用 2024-04-05 02:22:03 +08:00
bunny eb22d344b3 feat(新增): 获取分页列表、获取活动规则 2024-04-05 01:06:56 +08:00
202 changed files with 6649 additions and 281 deletions

View File

@ -40,6 +40,7 @@
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.resource.type" value="Deployment" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
@ -50,6 +51,36 @@
<imported>true</imported>
<jdbc-driver>jdbc.RedisDriver</jdbc-driver>
<jdbc-url>jdbc:redis://47.120.65.66:6379/0</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.resource.type" value="Deployment" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
<data-source source="LOCAL" name="shequ-activity@106.15.251.123" uuid="5ca43232-baa4-471e-9ed7-f45169d4cda5">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/service/service-activity/src/main/resources/application.yml</remarks>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://106.15.251.123:3305/shequ-activity?serverTimezone=GMT</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />
<property name="com.intellij.clouds.kubernetes.db.resource.type" value="Deployment" />
<property name="com.intellij.clouds.kubernetes.db.container.port" />
</jdbc-additional-properties>
<working-dir>$ProjectFileDir$</working-dir>
</data-source>
<data-source source="LOCAL" name="shequ-user@106.15.251.123" uuid="8b2549c2-e3f6-45f4-b269-7f3611e86c69">
<driver-ref>mysql.8</driver-ref>
<synchronize>true</synchronize>
<imported>true</imported>
<remarks>$PROJECT_DIR$/service/service-user/src/main/resources/application.yml</remarks>
<jdbc-driver>com.mysql.cj.jdbc.Driver</jdbc-driver>
<jdbc-url>jdbc:mysql://106.15.251.123:3305/shequ-user?serverTimezone=GMT</jdbc-url>
<jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />

View File

@ -14,15 +14,25 @@
<file url="file://$PROJECT_DIR$/model/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/model/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/model/src/main/resources-filtered" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/service-activity-client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/service-cart-client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/service-product-client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/service-region-client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/service-search-client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/service-user-client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-client/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service-gateway/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-acl/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-activity/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-cart/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-home/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-order/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-payment/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-product/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-search/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-sys/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/service-user/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/service/src/main/resources-filtered" charset="UTF-8" />

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<writeAnnotations>
<writeAnnotation name="com.baomidou.mybatisplus.annotation.EnumValue" />
</writeAnnotations>
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
@ -8,8 +13,13 @@
<option value="$PROJECT_DIR$/service-gateway/pom.xml" />
</list>
</option>
<option name="ignoredFiles">
<set>
<option value="$PROJECT_DIR$/service/service-payment/pom.xml" />
</set>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<component name="ProjectRootManager" version="2" languageLevel="JDK_18" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PrettierConfiguration">
<option name="myRunOnSave" value="true" />
</component>
</project>

5
ReadMe.md Normal file
View File

@ -0,0 +1,5 @@
### 小程序申请
申请地址https://mp.weixin.qq.com/wxamp/sandbox?doc=1
地址https://developers.weixin.qq.com/miniprogram/dev/devtools/download.html

View File

@ -40,5 +40,11 @@
<version>1.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,52 @@
package com.atguigu.common.utils;
import io.jsonwebtoken.*;
import org.springframework.util.StringUtils;
import java.util.Date;
public class JwtHelper {
private static final long tokenExpiration = 365L * 24 * 60 * 60 * 1000;
private static final String tokenSignKey = "ssyx";
public static String createToken(Long userId, String userName) {
return Jwts.builder()
.setSubject("ssyx-USER")
.setExpiration(new Date(System.currentTimeMillis() + tokenExpiration))
.claim("userId", userId)
.claim("userName", userName)
.signWith(SignatureAlgorithm.HS256, tokenSignKey)
.compressWith(CompressionCodecs.GZIP)
.compact();
}
public static Long getUserId(String token) {
if (StringUtils.isEmpty(token)) return null;
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
Integer userId = (Integer) claims.get("userId");
return userId.longValue();
// return 1L;
}
public static String getUserName(String token) {
if (StringUtils.isEmpty(token)) return "";
Jws<Claims> claimsJws = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(token);
Claims claims = claimsJws.getBody();
return (String) claims.get("userName");
}
public static void removeToken(String token) {
// jwttoken无需删除客户端扔掉即可
}
public static void main(String[] args) {
String token = JwtHelper.createToken(7L, "admin");
System.out.println(token);
System.out.println(JwtHelper.getUserId(token));
System.out.println(JwtHelper.getUserName(token));
}
}

View File

@ -0,0 +1,53 @@
package com.atguigu.ssyx.mq.config;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
@Component
public class MQProducerAckConfig implements RabbitTemplate.ReturnCallback, RabbitTemplate.ConfirmCallback {
// 我们发送消息使用的是 private RabbitTemplate rabbitTemplate; 对象
// 如果不做设置的话 当前的rabbitTemplate 与当前的配置类没有任何关系
@Autowired
private RabbitTemplate rabbitTemplate;
// 设置 表示修饰一个非静态的void方法在服务器加载Servlet的时候运行并且只执行一次
@PostConstruct
public void init() {
rabbitTemplate.setReturnCallback(this);
rabbitTemplate.setConfirmCallback(this);
}
/**
* 表示消息是否正确发送到了交换机上
*
* @param correlationData 消息的载体
* @param ack 判断是否发送到交换机上
* @param cause 原因
*/
@Override
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
if (ack) {
System.out.println("消息发送成功!");
} else {
System.out.println("消息发送失败!" + cause);
}
}
/**
* 消息如果没有正确发送到队列中则会走这个方法如果消息被正常处理则这个方法不会走
*/
@Override
public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
System.out.println("消息主体: " + new String(message.getBody()));
System.out.println("应答码: " + replyCode);
System.out.println("描述:" + replyText);
System.out.println("消息使用的交换器 exchange : " + exchange);
System.out.println("消息使用的路由键 routing : " + routingKey);
}
}

View File

@ -19,7 +19,7 @@ public class CodeGet {
// 全局配置
GlobalConfig gc = new GlobalConfig();
// TODO 需要修改路径名称
gc.setOutputDir("G:\\File\\Java\\ssyx\\ssyx-parent\\service\\service-activity" + "/src/main/java");
gc.setOutputDir("F:\\File\\Java\\ssyx\\ssyx-parent\\service\\service-order" + "/src/main/java");
gc.setServiceName("%sService"); // 去掉Service接口的首字母I
gc.setAuthor("bunny");
@ -29,7 +29,7 @@ public class CodeGet {
// 3数据源配置
DataSourceConfig dsc = new DataSourceConfig();
// TODO 需要修改数据库
dsc.setUrl("jdbc:mysql://106.15.251.123:3305/shequ-activity?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true");
dsc.setUrl("jdbc:mysql://106.15.251.123:3305/shequ-order?serverTimezone=GMT%2B8&useSSL=false&characterEncoding=utf-8&allowPublicKeyRetrieval=true");
dsc.setDriverName("com.mysql.cj.jdbc.Driver");
dsc.setUsername("root");
dsc.setPassword("02120212");
@ -40,7 +40,7 @@ public class CodeGet {
PackageConfig pc = new PackageConfig();
pc.setParent("com.atguigu.ssyx");
// TODO 需要修改模块名
pc.setModuleName("activity");
pc.setModuleName("order");
pc.setController("controller");
pc.setService("service");
pc.setMapper("mapper");
@ -58,8 +58,8 @@ public class CodeGet {
@NotNull
private static StrategyConfig getStrategyConfig() {
StrategyConfig strategy = new StrategyConfig();
strategy.setInclude("activity_info", "activity_rule", "activity_sku", "coupon_info", "coupon_range", "coupon_use");
// TODO 要生成的表
strategy.setInclude("cart_info", "order_item", "order_info", "order_deliver");
strategy.setNaming(NamingStrategy.underline_to_camel);// 数据库表映射到实体的命名策略
strategy.setColumnNaming(NamingStrategy.underline_to_camel);// 数据库表字段映射到实体的命名策略
strategy.setEntityLombokModel(true); // lombok 模型 @Accessors(chain = true) setter链式操作

View File

@ -24,6 +24,7 @@ import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
@ -58,15 +59,14 @@ public class RedisConfiguration {
public CacheManager cacheManager(RedisConnectionFactory factory) {
log.info("RedisConfiguration===>解决cache(@Cacheable)把数据缓存到redis中的value是乱码问题");
StringRedisSerializer redisSerializer = new StringRedisSerializer();
// 配置序列化
RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig();
RedisCacheConfiguration redisCacheConfiguration = config
.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(redisSerializer))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer()));
config.serializeKeysWith(RedisSerializationContext.SerializationPair.fromSerializer(new StringRedisSerializer()))
.serializeValuesWith(RedisSerializationContext.SerializationPair.fromSerializer(jsonRedisSerializer()))
.entryTtl(Duration.ofDays(365));
RedisCacheManager cacheManager = RedisCacheManager.builder(factory)
.cacheDefaults(redisCacheConfiguration).build();
.cacheDefaults(config).build();
return cacheManager;
}

View File

@ -1,11 +1,25 @@
package com.atguigu.ssyx.common.config;
import com.atguigu.ssyx.common.interceptor.UserLoginInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
@Slf4j
@Configuration
public class WebMvcConfiguration implements WebMvcConfigurer {
@Autowired
private UserLoginInterceptor userLoginAuthInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
log.info("WebMvcConfiguration===>开始注册自定义拦截器...");
String[] userLoginExcludes = {"/api/user/weixin/wxLogin/*"};
registry.addInterceptor(userLoginAuthInterceptor)
.addPathPatterns("/api/**")
.excludePathPatterns(userLoginExcludes);
}
}

View File

@ -33,4 +33,6 @@ public class MessageConstant {
public static final String TOKEN_IS_EMPTY = "token为空";
public static final String DATA_IS_EMPTY = "数据为空";
public static final String STOCK_LESS = "库存不足";
public static final String SKU_NUM_CANNOT_BE_LESS = "商品数量不能再少了";
public static final String CART_IS_EMPTY = "购物车为空";
}

View File

@ -0,0 +1,45 @@
package com.atguigu.ssyx.common.constant;
/**
* Redis常量配置类
* set name admin
*/
public class RedisConst {
public static final String SKUKEY_PREFIX = "sku:";
public static final String SKUKEY_SUFFIX = ":info";
// 单位
public static final long SKUKEY_TIMEOUT = 24 * 60 * 60;
// 定义变量记录空对象的缓存过期时间 缓存穿透key的过期时间
public static final long SKUKEY_TEMPORARY_TIMEOUT = 10 * 60;
// 单位 尝试获取锁的最大等待时间
public static final long SKULOCK_EXPIRE_PX1 = 1;
// 单位 锁的持有时间
public static final long SKULOCK_EXPIRE_PX2 = 1;
public static final String SKULOCK_SUFFIX = ":lock";
public static final String USER_KEY_PREFIX = "user:";
public static final String USER_CART_KEY_SUFFIX = ":cart";
public static final long USER_CART_EXPIRE = 60 * 60 * 24 * 7;
public static final String SROCK_INFO = "stock:info:";
public static final String ORDER_REPEAT = "order:repeat:";
// 用户登录
public static final String USER_LOGIN_KEY_PREFIX = "user:login:";
public static final String ADMIN_LOGIN_KEY_PREFIX = "admin:login:";
// public static final String userinfoKey_suffix = ":info";
public static final int USERKEY_TIMEOUT = 365;
public static final String ORDER_SKU_MAP = "order:sku:";
// 秒杀商品前缀
public static final String SECKILL_TIME_MAP = "seckill:time:map";
public static final String SECKILL_SKU_MAP = "seckill:sku:map";
public static final String SECKILL_SKU_LIST = "seckill:sku:list:";
public static final String SECKILL_USER_MAP = "seckill:user:map:";
public static final String SECKILL_ORDERS_USERS = "seckill:orders:users";
public static final String SECKILL_STOCK_PREFIX = "seckill:stock:";
public static final String SECKILL_USER = "seckill:user:";
// 用户锁定时间 单位
public static final int SECKILL__TIMEOUT = 60 * 60;
}

View File

@ -1,27 +1,78 @@
package com.atguigu.ssyx.common.context;
import com.atguigu.ssyx.vo.acl.AdminLoginVo;
import com.atguigu.ssyx.vo.user.UserLoginVo;
public class BaseContext {
public static ThreadLocal<Long> threadLocal = new ThreadLocal<>();
private static final ThreadLocal<Long> userId = new ThreadLocal<>();
private static final ThreadLocal<Long> wareId = new ThreadLocal<>();
private static final ThreadLocal<Long> adminId = new ThreadLocal<>();
private static final ThreadLocal<AdminLoginVo> adminLoginVo = new ThreadLocal<>();
private static final ThreadLocal<UserLoginVo> userLoginVo = new ThreadLocal<>();
/**
* 获取当前用户id
*/
// 用户id相关
public static Long getUserId() {
return threadLocal.get();
return userId.get();
}
/**
* 设置用户id
*/
public static void setUserId(Long userId) {
threadLocal.set(userId);
public static void setUserId(Long _userId) {
userId.set(_userId);
}
/**
* 移出当前id
*/
public static void remove() {
threadLocal.remove();
public static void removeUserId() {
userId.remove();
}
// wareId相关
public static Long getWareId() {
return wareId.get();
}
public static void setWareId(Long _wareId) {
wareId.set(_wareId);
}
public static void removeWareId() {
wareId.remove();
}
// adminId 相关
public static Long getAdminId() {
return adminId.get();
}
public static void setAdminId(Long _adminId) {
adminId.set(_adminId);
}
public static void removeAdminId() {
adminId.remove();
}
// adminLoginVo相关
public static AdminLoginVo getAdminLoginVo() {
return adminLoginVo.get();
}
public static void setAdminLoginVo(AdminLoginVo _adminLoginVo) {
adminLoginVo.set(_adminLoginVo);
}
public static void removeAdminLoginVo() {
adminLoginVo.remove();
}
// userLoginVo相关
public static UserLoginVo getUserLoginVo() {
return userLoginVo.get();
}
public static void setUserLoginVo(UserLoginVo _userLoginVo) {
userLoginVo.set(_userLoginVo);
}
public static void removeUserLoginVo() {
userLoginVo.remove();
}
}

View File

@ -9,6 +9,7 @@ import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import java.io.FileNotFoundException;
import java.nio.file.AccessDeniedException;
import java.sql.SQLIntegrityConstraintViolationException;
@ -28,9 +29,9 @@ public class GlobalExceptionHandler {
// 运行时异常信息
@ExceptionHandler(RuntimeException.class)
@ResponseBody
public Result<Object> exceptionHandler(RuntimeException exception) {
public Result<Object> exceptionHandler(RuntimeException exception) throws FileNotFoundException {
log.error("GlobalExceptionHandler===>运行时异常信息:{}", exception.getMessage());
exception.printStackTrace();
return Result.error(null, 500, "出错了啦");
}
@ -40,7 +41,7 @@ public class GlobalExceptionHandler {
public Result<Object> error(Exception exception) {
log.error("GlobalExceptionHandler===>系统异常信息:{}", exception.getMessage());
return Result.error(null, 500, exception.getMessage());
return Result.error(null, 500, "系统异常");
}
// 特定异常处理

View File

@ -0,0 +1,47 @@
package com.atguigu.ssyx.common.interceptor;
import com.alibaba.fastjson.JSON;
import com.atguigu.common.utils.JwtHelper;
import com.atguigu.ssyx.common.constant.RedisConst;
import com.atguigu.ssyx.common.context.BaseContext;
import com.atguigu.ssyx.vo.user.UserLoginVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.lang.Nullable;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
@Configuration
public class UserLoginInterceptor implements HandlerInterceptor {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String token = request.getHeader("token");
log.info("用户Id登录.UserLoginInterceptor===>{}", token);
if (!StringUtils.isEmpty(token)) {
Long userId = JwtHelper.getUserId(token);
Object userIdObject = redisTemplate.opsForValue().get(RedisConst.USER_LOGIN_KEY_PREFIX + userId);
if (userIdObject != null) {
UserLoginVo userLoginVo = JSON.parseObject(JSON.toJSONString(userIdObject), UserLoginVo.class);
BaseContext.setUserId(userLoginVo.getUserId());
BaseContext.setWareId(userLoginVo.getWareId());
}
}
return true;
}
@Override
public void afterCompletion(@NotNull HttpServletRequest request, @NotNull HttpServletResponse response, @NotNull Object handler, @Nullable Exception ex) throws Exception {
BaseContext.removeUserId();
BaseContext.removeWareId();
}
}

View File

@ -0,0 +1,21 @@
package com.atguigu.ssyx.common.properties;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@ConditionalOnProperty(name = "wx.open.appId")
@ConfigurationProperties(prefix = "wx.open")
@Configuration
@Data
@Slf4j
public class WeChatProperties {
private String appId;
private String appSecret;
WeChatProperties() {
log.info("注册微信配置信息...");
}
}

View File

@ -5,15 +5,16 @@ import lombok.Getter;
@Getter
public enum ActivityType {
FULL_REDUCTION(1,"满减"),
FULL_DISCOUNT(2,"满量打折" );
FULL_REDUCTION(1, "满减"),
FULL_DISCOUNT(2, "满量打折");
@EnumValue
private Integer code ;
private String comment ;
private final Integer code;
@EnumValue
private final String comment;
ActivityType(Integer code, String comment ){
this.code=code;
this.comment=comment;
ActivityType(Integer code, String comment) {
this.code = code;
this.comment = comment;
}
}

View File

@ -8,6 +8,7 @@ import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.util.Date;
@ -18,41 +19,42 @@ import java.util.Date;
*
* @author qy
*/
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description = "ActivityInfo")
@TableName("activity_info")
public class ActivityInfo extends BaseEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "活动名称")
@TableField("activity_name")
private String activityName;
@ApiModelProperty(value = "活动类型(满减、折扣)")
@TableField("activity_type")
private ActivityType activityType;
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "活动描述")
@TableField("activity_desc")
private String activityDesc;
@ApiModelProperty(value = "活动名称")
@TableField("activity_name")
private String activityName;
@ApiModelProperty(value = "开始时间")
@TableField("start_time")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date startTime;
@ApiModelProperty(value = "活动类型(满减、折扣)")
@TableField("activity_type")
private ActivityType activityType;
@ApiModelProperty(value = "结束时间")
@TableField("end_time")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date endTime;
@ApiModelProperty(value = "活动描述")
@TableField("activity_desc")
private String activityDesc;
@ApiModelProperty(value = "创建时间")
@TableField("create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@ApiModelProperty(value = "开始时间")
@TableField("start_time")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date startTime;
@TableField(exist = false)
private String activityTypeString;
@ApiModelProperty(value = "结束时间")
@TableField("end_time")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date endTime;
@ApiModelProperty(value = "创建时间")
@TableField("create_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
@TableField(exist = false)
private String activityTypeString;
}

View File

@ -11,19 +11,17 @@ import lombok.Data;
@ApiModel(description = "AttrGroup")
@TableName("attr_group")
public class AttrGroup extends BaseEntity {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "组名")
@TableField("name")
private String name;
@ApiModelProperty(value = "组名")
@TableField("name")
private String name;
@ApiModelProperty(value = "排序")
@TableField("sort")
private Integer sort;
@ApiModelProperty(value = "备注")
@TableField("remark")
private String remark;
@ApiModelProperty(value = "排序")
@TableField("sort")
private Integer sort;
@ApiModelProperty(value = "备注")
@TableField("remark")
private String remark;
}

View File

@ -6,9 +6,11 @@ import com.baomidou.mybatisplus.annotation.TableName;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel(description = "SkuInfo")
@TableName("sku_info")

View File

@ -11,27 +11,25 @@ import lombok.Data;
@ApiModel(description = "RegionWare")
@TableName("region_ware")
public class RegionWare extends BaseEntity {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "开通区域")
@TableField("region_id")
private Long regionId;
@ApiModelProperty(value = "开通区域")
@TableField("region_id")
private Long regionId;
@ApiModelProperty(value = "区域名称")
@TableField("region_name")
private String regionName;
@ApiModelProperty(value = "区域名称")
@TableField("region_name")
private String regionName;
@ApiModelProperty(value = "仓库")
@TableField("ware_id")
private Long wareId;
@ApiModelProperty(value = "仓库")
@TableField("ware_id")
private Long wareId;
@ApiModelProperty(value = "仓库名称")
@TableField("ware_name")
private String wareName;
@ApiModelProperty(value = "状态0未开通 1已开通")
@TableField("status")
private Integer status;
@ApiModelProperty(value = "仓库名称")
@TableField("ware_name")
private String wareName;
@ApiModelProperty(value = "状态0未开通 1已开通")
@TableField("status")
private Integer status;
}

View File

@ -18,32 +18,30 @@ import java.util.List;
*/
@Data
public class OrderConfirmVo implements Serializable {
private static final long serialVersionUID = 1L;
private static final long serialVersionUID = 1L;
@ApiModelProperty(value = "预生产订单号")
private String orderNo;
@ApiModelProperty(value = "预生产订单号")
private String orderNo;
@ApiModelProperty(value = "用户对应的团长地址")
private LeaderAddressVo leaderAddressVo;
@ApiModelProperty(value = "购物项列表")
private List<CartInfoVo> carInfoVoList;
@ApiModelProperty(value = "用户对应的团长地址")
private LeaderAddressVo leaderAddressVo;
@ApiModelProperty(value = "订单优惠券列表")
@ApiModelProperty(value = "购物项列表")
private List<CartInfoVo> carInfoVoList;
@ApiModelProperty(value = "订单优惠券列表")
private List<CouponInfo> couponInfoList;
@ApiModelProperty(value = "促销优惠金额")
private BigDecimal activityReduceAmount;
@ApiModelProperty(value = "促销优惠金额")
private BigDecimal activityReduceAmount;
@ApiModelProperty(value = "优惠券优惠金额")
private BigDecimal couponReduceAmount;
@ApiModelProperty(value = "优惠券优惠金额")
private BigDecimal couponReduceAmount;
@ApiModelProperty(value = "购物车原始总金额")
private BigDecimal originalTotalAmount;
@ApiModelProperty(value = "最终总金额")
private BigDecimal totalAmount;
@ApiModelProperty(value = "购物车原始总金额")
private BigDecimal originalTotalAmount;
@ApiModelProperty(value = "最终总金额")
private BigDecimal totalAmount;
}

View File

@ -1,17 +1,14 @@
package com.atguigu.ssyx.vo.search;
import lombok.Data;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
// 封装查询条件
@Data
public class SkuEsQueryVo {
private Long categoryId;;//三级分类id
private String keyword;//检索的关键字
private Integer limit;
private Integer page;
private Long categoryId;
// 三级分类id
private String keyword;// 检索的关键字
private Long wareId;
}

View File

@ -1,9 +1,11 @@
package com.atguigu.ssyx.vo.user;
import com.baomidou.mybatisplus.annotation.TableField;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* <p>
@ -13,47 +15,48 @@ import lombok.Data;
* @author qy
*/
@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@ApiModel(description = "用户地址")
public class LeaderAddressVo {
@ApiModelProperty(value = "用户id")
private Long userId;
@ApiModelProperty(value = "用户id")
private Long userId;
@ApiModelProperty(value = "团长id")
private Long leaderId;
@ApiModelProperty(value = "团长id")
private Long leaderId;
@ApiModelProperty(value = "团长名称")
private String leaderName;
@ApiModelProperty(value = "团长名称")
private String leaderName;
@ApiModelProperty(value = "团长电话")
private String leaderPhone;
@ApiModelProperty(value = "团长电话")
private String leaderPhone;
@ApiModelProperty(value = "仓库id")
private Long wareId;
@ApiModelProperty(value = "仓库id")
private Long wareId;
@ApiModelProperty(value = "提货点名称")
private String takeName;
@ApiModelProperty(value = "提货点名称")
private String takeName;
@ApiModelProperty(value = "")
private String province;
@ApiModelProperty(value = "")
private String province;
@ApiModelProperty(value = "城市")
private String city;
@ApiModelProperty(value = "城市")
private String city;
@ApiModelProperty(value = "区域")
private String district;
@ApiModelProperty(value = "区域")
private String district;
@ApiModelProperty(value = "详细地址")
private String detailAddress;
@ApiModelProperty(value = "详细地址")
private String detailAddress;
@ApiModelProperty(value = "经度")
private String longitude;
@ApiModelProperty(value = "经度")
private String longitude;
@ApiModelProperty(value = "纬度")
private String latitude;
@ApiModelProperty(value = "门店照片")
private String storePath;
@ApiModelProperty(value = "纬度")
private String latitude;
@ApiModelProperty(value = "门店照片")
private String storePath;
}

11
pom.xml
View File

@ -44,6 +44,11 @@
<!--配置dependencyManagement锁定依赖的版本-->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
@ -129,6 +134,12 @@
<artifactId>hutool-all</artifactId>
<version>5.8.25</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.3.1</version>
</dependency>
</dependencies>
</dependencyManagement>
<!-- <repositories> -->

View File

@ -14,6 +14,11 @@
<url>https://maven.apache.org</url>
<modules>
<module>service-product-client</module>
<module>service-region-client</module>
<module>service-user-client</module>
<module>service-search-client</module>
<module>service-activity-client</module>
<module>service-cart-client</module>
</modules>
<properties>

View File

@ -0,0 +1,23 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>service-client</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>service-activity-client</artifactId>
<packaging>jar</packaging>
<name>service-activity-client</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
</project>

View File

@ -0,0 +1,40 @@
package com.atguigu.ssyx.client;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.vo.order.OrderConfirmVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
import java.util.Map;
@FeignClient(value = "service-activity", path = "/api/activity")
public interface ActivityFeignClient {
// 根据skuId列表获取促销信息
@PostMapping("inner/findActivity")
Map<Long, List<String>> findActivity(@RequestBody List<Long> skuIdList);
// 根据skuId获取促销与优惠券信息
@GetMapping("inner/findActivityAndCoupon/{skuId}/{userId}")
Map<String, Object> findActivityAndCoupon(@PathVariable Long skuId, @PathVariable Long userId);
// 获取购物车满足条件的促销与优惠券信息
@PostMapping("inner/findCartActivityAndCoupon/{userId}")
OrderConfirmVo findCartActivityAndCoupon(@RequestBody List<CartInfo> cartInfoList, @PathVariable Long userId);
// 获取优惠券范围对应的购物车列表
@PostMapping(value = "/api/activity/inner/findRangeSkuIdList/{couponId}")
CouponInfo findRangeSkuIdList(@RequestBody List<CartInfo> cartInfoList, @PathVariable("couponId") Long couponId);
// 根据活动id获取活动skuId列表
@GetMapping(value = "/api/activity/inner/findSkuIdList/{activityId}")
List<Long> findSkuIdList(@PathVariable("activityId") Long activityId);
// 更新优惠券支付时间
@GetMapping(value = "/api/activity/inner/updateCouponInfoUsedTime/{couponId}/{userId}")
Boolean updateCouponInfoUsedTime(@PathVariable("couponId") Long couponId, @PathVariable("userId") Long userId);
}

View File

@ -0,0 +1,23 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>service-client</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>service-cart-client</artifactId>
<packaging>jar</packaging>
<name>service-cart-client</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
</project>

View File

@ -0,0 +1,15 @@
package com.atguigu.ssyx.client.cart;
import com.atguigu.ssyx.model.order.CartInfo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
@FeignClient(value = "service-cart", path = "/api/cart")
public interface CartFeignClient {
// 根据用户Id查询购物车列表
@GetMapping("inner/getCartCheckedList/{userId}")
List<CartInfo> getCartCheckedList(@PathVariable Long userId);
}

View File

@ -3,15 +3,46 @@ package com.atguigu.ssyx.client.product;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.product.SkuInfoVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
@FeignClient(value = "service-product", path = "/api/product")
public interface ProductFeignClient {
// 根据分类id获取分类信息
@GetMapping("inner/getCategory/{categoryId}")
Result<Category> getCategory(@PathVariable Long categoryId);
// 根据skuId获取sku信息
@GetMapping("inner/getSkuInfo/{skuId}")
Result<SkuInfo> getSkuInfo(@PathVariable Long skuId);
// 根据skuId得到sku信息列表
@PostMapping("inner/findSkuInfoList")
Result<List<SkuInfo>> findSkuInfoList(@RequestBody List<Long> skuIdList);
// 根据关键字获取sku列表
@GetMapping("inner/findSkuInfoByKeyword/{keyword}")
Result<List<SkuInfo>> findSkuInfoByKeyword(@PathVariable("keyword") String keyword);
// 批量获取分类信息
@PostMapping("inner/findCategoryList")
List<Category> findCategoryList(@RequestBody List<Long> rangeIdList);
// 获取全部商品分类
@GetMapping("findAllList")
Result<List<Category>> findAllCategoryList();
// 获取新人专享
@GetMapping("inner/findNewPersonSkuInfoList")
Result<List<SkuInfo>> findNewPersonSkuInfoList();
// 根据skuId获取sku信息
@GetMapping("inner/getSkuInfoVo/{skuId}")
SkuInfoVo getSkuInfoVo(@PathVariable Long skuId);
}

View File

@ -0,0 +1,23 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>service-client</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>service-region-client</artifactId>
<packaging>jar</packaging>
<name>service-region-client</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
</project>

View File

@ -0,0 +1,12 @@
package com.atguigu.ssyx.client.region;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
@FeignClient(value = "service-sys", path = "/admin/sys/regionWare")
public interface RegionFeignClient {
// 根据RegionId查询WareId
@GetMapping("getWareId")
Long getWareId(@RequestParam Long regionId);
}

View File

@ -0,0 +1,23 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>service-client</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>service-search-client</artifactId>
<packaging>jar</packaging>
<name>service-search-client</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
</project>

View File

@ -0,0 +1,19 @@
package com.atguigu.ssyx.client.search;
import com.atguigu.ssyx.model.search.SkuEs;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import java.util.List;
@FeignClient(value = "service-search", path = "/api/search/sku")
public interface SearchFeignClient {
// 获取爆品商品
@GetMapping("inner/findHotSkuList")
List<SkuEs> findHotSkuList();
// 更新商品incrHotScore
@GetMapping("inner/incrHotScore/{skuId}")
Boolean incrHotScore(@PathVariable Long skuId);
}

View File

@ -0,0 +1,23 @@
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.atguigu</groupId>
<artifactId>service-client</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>service-user-client</artifactId>
<packaging>jar</packaging>
<name>service-user-client</name>
<url>https://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
</dependencies>
</project>

View File

@ -0,0 +1,13 @@
package com.atguigu.ssyx.client.user;
import com.atguigu.ssyx.vo.user.LeaderAddressVo;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
@FeignClient(value = "service-user", path = "/api/user/leader")
public interface UserFeignClient {
// 提货点地址信息
@GetMapping("/inner/getUserAddressByUserId/{userId}")
LeaderAddressVo getLeaderAddressByUserId(@PathVariable Long userId);
}

View File

@ -14,6 +14,9 @@
<url>https://maven.apache.org</url>
<properties>
<!-- <docker.repostory>192.168.1.4:1100</docker.repostory> -->
<docker.repostory>192.168.3.98:1100</docker.repostory>
<docker.registry.name>ssyx</docker.registry.name>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@ -44,4 +47,52 @@
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<!--将插件绑定在某个phase执行-->
<executions>
<execution>
<id>build-image</id>
<!--将插件绑定在package这个phase(阶段)上。也就是说用户只需执行mvn package就会自动执行mvn docker:build-->
<phase>package</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>harbor</serverId>
<registryUrl>http://${docker.repostory}</registryUrl>
<!-- 配置docker主机地址 -->
<!-- <dockerHost>http://192.168.1.4:2375</dockerHost> -->
<dockerHost>http://192.168.3.98:2375</dockerHost>
<!--指定生成的镜像名-->
<imageName>
${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version}
</imageName>
<!-- 指定 dockerfile 路径-->
<dockerDirectory>${project.basedir}</dockerDirectory>
<!-- 是否跳过docker构建 -->
<skipDockerBuild>false</skipDockerBuild>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -18,6 +18,10 @@
<module>service-product</module>
<module>service-search</module>
<module>service-activity</module>
<module>service-user</module>
<module>service-home</module>
<module>service-cart</module>
<module>service-order</module>
</modules>
<properties>

View File

@ -14,7 +14,8 @@
<url>https://maven.apache.org</url>
<properties>
<docker.repostory>192.168.1.4:1100</docker.repostory>
<!-- <docker.repostory>192.168.1.4:1100</docker.repostory> -->
<docker.repostory>192.168.3.98:1100</docker.repostory>
<docker.registry.name>ssyx</docker.registry.name>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
@ -59,7 +60,8 @@
<serverId>harbor</serverId>
<registryUrl>http://${docker.repostory}</registryUrl>
<!-- 配置docker主机地址 -->
<dockerHost>http://192.168.1.4:2375</dockerHost>
<!-- <dockerHost>http://192.168.1.4:2375</dockerHost> -->
<dockerHost>http://192.168.3.98:2375</dockerHost>
<!--指定生成的镜像名-->
<imageName>
${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version}

View File

@ -46,4 +46,19 @@ public class PermissionController {
permissionService.removeChildById(id);
return Result.success();
}
@ApiOperation(value = "查询所有菜单和角色分配菜单")
@GetMapping("toAssign/{roleId}")
public Result<List<Permission>> toAssign(@PathVariable Long roleId) {
List<Permission> permissionList = permissionService.findMenuByRoleId(roleId);
return Result.success(permissionList);
}
@ApiOperation(value = "查询所有菜单和角色分配菜单")
@PostMapping("doAssign")
public Result<Permission> doAssign(@RequestParam Long roleId,
@RequestParam List<Long> permissions) {
permissionService.doAssign(roleId, permissions);
return Result.success();
}
}

View File

@ -0,0 +1,9 @@
package com.atguigu.ssyx.acl.mapper;
import com.atguigu.ssyx.model.acl.RolePermission;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface RolePermissionMapper extends BaseMapper<RolePermission> {
}

View File

@ -20,4 +20,20 @@ public interface PermissionService extends IService<Permission> {
* @param id 删除ID
*/
void removeChildById(Long id);
/**
* 查询所有菜单和角色分配菜单
*
* @param roleId 角色Id
* @return 权限列表
*/
List<Permission> findMenuByRoleId(Long roleId);
/**
* 查询所有菜单和角色分配菜单
*
* @param roleId 角色Id
* @param permissions 分配权限Id
*/
void doAssign(Long roleId, List<Long> permissions);
}

View File

@ -0,0 +1,7 @@
package com.atguigu.ssyx.acl.service;
import com.atguigu.ssyx.model.acl.RolePermission;
import com.baomidou.mybatisplus.extension.service.IService;
public interface RolePermissionService extends IService<RolePermission> {
}

View File

@ -3,19 +3,25 @@ package com.atguigu.ssyx.acl.service.impl;
import com.atguigu.common.utils.PermissionHelper;
import com.atguigu.ssyx.acl.mapper.PermissionMapper;
import com.atguigu.ssyx.acl.service.PermissionService;
import com.atguigu.ssyx.acl.service.RolePermissionService;
import com.atguigu.ssyx.acl.service.module.PermissionServiceModule;
import com.atguigu.ssyx.model.acl.Permission;
import com.atguigu.ssyx.model.acl.RolePermission;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {
@Autowired
private PermissionServiceModule permissionServiceModule;
@Autowired
private RolePermissionService rolePermissionService;
/**
* 获取所有菜单列表
@ -43,4 +49,52 @@ public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permiss
// 调用方法根据多个菜单ID删除
baseMapper.deleteBatchIds(idList);
}
/**
* 查询所有菜单和角色分配菜单
*
* @param roleId 角色Id
* @return 权限列表
*/
@Override
public List<Permission> findMenuByRoleId(Long roleId) {
List<Permission> permissionList = list();
List<RolePermission> rolePermissionList = rolePermissionService.list(
Wrappers.<RolePermission>lambdaQuery().eq(RolePermission::getRoleId, roleId)
);
List<Long> permissionIdList = rolePermissionList.stream().map(RolePermission::getPermissionId).collect(Collectors.toList());
permissionList.forEach(permission -> {
if (permissionIdList.contains(permission.getId())) {
permission.setSelect(true);
}
permission.setSelect(false);
});
return PermissionHelper.buildPermissions(permissionList);
}
/**
* 查询所有菜单和角色分配菜单
*
* @param roleId 角色Id
* @param permissions 分配权限Id
*/
@Override
public void doAssign(Long roleId, List<Long> permissions) {
// 先删除之前分配的角色
rolePermissionService.remove(Wrappers.<RolePermission>lambdaQuery().eq(RolePermission::getRoleId, roleId));
ArrayList<RolePermission> list = new ArrayList<>();
permissions.forEach(permissionId -> {
RolePermission rolePermission = new RolePermission();
rolePermission.setPermissionId(permissionId);
rolePermission.setRoleId(roleId);
list.add(rolePermission);
});
rolePermissionService.saveBatch(list);
}
}

View File

@ -0,0 +1,11 @@
package com.atguigu.ssyx.acl.service.impl;
import com.atguigu.ssyx.acl.mapper.RolePermissionMapper;
import com.atguigu.ssyx.acl.service.RolePermissionService;
import com.atguigu.ssyx.model.acl.RolePermission;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class RolePermissionServiceImpl extends ServiceImpl<RolePermissionMapper, RolePermission> implements RolePermissionService {
}

View File

@ -28,21 +28,10 @@ spring:
mybatis-plus:
type-aliases-package: com.atguigu.model # 配置每个包前缀
type-enums-package: com.atguigu.ssyx.enums # 加上枚举类型
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
global-config:
db-config:
# 设置表名前缀不用在每个tableName添加前缀
# table-prefix: t_
# 全局配置主键值方式
id-type: assign_id
logic-not-delete-value: 0 # 未删除默认为0
logic-delete-value: 1 # 删除
logic-delete-field: deleted # 全局配置逻辑删除
logging:
level:

View File

@ -0,0 +1,20 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo1 {
/**
* * runAsync
* 不返回返回值
*/
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
System.out.println("main begin....");
CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int result = 1024;
System.out.println("result:" + result);
}, executorService);
System.out.println("main over....");
}
}

View File

@ -0,0 +1,25 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo2 {
/**
* * supplyAsync
* 可以指定返回值
*/
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
System.out.println("main begin....");
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int result = 1024;
System.out.println("result:" + result);
return result;
}, executorService);
// 获取返回结果
Integer value = completableFuture.get();
System.out.println("main over...." + value);
}
}

View File

@ -0,0 +1,24 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo3 {
// **whenComplete whenCompleteAsync 的区别**
// whenComplete是执行当前任务的线程执行继续执行 whenComplete 的任务
// whenCompleteAsync是执行把 whenCompleteAsync 这个任务继续提交给线程池来进行执行
// 方法不以Async结尾意味着Action使用相同的线程执行而Async可能会使用其他线程执行如果是使用相同的线程池也可能会被同一个线程选中执行
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
System.out.println("main begin....");
CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {
System.out.println("当前线程:" + Thread.currentThread().getId());
int result = 1024;
System.out.println("result:" + result);
return result;
}, executorService).whenComplete((result, exception) -> {
System.out.println("结果:" + result);
System.out.println(exception.getMessage());
});
System.out.println("main over....");
}
}

View File

@ -0,0 +1,29 @@
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Demo4 {
// 只要上面的任务执行完成就开始执行thenRun只是处理完任务后执行 thenRun的后续操作
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 现成的串行执行
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> {
int value = 1024;
System.out.println("1===>" + value);
return 1024;
});
CompletableFuture<Integer> futureB = futureA.thenApplyAsync((result) -> {
System.out.println("2===>" + result);
return result;
}, executorService);
CompletableFuture<Integer> futureC = futureB.thenApplyAsync((result) -> {
System.out.println("3===>" + result);
return result;
}, executorService);
executorService.shutdown();
}
}

View File

@ -0,0 +1,33 @@
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
public class Demo5 {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
// 线程一 的异步执行
CompletableFuture<Integer> futureA = CompletableFuture.supplyAsync(() -> {
int count = 100;
log.info("线程一:{}", count);
return count;
}, executorService);
// 线程二 异步执行
CompletableFuture<Integer> futureB = CompletableFuture.supplyAsync(() -> {
System.out.println(Thread.currentThread().getName() + "--begin..");
int res = 30;
System.out.println("二:" + res);
System.out.println(Thread.currentThread().getName() + "--over..");
return res;
}, executorService);
CompletableFuture<Void> all = CompletableFuture.allOf(futureA, futureB);
all.get();
System.out.println("over....");
}
}

View File

@ -14,10 +14,65 @@
<url>https://maven.apache.org</url>
<properties>
<!-- <docker.repostory>192.168.1.4:1100</docker.repostory> -->
<docker.repostory>192.168.3.98:1100</docker.repostory>
<docker.registry.name>ssyx</docker.registry.name>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.atguigu</groupId>
<artifactId>service-product-client</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>com.spotify</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>1.2.2</version>
<!--将插件绑定在某个phase执行-->
<executions>
<execution>
<id>build-image</id>
<!--将插件绑定在package这个phase(阶段)上。也就是说用户只需执行mvn package就会自动执行mvn docker:build-->
<phase>package</phase>
<goals>
<goal>build</goal>
<goal>push</goal>
</goals>
</execution>
</executions>
<configuration>
<serverId>harbor</serverId>
<registryUrl>http://${docker.repostory}</registryUrl>
<!-- 配置docker主机地址 -->
<!-- <dockerHost>http://192.168.1.4:2375</dockerHost> -->
<dockerHost>http://192.168.3.98:2375</dockerHost>
<!--指定生成的镜像名-->
<imageName>
${docker.repostory}/${docker.registry.name}/${project.artifactId}:${project.version}
</imageName>
<!-- 指定 dockerfile 路径-->
<dockerDirectory>${project.basedir}</dockerDirectory>
<!-- 是否跳过docker构建 -->
<skipDockerBuild>false</skipDockerBuild>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -2,6 +2,8 @@ package com.atguigu.ssyx.activity;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@ -10,6 +12,8 @@ import org.springframework.transaction.annotation.EnableTransactionManagement;
"com.atguigu.ssyx.common",
"com.atguigu.ssyx.activity"})
@EnableTransactionManagement
@EnableDiscoveryClient
@EnableFeignClients(basePackages = {"com.atguigu.ssyx.client"})
public class ServiceActivityApplication {
public static void main(String[] args) {
SpringApplication.run(ServiceActivityApplication.class, args);

View File

@ -0,0 +1,40 @@
package com.atguigu.ssyx.activity.api;
import com.atguigu.ssyx.activity.service.ActivityInfoService;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.vo.order.OrderConfirmVo;
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;
import java.util.Map;
@Api(tags = "促销与优惠券接口")
@RestController
@RequestMapping("/api/activity")
@Slf4j
public class ActivityApiController {
@Autowired
private ActivityInfoService activityInfoService;
@ApiOperation(value = "根据skuId列表获取促销信息")
@PostMapping("inner/findActivity")
public Map<Long, List<String>> findActivity(@RequestBody List<Long> skuIdList) {
return activityInfoService.findActivity(skuIdList);
}
@ApiOperation(value = "根据skuId获取促销与优惠券信息")
@GetMapping("inner/findActivityAndCoupon/{skuId}/{userId}")
public Map<String, Object> findActivityAndCoupon(@PathVariable Long skuId, @PathVariable Long userId) {
return activityInfoService.findActivityAndCoupon(skuId, userId);
}
@ApiOperation(value = "获取购物车满足条件的促销与优惠券信息")
@PostMapping("inner/findCartActivityAndCoupon/{userId}")
public OrderConfirmVo findCartActivityAndCoupon(@RequestBody List<CartInfo> cartInfoList, @PathVariable Long userId) {
return activityInfoService.findCartActivityAndCoupon(cartInfoList, userId);
}
}

View File

@ -0,0 +1,54 @@
package com.atguigu.ssyx.activity.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.ParameterBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.ModelRef;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.Contact;
import springfox.documentation.service.Parameter;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2WebMvc;
import java.util.ArrayList;
import java.util.List;
@Configuration
@EnableSwagger2WebMvc
public class Knife4jConfig {
@Bean
public Docket adminApiConfig() {
List<Parameter> pars = new ArrayList<>();
ParameterBuilder tokenPar = new ParameterBuilder();
tokenPar.name("adminId")
.description("用户token")
.defaultValue("1")
.modelRef(new ModelRef("string"))
.parameterType("header")
.required(false)
.build();
pars.add(tokenPar.build());
return new Docket(DocumentationType.SWAGGER_2)
.groupName("活动相关API")
.apiInfo(adminApiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("com.atguigu.ssyx.activity.controller"))
.paths(PathSelectors.regex("/admin/.*"))
.build()
.globalOperationParameters(pars);
}
private ApiInfo adminApiInfo() {
return new ApiInfoBuilder()
.title("后台管理系统-API文档")
.description("本文档描述了尚上优选后台系统服务接口定义")
.version("1.0")
.contact(new Contact("atguigu", "http://atguigu.com", "atguigu"))
.build();
}
}

View File

@ -2,23 +2,95 @@ package com.atguigu.ssyx.activity.controller;
import com.atguigu.ssyx.activity.service.ActivityInfoService;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.activity.ActivityInfo;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.activity.ActivityRuleVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
/**
* <p>
* 活动表 前端控制器
* </p>
*
* @author bunny
* @since 2024-04-04
*/
import java.util.Date;
import java.util.List;
import java.util.Map;
@Api(tags = "活动相关接口")
@RestController
@RequestMapping("/admin/activity/activityInfo")
public class ActivityInfoController {
@Autowired
private ActivityInfoService activityInfoService;
@ApiOperation(value = "获取分页列表")
@GetMapping("{page}/{limit}")
public Result<IPage<ActivityInfo>> index(
@ApiParam(name = "page", value = "当前页码", required = true) @PathVariable Long page,
@ApiParam(name = "limit", value = "每页记录数", required = true) @PathVariable Long limit
) {
Page<ActivityInfo> pageParam = new Page<>(page, limit);
IPage<ActivityInfo> pageModel = activityInfoService.selectPage(pageParam);
return Result.success(pageModel);
}
@ApiOperation(value = "获取活动")
@GetMapping("get/{id}")
public Result<ActivityInfo> get(@PathVariable Long id) {
ActivityInfo activityInfo = activityInfoService.getById(id);
activityInfo.setActivityTypeString(activityInfo.getActivityType().getComment());
return Result.success(activityInfo);
}
@ApiOperation(value = "新建活动")
@PostMapping("save")
public Result<ActivityInfo> save(@RequestBody ActivityInfo activityInfo) {
activityInfo.setCreateTime(new Date());
activityInfoService.save(activityInfo);
return Result.success();
}
@ApiOperation(value = "修改活动")
@PutMapping("update")
public Result<ActivityInfo> updateById(@RequestBody ActivityInfo activityInfo) {
activityInfoService.updateById(activityInfo);
return Result.success();
}
@ApiOperation(value = "删除活动")
@DeleteMapping("remove/{id}")
public Result<ActivityInfo> remove(@PathVariable Long id) {
activityInfoService.removeById(id);
return Result.success();
}
@ApiOperation(value = "根据id列表删除活动")
@DeleteMapping("batchRemove")
public Result<ActivityInfo> batchRemove(@RequestBody List<String> ids) {
activityInfoService.removeByIds(ids);
return Result.success();
}
@ApiOperation(value = "获取活动规则")
@GetMapping("findActivityRuleList/{id}")
public Result<Map<String, Object>> findActivityRuleList(@PathVariable Long id) {
return Result.success(activityInfoService.findActivityRuleList(id));
}
@ApiOperation(value = "新增活动规则")
@PostMapping("saveActivityRule")
public Result<ActivityInfo> saveActivityRule(@RequestBody ActivityRuleVo activityRuleVo) {
activityInfoService.saveActivityRule(activityRuleVo);
return Result.success();
}
@ApiOperation(value = "根据关键字获取sku列表活动使用")
@GetMapping("findSkuInfoByKeyword/{keyword}")
public Result<List<SkuInfo>> findSkuInfoByKeyword(@PathVariable("keyword") String keyword) {
return Result.success(activityInfoService.findSkuInfoByKeyword(keyword));
}
}

View File

@ -1,21 +1,94 @@
package com.atguigu.ssyx.activity.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import com.atguigu.ssyx.activity.service.CouponInfoService;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.vo.activity.CouponRuleVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
import java.util.Map;
/**
* <p>
* 优惠券信息 前端控制器
* </p>
*
* @author bunny
* @since 2024-04-04
*/
@Api(tags = "优惠卷相关接口")
@RestController
@RequestMapping("/activity/coupon-info")
@RequestMapping("/admin/activity/couponInfo")
public class CouponInfoController {
}
@Autowired
private CouponInfoService couponInfoService;
@ApiOperation(value = "获取分页列表")
@GetMapping("{page}/{limit}")
public Result<IPage<CouponInfo>> index(
@ApiParam(name = "page", value = "当前页码", required = true)
@PathVariable Long page,
@ApiParam(name = "limit", value = "每页记录数", required = true)
@PathVariable Long limit
) {
Page<CouponInfo> pageParam = new Page<>(page, limit);
IPage<CouponInfo> pageModel = couponInfoService.selectPage(pageParam);
return Result.success(pageModel);
}
@ApiOperation(value = "获取优惠券")
@GetMapping("get/{id}")
public Result<CouponInfo> get(@PathVariable Long id) {
CouponInfo couponInfo = couponInfoService.getCouponInfo(id);
return Result.success(couponInfo);
}
@ApiOperation(value = "新增优惠券")
@PostMapping("save")
public Result<CouponInfo> save(@RequestBody CouponInfo couponInfo) {
couponInfoService.save(couponInfo);
return Result.success();
}
@ApiOperation(value = "修改优惠券")
@PutMapping("update")
public Result<CouponInfo> update(@RequestBody CouponInfo couponInfo) {
couponInfoService.save(couponInfo);
return Result.success();
}
@ApiOperation(value = "删除优惠券")
@DeleteMapping("remove/{id}")
public Result<CouponInfo> remove(@PathVariable Long id) {
couponInfoService.removeById(id);
return Result.success();
}
@ApiOperation(value = "根据id列表删除优惠券")
@DeleteMapping("batchRemove")
public Result<CouponInfo> batchRemove(@RequestBody List<Long> ids) {
couponInfoService.removeByIds(ids);
return Result.success();
}
@ApiOperation(value = "获取优惠券信息")
@GetMapping("findCouponRuleList/{id}")
public Result<Map<String, Object>> findCouponRuleList(@PathVariable Long id) {
Map<String, Object> map = couponInfoService.findCouponRuleList(id);
return Result.success(map);
}
@ApiOperation(value = "新增活动")
@PostMapping("saveCouponRule")
public Result<CouponRuleVo> saveCouponRule(@RequestBody CouponRuleVo couponRuleVo) {
couponInfoService.saveCouponRule(couponRuleVo);
return Result.success();
}
@ApiOperation(value = "根据关键字获取sku列表活动使用")
@GetMapping("findCouponByKeyword/{keyword}")
public Result<List<CouponInfo>> findCouponByKeyword(@PathVariable("keyword") String keyword) {
return Result.success(couponInfoService.findCouponByKeyword(keyword));
}
}

View File

@ -0,0 +1,89 @@
package com.atguigu.ssyx.activity.controller;
import com.atguigu.ssyx.activity.service.SecKillService;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.activity.Seckill;
import com.atguigu.ssyx.vo.activity.SeckillQueryVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* <p>
* 秒杀活动 前端控制器
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Api(value = "Seckill管理", tags = "Seckill管理")
@RestController
@RequestMapping(value = "/admin/activity/seckill")
public class SecKillController {
@Autowired
private SecKillService secKillService;
@ApiOperation(value = "获取分页列表")
@GetMapping("{page}/{limit}")
public Result<IPage<Seckill>> index(
@ApiParam(name = "page", value = "当前页码", required = true)
@PathVariable Long page,
@ApiParam(name = "limit", value = "每页记录数", required = true)
@PathVariable Long limit,
@ApiParam(name = "seckillQueryVo", value = "查询对象", required = false)
SeckillQueryVo seckillQueryVo) {
Page<Seckill> pageParam = new Page<>();
IPage<Seckill> pageModel = secKillService.selectPage(pageParam, seckillQueryVo);
return Result.success(pageModel);
}
@ApiOperation(value = "获取")
@GetMapping("get/{id}")
public Result<Seckill> getSecKill(@PathVariable Long id) {
Seckill seckill = secKillService.getById(id);
return Result.success(seckill);
}
@ApiOperation(value = "新增")
@PostMapping("save")
public Result<Seckill> save(@RequestBody Seckill seckill) {
secKillService.save(seckill);
return Result.success();
}
@ApiOperation(value = "修改")
@PutMapping("update")
public Result<Seckill> updateById(@RequestBody Seckill seckill) {
secKillService.updateById(seckill);
return Result.success();
}
@ApiOperation(value = "删除")
@DeleteMapping("remove/{id}")
public Result<Seckill> removeById(@PathVariable Long id) {
secKillService.removeById(id);
return Result.success();
}
@ApiOperation(value = "根据id列表删除")
@DeleteMapping("batchRemove")
public Result<Seckill> batchRemove(@RequestBody List<Long> ids) {
secKillService.removeByIds(ids);
return Result.success();
}
@ApiOperation(value = "更新状态")
@PostMapping("updateStatus/{id}/{status}")
public Result<Seckill> updateStatus(@PathVariable Long id, @PathVariable Integer status) {
secKillService.updateStatus(id, status);
return Result.success();
}
}

View File

@ -0,0 +1,75 @@
package com.atguigu.ssyx.activity.controller;
import com.atguigu.ssyx.activity.service.SecKillSkuService;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.activity.SeckillSku;
import com.atguigu.ssyx.vo.activity.SeckillSkuVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@Api(value = "SeckillSku管理", tags = "SeckillSku管理")
@RestController
@RequestMapping(value = "/admin/activity/seckillSku")
public class SecKillSkuController {
@Autowired
private SecKillSkuService secKillSkuService;
@ApiOperation(value = "获取分页列表")
@GetMapping("{page}/{limit}")
public Result<IPage<SeckillSku>> index(
@ApiParam(name = "page", value = "当前页码", required = true)
@PathVariable Long page,
@ApiParam(name = "limit", value = "每页记录数", required = true)
@PathVariable Long limit,
@ApiParam(name = "seckillSkuQueryVo", value = "查询对象", required = false)
SeckillSkuVo seckillSkuVo
) {
Page<SeckillSku> pageParam = new Page<>();
IPage<SeckillSku> pageModel = secKillSkuService.selectPage(pageParam, seckillSkuVo);
return Result.success(pageModel);
}
@ApiOperation(value = "获取")
@GetMapping("get/{id}")
public Result<SeckillSku> get(@PathVariable Long id) {
SeckillSku seckillSku = secKillSkuService.getById(id);
return Result.success(seckillSku);
}
@ApiOperation(value = "新增")
@PostMapping("save")
public Result<SeckillSku> save(@RequestBody List<SeckillSku> seckillSkuList) {
secKillSkuService.saveBatch(seckillSkuList);
return Result.success();
}
@ApiOperation(value = "修改")
@PutMapping("update")
public Result<SeckillSku> updateById(@RequestBody SeckillSku seckillSku) {
secKillSkuService.updateById(seckillSku);
return Result.success();
}
@ApiOperation(value = "删除")
@DeleteMapping("remove/{id}")
public Result<SeckillSku> remove(@PathVariable Long id) {
secKillSkuService.removeById(id);
return Result.success();
}
@ApiOperation(value = "根据id列表删除")
@DeleteMapping("batchRemove")
public Result<SeckillSku> batchRemove(@RequestBody List<Long> ids) {
secKillSkuService.removeByIds(ids);
return Result.success();
}
}

View File

@ -0,0 +1,20 @@
package com.atguigu.ssyx.activity.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* 秒杀商品通知订阅 前端控制器
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@RestController
@RequestMapping("/activity/seckill-sku-notice")
public class SecKillSkuNoticeController {
}

View File

@ -0,0 +1,69 @@
package com.atguigu.ssyx.activity.controller;
import com.atguigu.ssyx.activity.service.SeckillTimeService;
import com.atguigu.ssyx.common.result.Result;
import com.atguigu.ssyx.model.activity.SeckillTime;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;
@Api(value = "秒杀场次管理", tags = "秒杀场次管理")
@RestController
@RequestMapping(value = "/admin/activity/seckillTime")
public class SeckillTimeController {
@Resource
private SeckillTimeService seckillTimeService;
@ApiOperation(value = "获取分页列表")
@GetMapping()
public Result<List<SeckillTime>> index() {
return Result.success(seckillTimeService.list());
}
@ApiOperation(value = "获取")
@GetMapping("get/{id}")
public Result<SeckillTime> get(@PathVariable Long id) {
SeckillTime seckillSession = seckillTimeService.getById(id);
return Result.success(seckillSession);
}
@ApiOperation(value = "新增")
@PostMapping("save")
public Result save(@RequestBody SeckillTime seckillSession) {
seckillTimeService.save(seckillSession);
return Result.success();
}
@ApiOperation(value = "修改")
@PutMapping("update")
public Result<SeckillTime> updateById(@RequestBody SeckillTime seckillSession) {
seckillTimeService.updateById(seckillSession);
return Result.success();
}
@ApiOperation(value = "删除")
@DeleteMapping("remove/{id}")
public Result<SeckillTime> remove(@PathVariable Long id) {
seckillTimeService.removeById(id);
return Result.success();
}
@ApiOperation(value = "根据id列表删除")
@DeleteMapping("batchRemove")
public Result<SeckillTime> batchRemove(@RequestBody List<Long> idList) {
seckillTimeService.removeByIds(idList);
return Result.success();
}
@ApiOperation(value = "更新状态")
@PostMapping("updateStatus/{id}/{status}")
public Result<SeckillTime> updateStatus(@PathVariable Long id, @PathVariable Integer status) {
seckillTimeService.updateStatus(id, status);
return Result.success();
}
}

View File

@ -0,0 +1,21 @@
package com.atguigu.ssyx.activity.controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* <p>
* sku信息 前端控制器
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@RestController
@RequestMapping("/activity/sku-info")
public class SkuInfoController {
}

View File

@ -1,7 +1,13 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.ActivityInfo;
import com.atguigu.ssyx.model.activity.ActivityRule;
import com.atguigu.ssyx.model.activity.ActivitySku;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
@ -11,6 +17,30 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @author bunny
* @since 2024-04-04
*/
@Mapper
public interface ActivityInfoMapper extends BaseMapper<ActivityInfo> {
/**
* 判断添加商品之前是否参加过活动
*
* @param skuIdList skuId
* @return List<Long>
*/
List<Long> selectSkuIdListExist(List<Long> skuIdList);
/**
* * 根据skuId 查询对应规则列表
*
* @param skuId 商品Id
* @return 商品活动列表
*/
List<ActivityRule> findActivityRule(Long skuId);
/**
* * 根据所有skuId获取参与活动
*
* @param skuIdList skuId列表
* @return List<ActivitySku>
*/
List<ActivitySku> selectCartActivity(@Param("skuIdList") List<Long> skuIdList);
}

View File

@ -0,0 +1,10 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.ActivityRule;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ActivityRuleMapper extends BaseMapper<ActivityRule> {
}

View File

@ -0,0 +1,9 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.ActivitySku;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface ActivitySkuMapper extends BaseMapper<ActivitySku> {
}

View File

@ -2,6 +2,9 @@ package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* <p>
@ -11,6 +14,23 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
* @author bunny
* @since 2024-04-04
*/
@Mapper
public interface CouponInfoMapper extends BaseMapper<CouponInfo> {
/**
* * 根据skuId获取活动规则数据
*
* @param id 商品id
* @param categoryId 分类id
* @param userId 用户id
* @return 优惠卷信息列表
*/
List<CouponInfo> selectCouponInfoList(Long id, Long categoryId, Long userId);
/**
* 获取用户全部优惠券
*
* @param userId 用户ID
* @return List<CouponInfo>
*/
List<CouponInfo> selectCartCouponInfoList(Long userId);
}

View File

@ -0,0 +1,9 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.CouponRange;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface CouponRangeMapper extends BaseMapper<CouponRange> {
}

View File

@ -0,0 +1,18 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.Seckill;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 秒杀活动 Mapper 接口
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Mapper
public interface SecKillMapper extends BaseMapper<Seckill> {
}

View File

@ -0,0 +1,18 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.SeckillSku;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 秒杀活动商品关联 Mapper 接口
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Mapper
public interface SecKillSkuMapper extends BaseMapper<SeckillSku> {
}

View File

@ -0,0 +1,18 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.SeckillSkuNotice;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* 秒杀商品通知订阅 Mapper 接口
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Mapper
public interface SecKillSkuNoticeMapper extends BaseMapper<SeckillSkuNotice> {
}

View File

@ -0,0 +1,10 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.activity.SeckillTime;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface SeckillTimeMapper extends BaseMapper<SeckillTime> {
}

View File

@ -0,0 +1,18 @@
package com.atguigu.ssyx.activity.mapper;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* <p>
* sku信息 Mapper 接口
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Mapper
public interface SkuInfoMapper extends BaseMapper<SkuInfo> {
}

View File

@ -1,16 +1,73 @@
package com.atguigu.ssyx.activity.service;
import com.atguigu.ssyx.model.activity.ActivityInfo;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.activity.ActivityRuleVo;
import com.atguigu.ssyx.vo.order.OrderConfirmVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 活动表 服务类
* </p>
*
* @author bunny
* @since 2024-04-04
*/
import java.util.List;
import java.util.Map;
public interface ActivityInfoService extends IService<ActivityInfo> {
/**
* 获取分页列表
*
* @param pageParam 分页查询条件
* @return 分页结果
*/
IPage<ActivityInfo> selectPage(Page<ActivityInfo> pageParam);
/**
* 获取活动规则
*
* @param id 当前id
* @return 返回集合
*/
Map<String, Object> findActivityRuleList(Long id);
/**
* 新增活动规则
*
* @param activityRuleVo 活动规则
*/
void saveActivityRule(ActivityRuleVo activityRuleVo);
/**
* 根据关键字获取sku列表活动使用
*
* @param keyword 关键字
* @return 活动列表
*/
List<SkuInfo> findSkuInfoByKeyword(String keyword);
/**
* * 根据skuId列表获取促销信息
*
* @param skuIdList 列表
* @return Map<Long, List < String>>
*/
Map<Long, List<String>> findActivity(List<Long> skuIdList);
/**
* * 根据skuId获取促销与优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 营销的活动
*/
Map<String, Object> findActivityAndCoupon(Long skuId, Long userId);
/**
* * 获取购物车满足条件的促销与优惠券信息
*
* @param cartInfoList 购物车信息列表
* @param userId 用户ID
* @return OrderConfirmVo
*/
OrderConfirmVo findCartActivityAndCoupon(List<CartInfo> cartInfoList, Long userId);
}

View File

@ -1,8 +1,15 @@
package com.atguigu.ssyx.activity.service;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.vo.activity.CouponRuleVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
import java.util.Map;
/**
* <p>
* 优惠券信息 服务类
@ -13,4 +20,60 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface CouponInfoService extends IService<CouponInfo> {
/**
* * 获取分页列表
*
* @param pageParam 查询分页条件
* @return 分页结果
*/
IPage<CouponInfo> selectPage(Page<CouponInfo> pageParam);
/**
* 获取优惠券
*
* @param id 优惠卷Id
* @return 优惠卷
*/
CouponInfo getCouponInfo(Long id);
/**
* 获取优惠券信息
*
* @param id 优惠卷Id
* @return Map<String, Object>
*/
Map<String, Object> findCouponRuleList(Long id);
/**
* * 新增活动
*
* @param couponRuleVo 新的活动
*/
void saveCouponRule(CouponRuleVo couponRuleVo);
/**
* 根据关键字获取sku列表活动使用
*
* @param keyword 关键字
* @return 根据关键字获取sku列表活动使用
*/
List<CouponInfo> findCouponByKeyword(String keyword);
/**
* * 获取优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 优惠卷列表
*/
List<CouponInfo> findCouponInfo(Long skuId, Long userId);
/**
* * 购物车可使用的优惠券列表
*
* @param cartInfoList 购物车列表信息
* @param userId 用户ID
* @return List<CouponInfo>
*/
List<CouponInfo> findCartCouponInfo(List<CartInfo> cartInfoList, Long userId);
}

View File

@ -0,0 +1,35 @@
package com.atguigu.ssyx.activity.service;
import com.atguigu.ssyx.model.activity.Seckill;
import com.atguigu.ssyx.vo.activity.SeckillQueryVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 秒杀活动 服务类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
public interface SecKillService extends IService<Seckill> {
/**
* * 获取分页列表
*
* @param pageParam 分页参数
* @param seckillQueryVo 秒杀信息
* @return 分页结果
*/
IPage<Seckill> selectPage(Page<Seckill> pageParam, SeckillQueryVo seckillQueryVo);
/**
* * 更新状态
*
* @param id Id
* @param status 状态值
*/
void updateStatus(Long id, Integer status);
}

View File

@ -0,0 +1,16 @@
package com.atguigu.ssyx.activity.service;
import com.atguigu.ssyx.model.activity.SeckillSkuNotice;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 秒杀商品通知订阅 服务类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
public interface SecKillSkuNoticeService extends IService<SeckillSkuNotice> {
}

View File

@ -0,0 +1,27 @@
package com.atguigu.ssyx.activity.service;
import com.atguigu.ssyx.model.activity.SeckillSku;
import com.atguigu.ssyx.vo.activity.SeckillSkuVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 秒杀活动商品关联 服务类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
public interface SecKillSkuService extends IService<SeckillSku> {
/**
* * 获取分页列表
*
* @param pageParam 当前页码信息
* @param vo 查询对象
* @return 分页结果
*/
IPage<SeckillSku> selectPage(Page<SeckillSku> pageParam, SeckillSkuVo vo);
}

View File

@ -0,0 +1,15 @@
package com.atguigu.ssyx.activity.service;
import com.atguigu.ssyx.model.activity.SeckillTime;
import com.baomidou.mybatisplus.extension.service.IService;
public interface SeckillTimeService extends IService<SeckillTime> {
/**
* * 更新状态
*
* @param id 当前Id
* @param status 当前状态
*/
void updateStatus(Long id, Integer status);
}

View File

@ -0,0 +1,16 @@
package com.atguigu.ssyx.activity.service;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* sku信息 服务类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
public interface SkuInfoService extends IService<SkuInfo> {
}

View File

@ -1,20 +1,251 @@
package com.atguigu.ssyx.activity.service.impl;
import com.atguigu.ssyx.activity.mapper.ActivityInfoMapper;
import com.atguigu.ssyx.activity.mapper.ActivityRuleMapper;
import com.atguigu.ssyx.activity.mapper.ActivitySkuMapper;
import com.atguigu.ssyx.activity.service.ActivityInfoService;
import com.atguigu.ssyx.activity.service.CouponInfoService;
import com.atguigu.ssyx.activity.service.module.ActivityInfoServiceModule;
import com.atguigu.ssyx.client.product.ProductFeignClient;
import com.atguigu.ssyx.model.activity.ActivityInfo;
import com.atguigu.ssyx.model.activity.ActivityRule;
import com.atguigu.ssyx.model.activity.ActivitySku;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.activity.ActivityRuleVo;
import com.atguigu.ssyx.vo.order.CartInfoVo;
import com.atguigu.ssyx.vo.order.OrderConfirmVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* <p>
* 活动表 服务实现类
* </p>
*
* @author bunny
* @since 2024-04-04
*/
@Service
@Transactional
public class ActivityInfoServiceImpl extends ServiceImpl<ActivityInfoMapper, ActivityInfo> implements ActivityInfoService {
@Autowired
private ProductFeignClient productFeignClient;
@Autowired
private ActivityRuleMapper activityRuleMapper;
@Autowired
private ActivitySkuMapper activitySkuMapper;
@Autowired
private CouponInfoService couponInfoService;
@Autowired
private ActivityInfoServiceModule module;
/**
* 获取分页列表
*
* @param pageParam 分页查询条件
* @return 分页结果
*/
@Override
public IPage<ActivityInfo> selectPage(Page<ActivityInfo> pageParam) {
QueryWrapper<ActivityInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
IPage<ActivityInfo> page = baseMapper.selectPage(pageParam, queryWrapper);
page.getRecords().forEach(item -> {
item.setActivityTypeString(item.getActivityType().getComment());
});
return page;
}
/**
* 获取活动规则
*
* @param activityId 当前id
* @return 返回集合
*/
@Override
public Map<String, Object> findActivityRuleList(Long activityId) {
Map<String, Object> result = new HashMap<>();
// 活动信息列表
List<ActivityRule> activityInfoList = activityRuleMapper.selectList(
Wrappers.<ActivityRule>lambdaQuery().eq(ActivityRule::getActivityId, activityId)
);
result.put("activityRuleList", activityInfoList);
// 查询活动列表
List<ActivitySku> activitySkuList = activitySkuMapper.selectList(
Wrappers.<ActivitySku>lambdaQuery().eq(ActivitySku::getActivityId, activityId)
);
List<Long> skuIdList = activitySkuList.stream().map(ActivitySku::getSkuId).collect(Collectors.toList());
// 通过远程调用根据skuId得到商品信息
List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoList(skuIdList).getData();
result.put("skuInfoList", skuInfoList);
return result;
}
/**
* 新增活动规则
*
* @param vo 活动规则
*/
@Override
public void saveActivityRule(ActivityRuleVo vo) {
Long activityId = vo.getActivityId();
List<ActivityRule> activityRuleList = vo.getActivityRuleList();
List<ActivitySku> activitySkuList = vo.getActivitySkuList();
// 根据id查询活动信息
ActivityInfo activityInfo = getById(activityId);
// 删除之前规则数据
activityRuleMapper.delete(Wrappers.<ActivityRule>lambdaQuery().eq(ActivityRule::getActivityId, activityId));
activitySkuMapper.delete(Wrappers.<ActivitySku>lambdaQuery().eq(ActivitySku::getActivityId, activityId));
// 获取规则列表数据
activityRuleList.forEach(activityRule -> {
activityRule.setActivityId(activityId);
activityRule.setActivityType(activityInfo.getActivityType());
activityRuleMapper.insert(activityRule);
});
// 获取规则范围数据
activitySkuList.forEach(activitySku -> {
activitySku.setActivityId(activityId);
activitySkuMapper.insert(activitySku);
});
}
/**
* 根据关键字获取sku列表活动使用
*
* @param keyword 关键字
* @return 活动列表
*/
@Override
public List<SkuInfo> findSkuInfoByKeyword(String keyword) {
// 根据关键字查询sku匹配内容
List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoByKeyword(keyword).getData();
if (!skuInfoList.isEmpty()) {
List<Long> skuIdList = skuInfoList.stream().map(SkuInfo::getId).collect(Collectors.toList());
// 判断添加商品之前是否参加过活动
List<Long> existSkuIdList = baseMapper.selectSkuIdListExist(skuIdList);
// 如果参加的话就剔除
skuInfoList.removeIf(skuInfo -> existSkuIdList.contains(skuInfo.getId()));
// 返回结果
return skuInfoList;
}
return skuInfoList;
}
/**
* * 根据skuId列表获取促销信息
*
* @param skuIdList 列表
* @return Map<Long, List < String>>
*/
@Override
public Map<Long, List<String>> findActivity(List<Long> skuIdList) {
Map<Long, List<String>> result = new HashMap<>();
// skuIdList遍历得到每个skuId
skuIdList.forEach(skuId -> {
// 根据skuId进行查询查询sku对应活动里面规则列表
List<ActivityRule> activityRuleList =
baseMapper.findActivityRule(skuId);
// 数据封装规则名称
if (!CollectionUtils.isEmpty(activityRuleList)) {
List<String> ruleList = new ArrayList<>();
// 把规则名称处理
for (ActivityRule activityRule : activityRuleList) {
ruleList.add(module.getRuleDesc(activityRule));
}
result.put(skuId, ruleList);
}
});
return result;
}
/**
* * 根据skuId获取促销与优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 营销的活动
*/
@Override
public Map<String, Object> findActivityAndCoupon(Long skuId, Long userId) {
// 一个sku只能有一个促销活动一个活动有多个活动规则如满赠满100送10满500送50
List<ActivityRule> activityRuleList = module.findActivityRuleList(skuId);
// 获取优惠券信息
List<CouponInfo> couponInfoList = couponInfoService.findCouponInfo(skuId, userId);
Map<String, Object> map = new HashMap<>();
map.put("activityRuleList", activityRuleList);
map.put("couponInfoList", couponInfoList);
return map;
}
/**
* * 获取购物车满足条件的促销与优惠券信息
*
* @param cartInfoList 购物车信息列表
* @param userId 用户ID
* @return OrderConfirmVo
*/
@Override
public OrderConfirmVo findCartActivityAndCoupon(List<CartInfo> cartInfoList, Long userId) {
// 获取购物车每个购物车参与活动根据活动规则分组
List<CartInfoVo> carInfoVoList = module.findCartActivityList(cartInfoList);
// 促销活动优惠的总金额
BigDecimal activityReduceAmount = carInfoVoList.stream()
.filter(carInfoVo -> null != carInfoVo.getActivityRule())
.map(carInfoVo -> carInfoVo.getActivityRule().getReduceAmount())
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 购物车可使用的优惠券列表
List<CouponInfo> couponInfoList = couponInfoService.findCartCouponInfo(cartInfoList, userId);
// 优惠券可优惠的总金额一次购物只能使用一张优惠券
BigDecimal couponReduceAmount = new BigDecimal(0);
if (!CollectionUtils.isEmpty(couponInfoList)) {
couponReduceAmount = couponInfoList.stream()
.filter(couponInfo -> couponInfo.getIsOptimal().intValue() == 1)
.map(couponInfo -> couponInfo.getAmount())
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
// 购物车总金额
BigDecimal carInfoTotalAmount = cartInfoList.stream()
.filter(cartInfo -> cartInfo.getIsChecked() == 1)
.map(cartInfo -> cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 购物车原始总金额
BigDecimal originalTotalAmount = cartInfoList.stream()
.filter(cartInfo -> cartInfo.getIsChecked() == 1)
.map(cartInfo -> cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum())))
.reduce(BigDecimal.ZERO, BigDecimal::add);
// 最终总金额
BigDecimal totalAmount = originalTotalAmount.subtract(activityReduceAmount).subtract(couponReduceAmount);
OrderConfirmVo orderTradeVo = new OrderConfirmVo();
orderTradeVo.setCarInfoVoList(carInfoVoList);
orderTradeVo.setActivityReduceAmount(activityReduceAmount);
orderTradeVo.setCouponInfoList(couponInfoList);
orderTradeVo.setCouponReduceAmount(couponReduceAmount);
orderTradeVo.setOriginalTotalAmount(originalTotalAmount);
orderTradeVo.setTotalAmount(totalAmount);
return orderTradeVo;
}
}

View File

@ -1,20 +1,226 @@
package com.atguigu.ssyx.activity.service.impl;
import com.atguigu.ssyx.activity.mapper.CouponInfoMapper;
import com.atguigu.ssyx.activity.mapper.CouponRangeMapper;
import com.atguigu.ssyx.activity.service.CouponInfoService;
import com.atguigu.ssyx.activity.service.module.CouponInfoServiceModule;
import com.atguigu.ssyx.client.product.ProductFeignClient;
import com.atguigu.ssyx.enums.CouponRangeType;
import com.atguigu.ssyx.model.activity.CouponInfo;
import com.atguigu.ssyx.model.activity.CouponRange;
import com.atguigu.ssyx.model.base.BaseEntity;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.model.product.Category;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.atguigu.ssyx.vo.activity.CouponRuleVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* 优惠券信息 服务实现类
* </p>
*
* @author bunny
* @since 2024-04-04
*/
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class CouponInfoServiceImpl extends ServiceImpl<CouponInfoMapper, CouponInfo> implements CouponInfoService {
@Autowired
private CouponRangeMapper couponRangeMapper;
@Autowired
private CouponInfoMapper couponInfoMapper;
@Autowired
private ProductFeignClient productFeignClient;
@Autowired
private CouponInfoServiceModule module;
/**
* * 获取分页列表
*
* @param pageParam 查询分页条件
* @return 分页结果
*/
@Override
public IPage<CouponInfo> selectPage(Page<CouponInfo> pageParam) {
Page<CouponInfo> page = page(pageParam);
List<CouponInfo> pageRecords = page.getRecords();
pageRecords.forEach(record -> {
record.setCouponTypeString(record.getCouponType().getComment());
CouponRangeType rangeType = record.getRangeType();
if (rangeType != null) {
record.setRangeTypeString(rangeType.getComment());
}
});
return page;
}
/**
* 获取优惠券
*
* @param id 优惠卷Id
* @return 优惠卷
*/
@Override
public CouponInfo getCouponInfo(Long id) {
CouponInfo couponInfo = getById(id);
couponInfo.setCouponTypeString(couponInfo.getCouponType().getComment());
// 使用范围
if (couponInfo.getRangeType() != null) {
couponInfo.setRangeTypeString(couponInfo.getRangeType().getComment());
}
return couponInfo;
}
/**
* 获取优惠券信息
*
* @param id 优惠卷Id
* @return Map<String, Object>
*/
@Override
public Map<String, Object> findCouponRuleList(Long id) {
Map<String, Object> result = new HashMap<>();
CouponInfo couponInfo = getById(id);
// 根据Id查询 couponRange 列表
List<CouponRange> couponRangeList = couponRangeMapper.selectList(Wrappers.<CouponRange>lambdaQuery().eq(CouponRange::getCouponId, id));
List<Long> rangeIdList = couponRangeList.stream().map(CouponRange::getRangeId).collect(Collectors.toList());
// 分别判断封装不同数据
if (!CollectionUtils.isEmpty(rangeIdList)) {
if (couponInfo.getRangeType() == CouponRangeType.SKU) {
List<SkuInfo> skuInfoList = productFeignClient.findSkuInfoList(rangeIdList).getData();
result.put("skuInfoList", skuInfoList);
}
if (couponInfo.getRangeType() == CouponRangeType.CATEGORY) {
List<Category> categoryList = productFeignClient.findCategoryList(rangeIdList);
result.put("categoryList", categoryList);
}
}
return result;
}
/**
* * 新增活动
*
* @param vo 新的活动
*/
@Override
public void saveCouponRule(CouponRuleVo vo) {
// 删除之前的内容
couponRangeMapper.delete(Wrappers.<CouponRange>lambdaQuery().eq(CouponRange::getCouponId, vo.getCouponId()));
// 查询优惠卷基本信息
CouponInfo couponInfo = getById(vo.getCouponId());
couponInfo.setRangeType(vo.getRangeType());
couponInfo.setConditionAmount(vo.getConditionAmount());
couponInfo.setAmount(vo.getAmount());
couponInfo.setConditionAmount(vo.getConditionAmount());
couponInfo.setRangeDesc(vo.getRangeDesc());
// 添加优惠卷信息
updateById(couponInfo);
// 添加优惠卷新的规则数据
List<CouponRange> couponRangeList = vo.getCouponRangeList();
couponRangeList.forEach(couponRange -> {
couponRange.setCouponId(vo.getCouponId());
couponRangeMapper.insert(couponRange);
});
}
@Override
public List<CouponInfo> findCouponByKeyword(String keyword) {
// 模糊查询
QueryWrapper<CouponInfo> couponInfoQueryWrapper = new QueryWrapper<>();
couponInfoQueryWrapper.like("coupon_name", keyword);
return list(couponInfoQueryWrapper);
}
/**
* * 获取优惠券信息
*
* @param skuId 商品id
* @param userId 用户id
* @return 优惠卷列表
*/
@Override
public List<CouponInfo> findCouponInfo(Long skuId, Long userId) {
SkuInfo skuInfo = productFeignClient.getSkuInfo(skuId).getData();
if (null == skuInfo) return new ArrayList<>();
// 根据skuId获取活动规则数据
return couponInfoMapper.selectCouponInfoList(skuInfo.getId(), skuInfo.getCategoryId(), userId);
}
/**
* * 购物车可使用的优惠券列表
*
* @param cartInfoList 购物车列表信息
* @param userId 用户ID
* @return List<CouponInfo>
*/
@Override
public List<CouponInfo> findCartCouponInfo(List<CartInfo> cartInfoList, Long userId) {
// 获取全部用户优惠券
List<CouponInfo> userAllCouponInfoList = baseMapper.selectCartCouponInfoList(userId);
if (CollectionUtils.isEmpty(userAllCouponInfoList)) return null;
// 获取优惠券id列表
List<Long> couponIdList = userAllCouponInfoList.stream().map(BaseEntity::getId).collect(Collectors.toList());
// 查询优惠券对应的范围
List<CouponRange> couponRangesList = couponRangeMapper.selectList(new LambdaQueryWrapper<CouponRange>().in(CouponRange::getCouponId, couponIdList));
// 获取优惠券id对应的满足使用范围的购物项skuId列表
Map<Long, List<Long>> couponIdToSkuIdMap = module.findCouponIdToSkuIdMap(cartInfoList, couponRangesList);
// 优惠后减少金额
BigDecimal reduceAmount = new BigDecimal("0");
// 记录最优优惠券
CouponInfo optimalCouponInfo = null;
for (CouponInfo couponInfo : userAllCouponInfoList) {
if (CouponRangeType.ALL == couponInfo.getRangeType()) {
// 全场通用
// 判断是否满足优惠使用门槛
// 计算购物车商品的总价
BigDecimal totalAmount = computeTotalAmount(cartInfoList);
if (totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= 0) {
couponInfo.setIsSelect(1);
}
} else {
// 优惠券id对应的满足使用范围的购物项skuId列表
List<Long> skuIdList = couponIdToSkuIdMap.get(couponInfo.getId());
// 当前满足使用范围的购物项
List<CartInfo> currentCartInfoList = cartInfoList.stream().filter(cartInfo -> skuIdList.contains(cartInfo.getSkuId())).collect(Collectors.toList());
BigDecimal totalAmount = computeTotalAmount(currentCartInfoList);
if (totalAmount.subtract(couponInfo.getConditionAmount()).doubleValue() >= 0) {
couponInfo.setIsSelect(1);
}
}
if (couponInfo.getIsSelect() == 1 && couponInfo.getAmount().subtract(reduceAmount).doubleValue() > 0) {
reduceAmount = couponInfo.getAmount();
optimalCouponInfo = couponInfo;
}
}
if (null != optimalCouponInfo) {
optimalCouponInfo.setIsOptimal(1);
}
return userAllCouponInfoList;
}
private BigDecimal computeTotalAmount(List<CartInfo> cartInfoList) {
BigDecimal total = new BigDecimal("0");
for (CartInfo cartInfo : cartInfoList) {
// 是否选中
if (cartInfo.getIsChecked() == 1) {
BigDecimal itemTotal = cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum()));
total = total.add(itemTotal);
}
}
return total;
}
}

View File

@ -0,0 +1,59 @@
package com.atguigu.ssyx.activity.service.impl;
import com.atguigu.ssyx.activity.mapper.SecKillMapper;
import com.atguigu.ssyx.activity.service.SecKillService;
import com.atguigu.ssyx.model.activity.Seckill;
import com.atguigu.ssyx.vo.activity.SeckillQueryVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
/**
* <p>
* 秒杀活动 服务实现类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Service
public class SeckillServiceImpl extends ServiceImpl<SecKillMapper, Seckill> implements SecKillService {
/**
* * 获取分页列表
*
* @param pageParam 分页参数
* @param vo 秒杀信息
* @return 分页结果
*/
@Override
public IPage<Seckill> selectPage(Page<Seckill> pageParam, SeckillQueryVo vo) {
Integer status = vo.getStatus();
String title = vo.getTitle();
LambdaQueryWrapper<Seckill> wrapper = new LambdaQueryWrapper<>();
if (!StringUtils.isEmpty(status)) {
wrapper.eq(Seckill::getStatus, status);
}
if (!StringUtils.isEmpty(title)) {
wrapper.like(Seckill::getTitle, title);
}
return baseMapper.selectPage(pageParam, wrapper);
}
/**
* * 更新状态
*
* @param id Id
* @param status 状态值
*/
@Override
public void updateStatus(Long id, Integer status) {
Seckill seckill = new Seckill();
seckill.setStatus(status);
seckill.setId(id);
this.updateById(seckill);
}
}

View File

@ -0,0 +1,20 @@
package com.atguigu.ssyx.activity.service.impl;
import com.atguigu.ssyx.activity.mapper.SecKillSkuNoticeMapper;
import com.atguigu.ssyx.activity.service.SecKillSkuNoticeService;
import com.atguigu.ssyx.model.activity.SeckillSkuNotice;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 秒杀商品通知订阅 服务实现类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Service
public class SeckillSkuNoticeServiceImpl extends ServiceImpl<SecKillSkuNoticeMapper, SeckillSkuNotice> implements SecKillSkuNoticeService {
}

View File

@ -0,0 +1,37 @@
package com.atguigu.ssyx.activity.service.impl;
import com.atguigu.ssyx.activity.mapper.SecKillSkuMapper;
import com.atguigu.ssyx.activity.service.SecKillSkuService;
import com.atguigu.ssyx.model.activity.SeckillSku;
import com.atguigu.ssyx.vo.activity.SeckillSkuVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* <p>
* 秒杀活动商品关联 服务实现类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Service
public class SeckillSkuServiceImpl extends ServiceImpl<SecKillSkuMapper, SeckillSku> implements SecKillSkuService {
@Autowired
private SecKillSkuMapper seckillSkuMapper;
/**
* * 获取分页列表
*
* @param pageParam 当前页码信息
* @param vo 查询对象
* @return 分页结果
*/
@Override
public IPage<SeckillSku> selectPage(Page<SeckillSku> pageParam, SeckillSkuVo vo) {
return page(pageParam);
}
}

View File

@ -0,0 +1,26 @@
package com.atguigu.ssyx.activity.service.impl;
import com.atguigu.ssyx.activity.mapper.SeckillTimeMapper;
import com.atguigu.ssyx.activity.service.SeckillTimeService;
import com.atguigu.ssyx.model.activity.SeckillTime;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
@Service
public class SeckillTimeServiceImpl extends ServiceImpl<SeckillTimeMapper, SeckillTime> implements SeckillTimeService {
/**
* * 更新状态
*
* @param id 当前Id
* @param status 当前状态
*/
@Override
public void updateStatus(Long id, Integer status) {
SeckillTime seckillTime = new SeckillTime();
seckillTime.setStatus(status);
seckillTime.setId(id);
updateById(seckillTime);
}
}

View File

@ -0,0 +1,20 @@
package com.atguigu.ssyx.activity.service.impl;
import com.atguigu.ssyx.activity.mapper.SkuInfoMapper;
import com.atguigu.ssyx.activity.service.SkuInfoService;
import com.atguigu.ssyx.model.product.SkuInfo;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* sku信息 服务实现类
* </p>
*
* @author bunny
* @since 2024-04-06
*/
@Service
public class SkuInfoServiceImpl extends ServiceImpl<SkuInfoMapper, SkuInfo> implements SkuInfoService {
}

View File

@ -0,0 +1,245 @@
package com.atguigu.ssyx.activity.service.module;
import com.atguigu.ssyx.activity.mapper.ActivityInfoMapper;
import com.atguigu.ssyx.activity.mapper.ActivityRuleMapper;
import com.atguigu.ssyx.enums.ActivityType;
import com.atguigu.ssyx.model.activity.ActivityRule;
import com.atguigu.ssyx.model.activity.ActivitySku;
import com.atguigu.ssyx.model.order.CartInfo;
import com.atguigu.ssyx.vo.order.CartInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class ActivityInfoServiceModule {
@Autowired
private ActivityInfoMapper activityInfoMapper;
@Autowired
private ActivityRuleMapper activityRuleMapper;
// 根据skuId获取活动规则数据
public List<ActivityRule> findActivityRuleList(Long skuId) {
List<ActivityRule> activityRuleList = activityInfoMapper.findActivityRule(skuId);
activityRuleList.forEach(activityRule -> {
String ruleDesc = this.getRuleDesc(activityRule);
activityRule.setRuleDesc(ruleDesc);
});
return activityRuleList;
}
// 构造规则名称的方法
public String getRuleDesc(ActivityRule activityRule) {
ActivityType activityType = activityRule.getActivityType();
StringBuilder ruleDesc = new StringBuilder();
if (activityType == ActivityType.FULL_REDUCTION) {
ruleDesc
.append("")
.append(activityRule.getConditionAmount())
.append("元减")
.append(activityRule.getBenefitAmount())
.append("");
} else {
ruleDesc
.append("")
.append(activityRule.getConditionNum())
.append("元打")
.append(activityRule.getBenefitDiscount())
.append("");
}
return ruleDesc.toString();
}
// 获取购物车每个购物车参与活动根据活动规则分组
public List<CartInfoVo> findCartActivityList(List<CartInfo> cartInfoList) {
// 创建最终返回集合
List<CartInfoVo> carInfoVoList = new ArrayList<>();
// 获取所有skuId
List<Long> skuIdList = cartInfoList.stream().map(CartInfo::getSkuId).collect(Collectors.toList());
// 根据所有skuId获取参与活动
List<ActivitySku> activitySkuList = activityInfoMapper.selectCartActivity(skuIdList);
Map<Long, Set<Long>> activityIdToSkuIdListMap = activitySkuList.stream().collect(Collectors.groupingBy(
ActivitySku::getActivityId, Collectors.mapping(ActivitySku::getSkuId, Collectors.toSet())));
// 获取活动里面规则数据
Set<Long> activityIdSet = activitySkuList.stream().map(ActivitySku::getActivityId).collect(Collectors.toSet());
Map<Long, List<ActivityRule>> activityIdToActivityRuleListMap = new HashMap<>();
if (!CollectionUtils.isEmpty(activityIdSet)) {
LambdaQueryWrapper<ActivityRule> wrapper = new LambdaQueryWrapper<>();
wrapper.in(ActivityRule::getActivityId, activityIdSet);
wrapper.orderByDesc(ActivityRule::getConditionAmount, ActivityRule::getConditionAmount);
List<ActivityRule> activityRuleList = activityRuleMapper.selectList(wrapper);
activityIdToActivityRuleListMap = activityRuleList.stream().collect(Collectors.groupingBy(ActivityRule::getActivityId));
}
// 第三步根据活动汇总购物项相同活动的购物项为一组显示在页面并且计算最优优惠金额
// 记录有活动的购物项skuId
Set<Long> activitySkuIdSet = new HashSet<>();
if (!CollectionUtils.isEmpty(activityIdToSkuIdListMap)) {
for (Map.Entry<Long, Set<Long>> entry : activityIdToSkuIdListMap.entrySet()) {
Long activityId = entry.getKey();
// 当前活动对应的购物项skuId列表
Set<Long> currentActivitySkuIdSet = entry.getValue();
// 当前活动对应的购物项列表
List<CartInfo> currentActivityCartInfoList = cartInfoList.stream().filter(cartInfo -> currentActivitySkuIdSet.contains(cartInfo.getSkuId())).collect(Collectors.toList());
// 当前活动的总金额
BigDecimal activityTotalAmount = this.computeTotalAmount(currentActivityCartInfoList);
// 当前活动的购物项总个数
Integer activityTotalNum = this.computeCartNum(currentActivityCartInfoList);
// 计算当前活动对应的最优规则
// 活动当前活动对应的规则
List<ActivityRule> currentActivityRuleList = activityIdToActivityRuleListMap.get(activityId);
ActivityType activityType = currentActivityRuleList.get(0).getActivityType();
ActivityRule optimalActivityRule = null;
if (activityType == ActivityType.FULL_REDUCTION) {
optimalActivityRule = this.computeFullReduction(activityTotalAmount, currentActivityRuleList);
} else {
optimalActivityRule = this.computeFullDiscount(activityTotalNum, activityTotalAmount, currentActivityRuleList);
}
// 同一活动对应的购物项列表与对应优化规则
CartInfoVo carInfoVo = new CartInfoVo();
carInfoVo.setCartInfoList(currentActivityCartInfoList);
carInfoVo.setActivityRule(optimalActivityRule);
carInfoVoList.add(carInfoVo);
// 记录
activitySkuIdSet.addAll(currentActivitySkuIdSet);
}
}
// 第四步无活动的购物项每一项一组
skuIdList.removeAll(activitySkuIdSet);
if (!CollectionUtils.isEmpty(skuIdList)) {
// 获取skuId对应的购物项
Map<Long, CartInfo> skuIdToCartInfoMap = cartInfoList.stream().collect(Collectors.toMap(CartInfo::getSkuId, CartInfo -> CartInfo));
for (Long skuId : skuIdList) {
CartInfoVo carInfoVo = new CartInfoVo();
carInfoVo.setActivityRule(null);
List<CartInfo> currentCartInfoList = new ArrayList<>();
currentCartInfoList.add(skuIdToCartInfoMap.get(skuId));
carInfoVo.setCartInfoList(currentCartInfoList);
carInfoVoList.add(carInfoVo);
}
}
return carInfoVoList;
}
/**
* 计算满量打折最优规则
*
* @param activityRuleList //该活动规则skuActivityRuleList数据已经按照优惠折扣从大到小排序了
*/
private ActivityRule computeFullDiscount(Integer totalNum, BigDecimal totalAmount, List<ActivityRule> activityRuleList) {
ActivityRule optimalActivityRule = null;
// 该活动规则skuActivityRuleList数据已经按照优惠金额从大到小排序了
for (ActivityRule activityRule : activityRuleList) {
// 如果订单项购买个数大于等于满减件数则优化打折
if (totalNum >= activityRule.getConditionNum()) {
BigDecimal skuDiscountTotalAmount = totalAmount.multiply(activityRule.getBenefitDiscount().divide(new BigDecimal("10")));
BigDecimal reduceAmount = totalAmount.subtract(skuDiscountTotalAmount);
activityRule.setReduceAmount(reduceAmount);
optimalActivityRule = activityRule;
break;
}
}
if (null == optimalActivityRule) {
// 如果没有满足条件的取最小满足条件的一项
optimalActivityRule = activityRuleList.get(activityRuleList.size() - 1);
optimalActivityRule.setReduceAmount(new BigDecimal("0"));
optimalActivityRule.setSelectType(1);
String ruleDesc = "" +
optimalActivityRule.getConditionNum() +
"元打" +
optimalActivityRule.getBenefitDiscount() +
"折,还差" +
(totalNum - optimalActivityRule.getConditionNum()) +
"";
optimalActivityRule.setRuleDesc(ruleDesc);
} else {
String ruleDesc = "" +
optimalActivityRule.getConditionNum() +
"元打" +
optimalActivityRule.getBenefitDiscount() +
"折,已减" +
optimalActivityRule.getReduceAmount() +
"";
optimalActivityRule.setRuleDesc(ruleDesc);
optimalActivityRule.setSelectType(2);
}
return optimalActivityRule;
}
/**
* 计算满减最优规则
*
* @param activityRuleList //该活动规则skuActivityRuleList数据已经按照优惠金额从大到小排序了
*/
private ActivityRule computeFullReduction(BigDecimal totalAmount, List<ActivityRule> activityRuleList) {
ActivityRule optimalActivityRule = null;
// 该活动规则skuActivityRuleList数据已经按照优惠金额从大到小排序了
for (ActivityRule activityRule : activityRuleList) {
// 如果订单项金额大于等于满减金额则优惠金额
if (totalAmount.compareTo(activityRule.getConditionAmount()) > -1) {
// 优惠后减少金额
activityRule.setReduceAmount(activityRule.getBenefitAmount());
optimalActivityRule = activityRule;
break;
}
}
if (null == optimalActivityRule) {
// 如果没有满足条件的取最小满足条件的一项
optimalActivityRule = activityRuleList.get(activityRuleList.size() - 1);
optimalActivityRule.setReduceAmount(new BigDecimal("0"));
optimalActivityRule.setSelectType(1);
String ruleDesc = "" +
optimalActivityRule.getConditionAmount() +
"元减" +
optimalActivityRule.getBenefitAmount() +
"元,还差" +
totalAmount.subtract(optimalActivityRule.getConditionAmount()) +
"";
optimalActivityRule.setRuleDesc(ruleDesc);
} else {
String ruleDesc = "" +
optimalActivityRule.getConditionAmount() +
"元减" +
optimalActivityRule.getBenefitAmount() +
"元,已减" +
optimalActivityRule.getReduceAmount() +
"";
optimalActivityRule.setRuleDesc(ruleDesc);
optimalActivityRule.setSelectType(2);
}
return optimalActivityRule;
}
private BigDecimal computeTotalAmount(List<CartInfo> cartInfoList) {
BigDecimal total = new BigDecimal("0");
for (CartInfo cartInfo : cartInfoList) {
// 是否选中
if (cartInfo.getIsChecked() == 1) {
BigDecimal itemTotal = cartInfo.getCartPrice().multiply(new BigDecimal(cartInfo.getSkuNum()));
total = total.add(itemTotal);
}
}
return total;
}
private int computeCartNum(List<CartInfo> cartInfoList) {
int total = 0;
for (CartInfo cartInfo : cartInfoList) {
// 是否选中
if (cartInfo.getIsChecked() == 1) {
total += cartInfo.getSkuNum();
}
}
return total;
}
}

View File

@ -0,0 +1,42 @@
package com.atguigu.ssyx.activity.service.module;
import com.atguigu.ssyx.enums.CouponRangeType;
import com.atguigu.ssyx.model.activity.CouponRange;
import com.atguigu.ssyx.model.order.CartInfo;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.stream.Collectors;
@Component
public class CouponInfoServiceModule {
@NotNull
private static Set<Long> getLongs(List<CartInfo> cartInfoList, Map.Entry<Long, List<CouponRange>> entry) {
List<CouponRange> couponRangeList = entry.getValue();
Set<Long> skuIdSet = new HashSet<>();
for (CartInfo cartInfo : cartInfoList) {
for (CouponRange couponRange : couponRangeList) {
if (CouponRangeType.SKU == couponRange.getRangeType() && couponRange.getRangeId() == cartInfo.getSkuId().intValue()) {
skuIdSet.add(cartInfo.getSkuId());
} else if (CouponRangeType.CATEGORY == couponRange.getRangeType() && couponRange.getRangeId() == cartInfo.getCategoryId().intValue()) {
skuIdSet.add(cartInfo.getSkuId());
}
}
}
return skuIdSet;
}
public Map<Long, List<Long>> findCouponIdToSkuIdMap(List<CartInfo> cartInfoList, List<CouponRange> couponRangesList) {
Map<Long, List<Long>> couponIdToSkuIdMap = new HashMap<>();
// 优惠券id对应的范围列表
Map<Long, List<CouponRange>> couponIdToCouponRangeListMap = couponRangesList.stream().collect(Collectors.groupingBy(couponRange -> couponRange.getCouponId()));
for (Map.Entry<Long, List<CouponRange>> entry : couponIdToCouponRangeListMap.entrySet()) {
Long couponId = entry.getKey();
Set<Long> skuIdSet = getLongs(cartInfoList, entry);
couponIdToSkuIdMap.put(couponId, new ArrayList<>(skuIdSet));
}
return couponIdToSkuIdMap;
}
}

View File

@ -27,21 +27,11 @@ spring:
time-zone: GMT+8
mybatis-plus:
type-aliases-package: com.atguigu.model # 配置每个包前缀
type-enums-package: com.atguigu.ssyx.enums # 加上枚举类型
mapper-locations: classpath:mapper/*.xml
configuration:
map-underscore-to-camel-case: true
auto-mapping-behavior: full
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 查看日志
global-config:
db-config:
# 设置表名前缀不用在每个tableName添加前缀
# table-prefix: t_
# 全局配置主键值方式
id-type: assign_id
logic-not-delete-value: 0 # 未删除默认为0
logic-delete-value: 1 # 删除
logic-delete-field: deleted # 全局配置逻辑删除
logging:
level:

View File

@ -1,5 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.ssyx.activity.mapper.ActivityInfoMapper">
<!-- 判断添加商品之前是否参加过活动 -->
<select id="selectSkuIdListExist" resultType="java.lang.Long">
select sku.sku_id
from activity_info info
inner join activity_sku sku on info.id = sku.activity_id
where sku.sku_id in
<foreach collection="skuIdList" item="skuId" open="(" close=")" separator=",">
#{skuId}
</foreach>
and now() between info.start_time and info.end_time
</select>
<!-- 根据skuId 查询对应规则列表 -->
<select id="findActivityRule" resultType="com.atguigu.ssyx.model.activity.ActivityRule">
select info.activity_type as activityType,
rule.id,
rule.activity_id,
rule.condition_amount,
rule.condition_num,
rule.benefit_amount,
rule.benefit_discount
from activity_info info
inner join activity_sku sku on sku.activity_id = info.id
inner join activity_rule rule on rule.activity_id = info.id
where sku.sku_id = #{skuId}
and now() between info.start_time and info.end_time
order by rule.condition_amount desc, rule.condition_num desc
</select>
<!-- 根据所有skuId获取参与活动 -->
<select id="selectCartActivity" resultType="com.atguigu.ssyx.model.activity.ActivitySku">
SELECT *
FROM activity_info info
INNER JOIN activity_sku sku ON info.id = sku.activity_id
WHERE sku.id IN
<foreach collection="skuIdList" item="item" open="(" close=")" separator=",">
#{item}
</foreach>
AND NOW() BETWEEN info.start_time
AND info.end_time
</select>
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.ssyx.activity.mapper.ActivityRuleMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.ssyx.activity.mapper.ActivitySkuMapper">
</mapper>

View File

@ -2,4 +2,50 @@
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.ssyx.activity.mapper.CouponInfoMapper">
<!-- 根据skuId获取活动规则数据 -->
<select id="selectCouponInfoList" resultType="com.atguigu.ssyx.model.activity.CouponInfo">
select info.id
, info.coupon_type
, info.coupon_name
, info.amount
, info.condition_amount
, info.start_time
, info.end_time
, info.range_type
, info.range_desc
, info.publish_count
, info.per_limit
, info.use_count
, info.receive_count
, info.expire_time
, info.publish_status
, info.create_time
, info.update_time
, info.is_deleted
, cuse.coupon_status
from coupon_info info
left join coupon_range crange on crange.coupon_id = info.id
left join coupon_use cuse on cuse.coupon_id = info.id and cuse.user_id = #{userId}
where (
info.range_type = 1
or (crange.range_type = 2 and crange.range_id = #{skuId})
or (crange.range_type = 3 and crange.range_id = #{categoryId})
)
and now() between info.start_time and info.end_time
order by info.amount desc
</select>
<!-- 获取用户全部优惠券 -->
<select id="selectCartCouponInfoList" resultType="com.atguigu.ssyx.model.activity.CouponInfo">
select
info.id,info.coupon_type,info.coupon_name,info.amount,info.condition_amount,info.start_time,info.end_time,info.range_type,info.range_desc,info.publish_count,info.per_limit,info.use_count,info.receive_count,info.expire_time,info.publish_status,info.create_time,info.update_time,info.is_deleted
,cuse.coupon_status
from coupon_use cuse
left join coupon_info info on cuse.coupon_id = info.id
<where>
and cuse.user_id = #{userId}
and info.expire_time >= now()
</where>
order by info.amount desc
</select>
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
<mapper namespace="com.atguigu.ssyx.activity.mapper.CouponRangeMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.ssyx.activity.mapper.SecKillMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.ssyx.activity.mapper.SecKillSkuNoticeMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.ssyx.activity.mapper.SecKillSkuMapper">
</mapper>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.atguigu.ssyx.activity.mapper.SeckillTimeMapper">
</mapper>

Some files were not shown because too many files have changed in this diff Show More