[项目练手笔记-谷粒商城(SpringCloud Alibaba+vue前后端分离)]day10属性分组功能编写(三级菜单组件抽离+父子组件交互+前后端级联菜单编写及回显)

[项目练手笔记-谷粒商城(SpringCloud Alibaba+vue前后端分离)]day10属性分组功能编写(三级菜单组件抽离+父子组件交互+前后端级联菜单编写及回显)

谷粒商城接口文档地址:https://easydoc.xyz/s/78237135

一、完善数据库菜单

1.使用gulimall-admin

2.建表

/*
SQLyog Ultimate v11.25 (64 bit)
MySQL - 5.7.27 : Database - gulimall_admin
*********************************************************************
*/


/*!40101 SET NAMES utf8 */;

/*!40101 SET SQL_MODE=''*/;

/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
CREATE DATABASE /*!32312 IF NOT EXISTS*/`gulimall_admin` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;

USE `gulimall_admin`;

/*Table structure for table `sys_menu` */

DROP TABLE IF EXISTS `sys_menu`;

CREATE TABLE `sys_menu` (
  `menu_id` BIGINT(20) NOT NULL AUTO_INCREMENT,
  `parent_id` BIGINT(20) DEFAULT NULL COMMENT '父菜单ID,一级菜单为0',
  `name` VARCHAR(50) DEFAULT NULL COMMENT '菜单名称',
  `url` VARCHAR(200) DEFAULT NULL COMMENT '菜单URL',
  `perms` VARCHAR(500) DEFAULT NULL COMMENT '授权(多个用逗号分隔,如:user:list,user:create)',
  `type` INT(11) DEFAULT NULL COMMENT '类型   0:目录   1:菜单   2:按钮',
  `icon` VARCHAR(50) DEFAULT NULL COMMENT '菜单图标',
  `order_num` INT(11) DEFAULT NULL COMMENT '排序',
  PRIMARY KEY (`menu_id`)
) ENGINE=INNODB AUTO_INCREMENT=76 DEFAULT CHARSET=utf8mb4 COMMENT='菜单管理';

/*Data for the table `sys_menu` */

INSERT  INTO `sys_menu`(`menu_id`,`parent_id`,`name`,`url`,`perms`,`type`,`icon`,`order_num`) VALUES (1,0,'系统管理',NULL,NULL,0,'system',0),(2,1,'管理员列表','sys/user',NULL,1,'admin',1),(3,1,'角色管理','sys/role',NULL,1,'role',2),(4,1,'菜单管理','sys/menu',NULL,1,'menu',3),(5,1,'SQL监控','http://localhost:8080/renren-fast/druid/sql.html',NULL,1,'sql',4),(6,1,'定时任务','job/schedule',NULL,1,'job',5),(7,6,'查看',NULL,'sys:schedule:list,sys:schedule:info',2,NULL,0),(8,6,'新增',NULL,'sys:schedule:save',2,NULL,0),(9,6,'修改',NULL,'sys:schedule:update',2,NULL,0),(10,6,'删除',NULL,'sys:schedule:delete',2,NULL,0),(11,6,'暂停',NULL,'sys:schedule:pause',2,NULL,0),(12,6,'恢复',NULL,'sys:schedule:resume',2,NULL,0),(13,6,'立即执行',NULL,'sys:schedule:run',2,NULL,0),(14,6,'日志列表',NULL,'sys:schedule:log',2,NULL,0),(15,2,'查看',NULL,'sys:user:list,sys:user:info',2,NULL,0),(16,2,'新增',NULL,'sys:user:save,sys:role:select',2,NULL,0),(17,2,'修改',NULL,'sys:user:update,sys:role:select',2,NULL,0),(18,2,'删除',NULL,'sys:user:delete',2,NULL,0),(19,3,'查看',NULL,'sys:role:list,sys:role:info',2,NULL,0),(20,3,'新增',NULL,'sys:role:save,sys:menu:list',2,NULL,0),(21,3,'修改',NULL,'sys:role:update,sys:menu:list',2,NULL,0),(22,3,'删除',NULL,'sys:role:delete',2,NULL,0),(23,4,'查看',NULL,'sys:menu:list,sys:menu:info',2,NULL,0),(24,4,'新增',NULL,'sys:menu:save,sys:menu:select',2,NULL,0),(25,4,'修改',NULL,'sys:menu:update,sys:menu:select',2,NULL,0),(26,4,'删除',NULL,'sys:menu:delete',2,NULL,0),(27,1,'参数管理','sys/config','sys:config:list,sys:config:info,sys:config:save,sys:config:update,sys:config:delete',1,'config',6),(29,1,'系统日志','sys/log','sys:log:list',1,'log',7),(30,1,'文件上传','oss/oss','sys:oss:all',1,'oss',6),(31,0,'商品系统','','',0,'editor',0),(32,31,'分类维护','product/category','',1,'menu',0),(34,31,'品牌管理','product/brand','',1,'editor',0),(37,31,'平台属性','','',0,'system',0),(38,37,'属性分组','product/attrgroup','',1,'tubiao',0),(39,37,'规格参数','product/baseattr','',1,'log',0),(40,37,'销售属性','product/saleattr','',1,'zonghe',0),(41,31,'商品维护','product/spu','',0,'zonghe',0),(42,0,'优惠营销','','',0,'mudedi',0),(43,0,'库存系统','','',0,'shouye',0),(44,0,'订单系统','','',0,'config',0),(45,0,'用户系统','','',0,'admin',0),(46,0,'内容管理','','',0,'sousuo',0),(47,42,'优惠券管理','coupon/coupon','',1,'zhedie',0),(48,42,'发放记录','coupon/history','',1,'sql',0),(49,42,'专题活动','coupon/subject','',1,'tixing',0),(50,42,'秒杀活动','coupon/seckill','',1,'daohang',0),(51,42,'积分维护','coupon/bounds','',1,'geren',0),(52,42,'满减折扣','coupon/full','',1,'shoucang',0),(53,43,'仓库维护','ware/wareinfo','',1,'shouye',0),(54,43,'库存工作单','ware/task','',1,'log',0),(55,43,'商品库存','ware/sku','',1,'jiesuo',0),(56,44,'订单查询','order/order','',1,'zhedie',0),(57,44,'退货单处理','order/return','',1,'shanchu',0),(58,44,'等级规则','order/settings','',1,'system',0),(59,44,'支付流水查询','order/payment','',1,'job',0),(60,44,'退款流水查询','order/refund','',1,'mudedi',0),(61,45,'会员列表','member/member','',1,'geren',0),(62,45,'会员等级','member/level','',1,'tubiao',0),(63,45,'积分变化','member/growth','',1,'bianji',0),(64,45,'统计信息','member/statistics','',1,'sql',0),(65,46,'首页推荐','content/index','',1,'shouye',0),(66,46,'分类热门','content/category','',1,'zhedie',0),(67,46,'评论管理','content/comments','',1,'pinglun',0),(68,41,'spu管理','product/spu','',1,'config',0),(69,41,'发布商品','product/spuadd','',1,'bianji',0),(70,43,'采购单维护','','',0,'tubiao',0),(71,70,'采购需求','ware/purchaseitem','',1,'editor',0),(72,70,'采购单','ware/purchase','',1,'menu',0),(73,41,'商品管理','product/manager','',1,'zonghe',0),(74,42,'会员价格','coupon/memberprice','',1,'admin',0),(75,42,'每日秒杀','coupon/seckillsession','',1,'job',0);

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

3.概览

在这里插入图片描述

二、初构属性分组三级菜单

1.抽取三级分类菜单组件

创建一个三级分类组件

目录是module/common/category.vue

2.新建attrgroup.vue

根据菜单目录,在product目录下创建一个attrgroup.vue

3.修改attrgroup布局

1.抽取category三级菜单
<template>
  <div>
    <el-tree :data="menus" :props="defaultProps" node-key="catId" ref="menuTree"></el-tree>
  </div>
</template>

<script>
//这里可以导入其他文件(比如:组件,工具js,第三方插件js,json文件,图片文件等等)
//例如:import 《组件名称》 from '《组件路径》';

export default {
  //import引入的组件需要注入到对象中才能使用
  components: {},
  data() {
    //这里存放数据
    return {
      menus: [],
      defaultProps: {
        children: "children",
        label: "name"
      }
    };
  },
  //监听属性 类似于data概念
  computed: {},
  //监控data中的数据变化
  watch: {},
  //方法集合
  methods: {
    getMenus() {
      this.$http({
        url: this.$http.adornUrl("/product/category/list/tree"),
        method: "get",
        params: this.$http.adornParams({})
      }).then(({ data }) => {
        this.menus = data.data;
      });
    }
  },
  //生命周期 - 创建完成(可以访问当前this实例)
  created() {
    this.getMenus();
  },
  //生命周期 - 挂载完成(可以访问DOM元素)
  mounted() {},
  beforeCreate() {}, //生命周期 - 创建之前
  beforeMount() {}, //生命周期 - 挂载之前
  beforeUpdate() {}, //生命周期 - 更新之前
  updated() {}, //生命周期 - 更新之后
  beforeDestroy() {}, //生命周期 - 销毁之前
  destroyed() {}, //生命周期 - 销毁完成
  activated() {} //如果页面有keep-alive缓存功能,这个函数会触发
};
</script>
<style lang='scss' scoped>
//@import url(); 引入公共css类
</style>
2.导入三级菜单组件
import Category from "../common/category";
export default {
  //import引入的组件需要注入到对象中才能使用
  components: {Category},
       <div class="grid-content bg-purple">
          <category></category>
        </div>
3.显示右侧表格

使用代码逆向生成器

4.概览

在这里插入图片描述

三、获取分类属性分组

1.父子组件交互

1.子组件绑定事件

使用事件机制,给父组件传递一个事件,携带上数据

给子组件category绑定一个结点点击事件,携带被点击结点的数据给父组件attrgroup

<el-tree :data="menus" :props="defaultProps" node-key="catId" ref="menuTree" @node-click="nodeClick"></el-tree>
2.子组件发送数据
    nodeClick(data,node,components) {
      console.log("子组件事件触发",data,node,components);
      this.$emit("tree-node-click",data,node,components);
    },

父组件接受响应

      <category @tree-node-click="TreeNodeClick"></category>
3.父组件接受触发
    TreeNodeClick(data, node, components) {
      console.log("父节点接受到参数", data, node, components);
    },

2.查询属性分组

需求:点击菜单获取属性分组在右侧显示

1.修改controller
    /**
     * 列表
     */
    @RequestMapping("/list/{catelogId}")
    //@RequiresPermissions("product:attrgroup:list")
    public R list(@RequestParam Map<String, Object> params,@PathVariable("catelogId") Long catelogId){
//        PageUtils page = attrGroupService.queryPage(params);
        PageUtils page = attrGroupService.queryPage(params,catelogId);

        return R.ok().put("page", page);
    }
2.修改serviceimpl
@Override
public PageUtils queryPage(Map<String, Object> params, Long catelogId) {
    if(catelogId==0) {
        IPage<AttrGroupEntity> page = this.page(
                new Query<AttrGroupEntity>().getPage(params),
                new QueryWrapper<AttrGroupEntity>()
        );

        return new PageUtils(page);
    }else {
        //select * from pms_attr_group where catlog_id =?and(attr_group_id=key or attr_group_name like %key%)
        String key = (String) params.get("key");//获取key的值
        QueryWrapper<AttrGroupEntity> queryWrapper = new QueryWrapper<AttrGroupEntity>().eq("catelog_id", catelogId);
        //如果接收的key不为空,也就是有查询条件
        if (!StringUtils.isEmpty(key)) {
            queryWrapper.and((obj)->{
                obj.eq("attr_group_id",key).or().like("attr_group_name",key);
            });
        }
        IPage<AttrGroupEntity> page = this.page(
                new Query<AttrGroupEntity>().getPage(params),
                queryWrapper
        );
        return new PageUtils(page);

    }

}
3.修改前端请求

获取数据方法改变url

    // 获取数据列表
    getDataList() {
      this.dataListLoading = true;
      this.$http({
        url: this.$http.adornUrl(`/product/attrgroup/list/${this.catId}`),

传递Id

  methods: {
    TreeNodeClick(data, node, components) {
      console.log("父节点接受到参数", data, node, components);
      if(node.level==3) {
          this.catId = data.catId;
          this.getDataList();
      }
    },

四、添加属性分类

1.使用级联选择器

      <el-form-item label="所属分类id" prop="catelogId">
        <!-- <el-input v-model="dataForm.catelogId" placeholder="所属分类id"></el-input> -->
        <el-cascader v-model="dataForm.catelogPath" :options="categorys" :props="props"></el-cascader>
      </el-form-item>
  data() {
    return {
      props: {
        value: "catId",
        label: "name",
        children: "children"
      },
      categorys: [],
      dataForm: {
        attrGroupId: 0,
        attrGroupName: "",
        sort: "",
        descript: "",
        icon: "",
        catelogPath: [],
        catelogId: 0
      },

2.提交catid

   // 表单提交
    dataFormSubmit() {
      this.$refs["dataForm"].validate(valid => {
        if (valid) {
          this.$http({
            url: this.$http.adornUrl(
              `/product/attrgroup/${
                !this.dataForm.attrGroupId ? "save" : "update"
              }`
            ),
            method: "post",
            data: this.$http.adornData({
              attrGroupId: this.dataForm.attrGroupId || undefined,
              attrGroupName: this.dataForm.attrGroupName,
              sort: this.dataForm.sort,
              descript: this.dataForm.descript,
              icon: this.dataForm.icon,
              catelogId: this.dataForm.catelogPath[
                this.dataForm.catelogPath.length - 1
              ]			//这里提交了最后一个ID查询
            })

3.修改entity

新增发现最后一级菜单还有空子菜单

在这里插入图片描述

去除办法是修改entity

/**
 * 所有子节点
 */
@JsonInclude(value = JsonInclude.Include.NON_EMPTY)
@TableField(exist=false)
private List<CategoryEntity> children;

这样当children为空的时候,就不会有输出

五、回显联级菜单

1.修改AttrGroupEntity

添加属性

/**
 * 联级目录路径
 */
@TableField(exist = false)
private Long[] catelogPath;

2.修改controller

/**
 * 信息
 */
@RequestMapping("/info/{attrGroupId}")
//@RequiresPermissions("product:attrgroup:info")
public R info(@PathVariable("attrGroupId") Long attrGroupId) {
    AttrGroupEntity attrGroup = attrGroupService.getById(attrGroupId);

    Long catelogId = attrGroup.getCatelogId();
    //获取路径
    Long[] path = attrGroupService.getCatelogPath(catelogId);
    attrGroup.setCatelogPath(path);

    return R.ok().put("attrGroup", attrGroup);
}

3.修改CategoryServiceImpl

/**
 * 找到[父/子]路径
 * @param catelogId
 * @return
 */
@Override
public Long[] getCatelogPath(Long catelogId) {
    List<Long> path = new ArrayList<>();//记录路径
    getPath(path,catelogId);

    return path.toArray(new Long[path.size()]);
}

/**
 * 递归查找父节点
 * @param path
 * @param catelogId
 */
private void getPath(List<Long> path, Long catelogId) {
    Long parentCid = this.getById(catelogId).getParentCid();
    //只要不是根节点,就继续往上找
    if(parentCid!=0) {
        getPath(path, parentCid);
    }
    path.add(catelogId);
}

4.关闭对话框初始函数

  <el-dialog
    :title="!dataForm.id ? '新增' : '修改'"
    :close-on-click-modal="false"
    :visible.sync="visible"
    @closed="dialogClose"
  >
    dialogClose() {
      this.dataForm.catelogPath = [];
    },

5.开启级联菜单搜索

        <el-cascader v-model="dataForm.catelogPath" :options="categorys" :props="props" filterable placeholder="试试搜索:手机"></el-cascader>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值