乐优商城day09(商品的新增修改)

所有代码发布在 [https://github.com/hades0525/leyou]

 

Day09

2019129

20:22

  1. 文件上传时出错:

spring boot的应用服务在启动的时候,会生成在操作系统的/tmp目录下生成一个Tomcat.*的文件目录,用于"java.io.tmpdir"文件流操作TomcatEmbeddedServletContainerFactory

程序对文件的操作时:会生成临时文件,暂存在临时文件中。但是由于长时间不操作,上传文件找不到目录,会报错。所以在配置文件中加一个参数,自定义目录。

server:

  tomcat:

    basedir: C:/Users/TEMP/AppData/Local/tomcat

2.通用mapper

在工具类里写一个BaseMapper接口,所有mapper直接继承BaseMapper

@RegisterMapper

public interface BaseMapper<T> extends Mapper<T>, IdListMapper<T,Long>, InsertListMapper<T> {

}

3.jdk8的lambda和stream使用

 

 

 

商品管理

  1. 商品的新增
    1. 前端页面

用了弹窗+4个stepper-content(分步的标签):新增的信息较多,分成4步来完成

    • 基本信息:主要是一些简单的文本数据,包含了SPU和SpuDetail的部分数据,如
      • 商品分类:是SPU中的cid1cid2cid3属性
      • 品牌:是spu中的brandId属性
      • 标题:是spu中的title属性
      • 子标题:是spu中的subTitle属性
      • 售后服务:是SpuDetail中的afterService属性
      • 包装列表:是SpuDetail中的packingList属性
    • 商品描述:是SpuDetail中的description属性,数据较多,所以单独放一个页面
    • 规格参数:商品规格信息,对应SpuDetail中的genericSpec属性
    • SKU属性:spu下的所有Sku信息
  1. 基本信息:需要获取商品分类分类下的品牌
    1. 获取商品分类已经在之前写了,还需要写一个根据分类获取品牌的方法
  2. 商品描述:运用了富文本编辑器,自定义了组件的上传图片的功能
  3. 规格参数:需要根据商品分类cid,获取规格参数
  4. sku属性:是spu下的每个商品的不同特征
  5. 页面提交:提交的数据整体是jason格式,包含spu表所有数据
    • brandId:品牌id
    • cid1、cid2、cid3:商品分类id
    • subTitle:副标题
    • title:标题
    • spuDetail:是一个json对象,代表商品详情表数据
      • afterService:售后服务
      • description:商品描述
      • packingList:包装列表
      • specialSpec:sku规格属性模板
      • genericSpec:通用规格参数
    • skus:spu下的所有sku数组,元素是每个sku对象:
      • title:标题
      • images:图片
      • price:价格
      • stock:库存
      • ownSpec:特有规格参数
      • indexes:特有规格参数的下标
  1. 后台实现
    1. pojo
      1. spu

@Table(name="tb_spu")

@Data

publicclassSpu{

@Id

@KeySql(useGeneratedKeys=true)

privateLongid;

privateLongbrandId;

privateLongcid1;//1级类目

privateLongcid2;//2级类目

privateLongcid3;//3级类目

privateStringtitle;//标题

privateStringsubTitle;//子标题

privateBooleansaleable;//是否上架

 

@JsonIgnore//页面忽略的字段

privateBooleanvalid;//是否有效,逻辑删除用

 

privateDatecreateTime;//创建时间

 

@JsonIgnore//页面忽略字段

privateDatelastUpdateTime;//最后修改时间

 

 

@Transient//spu表里没有的字段,但页面查询要用

privateStringcname;

@Transient//spu表里没有的字段,但页面查询要用

privateStringbname;

@Transient//spu表里没有的字段,但页面新增,修改要用

privateList<Sku>skus;

@Transient//spu表里没有的字段,但页面新增,修改要用

privateSpuDetailspuDetail;

}

  1. spuDetail

@Table(name="tb_spu_detail")

@Data

publicclassSpuDetail{

@Id

privateLongspuId;//对应的SPUid

privateStringdescription;//商品描述

privateStringspecialSpec;//商品特殊规格的名称及可选值模板

privateStringgenericSpec;//商品的全局规格属性

privateStringpackingList;//包装清单

privateStringafterService;//售后服务

 

}

  1. sku

@Table(name="tb_sku")

@Data

publicclassSku{

@Id

@KeySql(useGeneratedKeys=true)

privateLongid;

privateLongspuId;

privateStringtitle;

privateStringimages;

privateLongprice;

privateStringownSpec;//商品特殊规格的键值对

privateStringindexes;//商品特殊规格的下标

privateBooleanenable;//是否有效,逻辑删除用

privateDatecreateTime;//创建时间

privateDatelastUpdateTime;//最后修改时间

 

@Transient//sku表里没有的字段,但页面商品新增和修改时要用

privateIntegerstock;//库存量

}

  1. stock

@Table(name="tb_stock")

@Data

publicclassStock{

@Id

privateLongskuId;//对应skuid

privateIntegerseckillStock;//秒杀可用库存

privateIntegerseckillTotal;//已秒杀数量

privateIntegerstock;//正常库存

}

  1. 点击弹窗的后台
    1. 根据分类获取品牌

/**

*根据cid查询品牌

*@paramcid

*@return

*/

@GetMapping("/cid/{cid}")

publicResponseEntity<List<Brand>>queryBrandByCid(@PathVariable("cid")Longcid){

returnResponseEntity.ok(brandService.queryBrandByCid(cid));

}

/**

*根据cid查询品牌

*@paramcid

*@return

*/

publicList<Brand>queryBrandByCid(Longcid){

List<Brand>brands=brandMapper.queryByCategoryId(cid);

if(CollectionUtils.isEmpty(brands)){

thrownewLyException(ExceptionEnum.BRAND_NOT_FOUND);

}

returnbrands;

}

 

 @Select("SELECT b.* FROM tb_category_brand cb INNER JOIN tb_brand b ON cb.brand_id = b.id WHERE cb.category_id = #{cid}")

    List<Brand> queryByCategoryId(@Param("cid") Long cid);

  1. 商品新增
    1. controller

/**

*商品的新增

*@paramspu是一个Jason对象要用@RequestBody

*@return

*/

@PostMapping("goods")

publicResponseEntity<Void>saveGoods(@RequestBodySpuspu){

goodsService.saveGoods(spu);

returnResponseEntity.status(HttpStatus.CREATED).build();

}

  1. service,要对SPU新增以外,还要对SpuDetail、Sku、Stock进行保存

/**

*新增商品

*@paramspu

*/

@Transactional

publicvoidsaveGoods(Spuspu){

//新增spu

spu.setId(null);

spu.setCreateTime(newDate());

spu.setLastUpdateTime(spu.getCreateTime());

spu.setSaleable(true);

spu.setValid(false);

intcount=spuMapper.insert(spu);

if(count!=1){

thrownewLyException(ExceptionEnum.GOODS_SAVE_ERROE);

}

 

//新增spu_detail

SpuDetaildetail=spu.getSpuDetail();

detail.setSpuId(spu.getId());

spuDetailMapper.insert(detail);

//新增skustock

saveSkuAndStock(spu);

 

}

 

/**

*新增skustock

*@paramspu

*/

privatevoidsaveSkuAndStock(Spuspu){

intcount;//定义库存集合

List<Stock>stockList=newArrayList<>();

//新增sku

List<Sku>skus=spu.getSkus();

for(Skusku:skus){

sku.setCreateTime(newDate());

sku.setLastUpdateTime(sku.getCreateTime());

sku.setSpuId(spu.getId());

count=skuMapper.insert(sku);

if(count!=1){

thrownewLyException(ExceptionEnum.GOODS_SAVE_ERROE);

}

//新增stock

Stockstock=newStock();

stock.setSkuId(sku.getId());

stock.setStock(sku.getStock());

stockList.add(stock);

}

 

//批量新增stock

count=stockMapper.insertList(stockList);

if(count!=1){

thrownewLyException(ExceptionEnum.GOODS_SAVE_ERROE);

}

}

  1. 商品更新
    1. 商品更新时,会发起两个请求,查询商品详情detail和sku信息
    • controller

/**

*根据spuid查询详情detail

*@paramspuId

*@return

*/

@GetMapping("/spu/detail/{id}")

publicResponseEntity<SpuDetail>queryDetailById(@PathVariable("id")LongspuId){

returnResponseEntity.ok(goodsService.queryDetailById(spuId));

}

 

/**

*根据spu查询下面所有sku

*@paramspuId

*@return

*/

@GetMapping("/sku/list")

publicResponseEntity<List<Sku>>querySkuBySpuId(@RequestParam("id")LongspuId){

returnResponseEntity.ok(goodsService.querySkuBySpuId(spuId));

}

  • service

/**

*根据spuid查询详情detail

*@paramspuId

*@return

*/

publicSpuDetailqueryDetailById(LongspuId){

SpuDetaildetail=spuDetailMapper.selectByPrimaryKey(spuId);

if(detail==null){

thrownewLyException(ExceptionEnum.GOODS_DETAIL_NOT_FOUND);

}

returndetail;

}

 

/**

*根据spuid查询下面所有的skustock

*@paramspuId

*@return

*/

publicList<Sku>querySkuBySpuId(LongspuId){

Skusku=newSku();

sku.setSpuId(spuId);

List<Sku>skuList=skuMapper.select(sku);

if(CollectionUtils.isEmpty(skuList)){

thrownewLyException(ExceptionEnum.GOODS_SKU_NOT_FOUND);

}

 

//查询库存

//根据skulist取得到所有id集合

List<Long> ids = skuList.stream().map(Sku::getId).collect(Collectors.toList());

//根据id集合查询到所有stock集合

List<Stock> stockList = stockMapper.selectByIdList(ids);

if(CollectionUtils.isEmpty(stockList)){

throw new LyException(ExceptionEnum.GOODS_STOCK_NOT_FOUND);

}

//stock变成一个map,keyskuidvalue是库存量

Map<Long,Integer> stockMap = stockList.stream()

.collect(Collectors.toMap(Stock::getSkuId,Stock::getStock));

//stockmap的库存量赋值给skulist的库存量

skuList.forEach(s->s.setStock(stockMap.get(s.getId())));

return skuList;

}

  1. 更新的提交
  • controller

/**

*商品的修改

*@paramspu是一个Jason对象要用@RequestBody

*@return

*/

@PutMapping("goods")

publicResponseEntity<Void>updateGoods(@RequestBodySpuspu){

goodsService.updateGoods(spu);

returnResponseEntity.status(HttpStatus.NO_CONTENT).build();

}

  • service

/**

*修改商品

*@param spu

*/

@Transactional

publicvoidupdateGoods(Spuspu){

if(spu.getId()==null){

thrownewLyException(ExceptionEnum.GOODS_ID_CANNOT_BE_NULL);

}

 

Skusku=newSku();

sku.setSpuId(spu.getId());

//查询sku

List<Sku>skuList=skuMapper.select(sku);

if(!CollectionUtils.isEmpty(skuList)){

//删除sku

skuMapper.delete(sku);

//删除stock

List<Long>ids=skuList.stream().map(Sku::getId).collect(Collectors.toList());

stockMapper.deleteByIdList(ids);

}

//修改spu

spu.setValid(null);

spu.setSaleable(null);

spu.setLastUpdateTime(newDate());

spu.setCreateTime(null);

 

intcount=spuMapper.updateByPrimaryKeySelective(spu);

if(count!=1){

thrownewLyException(ExceptionEnum.UPDATE_GOODS_ERROR);

}

//修改detail

count=spuDetailMapper.updateByPrimaryKeySelective(spu.getSpuDetail());

if(count!=1){

thrownewLyException(ExceptionEnum.UPDATE_GOODS_ERROR);

}

//新增skustock

saveSkuAndStock(spu);

}

  1. 前台门户系统 leyou-portal
    1. 不再采用后台的单页应用,而是直接编写原生的静态HTML。nuxt + vue + webpack 服务端渲染
    2. 使用带有热加载功能的小型开发服务器live-server。用它来展示你的HTML / JavaScript / CSS,但不能用于部署最终的网站。
      1. 安装:npm install -g live-server
      2. 运行:live-server --port=9002
    3. 在nginx中配置域名

server {

    listen       80;

    server_name  www.leyou.com;

 

    proxy_set_header X-Forwarded-Host $host;

    proxy_set_header X-Forwarded-Server $host;

    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

 

    location / {

        proxy_pass http://192.168.163.128:9002;

        proxy_connect_timeout 600;

        proxy_read_timeout 600;

    }

}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值