# 一、商品规格表 skus

具体查看,三、skus[商品规格表] 字段设计

# 二、创建商品规格

# 1. 路由

app/router/admin/shop.js

module.exports = app => {
    ...
    //删除商品规格功能
    router.post('/shop/admin/skus/:id/delete', controller.admin.skus.deleteAPI);
    router.get('/shop/admin/skus/:id/delete', controller.admin.skus.delete);
    //修改商品规格状态功能
    router.post('/shop/admin/skus/:id/update_status',controller.admin.skus.updateStatus);
    //修改商品规格界面
    router.get('/shop/admin/skus/edit/:id', controller.admin.skus.edit);
    //批量删除商品规格
    router.post('/shop/admin/skus/deleteAll', controller.admin.skus.deleteAll);
    //修改商品规格数据功能
    router.post('/shop/admin/skus/:id', controller.admin.skus.update);
    // 创建商品规格界面
    router.get('/shop/admin/skus/create', controller.admin.skus.create);
    //创建商品规格提交数据
    router.post('/shop/admin/skus', controller.admin.skus.save);
    //商品规格列表页面
    router.get('/shop/admin/skus/:page', controller.admin.skus.indexAPI);
    router.get('/shop/admin/skus', controller.admin.skus.index);
    
};

# 2. 新建模型

app/model/skus.js

'use strict';

module.exports = app => {
    const { INTEGER, STRING, DATE, ENUM, TEXT, BIGINT } = app.Sequelize;

    const Skus = app.model.define('skus', {
        id: {
            type: INTEGER(20).UNSIGNED,
            primaryKey: true,
            autoIncrement: true,
            comment: '主键id'
        },
        type: {
            type: INTEGER(11),
            allowNull: true,
            defaultValue: 0,
            comment: '规格类型:0无限制,1颜色,2图片,3尺寸等等',
        },
        name: {
            type: STRING(30),
            allowNull: false,
            defaultValue: '',
            comment: '规格名称'
        },
        default: {
            type: STRING(2000),
            allowNull: true,
            defaultValue: '',
            comment: '规格值,用逗号隔开'
        },
        order: {
            type: INTEGER,//不限定长度.默认int(11)
            allowNull: true,
            defaultValue: 50,
            comment: '排序,默认50'
        },
        status: {
            type: INTEGER(1),
            allowNull: false,
            defaultValue: 1,
            comment: '状态:1:启用,0:禁用'
        },
        // sex: { type: ENUM, values: ['男','女','保密'], allowNull: true, defaultValue: '保密', comment: '留言用户性别'},
        create_time: {
            type: DATE,
            allowNull: false,
            defaultValue: app.Sequelize.fn('NOW'),
            get() {
                return app.formatTime(this.getDataValue('create_time'));
            }
        },
        update_time: { type: DATE, allowNull: false, defaultValue: app.Sequelize.fn('NOW') }
    });


    // 模型关联关系
    // Skus.associate = function (models) {
    //     // 关联到自己 (通过pid关联)
    //     // this.hasMany(app.model.GoodsClass, {
    //     //     foreignKey: 'pid',
    //     //     as: 'ChildGoodsClass' // 别名(可选)
    //     // });

    //     // 关联商品模型
    //     // this.hasMany(app.model.Image, {
    //     //     foreignKey: 'image_class_id',
    //     //     // as: 'images' // 别名(可选)
    //     // });


    // }

    return Skus;
}

# 3. 新建控制器

app/controller/admin/skus.js

'use strict';

const Controller = require('egg').Controller;

class SkusController extends Controller {
    // 创建商品规格界面
    async create() {
        const { ctx, app } = this;

        //渲染公共模版
        await ctx.renderTemplate({
            title: '创建商品规格',//现在网页title,面包屑导航title,页面标题
            tempType: 'form', //模板类型:table表格模板 ,form表单模板
            form: {
                //提交地址
                action: "/shop/admin/skus",
                //  字段
                fields: [
                    {
                        label: '商品规格名称',
                        type: 'text',
                        name: 'name',
                        placeholder: '请输入商品规格名称',
                        // default:'默认值测试', //新增时候默认值,可选
                    },
                    {
                        label: '规格值',
                        type: 'textarea',
                        name: 'default',
                        placeholder: '请输入商品规格值,多个规格值用逗号隔开',
                    },
                    {
                        label: '规格类型',
                        type: 'number',
                        name: 'type',
                        placeholder: '请输入规格类型,选填,默认0,0无限制,1颜色,2图片,3尺寸等等',
                        default:0,
                    },
                    {
                        label: '排序',
                        type: 'number',
                        name: 'order',
                        placeholder: '请输入排序',
                        default:50,
                    },
                    {
                        label: '可用状态',
                        type: 'btncheck', //按钮组选择
                        name: 'status',
                        default: JSON.stringify([
                            { value: 1, name: '可用', checked: true },
                            { value: 0, name: '不可用' },
                        ]),
                        placeholder: '分类状态 0不可用 1可用 等等状态',
                    },
                ],
            },
            //新增成功之后跳转到哪个页面
            successUrl: '/shop/admin/skus',
        });
    }
    //创建商品规格提交数据
    async save() {
        const { ctx, app } = this;
        //一般处理流程
        //1.参数验证
        this.ctx.validate({
            name: {
                type: 'string',  //参数类型
                required: true, //是否必须
                // defValue: '', 
                desc: '商品规格名称', //字段含义
                range:{
                    min:2,
                    max:30
                }
            },
            default: {
                type: 'string',
                required: true,
                defValue: '',
                desc: '商品规格值',
                range:{
                    min:0,
                    max:2000
                }
            },
            type: {
                type: 'int',
                required: false,
                defValue: 0,
                desc: '规格类型:0无限制,1颜色,2图片,3尺寸等等'
            },
            status: {
                type: 'int',
                required: false,
                defValue: 1,
                desc: '状态 0不可用 1可用 等等状态',
                range:{
                    in:[0,1]
                }
            },
            order: {
                type: 'int',
                required: false,
                defValue: 50,
                desc: '排序'
            }
        });
        //先判断一下直播功能中的礼物账号是否存在,不存在在写入数据库
        //2.写入数据库
        //3.成功之后给页面反馈
        let { name, default: defaultValue, status, type,order } = this.ctx.request.body;
        // if (await this.app.model.Skus.findOne({ where: { name } })) {
        //     return this.ctx.apiFail('名称已存在');
        // }
        //写入数据库
        const res = await this.app.model.Skus.create({
            name, default: defaultValue, status, type,order
        });
        this.ctx.apiSuccess('创建商品规格成功');
    }
    //商品规格列表页面
    async index() {
    
    }
    //商品规格列表页面api
    async indexAPI() {
    
    }
    //修改商品规格界面
    async edit() {
    
    }
    //修改商品规格数据功能
    async update() {
    
    }
    //修改商品规格状态功能
    async updateStatus() {
    
    }
    //删除商品规格功能
    async delete() {
    
    }
    //删除商品规格功能api
    async deleteAPI() {
    
    }
}

module.exports = SkusController;

# 三、商品规格列表数据、修改、修改状态、删除、批量删除

# 1. 字体图标查看 https://fontawesome.dashgame.com/ (opens new window)

# 2. 后台左侧菜单

data/root.json

[
    ...
   {"id":23,"pid":17, "name": "商品规格管理", "icon": "fa fa-cubes", "url": "/shop/admin/skus" }
]

# 3. 控制器

app/controller/admin/skus.js

    //商品规格列表页面
    async index() {
        const { ctx, app } = this;
        //分页:可以提炼成一个公共方法page(模型名称,where条件,其他参数options)
        let keyword = this.ctx.query.keyword || '';
        let data = await ctx.page('Skus',{
            name:{
                [this.app.Sequelize.Op.like]:'%'+keyword+'%',
            }
        });
        // let data = await ctx.service.goodsClass.datalist({ limit: 10000 });
        // console.log('分类数据', data);
        // ctx.body = data;
        // return;
        // data = data.rules;
        //渲染公共模版
        await ctx.renderTemplate({
            title: '商品规格列表',//现在网页title,面包屑导航title,页面标题
            data,
            tempType: 'table', //模板类型:table表格模板 ,form表单模板
            table: {
                //表格上方按钮,没有不要填buttons
                buttons: [
                    {
                        url: '/shop/admin/skus/create',//新增路径
                        desc: '创建商品规格',//新增 //按钮名称
                        // icon: 'fa fa-plus fa-lg',//按钮图标
                    },
                    // {
                    //     url: '/shop/admin/goods/create',//新增路径
                    //     desc: '上传商品',//新增 //按钮名称
                    //     // icon: 'fa fa-plus fa-lg',//按钮图标
                    // }
                ],
                //表头
                columns: [
                    {
                        title: '商品规格名称',
                        key: 'name',
                        class: 'text-left',//可选
                        // render(item) { //树形数据
                        //     // console.log('每个item',item);
                        //     if (item.level) {
                        //         let w = item.level * 40;
                        //         return `<span style="display:inline-block;width:${w}px"></span>`;
                        //     }
                        // }
                    },
                    // {
                    //     title: '分类下的商品',
                    //     // key: 'name',
                    //     class: 'text-left',//可选
                    //     render(item) { //树形数据
                    //         // console.log('每个item',item);
                    //         // if (item.level) {
                    //         //     let w = item.level * 40;
                    //         //     return `<span style="display:inline-block;width:${w}px"></span>`;
                    //         // }
                    //         return `<a href="/shop/admin/imageclass/${item.id}/imgList">${item.images.length}张</a>`;
                    //     }
                    // },
                    // {
                    //     title: '是否是导航栏栏目',
                    //     key: 'isnav',
                    //     width: 200,//可选
                    //     class: 'text-center',//可选
                    //     hidekeyData: true,//是否隐藏key对应的数据
                    //     render(item) {
                    //         console.log('可用状态里面每个item', item);
                    //         let arr = [
                    //             { value: 1, name: '是' },
                    //             { value: 0, name: '否' },
                    //         ];
                    //         let str = `<div class="btn-group btn-group-${item.id}">`;
                    //         for (let i = 0; i < arr.length; i++) {
                    //             str += `<button type="button" class="btn btn-light" data="${item.isnav}"
                    //             value="${arr[i].value}"
                    //             @click="changeBtnStatus('isnav','btn-group-${item.id}',${arr[i].value},${i},${item.id},'category','Category')">${arr[i].name}</button>`;
                    //         }
                    //         str += `</div>`;
                    //         return str;
                    //     }
                    // },
                    {
                        title: '规格值',
                        key: 'default',
                        class: 'text-center',//可选
                    },
                    {
                        title: '排序',
                        key: 'order',
                        class: 'text-center',//可选
                    },
                    {
                        title: '可用状态',
                        key: 'status',
                        width: 200,//可选
                        class: 'text-center',//可选
                        hidekeyData: true,//是否隐藏key对应的数据
                        render(item) {
                            // console.log('可用状态里面每个item', item);
                            let arr = [
                                { value: 1, name: '可用' },
                                { value: 0, name: '不可用' },
                            ];
                            let str = `<div class="btn-group btn-group-${item.id}">`;
                            for (let i = 0; i < arr.length; i++) {
                                str += `<button type="button" class="btn btn-light" data="${item.status}"
                                value="${arr[i].value}"
                                @click="changeBtnStatus('status','btn-group-${item.id}',${arr[i].value},${i},${item.id},'/shop/admin/skus','Skus')">${arr[i].name}</button>`;
                            }
                            str += `</div>`;
                            return str;
                        }
                    },
                    {
                        title: '操作',
                        class: 'text-right',//可选
                        action: {
                            //修改
                            edit: function (id) {
                                return `/shop/admin/skus/edit/${id}`;
                            },
                            //删除
                            delete: function (id) {
                                return `/shop/admin/skus/${id}/delete`;
                            }
                        }
                    },
                ],
            },
        });
    }
    // 商品规格列表api
    async indexAPI() {
        const { ctx, app } = this;
        //参数
        let page = parseInt(ctx.params.page) || 1;

        let limit = parseInt(ctx.query.limit) || 20;
        let order = ctx.query.order || 'desc';
        let keyword = ctx.query.keyword || '';
        let where = {};
        if(keyword){
            where.name = {
                [this.app.Sequelize.Op.like]:'%'+keyword+'%',
            };
        }

        //存在,则查列表
        let list = await app.model.Skus.findAll({
            where:{
                status:1,
                // name:{
                //     [this.app.Sequelize.Op.like]:'%'+keyword+'%',
                // }
                ...where,
            },
            offset:(page-1)*limit,
            limit,
            order:[
                ['order',order],
                ['id','desc']
            ],
            // attributes:['id','name','url'],
            attributes:{
                exclude:['create_time','update_time']
            },
            // include:[
            //     {
            //         model:app.model.ImageClass,
            //         // as:'imageClass',
            //         // attributes:{
            //         //     exclude:['create_time','update_time']
            //         // },
            //         attributes:['name'],
            //     }
            // ]
        });
        let totalCount = await app.model.Skus.count({
            where:{
                status:1,
                ...where,
            }
        });
        ctx.apiSuccess({
            list,
            totalCount
        });
    }
    //修改商品规格界面
    async edit() {
        const { ctx, app } = this;
        const id = ctx.params.id;
        let currentdata = await app.model.Skus.findOne({
            where: {
                id
            }
        });
        if (!currentdata) {
            return ctx.apiFail('该商品规格不存在');
        }
        currentdata = JSON.parse(JSON.stringify(currentdata));
        // console.log('当前商品规格数据', currentdata);
        // return;

        // 渲染模版前先拿到所有分类
        // let data = await ctx.service.goodsClass.dropdown_goodsclass_list();
        // console.log('下拉框显示的所有分类', JSON.stringify(data));
        // return;

        //渲染公共模版
        await ctx.renderTemplate({
            id,
            title: '修改商品规格:' + currentdata.name,//现在网页title,面包屑导航title,页面标题
            tempType: 'form', //模板类型:table表格模板 ,form表单模板
            form: {
                //修改提交地址
                action: '/shop/admin/skus/' + id,
                //  字段
                fields: [
                    // {
                    //     label: '放在哪个商品分类里面',
                    //     type: 'dropdown', //下拉框
                    //     name: 'pid',
                    //     default: JSON.stringify(data),
                    //     placeholder: '不调整(如需调整请选择)',
                    // },
                    {
                        label: '商品规格名称',
                        type: 'text',
                        name: 'name',
                        placeholder: '请输入商品规格名称',
                        // default:'默认值测试', //新增时候默认值,可选
                    },
                    {
                        label: '商品规格值',
                        type: 'textarea',
                        name: 'default',
                        placeholder: '请输入规格值,用逗号隔开',
                    },
                    {
                        label: '规格类型',
                        type: 'number',
                        name: 'type',
                        placeholder: '请输入规格类型:0无限制,1颜色,2图片,3尺寸等等,选填',
                        // default:50,
                    },
                    {
                        label: '排序',
                        type: 'number',
                        name: 'order',
                        placeholder: '请输入排序',
                        // default:50,
                    },
                    {
                        label: '可用状态',
                        type: 'btncheck', //按钮组选择
                        name: 'status',
                        default: JSON.stringify([
                            { value: 1, name: '可用', checked: currentdata.status === 1 },
                            { value: 0, name: '不可用', checked: currentdata.status === 0 },
                        ]),
                        placeholder: '状态 0不可用 1可用 等等状态',
                    },
                ],
                //修改内容默认值
                data:currentdata,
            },
            //修改成功之后跳转到哪个页面
            successUrl: '/shop/admin/skus',
        });

    }
    //修改商品规格数据功能
    async update() {
        const { ctx, app } = this;
        //1.参数验证
        this.ctx.validate({
            id: {
                type: 'int',
                required: true,
                desc: '商品规格id'
            },
            name: {
                type: 'string',  //参数类型
                required: true, //是否必须
                // defValue: '', 
                desc: '商品规格名称', //字段含义
                range:{
                    min:2,
                    max:30
                }
            },
            default: {
                type: 'string',
                required: true,
                // defValue: '',
                desc: '规格值,用逗号隔开',
                range:{
                    min:0,
                    max:2000
                }
            },
            status: {
                type: 'int',
                required: false,
                defValue: 1,
                desc: '状态 0不可用 1可用 等等状态',
                range:{
                    in:[0,1]
                }
            },
            type: {
                type: 'int',
                required: false,
                defValue: 0,
                desc: '规格类型:0无限制,1颜色,2图片,3尺寸等等'
            },
            order: {
                type: 'int',
                required: false,
                defValue: 50,
                desc: '排序'
            }
        });

        // 参数
        const id = ctx.params.id;
        const {  name, default:defaultValue, status, type,order } = ctx.request.body;
        // 先看一下是否存在
        let data = await app.model.Skus.findOne({ where: { id } });
        if (!data) {
            return ctx.apiFail('该商品规格记录不存在');
        }
        //存在
        // const Op = this.app.Sequelize.Op;//拿Op,固定写法
        //只要不放在同一分类级别下还是可以的
        // const hasdata = await app.model.GoodsClass.findOne({
        //     where: {
        //         name,
        //         id: {
        //             [Op.ne]: id
        //         }
        //     }
        // });
        // if (hasdata && hasdata.pid == pid) {
        //     return ctx.apiFail('同一个分类下不能有相同的商品分类名称');
        // }
        // 修改数据
        data.name = name;
        data['default'] = defaultValue;
        data.status = status;
        data.type = type;
        data.order = order;
        await data.save();
        // 给一个反馈
        ctx.apiSuccess('修改商品规格成功');
    }
    //修改商品规格状态功能
    async updateStatus(){
        const { ctx, app } = this;
        //1.参数验证
        this.ctx.validate({
            id: {
                type: 'int',
                required: true,
                desc: '商品规格id'
            },
            status: {
                type: 'int',  //参数类型
                required: true, //是否必须
                // defValue: '', 
                desc: '商品规格状态', //字段含义
                range:{
                    in:[0,1]
                },
            },
        });
        // 参数
        const id = ctx.params.id;
        const { status } = ctx.request.body;
        // 是否存在
        let data = await app.model.Skus.findOne({ where: { id } });
        if (!data) {
            return ctx.apiFail('商品规格不存在');
        }
        // 修改数据
        data.status = status;
        
        await data.save();
        // 给一个反馈
        ctx.apiSuccess('修改商品规格状态成功');
    }
    //删除商品规格功能
    async delete() {
        const { ctx, app } = this;
        const id = ctx.params.id;

        // 是否存在
        let data = await app.model.Skus.findOne({ where: { id } });
        if (!data) {
            return ctx.apiFail('商品规格不存在');
        }
        await app.model.Skus.destroy({
            where: {
                id:id
            }
        });
        //提示
        ctx.toast('商品规格删除成功', 'success');
        //跳转
        ctx.redirect('/shop/admin/skus');
    }
    //删除商品规格功能api
    async deleteAPI() {
        const { ctx, app } = this;
        const id = ctx.params.id;

        // 是否存在
        let data = await app.model.Skus.findOne({ where: { id } });
        if (!data) {
            return ctx.apiFail('商品规格不存在');
        }
        await app.model.Skus.destroy({
            where: {
                id:id
            }
        });

        ctx.apiSuccess(true);
    }

    //批量删除商品规格
    async deleteAll(){
        const { ctx, app } = this;
        //1.参数验证
        this.ctx.validate({
            ids: {
                type: 'array',
                required: true,
                desc: '商品规格id集合'
            },
        });
        const { ids } = ctx.request.body;
        await app.model.Skus.destroy({
            where: {
                id:{
                    [this.app.Sequelize.Op.in]: ids
                }
            }
        });
        ctx.apiSuccess(true);
    }

# 四. 商品规格所有接口

具体查看,skus[商品规格表] 所有接口

更新时间: 2025年4月24日星期四晚上8点34分