diff --git a/README.md b/README.md index 733cafd4..2ec84fdb 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ ## Lilishop B2B2C商城系统 +##### 开源不易,如有帮助请点Star +[![star](https://gitee.com/beijing_hongye_huicheng/lilishop/badge/star.svg?theme=dark)](https://gitee.com/beijing_hongye_huicheng/lilishop/stargazers) + + ### 介绍 **官网**:https://pickmall.cn @@ -60,21 +64,24 @@ Lilishop 是一款Java开发,基于SpringBoot的B2B2C多用户商城,前端 `git clone https://gitee.com/beijing_hongye_huicheng/docker.git ` ##### 部署基础环境 `docker-compose up -d` + ##### 部署应用 `docker-compose -f docker-compose-application.yml up -d` +PS:单独部署的话,数据库文件访问这里:https://gitee.com/beijing_hongye_huicheng/docker/tree/master/init/mysql + ##### 各个地址 | API | 地址 | | -------------- | --------------- | -| 买家api | http://127.0.0.1:8888 | -| 商家api | http://127.0.0.1:8889 | -| 管理端api | http://127.0.0.1:8887 | -| 通用api | http://127.0.0.1:8890 | +| 买家API | http://127.0.0.1:8888 | +| 商家API | http://127.0.0.1:8889 | +| 管理端API | http://127.0.0.1:8887 | +| 通用API | http://127.0.0.1:8890 | -| 演示 | 地址 | +| 前端演示 | 地址 | | -------------- | --------------- | | PC | http://127.0.0.1:10000 | | WAP | http://127.0.0.1:10001 | @@ -83,6 +90,44 @@ Lilishop 是一款Java开发,基于SpringBoot的B2B2C多用户商城,前端 + + +### 功能列表 + + + +#### 平台功能 + +![平台功能](https://pickmall.cn/assets/imgs/other/managerList.jpg) + + + +#### 商家端功能 + +![商家端功能](https://pickmall.cn/assets/imgs/other/storeList.jpg) + + + + + +### 功能展示 + + + +#### 移动端 + +移动端功能展示 + + + + + +#### 管理端 + +管理端功能展示 + + + ### 技术选型 ##### Java后台 @@ -136,125 +181,35 @@ Lilishop 是一款Java开发,基于SpringBoot的B2B2C多用户商城,前端 | CSS预处理 | scss | | 地图引擎 | amap | - - -### 功能列表 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
运营后台功能
首页平台统计、待办事项、流量统计
会员会员列表
评价列表
积分历史
会员资金
充值记录
订单商品订单
订单售后
交易投诉
售后原因
收款流水
退款流水
商品商品列表
商品审核
商品分类
商品品牌
商品规格
计量单位
促销优惠券
秒杀活动
拼团活动
积分商品
积分分类
店铺店铺管理
店铺结算
店铺结算
店铺结算
店铺对账
运营店铺对账
PC端楼层装修
移动端楼层装修
分销管理
文章管理
意见反馈
站内信
短信管理
APP版本管理
统计会员统计
订单统计
商品统计
流量统计
设置用户管理
菜单管理
部门管理
系统设置
OSS资源
行政地区
物流公司
信任登录
支付设置
验证码管理
敏感词管理
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
店铺后台功能列表
首页店铺信息
待办事项
平台公告
商品商品发布
商品列表
店铺商品分类
订单商品订单
退货管理
退款管理
投诉管理
评价管理
财务财务对账
店铺结算
发票管理
促销拼团管理
秒杀活动
满额活动
优惠券
分销商品
统计商品统计
订单统计
设置配送模板
物流公司
店铺设置
自提点管理
系统消息
- ### 技术亮点 1.后端框架基于Springboot,构建基于maven,持久层使用MyBatisPlus。使用elasticsearch、redis、mongodb、rocketmq 等各种中间健。都是主流架构,轻松应对各种环境。 - + 2.支持集群、分布式,支持docker 轻松部署,解决各种复杂场景! - + 3.代码模块清晰,主要分为三端api(买家、卖家、管理),各端API互相隔离,自己鉴权,自己操作业务。 - + 4.使用阿里开源的RocketMQ,基于mq解决各种并发场景,解决事务一致性,解决搞并发延迟场景问题。 - + 5.项目使用多级缓存,应用不同场景,redis缓存业务数据、mongodb缓存关系型多对多关系问题、nginx缓存高频访问低频修改的页面。 - + 6.支持各种联合登陆,支持各种客户端的支付问题,灵活配置灵活开启。 - + 7.内置完善的楼层装修机制,各种拖拉拽,维护跳转页面或外网,即便是一个什么都不懂的运营也可以轻松掌握。 - + 8.内置阿里短信接口,可以在线申请短信模版。内置阿里oss系统,可以对文件执行各种操作。oss商家端资源相互隔离。 - + 10.强大的统计报表,统计效果,可以实现各个场景,包含在线人数,历史在线人数,活跃人数等信息。 - + 11.标准Api接口、提供swagger文档,快速二开。 - + 12.分布式调度任务中心,解决分布式定时任务多次执行问题。 - + 13.代码注释完善,快速上手。 - + 14.非移动端采用IView框架,各种自定义插件、选择器实现。移动端采用uniapp,一次编写,全端使用 - + 15.已经对接好各种第三方插件,支持各种复杂等联合登陆,联合支付等场景。 diff --git a/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java b/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java index 8a504ab7..f0e67719 100644 --- a/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java +++ b/consumer/src/main/java/cn/lili/timetask/handler/impl/promotion/PromotionEverydayExecute.java @@ -11,7 +11,6 @@ import cn.lili.modules.promotion.service.*; import cn.lili.timetask.handler.EveryDayExecute; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.mongodb.core.MongoTemplate; import org.springframework.data.mongodb.core.query.Criteria; @@ -59,11 +58,14 @@ public class PromotionEverydayExecute implements EveryDayExecute { public void execute() { Query query = new Query(); - query.addCriteria(Criteria.where("promotionStatus").ne(PromotionStatusEnum.END.name()).orOperator(Criteria.where("promotionStatus").ne(PromotionStatusEnum.CLOSE.name()))); +// 结束条件 活动关闭/活动结束 + query.addCriteria(Criteria.where("promotionStatus").ne(PromotionStatusEnum.END.name()) + .orOperator(Criteria.where("promotionStatus").ne(PromotionStatusEnum.CLOSE.name()))); query.addCriteria(Criteria.where("endTime").lt(new Date())); List promotionIds = new ArrayList<>(); + //关闭满减活动 List fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class); if (!fullDiscountVOS.isEmpty()) { List ids = new ArrayList<>(); @@ -80,9 +82,10 @@ public class PromotionEverydayExecute implements EveryDayExecute { fullDiscountService.update(this.getUpdatePromotionWrapper(ids)); promotionIds.addAll(ids); } - + //关闭拼团活动 List pintuanVOS = mongoTemplate.find(query, PintuanVO.class); if (!pintuanVOS.isEmpty()) { + //准备修改活动的id List ids = new ArrayList<>(); for (PintuanVO vo : pintuanVOS) { vo.setPromotionStatus(PromotionStatusEnum.END.name()); @@ -98,6 +101,7 @@ public class PromotionEverydayExecute implements EveryDayExecute { promotionIds.addAll(ids); } + //关闭优惠券活动 List couponVOS = mongoTemplate.find(query, CouponVO.class); if (!couponVOS.isEmpty()) { List ids = new ArrayList<>(); @@ -121,13 +125,22 @@ public class PromotionEverydayExecute implements EveryDayExecute { } + /** + * 获取促销修改查询条件 修改活动状态 + * @param ids + * @return + */ private UpdateWrapper getUpdatePromotionWrapper(List ids) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.in("id", ids); updateWrapper.set("promotion_status", PromotionStatusEnum.END.name()); return updateWrapper; } - + /** + * 获取商品的促销修改查询条件 修改商品状态 + * @param ids + * @return + */ private UpdateWrapper getUpdatePromotionGoodsWrapper(List ids) { UpdateWrapper updateWrapper = new UpdateWrapper<>(); updateWrapper.in("promotion_id", ids); diff --git a/consumer/src/main/java/cn/lili/trigger/executor/PromotionTimeTriggerExecutor.java b/consumer/src/main/java/cn/lili/trigger/executor/PromotionTimeTriggerExecutor.java index d3daf329..c0aee57d 100644 --- a/consumer/src/main/java/cn/lili/trigger/executor/PromotionTimeTriggerExecutor.java +++ b/consumer/src/main/java/cn/lili/trigger/executor/PromotionTimeTriggerExecutor.java @@ -12,7 +12,6 @@ import cn.lili.config.rocketmq.RocketmqCustomProperties; import cn.lili.modules.order.order.service.OrderService; import cn.lili.modules.promotion.entity.enums.PromotionStatusEnum; import cn.lili.modules.promotion.service.PromotionService; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -65,6 +64,7 @@ public class PromotionTimeTriggerExecutor implements TimeTriggerExecutor { } return; } + //拼团订单消息 PintuanOrderMessage pintuanOrderMessage = JSONUtil.toBean(JSONUtil.parseObj(object), PintuanOrderMessage.class); if (pintuanOrderMessage != null && pintuanOrderMessage.getPintuanId() != null) { log.info("拼团订单信息消费:{}", pintuanOrderMessage); diff --git a/framework/src/main/java/cn/lili/common/sms/impl/SmsUtilAliImplService.java b/framework/src/main/java/cn/lili/common/sms/impl/SmsUtilAliImplService.java index 2e2ec190..bfb58582 100644 --- a/framework/src/main/java/cn/lili/common/sms/impl/SmsUtilAliImplService.java +++ b/framework/src/main/java/cn/lili/common/sms/impl/SmsUtilAliImplService.java @@ -55,7 +55,6 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil { public void sendSmsCode(String mobile, VerificationEnums verificationEnums, String uuid) { String code = CommonUtil.getRandomNum(); - code = "111111"; switch (verificationEnums) { //如果某个模版需要自定义,则在此处进行调整 @@ -67,7 +66,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil { Map params = new HashMap<>(); params.put("code", code); cache.put(cacheKey(verificationEnums, mobile, uuid), code, 300L); - //this.sendSmsCode("北京宏业汇成科技有限公司",mobile, params, verificationEnums.getSmsTemplate()); + this.sendSmsCode("北京宏业汇成科技有限公司",mobile, params, "SMS_205755300"); break; } case UPDATE_PASSWORD: { @@ -80,7 +79,7 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil { Map params = new HashMap<>(); params.put("code", code); cache.put(cacheKey(verificationEnums, memberMobile, uuid), code, 300L); - //this.sendSmsCode("北京宏业汇成科技有限公司",mobile, params, verificationEnums.getSmsTemplate()); + this.sendSmsCode("北京宏业汇成科技有限公司",mobile, params, "SMS_205755297"); break; } //如果不是有效的验证码手段,则此处不进行短信操作 @@ -162,19 +161,22 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil { //设置参数添加短信签名 com.aliyun.dysmsapi20170525.Client client = this.createClient(); + System.out.println(smsSign.getBusinessLicense().substring(smsSign.getBusinessLicense().lastIndexOf(".") + 1)); + //营业执照 AddSmsSignRequest.AddSmsSignRequestSignFileList signFileList0 = new AddSmsSignRequest.AddSmsSignRequestSignFileList() .setFileContents(Base64Utils.encode(smsSign.getBusinessLicense())) .setFileSuffix(smsSign.getBusinessLicense().substring(smsSign.getBusinessLicense().lastIndexOf(".") + 1)); - AddSmsSignRequest.AddSmsSignRequestSignFileList signFileList1 = new AddSmsSignRequest.AddSmsSignRequestSignFileList() - .setFileContents(Base64Utils.encode(smsSign.getLicense())) - .setFileSuffix(smsSign.getLicense().substring(smsSign.getBusinessLicense().lastIndexOf(".") + 1)); + //授权委托书 +// AddSmsSignRequest.AddSmsSignRequestSignFileList signFileList1 = new AddSmsSignRequest.AddSmsSignRequestSignFileList() +// .setFileContents(Base64Utils.encode(smsSign.getLicense())) +// .setFileSuffix(smsSign.getLicense().substring(smsSign.getLicense().lastIndexOf(".") + 1)); + //添加短信签名 AddSmsSignRequest addSmsSignRequest = new AddSmsSignRequest() .setSignName(smsSign.getSignName()) .setSignSource(smsSign.getSignSource()) .setRemark(smsSign.getRemark()) .setSignFileList(java.util.Arrays.asList( - signFileList0, - signFileList1 + signFileList0 )); AddSmsSignResponse response = client.addSmsSign(addSmsSignRequest); if (!response.getBody().getCode().equals("OK")) { diff --git a/framework/src/main/java/cn/lili/common/token/base/generate/StoreTokenGenerate.java b/framework/src/main/java/cn/lili/common/token/base/generate/StoreTokenGenerate.java index 963eeb49..0496fcea 100644 --- a/framework/src/main/java/cn/lili/common/token/base/generate/StoreTokenGenerate.java +++ b/framework/src/main/java/cn/lili/common/token/base/generate/StoreTokenGenerate.java @@ -6,13 +6,11 @@ import cn.lili.common.security.enums.UserEnums; import cn.lili.common.token.Token; import cn.lili.common.token.TokenUtil; import cn.lili.common.token.base.AbstractTokenGenerate; -import cn.lili.common.enums.SwitchEnum; import cn.lili.modules.member.entity.dos.Member; import cn.lili.modules.member.service.MemberService; import cn.lili.modules.store.entity.dos.Store; import cn.lili.modules.store.service.StoreService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -37,10 +35,10 @@ public class StoreTokenGenerate extends AbstractTokenGenerate { public Token createToken(String username, Boolean longTerm) { // 生成token Member member = memberService.findByUsername(username); - if (member.getHaveStore().equals(SwitchEnum.CLOSE.name())) { + if (!member.getHaveStore()) { throw new ServiceException("该会员未开通店铺"); } - AuthUser user = new AuthUser(member.getUsername(), member.getId(),member.getNickName(), UserEnums.STORE); + AuthUser user = new AuthUser(member.getUsername(), member.getId(), member.getNickName(), UserEnums.STORE); LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(Store::getMemberId, member.getId()); Store store = storeService.getOne(queryWrapper); diff --git a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java index 2de787c3..257714ae 100644 --- a/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/search/serviceimpl/EsGoodsIndexServiceImpl.java @@ -24,7 +24,6 @@ import cn.lili.modules.search.repository.EsGoodsIndexRepository; import cn.lili.modules.search.service.EsGoodsIndexService; import cn.lili.modules.search.service.EsGoodsSearchService; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; -import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.assertj.core.util.IterableUtil; import org.elasticsearch.action.search.SearchResponse; @@ -44,6 +43,7 @@ import java.util.stream.Collectors; /** * 商品索引业务层实现 + * * @author paulG * @since 2020/10/14 **/ @@ -64,19 +64,26 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void addIndex(EsGoodsIndex goods) { + //索引名称拼接 String indexName = elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME; try { + //分词器分词 AnalyzeRequest analyzeRequest = AnalyzeRequest.withIndexAnalyzer(indexName, "ik_max_word", goods.getGoodsName()); AnalyzeResponse analyze = client.indices().analyze(analyzeRequest, RequestOptions.DEFAULT); List tokens = analyze.getTokens(); + if (goods.getAttrList() != null && !goods.getAttrList().isEmpty()) { + //保存分词 for (EsGoodsAttribute esGoodsAttribute : goods.getAttrList()) { wordsToDb(esGoodsAttribute.getValue()); } } + //分析词条 for (AnalyzeResponse.AnalyzeToken token : tokens) { + //保存词条进入数据库 wordsToDb(token.getTerm()); } + //生成索引 goodsIndexRepository.save(goods); } catch (IOException e) { log.error("为商品[" + goods.getGoodsName() + "]生成索引异常", e); @@ -112,6 +119,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void updateIndexCommentNum(String id, Integer commentNum, Integer highPraiseNum, Double grade) { EsGoodsIndex goodsIndex = this.findById(id); + //写入新的商品数据 goodsIndex.setCommentNum(commentNum); goodsIndex.setHighPraiseNum(highPraiseNum); goodsIndex.setGrade(grade); @@ -139,8 +147,10 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void initIndex(List goodsIndexList) { + //索引名称拼接 String indexName = elasticsearchProperties.getIndexPrefix() + "_" + EsSuffix.GOODS_INDEX_NAME; // deleteIndexRequest(indexName); + //如果索引不存在,则创建索引 if (!indexExist(indexName)) { createIndexRequest(indexName); } @@ -156,11 +166,14 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements public void updateEsGoodsIndex(String id, BasePromotion promotion, String key, Double price) { EsGoodsIndex goodsIndex = findById(id); if (goodsIndex != null) { + //如果有促销活动开始,则将促销金额写入 if (promotion.getPromotionStatus().equals(PromotionStatusEnum.START.name()) && price != null) { goodsIndex.setPromotionPrice(price); } else { + //否则促销金额为商品原价 goodsIndex.setPromotionPrice(goodsIndex.getPrice()); } + //更新索引 this.updateGoodsIndexPromotion(goodsIndex, key, promotion); } else { log.error("更新索引商品促销信息失败!skuId 为 【{}】的索引不存在!", id); @@ -170,6 +183,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void updateEsGoodsIndexByList(List promotionGoodsList, BasePromotion promotion, String key) { if (promotionGoodsList != null) { + //循环更新 促销商品索引 for (PromotionGoods promotionGoods : promotionGoodsList) { updateEsGoodsIndex(promotionGoods.getSkuId(), promotion, key, promotionGoods.getPrice()); } @@ -186,15 +200,20 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void updateEsGoodsIndexAllByList(BasePromotion promotion, String key) { List goodsIndices; + //如果storeid不为空,则表示是店铺活动 if (promotion.getStoreId() != null) { EsGoodsSearchDTO searchDTO = new EsGoodsSearchDTO(); searchDTO.setStoreId(promotion.getStoreId()); + //查询出店铺商品 Page esGoodsIndices = goodsSearchService.searchGoods(searchDTO, null); goodsIndices = esGoodsIndices.getContent(); } else { + //否则是平台活动 Iterable all = goodsIndexRepository.findAll(); +// 查询出全部商品 goodsIndices = new ArrayList<>(IterableUtil.toCollection(all)); } + //更新商品索引 for (EsGoodsIndex goodsIndex : goodsIndices) { this.updateGoodsIndexPromotion(goodsIndex, key, promotion); } @@ -202,8 +221,10 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public void deleteEsGoodsPromotionIndexByList(List skuIds, PromotionTypeEnum promotionType) { + //批量删除活动索引 for (String skuId : skuIds) { EsGoodsIndex goodsIndex = findById(skuId); + //商品索引不为空 if (goodsIndex != null) { Map promotionMap = goodsIndex.getPromotionMap(); if (promotionMap != null && !promotionMap.isEmpty()) { @@ -220,16 +241,19 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } /** - * 清除所以商品索引的无效促销活动 + * 清除所有商品索引的无效促销活动 */ @Override public void cleanInvalidPromotion() { Iterable all = goodsIndexRepository.findAll(); for (EsGoodsIndex goodsIndex : all) { Map promotionMap = goodsIndex.getPromotionMap(); + //获取商品索引 if (promotionMap != null && !promotionMap.isEmpty()) { + //促销不为空则进行清洗 for (Map.Entry entry : promotionMap.entrySet()) { BasePromotion promotion = (BasePromotion) entry.getValue(); + //判定条件为活动已结束 if (promotion.getEndTime().getTime() > DateUtil.date().getTime()) { promotionMap.remove(entry.getKey()); } @@ -258,6 +282,8 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public Map getPromotionMap(String id) { EsGoodsIndex goodsIndex = this.findById(id); + + // 如果商品索引不为空,返回促销信息,否则返回空 if (goodsIndex != null) { Map promotionMap = goodsIndex.getPromotionMap(); if (promotionMap == null || promotionMap.isEmpty()) { @@ -278,11 +304,14 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public List getPromotionIdByPromotionType(String id, PromotionTypeEnum promotionTypeEnum) { Map promotionMap = this.getPromotionMap(id); + //如果没有促销信息,则返回新的 if (promotionMap == null || promotionMap.isEmpty()) { return new ArrayList<>(); } + //对促销进行过滤 List keyCollect = promotionMap.keySet().stream().filter(i -> i.contains(promotionTypeEnum.name())).collect(Collectors.toList()); List promotionIds = new ArrayList<>(); + //写入促销id for (String key : keyCollect) { BasePromotion promotion = (BasePromotion) promotionMap.get(key); promotionIds.add(promotion.getId()); @@ -299,25 +328,37 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements @Override public EsGoodsIndex resetEsGoodsIndex(GoodsSku goodsSku) { EsGoodsIndex index = new EsGoodsIndex(goodsSku); + //获取活动信息 Map goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index); + //写入促销信息 index.setPromotionMap(goodsCurrentPromotionMap); this.addIndex(index); return index; } + /** + * 修改商品活动索引 + * + * @param goodsIndex 商品索引 + * @param key 关键字 + * @param promotion 活动 + */ private void updateGoodsIndexPromotion(EsGoodsIndex goodsIndex, String key, BasePromotion promotion) { Map promotionMap; + //数据非空处理,如果空给一个新的信息 if (goodsIndex.getPromotionMap() == null || goodsIndex.getPromotionMap().isEmpty()) { promotionMap = new HashMap<>(1); } else { promotionMap = goodsIndex.getPromotionMap(); } - - + //如果活动已结束 if (promotion.getPromotionStatus().equals(PromotionStatusEnum.END.name()) || promotion.getPromotionStatus().equals(PromotionStatusEnum.CLOSE.name())) { + //如果存在活动 if (promotionMap.containsKey(key)) { + //删除活动 promotionMap.remove(key); } else { + //不存在则说明是秒杀活动,尝试删除秒杀信息 this.removePromotionKey(key, promotionMap, PromotionTypeEnum.SECKILL.name()); } } else { @@ -337,9 +378,13 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements * @param needRemoveKeys 需移除的促销活动 */ private void removePromotionKey(String currentKey, Map promotionMap, String... needRemoveKeys) { + //判定是否需要移除 if (CharSequenceUtil.containsAny(currentKey, needRemoveKeys)) { + List removeKeys = new ArrayList<>(); + //促销循环 for (String entry : promotionMap.keySet()) { + //需要移除则进行移除处理 for (String needRemoveKey : needRemoveKeys) { if (entry.contains(needRemoveKey) && currentKey.contains(needRemoveKey)) { removeKeys.add(entry); @@ -347,6 +392,7 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements } } } + //移除促销信息 promotionMap.keySet().removeAll(removeKeys); } } diff --git a/framework/src/main/java/cn/lili/modules/store/entity/dto/StoreEditDTO.java b/framework/src/main/java/cn/lili/modules/store/entity/dto/StoreEditDTO.java index 16273681..33616b57 100644 --- a/framework/src/main/java/cn/lili/modules/store/entity/dto/StoreEditDTO.java +++ b/framework/src/main/java/cn/lili/modules/store/entity/dto/StoreEditDTO.java @@ -20,7 +20,7 @@ public class StoreEditDTO extends StoreDetail { private String storeDisable; @ApiModelProperty(value = "是否自营", required = true) - private Integer selfOperated; + private Boolean selfOperated; @ApiModelProperty(value = "经纬度") private String storeCenter; diff --git a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java index aab4878d..687b9eb5 100644 --- a/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java +++ b/framework/src/main/java/cn/lili/modules/store/serviceimpl/StoreServiceImpl.java @@ -3,7 +3,6 @@ package cn.lili.modules.store.serviceimpl; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.lili.common.enums.ResultCode; -import cn.lili.common.enums.SwitchEnum; import cn.lili.common.exception.ServiceException; import cn.lili.common.security.context.UserContext; import cn.lili.common.utils.BeanUtil; @@ -98,24 +97,24 @@ public class StoreServiceImpl extends ServiceImpl implements throw new ServiceException(ResultCode.USER_NOT_EXIST); } //判断是否拥有店铺 - if (SwitchEnum.OPEN.name().equals(member.getHaveStore())) { + if (member.getHaveStore()) { throw new ServiceException(ResultCode.STORE_APPLY_DOUBLE_ERROR); } //添加店铺 - Store store=new Store(member,adminStoreApplyDTO); + Store store = new Store(member, adminStoreApplyDTO); this.save(store); //判断是否存在店铺详情,如果没有则进行新建,如果存在则进行修改 - StoreDetail storeDetail = new StoreDetail(store,adminStoreApplyDTO); + StoreDetail storeDetail = new StoreDetail(store, adminStoreApplyDTO); storeDetailService.save(storeDetail); //设置会员-店铺信息 memberService.update(new LambdaUpdateWrapper() - .eq(Member::getId,member.getId()) - .set(Member::getHaveStore,SwitchEnum.OPEN.name()) - .set(Member::getStoreId,store.getId())); + .eq(Member::getId, member.getId()) + .set(Member::getHaveStore, true) + .set(Member::getStoreId, store.getId())); return store; } @@ -173,6 +172,12 @@ public class StoreServiceImpl extends ServiceImpl implements store.setStoreDisable(StoreStatusEnum.OPEN.value()); //添加店铺页面 pageDataService.addStorePageData(store.getId()); + //修改会员 表示已有店铺 + Member member = memberService.getById(store.getMemberId()); + member.setHaveStore(true); + member.setStoreId(id); + memberService.updateById(member); + } else { store.setStoreDisable(StoreStatusEnum.REFUSED.value()); } @@ -190,6 +195,7 @@ public class StoreServiceImpl extends ServiceImpl implements goodsService.underStoreGoods(id); return this.updateById(store); } + throw new ServiceException(ResultCode.STORE_NOT_EXIST); } @@ -281,26 +287,26 @@ public class StoreServiceImpl extends ServiceImpl implements @Override public void updateStoreGoodsNum(String storeId) { //获取店铺已上架已审核通过商品数量 - Integer goodsNum=goodsService.count(new LambdaQueryWrapper() - .eq(Goods::getStoreId,storeId) + Integer goodsNum = goodsService.count(new LambdaQueryWrapper() + .eq(Goods::getStoreId, storeId) .eq(Goods::getIsAuth, GoodsAuthEnum.PASS.name()) .eq(Goods::getMarketEnable, GoodsStatusEnum.UPPER.name())); //修改店铺商品数量 this.update(new LambdaUpdateWrapper() - .set(Store::getGoodsNum,goodsNum) - .eq(Store::getId,storeId)); + .set(Store::getGoodsNum, goodsNum) + .eq(Store::getId, storeId)); } @Override public void updateStoreCollectionNum(String goodsId) { - String storeId=goodsSkuService.getById(goodsId).getStoreId(); + String storeId = goodsSkuService.getById(goodsId).getStoreId(); //获取店铺收藏数量 - Integer collectionNum=storeCollectionService.count(new LambdaQueryWrapper() - .eq(StoreCollection::getStoreId,storeId)); + Integer collectionNum = storeCollectionService.count(new LambdaQueryWrapper() + .eq(StoreCollection::getStoreId, storeId)); //修改店铺收藏数量 this.update(new LambdaUpdateWrapper() - .set(Store::getCollectionNum,collectionNum) - .eq(Store::getId,storeId)); + .set(Store::getCollectionNum, collectionNum) + .eq(Store::getId, storeId)); } /** diff --git a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java index a5237cb1..25f8a32f 100644 --- a/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java +++ b/manager-api/src/main/java/cn/lili/controller/other/ElasticsearchController.java @@ -46,11 +46,14 @@ public class ElasticsearchController { @GetMapping public void init() { + //查询商品信息 LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name()); queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name()); + List list = goodsSkuService.list(queryWrapper); List esGoodsIndices = new ArrayList<>(); + //库存锁是在redis做的,所以生成索引,同时更新一下redis中的库存数量 for (GoodsSku goodsSku : list) { EsGoodsIndex index = new EsGoodsIndex(goodsSku); Map goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index); @@ -58,6 +61,7 @@ public class ElasticsearchController { esGoodsIndices.add(index); stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString()); } + //初始化商品索引 esGoodsIndexService.initIndex(esGoodsIndices); Assertions.assertTrue(true); } diff --git a/pom.xml b/pom.xml index b957fccf..038c1a81 100644 --- a/pom.xml +++ b/pom.xml @@ -23,7 +23,6 @@ buyer-api manager-api seller-api - socket-api common-api consumer diff --git a/socket-api/pom.xml b/socket-api/pom.xml deleted file mode 100644 index f798e24c..00000000 --- a/socket-api/pom.xml +++ /dev/null @@ -1,31 +0,0 @@ - - - 4.0.0 - - socket-api - - cn.lili - lili-shop-parent - 1.0.1 - - - - - cn.lili - framework - 1.0.1 - - - - - - - org.springframework.boot - spring-boot-maven-plugin - - - - - \ No newline at end of file diff --git a/socket-api/src/main/java/cn/lili/SocketApiApplication.java b/socket-api/src/main/java/cn/lili/SocketApiApplication.java deleted file mode 100644 index 947991d7..00000000 --- a/socket-api/src/main/java/cn/lili/SocketApiApplication.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.lili; - -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.web.servlet.config.annotation.CorsRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; - -/** - * @author Chopper - */ -@SpringBootApplication -public class SocketApiApplication extends WebMvcConfigurerAdapter { - - - public static void main(String[] args) { - - System.setProperty("es.set.netty.runtime.available.processors", "false"); - SpringApplication.run(SocketApiApplication.class, args); - } - - @Override - public void addCorsMappings(CorsRegistry registry) { - - registry.addMapping("/**") - .allowCredentials(true) - .allowedHeaders("*") //允许任何头 - .allowedOrigins("*") //允许任何域名 - .allowedMethods("*"); //允许任何方法 - } - - -} diff --git a/socket-api/src/main/java/cn/lili/scocket/listener/MessageSendListener.java b/socket-api/src/main/java/cn/lili/scocket/listener/MessageSendListener.java deleted file mode 100644 index 8e26701a..00000000 --- a/socket-api/src/main/java/cn/lili/scocket/listener/MessageSendListener.java +++ /dev/null @@ -1,67 +0,0 @@ -package cn.lili.scocket.listener; - -import cn.hutool.json.JSONUtil; -import cn.lili.common.rocketmq.tags.OtherTagsEnum; -import cn.lili.common.utils.BeanUtil; -import cn.lili.modules.message.entity.dos.Message; -import cn.lili.modules.message.entity.enums.MessageShowType; -import cn.lili.modules.message.entity.vos.MessageShowVO; -import cn.lili.modules.message.mapper.StoreMessageMapper; -import lombok.extern.slf4j.Slf4j; -import org.apache.rocketmq.common.message.MessageExt; -import org.apache.rocketmq.spring.annotation.RocketMQMessageListener; -import org.apache.rocketmq.spring.core.RocketMQListener; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.messaging.simp.SimpMessagingTemplate; -import org.springframework.stereotype.Component; -import org.springframework.web.bind.annotation.CrossOrigin; - -/** - * @author paulG - * @since 2020/12/9 - **/ -@Component -@CrossOrigin -@Slf4j -@RocketMQMessageListener(topic = "${lili.data.rocketmq.other-topic}", consumerGroup = "${lili.data.rocketmq.other-group}") -public class MessageSendListener implements RocketMQListener { - - - - @Autowired - private SimpMessagingTemplate simpMessagingTemplate; - - @Override - public void onMessage(MessageExt messageExt) { - log.info(messageExt.getTags()); - switch (OtherTagsEnum.valueOf(messageExt.getTags())) { - //站内消息提醒 - case MESSAGE: - System.out.println("消息提醒"); - sendNoticeMessage(messageExt); - break; - default: - break; - } - } - - /** - * 给商家发送站内信息 - * - * @param messageExt - */ - private void sendNoticeMessage(MessageExt messageExt) { - MessageShowVO messageVO = new MessageShowVO(); - Message message = JSONUtil.toBean(new String(messageExt.getBody()), Message.class); - //构建vo - BeanUtil.copyProperties(message, messageVO); - messageVO.setType(MessageShowType.NOTICE.name()); - if (message.getMessageRange().equals("ALL")) { - simpMessagingTemplate.convertAndSend("/topic/subscribe", messageVO); - } else { - for (String id : message.getUserIds()) { - simpMessagingTemplate.convertAndSendToUser("SHOP_" + id, "/queue/subscribe", messageVO); - } - } - } -} diff --git a/socket-api/src/main/java/cn/lili/scocket/listener/ScoketSecurityConfig.java b/socket-api/src/main/java/cn/lili/scocket/listener/ScoketSecurityConfig.java deleted file mode 100644 index 85eb8558..00000000 --- a/socket-api/src/main/java/cn/lili/scocket/listener/ScoketSecurityConfig.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.lili.scocket.listener; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; -import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; - -/** - * spring Security 核心配置类 Store安全配置中心 - * - * @author Chopper - * @version v4.0 - * @Description: - * @since 2020/11/14 16:20 - */ -@Slf4j -@Configuration -@EnableGlobalMethodSecurity(prePostEnabled = true) - -public class ScoketSecurityConfig extends WebSecurityConfigurerAdapter { - - - @Override - protected void configure(HttpSecurity http) throws Exception { - - ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = http - .authorizeRequests(); - registry.antMatchers("**").permitAll(); - } - -}