欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

商城作战项目分析--SKU 商品管理

最编程 2024-03-31 11:23:21
...

一、什么是“SKU”

SKU英文全称为Stock Keeping Unit,简称SKU,是产品入库后一种编码归类方法,也是库存控制的最小单位

我们可以理解为商家用于管理商品库存和销售的一种方式。

每个 SKU 对应着一个若干属性的组合,例如一个商品存在颜色、尺寸、款式等属性。商家可以根据商品的不同属性设置不同的 SKU,并对每个 SKU 进行价格、库存若干信息的管理。

举个例子:

一款手机的购买选择有颜色存储大小

  • 颜色有白色黑色

  • 存储大小有128g256g

那么该商品便存在 4 个 SKU ,分别为:

  • 白色+128g

  • 白色+256g

  • 黑色+128g

  • 黑色+256g

在这里我们就要明确一下概念了,颜色、存储大小都是我们的商品属性中的销售属性,而生成的“白色+128g”、“黑色+128g”等等 就是我们的SKU。

下面看一下某商品界面的截图

1.png

这个商品的销售属性:颜色(4个) 存储容量(4个),那么通过销售属性,最终将会生成4*4=16个SKU,而用户选择任意存储容量 + 颜色分类的搭配都可以匹配到具体的价格与库存等信息。

二、实现商品SKU构建

源码下载链接:https://gitee.com/wang-boy326/nothing-boy.git

1、表设计

我们遇到的商品参数更多时候都是多个的,我们重点看一下多个商品参数我们应该怎么去设计表

商品表

我们要有一个商品表,表内容应该有商品id、商品标识、商品图片、商品状态、商品价格等等,示例建表语句如下:

CREATE TABLE `shop` (
  `shop_id` int(10) NOT NULL,
  `title` varchar(100) NOT NULL COMMENT '标题',
  `img` varchar(255) NOT NULL COMMENT '图片',
  `price` decimal(10,0) NOT NULL COMMENT '现价',
  `info` text NOT NULL COMMENT '信息',
  `status` enum('close','open') NOT NULL DEFAULT 'close' COMMENT '状态',
  `old_price` decimal(10,0) NOT NULL COMMENT '原价',
  `createtime` int(11) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='商品表';

表中数据如下

INSERT INTO `shop` (`shop_id`, `title`, `img`, `price`, `info`, `status`, `old_price`, `createtime`) VALUES
(1, '上衣', '111', '30', '111', 'close', '100', 111),
(2, '内裤', '222', '33', '222', 'close', '100', 222),
(3, '裙子', '333', '40', '333', 'close', '100', 100),
(4, '鞋子', '444', '40', '444', 'close', '100', 100);

属性表

然后就是商品下的属性,这个属性表表示的是第一级的参数,也就是示例中的款式颜色

这时表的内容就可以包括id、name、排序(sort)、商品id(shop_id)、图片(img)、等等,可以根据需要添加,下面我们创建一个上衣的属性表,建表语句如下

CREATE TABLE `shop_attribute` (
  `aid` int(10) NOT NULL,
  `name` varchar(100) NOT NULL COMMENT '属性名',
  `sort` int(100) NOT NULL COMMENT '排序',
  `shop_id` int(10) NOT NULL COMMENT '商品id'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='属性表';

其中的shop_id对应商品表中的shop_id;我们可以根据商品可能需要的属性,自行添加会需要的,例如上述示例中的材质、尺寸等等

表中数据示例如下

INSERT INTO `shop_attribute` (`aid`, `name`, `sort`, `shop_id`) VALUES
(1, '款式', 100, 1),
(2, '颜色', 99, 1),
(3, '尺寸', 98, 1),
(4, '材质', 11, 1);

属性值表

属性值顾名思义表示的就是上面商品属性中可能存在的值,例如款式中的圆形、心形,颜色中的白色、黑色等等,

其中我们需要添加一个属性id,对应上一个属性表中的aid,建表语句示例如下

CREATE TABLE `shop_attribute_value` (
  `vid` int(10) NOT NULL COMMENT '属性值id',
  `name` varchar(100) NOT NULL COMMENT '属性名',
  `sort` int(100) NOT NULL COMMENT '排序',
  `shop_id` int(100) NOT NULL COMMENT '商品id',
  `aid` int(100) NOT NULL COMMENT '属性id'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='属性值表';

我们设计了共有四类属性,分别是款式、颜色、尺寸和材质;那就给这些属性添加属性值,设计如下

INSERT INTO `shop_attribute_value` (`vid`, `name`, `sort`, `shop_id`, `aid`) VALUES
(1, '圆形', 100, 1, 1),
(2, '花型', 99, 1, 1),
(3, '心形', 98, 1, 1),
(4, '肉色', 100, 1, 2),
(5, '黑色', 99, 1, 2),
(6, '红色', 98, 1, 2),
(7, 'XL', 90, 1, 3),
(8, '全棉', 1, 1, 4),
(9, '涤纶', 11, 1, 4);

属性组合表(sku)

上面的表已经把我们需要的商品、商品属性、商品属性值已经列出来了,这时候就是简单的排列组合,也就是我们的属性组合表sku,

这次的表中我们要加入指定sku的价格和库存;

在上述属性值表的例子中,我们有4个属性,属性值共有9个;我们需要创建一个sku表,这个表需要有的内容可能会包括指定属性值的价格、库存数量、商品id,建表语句如下

CREATE TABLE `shop_sku_value` (
  `skuid` int(11) NOT NULL,
  `vids` varchar(20) NOT NULL COMMENT 'sku',
  `price` decimal(10,0) NOT NULL COMMENT '价格',
  `num` int(11) NOT NULL COMMENT '数量',
  `shop_id` int(100) NOT NULL COMMENT '商品id'
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='sku表';

示例中的vids,,表示的就是属性值的排列组合,也即sku,那么这种情况下的属性组合表的数据就是

INSERT INTO `shop_sku_value` (`skuid`, `vids`, `price`, `num`, `shop_id`) VALUES
(1, '1,4,7,8', '30', 900, 1),
(2, '1,4,7,9', '41', 78, 1),
(3, '1,5,7,8', '71', 900, 1),
(4, '1,5,7,9', '40', 30, 1),
(5, '1,6,7,8', '40', 90, 1),
(6, '1,6,7,9', '50', 0, 1),
(7, '2,4,7,8', '30', 900, 1),
(8, '2,4,7,9', '41', 78, 1),
(9, '2,5,7,8', '71', 900, 1),
(10, '2,5,7,9', '40', 30, 1),
(11, '2,6,7,8', '40', 90, 1),
(12, '2,6,7,9', '50', 0, 1),
(13, '3,4,7,8', '30', 900, 1),
(14, '3,4,7,9', '41', 78, 1),
(15, '3,5,7,8', '71', 900, 1),
(16, '3,5,7,9', '40', 30, 1),
(17, '3,6,7,8', '40', 90, 1),
(18, '3,6,7,9', '50', 0, 1);

简单介绍一下,其中vids数据1,4,7,8表示:1->圆形,4->肉色,7->XL,8->全棉,那么一件肉色、圆形并且全棉的XL商品,价格是30,还有900库存。

2、代码设计

2.1 模型

我们创建一个名为ShopModel的模型,路径为tp/app/model/ShopModel.php,用于操作shop表,也即商品表;

<?php
namespace app\model;
use think\Model;
class ShopModel extends Model
{
    protected $table = 'shop';
    protected $pk = 'shop_id';
}

创建一个名为ShopAttribute的模型,路径为tp/app/model/ShopAttribute.php,用于操作shop_attribute表,也即属性表;

<?php
namespace app\model;
use think\Model;
class ShopAttribute extends Model
{
    protected $table = 'shop_attribute';
    protected $pk = 'aid';
}

创建一个名为ShopAttributeValue的模型,路径为tp/app/model/ShopAttributeValue.php,用于操作shop_attribute_value表,也即属性值表;

<?php
namespace app\model;
use think\Model;
class ShopAttributeValue extends Model
{
    protected $table = 'shop_attribute_value';
    protected $pk = 'vid';
}

创建一个名为ShopSkuValue的模型,路径为tp/app/model/ShopSkuValue.php,用于操作shop_sku_value表,也即sku表;

<?php
namespace app\model;
use think\Model;
class ShopSkuValue extends Model
{
    protected $table = 'shop_sku_value';
    protected $pk = 'skuid';
}

2.2 控制层

创建一个名为Shop.php的控制器,路径为app/controller/Shop.php,其中包含以下方法:

<?php
namespace app\controller;
use app\model\ShopModel;
use app\model\ShopAttribute;
use app\model\ShopAttributeValue;
use app\model\ShopSkuValue;
use app\BaseController;
use think\facade\View;
class Shop extends BaseController
{
    public function index()
    {
        $sid = 1;
        //查询商品
        $shop = ShopModel::where('status', 'close')->where('shop_id',$sid)->limit(3)->order('shop_id', 'asc')->find();
        //查询与指定商品相关的属性和属性值,并将查询结果存储在$attr数组中。
        $attr = ShopAttribute::where('shop_id',$shop['shop_id'])->order('sort', 'desc')->select()->toArray();
        foreach($attr as &$val)
        {
            //获取每一个属性的值,保存起来
            $val['attrvalue'] = ShopAttributeValue::where('aid',$val['aid'])->order('sort', 'desc')->select()->toArray();
        }
        return View::fetch('index', ['shop' => $shop,'attrs'=> $attr]);
    }
}

2.3、视图层

然后再创建index.html,用于前端展示,路径为tp/app/view/shop/index.html,示例如下:

<!-- app\view\shop\index.html -->
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>SKU程序</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
        <!-- 在页面上显示商品的标题和价格。 -->
    <h2><?php echo $shop['title']?>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;价格<span id="price"><?php echo $shop['price']?></span>元</h2>
     <!-- 分页查询 -->
     <!-- 根据给定的属性和属性值数组,在页面中显示数据。每个下拉列表框代表一个属性,其中的选项代表该属性的属性值 -->
    {volist name='attrs' id='v'}
    <select id="shopSelect">
        <option value="">请选择{$v.name}</option>
        {volist name='$v.attrvalue' id='vv'}
            <option value="{$vv.vid}"> {$vv.name}</option>
        {/volist}
    </select>
    {/volist}
</body>
</html>

显示结果如下:

20.png

现在所有的属性都可以在前台展示,我们需要根据点击选择的不同属性也即sku,来确定不同的价格

这时候我们要用到一个按钮点击事件,用于实现了一个点击按钮后发送Ajax请求,并根据请求结果更新页面内容的功能

<button id="submitButton">提交</button>
    <script>
        var shop_id = '<?php echo $shop['shop_id']?>';
        $(document).ready(function() {
            // 给按钮添加点击事件
            $("#submitButton").click(function() {
                var vids = {}; // 定义请求数据对象
                // 循环遍历所有select元素
                $("select").each(function(index) {
                    var selectValue = $(this).val(); // 获取当前select的值
                    var selectName = "select" + (index + 1); // 构造select的名称,如select1、select2、select3...
                    vids[selectName] = selectValue; // 将select的名称和值添加到请求数据对象中
                });
                // 发送Ajax请求
                $.ajax({
                    url: "/get_shop_price", // 替换为实际的请求地址
                    type: "GET", // GET请求
                    data: {shop_id:shop_id,vids:vids},//指定了请求的参数
                    dataType: "json", // 返回数据的类型
                    success: function(response) {
                        // 请求成功的处理逻辑
                        if(response.data.num>0)
                        {
                            //如果返回的数据中num大于0,则将price的文本内容更新为返回数据中的price
                            $('#price').text(response.data.price);
                        }
                        else{
                            //否则弹出提示
                            alert('已经卖完');
                        }
                    },
                    error: function(xhr, status, error) {
                        // 请求失败的处理逻辑
                        console.error(error);
                    }
                });
            });
        });
    </script>

根据传入的shop_id和vids参数,查询数据库中是否存在匹配的SKU值。如果存在,返回查询结果的JSON格式响应数据;如果不存在,返回一个空的JSON响应数据。

将下列代码添加到app/controller/Shop.php中:

    public function getShopPrice()
    {
        //获取请求中的shop_id参数,并将其赋值给变量$shop_id
        $shop_id=$_GET['shop_id'];
        //获取请求中的vids参数,并将其赋值给变量$vids
        $vids=$_GET['vids'];
        //确保每次传入的vids参数的顺序一致
        sort($vids);
        //将排序后的数组拼接成以逗号分隔的字符串
        $vids = implode(",", $vids);
        //查询数据库中符合条件的记录
        if($shopSkuValue = ShopSkuValue::where('vids',$vids)->where('shop_id',$shop_id)->find())
        {
            //如果查询结果存在,即找到了匹配的SKU值,将查询结果转换为数组
            $skuData = $shopSkuValue->toArray();
            //返回JSON格式的响应数据
            return json(['data'=>$skuData]);
        }
        else {
            //如果查询结果不存在,返回一个空的JSON响应数据
            return json(['data'=>[]]);
        }
    }

结果显示如下:

17.png

指定sku之后显示结果:

21.png

当没有库存时显示结果:

22.png

源码下载链接:https://gitee.com/wang-boy326/nothing-boy.git