添加时添加树型结构

后端:

实体类中添加字段

@JsonInclude(JsonInclude.Include.NON_NULL) //属性值为null不进行序列化操作
    @TableField(exist = false)
    private List<Permission> children = new ArrayList<Permission>();
    /**
     * 用于前端判断是菜单、目录或按钮
     */
    @TableField(exist = false)
    private String value;
    /**
     * 是否展开
     */
    @TableField(exist = false)
    private Boolean open;

需要工具类,生成树形列表

public static List<Permission> makeMenuTree(List<Permission> menuList,Long pid){
        //创建集合保存菜单数据
        List<Permission> permissionList = new ArrayList<>();
        //判断菜单列表是否为空,如果不为空则使用菜单列表,否则创建集合对象
        Optional.ofNullable(menuList).orElse(new ArrayList<Permission>())
                .stream().filter(item -> item!=null && item.getParentId() == pid)
                .forEach(item ->{
                    //创建权限菜单对象
                    Permission permission = new Permission();
                    //将原有的属性赋值给菜单对象
                    BeanUtils.copyProperties(item,permission);
                    //获取每一个item对象的子菜单,递归生成菜单树
                    List<Permission> children = makeMenuTree(menuList, item.getId());
                    //设置子菜单
                    permission.setChildren(children);
                    //将菜单对象添加到集合
                    permissionList.add(permission);
                });
        //返回菜单信息
        return permissionList;
    }

service中,需要获取最顶级的菜单。

@Override
    public List<Permission> findParentPermissionList() {
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        //只查询0目录  1 菜单  的数据
        wrapper.in("type", Arrays.asList(0,1));
        //排序
        wrapper.orderByAsc("order_num");
        //调用查询菜单列表的方法
        List<Permission> permissionList = permissionMapper.selectList(wrapper);
        //创建部门对象
        Permission permission = new Permission();
        permission.setId(0L);
        permission.setParentId(-1L);
        permission.setLabel("顶级列表");
        permissionList.add(permission);
        //生成树列表
        List<Permission> menuTree = MenuTree.makeMenuTree(permissionList, -1L);
        return menuTree;
    }

controller层:

@GetMapping("/parent/list")
    public Result findParentPermissionList() {
        //查询菜单列表
        List<Permission> permissionList = permissionService.findParentPermissionList();
        return Result.ok(permissionList);
    }

前端:

 打开对话框的添加按钮

//新增按钮
        openAddWindow(){
            //每次打开表单时,都要清空数据 ref  和 model 
            this.$resetForm("menuForm",this.menu)
            //清空图标选择器
            this.$nextTick(() => {
                //拿到儿子组件里的属性值,赋值为空。
                this.$refs.child.userChooseIcon = "";
            })
            //点击新增按钮,打开弹出窗口 并添加标题
            this.menuDialog.visible = true;
            this.menuDialog.title = "新增表单";
        },

这里使用了v-if控制表单内容的显隐,使用v-show是不能去掉表单验证的。

<!--添加的弹出表单  使用自定义组件-->
        <system-dialog 
        :title="menuDialog.title"
        :width="menuDialog.width"
        :height="menuDialog.height"
        :visible="menuDialog.visible"
        @onClose="onClose()"
        @onConfirm="onConfirm()"
        >
            <!--引入插槽-->
            <div slot="content">
                <!--添加form表单-->
                <el-form
                :model="menu"
                ref="menuForm"
                :rules="rules"
                label-width="80px"
                :inline="true"
                size="small"
                >
                    <el-row>
                        <el-col :span="24">
                            <el-form-item prop="type" label="菜单类型">
                                <el-radio-group v-model="menu.type">
                                    <el-radio :label="0">目录</el-radio>
                                    <el-radio :label="1">菜单</el-radio>
                                    <el-radio :label="2">按钮</el-radio>
                                </el-radio-group>
                            </el-form-item>
                        </el-col>
                    </el-row>
                    <el-form-item prop="parentName" size="small" label="所属菜单">
                        <el-input @click.native="selectParentMenu()" v-model="menu.parentName" :readonly="true" ></el-input>
                    </el-form-item>

                    <el-form-item prop="label" size="small" label="菜单名称">
                        <el-input v-model="menu.label"></el-input>
                    </el-form-item>

                    <el-form-item prop="name" v-if="menu.type == 1"  size="small"  label="路由名称">
                        <el-input v-model="menu.name"></el-input>
                    </el-form-item>

                    <el-form-item prop="path" v-if="menu.type != 2" size="small" label="路由地址">
                        <el-input v-model="menu.path"></el-input>
                    </el-form-item>

                    <el-form-item prop="url" v-if="menu.type == 1" size="small" label="组件路径">
                        <el-input v-model="menu.url"></el-input>
                    </el-form-item>

                    <el-form-item prop="code" size="small" label="权限字段">
                        <el-input v-model="menu.code"></el-input>
                    </el-form-item>

                    <el-form-item size="small" label="菜单图标">
                        <my-icon @selecticon="setIcon" ref="child"></my-icon>
                    </el-form-item>
                    
                    <el-form-item size="small" label="菜单序号">
                        <el-input v-model="menu.orderNum"></el-input>
                    </el-form-item>
                </el-form>
            </div>
        </system-dialog>

当点击所属菜单输入框时,会弹出一个新的对话框

再次定义一个对话框:用于显示树形结构的数据:

返回值中定义好属性:

menuDialog:{
                title: "",
                width: 630,
                height: 270,
                visible: false,
            },
            //菜单属性
            menu: {
                id: "",
                type: "",
                parentId: "",
                parentName: "",
                label: "",
                icon: "",
                name: "",
                path: "",
                url: "",
                code: "",
                orderNum: "",
            },

其中使用了插槽插入了一个需要选择的树形结构:

<!--点击输入框时触发的弹窗-->
        <system-dialog
        :title="parentDialog.title"
        :width="parentDialog.width"
        :height="parentDialog.height"
        :visible="parentDialog.visible"
        @onClose="onParentClose()"
        @onConfirm="onParentConfirm()"
        >
            <div slot="content">
                <el-tree
                style="font-size: 14px"
                ref="parentTrees"
                :data="treeList"
                node-key="id"
                :props="defaultProps"
                empty-text="暂无数据"
                :show-checkbox="false"
                default-expand-all
                :highlight-current="true"
                :expand-on-click-node="false"
                @node-click="handleNodeClick"
                >
                    <!---->
                    <div class="customer-tree-node" slot-scope="{ node, data }">
                        <!--判断当前节点的子节点是否为0-->
                        <span v-if="data.children.length === 0">
                            <i class="el-icon-document"></i>
                        </span>
                        <!--绑定的这个方法,就是展开后显示-,没展开显示+  -->
                        <span v-else @click="openBtn(data)">
                            <!--判断当前节点是否是展开的--> 
                            <!--icon-class=添加自定义的图标的名字-->
                            <!--图片添加在src/icons/svg下,后缀名.svg-->
                            <svg-icon v-if="data.open" icon-class="添加+" />
                            <svg-icon v-else icon-class="删除-" />
                        </span>
                        <!--显示的文本信息 选择完成之后数据的回显-->
                        <span style="margin-left: 5px">{{ node.label }}</span>
                    </div>
                </el-tree>
            </div>

        </system-dialog>

 :data:展示数据

node-key:每个树节点用来作为唯一标识的属性

props:配置选项

empty-text:内容为空时展示的文本

show-checkbox:节点是否可以被选择

default-expand-all:是否默认展开所有节点

:highlight-current:是否高亮当前选中的节点。默认false

:expand-on-click-node:是否在点击节点时展开或收缩节点,默认true.

@node-click: 节点被点击时的回调

 定义属性:

//选择属性下拉菜单的弹框
            parentDialog: {
                title: '选择所属菜单',
                width: 280,
                height: 450,
                visible: false
            },
            //树属性定义  绑定的props。其中的label的属性值是显示的名称
            defaultProps: {
                children: 'children',
                label: 'label'
            },
            treeList: [], //所属菜单列表

 给点击事件进行赋值(给表单属性赋值)

//点击树结构时触发
        handleNodeClick(data){
            this.menu.parentId = data.id
            this.menu.parentName = data.label
        },

 点击图标进行树结构的折叠

/**
        * 点击树节点+-号折叠展开事件
        */
        openBtn(data) {
            //修改折叠展开状态
            data.open = !data.open;
            this.$refs.parentTrees.store.nodesMap[data.id].expanded = !data.open;
        },

 给输入框的方法进行定义:就是给显示的数组进行赋值。

//选择所属菜单的方法  (点击输入框时触发  发送查询请求
        async selectParentMenu(){
            this.parentDialog.title="选择菜单信息"
            this.parentDialog.visible = true;
            //调用API连接后端的方法。
            let res = await menuApi.getParentList();
            if(res.success){
                this.treeList = res.data;
            }
        },

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值