【29-业务开发-基础业务-属性管理-属性组业务逻辑开发-页面布局-三级分类组件功能-属性组表单-父子组件传值-属性组数据展示-属性组数据添加-属性组数据修改-前后端项目整合交互测试】

一.知识回顾

【0.三高商城系统的专题专栏都帮你整理好了,请点击这里!】
【1-系统架构演进过程】
【2-微服务系统架构需求】
【3-高性能、高并发、高可用的三高商城系统项目介绍】
【4-Linux云服务器上安装Docker】
【5-Docker安装部署MySQL和Redis服务】
【6-Git安装与配置过程、Gitee码云上创建项目、IDEA关联克隆的项目】
【7-创建商城系统的子模块并将修改后的信息使用Git提交到Gitee上】
【8-数据库表结构的创建&后台管理系统的搭建】
【9-前端项目的搭建部署、Node安装、VSCode安装】
【10-Node的安装以及全局环境变量的相关配置&解决启动报错的问题(1.Error: Cannot find module ‘fs/promises)(2.npm安装node-sass报错)】
【11-导入人人generator项目并自动生成相关的文件&商品子模块的调试&公共模块common子模块的抽离与实现&Lombok插件的安装】
【12-商品子模块整合MyBatisPlus技术&其它模块通过generator的自动生成与补充完善】
【13-项目中微服务组件的学习-SpringCloudAlibaba微服务生态体系的学习&SpringCloudAlibaba的依赖管理&项目中SpringBoot和SpringCloud版本的统一】
【14-微服务的注册中心与配置中心Nacos&Windows操作系统上安装Nacos和Linux操作系统上用Docker中安装Nacos&每个子项目模块使用Nacos进行服务注册与发现】
【15-项目中服务的远程调用之OpenFeign&订单模块与商品模块集成使用OpenFeign的案例】
【16-配置中心之Nacos的基本使用&Nacos服务之命令空间、Nacos服务之配置组、Nacos服务之配置拆分】
【17-微服务网关之Spring Cloud Gateway&Spring Cloud Gateway网关服务搭建】
【18-业务开发-基础业务-商品模块-分类管理-前后端管理系统的启动-为分类管理表增加数据-Json插件的下载-返回具有层级目录、父子关系结构的数据】
【19-业务开发-基础业务-商品模块-分类管理-管理系统新建菜单-后端项目renren注册到Nacos注册中心和配置中心去-项目gateway网关模块的搭建-浏览器的同源策略与解决跨域问题实操案例】
【20-业务开发-基础业务-商品模块-分类管理-前端展示后端具有层级关系的目录数据-商品系统三级分类的逻辑删除前后端代码实现】
【21-业务开发-基础业务-商品模块-分类管理-商品系统三级分类的新增类别前后端代码实现-商品系统三级分类的更新类别前后端代码实现-之前错误的Bug修正】
【22-业务开发-基础业务-商品模块-分类管理-商品系统三级分类拖拽页面的功能-前后端代码的逻辑实现-访问测试-拖拽开关的开启和关系-批量更新拖拽数据-批量删除选定数据】
【23-业务开发-基础业务-品牌管理-品牌管理项目搭建-品牌管理实现的增删改查操作测试-后端数据显示状态使用前端组件开关按钮展示-以及数据处理以及测试】
【24-业务开发-基础业务-品牌管理-图片管理-阿里云OSS服务开通和使用-阿里云OSS服务API使用-SpringCloudAlibaba OSS服务的使用】
【25-业务开发-基础业务-品牌管理-图片管理-图片上传方式的三种实现方式-第三方公共服务模块集成到项目中-服务端生成签名实战】
【26-业务开发-基础业务-品牌管理-图片管理-上传图片功能实现-基于阿里云OSS服务-解决跨域问题-设置跨域规则-修改ACL权限为公共读】
【27-业务开发-基础业务-品牌管理-图片管理-添加修改品牌信息并显示图片-前端数据校验-后端数据JSR303校验实现-统一异常处理-自定义响应编码规则-分组校验-自定义校验注解-项目Bug解决】
【28-业务开发-基础业务-属性管理-SKU和SPU基本概念-SKU和SPU关联关系-属性实体之间的关联关系-批量菜单创建】

二.属性组业务逻辑开发

2.1 属性组的页面

根据前端创建菜单的url提示,我们在前端product文件目录下,新建立一个attrgroup.vue的前端文件
在这里插入图片描述

前端代码编写测试
在这里插入图片描述

前端项目启动,后端需要用到的四个微服务项目模块启动,访问测试
在这里插入图片描述

2.2 页面布局

在整个属性组中我们需要通过分类来管理属性组的信息,这时我们需要将业务布局为两部分,这时我们可以借助ElementUI中的Layout来实现

在这里插入图片描述

前端代码的实现

<template>
  <el-row :gutter="20">
  <el-col :span="8"><div class="grid-content bg-purple">三级分类</div></el-col>
  <el-col :span="16"><div class="grid-content bg-purple">表格</div></el-col>
  
</el-row>
</template>

<script>
export default {

}
</script>

<style>

</style>

前端访问测试页面效果
在这里插入图片描述

2.3 三级分类组件抽取

  三级分类的展示我们后面在多个菜单中都需要使用到。这时我们可以把这个功能抽取出来为一个独立的组件。实现复用。在product目录的同级下创建一个复用的目录common,然后在其中创建category.vue
在这里插入图片描述

抽取前端代码实现逻辑

<template>
  <div>
    <el-tree
      :data="data"
      :props="defaultProps" 
      node-key="catId"
    >
    </el-tree>
  </div>
</template>

<script>
/* eslint-disable */
export default {
  data() {
    return {
      data:[],
      defaultProps: {
        children: "childrens",
        label: "name",
      },
    };
  },
  methods: {
    getCategory() {
      this.$http({
        url: this.$http.adornUrl("/product/category/listTree"),
        method: "get",
      }).then(({ data }) => {
        this.data = data.data;
      });
    },
  },
  created() {
    this.getCategory();
  },
};
</script>

<style>
</style>

公共组件实现结果
在这里插入图片描述

然后在属性组中我们来使用这个组件,引用其他组件的步骤有三个:

1.通过import 来引入组件
在这里插入图片描述

2.在components中注册我们引入的组件
在这里插入图片描述

3.在页面中使用组件

在这里插入图片描述

访问测试看效果

在这里插入图片描述

2.4 属性组表单

我们需要在右侧展示一个属性组维护的表单,现在我们需要将mall-product代码生成器中生成的属性组的相关的代码拷贝进来即可。

找到商品模块下代码生成器生成的前端代码
在这里插入图片描述

将<div> data 相关的结构布局拷贝到我们的文件中来,attgroup.vue前端代码文件如下:

<template>
  <el-row :gutter="20">
  <el-col :span="6">
    <category></category>
  </el-col>
  <el-col :span="18">
    <div class="mod-config">
    <el-form :inline="true" :model="dataForm" @keyup.enter.native="getDataList()">
      <el-form-item>
        <el-input v-model="dataForm.key" placeholder="参数名" clearable></el-input>
      </el-form-item>
      <el-form-item>
        <el-button @click="getDataList()">查询</el-button>
        <el-button v-if="isAuth('product:attrgroup:save')" type="primary" @click="addOrUpdateHandle()">新增</el-button>
        <el-button v-if="isAuth('product:attrgroup:delete')" type="danger" @click="deleteHandle()" :disabled="dataListSelections.length <= 0">批量删除</el-button>
      </el-form-item>
    </el-form>
    <el-table
      :data="dataList"
      border
      v-loading="dataListLoading"
      @selection-change="selectionChangeHandle"
      style="width: 100%;">
      <el-table-column
        type="selection"
        header-align="center"
        align="center"
        width="50">
      </el-table-column>
      <el-table-column
        prop="attrGroupId"
        header-align="center"
        align="center"
        label="分组id">
      </el-table-column>
      <el-table-column
        prop="attrGroupName"
        header-align="center"
        align="center"
        label="组名">
      </el-table-column>
      <el-table-column
        prop="sort"
        header-align="center"
        align="center"
        label="排序">
      </el-table-column>
      <el-table-column
        prop="descript"
        header-align="center"
        align="center"
        label="描述">
      </el-table-column>
      <el-table-column
        prop="icon"
        header-align="center"
        align="center"
        label="组图标">
      </el-table-column>
      <el-table-column
        prop="catelogId"
        header-align="center"
        align="center"
        label="所属分类id">
      </el-table-column>
      <el-table-column
        fixed="right"
        header-align="center"
        align="center"
        width="150"
        label="操作">
        <template slot-scope="scope">
          <el-button type="text" size="small" @click="addOrUpdateHandle(scope.row.attrGroupId)">修改</el-button>
          <el-button type="text" size="small" @click="deleteHandle(scope.row.attrGroupId)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    <el-pagination
      @size-change="sizeChangeHandle"
      @current-change="currentChangeHandle"
      :current-page="pageIndex"
      :page-sizes="[10, 20, 50, 100]"
      :page-size="pageSize"
      :total="totalPage"
      layout="total, sizes, prev, pager, next, jumper">
    </el-pagination>
    <!-- 弹窗, 新增 / 修改 -->
    <add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList"></add-or-update>
  </div>
  </el-col>
  
</el-row>
</template>

<script>
import Category from "../common/category.vue"
export default {
  data(){
return {
        dataForm: {
          key: ''
        },
        dataList: [],
        pageIndex: 1,
        pageSize: 10,
        totalPage: 0,
        dataListLoading: false,
        dataListSelections: [],
        addOrUpdateVisible: false
      }
  },components:{Category}
  ,methods: {
      // 获取数据列表
      getDataList () {
        this.dataListLoading = true
        this.$http({
          url: this.$http.adornUrl('/product/attrgroup/list'),
          method: 'get',
          params: this.$http.adornParams({
            'page': this.pageIndex,
            'limit': this.pageSize,
            'key': this.dataForm.key
          })
        }).then(({data}) => {
          if (data && data.code === 0) {
            this.dataList = data.page.list
            this.totalPage = data.page.totalCount
          } else {
            this.dataList = []
            this.totalPage = 0
          }
          this.dataListLoading = false
        })
      },
      // 每页数
      sizeChangeHandle (val) {
        this.pageSize = val
        this.pageIndex = 1
        this.getDataList()
      },
      // 当前页
      currentChangeHandle (val) {
        this.pageIndex = val
        this.getDataList()
      },
      // 多选
      selectionChangeHandle (val) {
        this.dataListSelections = val
      },
      // 新增 / 修改
      addOrUpdateHandle (id) {
        this.addOrUpdateVisible = true
        this.$nextTick(() => {
          this.$refs.addOrUpdate.init(id)
        })
      },
      // 删除
      deleteHandle (id) {
        var ids = id ? [id] : this.dataListSelections.map(item => {
          return item.attrGroupId
        })
        this.$confirm(`确定对[id=${ids.join(',')}]进行[${id ? '删除' : '批量删除'}]操作?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.$http({
            url: this.$http.adornUrl('/product/attrgroup/delete'),
            method: 'post',
            data: this.$http.adornData(ids, false)
          }).then(({data}) => {
            if (data && data.code === 0) {
              this.$message({
                message: '操作成功',
                type: 'success',
                duration: 1500,
                onClose: () => {
                  this.getDataList()
                }
              })
            } else {
              this.$message.error(data.msg)
            }
          })
        })
      }
    }
}
</script>

<style>

</style>

访问测试

在这里插入图片描述

2.5 父子组件传值

特别说明:函数事件和绑定的函数方法

<category @show="treenodeclick"></category>

`特别说明:`
@show:是声明一个show事件
treenodeclick:是与这个show事件绑定的函数方法

当我们点击分类菜单的节点的时候,需要把我们的节点Id传递给我们右侧父节点的table展示出来

在这里插入图片描述

1.我们需要触发Tree节点的点击事件

在这里插入图片描述

2.我们需要在父组件中定义的一个事件

在这里插入图片描述

3.在子组件中触发父组件中绑定的事件,实现数据的传递在这里插入图片描述

4.触发事件会回调对应的方法

在这里插入图片描述

5.测试访问, 看结果。

在这里插入图片描述

2.6 属性组的展示

2.6.1 后端代码实现

前后端进行数据交互封装的数据

{
    page:1, // 当前页
    limit:10, // 每页显示的条数
    sidx:"id", // 排序的字段
    order:"asc/desc", // 排序的方式
    key:"检索条件" // 查询的关键字
}

AttrGroupController控制器中的处理

/**
 * catelogId商品分类Id
 * 根据catelogId进行查找数据
 * 如果是0 查找所有的分类信息
 * 如果非0 查找对应的catelogId下的分类信息
 */
@RequestMapping("/list/{catelogId}")
//@RequiresPermissions("product:attrgroup:list")
public R list(@RequestParam Map<String, Object> params,@PathVariable("catelogId") Long catelogId){
    PageUtils page = attrGroupService.queryPage(params,catelogId);
    return R.ok().put("page", page);
}

service接口定义的接口方法

PageUtils queryPage(Map<String, Object> params, Long catelogId);

serviceImpl中具体方法处理逻辑

    /**
     * 查询列表数据
     *    根据列表编号来查询
     * @param params
     * @param catelogId 如何catelogId为0 就不根据catelogId来查询
     * @return
     */
    @Override
    public PageUtils queryPage(Map<String, Object> params, Long catelogId) {
        // 获取检索的关键字
        String key = (String) params.get("key");
        QueryWrapper<AttrGroupEntity> wrapper = new QueryWrapper<>();
        if(!StringUtils.isEmpty(key)){
            // 拼接查询的条件
            wrapper.and((obj)->{
                obj.eq("attr_group_id",key).or().like("attr_group_name",key);
            });
        }

        if(catelogId == 0){
            // 不根据catelogId来查询
            IPage<AttrGroupEntity> page = this.page(
                    new Query<AttrGroupEntity>().getPage(params),wrapper
                    );
            return new PageUtils(page);
        }
        // 根据类别编号来查询属性信息
        wrapper.eq("catelog_id",catelogId);
        IPage<AttrGroupEntity> page = this.page(
                new Query<AttrGroupEntity>().getPage(params),wrapper
        );
        return new PageUtils(page);
    }
2.6.2 前端代码实现

先将common/category.vue组件中的传递所有的data给父组件
在这里插入图片描述

定义全局id、三级分类实现逻辑操作、定义前端与后端进行接口交互的方法

注意:下面图片中有一个小问题,就是发送请求的后面有少了一个/,加上即可

url: this.$http.adornUrl('/product/attrgroup/list/'+this.catId)

在这里插入图片描述

重启项目,测试效果:

在这里插入图片描述

2.7 属性组添加

2.7.1 属性组添加数据实现-1

先导入我们对应添加的增加和更新组件
在这里插入图片描述

导入,声明引入的组件
在这里插入图片描述

测试一下,导入的组件是否成功可用
在这里插入图片描述

点击添加按钮弹出对话框,我们需要对属性组的类别做级联选择操作。然后维护类别的级联查找

在这里插入图片描述
查找对应的组件代码
在这里插入图片描述

定义三级联查
在这里插入图片描述

设置全局需要的属性信息
在这里插入图片描述

定义与后端交互发送请求的接口方法
在这里插入图片描述

在生命周期的方法中填充数据
在这里插入图片描述

还有就是在级联中的childrens为空的情况,在后端通过@JsonInclude注解来解决

在这里插入图片描述

启动项目,访问前端的页面效果,搞定!

在这里插入图片描述

2.7.2 属性组添加数据实现-2

当我们提交表单数据后出现了如下的异常,id是一个数组,但是我们只需要获取最后一个分类的id就可以,所以我们需要做如下的调整。

image.png

首先先对三级关联中的属性绑定
在这里插入图片描述

然后在提交数据的位置获取最小的类别编号提交就可以了

在这里插入图片描述

访问测试
在这里插入图片描述

增加成功结果显示:
在这里插入图片描述

2.8 属性组修改

在更新属性组的信息的时候,因为三级分类的信息展示需要为[第一级分类id,第二级分类id,第三级分类id]这种方式,而后台只是提供了第三级分类id,那么为了能够更加清楚的展示相关的信息,我们需要自己再来实现相关的逻辑代码

2.8.1 前端逻辑

修改逻辑—>初始化获取后端数据的逻辑
在这里插入图片描述

修改完毕,级联数据清空
定义事件
在这里插入图片描述
绑定方法,清楚数据
在这里插入图片描述

设置级联查询的小功能
在这里插入图片描述

2.8.2 后端逻辑

AttrGroupEntity实体类中添加catelogPath long数组类型的属性
在这里插入图片描述

AttrGroupController中注入CategoryService注解

在这里插入图片描述

AttrGroupController中实现相关的逻辑
image.png

在CategoryService定义相关接口
在这里插入图片描述

在CategoryServiceImpl中实现具体的逻辑方法
在这里插入图片描述

2.8.3 重新启动项目,访问测试效果

点击修改,正常显示
在这里插入图片描述

再次增加,数据清空
在这里插入图片描述

默认背景提示
在这里插入图片描述

自定义搜索
在这里插入图片描述

好了,关于【28-业务开发-基础业务-属性管理-属性组业务逻辑开发-页面布局-三级分类组件功能-属性组表单-父子组件传值-属性组数据展示-属性组数据添加-属性组数据修改-前后端项目整合交互】就先学习到这里,后续的内容持续创作中。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

硕风和炜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值