黑馬暢購商城---3.商品管理

學習目標

  • SPU與SKU概念理解
1
2
  SPU:某一款商品的公共屬性
  SKU:某款商品的不同參數對應的商品信息[某個商品]

 

  • ==新增商品、修改商品==
1
2
  增加:增加SPU和SKU
  修改:修改SPU和SKU

 

  • 商品審覈、上架、下架
1
2
  審覈:修改審覈狀態
  上架下架:修改上架下架狀態

 

  • 刪除商品
1
2
  邏輯刪除:修改了刪除狀態
  物理刪除:真實刪除了數據

 

  • 找回商品
  找回商品:一定是屬於邏輯刪除的商品

 

1 SPU與SKU

1.1 SPU與SKU概念

SPU = Standard Product Unit  (標準產品單位)

  • 概念 : SPU 是商品信息聚合的最小單位,是一組可複用、易檢索的標準化信息的集合,該集合描述了一個產品的特性。

  • 通俗點講,屬性值、特性相同的貨品就可以稱爲一個 SPU

==同款商品的公共屬性抽取==

例如:**華爲P30 就是一個 SPU**

SKU=stock keeping unit( 庫存量單位)

  • SKU 即庫存進出計量的單位, 可以是以件、盒、托盤等爲單位。

  • SKU 是物理上不可分割的最小存貨單元。在使用時要根據不同業態,不同管理模式來處理。

  • 在服裝、鞋類商品中使用最多最普遍。

例如:**華爲P30 紅色 64G 就是一個 SKU**

==某個庫存單位的商品獨有屬性(某個商品的獨有屬性)==

1.2 表結構分析

tb_spu 表 (SPU表)

 

字段名稱 字段含義 字段類型 字段長度 備註
id 主鍵 BIGINT    
sn 貨號 VARCHAR    
name SPU名 VARCHAR    
caption 副標題 VARCHAR    
brand_id 品牌ID INT    
category1_id 一級分類 INT    
category2_id 二級分類 INT    
category3_id 三級分類 INT    
template_id 模板ID INT    
freight_id 運費模板id INT    
image 圖片 VARCHAR    
images 圖片列表 VARCHAR    
sale_service 售後服務 VARCHAR    
introduction 介紹 TEXT    
spec_items 規格列表 VARCHAR    
para_items 參數列表 VARCHAR    
sale_num 銷量 INT    
comment_num 評論數 INT    
is_marketable 是否上架 CHAR    
is_enable_spec 是否啓用規格 CHAR    
is_delete 是否刪除 CHAR    
status 審覈狀態 CHAR    

tb_sku 表(SKU商品表)

字段名稱 字段含義 字段類型 字段長度 備註
id 商品id BIGINT    
sn 商品條碼 VARCHAR    
name SKU名稱 VARCHAR    
price 價格(分) INT    
num 庫存數量 INT    
alert_num 庫存預警數量 INT    
image 商品圖片 VARCHAR    
images 商品圖片列表 VARCHAR    
weight 重量(克) INT    
create_time 創建時間 DATETIME    
update_time 更新時間 DATETIME    
spu_id SPUID BIGINT    
category_id 類目ID INT    
category_name 類目名稱 VARCHAR    
brand_name 品牌名稱 VARCHAR    
spec 規格 VARCHAR    
sale_num 銷量 INT    
comment_num 評論數 INT    
status 商品狀態 1-正常,2-下架,3-刪除 CHAR    

2 新增和修改商品

2.1 需求分析

實現商品的新增與修改功能。

(1)第1個步驟,先選擇添加的商品所屬分類

這塊在第2天的代碼中已經有一個根據父節點ID查詢分類信息的方法,參考第2天的4.3.4的findByPrantId方法,首先查詢頂級分類,也就是pid=0,然後根據用戶選擇的分類,將選擇的分類作爲pid查詢子分類。

(2)第2個步驟,填寫SPU的信息

(3)第3個步驟,填寫SKU信息

先進入選擇商品分類 再填寫商品的信息 填寫商品的屬性添加商品。

2.2 實現思路

 

前端傳遞給後端的數據格式 是一個spu對象和sku列表組成的對象,如下圖:

上圖JSON數據如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
{
  "spu": {
    "name": "這個是商品名稱",
    "caption": "這個是副標題",
    "brandId": 12,
    "category1Id": 558,
    "category2Id": 559,
    "category3Id": 560,
    "freightId": 10,
    "image": "http://www.qingcheng.com/image/1.jpg",
    "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg",
    "introduction": "這個是商品詳情,html代碼",
    "paraItems": {
      "出廠年份": "2019",
      "贈品": "充電器"
    },
    "saleService": "七天包退,閃電退貨",
    "sn": "020102331",
    "specItems": {
      "顏色": [
        "紅",
        "綠"
      ],
      "機身內存": [
        "64G",
        "8G"
      ]
    },
    "templateId": 42
  },
  "skuList": [
    {
      "sn": "10192010292",
      "num": 100,
      "alertNum": 20,
      "price": 900000,
      "spec": {
        "顏色": "紅",
        "機身內存": "64G"
      },
      "image": "http://www.qingcheng.com/image/1.jpg",
      "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg",
      "status": "1",
      "weight": 130
    },
    {
      "sn": "10192010293",
      "num": 100,
      "alertNum": 20,
      "price": 600000,
      "spec": {
        "顏色": "綠",
        "機身內存": "8G"
      },
      "image": "http://www.qingcheng.com/image/1.jpg",
      "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg",
      "status": "1",
      "weight": 130
    }
  ]
}

2.3 代碼生成

準備工作:爲了更快的實現代碼編寫,我們可以採用《黑馬代碼生成器》來批量生成代碼,這些代碼就已經實現了我們之前的增刪改查功能。

 

《黑馬代碼生成器》一款由傳智播客教育集團JavaEE教研團隊開發的基於Freemarker模板引擎的“代碼生成神器”。即便是一個工程幾百個表,也可以瞬間完成基礎代碼的構建!用戶只需建立數據庫表結構,運行main方法就可快速生成可以運行的一整套代碼,可以極大地縮短開發週期,降低人力成本。《黑馬代碼生成器》的誕生主要用於迅速構建生成微服務工程的Pojo、Dao、Service、Controller各層、並且可以生成swagger API模板等。 用戶通過自己開發模板也可以實現生成php、python、C# 、c++、數據庫存儲過程等其它編程語言的代碼。

《黑馬代碼生成器》目前已經開源 地址:https://github.com/shenkunlin/code-template.git

如下圖資料,將其導入到idea中 並執行即可:

使用說明,簡單來說如下圖所示:

2.4 代碼實現

一會兒會用到ID生成,我們可以使用IdWorker,在啓動類GoodsApplication中添加如下代碼,用於創建IdWorker,並將IdWorker交給Spring容器,代碼如下:

1
2
3
4
5
6
7
8
/***
 * IdWorker
 * @return
 */
@Bean
public IdWorker idWorker(){
    return new IdWorker(0,0);
}

2.4.1 查詢分類

2.4.1.1 分析

在實現商品增加之前,需要先選擇對應的分類,選擇分類的時候,首選選擇一級分類,然後根據選中的分類,將選中的分類作爲查詢的父ID,再查詢對應的子分類集合,因此我們可以在後臺編寫一個方法,根據父類ID查詢對應的分類集合即可。

2.4.1.2 代碼實現

(1)Service層

修改com.changgou.goods.service.CategoryService添加根據父類ID查詢所有子節點,代碼如下:

1
2
3
4
/***
 * 根據分類的父ID查詢子分類節點集合
 */
List<Category> findByParentId(Integer pid);

修改com.changgou.goods.service.impl.CategoryServiceImpl添加上面的實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
/***
 * 根據分類的父節點ID查詢所有子節點
 * @param pid
 * @return
 */
@Override
public List<Category> findByParentId(Integer pid) {
    //SELECT * FROM tb_category WHERE parent_id=?
    Category category = new Category();
    category.setParentId(pid);
    return categoryMapper.select(category);
}

(2)Controller層

修改com.changgou.goods.controller.CategoryController添加根據父ID查詢所有子類集合,代碼如下:

1
2
3
4
5
6
7
8
9
/****
 * 根據節點ID查詢所有子節點分類集合
 */
@GetMapping(value = "/list/{pid}")
public Result<List<Category>> findByParentId(@PathVariable(value = "pid")Integer pid){
    //調用Service實現查詢
    List<Category> categories = categoryService.findByParentId(pid);
    return new Result<List<Category>>(true,StatusCode.OK,"查詢成功!",categories);
}

2.4.2 模板查詢(規格參數組)

同學作業

2.4.2.1 分析

如上圖,當用戶選中了分類後,需要根據分類的ID查詢出對應的模板數據,並將模板的名字顯示在這裏,模板表結構如下:

1
2
3
4
5
6
7
CREATE TABLE `tb_template` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(50) DEFAULT NULL COMMENT '模板名稱',
  `spec_num` int(11) DEFAULT '0' COMMENT '規格數量',
  `para_num` int(11) DEFAULT '0' COMMENT '參數數量',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=44 DEFAULT CHARSET=utf8;

2.4.2.2 代碼實現

(1)Service層

修改com.changgou.goods.service.TemplateService接口,添加如下方法根據分類ID查詢模板:

1
2
3
4
5
6
/**
 * 根據分類ID查詢模板信息
 * @param id
 * @return
 */
Template findByCategoryId(Integer id);

修改com.changgou.goods.service.impl.TemplateServiceImpl添加上面方法的實現:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@Autowired
private CategoryMapper categoryMapper;

/***
 * 根據分類ID查詢模板信息
 * @param id
 * @return
 */
@Override
public Template findByCategoryId(Integer id) {
    //查詢分類信息
    Category category = categoryMapper.selectByPrimaryKey(id);

    //根據模板Id查詢模板信息
    return templateMapper.selectByPrimaryKey(category.getTemplateId());
}

(2)Controller層

修改com.changgou.goods.controller.TemplateController,添加根據分類ID查詢模板數據:

1
2
3
4
5
6
7
8
9
10
/***
 * 根據分類查詢模板數據
 * @param id:分類ID
 */
@GetMapping(value = "/category/{id}")
public Result<Template> findByCategoryId(@PathVariable(value = "id")Integer id){
    //調用Service查詢
    Template template = templateService.findByCategoryId(id);
    return new Result<Template>(true, StatusCode.OK,"查詢成功",template);
}

2.4.3 查詢分類品牌數據

2.4.3.1 分析

用戶每次選擇了分類之後,可以根據用戶選擇的分類到tb_category_brand表中查詢指定的品牌集合ID,然後根據品牌集合ID查詢對應的品牌集合數據,再將品牌集合數據拿到這裏來展示即可實現上述功能。

2.4.3.2 代碼實現

(1)Dao實現

修改com.changgou.goods.dao.BrandMapper添加根據分類ID查詢對應的品牌數據,代碼如下:

1
2
3
4
5
6
7
8
public interface BrandMapper extends Mapper<Brand> {

    /***
     * 查詢分類對應的品牌集合
     */
    @Select("SELECT tb.* FROM tb_category_brand tcb,tb_brand tb WHERE tcb.category_id=#{categoryid} AND tb.id=tcb.brand_id")
    List<Brand> findByCategory(Integer categoryid);
}

(2)Service層

修改com.changgou.goods.service.BrandService,添加根據分類ID查詢指定的品牌集合方法,代碼如下:

1
2
3
4
5
/***
 * 根據分類ID查詢品牌集合
 * @param categoryid:分類ID
 */
List<Brand> findByCategory(Integer categoryid);

修改com.changgou.goods.service.impl.BrandServiceImpl添加上面方法的實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/***
 * 根據分類ID查詢品牌集合
 * @param categoryid:分類ID
 * @return
 */
@Override
public List<Brand> findByCategory(Integer categoryid) {
    //1.查詢當前分類所對應的所有品牌信息
    //2.根據品牌ID查詢對應的品牌集合

    //自己創建DAO實現查詢
    return brandMapper.findByCategory(categoryid);
}

(3)Controller層

修改,添加根據分類ID查詢對應的品牌數據代碼如下:

1
2
3
4
5
6
7
8
9
10
/***
 * 根據分類實現品牌列表查詢
 * /brand/category/{id}  分類ID
 */
@GetMapping(value = "/category/{id}")
public Result<List<Brand>> findBrandByCategory(@PathVariable(value = "id")Integer categoryId){
    //調用Service查詢品牌數據
    List<Brand> categoryList = brandService.findByCategory(categoryId);
    return new Result<List<Brand>>(true,StatusCode.OK,"查詢成功!",categoryList);
}

2.4.4 規格查詢

2.4.4.1 分析

用戶選擇分類後,需要根據所選分類對應的模板ID查詢對應的規格,規格表結構如下:

1
2
3
4
5
6
7
8
CREATE TABLE `tb_spec` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID',
  `name` varchar(50) DEFAULT NULL COMMENT '名稱',
  `options` varchar(2000) DEFAULT NULL COMMENT '規格選項',
  `seq` int(11) DEFAULT NULL COMMENT '排序',
  `template_id` int(11) DEFAULT NULL COMMENT '模板ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=40 DEFAULT CHARSET=utf8;

2.4.4.2 代碼實現

(1)Service層

修改com.changgou.goods.service.SpecService添加根據分類ID查詢規格列表,代碼如下:

1
2
3
4
5
6
/***
 * 根據分類ID查詢規格列表
 * @param categoryid
 * @return
 */
List<Spec> findByCategoryId(Integer categoryid);

修改com.changgou.goods.service.impl.SpecServiceImpl添加上面方法的實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Autowired
private CategoryMapper categoryMapper;

/***
 * 根據分類ID查詢規格列表
 * @param categoryid
 * @return
 */
@Override
public List<Spec> findByCategoryId(Integer categoryid) {
    //查詢分類
    Category category = categoryMapper.selectByPrimaryKey(categoryid);
    //根據分類的模板ID查詢規格
    Spec spec = new Spec();
    spec.setTemplateId(category.getTemplateId());
    return specMapper.select(spec);
}

(2)Controller層

修改com.changgou.goods.controller.SpecController添加根據分類ID查詢規格數據,代碼如下:

1
2
3
4
5
6
7
8
9
/***
 * 根據分類ID查詢對應的規格列表
 */
@GetMapping(value = "/category/{id}")
public Result<List<Spec>> findByCategoryId(@PathVariable(value = "id")Integer categoryid){
    //調用Service查詢
    List<Spec> specs = specService.findByCategoryId(categoryid);
    return new Result<List<Spec>>(true, StatusCode.OK,"查詢成功",specs);
}

2.4.5 參數列表查詢

2.4.5.1 分析

當用戶選中分類後,需要根據分類的模板ID查詢對應的參數列表,參數表結構如下:

1
2
3
4
5
6
7
8
CREATE TABLE `tb_para` (
  `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'id',
  `name` varchar(50) DEFAULT NULL COMMENT '名稱',
  `options` varchar(2000) DEFAULT NULL COMMENT '選項',
  `seq` int(11) DEFAULT NULL COMMENT '排序',
  `template_id` int(11) DEFAULT NULL COMMENT '模板ID',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

2.4.5.2 代碼實現

(1)Service層

修改com.changgou.goods.service.ParaService添加根據分類ID查詢參數列表,代碼如下:

1
2
3
4
5
6
/***
 * 根據分類ID查詢參數列表
 * @param id
 * @return
 */
List<Para> findByCategoryId(Integer id);

修改com.changgou.goods.service.impl.ParaServiceImpl添加上面方法的實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Autowired
private CategoryMapper categoryMapper;

/***
 * 根據分類ID查詢參數列表
 * @param id
 * @return
 */
@Override
public List<Para> findByCategoryId(Integer id) {
    //查詢分類信息
    Category category = categoryMapper.selectByPrimaryKey(id);
    //根據分類的模板ID查詢參數列表
    Para para = new Para();
    para.setTemplateId(category.getTemplateId());
    return paraMapper.select(para);
}

(2)Controller層

修改com.changgou.goods.controller.ParaController,添加根據分類ID查詢參數列表,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 根據分類ID查詢參數列表
 * @param id
 * @return
 */
@GetMapping(value = "/category/{id}")
public Result<List<Para>> getByCategoryId(@PathVariable(value = "id")Integer id){
    //根據分類ID查詢對應的參數信息
    List<Para> paras = paraService.findByCategoryId(id);
    Result<List<Para>> result = new Result<List<Para>>(true,StatusCode.OK,"查詢分類對應的品牌成功!",paras);
    return result;
}

2.4.6 SPU+SKU保存

2.4.6.1 分析

保存商品數據的時候,需要保存Spu和Sku,一個Spu對應多個Sku,我們可以先構建一個Goods對象,將SpuList<Sku>組合到一起,前端將2者數據提交過來,再實現添加操作。

2.4.62 代碼實現

(1)Pojo改造

修改changgou-service-goods-api工程創建組合實體類,創建com.changgou.goods.pojo.Goods,代碼如下:

1
2
3
4
5
6
7
8
public class Goods implements Serializable {
    //SPU
    private Spu spu;
    //SKU集合
    private List<Sku> skuList;

    //..get..set..toString
}

(2) 業務層

修改com.changgou.goods.service.SpuService接口,添加保存Goods方法,代碼如下:

1
2
3
4
5
/**
 * 保存商品
 * @param goods
 */
void saveGoods(Goods goods);

修改com.changgou.goods.service.impl.SpuServiceImpl類,添加保存Goods的方法實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
@Autowired
private IdWorker idWorker;

@Autowired
private CategoryMapper categoryMapper;

@Autowired
private BrandMapper brandMapper;

@Autowired
private SkuMapper skuMapper;

/***
 * 保存Goods
 * @param goods
 */
@Override
public void saveGoods(Goods goods) {
    //增加Spu
    Spu spu = goods.getSpu();
    spu.setId(idWorker.nextId());
    spuMapper.insertSelective(spu);

    //增加Sku
    Date date = new Date();
    Category category = categoryMapper.selectByPrimaryKey(spu.getCategory3Id());
    Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());
    //獲取Sku集合
    List<Sku> skus = goods.getSkus();
    //循環將數據加入到數據庫
    for (Sku sku : skus) {
        //構建SKU名稱,採用SPU+規格值組裝
        if(StringUtils.isEmpty(sku.getSpec())){
            sku.setSpec("{}");
        }
        //獲取Spu的名字
        String name = spu.getName();

        //將規格轉換成Map
        Map<String,String> specMap = JSON.parseObject(sku.getSpec(), Map.class);
        //循環組裝Sku的名字
        for (Map.Entry<String, String> entry : specMap.entrySet()) {
            name+="  "+entry.getValue();
        }
        sku.setName(name);
        //ID
        sku.setId(idWorker.nextId());
        //SpuId
        sku.setSpuId(spu.getId());
        //創建日期
        sku.setCreateTime(date);
        //修改日期
        sku.setUpdateTime(date);
        //商品分類ID
        sku.setCategoryId(spu.getCategory3Id());
        //分類名字
        sku.setCategoryName(category.getName());
        //品牌名字
        sku.setBrandName(brand.getName());
        //增加
        skuMapper.insertSelective(sku);
    }
}

(3)控制層

修改com.changgou.goods.controller.SpuController,增加保存Goods方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
/***
 * 添加Goods
 * @param goods
 * @return
 */
@PostMapping("/save")
public Result save(@RequestBody Goods goods){
    spuService.saveGoods(goods);
    return new Result(true,StatusCode.OK,"保存成功");
}

測試數據

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{
  "skuList": [
    {
      "alertNum": 10,
      "brandName": "華爲",
      "categoryId": 64,
      "commentNum": 0,
      "image": "http://www.baidu.com",
      "images": "",
      "name": "華爲P30手機",
      "num": 5,
      "price": 1000,
      "saleNum": 0,
      "sn": "No1001",
      "spec": "{\"顏色\":\"紅色\",\"網絡\":\"移動3G\"}",
      "weight": 0
    }
  ],
  "spu": {
    "brandId": 8557,
    "caption": "華爲手機大促銷",
    "category1Id": 1,
    "category2Id": 59,
    "category3Id": 64,
    "commentNum": 0,
    "freightId": 0,
    "images": "http://www.qingcheng.com/image/1.jpg,http://www.qingcheng.com/image/2.jpg",
    "introduction": "華爲產品世界最強",
    "isEnableSpec": "1",
    "isMarketable": "1",
    "name": "string",
    "specItems": "{\"顏色\":[\"紅\",\"綠\"],\"機身內存\":[\"64G\",\"8G\"]}",
    "paraItems": "{\"贈品\":\"充電器\",\"出廠年份\":\"2019\"}",
    "saleNum": 0,
    "saleService": "一年包換",
    "sn": "No10001",
    "status": "1",
    "templateId": 42
  }
}

2.4.7 根據ID查詢商品

2.4.7.1 需求分析

需求:根據id 查詢SPU和SKU列表 ,顯示效果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
{
    "spu": {
		"brandId": 0,
		"caption": "111",
		"category1Id": 558,
		"category2Id": 559,
		"category3Id": 560,
		"commentNum": null,
		"freightId": null,
		"id": 149187842867993,
		"image": null,
		"images": null,
		"introduction": null,
		"isDelete": null,
		"isEnableSpec": "0",
		"isMarketable": "1",
		"name": "黑馬智能手機",
		"paraItems": null,
		"saleNum": null,
		"saleService": null,
		"sn": null,
		"specItems": null,
		"status": null,
		"templateId": 42
	},
	"skuList": [{
		"alertNum": null,
		"brandName": "金立(Gionee)",
		"categoryId": 560,
		"categoryName": "手機",
		"commentNum": null,
		"createTime": "2018-11-06 10:17:08",
		"id": 1369324,
		"image": null,
		"images": "blob:http://localhost:8080/ec04d1a5-d865-4e7f-a313-2e9a76cfb3f8",
		"name": "黑馬智能手機",
		"num": 100,
		"price": 900000,
		"saleNum": null,
		"sn": "",
		"spec": null,
		"spuId": 149187842867993,
		"status": "1",
		"updateTime": "2018-11-06 10:17:08",
		"weight": null
	},{
		"alertNum": null,
		"brandName": "金立(Gionee)",
		"categoryId": 560,
		"categoryName": "手機",
		"commentNum": null,
		"createTime": "2018-11-06 10:17:08",
		"id": 1369325,
		"image": null,
		"images": "blob:http://localhost:8080/ec04d1a5-d865-4e7f-a313-2e9a76cfb3f8",
		"name": "黑馬智能手機",
		"num": 100,
		"price": 900000,
		"saleNum": null,
		"sn": "",
		"spec": null,
		"spuId": 149187842867993,
		"status": "1",
		"updateTime": "2018-11-06 10:17:08",
		"weight": null
	  }
   ]
}

2.4.7.2 代碼實現

(1)業務層

修改qingcheng-service-goods工程,修改com.changgou.goods.service.SpuService接口,添加根據ID查找方法findGoodsById代碼如下:

1
2
3
4
5
/***
 * 根據SPU的ID查找SPU以及對應的SKU集合
 * @param spuId
 */
Goods findGoodsById(Long spuId);

修改qingcheng-service-goods工程,修改com.changgou.goods.service.impl.SpuServiceImpl類,添加根據ID查找findGoodsById方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/***
 * 根據SpuID查詢goods信息
 * @param spuId
 * @return
 */
@Override
public Goods findGoodsById(Long spuId) {
    //查詢Spu
    Spu spu = spuMapper.selectByPrimaryKey(spuId);

    //查詢List<Sku>
    Sku sku = new Sku();
    sku.setSpuId(spuId);
    List<Sku> skus = skuMapper.select(sku);
    //封裝Goods
    Goods goods = new Goods();
    goods.setSkus(skus);
    goods.setSpu(spu);
    return goods;
}

(2)控制層

修改com.changgou.goods.controller.SpuController,修改findById方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
/***
 * 根據ID查詢Goods
 * @param id
 * @return
 */
@GetMapping("/goods/{id}")
public Result<Goods> findGoodsById(@PathVariable Long id){
    //根據ID查詢Goods(SPU+SKU)信息
    Goods goods = spuService.findGoodsById(id);
    return new Result<Goods>(true,StatusCode.OK,"查詢成功",goods);
}

測試:http://localhost:18081/spu/goods/1088256029394866176

2.4.8 保存修改

 

修改changgou-service-goods的SpuServiceImpl的saveGoods方法,修改添加SPU部分代碼:

上圖代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
if(spu.getId()==null){
    //增加
    spu.setId(idWorker.nextId());
    spuMapper.insertSelective(spu);
}else{
    //修改數據
    spuMapper.updateByPrimaryKeySelective(spu);
    //刪除該Spu的Sku
    Sku sku = new Sku();
    sku.setSpuId(spu.getId());
    skuMapper.delete(sku);
}

2.4.9 修改SKU庫存

(學員實現)

3 商品審覈與上下架

3.1 需求分析

商品新增後,審覈狀態爲0(未審覈),默認爲下架狀態。

審覈商品,需要校驗是否是被刪除的商品,如果未刪除則修改審覈狀態爲1,並自動上架

下架商品,需要校驗是否是被刪除的商品,如果未刪除則修改上架狀態爲0

上架商品,需要審覈通過的商品

3.2 實現思路

(1)按照ID查詢SPU信息

(2)判斷修改審覈、上架和下架狀態

(3)保存SPU

3.3 代碼實現

3.3.1 商品審覈

實現審覈通過,自動上架。

(1)業務層

修改修改changgou-service-goods工程的com.changgou.goods.service.SpuService接口,添加審覈方法,代碼如下:

1
2
3
4
5
/***
 * 商品審覈
 * @param spuId
 */
void audit(Long spuId);

修改changgou-service-goods工程的com.changgou.goods.service.impl.SpuServiceImpl類,添加audit方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/***
 * 商品審覈
 * @param spuId
 */
@Override
public void audit(Long spuId) {
    //查詢商品
    Spu spu = spuMapper.selectByPrimaryKey(spuId);
    //判斷商品是否已經刪除
    if(spu.getIsDelete().equalsIgnoreCase("1")){
        throw new RuntimeException("該商品已經刪除!");
    }
    //實現上架和審覈
    spu.setStatus("1"); //審覈通過
    spu.setIsMarketable("1"); //上架
    spuMapper.updateByPrimaryKeySelective(spu);
}

(2)控制層

修改com.changgou.goods.controller.SpuController,新增audit方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
/**
 * 審覈
 * @param id
 * @return
 */
@PutMapping("/audit/{id}")
public Result audit(@PathVariable Long id){
    spuService.audit(id);
    return new Result(true,StatusCode.OK,"審覈成功");
}

3.3.2 下架商品

(1)業務層

修改com.changgou.goods.service.SpuService接口,添加pull方法,用於商品下架,代碼如下:

1
2
3
4
5
/***
 * 商品下架
 * @param spuId
 */
void pull(Long spuId);

修改com.changgou.goods.service.impl.SpuServiceImpl,添加如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * 商品下架
 * @param spuId
 */
@Override
public void pull(Long spuId) {
    Spu spu = spuMapper.selectByPrimaryKey(spuId);
    if(spu.getIsDelete().equals("1")){
        throw new RuntimeException("此商品已刪除!");
    }
    spu.setIsMarketable("0");//下架狀態
    spuMapper.updateByPrimaryKeySelective(spu);
}

(2)控制層

修改com.changgou.goods.controller.SpuController,添加pull方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
/**
 * 下架
 * @param id
 * @return
 */
@PutMapping("/pull/{id}")
public Result pull(@PathVariable Long id){
    spuService.pull(id);
    return new Result(true,StatusCode.OK,"下架成功");
}

3.3.3 上架商品

必須是通過審覈的商品才能上架

(1)業務層

修改com.changgou.goods.service.SpuService,添加put方法,代碼如下:

1
2
3
4
5
/***
 * 商品上架
 * @param spuId
 */
void put(Long spuId);

修改com.changgou.goods.service.impl.SpuServiceImpl,添加put方法實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/***
 * 商品上架
 * @param spuId
 */
@Override
public void put(Long spuId) {
    Spu spu = spuMapper.selectByPrimaryKey(spuId);
    //檢查是否刪除的商品
    if(spu.getIsDelete().equals("1")){
        throw new RuntimeException("此商品已刪除!");
    }
    if(!spu.getStatus().equals("1")){
        throw new RuntimeException("未通過審覈的商品不能!");
    }
    //上架狀態
    spu.setIsMarketable("1");
    spuMapper.updateByPrimaryKeySelective(spu);
}

(2)控制層

修改com.changgou.goods.controller.SpuController,添加put方法代碼如下:

1
2
3
4
5
6
7
8
9
10
/**
 * 商品上架
 * @param id
 * @return
 */
@PutMapping("/put/{id}")
public Result put(@PathVariable Long id){
    spuService.put(id);
    return new Result(true,StatusCode.OK,"上架成功");
}

3.3.4 批量上架

前端傳遞一組商品ID,後端進行批量上下架處理

(1)業務層

修改com.changgou.goods.service.SpuService接口,代碼如下:

int putMany(Long[] ids);

修改com.changgou.goods.service.impl.SpuServiceImpl,添加批量上架方法實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/***
 * 批量上架
 * @param ids:需要上架的商品ID集合
 * @return
 */
@Override
public int putMany(Long[] ids) {
    Spu spu=new Spu();
    spu.setIsMarketable("1");//上架
    //批量修改
    Example example=new Example(Spu.class);
    Example.Criteria criteria = example.createCriteria();
    criteria.andIn("id", Arrays.asList(ids));//id
    //下架
    criteria.andEqualTo("isMarketable","0");
    //審覈通過的
    criteria.andEqualTo("status","1");
    //非刪除的
    criteria.andEqualTo("isDelete","0");
    return spuMapper.updateByExampleSelective(spu, example);
}

(2)控制層

修改com.changgou.goods.controller.SpuController,天啊及批量上架方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
/**
 *  批量上架
 * @param ids
 * @return
 */
@PutMapping("/put/many")
public Result putMany(@RequestBody Long[] ids){
    int count = spuService.putMany(ids);
    return new Result(true,StatusCode.OK,"上架"+count+"個商品");
}

使用Postman測試:

3.3.5 批量下架

學員實現

4 刪除與還原商品

4.1 需求分析

請看管理後臺的靜態原型

商品列表中的刪除商品功能,並非真正的刪除,而是將刪除標記的字段設置爲1,

在回收站中有恢復商品的功能,將刪除標記的字段設置爲0

在回收站中有刪除商品的功能,是真正的物理刪除。

4.2 實現思路

邏輯刪除商品,修改spu表is_delete字段爲1

商品回收站顯示spu表is_delete字段爲1的記錄

回收商品,修改spu表is_delete字段爲0

4.3 代碼實現

4.3.1 邏輯刪除商品

(1)業務層

修改com.changgou.goods.service.SpuService接口,增加logicDelete方法,代碼如下:

1
2
3
4
5
/***
 * 邏輯刪除
 * @param spuId
 */
void logicDelete(Long spuId);

修改com.changgou.goods.service.impl.SpuServiceImpl,添加logicDelete方法實現,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/***
 * 邏輯刪除
 * @param spuId
 */
@Override
@Transactional
public void logicDelete(Long spuId) {
    Spu spu = spuMapper.selectByPrimaryKey(spuId);
    //檢查是否下架的商品
    if(!spu.getIsMarketable().equals("0")){
        throw new RuntimeException("必須先下架再刪除!");
    }
    //刪除
    spu.setIsDelete("1");
    //未審覈
    spu.setStatus("0");
    spuMapper.updateByPrimaryKeySelective(spu);
}

(2)控制層

修改com.changgou.goods.controller.SpuController,添加logicDelete方法,如下:

1
2
3
4
5
6
7
8
9
10
/**
 * 邏輯刪除
 * @param id
 * @return
 */
@DeleteMapping("/logic/delete/{id}")
public Result logicDelete(@PathVariable Long id){
    spuService.logicDelete(id);
    return new Result(true,StatusCode.OK,"邏輯刪除成功!");
}

4.3.2 還原被刪除的商品

(1)業務層

修改com.changgou.goods.service.SpuService接口,添加restore方法代碼如下:

1
2
3
4
5
/***
 * 還原被刪除商品
 * @param spuId
 */
void restore(Long spuId);

修改com.changgou.goods.service.impl.SpuServiceImpl類,添加restore方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
 * 恢復數據
 * @param spuId
 */
@Override
public void restore(Long spuId) {
    Spu spu = spuMapper.selectByPrimaryKey(spuId);
    //檢查是否刪除的商品
    if(!spu.getIsDelete().equals("1")){
        throw new RuntimeException("此商品未刪除!");
    }
    //未刪除
    spu.setIsDelete("0");
    //未審覈
    spu.setStatus("0");
    spuMapper.updateByPrimaryKeySelective(spu);
}

(2)控制層

修改com.changgou.goods.controller.SpuController,添加restore方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
/**
 * 恢復數據
 * @param id
 * @return
 */
@PutMapping("/restore/{id}")
public Result restore(@PathVariable Long id){
    spuService.restore(id);
    return new Result(true,StatusCode.OK,"數據恢復成功!");
}

4.3.3 物理刪除商品

修改com.changgou.goods.service.impl.SpuServiceImpl的delete方法,代碼如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * 刪除
 * @param id
 */
@Override
public void delete(Long id){
    Spu spu = spuMapper.selectByPrimaryKey(id);
    //檢查是否被邏輯刪除  ,必須先邏輯刪除後才能物理刪除
    if(!spu.getIsDelete().equals("1")){
        throw new RuntimeException("此商品不能刪除!");
    }
    spuMapper.deleteByPrimaryKey(id);
}

5 商品列表

5.1 需求分析

 

如圖所示 展示商品的列表。並實現分頁。

思路:

1
2
根據查詢的條件 分頁查詢 並返回分頁結果即可。
分頁查詢 採用 pagehelper ,條件查詢  通過map進行封裝傳遞給後臺即可。

5.2 代碼實現

在代碼生成器生成的代碼中已經包含了該實現,這裏就省略了。

 

控制層(SpuController):

1
2
3
4
5
6
7
8
9
10
11
12
13
/***
 * Spu分頁條件搜索實現
 * @param spu
 * @param page
 * @param size
 * @return
 */
@PostMapping(value = "/search/{page}/{size}" )
public Result<PageInfo> findPage(@RequestBody(required = false) Spu spu, @PathVariable  int page, @PathVariable  int size){
    //執行搜索
    PageInfo<Spu> pageInfo = spuService.findPage(spu, page, size);
    return new Result(true,StatusCode.OK,"查詢成功",pageInfo);
}

 

其他每層代碼,代碼生成器已經生成,這裏就不再列出來了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章