专栏首页猿人工厂猿实战15——关联你所不明白的前后台类目

猿实战15——关联你所不明白的前后台类目

上一个章节,猿人君教会了你如何去设置广告牌,今天我们一起来学习,如何绑定前后台类目。

功能概览

在三级前台类目列表中,点击管理按钮,设置当前前台三级类目和后台类目的关系。通过勾选左侧后台类目的形式,将选中的三级类目内容放置到右侧的列表中,同时列表提供删除功能,点击保存按钮,完成前台类目和后台类目的关系绑定。

数据库设计

既然是绑定关系,那自然是需要关系表来持久这样的数据。至于为什么要建立这种关系,你可以查看之前的设计文章。

数据展示后端功能实现

在思考后端功能怎样实现时,我们可以先看看功能描述。点击管理后,来完成前后端类目关系设置的操作。你看,又是“设置”类的操作。对于这种操作,自然需要返回需要操作的数据,以及已经建立的关系数据了。

也就是说,我们的后端,需要至少两个数据接口——一个用于返回右侧的类目数据,一个返回已有的前后台类目关系。我们先在MallFnCategoryController中增加代码。

/**
     * 返回用于选择的后台类目
     * @param queryMallFnBgCategoryRel
     * @return
     */
    @RequestMapping("/findForSelect")
    public  Result<List<MallCategoryVo>> findForSelect(@RequestBody QueryMallFnBgCategoryRel queryMallFnBgCategoryRel){
         QueryMallCategory queryMallCategory = new QueryMallCategory();
         Result<List<MallCategoryVo>> dataResult= mallCategoryService.getMallCategoryVoList(queryMallCategory,null);
         return dataResult;
 
    }
 
 
    /**
     * 返回前台类目后台类目关系列表
     * @param queryMallFnBgCategoryRel
     * @return
     */
    @RequestMapping("/findForSelectedTable")
    public  Result<List<MallFnBgCategoryRel>> findForSelectedTable(@RequestBody QueryMallFnBgCategoryRel queryMallFnBgCategoryRel){
 
        Result<List<MallFnBgCategoryRel>>  result=  mallFnBgCategoryRelService.getMallFnBgCategoryRelsByQueryWithCateName(queryMallFnBgCategoryRel);
        return result;
 
    }

考虑到部分朋友对如何获取树结构数据不太熟悉,这里把service层的代码给到你。

/**
 * 获取需要展示的类目
 * @param queryMallCategory
 * @param exculdeIdlist
 * @return
 */
public Result<List<MallCategoryVo>> getMallCategoryVoList(QueryMallCategory queryMallCategory,List<Long> exculdeIdlist) {
 
Result<List<MallCategoryVo>> result = new Result<List<MallCategoryVo>>();
try {
List<MallCategory> dataList= mallCategoryDao.selectMallCategoryByQuery(queryMallCategory);
//删除需要屏蔽的对象
if(!CollectionUtils.isEmpty(exculdeIdlist)){
dataList.removeIf(a -> {
return exculdeIdlist.stream().anyMatch(b -> {
if (b!= null && b.equals(a.getCategoryId())) {
return true;
} else {
return false;
}
});
});
}
List<MallCategoryVo> voList= new ArrayList<MallCategoryVo>();
result.addDefaultModel(voList);
for(MallCategory category:dataList){
 
if(category.getLevel()==1){
MallCategoryVo vo = new MallCategoryVo();
vo.setCategoryId(category.getCategoryId());
vo.setCategoryName(category.getCategoryName());
vo.setLevel(category.getLevel());
voList.add(vo);
setChildren(dataList,vo);
}
 
}
} catch(Exception e) {
result.setSuccess(false);
}
return result;
}
 
/**
 * 递归设置子节点
 * @param dataList
 * @param mallCategoryVo
 */
private void setChildren(List<MallCategory> dataList,MallCategoryVo mallCategoryVo){
for(MallCategory category:dataList){
if(mallCategoryVo.getCategoryId().equals(category.getParentId())){
MallCategoryVo child = new MallCategoryVo();
child.setCategoryId(category.getCategoryId());
child.setCategoryName(category.getCategoryName());
child.setLevel(category.getLevel());
mallCategoryVo.getChildren().add(child);
setChildren(dataList,child);
}
 
}
}

数据展示前端功能实现

后端的数据有了,那么接下来就是前端数据展示的实现了。像这样的前端界面,我们其实在类目属性绑定的功能中也遇到过。这里帮你复习下。

同样的,我们使用el-tree组件来展示后台类目数据。

使用el-table组件,实现动态表单的功能。

前端数据初始化

页面已经有了,我们一起来看看数据初始化的问题。

我们需要调用后端接口,初始化类目和动态表单的数据,以完成数据内容的填充。

后台类目数据选择

由于当前的前台类目,可能出现已经绑定的后台类目,那么在实现时,需要过滤已经设置过的数据。

updateKeyChildren(data, key1, key2) {
      const checkedNodes = this.$refs.tree.getCheckedNodes()
      if (checkedNodes != null && checkedNodes.length > 0) {
        for (let i = 0; i < checkedNodes.length; i++) {
          this.atteibute = {
            id: undefined,
            fnCategoryId: this.fnCategoryId,
            categoryId: checkedNodes[i].categoryId,
            categoryName: checkedNodes[i].categoryName,
            fnCategoryName: this.fnCategoryName,
            status: 1,
            checked: true
          }
          const checkedNode = checkedNodes[i]
          if (checkedNode.categoryId !== null && checkedNode.level === 3) {
            let flag = true
            for (let j = 0; j < this.tableList.length; j++) {
              if (this.tableList[j].categoryId === checkedNode.categoryId) {
                console.log(checkedNode)
                flag = false
              }
            }
            if (flag) {
              if (checkedNode.checked) {
                this.atteibute.mainCategory = 1
              } else {
                this.atteibute.mainCategory = 0
              }
              this.tableList.push(this.atteibute)
            }
          }
        }
      }
    }

那有些内容,并不是想要的,需要删除怎么办啊?提供一个删除功能就好了。

handleDelete(index, row) {
      this.tableList.splice(index, 1)
    }

前端保存按钮功能实现

API的封装?你已经封装过很多次api了,这次你自己好好实现一把吧。

后端保存数据

增加一个后端数据接口,用于保存前后台类目的绑定关系就可以了。

/**
     * 批量新增前后台类目关系
     * @param mallFnBgCategoryRelList
     * @return
     */
    @RequestMapping("/addMallFnBgCategoryRelBatch")
    public Result<List<MallFnBgCategoryRel>> addMallCategoryPropertyValueBatch(@RequestBody List<MallFnBgCategoryRel> mallFnBgCategoryRelList){
        try{
            return mallFnBgCategoryRelService.addMallFnBgCategoryRelBatch(mallFnBgCategoryRelList);
        }catch(Exception e){
            e.printStackTrace();
            return new Result(false);
        }
    }
 
@Override
public Result<List<MallFnBgCategoryRel>> addMallFnBgCategoryRelBatch(List<MallFnBgCategoryRel> mallFnBgCategoryRelList) {
Result<List<MallFnBgCategoryRel>> result = new Result<List<MallFnBgCategoryRel>>();
try {
QueryMallFnBgCategoryRel query = new QueryMallFnBgCategoryRel();
query.setFnCategoryId(mallFnBgCategoryRelList.get(0).getFnCategoryId());
List<MallFnBgCategoryRel> dbList = mallFnBgCategoryRelDao.selectMallFnBgCategoryRelByQuery(query);
 
            //有即新增无则删除
for(MallFnBgCategoryRel newRel:mallFnBgCategoryRelList){
 
if(null==newRel.getId()){
mallFnBgCategoryRelDao.insertMallFnBgCategoryRelModified(newRel);
continue;
}
 
for(MallFnBgCategoryRel dbRel:dbList){
if(newRel.getId().equals(dbRel.getId())){
mallFnBgCategoryRelDao.updateMallFnBgCategoryRelByIdModified(dbRel);
continue;
}
 
}
}
            //删除列表中没有的记录
for(MallFnBgCategoryRel dbRel: dbList){
boolean flag=true;
for(MallFnBgCategoryRel newRel:mallFnBgCategoryRelList){
if(newRel.getId().equals(dbRel.getId())){
flag=false;
}
if(flag){
dbRel.setStatus(-1);
mallFnBgCategoryRelDao.updateMallFnBgCategoryRelByIdModified(dbRel);
}
}
 
}
result.addDefaultModel(mallFnBgCategoryRelList);
}catch(Exception e) {
result.setSuccess(false);
}
return result;
 
}

本文分享自微信公众号 - 猿人工厂(gh_deca5a88e287),作者:山旮旯的胖子

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-09-18

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 猿实战16——承运商之搭建你的运费基石

    上几个章节,猿人君教会了你如何去实现前台类目的后台管理功能,今天我们一起来学习,如何实现承运商管理。

    山旮旯的胖子
  • 猿实战03——猿首战之手把手教你撸品牌

    猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,跟着教程走下...

    山旮旯的胖子
  • 猿实战17——实现你未必知晓的运费模板

    猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到...

    山旮旯的胖子
  • 三万字带你彻底吃透MyBatis源码!!

    作者个人研发的在高并发场景下,提供的简单、稳定、可扩展的延迟消息队列框架,具有精准的定时任务和延迟队列处理功能。自开源半年多以来,已成功为十几家中小型企业提供了...

    冰河
  • leetcode468. Validate IP Address

    校验该字符串是IPV4地址还是IPV6地址还是二者都不是。 IPV4地址通过小数点分割为4个部分,每个部分都是0~255之间的正整数,且不能包含开头的0,如01...

    眯眯眼的猫头鹰
  • 命令式到函数式编程

    应用场景:当我们用到 if-elseif-else 的时候,可以考虑使用 Optional 语义。 举例说明:

    lambeta
  • 源码分析 Sentinel DegradeSlot 熔断实现原理

    Sentinel 中的熔断实现类为 DegradeSlot。DegradeSlot 的类定义如下图所示:

    丁威
  • 源码分析Dubbo服务调用日志(accesslog参数)实现原理

    谈到服务调用日志,大家恐怕第一想到就是如果开启了这个参数,会影响性能。那真实的情况是怎么样了?性能损耗到底有多大呢?在实践中我们如何使用该功能呢?本文将详细分析...

    丁威
  • 漏洞复现 | WordPress 4.2.0-4.5.1 flashmediaelement.swf 反射型 XSS

    首先来看存在漏洞的输出, 99%的Flash XSS都是由于ExternalInterface.call函数的参数注入导致的, 当然本次也不例外. 拿到源码之后...

    TeamsSix
  • jQuery原理(原型上的属性、方法)

    jQuery存在两个each方法,一个类方法,一个对象方法。当实现类方法时,只需要让对象方法调用类方法即可实现。

    Dreamy.TZK

扫码关注云+社区

领取腾讯云代金券