第10天-商品服务(分层领域模型及规格参数编码实现)

news2025/1/16 1:01:35

1.分层领域模型规约

  • DO( Data Object): 此对象与数据库表结构一一对应,通过 DAO 层向上传输数据源对象。
  • DTO( Data Transfer Object):数据传输对象, Service 或 Manager 向外传输的对象。
  • BO( Business Object):业务对象, 可以由 Service 层输出的封装业务逻辑的对象。
  • Query:数据查询对象,各层接收上层的查询请求。 注意超过 2 个参数的查询封装,禁止使用 Map
    类来传输。
  • VO( View Object):显示层对象,通常是 Web 向模板渲染引擎层传输的对象。


2.规格参数-新增

前端Vue

2.1.抽取VO对象

  • AttrEntity 的属性抽取到 AttrVO 对象中,并新增四个属性
    private Long attrGroupId;
    private String catelogName;
    private String groupName;
    private Long[] catelogPath;
  • Controller层的Handler处理方法入参统一使用 VO 对象
package com.atguigu.gmall.product.vo;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;

import java.io.Serializable;

/**
 * 规格参数(基本属性) VO 对象
 *
 * @author zhangwen
 * @email 1466787185@qq.com
 * @date 2023-02-22 12:20:05
 */
@Data
public class AttrVO {
	/**
	 * 属性id
	 */
	private Long attrId;
	/**
	 * 属性名
	 */
	private String attrName;
	/**
	 * 是否需要检索[0-不需要,1-需要]
	 */
	private Integer searchType;
	/**
	 * 值类型[0-为单个值,1-可以选择多个值]
	 */
	private Integer valueType;
	/**
	 * 属性图标
	 */
	private String icon;
	/**
	 * 可选值列表[用逗号分隔]
	 */
	private String valueSelect;
	/**
	 * 属性类型[0-销售属性,1-基本属性,2-既是销售属性又是基本属性]
	 */
	private Integer attrType;
	/**
	 * 启用状态[0 - 禁用,1 - 启用]
	 */
	private Long enable;
	/**
	 * 所属分类
	 */
	private Long catelogId;
	/**
	 * 快速展示【是否展示在介绍上;0-否 1-是】,在sku中仍然可以调整
	 */
	private Integer showDesc;
	/**
	 * 属性分组Id
	 */
	private Long attrGroupId;
	/**
	 * 所属分类名
	 */
	private String catelogName;
	/**
	 * 所属分组名
	 */
	private String groupName;
	/**
	 * 三级分类完整路径
	 */
	private Long[] catelogPath;
}


2.2.商品常量类

gmall-common 公共服务中创建商品常量类 ProductConstant

package com.atguigu.common.constant;

/**
 * @Description:商品服务常量类
 * @Auther: zhangwen
 * @Date: 2023-02-22 10:51
 * @version: 1.0
 */
public class ProductConstant {
    /**
     * 属性枚举
     */
    public enum attrEnum{
        /**
         * 基本属性
         */
        ATTR_TYPE_BASE(1,"基本属性"),
        /**
         * 销售属性
         */
        ATTR_TYPE_SALE(0,"销售属性");

        private int code;
        private String msg;

        attrEnum(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }
}    
    


2.3.API

POST /product/attr/save



2.4.后台接口实现

AttrController

 	/**
     * 保存规格参数
     */
    @RequestMapping("/save")
    public R save(@RequestBody AttrVO attrVO){
		attrService.saveAttr(attrVO);

        return R.ok();
    }

AttrServiceImpl

	/**
     * 保存规则参数
     * @param attrVO
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveAttr(AttrVO attrVO) {
        //保存基本属性
        AttrEntity attrEntity = new AttrEntity();
        //属性拷贝
        BeanUtils.copyProperties(attrVO, attrEntity);
        this.save(attrEntity);

        //保存关联关系 - 基本属性(只有规格参数需要和属性分组建立关系,销售属性不建立关系)
        if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrId(attrEntity.getAttrId());
            relationEntity.setAttrGroupId(attrVO.getAttrGroupId());
            relationDao.insert(relationEntity);
        }
    }


3.规格参数-列表查询



3.1.API

GET /product/attr/base/list/{catelogId}

//请求参数
{
	page: 1, //当前页码
	limit: 10, //每页记录数
	sidx: 'id', //排序字段
	order: 'asc', //排序方式
	key: '华为' //检索关键字
}

//响应数据
{
	"msg": "success",
	"code": 0,
	"page": {
	"totalCount": 0,
	"pageSize": 10,
	"totalPage": 0,
	"currPage": 1,
	"list": [{
		"attrId": 0, //属性id
		"attrName": "string", //属性名
		"attrType": 0, //属性类型,0-销售属性,1-基本属性
		"catelogName": "手机/数码/手机", //所属分类名字
		"groupName": "主体", //所属分组名字
		"enable": 0, //是否启用
		"icon": "string", //图标
		"searchType": 0, //是否需要检索[0-不需要,1-需要]
		"showDesc": 0, //是否展示在介绍上;0-否 1-是
		"valueSelect": "string", //可选值列表[用逗号分隔]
		"valueType": 0 //值类型[0-为单个值,1-可以选择多个值]
	}]
	}
}


3.2.后台接口实现

AttrController

	/**
     * 查询规格参数和销售属性列表
     * @param params 分页信息和查询关键字key
     * @param catelogId 三级分类ID
     * @param attrType 属性类型
     * @return
     */
     @GetMapping("/{attrType}/list/{catelogId}")
     public R listAttr(@RequestParam Map<String, Object> params,
					   @PathVariable("catelogId") Long catelogId, 
					   @PathVariable("attrType") String attrType) {
         PageUtils page = attrService.queryBaseAttrPage(params, catelogId, attrType);
         return R.ok().put("page", page);
     }

AttrServiceImpl

	/**
     * 查询规格参数和销售属性列表
     * @param params 分页信息和查询关键字key
     * @param catelogId 三级分类ID
     * @param attrType 属性类型
     * @return
     */
    @Override
    public PageUtils queryBaseAttrPage(Map<String, Object> params, Long catelogId, String attrType) {
        QueryWrapper<AttrEntity> queryWrapper = new QueryWrapper<AttrEntity>()
                .eq("attr_type","base".equalsIgnoreCase(attrType)
                        ? ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()
                        : ProductConstant.attrEnum.ATTR_TYPE_SALE.getCode());

        if(catelogId != 0){
            queryWrapper.eq("catelog_id",catelogId);
        }

        String key = (String)params.get("key");
        if(!StringUtils.isEmpty(key)){
            queryWrapper.and(wrapper ->{
                wrapper.eq("attr_id",key).or().like("attr_name",key);
            });
        }

        IPage<AttrEntity> page = this.page(new Query<AttrEntity>().getPage(params), queryWrapper);

        PageUtils pageUtils = new PageUtils(page);
        //从分页对象中获取查询记录集
        List<AttrEntity> records = page.getRecords();
        List<AttrVO> attrVoList = records.stream().map(attrEntity -> {
            AttrVO attrVO = new AttrVO();
            BeanUtils.copyProperties(attrEntity, attrVO);

            //查询并设置分组名 groupName,基本属性需要显示分组,销售属性没有属性分组
            if ("base".equalsIgnoreCase(attrType)) {
                AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(
                        new QueryWrapper<AttrAttrgroupRelationEntity>()
                                .eq("attr_id", attrEntity.getAttrId()));
                if(relationEntity != null && relationEntity.getAttrGroupId() != null ){
                    AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                    attrVO.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }

            //查询并设置分类名 catelogName
            CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
            if(categoryEntity != null){
                attrVO.setCatelogName(categoryEntity.getName());
            }
            return attrVO;
        }).collect(Collectors.toList());

        pageUtils.setList(attrVoList);

        return  pageUtils;
    }

运行结果如下:

在这里插入图片描述



4.规格参数-修改



4.1.所属分类及分组数据回显

在这里插入图片描述

4.1.1API

GET /product/attr/info/{attrId}
//响应数据
{
"msg": "success",
"code": 0,
"attr": {
	"attrId": 1,
	"attrName": "入网型号",
	"searchType": 1,
	"valueType": 1,
	"icon": "icon-1",
	"valueSelect": "v;q;w",
	"attrType": 1,
	"enable": 1,
	"showDesc": 1,
	"attrGroupId": 1, //分组id
	"catelogId": 225, //分类id
	"catelogPath": [2, 34, 225] //分类完整路径
	}
}

4.1.2后台接口实现

AttrController

	/**
     * 获取规格参数
     */
    @RequestMapping("/info/{attrId}")
    public R info(@PathVariable("attrId") Long attrId){
        AttrVO attrVO = attrService.getAttrInfo(attrId);

        return R.ok().put("attr", attrVO);
    }

AttrServiceImpl

	/**
     * 获取规格参数
     * @param attrId 属性id
     * @return 规格参数VO对象
     */
    @Override
    public AttrVO getAttrInfo(Long attrId) {
        AttrVO attrVO = new AttrVO();
        AttrEntity attrEntity = this.getById(attrId);
        BeanUtils.copyProperties(attrEntity,attrVO);

        //查询并设置分组名 groupName,基本属性需要显示分组,销售属性没有属性分组
        if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {
            AttrAttrgroupRelationEntity relationEntity = relationDao.selectOne(
                    new QueryWrapper<AttrAttrgroupRelationEntity>()
                            .eq("attr_id", attrEntity.getAttrId()));
            if (relationEntity != null && relationEntity.getAttrGroupId() != null) {
                AttrGroupEntity attrGroupEntity = attrGroupDao.selectById(relationEntity.getAttrGroupId());
                attrVO.setAttrGroupId(attrGroupEntity.getAttrGroupId());
                if (attrGroupEntity != null) {
                    attrVO.setGroupName(attrGroupEntity.getAttrGroupName());
                }
            }
        }

        //查询并设置所属分类信息
        //一个微服务内部,service之间调用没有问题,考虑到开发便捷性和代码重用
        //对于是否违背设计原则,高内聚低耦合,本身微服务划分从根本上就已经做到了高内聚低耦合
        CategoryEntity categoryEntity = categoryDao.selectById(attrEntity.getCatelogId());
        if(categoryEntity != null){
            attrVO.setCatelogName(categoryEntity.getName());
        }
        Long[] categoryPath = categoryService.findCategoryPath(attrEntity.getCatelogId());
        attrVO.setCatelogPath(categoryPath);
        
        return attrVO;
    }

运行结果:

在这里插入图片描述



4.2.修改规格参数


4.2.1.API

POST /product/attr/update


4.2.2.后台接口实现

AttrController

	/**
     * 修改规格参数
     */
    @RequestMapping("/update")
    public R update(@RequestBody AttrVO attrVO){
		attrService.updateAttr(attrVO);

        return R.ok();
    }

AttrServiceImpl

	/**
     * 修改规格参数
     * @param attrVO  规格参数VO对象
     */
    @Override
    public void updateAttr(AttrVO attrVO) {
        //修改基本信息
        AttrEntity attrEntity = new AttrEntity();
        BeanUtils.copyProperties(attrVO,attrEntity);
        this.updateById(attrEntity);

        //修改分组关联 - 基本属性
        if (attrVO.getAttrType() == ProductConstant.attrEnum.ATTR_TYPE_BASE.getCode()) {
            AttrAttrgroupRelationEntity relationEntity = new AttrAttrgroupRelationEntity();
            relationEntity.setAttrGroupId(attrVO.getAttrGroupId());
            relationEntity.setAttrId(attrVO.getAttrId());

            Integer count = relationDao.selectCount(
                    new QueryWrapper<AttrAttrgroupRelationEntity>()
                            .eq("attr_id", attrVO.getAttrId()));
            if (count > 0) {
                //修改关联关系
                relationDao.update(relationEntity,new UpdateWrapper<AttrAttrgroupRelationEntity>()
                        .eq("attr_id", attrVO.getAttrId()));
            }else{
                //新增关联关系
                relationDao.insert(relationEntity);
            }
        }
    }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/365381.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【likeshop多商户】电子面单商家直播上线啦~

likeshop多商户商城v2.2.0版本更新啦&#xff01; 新增功能&#xff1a; 商家直播 单子面单 优化&#xff1a; 个人中心优惠券数量统计优化 修复&#xff1a; 秒杀商品待审核时&#xff0c;下单价格计算错误 个人中心修改头像后地址保存错误 「商家直播」 提升品牌知名度…

矩阵中的路径 AcWing (JAVA)

请设计一个函数&#xff0c;用来判断在一个矩阵中是否存在一条路径包含的字符按访问顺序连在一起恰好为给定字符串。 路径可以从矩阵中的任意一个格子开始&#xff0c;每一步可以在矩阵中向左&#xff0c;向右&#xff0c;向上&#xff0c;向下移动一个格子。 如果一条路径经过…

【c语言】预处理

&#x1f680;write in front&#x1f680; &#x1f4dc;所属专栏&#xff1a;> c语言学习 &#x1f6f0;️博客主页&#xff1a;睿睿的博客主页 &#x1f6f0;️代码仓库&#xff1a;&#x1f389;VS2022_C语言仓库 &#x1f3a1;您的点赞、关注、收藏、评论&#xff0c;是…

设计模式--工厂模式

这种类型的设计模式属于创建型模式&#xff0c;它提供了一种创建对象的最佳方式。在工厂模式中&#xff0c;我们在创建对象时不会对客户端暴露创建逻辑&#xff0c;并且是通过使用一个共同的接口来指向新创建的对象。   工厂模式主要使用了C的多态特性。将存在继承关系的类&a…

通过一张照片来定位拍摄地点和网站的域名 LA CTF 2023

简介 这次打ctf遇到了一个比较经典的osint类题目&#xff0c;在这里分享一下如何做此类题目 题目链接&#xff1a; https://platform.lac.tf/challs题目简介&#xff1a; 你能猜出这个猫天堂的名字吗&#xff1f;答案是此位置的网站域。例如&#xff0c;如果答案是 ucla&…

浅谈分布式锁的原理

1.业务场景引入 在进行代码实现之前&#xff0c;我们先来看一个业务场景&#xff1a; 系统A是一个电商系统&#xff0c;目前是一台机器部署&#xff0c;系统中有一个用户下订单的接口&#xff0c;但是用户下订单之前一定要去检查一下库存&#xff0c;确保库存足够了才会给用户…

SPINAND UBI 离线烧录 开发指南

SPINAND UBI 离线烧录 开发指南 1 概述 编写目的: 介绍Sunxi SPINand 烧写时的数据布局 2 名词解释 词义UBIunsorted block imagePEBphysical erase blockLEBlogical erase block PEB 和logical block 关系 1 PEB 1 logical block 1 logical block 2 physical blocks3 总…

React从入门到精通二

React从入门到精通之购物车案例1. 购物车需求说明使用到的data list2. 项目code1. 购物车需求说明 list data展示到列表中每个item的通过按钮来控制购买的数据量删除按钮可以删除当前的itemTotal Price计算当前购物车的总的价格 使用到的data list const books [{id: 1,name…

OAK相机深度流探测草莓距离

编辑&#xff1a;OAK中国 首发&#xff1a;oakchina.cn 喜欢的话&#xff0c;请多多&#x1f44d;⭐️✍ 内容可能会不定期更新&#xff0c;官网内容都是最新的&#xff0c;请查看首发地址链接。 ▌前言 Hello&#xff0c;大家好&#xff0c;这里是OAK中国&#xff0c;我是助手…

uniapp 悬浮窗(悬浮球、动态菜单、在其他应用上层显示) Ba-FloatBall

简介&#xff08;下载地址&#xff09; Ba-FloatBall 是一款在其他应用上层显示的悬浮球插件。支持展示菜单、拖动、自动贴边等&#xff1b;支持自定义样式。 支持添加展示菜单&#xff0c;可自定义&#xff08;不添加菜单&#xff0c;可只显示悬浮球&#xff09;支持自定义悬…

一口吃不成ChatGPT,复旦版MOSS服务器被挤崩后续

ChatGPT 是目前最先进的 AI&#xff0c;由于 ChatGPT 的训练过程所需算力资源大、标注成本高&#xff0c;此前国内暂未出现对大众开放的同类产品。 适逢ChatGPT概念正火&#xff0c;2 月 21 日&#xff0c;复旦团队发布首个中国版类 ChatGPT 模型「MOSS」&#xff0c;没想到瞬时…

Python-生成列表

1.生成列表使用列表前必须先生成列表。1.1使用运算符[ ]生成列表在运算符[ ]中以逗号隔开各个元素会生成包含这些元素的新列表。另外&#xff0c;如果[ ]中没有元素就会生成空列表示例>>> list01 [] >>> list01 [] >>> list02 [1, 2, 3] >>…

云、安全、网络三位一体,Akamai 推出大规模分布式边缘和云平台 Akamai Connected Cloud

出品 | CSDN 云计算 云服务市场规模在持续增长。 基于网络技术积累与优势&#xff0c;与布局边缘计算之后&#xff0c;巨头 Akamai 在继续推进它的技术与产品进程。近日&#xff0c;Akamai 正式推出大规模分布式边缘和云平台 Akamai Connected Cloud&#xff0c;包含云计算、安…

软考学习笔记(题目知识记录)

答案为 概要设计阶段 本题涉及软件工程的概念 软件工程的任务是基于需求分析的结果建立各种设计模型&#xff0c;给出问题的解决方案 软件设计可以分为两个阶段&#xff1a; 概要设计阶段和详细设计阶段 结构化设计方法中&#xff0c;概要设计阶段进行软件体系结构的设计&…

学生管理系统-课后程序(JAVA基础案例教程-黑马程序员编著-第六章-课后作业)

【案例6-2】 学生管理系统 【案例介绍】 1.任务描述 在一所学校中&#xff0c;对学生人员流动的管理是很麻烦的&#xff0c;本案例要求编写一个学生管理系统&#xff0c;实现对学生信息的添加、删除、修改和查询功能。每个功能的具体要求如下&#xff1a; 系统的首页&#…

视频技术基础知识

一、视频图像基础 像素&#xff1a;图像的基本单元&#xff0c;即一个带有颜色的小块分辨率&#xff1a;图像的大小或尺寸&#xff0c;用像素个数来表示。原始图像分辨率越高&#xff0c;图像就越清晰位深&#xff1a;存储每位像素需要的二进制位数&#xff1b;位深越大&#…

JAVA线程入门简介

线程入门简介什么是程序?什么是进程?什么是线程&#xff1f;单线程与多线程并发与并行线程的使用用java查看有多少个cpu创建线程的两种方式继承Thread类&#xff0c;重写run方法实现Runnable接口&#xff0c;重写run方法多线程机制为社么是start?源码解析什么是程序? 是为完…

防错料使用二维码解决方案 生产过程物料防错管理

生产过程中&#xff0c;物料的防错管理是非常重要的一环。它能够有效地防止物料错用或混用&#xff0c;从而降低产品质量问题的发生率&#xff0c;减少生产成本和生产周期&#xff0c;提高生产效率和产品质量。以下是生产过程物料防错管理的具体措施&#xff1a;1.明确物料标识…

SpringBoot Data Redis来操作Redis

SpringBoot Data Redis来操作Redis1、Redis启动Redis主要的作用安装的位置启动2、Java中来操作Redis3、Spring Data Redis(重点)测试连接配置Redis序列化器redisTemplate操作常见数据类型通用操作&#xff0c;针对不同的数据类型都可以操作申明&#xff1a; 未经许可&#xff0…

浅谈Springboot自动化配置原理

文章目录1.前言2.SpringBoot的入口3.SpringBootApplication背后的秘密4.Configuration5.ComponentScan扫描bean6.EnableAutoConfiguration7.自动配置生效1.前言 不论在工作中&#xff0c;亦或是求职面试&#xff0c;Spring Boot已经成为我们必知必会的技能项。除了某些老旧的政…