Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >猿实战11——类目属性绑定之el-tree的使用

猿实战11——类目属性绑定之el-tree的使用

作者头像
山旮旯的胖子
发布于 2020-09-14 02:17:56
发布于 2020-09-14 02:17:56
97000
代码可运行
举报
文章被收录于专栏:猿人工厂猿人工厂
运行总次数:0
代码可运行

猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题。想要一起实战吗?关注公号即可获取基础代码!

上一个章节,猿人君教会了你实现了后台类目的三级联动,今天我们继续来讲述,新增属性的实现。

功能概览

我们先看看新增属性的功能。

在页面选择类目后(目前暂时要求只新增1.2级类目属性),点击新增属性按钮,可以搜索属性库(要求同时检索属性以及属性组,同时支持模糊左匹配查询),通过勾选的方式新增属性为当前类目的属性。

属性展示之el-tree

我们可以很直观的看出,属性,是以分组的形式进行展示,当然,有的属性并没有从属于,某一个属性组,我们可以考虑一个叫“未分组”的属性组,用于归纳未分组的属性。

这样,属性组和属性之间,就形成了一种父子关系,对于这样的树形展示,element UI 提供了el-tree这样的组件,用于展现数据。

大家可以看一下官网上的内容。https://element.eleme.cn/#/zh-CN/component/tree

el-tree的属性和事件,相对来说比较丰富,就我们系统需要用到的而言,仅仅是展示,然后会关注数据的选择。

Data:用于展示的数据

Node-key:节点id的名称

default-expanded-keys:默认展开的节点的 key 的数组

props:定义数据节点的参数,详见上表

render-content:自定义,展示回调函数。

@check-change:节点选中状态发生变化时的回调。

属性检索后端实现

考虑到,属性和属性值的数据需要一起按照分组进行展示,我们需要定义一个专门用于显示的类来支撑,数据展示。像这样的类往往叫做VO。

由于是属性组内部再包装了,具体的属性,那么我们可以相对较快的定义这样的结构。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
package com.pz.basic.mall.domain.product.property.vo;
 
import com.pz.basic.mall.domain.base.BaseDO;
import com.pz.basic.mall.domain.product.property.MallProperty;
 
import java.util.List;
 
public class MallGroupVo extends BaseDO {
 
    private Long id;
 
    private String label;
 
    private List<MallProperty> children;
 
   //省略getter setter
}
 
 
/**
 * Copyright(c) 2004-2020 pangzi
 * com.pz.basic.mall.domain.product.property.MallProperty.java
 */
package com.pz.basic.mall.domain.product.property;
 
import com.pz.basic.mall.domain.base.BaseDO;
 
import java.util.Date;
 
 
/**
 *
 * @author pangzi
 * @date 2020-06-28 11:40:14
 *
 */
public class MallProperty extends BaseDO {
 
    /**属性库属性ID**/
private Long propertyId;


    /**属性库属性名称**/
private String propertyName;


    /**属性分组ID,来自property_group表**/
private Long groupId;


    /**键值对,扩展字段**/
private String features;


    /**排序**/
private Integer sortOrder;


    /**状态
0=停用
1=启用
**/
private Integer status;


    /**创建人**/
private String createUser;


    /**修改人**/
private String modifyUser;


    /**创建时间**/
private Date created;


    /**最后修改时间**/
private Date modified;

}

接下来要做的事情,自然是要返回数据了。在MallCategoryPropertyController中定义方法,返回属性组俩表数据

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
     * 返回类目属性列表
     * @param queryMallProperty
     * @return
     */
    @RequestMapping("/findForSelect")
    public  Result<List<MallGroupVo>> findForSelect(@RequestBody QueryMallProperty queryMallProperty){
        return mallCategoryPropertyService.getMallPropertyGroup(queryMallProperty);
    }

我们可以思考下服务层的实现,由于我们的属性表中,只有属性组ID,而没有属性组名称,而我们的检索条件是需要同时支持属性组名称和属性名称进行查询的,这该如何是好?

一般来讲,很常见而且有些偏传统管理软件的实现方式是直接将属性表与属性组表进行关联查询。但是互联网行业在做查询时,考虑到sql的后续优化,是需要控制表之间的关联连接查询的。通常情况下,需要做将这种join关系做些转化。比如将join转化为in的方式,就是最常见的一种方式。

比如我们可以先查询出符合条件的属性组的id,然后再将这些以in的方式在属性表中做查询就好了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public Result<List<MallGroupVo>> getMallPropertyGroup(QueryMallProperty queryMallProperty) {
 
Result<List<MallGroupVo>> result = new Result<List<MallGroupVo>>();
 
QueryMallPropertyGroup groupQuery = new QueryMallPropertyGroup();
groupQuery.setGroupNameLike(queryMallProperty.getPropertyNameLike());

//根据分组名查询分组对象,用于后续展示分组名,以及对属性表支持对应的分组id 用于属性表的 or 关系查询

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
List<MallPropertyGroup>  groupList  =getGroupList(groupQuery);
 
if(!CollectionUtils.isEmpty(groupList)){
List<Long> idList = groupList.stream().map(e -> e.getGroupId()).collect(Collectors.toList());
queryMallProperty.setGroupIdList(idList);
}
 
List<MallProperty> propertyList=mallPropertyDao.selectMallPropertyByQuery(queryMallProperty);
 
List<Long> shieldIdList=getShieldPropertyIdList(queryMallProperty);
 
//删除需要屏蔽的对象
if(!CollectionUtils.isEmpty(shieldIdList)){
propertyList.removeIf(a -> {
return shieldIdList.stream().anyMatch(b -> {
if (b!= null && b.equals(a.getPropertyId())) {
return true;
} else {
return false;
}
});
});
}
List<MallGroupVo> dataList=getMallGroupVoList(propertyList,groupList);
result.addDefaultModel(dataList);
return result;
}
 
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private List<MallGroupVo> getMallGroupVoList(List<MallProperty> propertyList,List<MallPropertyGroup> groupList ){
Map<Long,MallGroupVo> groupMap = new HashMap<Long,MallGroupVo>();
 
List<MallGroupVo> dataList= new ArrayList<MallGroupVo>();
MallGroupVo group =null;
 
MallPropertyGroup mallGroup=null;
 
if(!CollectionUtils.isEmpty(propertyList)){
 
for(MallProperty property:propertyList){
 
mallGroup=getMallPropertyGroup(groupList,property.getGroupId());
 
if(null==mallGroup){
group=groupMap.get(UnsignedGroupId);
 
}else{
group=groupMap.get(property.getGroupId());
}
if(null==group){
List<MallGroupVo> list = new ArrayList<MallGroupVo>();
List<MallProperty> dbList = new  ArrayList<MallProperty>();
dbList.add(property);
group = new MallGroupVo();
list.add(group);
if(null==mallGroup){
group.setId(UnsignedGroupId);
group.setLabel(UnsignedGroupName);
}else{
group.setId(mallGroup.getGroupId());
group.setLabel(mallGroup.getGroupName());
}
group.setChildren(dbList);
groupMap.put(group.getId(),group);
}else{
group.getChildren().add(property);
}
}
 
}
if(!CollectionUtils.isEmpty(groupMap) ){
dataList.addAll(groupMap.values());
}
return dataList;
}
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * 获取需要屏蔽的对象
 * @param queryMallProperty
 * @return
 */
private List<Long> getShieldPropertyIdList(QueryMallProperty queryMallProperty){
 
List<Long> catIdList = new ArrayList<Long>();
 
if(null!=queryMallProperty.getCatOneId()){
catIdList.add(queryMallProperty.getCatOneId());
}
 
if(null!=queryMallProperty.getCatTwoId()){
catIdList.add(queryMallProperty.getCatTwoId());
}
 
if(null!=queryMallProperty.getCatThreeId()){
catIdList.add(queryMallProperty.getCatThreeId());
}
 
if(!CollectionUtils.isEmpty(catIdList)){
QueryMallCategoryProperty query = new QueryMallCategoryProperty();
    query.setCategoryIdList(catIdList);
List<MallCategoryProperty> dataList=mallCategoryPropertyDao.selectMallCategoryPropertyByQuery(query);
List<Long> shieldIdList = dataList.stream().map(e -> e.getPropertyId()).collect(Collectors.toList());
return shieldIdList;
}
 
return null;
 
}

如何使用List的方面的in语句?这里可以给你看一下

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 猿人工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
猿实战12——类目属性之动态绑定
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是问题。更多精彩内容,敬请大家关注公主号猿人工厂,点击猿人养成获取!
山旮旯的胖子
2020/09/14
7110
猿实战15——关联你所不明白的前后台类目
上一个章节,猿人君教会了你如何去设置广告牌,今天我们一起来学习,如何绑定前后台类目。
山旮旯的胖子
2020/09/23
6780
猿实战15——关联你所不明白的前后台类目
猿实战08——属性库实现之属性关系绑定
属性和属性值,看上去很不起眼,数据粒度也很小,但是正式因为数据粒度小,灵活多变,组织得当可以强有力的区分千变万化的商品。
山旮旯的胖子
2020/09/05
9070
猿实战08——属性库实现之属性关系绑定
猿实战14——前台类目之广告牌设置
上一个章节,猿人君教会了你如何去实现前台类目,虽然已经讲得很详细了,还是有朋友认为比较困难。可能是每个人的基础真的不一样吧。
山旮旯的胖子
2020/09/23
5290
猿实战14——前台类目之广告牌设置
猿实战21——商品发布之商品数据存储
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题。还等什么呢?关注公号,取基础代码,一起实战吧。
山旮旯的胖子
2020/10/22
6250
猿实战21——商品发布之商品数据存储
猿实战03——猿首战之手把手教你撸品牌
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下来,变身猿人找到工作不是问题。想要一起实战吗?,关注公主号猿人工厂,获取基础代码,手把手带你开发一个完整的电商系统。
山旮旯的胖子
2020/08/24
6870
猿实战03——猿首战之手把手教你撸品牌
猿实战09——实现你设计的类目系统
上两个章节,猿人君教会了你如何通过设计落地实现了属性库,今天我们继续来实现系统的另一个基石地位的模块——后台类目。
山旮旯的胖子
2020/09/07
7960
猿实战09——实现你设计的类目系统
猿实战05——手把手教你拥有自己的代码生成器
哈哈,猿设计终于讲完了,接下来的一段时间,工厂君打算和大家一起来实现我们之间的设计——构建一个自己的电商系统来玩耍。嗯,这个可是一个大工程,代码量很大,业务也比较复杂,要搞就好好搞,代码方面还是需要一些规范的。
山旮旯的胖子
2020/08/31
7400
猿实战05——手把手教你拥有自己的代码生成器
猿实战13——实现你没听说过的前台类目
上几个章节,猿人君教会了你实现了属性/属性值和后台类目的绑定关系,今天,猿人君就带你来实现前台类目。
山旮旯的胖子
2020/09/23
6880
猿实战13——实现你没听说过的前台类目
猿实战07——属性库之实现电商系统基石模块
上一章节,猿人君教会了你一个不一样的地址管理,体验了代码生成器。一点一点引导你去设计和实现地址管理的功能模块。
山旮旯的胖子
2020/09/05
7040
猿实战07——属性库之实现电商系统基石模块
猿实战06——不一样的地址管理
上一章节,猿人君教会了你一个新鲜的东西——猿实战05——手把手教你拥有自己的代码生成器。大家掌握原理,知道怎么去抽象你的代码就好了,莫要过于纠结。今天我们来学习新的东西——地址管理。
山旮旯的胖子
2020/09/06
6560
猿实战17——实现你未必知晓的运费模板
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题。还等什么呢?关注公号,取基础代码,一起实战吧。
山旮旯的胖子
2020/09/28
7560
猿实战17——实现你未必知晓的运费模板
猿实战16——承运商之搭建你的运费基石
上几个章节,猿人君教会了你如何去实现前台类目的后台管理功能,今天我们一起来学习,如何实现承运商管理。
山旮旯的胖子
2020/09/23
6410
猿实战16——承运商之搭建你的运费基石
猿实战19——商品发布之商详数据准备
猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题。还等什么呢?关注公号,取基础代码,一起实战吧。
山旮旯的胖子
2020/09/29
4580
猿实战19——商品发布之商详数据准备
【第五篇】商城系统-商品属性管理
SPU是商品信息聚合的最小单位,是一组可复用、易检索的标准化信息的集合,该集合描述了一个产品的特性。通俗点讲,属性值、特性相同的商品就可以称为一个SPU。
用户4919348
2022/09/16
8950
【第五篇】商城系统-商品属性管理
猿实战04——el-upload结合nginx之通用图片处理
在上一章节品牌管理的设计和实现中。你一定会遇到一个小麻烦——文件上传。文件上传,其实是一个老生常谈的话题,在之前的文章中,猿人君也多次提及。在上一章节中,细心的你或许会发现一个标签,el-upload。没错,它就是Element组件库提供的一个upload组件,今天我们就来结合它讲一讲如何封装一个通用的文件上传工具,供我们的电商系统使用。
山旮旯的胖子
2020/08/28
1.3K0
Java 数据分批调用接口的正确姿势
现实业务开发中,通常为了避免超时、对方接口限制等原因需要对支持批量的接口的数据分批调用。
明明如月学长
2021/08/31
2.1K0
乐优项目:商品规格参数管理,SPU和SKU数据结构,商品查询(四)
乐优商城是一个全品类的电商网站,因此商品的种类繁多,每一件商品,其属性又有差别。为了更准确描述商品及细分差别,抽象出两个概念:SPU和SKU,了解一下:
用户4396583
2024/07/30
3770
项目实践·Snippets
属于上面的变种方式,重点关注 columnPrefix,他将 child_id 和 child_name 归纳到 children 字段里去。
数媒派
2022/12/01
7400
猿进化系列17——实战之一文学会前后端分离套路
看完上一个章节,相信你已经掌握了一个高效无误地编写SQL的办法,学会了完成小项目的注册功能,对如何使用之前学过的一些知识有了一定的认识,今天我们继续学习,一起来搞懂前后端分离的套路。
山旮旯的胖子
2020/07/28
5600
猿进化系列17——实战之一文学会前后端分离套路
推荐阅读
相关推荐
猿实战12——类目属性之动态绑定
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验