merge master

This commit is contained in:
lifenlong 2021-05-18 08:17:14 +08:00
commit 0c3a1928ff
14 changed files with 170 additions and 312 deletions

171
README.md
View File

@ -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)
### 功能展示
#### 移动端
<img src="https://pickmall.cn/assets/imgs/other/app.gif" alt="移动端功能展示" style="width:300px;" />
#### 管理端
<img src="https://pickmall.cn/assets/imgs/other/manager.gif" alt="管理端功能展示" />
### 技术选型
##### Java后台
@ -136,125 +181,35 @@ Lilishop 是一款Java开发基于SpringBoot的B2B2C多用户商城前端
| CSS预处理 | scss |
| 地图引擎 | amap |
### 功能列表
<table>
<tr><td colspan="2">运营后台功能</td></tr>
<tr><td>首页</td><td>平台统计、待办事项、流量统计</td></tr>
<tr><td rowspan="5">会员</td><td>会员列表</td></tr>
<tr><td>评价列表</td></tr>
<tr><td>积分历史</td></tr>
<tr><td>会员资金</td></tr>
<tr><td>充值记录</td></tr>
<tr><td rowspan="6">订单</td><td>商品订单</td></tr>
<tr><td>订单售后</td></tr>
<tr><td>交易投诉</td></tr>
<tr><td>售后原因</td></tr>
<tr><td>收款流水</td></tr>
<tr><td>退款流水</td></tr>
<tr><td rowspan="6">商品</td><td>商品列表</td></tr>
<tr><td>商品审核</td></tr>
<tr><td>商品分类</td></tr>
<tr><td>商品品牌</td></tr>
<tr><td>商品规格</td></tr>
<tr><td>计量单位</td></tr>
<tr><td rowspan="5">促销</td><td>优惠券</td></tr>
<tr><td>秒杀活动</td></tr>
<tr><td>拼团活动</td></tr>
<tr><td>积分商品</td></tr>
<tr><td>积分分类</td></tr>
<tr><td rowspan="5">店铺</td><td>店铺管理</td></tr>
<tr><td>店铺结算</td></tr>
<tr><td>店铺结算</td></tr>
<tr><td>店铺结算</td></tr>
<tr><td>店铺对账</td></tr>
<tr><td rowspan="9">运营</td><td>店铺对账</td></tr>
<tr><td>PC端楼层装修</td></tr>
<tr><td>移动端楼层装修</td></tr>
<tr><td>分销管理</td></tr>
<tr><td>文章管理</td></tr>
<tr><td>意见反馈</td></tr>
<tr><td>站内信</td></tr>
<tr><td>短信管理</td></tr>
<tr><td>APP版本管理</td></tr>
<tr><td rowspan="4">统计</td><td>会员统计</td></tr>
<tr><td>订单统计</td></tr>
<tr><td>商品统计</td></tr>
<tr><td>流量统计</td></tr>
<tr><td rowspan="11">设置</td><td>用户管理</td></tr>
<tr><td>菜单管理</td></tr>
<tr><td>部门管理</td></tr>
<tr><td>系统设置</td></tr>
<tr><td>OSS资源</td></tr>
<tr><td>行政地区</td></tr>
<tr><td>物流公司</td></tr>
<tr><td>信任登录</td></tr>
<tr><td>支付设置</td></tr>
<tr><td>验证码管理</td></tr>
<tr><td>敏感词管理</td></tr>
</table>
<table>
<tr><td colspan="2">店铺后台功能列表</td></tr>
<tr><td rowspan="3">首页</td><td>店铺信息</td></tr>
<tr><td>待办事项</td></tr>
<tr><td>平台公告</td></tr>
<tr><td rowspan="3">商品</td><td>商品发布</td></tr>
<tr><td>商品列表</td></tr>
<tr><td>店铺商品分类</td></tr>
<tr><td rowspan="5">订单</td><td>商品订单</td></tr>
<tr><td>退货管理</td></tr>
<tr><td>退款管理</td></tr>
<tr><td>投诉管理</td></tr>
<tr><td>评价管理</td></tr>
<tr><td rowspan="3">财务</td><td>财务对账</td></tr>
<tr><td>店铺结算</td></tr>
<tr><td>发票管理</td></tr>
<tr><td rowspan="5">促销</td><td>拼团管理</td></tr>
<tr><td>秒杀活动</td></tr>
<tr><td>满额活动</td></tr>
<tr><td>优惠券</td></tr>
<tr><td>分销商品</td></tr>
<tr><td rowspan="2">统计</td><td>商品统计</td></tr>
<tr><td>订单统计</td></tr>
<tr><td rowspan="5">设置</td><td>配送模板</td></tr>
<tr><td>物流公司</td></tr>
<tr><td>店铺设置</td></tr>
<tr><td>自提点管理</td></tr>
<tr><td>系统消息</td></tr>
</table>
### 技术亮点
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.已经对接好各种第三方插件,支持各种复杂等联合登陆,联合支付等场景。

View File

@ -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<String> promotionIds = new ArrayList<>();
//关闭满减活动
List<FullDiscountVO> fullDiscountVOS = mongoTemplate.find(query, FullDiscountVO.class);
if (!fullDiscountVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
@ -80,9 +82,10 @@ public class PromotionEverydayExecute implements EveryDayExecute {
fullDiscountService.update(this.getUpdatePromotionWrapper(ids));
promotionIds.addAll(ids);
}
//关闭拼团活动
List<PintuanVO> pintuanVOS = mongoTemplate.find(query, PintuanVO.class);
if (!pintuanVOS.isEmpty()) {
//准备修改活动的id
List<String> 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<CouponVO> couponVOS = mongoTemplate.find(query, CouponVO.class);
if (!couponVOS.isEmpty()) {
List<String> ids = new ArrayList<>();
@ -121,13 +125,22 @@ public class PromotionEverydayExecute implements EveryDayExecute {
}
/**
* 获取促销修改查询条件 修改活动状态
* @param ids
* @return
*/
private UpdateWrapper getUpdatePromotionWrapper(List<String> 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<String> ids) {
UpdateWrapper updateWrapper = new UpdateWrapper<>();
updateWrapper.in("promotion_id", ids);

View File

@ -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);

View File

@ -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<String, String> 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<String, String> 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")) {

View File

@ -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<Store> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(Store::getMemberId, member.getId());
Store store = storeService.getOne(queryWrapper);

View File

@ -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<AnalyzeResponse.AnalyzeToken> 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<EsGoodsIndex> 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<PromotionGoods> 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<EsGoodsIndex> goodsIndices;
//如果storeid不为空则表示是店铺活动
if (promotion.getStoreId() != null) {
EsGoodsSearchDTO searchDTO = new EsGoodsSearchDTO();
searchDTO.setStoreId(promotion.getStoreId());
//查询出店铺商品
Page<EsGoodsIndex> esGoodsIndices = goodsSearchService.searchGoods(searchDTO, null);
goodsIndices = esGoodsIndices.getContent();
} else {
//否则是平台活动
Iterable<EsGoodsIndex> 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<String> skuIds, PromotionTypeEnum promotionType) {
//批量删除活动索引
for (String skuId : skuIds) {
EsGoodsIndex goodsIndex = findById(skuId);
//商品索引不为空
if (goodsIndex != null) {
Map<String, Object> promotionMap = goodsIndex.getPromotionMap();
if (promotionMap != null && !promotionMap.isEmpty()) {
@ -220,16 +241,19 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
}
/**
* 清除所商品索引的无效促销活动
* 清除所商品索引的无效促销活动
*/
@Override
public void cleanInvalidPromotion() {
Iterable<EsGoodsIndex> all = goodsIndexRepository.findAll();
for (EsGoodsIndex goodsIndex : all) {
Map<String, Object> promotionMap = goodsIndex.getPromotionMap();
//获取商品索引
if (promotionMap != null && !promotionMap.isEmpty()) {
//促销不为空则进行清洗
for (Map.Entry<String, Object> 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<String, Object> getPromotionMap(String id) {
EsGoodsIndex goodsIndex = this.findById(id);
// 如果商品索引不为空返回促销信息否则返回空
if (goodsIndex != null) {
Map<String, Object> promotionMap = goodsIndex.getPromotionMap();
if (promotionMap == null || promotionMap.isEmpty()) {
@ -278,11 +304,14 @@ public class EsGoodsIndexServiceImpl extends BaseElasticsearchService implements
@Override
public List<String> getPromotionIdByPromotionType(String id, PromotionTypeEnum promotionTypeEnum) {
Map<String, Object> promotionMap = this.getPromotionMap(id);
//如果没有促销信息则返回新的
if (promotionMap == null || promotionMap.isEmpty()) {
return new ArrayList<>();
}
//对促销进行过滤
List<String> keyCollect = promotionMap.keySet().stream().filter(i -> i.contains(promotionTypeEnum.name())).collect(Collectors.toList());
List<String> 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<String, Object> 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<String, Object> 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<String, Object> promotionMap, String... needRemoveKeys) {
//判定是否需要移除
if (CharSequenceUtil.containsAny(currentKey, needRemoveKeys)) {
List<String> 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);
}
}

View File

@ -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;

View File

@ -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<StoreMapper, Store> 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<Member>()
.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<StoreMapper, Store> 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<StoreMapper, Store> implements
goodsService.underStoreGoods(id);
return this.updateById(store);
}
throw new ServiceException(ResultCode.STORE_NOT_EXIST);
}
@ -281,26 +287,26 @@ public class StoreServiceImpl extends ServiceImpl<StoreMapper, Store> implements
@Override
public void updateStoreGoodsNum(String storeId) {
//获取店铺已上架已审核通过商品数量
Integer goodsNum=goodsService.count(new LambdaQueryWrapper<Goods>()
.eq(Goods::getStoreId,storeId)
Integer goodsNum = goodsService.count(new LambdaQueryWrapper<Goods>()
.eq(Goods::getStoreId, storeId)
.eq(Goods::getIsAuth, GoodsAuthEnum.PASS.name())
.eq(Goods::getMarketEnable, GoodsStatusEnum.UPPER.name()));
//修改店铺商品数量
this.update(new LambdaUpdateWrapper<Store>()
.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<StoreCollection>()
.eq(StoreCollection::getStoreId,storeId));
Integer collectionNum = storeCollectionService.count(new LambdaQueryWrapper<StoreCollection>()
.eq(StoreCollection::getStoreId, storeId));
//修改店铺收藏数量
this.update(new LambdaUpdateWrapper<Store>()
.set(Store::getCollectionNum,collectionNum)
.eq(Store::getId,storeId));
.set(Store::getCollectionNum, collectionNum)
.eq(Store::getId, storeId));
}
/**

View File

@ -46,11 +46,14 @@ public class ElasticsearchController {
@GetMapping
public void init() {
//查询商品信息
LambdaQueryWrapper<GoodsSku> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(GoodsSku::getIsAuth, GoodsAuthEnum.PASS.name());
queryWrapper.eq(GoodsSku::getMarketEnable, GoodsStatusEnum.UPPER.name());
List<GoodsSku> list = goodsSkuService.list(queryWrapper);
List<EsGoodsIndex> esGoodsIndices = new ArrayList<>();
//库存锁是在redis做的所以生成索引同时更新一下redis中的库存数量
for (GoodsSku goodsSku : list) {
EsGoodsIndex index = new EsGoodsIndex(goodsSku);
Map<String, Object> 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);
}

View File

@ -23,7 +23,6 @@
<module>buyer-api</module>
<module>manager-api</module>
<module>seller-api</module>
<module>socket-api</module>
<module>common-api</module>
<module>consumer</module>
</modules>

View File

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>socket-api</artifactId>
<parent>
<groupId>cn.lili</groupId>
<artifactId>lili-shop-parent</artifactId>
<version>1.0.1</version>
</parent>
<dependencies>
<dependency>
<groupId>cn.lili</groupId>
<artifactId>framework</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

View File

@ -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("*"); //允许任何方法
}
}

View File

@ -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<MessageExt> {
@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);
}
}
}
}

View File

@ -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<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http
.authorizeRequests();
registry.antMatchers("**").permitAll();
}
}