Merge branch 'Bulbasaur' of gitee.com:beijing_hongye_huicheng/lilishop into Bulbasaur

This commit is contained in:
Chopper 2021-06-18 14:23:54 +08:00
commit 30d34d69f1
46 changed files with 482 additions and 1646 deletions

View File

@ -1,5 +1,6 @@
package cn.lili.controller.member;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
@ -55,7 +56,7 @@ public class MemberEvaluationBuyerController {
public ResultMessage<IPage<MemberEvaluation>> queryMineEvaluation(EvaluationQueryParams evaluationQueryParams) {
//设置当前登录会员
evaluationQueryParams.setMemberId(UserContext.getCurrentUser().getId());
return ResultUtil.data(memberEvaluationService.queryByParams(evaluationQueryParams));
return ResultUtil.data(memberEvaluationService.managerQuery(evaluationQueryParams));
}
@ApiOperation(value = "查看某一个商品的评价列表")
@ -65,7 +66,8 @@ public class MemberEvaluationBuyerController {
@NotNull @PathVariable("goodsId") String goodsId) {
//设置查询查询商品
evaluationQueryParams.setGoodsId(goodsId);
return ResultUtil.data(memberEvaluationService.queryByParams(evaluationQueryParams));
evaluationQueryParams.setStatus(SwitchEnum.OPEN.name());
return ResultUtil.data(memberEvaluationService.managerQuery(evaluationQueryParams));
}
@ApiOperation(value = "查看某一个商品的评价数量")

View File

@ -222,8 +222,7 @@ lili:
#支付密码
WALLET_PASSWORD: SMS_205755301
system:
isDemoSite: true
licences: 'temporary'
isTestModel: true
statistics:
# 在线人数统计 X 小时。这里设置48即统计过去48小时每小时在线人数
onlineMember: 48

View File

@ -224,6 +224,7 @@ lili:
WALLET_PASSWORD: SMS_205755301
system:
isDemoSite: false
isTestModel: true
statistics:
# 在线人数统计 X 小时。这里设置48即统计过去48小时每小时在线人数
onlineMember: 48

View File

@ -12,6 +12,7 @@ import cn.lili.modules.order.order.service.OrderService;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.enums.PromotionTypeEnum;
import cn.lili.modules.promotion.service.PromotionGoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
@ -26,9 +27,12 @@ import java.util.List;
* @author Chopper
* @date 2020-07-03 11:20
*/
@Slf4j
@Service
public class StockUpdateExecute implements OrderStatusChangeEvent {
//出库失败消息
static String outOfStockMessage = "库存不足,出库失败";
//Redis
@Autowired
private StringRedisTemplate stringRedisTemplate;
@ -52,6 +56,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
switch (orderMessage.getNewStatus()) {
case PAID: {
//获取订单详情
OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn());
//库存key 扣减数量
List<String> keys = new ArrayList<>();
@ -66,32 +71,41 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray());
//如果库存扣减都成功则记录成交订单
if (Boolean.TRUE.equals(skuResult)) {
log.info("库存扣减成功,参数为{};{}", keys, values);
//库存确认之后对结构处理
orderService.afterOrderConfirm(orderMessage.getOrderSn());
//成功之后同步库存
synchroDB(order);
} else {
log.info("库存扣件失败变更缓存key{} 变更缓存value{}", keys, values);
//失败之后取消订单
this.errorOrder(orderMessage.getOrderSn());
}
break;
}
case CANCELLED: {
//获取订单详情
OrderDetailVO order = orderService.queryDetail(orderMessage.getOrderSn());
if (order.getOrder().getPayStatus().equals(PayStatusEnum.PAID.name())) {
//判定是否已支付 并且 非库存不足导致库存回滚 则需要考虑订单库存返还业务
if (order.getOrder().getPayStatus().equals(PayStatusEnum.PAID.name()) && order.getOrder().getCancelReason().equals(outOfStockMessage)) {
//库存key 还原数量
List<String> keys = new ArrayList<>();
List<String> values = new ArrayList<>();
//返还商品库存促销库存不与返还不然前台展示层有展示逻辑错误
for (OrderItem orderItem : order.getOrderItems()) {
if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) {
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType());
Integer goodsPromotionOriginStock = promotionGoodsService.getPromotionGoodsStock(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
int goodsPromotionStock = goodsPromotionOriginStock + orderItem.getNum();
String promotionGoodsStockCacheKey = PromotionGoodsService.getPromotionGoodsStockCacheKey(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
stringRedisTemplate.opsForValue().set(promotionGoodsStockCacheKey, Integer.toString(goodsPromotionStock));
}
String stockCacheKey = GoodsSkuService.getStockCacheKey(orderItem.getSkuId());
Integer goodsOriginStock = goodsSkuService.getStock(orderItem.getSkuId());
int goodsStock = goodsOriginStock + orderItem.getNum();
stringRedisTemplate.opsForValue().set(stockCacheKey, Integer.toString(goodsStock));
keys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
int i = orderItem.getNum();
values.add(Integer.toString(i));
}
//批量脚本执行库存回退
Boolean skuResult = stringRedisTemplate.execute(quantityScript, keys, values.toArray());
//返还失败则记录日志
if (Boolean.FALSE.equals(skuResult)) {
log.error("库存回退异常keys{},回复库存值为: {}", keys, values);
}
rollbackOrderStock(order);
}
break;
}
@ -106,7 +120,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
* @param orderSn 失败入库订单信息
*/
private void errorOrder(String orderSn) {
orderService.systemCancel(orderSn, "库存不足,出库失败");
orderService.systemCancel(orderSn, outOfStockMessage);
}
@ -130,8 +144,9 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
}
}
/**
* 写入需要更改促销库存的商品
* 同步库存和促销库存
*
* @param order 订单
*/
@ -157,6 +172,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
if (PromotionTypeEnum.haveStock(orderItem.getPromotionType())) {
PromotionTypeEnum promotionTypeEnum = PromotionTypeEnum.valueOf(orderItem.getPromotionType());
PromotionGoods pGoods = promotionGoodsService.getPromotionGoods(promotionTypeEnum, orderItem.getPromotionId(), orderItem.getSkuId());
//记录需要更新的促销库存信息
promotionKey.add(
PromotionGoodsService.getPromotionGoodsStockCacheKey(
promotionTypeEnum,
@ -168,6 +184,7 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
goodsSkus.add(goodsSku);
}
//批量获取商品库存
List skuStocks = cache.multiGet(skuKeys);
//循环写入商品库存
for (int i = 0; i < skuStocks.size(); i++) {
@ -186,8 +203,41 @@ public class StockUpdateExecute implements OrderStatusChangeEvent {
}
promotionGoodsService.updateBatchById(promotionGoods);
}
//商品库存包含sku库存集合批量更新商品库存相关
goodsSkuService.updateGoodsStuck(goodsSkus);
log.info("订单确认,库存同步:商品信息--{};促销信息---{}", goodsSkus, promotionGoods);
}
/**
* 恢复商品库存
*
* @param order 订单
*/
private void rollbackOrderStock(OrderDetailVO order) {
//sku商品
List<GoodsSku> goodsSkus = new ArrayList<>();
//sku库存key 集合
List<String> skuKeys = new ArrayList<>();
// 循环订单
for (OrderItem orderItem : order.getOrderItems()) {
skuKeys.add(GoodsSkuService.getStockCacheKey(orderItem.getSkuId()));
GoodsSku goodsSku = new GoodsSku();
goodsSku.setId(orderItem.getSkuId());
goodsSkus.add(goodsSku);
}
//批量获取商品库存
List skuStocks = cache.multiGet(skuKeys);
//循环写入商品SKU库存
for (int i = 0; i < skuStocks.size(); i++) {
goodsSkus.get(i).setQuantity(Integer.parseInt(skuStocks.get(i).toString()));
}
log.info("订单取消,库存还原:{}", goodsSkus);
//批量修改商品库存
goodsSkuService.updateBatchById(goodsSkus);
goodsSkuService.updateGoodsStuck(goodsSkus);
}
}

View File

@ -11,6 +11,7 @@ import cn.lili.common.sms.SmsUtil;
import cn.lili.common.utils.CommonUtil;
import cn.lili.common.verification.enums.VerificationEnums;
import cn.lili.config.properties.SmsTemplateSetting;
import cn.lili.config.properties.SystemSetting;
import cn.lili.modules.connect.util.Base64Utils;
import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.service.MemberService;
@ -55,6 +56,9 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
@Autowired
private SmsTemplateSetting smsTemplateSetting;
@Autowired
private SystemSetting systemSetting;
@Override
public void sendSmsCode(String mobile, VerificationEnums verificationEnums, String uuid) {
//获取短信配置
@ -115,12 +119,15 @@ public class SmsUtilAliImplService implements SmsUtil, AliSmsUtil {
default:
return;
}
log.info("短信验证码:"+code);
//如果是测试模式 默认验证码 6个1
if (systemSetting.getIsTestModel()) {
code = "111111";
} else {
//发送短信
this.sendSmsCode(smsSetting.getSignName(), mobile, params, templateCode);
}
//缓存中写入要验证的信息
cache.put(cacheKey(verificationEnums, mobile, uuid), code, 300L);
//发送短信
this.sendSmsCode(smsSetting.getSignName(), mobile, params, templateCode);
}
@Override

View File

@ -1,5 +1,7 @@
package cn.lili.common.utils;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.payment.kit.dto.PayParam;
import org.springframework.beans.BeanUtils;
import java.lang.reflect.Field;
@ -56,4 +58,75 @@ public class BeanUtil {
return null;
}
}
/**
* 将对象转换为key value
* A=a&B=b&C=c 格式
*/
public static String formatKeyValuePair(Object object) {
//准备接受的字符串
StringBuilder stringBuffer = new StringBuilder();
//获取对象字段
String[] fieldNames = BeanUtil.getFiledName(object);
//遍历所有属性
for (int j = 0; j < fieldNames.length; j++) {
//不是第一个并且不是最后一个拼接&
if (j != 0) {
stringBuffer.append("&");
}
//获取属性的名字
String key = fieldNames[j];
//获取值
Object value = BeanUtil.getFieldValueByName(key, object);
stringBuffer.append(key).append("=").append(value.toString());
}
return stringBuffer.toString();
}
/**
* key value键值对 转换为 对象
* A=a&B=b&C=c 格式 转换为对象
*/
public static <T> T formatKeyValuePair(String str, T t) {
//填写对参数键值对
String[] params = str.split("&");
//获取对象字段
String[] fieldNames = BeanUtil.getFiledName(t);
try {
//循环每个参数
for (String param : params) {
String[] keyValues = param.split("=");
for (int i = 0; i < fieldNames.length; i++) {
if (fieldNames[i].equals(keyValues[0])) {
Field f = t.getClass().getDeclaredField(fieldNames[i]);
f.setAccessible(true);
//长度为2 才转换否则不转
if (keyValues.length == 2) {
f.set(t, keyValues[1]);
}
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return t;
}
public static void main(String[] args) throws IllegalAccessException {
PayParam payParam = new PayParam();
payParam.setClientType("client");
payParam.setOrderType("");
payParam.setSn("sn");
String val = formatKeyValuePair(payParam);
System.out.println(val);
PayParam param = formatKeyValuePair(val, new PayParam());
System.out.println(JSONUtil.toJsonStr(param));
}
}

View File

@ -12,6 +12,8 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 字串工具类
@ -250,6 +252,19 @@ public class StringUtils extends StrUtil {
}
return str.concat(appendStr);
}
/**
* 过滤特殊字符串
*
* @param str
* @return
*/
public static String filterSpecialChart(String str) {
String regEx = "[`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~@#¥%……&*()——+|{}【】‘;:”“’。,、?]";
Pattern p = Pattern.compile(regEx);
Matcher m = p.matcher(str);
return m.replaceAll("").trim();
}
}

View File

@ -20,6 +20,12 @@ public class SystemSetting {
*/
private Boolean isDemoSite = false;
/**
* 测试模式
* 验证码短信为6个1
*/
private Boolean isTestModel = false;
/**
* 授权信息
*/

View File

@ -101,7 +101,7 @@ public class CodeGenerator {
*/
public static void main(String[] args) throws IOException {
// 模板路径
ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader("/templates/java/");
ClasspathResourceLoader resourceLoader = new ClasspathResourceLoader("/templates/");
Configuration cfg = Configuration.defaultConfiguration();
GroupTemplate gt = new GroupTemplate(resourceLoader, cfg);
// 生成代码

View File

@ -1,15 +1,18 @@
package cn.lili.modules.goods.entity.dos;
import cn.hutool.json.JSONUtil;
import cn.lili.base.BaseEntity;
import cn.lili.modules.goods.entity.dto.GoodsOperationDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import javax.validation.constraints.Max;
@ -182,12 +185,19 @@ public class Goods extends BaseEntity {
@ApiModelProperty(value = "销售模式", required = true)
private String salesModel;
/**
* @see cn.lili.modules.goods.entity.enums.GoodsTypeEnum
*/
@ApiModelProperty(value = "商品类型", required = true)
private String goodsType;
@ApiModelProperty(value = "商品参数json", hidden = true)
@Column(columnDefinition = "TEXT")
@JsonIgnore
private String params;
public Goods() {
}
@ -207,6 +217,9 @@ public class Goods extends BaseEntity {
this.intro = goodsOperationDTO.getIntro();
this.mobileIntro = goodsOperationDTO.getMobileIntro();
this.cost = goodsOperationDTO.getCost();
if (goodsOperationDTO.getGoodsParamsList() != null && goodsOperationDTO.getGoodsParamsList().isEmpty()) {
this.params = JSONUtil.toJsonStr(goodsOperationDTO.getGoodsParamsList());
}
//如果立即上架则
this.marketEnable = goodsOperationDTO.isRelease() ? GoodsStatusEnum.UPPER.name() : GoodsStatusEnum.DOWN.name();
this.goodsType=goodsOperationDTO.getGoodsType();

View File

@ -164,8 +164,7 @@ public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> i
Category parentCategory = this.getById(category.getParentId());
category.setDeleteFlag(parentCategory.getDeleteFlag());
}
save(category);
//清除缓存
this.save(category);
removeCache();
return true;
}

View File

@ -11,10 +11,7 @@ import cn.lili.common.rocketmq.tags.GoodsTagsEnum;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.PageUtil;
import cn.lili.config.rocketmq.RocketmqCustomProperties;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dos.SpecValues;
import cn.lili.modules.goods.entity.dos.Specification;
import cn.lili.modules.goods.entity.dos.*;
import cn.lili.modules.goods.entity.dto.GoodsSearchParams;
import cn.lili.modules.goods.entity.dto.GoodsSkuStockDTO;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
@ -26,6 +23,7 @@ import cn.lili.modules.member.entity.dos.FootPrint;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
import cn.lili.modules.member.service.MemberEvaluationService;
import cn.lili.modules.promotion.service.PromotionService;
import cn.lili.modules.search.entity.dos.EsGoodsAttribute;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsIndexService;
@ -83,14 +81,20 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
private GoodsService goodsService;
//商品索引
private EsGoodsIndexService goodsIndexService;
@Autowired
private ParametersService parametersService;
@Autowired
private PromotionService promotionService;
@Override
public void add(List<Map<String, Object>> skuList, Goods goods) {
// 检查是否需要生成索引
boolean needIndex = checkNeedIndex(goods);
List<GoodsSku> newSkuList;
// 如果有规格
if (skuList != null && !skuList.isEmpty()) {
// 添加商品sku
newSkuList = this.addGoodsSku(skuList, goods);
newSkuList = this.addGoodsSku(skuList, goods, needIndex);
} else {
throw new ServiceException("规格必须要有一个!");
}
@ -99,8 +103,23 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
generateEsCheck(goods);
}
private boolean checkNeedIndex(Goods goods) {
if (goods.getParams() != null && !goods.getParams().isEmpty()) {
List<GoodsParams> goodsParams = JSONUtil.toList(goods.getParams(), GoodsParams.class);
for (GoodsParams goodsParam : goodsParams) {
Parameters parameters = parametersService.getById(goodsParam.getParamId());
if (parameters.getIsIndex() == 1) {
return true;
}
}
}
return false;
}
@Override
public void update(List<Map<String, Object>> skuList, Goods goods, Boolean regeneratorSkuFlag) {
// 检查是否需要生成索引
boolean needIndex = checkNeedIndex(goods);
// 是否存在规格
if (skuList == null || skuList.isEmpty()) {
throw new ServiceException("规格必须要有一个!");
@ -120,7 +139,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
//删除sku相册
goodsGalleryService.removeByIds(oldSkuIds);
// 添加商品sku
newSkuList = this.addGoodsSku(skuList, goods);
newSkuList = this.addGoodsSku(skuList, goods, needIndex);
//发送mq消息
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.SKU_DELETE.name();
@ -142,7 +161,9 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
this.updateBatchById(newSkuList);
}
this.updateStock(newSkuList);
generateEsCheck(goods);
if (Boolean.TRUE.equals(needIndex)) {
generateEsCheck(goods);
}
}
/**
@ -198,7 +219,8 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
// 获取当前商品的索引信息
EsGoodsIndex goodsIndex = goodsIndexService.findById(skuId);
if (goodsIndex == null) {
goodsIndex = goodsIndexService.resetEsGoodsIndex(goodsSku);
goodsIndex = new EsGoodsIndex(goodsSku);
goodsIndex.setPromotionMap(promotionService.getGoodsCurrentPromotionMap(goodsIndex));
}
//商品规格
GoodsSkuVO goodsSkuDetail = this.getGoodsSkuVO(goodsSku);
@ -416,7 +438,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
//修改规格
this.update(goodsSku);
//修改规格索引
goodsIndexService.updateIndexCommentNum(goodsSku.getId(), goodsSku.getCommentNum(), (int) highPraiseNum, grade);
goodsIndexService.updateIndexCommentNum(goodsSku.getId(), goodsSku.getCommentNum(), highPraiseNum, grade);
//修改商品的评价数量
goodsService.updateGoodsCommentNum(goodsSku.getGoodsId());
@ -479,7 +501,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
* @param skuList sku列表
* @param goods 商品信息
*/
private List<GoodsSku> addGoodsSku(List<Map<String, Object>> skuList, Goods goods) {
private List<GoodsSku> addGoodsSku(List<Map<String, Object>> skuList, Goods goods, Boolean needIndex) {
List<GoodsSku> skus = new ArrayList<>();
List<EsGoodsIndex> goodsIndices = new ArrayList<>();
for (Map<String, Object> skuVO : skuList) {
@ -495,9 +517,11 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString());
}
this.saveBatch(skus);
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GENERATOR_GOODS_INDEX.name();
//发送mq消息
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goodsIndices), RocketmqSendCallbackBuilder.commonCallback());
if (Boolean.TRUE.equals(needIndex)) {
String destination = rocketmqCustomProperties.getGoodsTopic() + ":" + GoodsTagsEnum.GENERATOR_GOODS_INDEX.name();
//发送mq消息
rocketMQTemplate.asyncSend(destination, JSONUtil.toJsonStr(goodsIndices), RocketmqSendCallbackBuilder.commonCallback());
}
return skus;
}
@ -617,7 +641,7 @@ public class GoodsSkuServiceImpl extends ServiceImpl<GoodsSkuMapper, GoodsSku> i
sku.setSmall(small);
//规格信息
sku.setId(Convert.toStr(map.get("id"), "").toString());
sku.setId(Convert.toStr(map.get("id"), ""));
sku.setSn(Convert.toStr(map.get("sn")));
sku.setWeight(Convert.toDouble(map.get("weight"), 0D));
sku.setPrice(Convert.toDouble(map.get("price"), 0D));

View File

@ -15,6 +15,10 @@ import lombok.Data;
@Data
public class EvaluationQueryParams extends PageVO {
@ApiModelProperty(value = "买家ID")
private String memberId;
@ApiModelProperty(value = "会员名称")
private String memberName;
@ -24,9 +28,6 @@ public class EvaluationQueryParams extends PageVO {
@ApiModelProperty(value = "卖家ID")
private String storeId;
@ApiModelProperty(value = "买家ID", hidden = true)
private String memberId;
@ApiModelProperty(value = "商品名称")
private String goodsName;
@ -45,6 +46,9 @@ public class EvaluationQueryParams extends PageVO {
@ApiModelProperty(value = "评论日期--结束时间")
private String endTime;
@ApiModelProperty(value = "状态")
private String status;
public EvaluationQueryParams() {
}
@ -78,6 +82,9 @@ public class EvaluationQueryParams extends PageVO {
if (StringUtils.isNotEmpty(haveImage)) {
queryWrapper.eq("have_image", haveImage);
}
if (StringUtils.isNotEmpty(status)) {
queryWrapper.eq("status", status);
}
queryWrapper.eq("delete_flag", false);
queryWrapper.orderByDesc("create_time");
return queryWrapper;

View File

@ -1,59 +0,0 @@
package cn.lili.modules.member.entity.dto;
import cn.hutool.core.date.DateUtil;
import cn.lili.common.security.context.UserContext;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* 店铺评价查询参数
*
* @author Chopper
* @date 2021/3/20 10:43
*/
@Data
public class StoreEvaluationQueryParams extends PageVO {
@ApiModelProperty(value = "会员名称")
private String memberName;
@ApiModelProperty(value = "商品名称")
private String goodsName;
@ApiModelProperty(value = "好中差评 good好评neutral中评bad差评", allowableValues = "GOOD,NEUTRAL,BAD")
private String grade;
@ApiModelProperty(value = "评论日期--开始时间")
private String startDate;
@ApiModelProperty(value = "评论日期--结束时间")
private String endDate;
public <T> QueryWrapper<T> queryWrapper() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("store_id", UserContext.getCurrentUser().getStoreId());
if (StringUtils.isNotEmpty(startDate) && StringUtils.isNotEmpty(endDate)) {
queryWrapper.between("create_time", DateUtil.parse(startDate), DateUtil.parse(endDate));
}
if (StringUtils.isNotEmpty(grade)) {
queryWrapper.eq("grade", grade);
}
if (StringUtils.isNotEmpty(goodsName)) {
queryWrapper.eq("goods_name", goodsName);
}
if (StringUtils.isNotEmpty(memberName)) {
queryWrapper.eq("member_name", memberName);
}
return queryWrapper;
}
}

View File

@ -25,7 +25,7 @@ public interface MemberEvaluationMapper extends BaseMapper<MemberEvaluation> {
@Select("select me.* from li_member_evaluation as me ${ew.customSqlSegment}")
IPage<MemberEvaluationListVO> getMemberEvaluationList(IPage<MemberEvaluationListVO> page, @Param(Constants.WRAPPER) Wrapper<MemberEvaluationListVO> queryWrapper);
@Select("select grade,count(1) as num from li_member_evaluation Where goods_id=#{goodsId} GROUP BY grade")
@Select("select grade,count(1) as num from li_member_evaluation Where goods_id=#{goodsId} and status='OPEN' GROUP BY grade")
List<Map<String, Object>> getEvaluationNumber(String goodsId);
@Select("SELECT round( AVG( delivery_score ), 2 ) AS delivery_score" +

View File

@ -1,10 +1,8 @@
package cn.lili.modules.member.service;
import cn.lili.common.vo.PageVO;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.entity.dto.EvaluationQueryParams;
import cn.lili.modules.member.entity.dto.MemberEvaluationDTO;
import cn.lili.modules.member.entity.dto.StoreEvaluationQueryParams;
import cn.lili.modules.member.entity.vo.EvaluationNumberVO;
import cn.lili.modules.member.entity.vo.MemberEvaluationListVO;
import cn.lili.modules.member.entity.vo.MemberEvaluationVO;
@ -25,23 +23,14 @@ public interface MemberEvaluationService extends IService<MemberEvaluation> {
* @param evaluationQueryParams 评价查询
* @return 评价分页
*/
IPage<MemberEvaluation> queryByParams(EvaluationQueryParams evaluationQueryParams);
/**
* 商家查询会员的评价分页列表
*
* @param storeEvaluationQueryParams 评价查询
* @return 会员的评价分页
*/
IPage<MemberEvaluationListVO> queryByParams(StoreEvaluationQueryParams storeEvaluationQueryParams);
IPage<MemberEvaluation> managerQuery(EvaluationQueryParams evaluationQueryParams);
/**
* 查询评价分页列表
* @param evaluationQueryParams 评价查询条件
* @param page 分页查询参数
* @return 评价分页列表
*/
IPage<MemberEvaluationListVO> queryPage(EvaluationQueryParams evaluationQueryParams, PageVO page);
IPage<MemberEvaluationListVO> queryPage(EvaluationQueryParams evaluationQueryParams);
/**
* 添加会员评价

View File

@ -3,8 +3,8 @@ package cn.lili.modules.member.serviceimpl;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.enums.SwitchEnum;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.rocketmq.RocketmqSendCallbackBuilder;
import cn.lili.common.rocketmq.tags.GoodsTagsEnum;
@ -12,7 +12,6 @@ import cn.lili.common.security.context.UserContext;
import cn.lili.common.security.enums.UserEnums;
import cn.lili.common.utils.PageUtil;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.PageVO;
import cn.lili.config.rocketmq.RocketmqCustomProperties;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.service.GoodsSkuService;
@ -20,7 +19,6 @@ import cn.lili.modules.member.entity.dos.Member;
import cn.lili.modules.member.entity.dos.MemberEvaluation;
import cn.lili.modules.member.entity.dto.EvaluationQueryParams;
import cn.lili.modules.member.entity.dto.MemberEvaluationDTO;
import cn.lili.modules.member.entity.dto.StoreEvaluationQueryParams;
import cn.lili.modules.member.entity.enums.EvaluationGradeEnum;
import cn.lili.modules.member.entity.vo.EvaluationNumberVO;
import cn.lili.modules.member.entity.vo.MemberEvaluationListVO;
@ -42,12 +40,12 @@ import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
@ -61,6 +59,9 @@ import java.util.Map;
@Transactional
public class MemberEvaluationServiceImpl extends ServiceImpl<MemberEvaluationMapper, MemberEvaluation> implements MemberEvaluationService {
//会员评价数据层
@Resource
private MemberEvaluationMapper memberEvaluationMapper;
//订单
@Autowired
private OrderService orderService;
@ -81,19 +82,14 @@ public class MemberEvaluationServiceImpl extends ServiceImpl<MemberEvaluationMap
private RocketmqCustomProperties rocketmqCustomProperties;
@Override
public IPage<MemberEvaluation> queryByParams(EvaluationQueryParams queryParams) {
public IPage<MemberEvaluation> managerQuery(EvaluationQueryParams queryParams) {
//获取评价分页
return this.page(PageUtil.initPage(queryParams), queryParams.queryWrapper());
}
@Override
public IPage<MemberEvaluationListVO> queryByParams(StoreEvaluationQueryParams storeEvaluationQueryParams) {
return this.baseMapper.getMemberEvaluationList(PageUtil.initPage(storeEvaluationQueryParams), storeEvaluationQueryParams.queryWrapper());
}
@Override
public IPage<MemberEvaluationListVO> queryPage(EvaluationQueryParams evaluationQueryParams, PageVO page) {
return this.baseMapper.getMemberEvaluationList(PageUtil.initPage(page), evaluationQueryParams.queryWrapper());
public IPage<MemberEvaluationListVO> queryPage(EvaluationQueryParams evaluationQueryParams) {
return memberEvaluationMapper.getMemberEvaluationList(PageUtil.initPage(evaluationQueryParams), evaluationQueryParams.queryWrapper());
}
@Override
@ -103,7 +99,7 @@ public class MemberEvaluationServiceImpl extends ServiceImpl<MemberEvaluationMap
//获取订单信息
Order order = orderService.getBySn(orderItem.getOrderSn());
//检测是否可以添加会员评价
checkMemberEvaluation(orderItem,order);
checkMemberEvaluation(orderItem, order);
//获取用户信息
Member member = memberService.getUserInfo();
//获取商品信息
@ -162,6 +158,7 @@ public class MemberEvaluationServiceImpl extends ServiceImpl<MemberEvaluationMap
EvaluationNumberVO evaluationNumberVO = new EvaluationNumberVO();
List<Map<String, Object>> list = this.baseMapper.getEvaluationNumber(goodsId);
Integer good = 0;
Integer moderate = 0;
Integer worse = 0;
@ -201,10 +198,11 @@ public class MemberEvaluationServiceImpl extends ServiceImpl<MemberEvaluationMap
/**
* 检测会员评价
*
* @param orderItem 子订单
* @param order 订单
* @param order 订单
*/
public void checkMemberEvaluation(OrderItem orderItem,Order order){
public void checkMemberEvaluation(OrderItem orderItem, Order order) {
//根据子订单编号判断是否评价过
if (orderItem.getCommentStatus().equals(CommentStatusEnum.FINISHED.name())) {

View File

@ -4,6 +4,15 @@ import cn.hutool.json.JSONUtil;
import cn.lili.base.BaseEntity;
import cn.lili.common.utils.BeanUtil;
import cn.lili.modules.base.entity.enums.ClientTypeEnum;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum;
import cn.lili.modules.order.order.entity.dto.PriceDetailDTO;
import cn.lili.modules.order.order.entity.enums.DeliverStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderStatusEnum;
import cn.lili.modules.order.order.entity.enums.OrderTypeEnum;
import cn.lili.modules.order.order.entity.enums.PayStatusEnum;
import cn.lili.modules.promotion.entity.dos.PromotionGoods;
import cn.lili.modules.promotion.entity.enums.PromotionTypeEnum;
import cn.lili.modules.order.cart.entity.dto.TradeDTO;
import cn.lili.modules.order.cart.entity.enums.CartTypeEnum;
import cn.lili.modules.order.cart.entity.enums.DeliveryMethodEnum;
@ -21,6 +30,7 @@ import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.Table;
import java.util.Date;
import java.util.Optional;
/**
* 订单
@ -205,17 +215,29 @@ public class Order extends BaseEntity {
* @param tradeDTO 交易DTO
*/
public Order(CartVO cartVO, TradeDTO tradeDTO) {
String orderId = this.getId();
String oldId = this.getId();
BeanUtil.copyProperties(tradeDTO, this);
BeanUtil.copyProperties(cartVO.getPriceDetailDTO(), this);
BeanUtil.copyProperties(cartVO, this);
//订单类型判断--普通订单活动订单
if (tradeDTO.getCartTypeEnum().equals(CartTypeEnum.CART) || tradeDTO.getCartTypeEnum().equals(CartTypeEnum.BUY_NOW)) {
this.setOrderType(OrderTypeEnum.NORMAL.name());
} else {
this.setOrderType(tradeDTO.getCartTypeEnum().name());
}
this.setId(oldId);
this.setOrderType(OrderTypeEnum.NORMAL.name());
//促销信息填充
if (cartVO.getSkuList().get(0).getPromotions() != null && tradeDTO.getCartTypeEnum().equals(CartTypeEnum.PINTUAN)) {
Optional<String> pintuanId = cartVO.getSkuList().get(0).getPromotions().stream().filter(i -> i.getPromotionType().equals(PromotionTypeEnum.PINTUAN.name())).map(PromotionGoods::getPromotionId).findFirst();
if (pintuanId.isPresent()) {
promotionId = pintuanId.get();
this.setOrderType(OrderTypeEnum.PINTUAN.name());
if (tradeDTO.getParentOrderSn() == null) {
this.setParentOrderSn("");
}
}
}
//设置默认支付状态
this.setOrderStatus(OrderStatusEnum.UNPAID.name());
@ -245,7 +267,12 @@ public class Order extends BaseEntity {
}
public PriceDetailDTO getPriceDetailDTO() {
return JSONUtil.toBean(priceDetail, PriceDetailDTO.class);
try {
return JSONUtil.toBean(priceDetail, PriceDetailDTO.class);
} catch (Exception e) {
return null;
}
}
public void setPriceDetailDTO(PriceDetailDTO priceDetail) {

View File

@ -13,8 +13,17 @@ public enum OrderTypeEnum {
*/
NORMAL,
/**
* 赠品订单
*/
GIFT,
/**
* 虚拟订单
*/
VIRTUAL;
VIRTUAL,
/**
* 拼团订单
*/
PINTUAN
}

View File

@ -129,38 +129,43 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
public void intoDB(TradeDTO tradeDTO) {
//检查TradeDTO信息
checkTradeDTO(tradeDTO);
//订单列表
//存放购物车即业务中的订单
List<Order> orders = new ArrayList<>(tradeDTO.getCartList().size());
//订单日志
List<OrderLog> orderLogs = new ArrayList<>(tradeDTO.getCartList().size());
//订单VO列表
List<OrderVO> OrderVOList = new ArrayList<>(tradeDTO.getCartList().size());
//订单货物列表
//存放自订单/订单日志
List<OrderItem> orderItems = new ArrayList<>();
//循环交易货物列表新增订单
List<OrderLog> orderLogs = new ArrayList<>();
//拼团判定不能参与自己创建的拼团
if (tradeDTO.getParentOrderSn() != null) {
Order parentOrder = this.getBySn(tradeDTO.getParentOrderSn());
if (parentOrder.getMemberId().equals(UserContext.getCurrentUser().getId())) {
throw new ServiceException("不能参与自己发起的拼团活动!");
}
}
//订单集合
List<OrderVO> orderVOS = new ArrayList<>();
//循环购物车商品集合
tradeDTO.getCartList().forEach(item -> {
//构建订单
Order order = new Order(item, tradeDTO);
//检查订单信息
checkOrder(order);
//新建订单
if (OrderTypeEnum.PINTUAN.name().equals(order.getOrderType())) {
Pintuan pintuan = pintuanService.getPintuanById(order.getPromotionId());
Integer limitNum = pintuan.getLimitNum();
if (limitNum != 0 && order.getGoodsNum() > limitNum) {
throw new ServiceException("购买数量超过拼团活动限制数量");
}
}
//构建orderVO对象
OrderVO orderVO = new OrderVO();
BeanUtil.copyProperties(order, orderVO);
orders.add(order);
//记录订单日志
orderLogs.add(new OrderLog(item.getSn(),
UserContext.getCurrentUser().getId(),
UserContext.getCurrentUser().getRole().getRole(),
UserContext.getCurrentUser().getUsername(), "订单[" + item.getSn() + "]创建"));
//添加订单货物
String message = "订单[" + item.getSn() + "]创建";
orderLogs.add(new OrderLog(item.getSn(), UserContext.getCurrentUser().getId(), UserContext.getCurrentUser().getRole().getRole(), UserContext.getCurrentUser().getUsername(), message));
item.getSkuList().forEach(
sku -> orderItems.add(new OrderItem(sku, item, tradeDTO))
);
//构建orderVO对象
OrderVO orderVO = new OrderVO(order, orderItems);
OrderVOList.add(orderVO);
orderVO.setOrderItems(orderItems);
orderVOS.add(orderVO);
});
tradeDTO.setOrderVO(OrderVOList);
tradeDTO.setOrderVO(orderVOS);
//批量保存订单
this.saveBatch(orders);
//批量保存 子订单
@ -168,7 +173,6 @@ public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements
// 批量记录订单操作日志
orderLogService.saveBatch(orderLogs);
// 赠品根据店铺单独生成订单
//todo 优化赠品订单代码逻辑
this.generatorGiftOrder(tradeDTO);
}

View File

@ -1,5 +1,6 @@
package cn.lili.modules.payment.kit.params.dto;
import cn.lili.common.utils.StringUtils;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.ToString;
@ -41,4 +42,11 @@ public class CashierParam {
@ApiModelProperty(value = "剩余余额")
private Double walletValue;
public String getDetail() {
if (StringUtils.isEmpty(detail)) {
return "清单详细";
}
return StringUtils.filterSpecialChart(detail);
}
}

View File

@ -4,8 +4,9 @@ import cn.hutool.core.net.URLDecoder;
import cn.hutool.core.net.URLEncoder;
import cn.hutool.json.JSONUtil;
import cn.lili.common.enums.ResultCode;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.exception.ServiceException;
import cn.lili.common.utils.BeanUtil;
import cn.lili.common.utils.SnowFlake;
import cn.lili.common.utils.StringUtils;
import cn.lili.common.vo.ResultMessage;
@ -63,11 +64,9 @@ public class AliPayPlugin implements Payment {
@Autowired
private ApiProperties apiProperties;
@Override
public ResultMessage<Object> h5pay(HttpServletRequest request, HttpServletResponse response, PayParam payParam) {
CashierParam cashierParam = cashierSupport.cashierParam(payParam);
//请求订单编号
String outTradeNo = SnowFlake.getIdStr();
@ -77,12 +76,13 @@ public class AliPayPlugin implements Payment {
payModel.setSubject(cashierParam.getDetail());
payModel.setTotalAmount(cashierParam.getPrice() + "");
//回传数据
payModel.setPassbackParams(URLEncoder.createAll().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8));
payModel.setPassbackParams(URLEncoder.createAll().encode(BeanUtil.formatKeyValuePair(payParam), StandardCharsets.UTF_8));
//3分钟超时
payModel.setTimeoutExpress("3m");
payModel.setOutTradeNo(outTradeNo);
payModel.setProductCode("QUICK_WAP_PAY");
try {
log.info("支付宝H5支付{}", JSONUtil.toJsonStr(payModel));
AliPayRequest.wapPay(response, payModel, callbackUrl(apiProperties.getBuyer(), PaymentMethodEnum.ALIPAY),
notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.ALIPAY));
} catch (Exception e) {
@ -115,11 +115,13 @@ public class AliPayPlugin implements Payment {
//3分钟超时
payModel.setTimeoutExpress("3m");
//回传数据
payModel.setPassbackParams(URLEncoder.createAll().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8));
payModel.setPassbackParams(URLEncoder.createAll().encode(BeanUtil.formatKeyValuePair(payParam), StandardCharsets.UTF_8));
payModel.setOutTradeNo(outTradeNo);
payModel.setProductCode("QUICK_MSECURITY_PAY");
log.info("支付宝APP支付{}", payModel);
String orderInfo = AliPayRequest.appPayToResponse(payModel, notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.ALIPAY)).getBody();
log.info("支付宝APP支付返回内容{}", orderInfo);
return ResultUtil.data(orderInfo);
} catch (AlipayApiException e) {
log.error("支付宝支付异常:", e);
@ -146,12 +148,14 @@ public class AliPayPlugin implements Payment {
payModel.setTotalAmount(cashierParam.getPrice() + "");
//回传数据
payModel.setPassbackParams(URLEncoder.createAll().encode(JSONUtil.toJsonStr(payParam), StandardCharsets.UTF_8));
payModel.setPassbackParams(URLEncoder.createAll().encode(BeanUtil.formatKeyValuePair(payParam), StandardCharsets.UTF_8));
// payModel.setStoreId("store_id");
payModel.setTimeoutExpress("3m");
payModel.setOutTradeNo(outTradeNo);
log.info("支付宝扫码:{}", payModel);
String resultStr = AliPayRequest.tradePrecreatePayToResponse(payModel, notifyUrl(apiProperties.getBuyer(), PaymentMethodEnum.ALIPAY)).getBody();
log.info("支付宝扫码交互返回:{}", resultStr);
JSONObject jsonObject = JSONObject.parseObject(resultStr);
return ResultUtil.data(jsonObject.getJSONObject("alipay_trade_precreate_response").getString("qr_code"));
} catch (Exception e) {
@ -212,7 +216,7 @@ public class AliPayPlugin implements Payment {
}
refundLogService.save(refundLog);
} catch (Exception e) {
log.error("支付宝退款异常",e);
log.error("支付宝退款异常", e);
}
}
@ -249,7 +253,7 @@ public class AliPayPlugin implements Payment {
String payParamStr = map.get("passback_params");
String payParamJson = URLDecoder.decode(payParamStr, StandardCharsets.UTF_8);
PayParam payParam = JSONUtil.toBean(payParamJson, PayParam.class);
PayParam payParam = BeanUtil.formatKeyValuePair(payParamJson, new PayParam());
if (verifyResult) {

View File

@ -13,6 +13,7 @@ import com.alipay.api.request.AlipayTradePrecreateRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeAppPayResponse;
import com.alipay.api.response.AlipayTradePrecreateResponse;
import lombok.extern.slf4j.Slf4j;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@ -24,7 +25,7 @@ import java.io.PrintWriter;
* @author Chopper
* @date 2020/12/15 19:26
*/
@Slf4j
public class AliPayRequest {
/**
@ -40,7 +41,7 @@ public class AliPayRequest {
public static void wapPay(HttpServletResponse response, AlipayTradeWapPayModel model, String returnUrl, String notifyUrl) throws AlipayApiException, IOException {
String form = wapPayStr(model, returnUrl, notifyUrl);
response.setContentType("text/html;charset=UTF-8");
log.info("支付表单{}", form);
PrintWriter out = response.getWriter();
out.write(form);
out.flush();

View File

@ -1,2 +0,0 @@
package cn.lili.modules.payment.kit.plugin.wechat.model;
//这个目录的很多类的属性都是下划线分割不符合本产品的驼峰类型约定后续会进行处理

View File

@ -0,0 +1,5 @@
/**
* 项目部分参考 IJPay
* git地址 https://gitee.com/javen205/IJPay
*/
package cn.lili.modules.payment;

View File

@ -28,14 +28,14 @@ public class CouponActivity extends BasePromotion {
* @see CouponActivityTypeEnum
*/
@NotNull(message = "优惠券活动类型不能为空")
@ApiModelProperty(value = "优惠券活动类型")
@ApiModelProperty(value = "优惠券活动类型", allowableValues = "REGISTERED:新人赠券,SPECIFY精确发券")
private String couponActivityType;
@NotNull(message = "请选择活动范围")
@ApiModelProperty(value = "活动范围", allowableValues = "ALL:全部会员,DESIGNATED指定会员")
private String activityScope;
@ApiModelProperty(value = "活动范围详情")
@ApiModelProperty(value = "活动范围详情,只有精准发券使用")
private String activityScopeInfo;
}

View File

@ -0,0 +1,30 @@
package cn.lili.modules.promotion.entity.vos;
import cn.lili.modules.promotion.entity.dos.CouponActivityItem;
import io.swagger.annotations.ApiModelProperty;
/**
* 优惠券活动的优惠券VO
*
* @author Bulbasaur
* @date: 2021/6/18 11:00 上午
*/
public class CouponActivityItemVO extends CouponActivityItem {
@ApiModelProperty(value = "优惠券名称")
private String couponName;
@ApiModelProperty(value = "面额")
private Double price;
/**
* POINT("打折"), PRICE("减免现金");
*
* @see cn.lili.modules.promotion.entity.enums.CouponTypeEnum
*/
@ApiModelProperty(value = "优惠券类型")
private String couponType;
@ApiModelProperty(value = "折扣")
private Double couponDiscount;
}

View File

@ -20,9 +20,9 @@ import java.util.List;
public class CouponActivityVO extends CouponActivity {
@ApiModelProperty(value = "优惠券活动下的优惠券列表")
private List<CouponActivityItem> couponActivityItems;
private List<CouponActivityItemVO> couponActivityItems;
public CouponActivityVO(CouponActivity couponActivity, List<CouponActivityItem> couponActivityItems) {
public CouponActivityVO(CouponActivity couponActivity, List<CouponActivityItemVO> couponActivityItemVOS) {
BeanUtil.copyProperties(couponActivity, this);
this.couponActivityItems = couponActivityItems;
}

View File

@ -1,7 +1,12 @@
package cn.lili.modules.promotion.mapper;
import cn.lili.modules.promotion.entity.dos.CouponActivityItem;
import cn.lili.modules.promotion.entity.vos.CouponActivityItemVO;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.util.List;
/**
* 优惠券活动
@ -11,5 +16,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface CouponActivityItemMapper extends BaseMapper<CouponActivityItem> {
@Select("SELECT cai.*,c.coupon_name,c.price,c.coupon_type,c.coupon_discount FROM li_coupon_activity_item cai INNER JOIN li_coupon c ON cai.coupon_id = c.id WHERE cai.activity_id= #{activityId} ")
List<CouponActivityItemVO> getCouponActivityItemListVO(String activityId);
}

View File

@ -1,6 +1,7 @@
package cn.lili.modules.promotion.service;
import cn.lili.modules.promotion.entity.dos.CouponActivityItem;
import cn.lili.modules.promotion.entity.vos.CouponActivityItemVO;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
@ -20,4 +21,11 @@ public interface CouponActivityItemService extends IService<CouponActivityItem>
* @return 优惠券关联优惠券列表
*/
List<CouponActivityItem> getCouponActivityList(String activityId);
/**
* 获取优惠券活动关联优惠券列表VO
*
* @param activityId 优惠券活动ID
* @return 优惠券关联优惠券列表
*/
List<CouponActivityItemVO> getCouponActivityItemListVO(String activityId);
}

View File

@ -1,6 +1,7 @@
package cn.lili.modules.promotion.serviceimpl;
import cn.lili.modules.promotion.entity.dos.CouponActivityItem;
import cn.lili.modules.promotion.entity.vos.CouponActivityItemVO;
import cn.lili.modules.promotion.mapper.CouponActivityItemMapper;
import cn.lili.modules.promotion.service.CouponActivityItemService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
@ -17,10 +18,17 @@ import java.util.List;
*/
@Service
public class CouponActivityItemServiceImpl extends ServiceImpl<CouponActivityItemMapper, CouponActivityItem> implements CouponActivityItemService {
@Override
public List<CouponActivityItem> getCouponActivityList(String activityId) {
LambdaQueryWrapper<CouponActivityItem> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(CouponActivityItem::getActivityId, activityId);
return this.list(lambdaQueryWrapper);
}
@Override
public List<CouponActivityItemVO> getCouponActivityItemListVO(String activityId) {
return this.baseMapper.getCouponActivityItemListVO(activityId);
}
}

View File

@ -79,7 +79,7 @@ public class CouponActivityServiceImpl extends ServiceImpl<CouponActivityMapper,
@Override
public CouponActivityVO getCouponActivityVO(String couponActivityId) {
CouponActivity couponActivity = this.getById(couponActivityId);
CouponActivityVO couponActivityVO = new CouponActivityVO(couponActivity, couponActivityItemService.getCouponActivityList(couponActivityId));
CouponActivityVO couponActivityVO = new CouponActivityVO(couponActivity, couponActivityItemService.getCouponActivityItemListVO(couponActivityId));
return couponActivityVO;
}

View File

@ -24,6 +24,7 @@ import java.util.Map;
/**
* 商品索引
*
* @author paulG
* @date 2020/10/13
**/
@ -248,35 +249,6 @@ public class EsGoodsIndex implements Serializable {
private Map<String, Object> promotionMap;
public void setGoodsSku(GoodsSku sku) {
if (sku != null) {
this.id = sku.getId();
this.goodsId = sku.getGoodsId();
this.goodsName = sku.getGoodsName();
this.price = sku.getPrice();
this.storeName = sku.getStoreName();
this.storeId = sku.getStoreId();
this.thumbnail = sku.getThumbnail();
this.categoryPath = sku.getCategoryPath();
this.goodsVideo = sku.getGoodsVideo();
this.mobileIntro = sku.getMobileIntro();
this.buyCount = sku.getBuyCount();
this.commentNum = sku.getCommentNum();
this.small = sku.getSmall();
this.brandId = sku.getBrandId();
this.sn = sku.getSn();
this.storeCategoryPath = sku.getStoreCategoryPath();
this.sellingPoint = sku.getSellingPoint();
this.selfOperated = sku.getSelfOperated();
this.salesModel = sku.getSalesModel();
this.marketEnable = sku.getMarketEnable();
this.isAuth = sku.getIsAuth();
this.intro = sku.getIntro();
this.grade = sku.getGrade();
this.releaseTime = new Date();
}
}
public EsGoodsIndex(GoodsSku sku) {
if (sku != null) {
this.id = sku.getId();
@ -320,4 +292,33 @@ public class EsGoodsIndex implements Serializable {
}
}
public void setGoodsSku(GoodsSku sku) {
if (sku != null) {
this.id = sku.getId();
this.goodsId = sku.getGoodsId();
this.goodsName = sku.getGoodsName();
this.price = sku.getPrice();
this.storeName = sku.getStoreName();
this.storeId = sku.getStoreId();
this.thumbnail = sku.getThumbnail();
this.categoryPath = sku.getCategoryPath();
this.goodsVideo = sku.getGoodsVideo();
this.mobileIntro = sku.getMobileIntro();
this.buyCount = sku.getBuyCount();
this.commentNum = sku.getCommentNum();
this.small = sku.getSmall();
this.brandId = sku.getBrandId();
this.sn = sku.getSn();
this.storeCategoryPath = sku.getStoreCategoryPath();
this.sellingPoint = sku.getSellingPoint();
this.selfOperated = sku.getSelfOperated();
this.salesModel = sku.getSalesModel();
this.marketEnable = sku.getMarketEnable();
this.isAuth = sku.getIsAuth();
this.intro = sku.getIntro();
this.grade = sku.getGrade();
this.releaseTime = new Date();
}
}
}

View File

@ -1,735 +0,0 @@
<template>
<div class="search">
<Row>
<Col>
<Card>
<%
if(searchSize>0&&!hideSearch){
%>
<Row <% if(searchSize>0){ %>v-show="openSearch"<% } %> @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="70">
<%
for(item in fields){
if(item.searchable){
%>
<%
if(item.searchType=="text"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<Input type="text" v-model="searchForm.${item.field}" placeholder="请输入${item.name}" clearable style="width: 200px"/>
</Form-item>
<%
}
%>
<%
if(item.searchType=="select"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<Select v-model="searchForm.${item.field}" placeholder="请选择" clearable style="width: 200px">
<Option value="0">请自行编辑下拉菜单</Option>
</Select>
</Form-item>
<%
}
%>
<%
if(item.searchType=="date"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<DatePicker type="date" v-model="searchForm.${item.field}" placeholder="请选择" readonly clearable style="width: 200px"></DatePicker>
</Form-item>
<%
}
%>
<%
if(item.searchType=="daterange"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<DatePicker v-model="selectDate" type="daterange" format="yyyy-MM-dd" clearable @on-change="selectDateRange" placeholder="选择起始时间" readonly style="width: 200px"></DatePicker>
</Form-item>
<%
}
%>
<%
if(item.searchType=="area"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<al-cascader v-model="searchForm.${item.field}" data-type="code" level="${item.searchLevel}" style="width:200px"/>
</Form-item>
<%
}
%>
<%
}
}
%>
<Form-item style="margin-left:-35px;" class="br">
<Button @click="handleSearch" type="primary" icon="ios-search">搜索</Button>
<Button @click="handleReset">重置</Button>
</Form-item>
</Form>
</Row>
<%
}
%>
<%
if(searchSize>0&&hideSearch){
%>
<Row @keydown.enter.native="handleSearch">
<Form ref="searchForm" :model="searchForm" inline :label-width="70" class="search-form">
<%
for(item in firstTwo){
%>
<%
if(item.searchType=="text"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<Input type="text" v-model="searchForm.${item.field}" placeholder="请输入${item.name}" clearable style="width: 200px"/>
</Form-item>
<%
}
%>
<%
if(item.searchType=="select"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<Select v-model="searchForm.${item.field}" placeholder="请选择" clearable style="width: 200px">
<Option value="0">请自行编辑下拉菜单</Option>
</Select>
</Form-item>
<%
}
%>
<%
if(item.searchType=="date"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<DatePicker type="date" v-model="searchForm.${item.field}" placeholder="请选择" readonly clearable style="width: 200px"></DatePicker>
</Form-item>
<%
}
%>
<%
if(item.searchType=="daterange"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<DatePicker v-model="selectDate" type="daterange" format="yyyy-MM-dd" clearable @on-change="selectDateRange" readonly placeholder="选择起始时间" style="width: 200px"></DatePicker>
</Form-item>
<%
}
%>
<%
if(item.searchType=="area"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<al-cascader v-model="searchForm.${item.field}" data-type="code" level="${item.searchLevel}" style="width:200px"/>
</Form-item>
<%
}
%>
<%
}
%>
<span v-if="drop">
<%
for(item in rest){
%>
<%
if(item.searchType=="text"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<Input type="text" v-model="searchForm.${item.field}" placeholder="请输入${item.name}" clearable style="width: 200px"/>
</Form-item>
<%
}
%>
<%
if(item.searchType=="select"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<Select v-model="searchForm.${item.field}" placeholder="请选择" clearable style="width: 200px">
<Option value="0">请自行编辑下拉菜单</Option>
</Select>
</Form-item>
<%
}
%>
<%
if(item.searchType=="date"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<DatePicker type="date" v-model="searchForm.${item.field}" placeholder="请选择" clearable style="width: 200px" readonly format="yyyy-MM-dd HH:mm:ss"></DatePicker>
</Form-item>
<%
}
%>
<%
if(item.searchType=="daterange"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<DatePicker v-model="selectDate" type="daterange" format="yyyy-MM-dd" clearable @on-change="selectDateRange" placeholder="选择起始时间" readonly style="width: 200px"></DatePicker>
</Form-item>
<%
}
%>
<%
if(item.searchType=="area"){
%>
<Form-item label="${item.name}" prop="${item.field}">
<al-cascader v-model="searchForm.${item.field}" data-type="code" level="${item.searchLevel}" style="width:200px"/>
</Form-item>
<%
}
%>
<%
}
%>
</span>
<Form-item style="margin-left:-35px;" class="br">
<Button @click="handleSearch" type="primary" icon="ios-search">搜索</Button>
<Button @click="handleReset">重置</Button>
<a class="drop-down" @click="dropDown">
{{dropDownContent}}
<Icon :type="dropDownIcon"></Icon>
</a>
</Form-item>
</Form>
</Row>
<%
}
%>
<Row class="operation">
<Button @click="add" type="primary" icon="md-add">添加</Button>
<Button @click="delAll" icon="md-trash">批量删除</Button>
<Button @click="getDataList" icon="md-refresh">刷新</Button>
<% if(searchSize>0){ %>
<Button type="dashed" @click="openSearch=!openSearch">{{openSearch ? "关闭搜索" : "开启搜索"}}</Button>
<% } %>
<Button type="dashed" @click="openTip=!openTip">{{openTip ? "关闭提示" : "开启提示"}}</Button>
</Row>
<Row v-show="openTip">
<Alert show-icon>
已选择 <span class="select-count">{{selectCount}}</span> 项
<a class="select-clear" @click="clearSelectAll">清空</a>
</Alert>
</Row>
<Row>
<Table :loading="loading" border :columns="columns" :data="data" ref="table" sortable="custom" @on-sort-change="changeSort" @on-selection-change="changeSelect"></Table>
</Row>
<Row type="flex" justify="end" class="page">
<Page :current="searchForm.pageNumber" :total="total" :page-size="searchForm.pageSize" @on-change="changePage" @on-page-size-change="changePageSize" :page-size-opts="[10,20,50]" size="small" show-total show-elevator show-sizer></Page>
</Row>
</Card>
</Col>
</Row>
<Modal :title="modalTitle" v-model="modalVisible" :mask-closable='false' :width="${modalWidth}">
<Form ref="form" :model="form" :label-width="100" :rules="formValidate" <% if(rowNum>1){ %>inline<% } %>>
<%
for(item in fields){
if(item.editable){
%>
<FormItem label="${item.name}" prop="${item.field}" <% if(rowNum>1&&(item.type=="switch"||item.type=="radio")){ %>style="width:${itemWidth}"<% } %>>
<%
if(item.type=="text"){
%>
<Input v-model="form.${item.field}" clearable style="width:${width}"/>
<%
}
%>
<%
if(item.type=="select"){
%>
<Select v-model="form.${item.field}" clearable style="width:${width}">
<Option value="0">请自行编辑下拉菜单</Option>
</Select>
<%
}
%>
<%
if(item.type=="switch"){
%>
<i-switch v-model="form.${item.field}"></i-switch>
<%
}
%>
<%
if(item.type=="radio"){
%>
<RadioGroup v-model="form.${item.field}">
<Radio label="0">请自行编辑单选框</Radio>
<Radio label="1">请自行编辑单选框</Radio>
</RadioGroup>
<%
}
%>
<%
if(item.type=="number"){
%>
<InputNumber v-model="form.${item.field}" style="width:${width}"></InputNumber>
<%
}
%>
<%
if(item.type=="date"){
%>
<DatePicker type="date" v-model="form.${item.field}" readonly clearable style="width:${width}"></DatePicker>
<%
}
%>
<%
if(item.type=="daterange"){
%>
<DatePicker type="daterange" v-model="form.${item.field}" readonly clearable style="width:${width}"></DatePicker>
<%
}
%>
<%
if(item.type=="time"){
%>
<TimePicker type="time" v-model="form.${item.field}" clearable style="width:${width}"></TimePicker>
<%
}
%>
<%
if(item.type=="area"){
%>
<al-cascader v-model="form.${item.field}" data-type="code" level="${item.level}" style="width:${width}"/>
<%
}
%>
<%
if(item.type=="slider"){
%>
<Slider v-model="form.${item.field}" style="width:${width}"></Slider>
<%
}
%>
<%
if(item.type=="upload"){
%>
<upload-pic-input v-model="form.${item.field}" style="width:${width}"></upload-pic-input>
<%
}
%>
</FormItem>
<%
}
}
%>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible=false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="handleSubmit">提交</Button>
</div>
</Modal>
</div>
</template>
<script>
<%
if(upload){
%>
import uploadPicInput from "@/views/my-components/lili/upload-pic-input";
<%
}
%>
export default {
name: "${vueName}",
components: {
<%
if(upload){
%>
uploadPicInput
<%
}
%>
},
data() {
return {
<% if(searchSize>0){ %>
openSearch: true, // 显示搜索
<% }%>
openTip: true, // 显示提示
loading: true, // 表单加载状态
modalType: 0, // 添加或编辑标识
modalVisible: false, // 添加或编辑显示
modalTitle: "", // 添加或编辑标题
<% if(hideSearch) { %>
drop: false,
dropDownContent: "展开",
dropDownIcon: "ios-arrow-down",
<% } %>
searchForm: { // 搜索框初始化对象
pageNumber: 1, // 当前页数
pageSize: 10, // 页面大小
sort: "createTime", // 默认排序字段
order: "desc", // 默认排序方式
<% if(daterangeSearch){ %>
startDate: "", // 起始时间
endDate: "" // 终止时间
<% } %>
},
<% if(daterangeSearch){ %>
selectDate: null,
<% } %>
form: { // 添加或编辑表单对象初始化数据
<%
for(item in fields){
if(item.editable){
%>
<% if(item.type=="switch"){ %>
${item.field}: true,
<% }else if(item.type=="number"||item.type=="slider"){ %>
${item.field}: 0,
<% }else if(item.type=="area"){ %>
${item.field}: [],
<% }else{ %>
${item.field}: "",
<% } %>
<%
}
}
%>
},
// 表单验证规则
formValidate: {
<%
for(item in fields){
if(item.editable&&item.validate){
%>
<% if(item.type=="daterange"||item.type=="area"){ %>
${item.field}: [{ type: "array", required: true, message: "不能为空", trigger: "blur" }],
<% }else if(item.type=="date"){ %>
${item.field}: [{ type: "date", required: true, message: "不能为空", trigger: "blur" }],
<% }else if(item.type=="number"||item.type=="slider"){ %>
${item.field}: [{ type: "number", required: true, message: "不能为空", trigger: "blur" }],
<% }else if(item.type=="switch"){ %>
${item.field}: [{ type: "boolean", required: true, message: "不能为空", trigger: "blur" }],
<% }else{ %>
${item.field}: [{ required: true, message: "不能为空", trigger: "blur" }],
<% } %>
<%
}
}
%>
},
submitLoading: false, // 添加或编辑提交状态
selectList: [], // 多选数据
selectCount: 0, // 多选计数
columns: [
// 表头
{
type: "selection",
width: 60,
align: "center"
},
{
type: "index",
width: 60,
align: "center"
},
<%
for(item in fields){
if(item.tableShow){
%>
{
title: "${item.name}",
key: "${item.field}",
minWidth: 120,
<%
if(item.sortable){
%>
sortable: true,
<%
}else{
%>
sortable: false,
<%
}
%>
<%
if(item.defaultSort){
%>
sortType: "${item.defaultSortType}"
<%
}
%>
},
<%
}
}
%>
{
title: "操作",
key: "action",
align: "center",
width: 200,
render: (h, params) => {
return h("div", [
h(
"Button",
{
props: {
type: "primary",
size: "small",
icon: "ios-create-outline"
},
style: {
marginRight: "5px"
},
on: {
click: () => {
this.edit(params.row);
}
}
},
"编辑"
),
h(
"Button",
{
props: {
type: "error",
size: "small",
icon: "md-trash"
},
on: {
click: () => {
this.remove(params.row);
}
}
},
"删除"
)
]);
}
}
],
data: [], // 表单数据
total: 0 // 表单数据总数
};
},
methods: {
init() {
this.getDataList();
},
changePage(v) {
this.searchForm.pageNumber = v;
this.getDataList();
this.clearSelectAll();
},
changePageSize(v) {
this.searchForm.pageSize = v;
this.getDataList();
},
handleSearch() {
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
this.getDataList();
},
handleReset() {
this.$refs.searchForm.resetFields();
this.searchForm.pageNumber = 1;
this.searchForm.pageSize = 10;
<% if(daterangeSearch){ %>
this.selectDate = null;
this.searchForm.startDate = "";
this.searchForm.endDate = "";
<% } %>
// 重新加载数据
this.getDataList();
},
changeSort(e) {
this.searchForm.sort = e.key;
this.searchForm.order = e.order;
if (e.order === "normal") {
this.searchForm.order = "";
}
this.getDataList();
},
clearSelectAll() {
this.$refs.table.selectAll(false);
},
changeSelect(e) {
this.selectList = e;
this.selectCount = e.length;
},
<% if(daterangeSearch){ %>
selectDateRange(v) {
if (v) {
this.searchForm.startDate = v[0];
this.searchForm.endDate = v[1];
}
},
<% } %>
<% if(hideSearch){ %>
dropDown() {
if (this.drop) {
this.dropDownContent = "展开";
this.dropDownIcon = "ios-arrow-down";
} else {
this.dropDownContent = "收起";
this.dropDownIcon = "ios-arrow-up";
}
this.drop = !this.drop;
},
<% } %>
getDataList() {
this.loading = true;
// 带多条件搜索参数获取表单数据 请自行修改接口
this.getRequest("/${vueName}/getByPage", this.searchForm).then(res => {
this.loading = false;
if (res.success) {
this.data = res.result.records;
this.total = res.result.total;
}
});
// 以下为模拟数据
//this.data = [
//];
this.total = this.data.length;
this.loading = false;
},
handleSubmit() {
this.$refs.form.validate(valid => {
if (valid) {
this.submitLoading = true;
if (this.modalType === 0) {
// 添加 避免编辑后传入id等数据 记得删除
delete this.form.id;
this.postRequest("/${vueName}/insertOrUpdate", this.form).then(res => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("操作成功");
this.getDataList();
this.modalVisible = false;
}
});
// 模拟请求成功
//this.submitLoading = false;
//this.$Message.success("操作成功");
//this.getDataList();
//this.modalVisible = false;
} else {
// 编辑
this.postRequest("/${vueName}/insertOrUpdate", this.form).then(res => {
this.submitLoading = false;
if (res.success) {
this.$Message.success("操作成功");
this.getDataList();
this.modalVisible = false;
}
});
// 模拟请求成功
//this.submitLoading = false;
//this.$Message.success("操作成功");
//this.getDataList();
//this.modalVisible = false;
}
}
});
},
add() {
this.modalType = 0;
this.modalTitle = "添加";
this.$refs.form.resetFields();
delete this.form.id;
this.modalVisible = true;
},
edit(v) {
this.modalType = 1;
this.modalTitle = "编辑";
this.$refs.form.resetFields();
// 转换null为""
for (let attr in v) {
if (v[attr] === null) {
v[attr] = "";
}
}
let str = JSON.stringify(v);
let data = JSON.parse(str);
this.form = data;
this.modalVisible = true;
},
remove(v) {
this.$Modal.confirm({
title: "确认删除",
// 记得确认修改此处
content: "您确认要删除么?",
loading: true,
onOk: () => {
// 删除
this.deleteRequest("/${vueName}/delByIds/" + v.id).then(res => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.getDataList();
}
});
// 模拟请求成功
//this.$Message.success("操作成功");
//this.$Modal.remove();
//this.getDataList();
}
});
},
delAll() {
if (this.selectCount <= 0) {
this.$Message.warning("您还未选择要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + this.selectCount + " 条数据?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function(e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
// 批量删除
this.deleteRequest("/${vueName}/delByIds/" + ids).then(res => {
this.$Modal.remove();
if (res.success) {
this.$Message.success("操作成功");
this.clearSelectAll();
this.getDataList();
}
});
// 模拟请求成功
//this.$Message.success("操作成功");
//this.$Modal.remove();
//this.clearSelectAll();
//this.getDataList();
}
});
}
},
mounted() {
this.init();
}
};
</script>
<style lang="less">
// 建议引入通用样式 可删除下面样式代码
// @import "../../../styles/table-common.less";
.search {
.operation {
margin-bottom: 2vh;
}
.select-count {
font-weight: 600;
color: #40a9ff;
}
.select-clear {
margin-left: 10px;
}
.page {
margin-top: 2vh;
}
.drop-down {
margin-left: 5px;
}
}
</style>

View File

@ -1,687 +0,0 @@
<template>
<div class="search">
<Card>
<Row class="operation">
<Button @click="add" type="primary" icon="md-add">添加子节点</Button>
<Button @click="addRoot" icon="md-add">添加一级节点</Button>
<Button @click="delAll" icon="md-trash">批量删除</Button>
<Button @click="getParentList" icon="md-refresh">刷新</Button>
<i-switch v-model="strict" size="large" style="margin-left:5px">
<span slot="open">级联</span>
<span slot="close">单选</span>
</i-switch>
</Row>
<Row type="flex" justify="start">
<Col span="6">
<Alert show-icon>
当前选择编辑:
<span class="select-title">{{editTitle}}</span>
<a class="select-clear" v-if="form.id" @click="cancelEdit">取消选择</a>
</Alert>
<Input
v-model="searchKey"
suffix="ios-search"
@on-change="search"
placeholder="输入节点名搜索"
clearable
/>
<div class="tree-bar" :style="{maxHeight: maxHeight}">
<Tree
ref="tree"
:data="data"
:load-data="loadData"
show-checkbox
@on-check-change="changeSelect"
@on-select-change="selectTree"
:check-strictly="!strict"
></Tree>
<Spin size="large" fix v-if="loading"></Spin>
</div>
</Col>
<Col span="${span}" style="margin-left:10px">
<Form ref="form" :model="form" :label-width="100" :rules="formValidate" <% if(rowNum>1){ %>inline<% } %>>
<FormItem label="上级节点" prop="parentTitle">
<div style="display:flex;">
<Input v-model="form.parentTitle" readonly style="margin-right:10px;"/>
<Poptip transfer trigger="click" placement="right-start" title="选择上级部门" width="250">
<Button icon="md-list">选择部门</Button>
<div slot="content" style="position:relative;min-height:5vh">
<Tree :data="dataEdit" :load-data="loadData" @on-select-change="selectTreeEdit"></Tree>
<Spin size="large" fix v-if="loadingEdit"></Spin>
</div>
</Poptip>
</div>
</FormItem>
<FormItem label="名称" prop="title">
<Input v-model="form.title" />
</FormItem>
<%
for(item in fields){
if(item.editable){
%>
<FormItem label="${item.name}" prop="${item.field}" <% if(rowNum>1&&(item.type=="switch"||item.type=="radio")){ %>style="width:${itemWidth}"<% } %>>
<%
if(item.type=="text"){
%>
<Input v-model="form.${item.field}" style="width:${editWidth}"/>
<%
}
%>
<%
if(item.type=="select"){
%>
<Select v-model="form.${item.field}" style="width:${editWidth}">
<Option value="0">请自行编辑下拉菜单</Option>
</Select>
<%
}
%>
<%
if(item.type=="number"){
%>
<InputNumber v-model="form.${item.field}" style="width:${editWidth}"></InputNumber>
<%
}
%>
<%
if(item.type=="switch"){
%>
<i-switch v-model="form.${item.field}"></i-switch>
<%
}
%>
<%
if(item.type=="radio"){
%>
<RadioGroup v-model="form.${item.field}">
<Radio label="0">请自行编辑单选框</Radio>
<Radio label="1">请自行编辑单选框</Radio>
</RadioGroup>
<%
}
%>
<%
if(item.type=="date"){
%>
<DatePicker type="date" v-model="form.${item.field}" style="width:${editWidth}"></DatePicker>
<%
}
%>
<%
if(item.type=="daterange"){
%>
<DatePicker type="daterange" v-model="form.${item.field}" style="width:${editWidth}"></DatePicker>
<%
}
%>
<%
if(item.type=="time"){
%>
<TimePicker type="time" v-model="form.${item.field}" style="width:${editWidth}"></TimePicker>
<%
}
%>
<%
if(item.type=="area"){
%>
<al-cascader v-model="form.${item.field}" data-type="code" level="${item.level}" style="width:${editWidth}"/>
<%
}
%>
<%
if(item.type=="slider"){
%>
<Slider v-model="form.${item.field}" style="width:${editWidth}"></Slider>
<%
}
%>
<%
if(item.type=="upload"){
%>
<upload-pic-input v-model="form.${item.field}" style="width:${editWidth}"></upload-pic-input>
<%
}
%>
</FormItem>
<%
}
}
%>
<FormItem label="排序值" prop="sortOrder">
<Poptip trigger="hover" placement="right" content="值越小越靠前,支持小数">
<InputNumber :max="1000" :min="0" v-model="form.sortOrder"></InputNumber>
</Poptip>
</FormItem>
<br>
<Form-item>
<Button
@click="submitEdit"
:loading="submitLoading"
type="primary"
icon="ios-create-outline"
style="margin-right:5px"
>修改并保存</Button>
<Button @click="handleReset">重置</Button>
</Form-item>
</Form>
</Col>
</Row>
</Card>
<Modal :title="modalTitle" v-model="modalVisible" :mask-closable="false" :width="${modalWidth}">
<Form ref="formAdd" :model="formAdd" :label-width="100" :rules="formValidate" <% if(rowNum>1){ %>inline<% } %>>
<div v-if="showParent">
<FormItem label="上级节点:">{{form.title}}</FormItem>
</div>
<FormItem label="名称" prop="title">
<Input v-model="form.title" />
</FormItem>
<%
for(item in fields){
if(item.editable){
%>
<FormItem label="${item.name}" prop="${item.field}" <% if(rowNum>1&&(item.type=="number"||item.type=="switch"||item.type=="radio")){ %>style="width:${itemWidth}"<% } %>>
<%
if(item.type=="text"){
%>
<Input v-model="formAdd.${item.field}" style="width:${width}"/>
<%
}
%>
<%
if(item.type=="select"){
%>
<Select v-model="formAdd.${item.field}" style="width:${width}">
<Option value="0">请自行编辑下拉菜单</Option>
</Select>
<%
}
%>
<%
if(item.type=="number"){
%>
<InputNumber v-model="formAdd.${item.field}"></InputNumber>
<%
}
%>
<%
if(item.type=="switch"){
%>
<i-switch v-model="formAdd.${item.field}"></i-switch>
<%
}
%>
<%
if(item.type=="radio"){
%>
<RadioGroup v-model="formAdd.${item.field}">
<Radio label="0">请自行编辑单选框</Radio>
<Radio label="1">请自行编辑单选框</Radio>
</RadioGroup>
<%
}
%>
<%
if(item.type=="date"){
%>
<DatePicker type="date" v-model="formAdd.${item.field}" style="width:${width}"></DatePicker>
<%
}
%>
<%
if(item.type=="daterange"){
%>
<DatePicker type="daterange" v-model="formAdd.${item.field}" style="width:${width}"></DatePicker>
<%
}
%>
<%
if(item.type=="time"){
%>
<TimePicker type="time" v-model="formAdd.${item.field}" style="width:${width}"></TimePicker>
<%
}
%>
<%
if(item.type=="area"){
%>
<al-cascader v-model="formAdd.${item.field}" data-type="code" level="${item.level}" style="width:${width}"/>
<%
}
%>
<%
if(item.type=="slider"){
%>
<Slider v-model="formAdd.${item.field}" style="width:${width}"></Slider>
<%
}
%>
<%
if(item.type=="upload"){
%>
<upload-pic-input v-model="formAdd.${item.field}" style="width:${width}"></upload-pic-input>
<%
}
%>
</FormItem>
<%
}
}
%>
<FormItem label="排序值" prop="sortOrder">
<Poptip trigger="hover" placement="right" content="值越小越靠前,支持小数">
<InputNumber :max="1000" :min="0" v-model="formAdd.sortOrder"></InputNumber>
</Poptip>
</FormItem>
</Form>
<div slot="footer">
<Button type="text" @click="modalVisible=false">取消</Button>
<Button type="primary" :loading="submitLoading" @click="submitAdd">提交</Button>
</div>
</Modal>
</div>
</template>
<script>
<%
if(upload){
%>
import uploadPicInput from "@/views/my-components/lili/upload-pic-input";
<%
}
%>
export default {
name: "${vueName}",
components: {
<%
if(upload){
%>
uploadPicInput
<%
}
%>
},
data() {
return {
maxHeight: "500px",
strict: true,
loading: false, // 树加载状态
loadingEdit: false, // 编辑上级树加载状态
modalVisible: false, // 添加显示
selectList: [], // 多选数据
selectCount: 0, // 多选计数
showParent: false, // 显示上级标识
modalTitle: "", // 添加标题
editTitle: "", // 编辑节点名称
searchKey: "", // 搜索树
form: {
// 编辑对象初始化数据
id: "",
title: "",
parentId: "",
parentTitle: "",
sortOrder: 0,
<%
for(item in fields){
if(item.editable){
%>
<% if(item.type=="switch"){ %>
${item.field}: true,
<% }else if(item.type=="number"||item.type=="slider"){ %>
${item.field}: 0,
<% }else if(item.type=="area"){ %>
${item.field}: [],
<% }else{ %>
${item.field}: "",
<% } %>
<%
}
}
%>
},
formAdd: {
// 添加对象初始化数据
},
formValidate: {
// 表单验证规则
title: [{ required: true, message: "不能为空", trigger: "blur" }],
sortOrder: [
{
required: true,
type: "number",
message: "排序值不能为空",
trigger: "blur"
}
],
<%
for(item in fields){
if(item.editable&&item.validate){
%>
<% if(item.type=="daterange"||item.type=="area"){ %>
${item.field}: [{ type: "array", required: true, message: "不能为空", trigger: "blur" }],
<% }else if(item.type=="date"){ %>
${item.field}: [{ type: "date", required: true, message: "不能为空", trigger: "blur" }],
<% }else if(item.type=="number"||item.type=="slider"){ %>
${item.field}: [{ type: "number", required: true, message: "不能为空", trigger: "blur" }],
<% }else if(item.type=="switch"){ %>
${item.field}: [{ type: "boolean", required: true, message: "不能为空", trigger: "blur" }],
<% }else{ %>
${item.field}: [{ required: true, message: "不能为空", trigger: "blur" }],
<% } %>
<%
}
}
%>
},
submitLoading: false,
data: [],
dataEdit: []
};
},
methods: {
init() {
// 初始化一级节点
this.getParentList();
// 初始化一级节点为编辑上级节点使用
this.getParentListEdit();
},
getParentList() {
// this.loading = true;
// this.getRequest("一级数据请求路径,如/tree/getByParentId/0").then(res => {
// this.loading = false;
// if (res.success) {
// res.result.forEach(function(e) {
// if (e.isParent) {
// e.loading = false;
// e.children = [];
// }
// });
// this.data = res.result;
// }
// });
// 模拟请求成功
this.data = [
];
},
getParentListEdit() {
// this.loadingEdit = true;
// this.getRequest("/tree/getByParentId/0").then(res => {
// this.loadingEdit = false;
// if (res.success) {
// res.result.forEach(function(e) {
// if (e.isParent) {
// e.loading = false;
// e.children = [];
// }
// });
// // 头部加入一级
// let first = {
// id: "0",
// title: "一级节点"
// };
// res.result.unshift(first);
// this.dataEdit = res.result;
// }
// });
// 模拟请求成功
this.dataEdit = [
];
},
loadData(item, callback) {
// 异步加载树子节点数据
// this.getRequest("请求路径,如/tree/getByParentId/" + item.id).then(res => {
// if (res.success) {
// res.result.forEach(function(e) {
// if (e.isParent) {
// e.loading = false;
// e.children = [];
// }
// });
// callback(res.result);
// }
// });
},
search() {
// 搜索树
if (this.searchKey) {
// 模拟请求
// this.loading = true;
// this.getRequest("搜索请求路径", { title: this.searchKey }).then(res => {
// this.loading = false;
// if (res.success) {
// this.data = res.result;
// }
// });
// 模拟请求成功
this.data = [
];
} else {
// 为空重新加载
this.getParentList();
}
},
selectTree(v) {
if (v.length > 0) {
// 转换null为""
for (let attr in v[0]) {
if (v[0][attr] === null) {
v[0][attr] = "";
}
}
let str = JSON.stringify(v[0]);
let data = JSON.parse(str);
this.form = data;
this.editTitle = data.title;
} else {
this.cancelEdit();
}
},
cancelEdit() {
let data = this.$refs.tree.getSelectedNodes()[0];
if (data) {
data.selected = false;
}
this.$refs.form.resetFields();
this.form.id = "";
this.editTitle = "";
},
selectTreeEdit(v) {
if (v.length > 0) {
// 转换null为""
for (let attr in v[0]) {
if (v[0][attr] === null) {
v[0][attr] = "";
}
}
let str = JSON.stringify(v[0]);
let data = JSON.parse(str);
this.form.parentId = data.id;
this.form.parentTitle = data.title;
}
},
handleReset() {
this.$refs.form.resetFields();
this.form.status = 0;
},
submitEdit() {
this.$refs.form.validate(valid => {
if (valid) {
if (!this.form.id) {
this.$Message.warning("请先点击选择要修改的节点");
return;
}
this.submitLoading = true;
// 避免传入null字符串
// this.postRequest("请求路径,如/tree/edit", this.form).then(res => {
// this.submitLoading = false;
// if (res.success) {
// this.$Message.success("编辑成功");
// this.init();
// this.modalVisible = false;
// }
// });
// 模拟成功
this.submitLoading = false;
this.$Message.success("编辑成功");
this.modalVisible = false;
}
});
},
submitAdd() {
this.$refs.formAdd.validate(valid => {
if (valid) {
this.submitLoading = true;
// this.postRequest("请求路径,如/tree/add", this.formAdd).then(res => {
// this.submitLoading = false;
// if (res.success) {
// this.$Message.success("添加成功");
// this.init();
// this.modalVisible = false;
// }
// });
// 模拟成功
this.submitLoading = false;
this.$Message.success("添加成功");
this.modalVisible = false;
}
});
},
add() {
if (this.form.id == "" || this.form.id == null) {
this.$Message.warning("请先点击选择一个节点");
return;
}
this.modalTitle = "添加子节点";
this.showParent = true;
this.formAdd = {
parentId: this.form.id,
sortOrder: 0,
<%
for(item in fields){
if(item.editable){
%>
<% if(item.type=="switch"){ %>
${item.field}: true,
<% }else if(item.type=="number"||item.type=="slider"){ %>
${item.field}: 0,
<% }else if(item.type=="area"){ %>
${item.field}: [],
<% }else{ %>
${item.field}: "",
<% } %>
<%
}
}
%>
};
this.modalVisible = true;
},
addRoot() {
this.modalTitle = "添加一级节点";
this.showParent = false;
this.formAdd = {
parentId: 0,
sortOrder: 0,
title: "",
<%
for(item in fields){
if(item.editable){
%>
<% if(item.type=="switch"){ %>
${item.field}: true,
<% }else if(item.type=="number"||item.type=="slider"){ %>
${item.field}: 0,
<% }else if(item.type=="area"){ %>
${item.field}: [],
<% }else{ %>
${item.field}: "",
<% } %>
<%
}
}
%>
};
this.modalVisible = true;
},
changeSelect(v) {
this.selectCount = v.length;
this.selectList = v;
},
delAll() {
if (this.selectCount <= 0) {
this.$Message.warning("您还未勾选要删除的数据");
return;
}
this.$Modal.confirm({
title: "确认删除",
content: "您确认要删除所选的 " + this.selectCount + " 条数据及其下级所有数据?",
loading: true,
onOk: () => {
let ids = "";
this.selectList.forEach(function(e) {
ids += e.id + ",";
});
ids = ids.substring(0, ids.length - 1);
// this.deleteRequest("请求路径,如/tree/delByIds/" + ids).then(res => {
// this.$Modal.remove();
// if (res.success) {
// this.$Message.success("删除成功");
// this.selectList = [];
// this.selectCount = 0;
// this.cancelEdit();
// this.init();
// }
// });
// 模拟成功
this.$Modal.remove();
this.$Message.success("删除成功");
this.selectList = [];
this.selectCount = 0;
this.cancelEdit();
}
});
}
},
mounted() {
// 计算高度
let height = document.documentElement.clientHeight;
this.maxHeight = Number(height-287) + "px";
this.init();
}
};
</script>
<style lang="less">
// 建议引入通用样式 可删除下面样式代码
// @import "../../../styles/tree-common.less";
.search {
.operation {
margin-bottom: 2vh;
}
.select-title {
font-size: 12px;
font-weight: 600;
color: #40a9ff;
}
.select-clear {
margin-left: 10px;
}
}
.tree-bar {
overflow: auto;
margin-top: 5px;
position: relative;
min-height: 80px;
}
.tree-bar::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.tree-bar::-webkit-scrollbar-thumb {
border-radius: 4px;
-webkit-box-shadow: inset 0 0 2px #d1d1d1;
background: #e4e4e4;
}
</style>

View File

@ -97,13 +97,8 @@ public class BrandManagerController {
@ApiImplicitParam(name = "ids", value = "品牌ID", required = true, dataType = "String", allowMultiple = true, paramType = "path")
@DeleteMapping(value = "/delByIds/{ids}")
public ResultMessage<Object> delAllByIds(@PathVariable List<String> ids) {
for (String id : ids) {
Brand brand = brandService.getById(id);
brand.setDeleteFlag(true);
brandService.updateById(brand);
}
return ResultUtil.success(ResultCode.BRAND_DELETE_ERROR);
brandService.removeByIds(ids);
return ResultUtil.success(ResultCode.SUCCESS);
}
}

View File

@ -42,7 +42,7 @@ public class MemberEvaluationManagerController {
@GetMapping(value = "/getByPage")
public ResultMessage<IPage<MemberEvaluationListVO>> getByPage(EvaluationQueryParams evaluationQueryParams, PageVO page) {
return ResultUtil.data(memberEvaluationService.queryPage(evaluationQueryParams, page));
return ResultUtil.data(memberEvaluationService.queryPage(evaluationQueryParams));
}
@ApiOperation(value = "修改评价状态")

View File

@ -1,9 +1,15 @@
package cn.lili.controller.other;
import cn.hutool.json.JSONUtil;
import cn.lili.modules.goods.entity.dos.Goods;
import cn.lili.modules.goods.entity.dos.GoodsParams;
import cn.lili.modules.goods.entity.dos.GoodsSku;
import cn.lili.modules.goods.entity.dos.Parameters;
import cn.lili.modules.goods.entity.enums.GoodsAuthEnum;
import cn.lili.modules.goods.entity.enums.GoodsStatusEnum;
import cn.lili.modules.goods.service.GoodsService;
import cn.lili.modules.goods.service.GoodsSkuService;
import cn.lili.modules.goods.service.ParametersService;
import cn.lili.modules.promotion.service.PromotionService;
import cn.lili.modules.search.entity.dos.EsGoodsIndex;
import cn.lili.modules.search.service.EsGoodsIndexService;
@ -38,12 +44,18 @@ public class ElasticsearchController {
@Autowired
private GoodsSkuService goodsSkuService;
@Autowired
private GoodsService goodsService;
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private PromotionService promotionService;
@Autowired
private ParametersService parametersService;
@GetMapping
public void init() {
//查询商品信息
@ -53,16 +65,33 @@ public class ElasticsearchController {
List<GoodsSku> list = goodsSkuService.list(queryWrapper);
List<EsGoodsIndex> esGoodsIndices = new ArrayList<>();
String goodsId = null;
//库存锁是在redis做的所以生成索引同时更新一下redis中的库存数量
for (GoodsSku goodsSku : list) {
EsGoodsIndex index = new EsGoodsIndex(goodsSku);
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index);
index.setPromotionMap(goodsCurrentPromotionMap);
esGoodsIndices.add(index);
stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString());
boolean needIndex = false;
if (goodsId == null || !goodsId.equals(goodsSku.getGoodsId())) {
goodsId = goodsSku.getGoodsId();
Goods goods = goodsService.getById(goodsId);
if (goods.getParams() != null && !goods.getParams().isEmpty()) {
List<GoodsParams> goodsParams = JSONUtil.toList(goods.getParams(), GoodsParams.class);
for (GoodsParams goodsParam : goodsParams) {
Parameters parameters = parametersService.getById(goodsParam.getParamId());
if (parameters.getIsIndex() == 1) {
needIndex = true;
break;
}
}
}
}
if (Boolean.TRUE.equals(needIndex)) {
EsGoodsIndex index = new EsGoodsIndex(goodsSku);
Map<String, Object> goodsCurrentPromotionMap = promotionService.getGoodsCurrentPromotionMap(index);
index.setPromotionMap(goodsCurrentPromotionMap);
esGoodsIndices.add(index);
stringRedisTemplate.opsForValue().set(GoodsSkuService.getStockCacheKey(goodsSku.getId()), goodsSku.getQuantity().toString());
}
}
//初始化商品索引
esGoodsIndexService.initIndex(esGoodsIndices);
Assertions.assertTrue(true);
}
}

View File

@ -2,6 +2,7 @@ package cn.lili.controller.setting;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.base.aspect.DemoSite;
import cn.lili.modules.base.service.RegionService;
import cn.lili.modules.system.entity.dos.Region;
import io.swagger.annotations.Api;
@ -29,6 +30,7 @@ public class RegionManagerController {
@Autowired
private RegionService regionService;
@DemoSite
@PostMapping(value = "/sync")
@ApiOperation(value = "同步高德行政地区数据")
public void synchronizationData(String url) {

View File

@ -2,7 +2,7 @@ package cn.lili.controller.trade;
import cn.lili.common.enums.ResultUtil;
import cn.lili.common.vo.ResultMessage;
import cn.lili.modules.member.entity.dto.StoreEvaluationQueryParams;
import cn.lili.modules.member.entity.dto.EvaluationQueryParams;
import cn.lili.modules.member.entity.vo.MemberEvaluationListVO;
import cn.lili.modules.member.entity.vo.MemberEvaluationVO;
import cn.lili.modules.member.service.MemberEvaluationService;
@ -30,9 +30,8 @@ public class MemberEvaluationStoreController {
@ApiOperation(value = "分页获取会员评论列表")
@GetMapping
public ResultMessage<IPage<MemberEvaluationListVO>> getByPage(StoreEvaluationQueryParams storeEvaluationQueryParams) {
return ResultUtil.data(memberEvaluationService.queryByParams(storeEvaluationQueryParams));
public ResultMessage<IPage<MemberEvaluationListVO>> getByPage(EvaluationQueryParams evaluationQueryParams) {
return ResultUtil.data(memberEvaluationService.queryPage(evaluationQueryParams));
}
@ApiOperation(value = "通过id获取")