樂優商城(十一)商品管理
目錄
3.8 表單提交
3.8.1 新增提交按鈕和動畫
樣式:
<v-layout row> <v-spacer></v-spacer> <v-btn :loading="loading3" :disabled="loading3" color="blue-grey" class="white--text mt-5" @click.native="loader = 'loading3'" @click="submit" > 儲存商品資訊 <v-icon right dark>cloud_upload</v-icon> </v-btn> </v-layout>
<style scoped> @-moz-keyframes loader { from { transform: rotate(0); } to { transform: rotate(360deg); } } @-webkit-keyframes loader { from { transform: rotate(0); } to { transform: rotate(360deg); } } @-o-keyframes loader { from { transform: rotate(0); } to { transform: rotate(360deg); } } @keyframes loader { from { transform: rotate(0); } to { transform: rotate(360deg); } } </style>
動畫:
loader () {
const l = this.loader
this[l] = !this[l]
setTimeout(() => (this[l] = false), 2000)
this.loader = null
},
效果:
3.8.2 點選事件
當用戶點選儲存,就需要對頁面的資料進行整理,然後提交到後臺服務。
現在頁面包含了哪些資訊呢?先與資料庫對比,看看少什麼
-
goods:裡面包含了SPU的幾乎所有資訊
-
title:標題
-
subtitle:子標題,賣點
-
categories:分類物件陣列,需要進行整理 **
-
brandId:品牌id
-
spuDetail:商品詳情
-
packingList:包裝清單
-
afterService:售後服務
-
description:商品描述
-
缺少全域性規格屬性specifications **
-
缺少特有規格屬性模板spec_template **
-
-
-
skus:包含了sku列表的幾乎所有資訊
-
price:價格,需要處理為以分為單位
-
stock:庫存
-
enable:是否啟用
-
indexes:索引
-
images:圖片,陣列,需要處理為字串**
-
缺少其它特有規格,ows_spec **
-
缺少標題:需要根據spu的標題結合特有屬性生成 **
-
-
specifications:全域性規格引數的鍵值對資訊
-
specialSpec:特有規格引數資訊
在頁面繫結點選事件:
程式碼(新增和修改二合一):
submit(){
//1.先處理goods,用結構表示式接收,除了categories外,都接收到goodsParams中
const {categories: [{id:cid1},{id:cid2},{id:cid3}], ...goodsParams} = this.goods;
//2.處理全部規格引數
//目前specifications中只有公共屬性的值,要把特有屬性的值加上,一起存入資料庫
this.allSpecs.forEach(({group,params}) => {
const special = this.specialSpecs;
params.forEach(s => {
if (!s.global){
//如果是特殊屬性,那麼從specialSpecs中獲取selected的值賦值給option
special.forEach(t => {
if (t.k === s.k){
s.options = t.selected
}
})
}
})
});
//去掉公共屬性中的options
const specs = this.allSpecs.map(({group,params}) => {
const newParams = params.map(s => {
if (s.global) {
let {options, ...rest} = s;
return rest;
}else {
return s;
}
});
return {group,params:newParams}
});
//3.處理特有規格引數模板
const specTemplate = {};
this.specialSpecs.forEach(({k,selected}) => {
specTemplate[k] = selected;
});
//4.處理sku
const skus = this.skus.filter(s => s.enable).map(({price,stock,enable,images,indexes, ...rest}) => {
//標題,在spu的title基礎上,拼接特有規格屬性值(記憶體、機身儲存、機身顏色)
const title = goodsParams.title+" "+Object.values(rest).join(" ");
return {
price: this.$format(price+""),enable,indexes,title, //基本屬性
stock: this.$format(stock+""),
images: images && images.length > 0 ? images.join(",") : "", //圖片
ownSpec:JSON.stringify(rest), //特有規格引數
}
});
Object.assign(goodsParams,{
cid1,cid2,cid3, //商品分類
skus,
});
goodsParams.spuDetail.specifications = JSON.stringify(specs);
goodsParams.spuDetail.specTemplate = JSON.stringify(specTemplate);
//console.log(goodsParams)
this.$http({
url:"/item/goods",
method: this.isEdit ? 'put':'post',
data:goodsParams
}).then(() => {
//成功,關閉視窗
setTimeout(() =>{
this.$emit('close');
this.$message.success("儲存成功!");
this.clear();
},2000);
}).catch(() => {
this.$message.error("儲存失敗!");
});
}
測試提交資料:
3.8.3 後臺介面
Pojo
Spu
package com.leyou.item.pojo;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import java.util.Date;
/**
* @author li
*/
@Table(name = "tb_spu")
public class Spu {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long brandId;
/**
* 1級類目
*/
private Long cid1;
/**
* 2級類目
*/
private Long cid2;
/**
* 3級類目
*/
private Long cid3;
/**
* 標題
*/
private String title;
/**
* 子標題
*/
private String subTitle;
/**
* 是否上架
*/
private Boolean saleable;
/**
* 是否有效,邏輯刪除使用
*/
private Boolean valid;
/**
* 建立時間
*/
private Date createTime;
/**
* 最後修改時間
*/
private Date lastUpdateTime;
}
Sku
package com.leyou.item.pojo;
import javax.persistence.*;
import java.util.Date;
/**
* @author li
*/
@Table(name = "tb_sku")
public class Sku {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private Long spuId;
private String title;
private String images;
private Long price;
/**
* 商品特殊規格的鍵值對
*/
private String ownSpec;
/**
* 商品特殊規格的下標
*/
private String indexes;
/**
* 是否有效,邏輯刪除用
*/
private Boolean enable;
/**
* 建立時間
*/
private Date createTime;
/**
* 最後修改時間
*/
private Date lastUpdateTime;
@Transient
/**
* @Transient 表示該屬性並非一個到資料庫表的欄位的對映,ORM框架將忽略該屬性.
*/
private Long stock;
}
注意:這裡儲存了一個庫存欄位,在資料庫中是另外一張表儲存的,方便查詢。
Stock
ckage com.leyou.item.pojo;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* @author li
*/
@Table(name = "tb_stock")
public class Stock {
@Id
private Long skuId;
/**
* 秒殺可用庫存
*/
private Integer seckillStock;
/**
* 已秒殺數量
*/
private Integer seckillTotal;
/**
* 正常庫存
*/
private Long stock;
}
Controller
四個問題:
-
請求方式:POST
-
請求路徑:/goods
-
請求引數:Spu的json格式的物件,spu中包含spuDetail和Sku集合。那麼該怎麼接收?使用之前定義了一個SpuBo物件,作為業務物件,不過需要再擴充套件spuDetail和skus欄位:
package com.leyou.item.bo;
import com.leyou.item.pojo.Sku;
import com.leyou.item.pojo.Spu;
import com.leyou.item.pojo.SpuDetail;
import javax.persistence.Transient;
import java.util.List;
/**
* @author: 98050
* Time: 2018-08-14 22:10
* Feature:
*/
public class SpuBo extends Spu {
/**
* 商品分類名稱
*/
@Transient
private String cname;
/**
* 品牌名稱
*/
@Transient
private String bname;
/**
* 商品詳情
*/
@Transient
private SpuDetail spuDetail;
/**
* sku列表
*/
@Transient
private List<Sku> skus;
}
-
返回型別:無
程式碼:
/**
* 儲存商品
* @param spu
* @return
*/
@PostMapping
public ResponseEntity<Void> saveGoods(@RequestBody SpuBo spu){
this.goodsService.saveGoods(spu);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
注意:通過@RequestBody註解來接收Json請求
Mapper
這裡面涉及到的spuMapper、skuMapper、stockMapper和spuDetailMapper都是通用mapper。
Service
介面
/**
* 儲存商品
* @param spu
*/
void saveGoods(SpuBo spu);
實現類
這裡的邏輯比較複雜,除了要對SPU新增以外,還要對SpuDetail、Sku、Stock進行儲存 。
/**
* 儲存商品
* @param spu
*/
@Transactional(rollbackFor = Exception.class)
@Override
public void saveGoods(SpuBo spu) {
//儲存spu
spu.setSaleable(true);
spu.setValid(true);
spu.setCreateTime(new Date());
spu.setLastUpdateTime(spu.getCreateTime());
this.spuMapper.insert(spu);
//儲存spu詳情
SpuDetail spuDetail = spu.getSpuDetail();
spuDetail.setSpuId(spu.getId());
System.out.println(spuDetail.getSpecifications().length());
this.spuDetailMapper.insert(spuDetail);
//儲存sku和庫存資訊
saveSkuAndStock(spu.getSkus(),spu.getId());
}
private void saveSkuAndStock(List<Sku> skus, Long id) {
for (Sku sku : skus){
if (!sku.getEnable()){
continue;
}
//儲存sku
sku.setSpuId(id);
//預設不參加任何促銷
sku.setCreateTime(new Date());
sku.setLastUpdateTime(sku.getCreateTime());
this.skuMapper.insert(sku);
//儲存庫存資訊
Stock stock = new Stock();
stock.setSkuId(sku.getId());
stock.setStock(sku.getStock());
this.stockMapper.insert(stock);
}
}