SPU = Standard Product Unit (标准化产品单元)
SPU是商品信息聚合的最小单位,是一组可复用、易检索
的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个SPU。
SKU=stock keeping unit(库存量单位)
SKU即库存进出计量的单位, 可以是以件、盒、托盘等为单位。
SKU是物理上不可分割的最小存货单元。在使用时要根据不同业态,不同管理模式来处理。在服装、鞋类商品中使用最多最普遍。
SPU就是代表多规格选项,SKU就是单件商品单种价格的单选项。所以一个SPU里面有多个SKU.
举例说明:
你想要一台iPhone XS, 店员也会再继续问: 你想要什么iPhone XS? 16G 银色?64G白色?每一台iPhone XS的毛重都是420.00g,产地也都是中国大陆,这两个属性就属于spu属性。
而容量和颜色,这种会影响价格和库存的(比如16G与64G的价格不同,16G银色还有货,金色卖完了)属性就是sku属性。
spu属性:
1、毛重420.00 g
2、产地中国大陆
sku属性:
2、容量: 16G, 64G, 128G
3、颜色: 银、白、玫瑰金
例如:iPhone X 可以确定一个产品即为一个SPU。
例如:iPhone X 64G 银色 则是一个SKU。
public class GoodsVo implements Serializable {
private Goods goods; // 商品基本信息
private GoodsDesc goodsDesc; // 商品描述信息
private List<Item> itemList; // 商品对应的库存信息
}
/**
* 保存商品
* @param goodsVo
* @return
*/
@RequestMapping("/add.do")
public Result add(@RequestBody GoodsVo goodsVo){
try {
// 设置商家的id
String sellerId = SecurityContextHolder.getContext().getAuthentication().getName();
goodsVo.getGoods().setSellerId(sellerId);
goodsService.add(goodsVo);
return new Result(true, "保存成功");
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "保存失败");
}
}
/**
* 录入商品
* @param goodsVo
*/
@Transactional
@Override
public void add(GoodsVo goodsVo) {
// 保存商品基本信息
Goods goods = goodsVo.getGoods();
goods.setAuditStatus("0"); // 该商品待审核的状态
// goods.setSellerId(); // 属于哪个商家
goodsDao.insertSelective(goods); // 返回自增主键的id
// 保存商品描述信息
GoodsDesc goodsDesc = goodsVo.getGoodsDesc();
goodsDesc.setGoodsId(goods.getId());
goodsDescDao.insertSelective(goodsDesc);
// 保存商品对应的库存信息
// 并不是所有的商品都有规格的
if("1".equals(goods.getIsEnableSpec())){
// 启用规格:一个商品对应多个库存
// 商品对应的库存
List<Item> itemList = goodsVo.getItemList();
if(itemList != null && itemList.size() > 0){
for (Item item : itemList) {
// 设置库存的标题=spu名称+spu副标题+规格名称
String title = goods.getGoodsName() + " " + goods.getCaption();
// 规格名称:
// 栗子:{"机身内存":"16G","网络":"联通3G"}
String spec = item.getSpec();
Map<String, String> map = JSON.parseObject(spec, Map.class);
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String, String> entry : entries) {
title += " " + entry.getValue();
}
item.setTitle(title);
setAttributeForItem(goods, goodsDesc, item);
// 保存库存
itemDao.insertSelective(item);
}
}
}else{
// 不启用规格:一个商品对应一个库存
Item item = new Item();
item.setTitle(goods.getGoodsName() + " " + goods.getCaption());
item.setIsDefault("1"); // 默认的库存信息
item.setSpec("{}"); // 无规格
item.setPrice(goods.getPrice());
item.setNum(9999); // 库存量
setAttributeForItem(goods, goodsDesc, item);
// 保存库存
itemDao.insertSelective(item);
}
}
// 设置库存的公共的属性
private void setAttributeForItem(Goods goods, GoodsDesc goodsDesc, Item item){
// 设置库存的图片
// 栗子:[{"color":"灰色","url":"http://192.168.200.128/group1/M00/00/01/wKjIgFrUSH2ABS1yAAh0T6sNTaI610.jpg"},{"color":"灰色","url":"http://192.168.200.128/group1/M00/00/01/wKjIgFrUSJGALjVYAAPzuN901mo975.jpg"},{"color":"灰色","url":"http://192.168.200.128/group1/M00/00/01/wKjIgFrUSJ6ARZShAAOxPhR4epI871.jpg"},{"color":"灰色","url":"http://192.168.200.128/group1/M00/00/01/wKjIgFrUSKeAeYH6AARqxrS1vQY435.jpg"},{"color":"灰色","url":"http://192.168.200.128/group1/M00/00/01/wKjIgFrUSLKAYbeGAAm3IpFnIFU096.jpg"},
// {"url":"http://192.168.200.128/group1/M00/00/01/wKjIgFrUSLqAE7jjAALFbaIpUAs688.jpg"}]
String images = goodsDesc.getItemImages();
List<Map> list = JSON.parseArray(images, Map.class);
if(list != null && list.size() > 0){
// 取出一张图片
String image = list.get(0).get("url").toString();
item.setImage(image);
}
item.setCategoryid(goods.getCategory3Id()); // 三级分类id
item.setStatus("1"); // 状态
item.setGoodsId(goods.getId()); // 商品id
item.setSellerId(goods.getSellerId()); // 商家id
item.setCreateTime(new Date());
item.setUpdateTime(new Date());
item.setCategory(itemCatDao.selectByPrimaryKey(goods.getCategory3Id()).getName()); // 分类名称
item.setBrand(brandDao.selectByPrimaryKey(goods.getBrandId()).getName()); // 品牌名称
item.setSeller(sellerDao.selectByPrimaryKey(goods.getSellerId()).getNickName()); // 店铺名称
}
package cn.itcast.core.controller.upload;
import cn.itcast.core.utils.fdfs.FastDFSClient;
import cn.itcast.entity.Result;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@RestController
@RequestMapping("/upload")
public class UploadController {
@Value("${FILE_SERVER_URL}")
private String FILE_SERVER_URL;
/**
* 商品图片的上传
* @param file
* @return
*/
@RequestMapping("/uploadFile.do")
public Result uploadFile(MultipartFile file){
try {
String conf = "classpath:fastDFS/fdfs_client.conf";
FastDFSClient fastDFSClient = new FastDFSClient(conf);
// 获取到文件的扩展名
// 获取原始附件名称:xxx.jpg
String filename = file.getOriginalFilename();
String extName = FilenameUtils.getExtension(filename);
String path = fastDFSClient.uploadFile(file.getBytes(), extName, null);
// 回显:拼接服务器地址http://192.168.200.128
// 服务器地址:常量,java中维护常量方式:配置文件、枚举、接口(对扩展开放,对修改关闭)
// 本次:通过配置文件维护服务器地址
String url = FILE_SERVER_URL + path;
return new Result(true, url);
} catch (Exception e) {
e.printStackTrace();
return new Result(false, "上传失败");
}
}
}
package cn.itcast.core.utils.fdfs;
import org.apache.commons.io.FilenameUtils;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
public class FastDFSClient {
private TrackerClient trackerClient = null;
private TrackerServer trackerServer = null;
private StorageServer storageServer = null;
private StorageClient1 storageClient = null;
public FastDFSClient(String conf) throws Exception {
if (conf.contains("classpath:")) {
conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
}
ClientGlobal.init(conf);
trackerClient = new TrackerClient();
trackerServer = trackerClient.getConnection();
storageServer = null;
storageClient = new StorageClient1(trackerServer, storageServer);
}
/**
* 上传文件方法
* Title: uploadFile
* Description:
* @param fileName 文件全路径
* @param extName 文件扩展名,不包含(.)
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileName, extName, metas);
return result;
}
public String uploadFile(byte[] file, String fileName, long fileSize) throws Exception {
NameValuePair[] metas = new NameValuePair[3];
metas[0] = new NameValuePair("fileName", fileName);
metas[1] = new NameValuePair("fileSize", String.valueOf(fileSize));
metas[2] = new NameValuePair("fileExt", FilenameUtils.getExtension(fileName));
String result = storageClient.upload_file1(file, FilenameUtils.getExtension(fileName), metas);
return result;
}
public String uploadFile(String fileName) throws Exception {
return uploadFile(fileName, null, null);
}
public String uploadFile(String fileName, String extName) throws Exception {
return uploadFile(fileName, extName, null);
}
/**
* 上传文件方法
* Title: uploadFile
* Description:
* @param fileContent 文件的内容,字节数组
* @param extName 文件扩展名
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileContent, extName, metas);
return result;
}
public String uploadFile(byte[] fileContent) throws Exception {
return uploadFile(fileContent, null, null);
}
public String uploadFile(byte[] fileContent, String extName) throws Exception {
return uploadFile(fileContent, extName, null);
}
}
部分知识引用自以下网站:
https://www.cnblogs.com/wangju/p/11997353.html