日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

乐优商城(04)--商品规格

發布時間:2023/12/10 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 乐优商城(04)--商品规格 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

樂優商城(04)–商品規格

一、商品規格數據結構

樂優商城是一個全品類的電商網站,因此商品的種類繁多,每一件商品,其屬性又有差別。為了更準確描述商品及細分差別,抽象出兩個概念:SPU和SKU,了解一下:

1.1.SPU和SKU

SPU:Standard Product Unit (標準產品單位) ,一組具有共同屬性的商品集

SKU:Stock Keeping Unit(庫存量單位),SPU商品集因具體特性不同而細分的每個商品

可以看出:

  • SPU是一個抽象的商品集概念,為了方便后臺的管理。
  • SKU才是具體要銷售的商品,每一個SKU的價格、庫存可能會不一樣,用戶購買的是SKU而不是SPU

1.2、數據庫表設計分析

數據庫中關于商品規格的表有五個即:

tb_spu表分析

以上面華為手機商品為例,頭部會顯示分類和品牌,所以需要該商品所屬的三個級別的分類id以及品牌id,

每個商品都會有標題和副標題,SPU是一個抽象的商品集概念,是為了方便后臺的管理的,所以需要該商品的上下架的狀態修改,以及創建時間和最后修改時間

這里是做了表的垂直拆分,將SPU的詳情放到了另一張表:tb_spu_detail

tb_spu_detail這張表中的數據都比較大,為了不影響主表的查詢效率所以拆分出這張表。

tb_spu_detail表分析

所以包含的字段有

description:描述 specification:規格 packaging_list:包裝 after_service:售后服務 comment:評價

評價的數據量很龐大且數據價值很低,若存儲在mysql中性能很不好,后面使用mongoDB存儲

一個分類下的所有SPU具有類似的規格參數。SPU下的SKU可能會有不同的規格參數信息,因此:

  • SPUDetail中保存通用的規格參數信息。
  • SKU中保存特有規格參數。

需要注意的是這兩個字段:generic_spec和special_spec。

  • generic_spec字段

    其中保存通用規格參數信息的值,為了方便查詢,使用json格式

    • key:對應的規格參數的spec_param的id
    • value:對應規格參數的值
  • special_spec字段

    以手機為例,品牌、操作系統等肯定是全局通用屬性,內存、顏色等肯定是特有屬性。

    當確定了一個SPU,比如小米的:小米11

    全局屬性值都是固定的了:

    品牌:小米 型號:小米11

    特有屬性舉例:

    顏色:[香檳金, 櫻花粉, 磨砂黑] 內存:[6G, 8G] 機身存儲:[56GB, 128GB, 256GB]

    顏色、內存、機身存儲,作為SKU特有屬性,key雖然一樣,但是SPU下的每一個SKU,其值都不一樣,所以值會有很多,形成數組。

    在SPU中,會把特有屬性的所有值都記錄下來,形成一個數組,也是json結構:

    • key:規格參數id
    • value:spu屬性的數組

    之所以在spu中也記錄一份特有規格參數,是因為有時候需要把所有規格參數都查詢出來,而不是只查詢1個sku的屬性。比如,商品詳情頁展示可選的規格參數時

tb_sku表分析

不同的商品分類,屬性是不同,比如手機有內存,衣服有尺碼,所以很難設計在同一張表中

但是注意SKU是具體的商品信息,也是有一些單個屬性的

即:與spu關聯、標題、產品圖片、價格、特有屬性

SKU的特有屬性是商品規格參數的一部分

這樣規格參數中的屬性可以標記成兩部分:

  • spu下所有sku共享的規格屬性(稱為全局屬性)
  • 每個sku不同的規格屬性(稱為特有屬性)

查看搜索面板:

不難發現很多過濾條件在規格參數中都能找到,規格參數中的數據,將來會有一部分作為搜索條件來使用。所以在設計時,將這部分屬性標記出來,將來做搜索的時候,作為過濾條件。要注意的是,無論是SPU的全局屬性,還是SKU的特有屬性,都有可能作為搜索過濾條件的,并不沖突,而是有一個交集:

  • indexes字段

    保存的是特有屬性待選項的下標組合,中間用’_'連接

    拿上面的產品圖為例:

    選中了:羽墨黑,4GB+128GB,官方標配,優惠套餐2

    indexes字段內容為:0_0_0_1

    這樣設計當用戶點擊選中一個特有屬性,就能根據角標快速定位到sku。

tb_spec_group

可以看到規格參數是分組的,每一組都有多個參數鍵值對。不過對于規格參數的模板而言,其值現在是不確定的,不同的商品值肯定不同,模板中只要保存組信息、組內參數信息即可。

因此設計了兩張表:

  • tb_spec_group:組,與商品分類關聯
  • tb_spec_param:參數名,與組關聯,一對多

該tb_spec_group表中有三個字段:

  • id:主鍵
  • cid:商品分類id,一個分類下有多個模板
  • name:該規格組的名稱。

tb_spec_param

  • 通用屬性

    用一個布爾類型字段來標記是否為通用:

    • generic來標記是否為通用屬性:
      • true:代表通用屬性
      • false:代表sku特有屬性
  • 搜索過濾

    與搜索相關的有兩個字段:

    • searching:標記是否用作過濾
      • true:用于過濾搜索
      • false:不用于過濾
    • segments:某些數值類型的參數,在搜索時需要按區間劃分,這里提前確定好劃分區間
      • 比如電池容量,02000mAh,2000mAh3000mAh,3000mAh~4000mAh
  • 數值類型

    某些規格參數可能為數值類型,這樣的數據才需要劃分區間,我們有兩個字段來描述:

    • numberic:是否為數值類型
      • true:數值類型
      • false:不是數值類型
    • unit:參數的單位

二、商品規格管理

2.1、頁面布局

打開規格參數頁面,看到如下內容:

因為規格是跟商品分類綁定的,因此首先會展現商品分類樹,并且提示你要選擇商品分類,才能看到規格參數的模板。一起了解下頁面的實現:

點擊該頁面,可以發現這里使用了v-layout來完成頁面布局,并且添加了row屬性,代表接下來的內容是行布局(左右)。

可以看出頁面分成2個部分:

  • <v-flex xs3>:左側,內部又分上下兩部分:商品分類樹及標題
    • v-card-title:標題部分,這里是提示信息,告訴用戶要先選擇分類,才能看到模板
    • v-tree:這里用到的是我們之前講過的樹組件,展示商品分類樹,
  • <v-flex xs9 class="px-1">:右側:內部是規格參數展示

2.2、右側規格

右側規格最終效果:

可以看到右側分為上下兩部分:

  • 上部:面包屑,顯示當前選中的分類
  • 下部:table,顯示規格參數信息

頁面實現:

這是一個spec-group組件(規格組)和spec-param組件(規格參數),這是提前定義的獨立組件。在SpecGroup中定義了表格。

2.3、規格組的查詢

2.3.1、前端頁面

當點擊樹節點時,要將v-dialog打開,因此必須綁定一個點擊事件:(Specification.vue)

來看下handleClick方法:(Specification.vue)

點擊事件發生時,發生了兩件事:

  • 記錄當前選中的節點,選中的就是商品分類
  • showGroup被置為true,則規格組就會顯示了。

同時,把被選中的節點(商品分類)的id傳遞給了SpecGroup組件:(Specification.vue)

來看下SpecGroup.vue中的實現:

查看頁面控制臺,可以看到請求已經發出:

2.3.1、后端實現

實體類

在leyou-item-interface中添加實體類:

@Table(name = "tb_spec_param") public class SpecParam {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id; //主鍵private Long cid; //商品分類idprivate Long groupId; //分組idprivate String name; //參數名@Column(name = "`numeric`") //該字段在數據庫中為關鍵字,需特殊處理private Boolean numeric; //是否是數字類型參數private String unit; //數字類型參數的單位private Boolean generic; //是否是通用參數private Boolean searching; //是否可用于查詢private String segments; //若數值類型為搜素,需添加一個數字范圍//get和set方法 } @Table(name = "tb_spec_group") public class SpecGroup {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)private Long id; //主鍵private Long cid; //分類id 一個分類下會有多個規格組private String name; //規格組的名稱@Transientprivate List<SpecParam> params; //參數集合//get和set方法 }

mapper

/*** SpecGroup 通用mapper*/ public interface SpecGroupMapper extends Mapper<SpecGroup> { }

這里將SpecGroup和SpecParam兩個放在一起實現

controller

  • 請求方式:get
  • 請求路徑:/spec/groups/{cid} ,這里通過路徑占位符傳遞商品分類的id
  • 請求參數:商品分類id
  • 返回結果:頁面是直接把resp.data賦值給了groups:
@RestController @RequestMapping("/spec") public class SpecificationController {@Autowiredprivate SpecificationService specificationService;/*** 根據分類id查詢參數組* @param cid* @return*/@GetMapping("/groups/{cid}")public ResponseEntity<List<SpecGroup>> queryGroupsByCid(@PathVariable("cid") Long cid){List<SpecGroup> specGroups = this.specificationService.queryGroupsByCid(cid);if (CollectionUtils.isEmpty(specGroups)){return ResponseEntity.notFound().build();}return ResponseEntity.ok(specGroups);} }

service

public interface SpecificationService {/*** 根據分類id查詢參數組* @param cid* @return*/List<SpecGroup> queryGroupsByCid(Long cid); }

實現類:

@Service public class SpecificationServiceImpl implements SpecificationService {@Autowiredprivate SpecGroupMapper specGroupMapper;/*** 根據分類id查詢參數組** @param cid* @return*/@Overridepublic List<SpecGroup> queryGroupsByCid(Long cid) {SpecGroup specGroup = new SpecGroup();specGroup.setCid(cid);return this.specGroupMapper.select(specGroup);} }

2.4、規格參數查詢

2.4.1、前端頁面

表格切換:

當點擊規格組,會切換到規格參數顯示,肯定是在規格組中綁定了點擊事件:

看下事件處理:

可以看到這里是使用了父子通信,子組件觸發了select事件.

再來看下父組件的事件綁定:

事件處理:

這里記錄了選中的分組,并且把標記設置為false,這樣規格組就不顯示了,而是顯示:SpecParam

并且,把group也傳遞到spec-param組件:

來看SpecParam.vue的實現:

查看頁面控制臺,發現請求已經發出:

2.4.2、后端實現

mapper

/*** SpecParam 的通用mapper*/ public interface SpecParamMapper extends Mapper<SpecParam> { }

controller

  • 請求方式:GET
  • 請求路徑:/spec/params
  • 請求參數:gid,分組id
  • 返回結果:該分組下的規格參數集合List<SpecParam>
/*** 根據gid查詢具體參數* @param gid* @return*/ @GetMapping("/params") public ResponseEntity<List<SpecParam>> queryParamsByGid(@RequestParam("gid") Long gid){List<SpecParam> specParams = this.specificationService.queryParamsByGid(gid);if (CollectionUtils.isEmpty(specParams)){return ResponseEntity.notFound().build();}return ResponseEntity.ok(specParams); }

service

/*** 根據gid查詢具體參數* @param gid* @return*/ List<SpecParam> queryParamsByGid(Long gid);

實現類:

@Autowired private SpecParamMapper specParamMapper;/*** 根據gid查詢具體參數** @param gid* @return*/ @Override public List<SpecParam> queryParamsByGid(Long gid) {SpecParam specParam = new SpecParam();specParam.setGroupId(gid);return this.specParamMapper.select(specParam); }

2.5、規格參數組增、刪、改

2.5.1、前端頁面

點擊新增分組按鈕,請求已發:

查看前端頁面代碼:

2.5.2、后端實現

增加:

controller

  • 請求方式:POST
  • 請求路徑:/item/spec/group
  • 請求參數:specGroup
  • 返回結果:無,響應狀態碼為201
/*** 添加一個參數分組* @param specGroup* @return*/ @PostMapping("/group") public ResponseEntity<Void> addSpecGroup(@RequestBody SpecGroup specGroup){this.specificationService.addSpecGroup(specGroup);return ResponseEntity.status(HttpStatus.CREATED).build(); }

service

/*** 添加一個參數分組* @param specGroup* @return*/ void addSpecGroup(SpecGroup specGroup);

實現類:

/*** 添加一個參數分組** @param specGroup* @return*/ @Override public void addSpecGroup(SpecGroup specGroup) {this.specGroupMapper.insert(specGroup); }

修改:

controller

  • 請求方式:PUT
  • 請求路徑:/item/spec/group
  • 請求參數:specGroup
  • 返回結果:無,響應狀態碼為202
/*** 修改一個參數分組* @param specGroup* @return*/@PutMapping("/group")public ResponseEntity<Void> updateSpecGroup(@RequestBody SpecGroup specGroup){this.specificationService.updateSpecGroup(specGroup);return ResponseEntity.status(HttpStatus.ACCEPTED).build();}

service

/*** 修改一個參數分組* @param specGroup* @return*/ void updateSpecGroup(SpecGroup specGroup);

實現類

/*** 修改一個參數分組** @param specGroup* @return*/ @Override public void updateSpecGroup(SpecGroup specGroup) {this.specGroupMapper.updateByPrimaryKeySelective(specGroup); }

刪除:

controller

  • 請求方式:POST
  • 請求路徑:/item/spec/group
  • 請求參數:id,即參數組的id
  • 返回結果:無,響應狀態碼為200
/*** 根據組id刪除參數組* @param gid* @return*/ @DeleteMapping("/group/{id}") public ResponseEntity<Void> deleteSpecGroup(@PathVariable("id") Long gid){this.specificationService.deleteSpecGroup(gid);return ResponseEntity.ok().build(); }

service

/*** 根據組id刪除參數組* @param gid* @return*/ void deleteSpecGroup(Long gid);

實現類:

/*** 根據組id刪除參數組** @param gid* @return*/ @Override @Transactional public void deleteSpecGroup(Long gid) {//先查詢該參數組內的參數List<SpecParam> specParams = queryParamsByGid(gid);//如果組內有數據if (specParams.size() > 0){//刪除組內的具體參數specParams.forEach(specParam -> this.specParamMapper.deleteByPrimaryKey(specParam));}//再刪除參數組this.specGroupMapper.deleteByPrimaryKey(gid); }

2.6、規格參數的增、刪、改

2.6.1、前端頁面

點即新增參數,查看表單和發送的請求

查看前端頁面代碼:

2.6.2、后端實現

新增:

controller

  • 請求方式:POST
  • 請求路徑:/item/spec/group
  • 請求參數:SpecParam
  • 返回結果:無,響應狀態碼為201
/*** 添加一個參數* @param specParam* @return*/ @PostMapping("/param") public ResponseEntity<Void> addSpecParam(@RequestBody SpecParam specParam){this.specificationService.addSpecParam(specParam);return ResponseEntity.status(HttpStatus.CREATED).build(); }

service

/*** 添加一個參數* @param specParam* @return*/ void addSpecParam(SpecParam specParam);

實現類:

/*** 添加一個參數** @param specParam* @return*/ @Override public void addSpecParam(SpecParam specParam) {this.specParamMapper.insert(specParam); }

修改:

controller

  • 請求方式:PUT
  • 請求路徑:/item/spec/group
  • 請求參數:SpecParam
  • 返回結果:無,響應狀態碼為202
/*** 修改一個參數* @param specParam* @return*/ @PutMapping("/param") public ResponseEntity<Void> updateSpecParam(@RequestBody SpecParam specParam){this.specificationService.updateSpecParam(specParam);return ResponseEntity.status(HttpStatus.ACCEPTED).build(); }

service

/*** 修改一個參數* @param specParam* @return*/ void updateSpecParam(SpecParam specParam);

實現類:

/*** 修改一個參數** @param specParam* @return*/ @Override public void updateSpecParam(SpecParam specParam) {this.specParamMapper.updateByPrimaryKeySelective(specParam); }

刪除:

controller

  • 請求方式:DELETE
  • 請求路徑:/item/spec/group
  • 請求參數:id,即參數的id
  • 返回結果:無,響應狀態碼為202
/*** 根據參數的id刪除參數* @param id* @return*/ @DeleteMapping("/param/{id}") public ResponseEntity<Void> deleteSpecParam(@PathVariable("id") Long id){this.specificationService.deleteSpecParam(id);return ResponseEntity.ok().build(); }

service

/*** 根據參數的id刪除參數* @param id* @return*/ void deleteSpecParam(Long id);

實現類:

/*** 根據參數的id刪除參數** @param id* @return*/ @Override public void deleteSpecParam(Long id) {this.specParamMapper.deleteByPrimaryKey(id); }

總結

以上是生活随笔為你收集整理的乐优商城(04)--商品规格的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。