diff --git a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/SpuInfoRespDTO.java b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/SpuInfoRespDTO.java index 6aae7191b..92c20a0d7 100644 --- a/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/SpuInfoRespDTO.java +++ b/yudao-module-mall/yudao-module-product-api/src/main/java/cn/iocoder/yudao/module/product/api/spu/dto/SpuInfoRespDTO.java @@ -31,7 +31,7 @@ public class SpuInfoRespDTO { */ private String code; /** - * 商品卖点 + * 促销语 */ private String sellPoint; /** diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java index 826cdd6c4..54f0986dd 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuBaseVO.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo; import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; import io.swagger.annotations.ApiModelProperty; @@ -25,7 +24,7 @@ public class ProductSpuBaseVO { @ApiModelProperty(value = "商品编码", example = "yudaoyuanma") private String code; - @ApiModelProperty(value = "商品卖点", example = "好吃!") + @ApiModelProperty(value = "促销语", example = "好吃!") private String sellPoint; @ApiModelProperty(value = "商品详情", required = true, example = "我是商品描述") diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java index f6b966a41..8d1bbee5f 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/admin/spu/vo/ProductSpuPageReqVO.java @@ -1,12 +1,11 @@ package cn.iocoder.yudao.module.product.controller.admin.spu.vo; -import lombok.*; -import java.util.*; -import io.swagger.annotations.*; import cn.iocoder.yudao.framework.common.pojo.PageParam; -import org.springframework.format.annotation.DateTimeFormat; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; @ApiModel("管理后台 - 商品 SPU 分页 Request VO") @Data @@ -26,7 +25,7 @@ public class ProductSpuPageReqVO extends PageParam { @ApiModelProperty(value = "商品品牌编号", example = "1") private Long brandId; - @ApiModelProperty(value = "上下架状态", example = "1", notes = "参见 CommonStatusEnum 枚举值") + @ApiModelProperty(value = "上下架状态", example = "1", notes = "参见 ProductSpuStatusEnum 枚举值") private Integer status; @ApiModelProperty(value = "销量最小值", example = "1") @@ -41,8 +40,7 @@ public class ProductSpuPageReqVO extends PageParam { @ApiModelProperty(value = "市场价最大值", example = "1024") private Integer marketPriceMax; - // TODO @luowenfeng: 这个可以改成前端基于 tab, 传递不同的条件么? - @ApiModelProperty(value = "tab 状态 null 全部, 0:销售中(上架) 1:仓库中(下架) 2:预警中", example = "1") - private Integer tabStatus; + @ApiModelProperty(value = "是否库存告警", example = "true") + private Boolean alarmStock; } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java index a22b68a2c..93c47d4af 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/dataobject/spu/ProductSpuDO.java @@ -47,7 +47,7 @@ public class ProductSpuDO extends BaseDO { */ private String code; /** - * 商品卖点 + * 促销语 */ private String sellPoint; /** diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java index b9dde2e68..dfc8fd4ff 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/sku/ProductSkuMapper.java @@ -40,7 +40,7 @@ public interface ProductSkuMapper extends BaseMapperX<ProductSkuDO> { } } - default List<ProductSkuDO> selectListByRemind(){ + default List<ProductSkuDO> selectListByAlarmStock(){ return selectList(new QueryWrapper<ProductSkuDO>().apply("stock <= warn_stock")); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java index dc39133d5..eea12f62f 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/dal/mysql/spu/ProductSpuMapper.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.product.controller.admin.spu.vo.ProductSpuPageReq import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; import org.apache.ibatis.annotations.Mapper; -import java.util.List; +import java.util.Set; /** * 商品spu Mapper @@ -29,8 +29,8 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> { .orderByDesc(ProductSpuDO::getSort)); } - default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO, List<Long> spuIds) { - LambdaQueryWrapperX<ProductSpuDO> productSpuDOLambdaQueryWrapperX = new LambdaQueryWrapperX<ProductSpuDO>() + default PageResult<ProductSpuDO> selectPage(ProductSpuPageReqVO reqVO, Set<Long> alarmStockSpuIds) { + return selectPage(reqVO, new LambdaQueryWrapperX<ProductSpuDO>() .likeIfPresent(ProductSpuDO::getName, reqVO.getName()) .eqIfPresent(ProductSpuDO::getCategoryId, reqVO.getCategoryId()) .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) @@ -38,16 +38,9 @@ public interface ProductSpuMapper extends BaseMapperX<ProductSpuDO> { .geIfPresent(ProductSpuDO::getSalesCount, reqVO.getSalesCountMin()) .leIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMax()) .geIfPresent(ProductSpuDO::getMarketPrice, reqVO.getMarketPriceMin()) - .orderByDesc(ProductSpuDO::getSort); - // TODO @芋艿: 需要优化下这里的代码 - if(reqVO.getTabStatus()!= null && reqVO.getTabStatus() == 2){ - productSpuDOLambdaQueryWrapperX.inIfPresent(ProductSpuDO::getId, spuIds); - }else{ - productSpuDOLambdaQueryWrapperX.eqIfPresent(ProductSpuDO::getStatus, reqVO.getTabStatus()); - } - - return selectPage(reqVO, productSpuDOLambdaQueryWrapperX); + .inIfPresent(ProductSpuDO::getId, alarmStockSpuIds) // 库存告警 + .eqIfPresent(ProductSpuDO::getStatus, reqVO.getStatus()) + .orderByDesc(ProductSpuDO::getSort)); } - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java index 9da746427..acde66a4a 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuService.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.product.service.sku; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuCreateOrUpdateReqVO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; -import javax.validation.Valid; import java.util.Collection; import java.util.List; @@ -84,10 +83,10 @@ public interface ProductSkuService { void deleteSkuBySpuId(Long spuId); /** - * 获得商品预警中的 SPU 集合 + * 获得库存预警的 SKU 数组 * - * @return 商品spuId集合 + * @return SKU 数组 */ - List<ProductSkuDO> getRemindSpuIds(); + List<ProductSkuDO> getSkusByAlarmStock(); } diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java index 8889e5a73..952fbeb74 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/sku/ProductSkuServiceImpl.java @@ -1,11 +1,7 @@ package cn.iocoder.yudao.module.product.service.sku; -import cn.hutool.core.collection.CollUtil; -import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.product.controller.admin.property.vo.property.ProductPropertyRespVO; import cn.iocoder.yudao.module.product.controller.admin.property.vo.value.ProductPropertyValueRespVO; import cn.iocoder.yudao.module.product.controller.admin.sku.vo.ProductSkuBaseVO; @@ -17,18 +13,15 @@ import cn.iocoder.yudao.module.product.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuSpecTypeEnum; import cn.iocoder.yudao.module.product.service.property.ProductPropertyService; import cn.iocoder.yudao.module.product.service.property.ProductPropertyValueService; -import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.util.*; -import java.util.function.Function; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.product.enums.ErrorCodeConstants.*; /** @@ -138,8 +131,8 @@ public class ProductSkuServiceImpl implements ProductSkuService { } @Override - public List<ProductSkuDO> getRemindSpuIds() { - return productSkuMapper.selectListByRemind(); + public List<ProductSkuDO> getSkusByAlarmStock() { + return productSkuMapper.selectListByAlarmStock(); } @Override diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java index aa8e59e5f..2e6e4b174 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.product.service.spu; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.product.controller.admin.property.vo.ProductPropertyViewRespVO; @@ -28,10 +29,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; -import java.util.Map; +import java.util.*; import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -180,18 +178,21 @@ public class ProductSpuServiceImpl implements ProductSpuService { @Override public PageResult<ProductSpuRespVO> getSpuPage(ProductSpuPageReqVO pageReqVO) { - List<Long> remindSpuIds = null; - if (pageReqVO.getTabStatus() != null && pageReqVO.getTabStatus() == 2) { - remindSpuIds = productSkuService.getRemindSpuIds().stream().map(ProductSkuDO::getSpuId).distinct().collect(Collectors.toList()); - if (remindSpuIds.isEmpty()) { - remindSpuIds.add(null); + // 库存告警的 SPU 编号的集合 + Set<Long> alarmStockSpuIds = null; + if (Boolean.TRUE.equals(pageReqVO.getAlarmStock())) { + alarmStockSpuIds = CollectionUtils.convertSet(productSkuService.getSkusByAlarmStock(), ProductSkuDO::getSpuId); + if (CollUtil.isEmpty(alarmStockSpuIds)) { + return PageResult.empty(); } } - return ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(pageReqVO, remindSpuIds)); + // 分页查询 + return ProductSpuConvert.INSTANCE.convertPage(productSpuMapper.selectPage(pageReqVO, alarmStockSpuIds)); } @Override public PageResult<AppSpuPageRespVO> getSpuPage(AppSpuPageReqVO pageReqVO) { + // TODO 芋艿:貌似实现不太合理 PageResult<ProductSpuDO> productSpuDOPageResult = productSpuMapper.selectPage(ProductSpuConvert.INSTANCE.convert(pageReqVO)); PageResult<AppSpuPageRespVO> pageResult = new PageResult<>(); // TODO @芋艿 这里用convert如何解决 diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java index 0bddf59ce..a254f636d 100755 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/spu/ProductSpuServiceImplTest.java @@ -208,6 +208,8 @@ public class ProductSpuServiceImplTest extends BaseDbUnitTest { Assertions.assertIterableEquals(createReqVO, spuList); } + // TODO @luowenfeng:单测要分情况;类似你这个,可以分 2 个单测;一个是有预存预警的;一个是没库存预警的; + // 然后,参考其它模块的 getPage 类型的方法的单测。 @Test void getSpuPage() { // 准备参数 diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java index 86a0e844c..f47152150 100644 --- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java +++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/order/TradeOrderServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.trade.service.order; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.text.StrBuilder; import cn.hutool.core.util.IdUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.TerminalEnum; import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; @@ -15,8 +14,8 @@ import cn.iocoder.yudao.module.market.api.price.dto.PriceCalculateRespDTO; import cn.iocoder.yudao.module.pay.api.order.PayOrderApi; import cn.iocoder.yudao.module.pay.api.order.PayOrderInfoCreateReqDTO; import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi; -import cn.iocoder.yudao.module.product.api.sku.dto.SkuDecrementStockBatchReqDTO; import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO; +import cn.iocoder.yudao.module.product.api.sku.dto.SkuDecrementStockBatchReqDTO; import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi; import cn.iocoder.yudao.module.product.api.spu.dto.SpuInfoRespDTO; import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum; @@ -181,7 +180,7 @@ public class TradeOrderServiceImpl implements TradeOrderService { private void checkSaleableFromSpu(List<SpuInfoRespDTO> spuInfos) { SpuInfoRespDTO spu = CollectionUtils.findFirst(spuInfos, - spuInfoDTO -> !Objects.equals(ProductSpuStatusEnum.ENABLE.getStyle(), spuInfoDTO.getStatus())); + spuInfoDTO -> !Objects.equals(ProductSpuStatusEnum.ENABLE.getStatus(), spuInfoDTO.getStatus())); if (Objects.isNull(spu)) { throw ServiceExceptionUtil.exception(ErrorCodeConstants.ORDER_SPU_NOT_SALE); } diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index 36ab6a8b2..fe88a0609 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -45,33 +45,33 @@ spring: datasource: master: name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + url: jdbc:mysql://139.9.196.247:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.master.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.master.name} # SQLServer 连接的示例 username: root - password: 123456 + password: ${RUOYI_VUE_PRO} # username: sa # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W slave: # 模拟从库,可根据自己需要修改 name: ruoyi-vue-pro - url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 + url: jdbc:mysql://139.9.196.247:3306/${spring.datasource.dynamic.datasource.master.name}?allowMultiQueries=true&useUnicode=true&useSSL=false&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&autoReconnect=true&nullCatalogMeansCurrent=true # MySQL Connector/J 8.X 连接的示例 # url: jdbc:mysql://127.0.0.1:3306/${spring.datasource.dynamic.datasource.slave.name}?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=CTT # MySQL Connector/J 5.X 连接的示例 # url: jdbc:postgresql://127.0.0.1:5432/${spring.datasource.dynamic.datasource.slave.name} # PostgreSQL 连接的示例 # url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例 # url: jdbc:sqlserver://127.0.0.1:1433;DatabaseName=${spring.datasource.dynamic.datasource.slave.name} # SQLServer 连接的示例 username: root - password: 123456 + password: ${RUOYI_VUE_PRO} # username: sa # password: JSm:g(*%lU4ZAkz06cd52KqT3)i1?H7W # Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优 redis: - host: 127.0.0.1 # 地址 + host: 139.9.196.247 # 地址 port: 6379 # 端口 database: 0 # 数据库索引 -# password: 123456 # 密码,建议生产环境开启 + password: 123456 # 密码,建议生产环境开启 jasypt: encryptor: diff --git a/yudao-ui-admin/src/utils/constants.js b/yudao-ui-admin/src/utils/constants.js index 67ecfdd46..9f5d796ed 100644 --- a/yudao-ui-admin/src/utils/constants.js +++ b/yudao-ui-admin/src/utils/constants.js @@ -185,37 +185,54 @@ export const PayOrderRefundStatusEnum = { * 支付退款订单状态枚举 */ export const PayRefundStatusEnum = { - CREATE:{ - status:0, + CREATE: { + status: 0, name: '退款订单生成' }, - SUCCESS:{ - status:1, + SUCCESS: { + status: 1, name: '退款成功' }, - FAILURE:{ - status:2, + FAILURE: { + status: 2, name: '退款失败' }, - PROCESSING_NOTIFY:{ - status:3, + PROCESSING_NOTIFY: { + status: 3, name: '退款中,渠道通知结果' }, - PROCESSING_QUERY:{ - status:4, + PROCESSING_QUERY: { + status: 4, name: '退款中,系统查询结果' }, - UNKNOWN_RETRY:{ - status:5, + UNKNOWN_RETRY: { + status: 5, name: '状态未知,请重试' }, - UNKNOWN_QUERY:{ - status:6, + UNKNOWN_QUERY: { + status: 6, name: '状态未知,系统查询结果' }, - CLOSE:{ - status:99, + CLOSE: { + status: 99, name: '退款关闭' } } +/** + * 商品 SPU 状态 + */ +export const ProductSpuStatusEnum = { + RECYCLE: { + status: -1, + name: '回收站' + }, + DISABLE: { + status: 0, + name: '下架' + }, + ENABLE: { + status: 1, + name: '上架' + }, +} diff --git a/yudao-ui-admin/src/utils/dict.js b/yudao-ui-admin/src/utils/dict.js index 1ddde889a..8c5b4bbca 100644 --- a/yudao-ui-admin/src/utils/dict.js +++ b/yudao-ui-admin/src/utils/dict.js @@ -56,6 +56,9 @@ export const DICT_TYPE = { PAY_ORDER_REFUND_STATUS: 'pay_order_refund_status', // 商户支付订单退款状态 PAY_REFUND_ORDER_STATUS: 'pay_refund_order_status', // 退款订单状态 PAY_REFUND_ORDER_TYPE: 'pay_refund_order_type', // 退款订单类别 + + // ========== MALL - PRODUCT 模块 ========== + PRODUCT_SPU_STATUS: 'product_spu_status', // 商品 SPU 状态 } /** @@ -114,6 +117,3 @@ export function getDictDataLabel(dictType, value) { const dict = getDictData(dictType, value); return dict ? dict.label : ''; } - -export class getDictDataL { -} diff --git a/yudao-ui-admin/src/views/mall/product/spu/index.vue b/yudao-ui-admin/src/views/mall/product/spu/index.vue index 41d9ebf14..3061c8417 100644 --- a/yudao-ui-admin/src/views/mall/product/spu/index.vue +++ b/yudao-ui-admin/src/views/mall/product/spu/index.vue @@ -4,74 +4,48 @@ <el-form-item label="商品名称" prop="name"> <el-input v-model="queryParams.name" placeholder="请输入商品名称" clearable @keyup.enter.native="handleQuery"/> </el-form-item> - <el-form-item label="商品编码" prop="code"> <el-input v-model="queryParams.code" placeholder="请输入商品编码" clearable @keyup.enter.native="handleQuery"/> </el-form-item> - <el-form-item label="商品分类" prop="categoryIds"> <el-cascader v-model="queryParams.categoryIds" placeholder="请输入商品分类" :options="categoryList" :props="propName" clearable ref="category"/> </el-form-item> - <el-form-item label="商品品牌" prop="brandId"> <el-select v-model="queryParams.brandId" placeholder="请输入商品品牌" clearable @keyup.enter.native="handleQuery"> <el-option v-for="item in brandList" :key="item.id" :label="item.name" :value="item.id"/> </el-select> </el-form-item> - + <!-- TODO 待实现:商品类型 --> + <!-- TODO 待实现:商品标签 --> + <!-- TODO 待实现:营销活动 --> + <!-- TODO 前端优化:商品销量、商品价格,排的整齐一点 --> <el-form-item label="商品销量"> - <el-col - :span="6" - style="padding-left:0" - > + <el-col :span="7" style="padding-left:0"> <el-form-item prop="salesCountMin"> - <el-input v-model="queryParams.salesCountMin" placeholder="最小值" clearable - @keyup.enter.native="handleQuery"/> + <el-input v-model="queryParams.salesCountMin" placeholder="最低销量" clearable @keyup.enter.native="handleQuery"/> </el-form-item> </el-col> - <el-col - :span="1" - > - - - </el-col> - <el-col - :span="6" - style="padding-left:0" - > + <el-col :span="1">-</el-col> + <el-col :span="7" style="padding-left:0"> <el-form-item prop="salesCountMax"> - <el-input v-model="queryParams.salesCountMax" placeholder="最大值" clearable - @keyup.enter.native="handleQuery"/> + <el-input v-model="queryParams.salesCountMax" placeholder="最高销量" clearable @keyup.enter.native="handleQuery"/> </el-form-item> </el-col> </el-form-item> - <el-form-item label="商品价格" prop="code"> - <el-col - :span="6" - style="padding-left:0" - > + <el-col :span="7" style="padding-left:0"> <el-form-item prop="marketPriceMin"> - <el-input v-model="queryParams.marketPriceMin" placeholder="最小值" clearable - @keyup.enter.native="handleQuery"/> + <el-input v-model="queryParams.marketPriceMin" placeholder="最低价格" clearable @keyup.enter.native="handleQuery"/> </el-form-item> </el-col> - <el-col - :span="1" - > - - - </el-col> - <el-col - :span="6" - style="padding-left:0" - > + <el-col :span="1">-</el-col> + <el-col :span="7" style="padding-left:0"> <el-form-item prop="marketPriceMax"> - <el-input v-model="queryParams.marketPriceMax" placeholder="最大值" clearable - @keyup.enter.native="handleQuery"/> + <el-input v-model="queryParams.marketPriceMax" placeholder="最高价格" clearable @keyup.enter.native="handleQuery"/> </el-form-item> </el-col> </el-form-item> - <el-form-item> <el-button type="primary" icon="el-icon-search" @click="handleQuery">搜索</el-button> <el-button icon="el-icon-refresh" @click="resetQuery">重置</el-button> @@ -82,8 +56,7 @@ <el-row :gutter="10" class="mb8"> <el-col :span="1.5"> <el-button type="primary" plain icon="el-icon-plus" size="mini" @click="handleAdd" - v-hasPermi="['product:spu:create']">新增 - </el-button> + v-hasPermi="['product:spu:create']">添加商品</el-button> </el-col> <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"/> </el-row> @@ -96,17 +69,13 @@ <el-table-column label="商品信息" align="center" width="260"> <template slot-scope="scope"> <div class="product-info"> - <img - v-if="scope.row.picUrls" - :src="scope.row.picUrls[0]" - alt="分类图片" - class="img-height" - /> + <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height" /> <div class="message">{{ scope.row.name }}</div> </div> </template> + <!-- TODO 前端优化:可以有个 + 号,点击后,展示每个 sku --> </el-table-column> - <el-table-column label="价格" align="center" prop="marketPrice" :formatter="unitConversion"/> + <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/> <el-table-column label="库存" align="center" prop="totalStock"/> <el-table-column label="销量" align="center" prop="salesCount"/> <el-table-column label="排序" align="center" prop="sort"/> @@ -117,18 +86,15 @@ </el-table-column> <el-table-column label="状态" align="center" prop="status"> <template slot-scope="scope"> - <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> + <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/> </template> </el-table-column> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" - v-hasPermi="['product:spu:update']">修改 - </el-button> + v-hasPermi="['product:spu:update']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" - v-hasPermi="['product:spu:delete']">删除 - </el-button> + v-hasPermi="['product:spu:delete']">删除</el-button> </template> </el-table-column> </el-table> @@ -141,17 +107,12 @@ <el-table-column label="商品信息" align="center" width="260"> <template slot-scope="scope"> <div class="product-info"> - <img - v-if="scope.row.picUrls" - :src="scope.row.picUrls[0]" - alt="分类图片" - class="img-height" - /> + <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/> <div class="message">{{ scope.row.name }}</div> </div> </template> </el-table-column> - <el-table-column label="价格" align="center" prop="marketPrice" :formatter="unitConversion"/> + <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/> <el-table-column label="库存" align="center" prop="totalStock"/> <el-table-column label="销量" align="center" prop="salesCount"/> <el-table-column label="排序" align="center" prop="sort"/> @@ -162,18 +123,15 @@ </el-table-column> <el-table-column label="状态" align="center" prop="status"> <template slot-scope="scope"> - <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> + <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/> </template> </el-table-column> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" - v-hasPermi="['product:spu:update']">修改 - </el-button> + v-hasPermi="['product:spu:update']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" - v-hasPermi="['product:spu:delete']">删除 - </el-button> + v-hasPermi="['product:spu:delete']">删除</el-button> </template> </el-table-column> </el-table> @@ -186,17 +144,12 @@ <el-table-column label="商品信息" align="center" width="260"> <template slot-scope="scope"> <div class="product-info"> - <img - v-if="scope.row.picUrls" - :src="scope.row.picUrls[0]" - alt="分类图片" - class="img-height" - /> + <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/> <div class="message">{{ scope.row.name }}</div> </div> </template> </el-table-column> - <el-table-column label="价格" align="center" prop="marketPrice" :formatter="unitConversion"/> + <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/> <el-table-column label="库存" align="center" prop="totalStock"/> <el-table-column label="销量" align="center" prop="salesCount"/> <el-table-column label="排序" align="center" prop="sort"/> @@ -207,18 +160,15 @@ </el-table-column> <el-table-column label="状态" align="center" prop="status"> <template slot-scope="scope"> - <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> + <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/> </template> </el-table-column> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" - v-hasPermi="['product:spu:update']">修改 - </el-button> + v-hasPermi="['product:spu:update']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" - v-hasPermi="['product:spu:delete']">删除 - </el-button> + v-hasPermi="['product:spu:delete']">删除</el-button> </template> </el-table-column> </el-table> @@ -231,17 +181,12 @@ <el-table-column label="商品信息" align="center" width="260"> <template slot-scope="scope"> <div class="product-info"> - <img - v-if="scope.row.picUrls" - :src="scope.row.picUrls[0]" - alt="分类图片" - class="img-height" - /> + <img v-if="scope.row.picUrls" :src="scope.row.picUrls[0]" alt="分类图片" class="img-height"/> <div class="message">{{ scope.row.name }}</div> </div> </template> </el-table-column> - <el-table-column label="价格" align="center" prop="marketPrice" :formatter="unitConversion"/> + <el-table-column label="价格" align="center" prop="marketPrice" :formatter="formatPrice"/> <el-table-column label="库存" align="center" prop="totalStock"/> <el-table-column label="销量" align="center" prop="salesCount"/> <el-table-column label="排序" align="center" prop="sort"/> @@ -252,27 +197,24 @@ </el-table-column> <el-table-column label="状态" align="center" prop="status"> <template slot-scope="scope"> - <dict-tag :type="DICT_TYPE.COMMON_STATUS" :value="scope.row.status"/> + <dict-tag :type="DICT_TYPE.PRODUCT_SPU_STATUS" :value="scope.row.status"/> </template> </el-table-column> - <el-table-column label="操作" align="center" class-name="small-padding fixed-width"> <template slot-scope="scope"> <el-button size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" - v-hasPermi="['product:spu:update']">修改 - </el-button> + v-hasPermi="['product:spu:update']">修改</el-button> <el-button size="mini" type="text" icon="el-icon-delete" @click="handleDelete(scope.row)" - v-hasPermi="['product:spu:delete']">删除 - </el-button> + v-hasPermi="['product:spu:delete']">删除</el-button> </template> </el-table-column> </el-table> </el-tab-pane> </el-tabs> + <!-- 分页组件 --> <pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize" @pagination="getList"/> - </div> </template> @@ -280,6 +222,7 @@ import {deleteSpu, getSpuPage,} from "@/api/mall/product/spu"; import {getProductCategoryList} from "@/api/mall/product/category"; import {getBrandList} from "@/api/mall/product/brand"; +import {ProductSpuStatusEnum} from "@/utils/constants"; export default { name: "Spu", @@ -318,7 +261,6 @@ export default { salesCountMax: null, marketPriceMin: null, marketPriceMax: null, - tabStatus: null, }, }; }, @@ -353,9 +295,6 @@ export default { this.addBeginAndEndTime(params, this.dateRangeCreateTime, "createTime"); // 执行查询 getSpuPage(params).then((response) => { - response.data.list.forEach(element => { - element.price = this.divide(element.minPrice, 100) + "~" + this.divide(element.maxPrice, 100) - }); this.list = response.data.list; this.total = response.data.total; this.loading = false; @@ -390,29 +329,29 @@ export default { .confirm('是否确认删除商品spu编号为"' + id + '"的数据项?') .then(function () { return deleteSpu(id); - }) - .then(() => { + }).then(() => { this.getList(); this.$modal.msgSuccess("删除成功"); - }) - .catch(() => { + }).catch(() => { }); }, - unitConversion(row, column, cellValue) { - return this.divide(cellValue, 100); + formatPrice(row, column, cellValue) { + return '¥' + this.divide(cellValue, 100); }, - // 选中tab + // 选中 tab handleClick(val) { if (val.name === "all") { - this.queryParams.tabStatus = null; + this.queryParams.status = undefined; + this.queryParams.alarmStock = undefined; } else if (val.name === "on") { - this.queryParams.tabStatus = 0; + this.queryParams.status = ProductSpuStatusEnum.ENABLE.status; + this.queryParams.alarmStock = undefined; } else if (val.name === "off") { - this.queryParams.tabStatus = 1; + this.queryParams.status = ProductSpuStatusEnum.DISABLE.status; + this.queryParams.alarmStock = undefined; } else if (val.name === "remind") { - this.queryParams.tabStatus = 2; - } else { - this.queryParams.tabStatus = null; + this.queryParams.status = undefined; + this.queryParams.alarmStock = true; } this.getList(); } diff --git a/yudao-ui-admin/src/views/mall/product/spu/save.vue b/yudao-ui-admin/src/views/mall/product/spu/save.vue index 5f6412d6d..c6adb04ab 100644 --- a/yudao-ui-admin/src/views/mall/product/spu/save.vue +++ b/yudao-ui-admin/src/views/mall/product/spu/save.vue @@ -7,8 +7,8 @@ <el-form-item label="商品名称" prop="name"> <el-input v-model="baseForm.name" placeholder="请输入商品名称"/> </el-form-item> - <el-form-item label="商品卖点"> - <el-input type="textarea" v-model="baseForm.sellPoint" placeholder="请输入商品卖点"/> + <el-form-item label="促销语"> + <el-input type="textarea" v-model="baseForm.sellPoint" placeholder="请输入促销语"/> </el-form-item> <el-form-item label="商品主图" prop="picUrls"> <ImageUpload v-model="baseForm.picUrls" :value="baseForm.picUrls" :limit="10" class="mall-image"/>