实战 9 权限菜单管理

目录

1、权限菜单后端接口

2、查询权限菜单列表

2.1 设计效果图

2.2 menuList.vue

3、 新增权限菜单

3.1 新增权限菜单窗口代码

3.2 选择所属菜单代码

3.3 封装图标选择器

3.4 新增、编辑和删除权限菜单


1、权限菜单后端接口

package com.cizhu.service;import com.cizhu.entity.Permission;
import com.baomidou.mybatisplus.extension.service.IService;
import com.cizhu.vo.query.PermissionQueryVo;import java.util.List;/*** <p>*  服务类* </p>** @author cizhu* @since 2023-12-14*/
public interface IPermissionService extends IService<Permission> {/*** 根据用户ID查询菜单列表* @param userId* @return*/List<Permission> findPermissionListByUserId(Long userId);List<Permission> findPermissionList(PermissionQueryVo permissionQueryVo);boolean hasChildrenOfPermission(Long id);List<Permission> findParentPermissionList();
}
package com.cizhu.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.cizhu.entity.Permission;
import com.cizhu.mapper.PermissionMapper;
import com.cizhu.service.IPermissionService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cizhu.utils.MenuTree;
import com.cizhu.vo.query.PermissionQueryVo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;import java.util.Arrays;
import java.util.List;/*** <p>*  服务实现类* </p>** @author cizhu* @since 2023-12-14*/
@Service
@Transactional
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements IPermissionService {@Overridepublic List<Permission> findPermissionListByUserId(Long userId) {return baseMapper.findPermissionListByUserId(userId);}@Overridepublic List<Permission> findPermissionList(PermissionQueryVo permissionQueryVo) {//创建条件构造器对象QueryWrapper<Permission> queryWrapper = new QueryWrapper<Permission>();//排序queryWrapper.orderByAsc("order_num");//调用查询菜单列表的方法List<Permission> permissionList = baseMapper.selectList(queryWrapper);//生成菜单树List<Permission> menuTree = MenuTree.makeMenuTree(permissionList, 0L);//返回数据return menuTree;}@Overridepublic boolean hasChildrenOfPermission(Long id) {return false;}@Overridepublic List<Permission> findParentPermissionList() {QueryWrapper<Permission> queryWrapper = new QueryWrapper<Permission>();//只查询type为目录和菜单的数据(type=0或type=1)queryWrapper.in("type", Arrays.asList(0,1));//排序queryWrapper.orderByAsc("order_num");//查询菜单数据List<Permission> permissionList = baseMapper.selectList(queryWrapper);//构造顶级菜单信息,如果数据库中的菜单表没有数据,选择上级菜单时则显示顶级菜单Permission permission = new Permission();permission.setId(0L);permission.setParentId(-1L);permission.setLabel("顶级菜单");permissionList.add(permission);//将顶级菜单添加到集合//生成菜单数据List<Permission> menuTree = MenuTree.makeMenuTree(permissionList, -1L);//返回数据return menuTree;}}
package com.cizhu.controller;import com.cizhu.entity.Permission;
import com.cizhu.service.IPermissionService;
import com.cizhu.utils.Result;
import com.cizhu.vo.query.PermissionQueryVo;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;import javax.annotation.Resource;
import java.util.List;/*** <p>*  前端控制器* </p>** @author cizhu* @since 2023-12-14*/
@RestController
@RequestMapping("/api/permission")
public class PermissionController {@Resourceprivate IPermissionService permissionService;/*** 查询菜单列表* @param permissionQueryVo* @return*/@GetMapping("/getPermissionList")@PreAuthorize("hasAuthority('sys:menu:select')")public Result getPermissionList(PermissionQueryVo permissionQueryVo){List<Permission> resultPermissionList = permissionService.findPermissionList(permissionQueryVo);return Result.ok(resultPermissionList);}/*** 查询上级菜单列表* @return*/@GetMapping("/parent/list")public Result getParentPermissionList(){List<Permission> parentPermissionList = permissionService.findParentPermissionList();return Result.ok(parentPermissionList);}/*** 根据id查询菜单信息* @param id* @return*/@GetMapping("/{id}")public Result getMenuById(@PathVariable Long id){return Result.ok(permissionService.getById(id));}/*** 添加菜单* @param permission* @return*/@PostMapping("/addPermission")@PreAuthorize("hasAuthority('sys:menu:add')")public Result addPermission(@RequestBody Permission permission){if (permissionService.save(permission)) return Result.ok().message("菜单新增成功!");return Result.error().message("菜单新增失败!");}/*** 修改菜单* @param permission* @return*/@PutMapping("/editPermission")@PreAuthorize("hasAuthority('sys:menu:edit')")public Result editPermission(@RequestBody Permission permission){if(permissionService.updateById(permission)) return Result.ok().message("修改菜单成功!");return Result.error().message("修改菜单失败!");}/*** 根据id删除菜单* @param id* @return*/@DeleteMapping("/delete/{id}")@PreAuthorize("hasAuthority('sys:menu:delete')")public Result deletePermissionById(@PathVariable Long id){if (permissionService.removeById(id)) return Result.ok().message("删除菜单成功!");return Result.ok().message("删除菜单失败!");}/*** 检查菜单是否有子菜单* @param id* @return*/@GetMapping("/check/{id}")public Result hasChildrenOfPermission(@PathVariable Long id){if (permissionService.hasChildrenOfPermission(id)) {return Result.exist().message("该菜单下有子菜单,不能删除!");}return Result.ok();}}
package com.cizhu.entity;import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;/*** <p>* * </p>** @author cizhu* @since 2023-12-14*/
@Getter
@Setter
@TableName("sys_role_permission")
@ApiModel(value = "RolePermission对象", description = "")
public class RolePermission implements Serializable {private static final long serialVersionUID = 1L;@ApiModelProperty("角色ID")private Long roleId;@ApiModelProperty("权限ID")private Long permissionId;}
package com.cizhu.vo.query;import com.cizhu.entity.Permission;
import lombok.Data;@Data
public class PermissionQueryVo extends Permission {
}
package com.cizhu.entity;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;/*** <p>* * </p>** @author cizhu* @since 2023-12-14*/
@Getter
@Setter
@TableName("sys_permission")
@ApiModel(value = "Permission对象", description = "")
public class Permission implements Serializable {/*** 子菜单列表*/@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;private static final long serialVersionUID = 1L;@ApiModelProperty("权限编号")@TableId(value = "id", type = IdType.AUTO)private Long id;@ApiModelProperty("权限名称")private String label;@ApiModelProperty("父权限ID")private Long parentId;@ApiModelProperty("父权限名称")private String parentName;@ApiModelProperty("授权标识符")private String code;@ApiModelProperty("路由地址")private String path;@ApiModelProperty("路由名称")private String name;@ApiModelProperty("授权路径")private String url;@ApiModelProperty("权限类型(0-目录 1-菜单 2-按钮)")private Integer type;@ApiModelProperty("图标")private String icon;@ApiModelProperty("创建时间")private Date createTime;@ApiModelProperty("修改时间")private Date updateTime;@ApiModelProperty("备注")private String remark;@ApiModelProperty("排序")private Integer orderNum;@ApiModelProperty("是否删除(0-未删除,1-已删除)")private Integer isDelete;}

2、查询权限菜单列表

2.1 设计效果图

2.2 menuList.vue

列表页面原型代码,编写前端api脚本和页面组件代码

<template><el-main><!-- 新增按钮 --><el-button type="success" size="small" @click="openAddWindow()" icon="el-icon-plus">新增</el-button><!-- 数据表格 --><el-table style="margin-top: 10px" :height="tableHeight" :data="menuList" row-key="id"default-expand-all :tree-props="{ children: 'children' }" :border="true" stripe><el-table-column prop="label" label="菜单名称"></el-table-column><el-table-column prop="type" label="菜单类型" align="center"><template slot-scope="scope"><el-tag v-if="scope.row.type == '0'" size="normal">目录</el-tag><el-tag type="success" v-else-if="scope.row.type == '1'" size="normal">菜单</el-tag><el-tag type="warning" v-else-if="scope.row.type == '2'" size="normal">按钮</el-tag></template></el-table-column><el-table-column prop="icon" label="图标" align="center"><template slot-scope="scope"><i :class="scope.row.icon" v-if="scope.row.icon.includes('el-icon')" ></i><svg-icon v-else :icon-class="scope.row.icon"></svg-icon></template></el-table-column><el-table-column prop="name" label="路由名称"></el-table-column><el-table-column prop="path" label="路由地址"></el-table-column><el-table-column prop="url" label="组件路径"></el-table-column><el-table-column label="操作" align="center"><template slot-scope="scope"><el-button type="primary" icon="el-icon-edit" size="small" @click="editMenu(scope.row)">编辑</el-button><el-button type="danger" size="small" icon="el-icon-delete" @click="deleteMenu(scope.row)">删除</el-button></template></el-table-column></el-table></el-main>
</template><style lang="scss" scoped></style>

 menu.js

import http from '@/utils/request'export default {/*** 查询权限菜单列表* @param params*/async getMenuList(params){return await http.get("/api/permission/list",params);},/*** 获取上级菜单* @returns*/async getParentMenuList(params) {return await http.get("/api/permission/parent/list", params)},/*** 添加菜单* @returns*/async addMenu(params){return await http.post("/api/permission/add",params)},/*** 修改菜单* @returns*/async updateMenu(params) {return await http.put("/api/permission/update", params);},/*** 检查菜单下是否存在子菜单*/async checkPermission(param){return await http.getRestApi("/api/permission/check",param);},/*** 删除菜单* @returns*/async deleteById(params) {return await http.delete("/api/permission/delete", params);}
}

1) 菜单类型,图标

2)滚动条样式

public/index.html

 ::-webkit-scrollbar{width: 5px;height: 5px;background-color: #F5F5F5;}::-webkit-scrollbar-track {box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3);border-radius: 8px;background-color: #F5F5F5;}::-webkit-scrollbar-thumb{border-radius: 8px;box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);-webkit-box-shadow: inset 0 0 6px rgba(0, 0, 0, .1);background-color: #c8c8c8;}

3、 新增权限菜单

3.1 新增权限菜单窗口代码

 <!-- 新增或编辑弹框 --><system-dialog:title="menuDialog.title":width="menuDialog.width":height="menuDialog.height":visible="menuDialog.visible"@onClose="onClose"@onConfirm="onConfirm"><div slot="content"><el-form :model="menu" ref="menuForm" :rules="rules" label-width="80px" :inline="true" size="small"><el-col :span="24"><el-form-item label="菜单类型" prop="type"><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-form-item label="所属菜单" size="small" prop="parentName"><el-input v-model="menu.parentName" :readonly="true" @click.native="selectParentMenu()" /></el-form-item><el-form-item label="菜单名称" size="small" prop="label"><el-input v-model="menu.label"></el-input></el-form-item><el-form-item label="路由名称" size="small" prop="name" v-if="menu.type == 1"><el-input v-model="menu.name"></el-input></el-form-item><el-form-item label="路由地址" size="small" prop="path" v-if="menu.type != 2"><el-input v-model="menu.path"></el-input></el-form-item><el-form-item label="组件路径" size="small" prop="url" v-if="menu.type == 1"><el-input v-model="menu.url"></el-input></el-form-item><el-form-item label="权限字段" size="small" prop="code"><el-input v-model="menu.code"></el-input></el-form-item><el-form-item label="菜单图标" size="small" ><my-icon @selecticon="setIcon" ref="child"></my-icon></el-form-item><el-form-item label="菜单序号" size="small"><el-input v-model="menu.orderNum"></el-input></el-form-item></el-form></div></system-dialog>

3.2 选择所属菜单代码

<!-- 选择所属菜单弹框 --><system-dialog:title="parentDialog.title":width="parentDialog.width":height="parentDialog.height":visible="parentDialog.visible"@onClose="onParentClose"@onConfirm="onParentConfirm"><div slot="content"><el-treestyle="font-size: 14px"ref="parentTree":data="parentMenuList"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" style="color: #8c8c8c; font-size: 18px"/></span><span v-else @click.stop="changeIcon(data)"><svg-icon v-if="data.open" icon-class="add-s"/><svg-icon v-else icon-class="sub-s"/></span><span style="margin-left: 3px">{{ node.label }}</span></div></el-tree></div></system-dialog>

3.3 封装图标选择器

utils/icons.js

export const elementIcons = ["platform-eleme", "eleme", "delete-solid", "delete",
"s-tools", "setting", "user-solid", "user", "phone", "phone-outline", "more",
"more-outline", "star-on", "star-off", "s-goods", "goods", "warning", "warningoutline", "question", "info", "remove", "circle-plus", "success", "error", "zoomin", "zoom-out", "remove-outline", "circle-plus-outline", "circle-check", "circleclose", "s-help", "help", "minus", "plus", "check", "close", "picture", "pictureoutline", "picture-outline-round", "upload", "upload2", "download", "camerasolid", "camera", "video-camera-solid", "video-camera", "message-solid", "bell",
"s-cooperation", "s-order", "s-platform", "s-fold", "s-unfold", "s-operation", "spromotion", "s-home", "s-release", "s-ticket", "s-management", "s-open", "s-shop",
"s-marketing", "s-flag", "s-comment", "s-finance", "s-claim", "s-custom", "sopportunity", "s-data", "s-check", "s-grid", "menu", "share", "d-caret", "caretleft", "caret-right", "caret-bottom", "caret-top", "bottom-left", "bottom-right",
"back", "right", "bottom", "top", "top-left", "top-right", "arrow-left", "arrowright", "arrow-down", "arrow-up", "d-arrow-left", "d-arrow-right", "video-pause",
"video-play", "refresh", "refresh-right", "refresh-left", "finished", "sort",
"sort-up", "sort-down", "rank", "loading", "view", "c-scale-to-original", "date",
"edit", "edit-outline", "folder", "folder-opened", "folder-add", "folder-remove",
"folder-delete", "folder-checked", "tickets", "document-remove", "documentdelete", "document-copy", "document-checked", "document", "document-add",
"printer", "paperclip", "takeaway-box", "search", "monitor", "attract", "mobile",
"scissors", "umbrella", "headset", "brush", "mouse", "coordinate", "magic-stick",
"reading", "data-line", "data-board", "pie-chart", "data-analysis", "collectiontag", "film", "suitcase", "suitcase-1", "receiving", "collection", "files",
"notebook-1", "notebook-2", "toilet-paper", "office-building", "school", "tablelamp", "house", "no-smoking", "smoking", "shopping-cart-full", "shopping-cart-1",
"shopping-cart-2", "shopping-bag-1", "shopping-bag-2", "sold-out", "sell",
"present", "box", "bank-card", "money", "coin", "wallet", "discount", "price-tag",
"news", "guide", "male", "female", "thumb", "cpu", "link", "connection", "open",
"turn-off", "set-up", "chat-round", "chat-line-round", "chat-square", "chat-dotround", "chat-dot-square", "chat-line-square", "message", "postcard", "position",
"turn-off-microphone", "microphone", "close-notification", "bangzhu", "time",
"odometer", "crop", "aim", "switch-button", "full-screen", "copy-document", "mic",
"stopwatch", "medal-1", "medal", "trophy", "trophy-1", "first-aid-kit",
"discover", "place", "location", "location-outline", "location-information", "addlocation", "delete-location", "map-location", "alarm-clock", "timer", "watch-1",
"watch", "lock", "unlock", "key", "service", "mobile-phone", "bicycle", "truck",
"ship", "basketball", "football", "soccer", "baseball", "wind-power", "lightrain", "lightning", "heavy-rain", "sunrise", "sunrise-1", "sunset", "sunny",
"cloudy", "partly-cloudy", "cloudy-and-sunny", "moon", "moon-night", "dish",
"dish-1", "food", "chicken", "fork-spoon", "knife-fork", "burger", "tableware",
"sugar", "dessert", "ice-cream", "hot-water", "water-cup", "coffee-cup", "colddrink", "goblet", "goblet-full", "goblet-square", "goblet-square-full",
"refrigerator", "grape", "watermelon", "cherry", "apple", "pear", "orange",
"coffee", "ice-tea", "ice-drink", "milk-tea", "potato-strips", "lollipop", "icecream-square", "ice-cream-round"].map(s => "el-icon-" + s);
    /*** 切换图标* @param data*/changeIcon(data) {data.ope = !data.openthis.$refs.parentTree.store.nodesMap[data.id].expanded = !data.open},//给icon绑定的点击事件setIcon(icon) {this.menu.icon = icon;},

 

<template><div class="chooseIcons"><el-popover placement="bottom" width="450" trigger="click"><span slot="reference" style="display: inline-block;width: 200px;height: 33px;line-height: 33px;"><i :class="userChooseIcon"></i>{{ userChooseIcon }}</span><div class="iconList"><i v-for="item in iconList" :key="item" :class="item" @click="setIcon(item)" style="font-size: 20px"></i></div></el-popover></div>
</template>
<script>
//导入自定义的icon图标库
import { elementIcons } from "@/utils/icons";export default {name: 'MyIcon',data(){return{userChooseIcon:"",//用户选中的图标iconList:[],//图标列表}},created() {//获取图标列表this.getIconList();},methods:{/*** 获取图标列表*/getIconList(){this.iconList = elementIcons;},//给icon绑定的点击事件setIcon(icon) {//将i的样式设为选中的样式el-icon-xxxthis.userChooseIcon = icon;//将选中的图标传递给父组件this.$emit("selecticon",icon)},}
}
</script><style scoped lang="scss">
.iconList {width: 400px;height: 300px;overflow-y: scroll;overflow-x: hidden;display: flex;justify-content: space-around;flex-wrap: wrap;i {display: inline-block;width: 60px;height: 45px;color: #000000;font-size: 20px;border: 1px solid #e6e6e6;border-radius: 4px;cursor: pointer;text-align: center;line-height: 45px;margin: 5px;&:hover {color: orange;border-color:orange;}}
}.chooseIcons{width: 175px;background-color: #FFFFFF;background-image: none;border-radius: 4px;border: 1px solid #DCDFE6;box-sizing: border-box;color: #606266;display: inline-block;font-size: inherit;height: 33px;line-height: 25px;outline: none;padding: 0 15px;transition: border-color 0.2s cubic-bezier(0.645, 0.045, 0.355, 1);
}
</style>

3.4 新增、编辑和删除权限菜单

<template><el-main><!-- 新增按钮 --><el-button type="success" size="small" @click="openAddWindow()" icon="el-icon-plus">新增</el-button><!-- 数据表格 --><el-table style="margin-top: 10px" :height="tableHeight" :data="menuList" row-key="id"default-expand-all :tree-props="{ children: 'children' }" :border="true" stripe><el-table-column prop="label" label="菜单名称"></el-table-column><el-table-column prop="type" label="菜单类型" align="center"><template slot-scope="scope"><el-tag v-if="scope.row.type == '0'" size="normal">目录</el-tag><el-tag type="success" v-else-if="scope.row.type == '1'" size="normal">菜单</el-tag><el-tag type="warning" v-else-if="scope.row.type == '2'" size="normal">按钮</el-tag></template></el-table-column><el-table-column prop="icon" label="图标" align="center"><template slot-scope="scope"><i :class="scope.row.icon" v-if="scope.row.icon.includes('el-icon')" ></i><svg-icon v-else :icon-class="scope.row.icon"></svg-icon></template></el-table-column><el-table-column prop="name" label="路由名称"></el-table-column><el-table-column prop="path" label="路由地址"></el-table-column><el-table-column prop="url" label="组件路径"></el-table-column><el-table-column label="操作" align="center"><template slot-scope="scope"><el-button type="primary" icon="el-icon-edit" size="small" @click="editMenu(scope.row)">编辑</el-button><el-button type="danger" size="small" icon="el-icon-delete" @click="deleteMenu(scope.row)">删除</el-button></template></el-table-column></el-table><!-- 新增或编辑弹框 --><system-dialog:title="menuDialog.title":width="menuDialog.width":height="menuDialog.height":visible="menuDialog.visible"@onClose="onClose"@onConfirm="onConfirm"><div slot="content"><el-form :model="menu" ref="menuForm" :rules="rules" label-width="80px" :inline="true" size="small"><el-col :span="24"><el-form-item label="菜单类型" prop="type"><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-form-item label="所属菜单" size="small" prop="parentName"><el-input v-model="menu.parentName" :readonly="true" @click.native="selectParentMenu()" /></el-form-item><el-form-item label="菜单名称" size="small" prop="label"><el-input v-model="menu.label"></el-input></el-form-item><el-form-item label="路由名称" size="small" prop="name" v-if="menu.type == 1"><el-input v-model="menu.name"></el-input></el-form-item><el-form-item label="路由地址" size="small" prop="path" v-if="menu.type != 2"><el-input v-model="menu.path"></el-input></el-form-item><el-form-item label="组件路径" size="small" prop="url" v-if="menu.type == 1"><el-input v-model="menu.url"></el-input></el-form-item><el-form-item label="权限字段" size="small" prop="code"><el-input v-model="menu.code"></el-input></el-form-item><el-form-item label="菜单图标" size="small" ><my-icon @selecticon="setIcon" ref="child"></my-icon></el-form-item><el-form-item label="菜单序号" size="small"><el-input v-model="menu.orderNum"></el-input></el-form-item></el-form></div></system-dialog><!-- 选择所属菜单弹框 --><system-dialog:title="parentDialog.title":width="parentDialog.width":height="parentDialog.height":visible="parentDialog.visible"@onClose="onParentClose"@onConfirm="onParentConfirm"><div slot="content"><el-treestyle="font-size: 14px"ref="parentTree":data="parentMenuList"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" style="color: #8c8c8c; font-size: 18px"/></span><span v-else @click.stop="changeIcon(data)"><svg-icon v-if="data.open" icon-class="add-s"/><svg-icon v-else icon-class="sub-s"/></span><span style="margin-left: 3px">{{ node.label }}</span></div></el-tree></div></system-dialog></el-main>
</template><script>
// 导入menu脚本文件
import menuApi from '@/api/menu'
//导入自定义图标组件
import MyIcon from '@/components/system/MyIcon.vue'
// 导入对话框组件
import SystemDialog from '@/components/system/SystemDialog.vue'export default {name: 'menuList',//注册组件components:{ SystemDialog, MyIcon },data() {return {//新增或编辑弹框属性menuDialog: {title: "",width: 630,height: 270,visible: false,},//菜单属性menu: {id: "",type: "",parentId: "",parentName: "",label: "",icon: "",name: "",path: "",url: "",code: "",orderNum: "",},rules: {type: [{ required: true, trigger: "change", message: "请选择菜单类型" }],parentName: [{ required: true, trigger: "change", message: "请选择所属菜单"}],label: [{ required: true, trigger: "blur", message: "请输入菜单名称" }],name: [{ required: true, trigger: "blur", message: "请输入路由名称" }],path: [{ required: true, trigger: "blur", message: "请输入路由路径" }],url: [{ required: true, trigger: "blur", message: "请输入组件路径" }],code: [{ required: true, trigger: "blur", message: "请输入权限字段" }],},parentDialog: {title: '选择所属菜单',width: 280,height: 450,visible: false},//树属性定义defaultProps: {children: 'children',label: 'label'},menuList: [],       //菜单列表tableHeight: 0,     //表格高度parentMenuList: [], //所属菜单列表}},mounted() {this.$nextTick(() => {this.tableHeight = window.innerHeight - 180})},//初始化时调用created(){//调用查询菜单列表的方法this.search()},mounted() {this.$nextTick(() => {this.tableHeight = window.innerHeight - 180})},methods:{/*** 选择所属菜单*/async selectParentMenu() {//显示窗口this.parentDialog.visible = true;//发送查询请求let res = await menuApi.getParentMenuList();//判断是否成功if (res.success) {//赋值this.parentMenuList = res.data;}},/*** 查询菜单列表*/async search() {//发送查询请求let res = await menuApi.getMenuList();//判断是否成功if(res.success){//赋值this.menuList = res.data;}},/*** 编辑菜单* @param row*/editMenu(row){//把当前要编辑的数据复制到数据域,给表单回显this.$objCopy(row, this.menu);//设置弹框属性this.menuDialog.title = "编辑菜单";this.menuDialog.visible = true;this.$nextTick(() => {this.$refs["child"].userChooseIcon = row.icon;//菜单图标回显})},/*** 删除菜单* @param row*/async deleteMenu(row){//判断是否存在子菜单let result = await menuApi.checkPermission({ id: row.id });//判断是否可以删除if (!result.success) {//提示不能删除this.$message.warning(result.message);} else {//确认是否删除let confirm =await this.$myconfirm("确定要删除该数据吗?");if (confirm) {//发送删除请求let res = await menuApi.deleteById({ id: row.id });//判断是否成功if (res.success) {//成功提示this.$message.success(res.message);//刷新this.search();} else {//失败提示this.$message.error(res.message);}}}},/*** 打开新增窗口*/openAddWindow(){this.$resetForm("menuForm", this.menu) //清空表单数据this.menuDialog.title = "新增菜单"      //设置窗口标题this.menuDialog.visible = true         //显示窗口this.$nextTick(() => {this.$refs['child'].userChooseIcon = '' // 清空菜单图标 })},/*** 选择所属菜单取消事件*/onParentClose() {this.parentDialog.visible = false //关闭窗口},/*** 选择所属菜单确认事件*/onParentConfirm() {this.parentDialog.visible = false //关闭窗口},/*** 添加和修改菜单窗口关闭事件*/onClose() {this.menuDialog.visible = false; //关闭窗口},/*** 添加和修改菜单窗口确认事件*/onConfirm() {//表单验证this.$refs.menuForm.validate(async (valid) => {if (valid) {let res = null;//判断菜单ID是否为空if (this.menu.id === "") {//发送添加请求res = await menuApi.addMenu(this.menu);} else {//发送修改请求res = await menuApi.updateMenu(this.menu);}//判断是否成功if (res.success) {this.$message.success(res.message);//刷新//this.search();window.location.reload();//关闭窗口this.menuDialog.visible = false;} else {this.$message.error(res.message);}this.menuDialog.visible = false; //关闭窗口}});},/*** 所属菜单节点点击事件*/handleNodeClick(data) {//所属父级菜单IDthis.menu.parentId = data.id;//所属父级菜单名称this.menu.parentName = data.label;},/*** 切换图标* @param data*/changeIcon(data) {data.open = !data.openthis.$refs.parentTree.store.nodesMap[data.id].expanded = !data.open},//给icon绑定的点击事件setIcon(icon) {this.menu.icon = icon;},}
}
</script>
<style lang="scss" scoped>
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/577941.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# WPF上位机开发(子窗口通知父窗口更新进度)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 这两天在编写代码的时候&#xff0c;正好遇到一个棘手的问题&#xff0c;解决之后感觉挺有意义的&#xff0c;所以先用blog记录一下&#xff0c;后…

基于flask和echarts的新冠疫情实时监控系统源码+数据库,后端基于python的flask框架,前端主要是echarts

介绍 基于flask和echarts的新冠疫情实时监控系统 软件架构 后端基于python的flask框架&#xff0c;前端主要是echarts 安装教程 下载到本地&#xff0c;在python相应环境下运行app.py,flask项目部署请自行完成 使用说明 flaskProject文件夹中 app.py是flask项目主运行文…

Android Studio解决:Connect time out问题

目录 前言 一、错误信息 二、解决方法 三、更多资源 前言 当您尝试建立网络连接时&#xff0c;如果连接的建立时间超过了预设的时间限制&#xff0c;就会出现"Connect time out"的错误提示。这通常是由于网络连接问题、服务器故障或网络延迟等原因导致的。 一、…

ARM Cortex-A学习(1):GIC(通用中断控制器)详解

文章目录 1 Cortex-A核中断1.1 处理器模式1.2 IRQ模式 2 GIC的操作2.1 CPU Interface2.2 Distributor GIC(通用中断控制器, Generic Interrupt Controller)是一种用于处理中断的硬件组件&#xff0c;它的主要功能是协调和管理系统中的中断请求&#xff0c;确保它们被正确地传递…

VD6283TX环境光传感器(1)----获取光强和色温

VD6283TX环境光传感器.1--获取光强和色温 概述视频教学样品申请完整代码下载主要特点硬件准备技术规格系统框图生成STM32CUBEMX串口配置IIC配置X-CUBE-ALS演示结果光强测试表 概述 为了充分利用VD6283TX传感器的特性和功能&#xff0c;本章节重点介绍了如何捕获光强度和相关色…

QT foreach

原型&#xff1a;foreach(variable, container) container&#xff1a;容器&#xff0c;即被遍历的对象 variable&#xff1a;当前元素&#xff0c;即遍历container过程中&#xff0c;当前的那个元素 代码&#xff1a; QStringList container { "1", "2&quo…

JVM 类加载子系统

1. 前言 ​ 虚拟机就是一款用来执行虚拟计算机指令的计算机软件。它相当于一台虚拟计算机。大体上&#xff0c;虚拟机分为系统虚拟机和程序虚拟机。系统虚拟机就相当于一台物理电脑&#xff0c;里面可以安装操作系统&#xff1b;程序虚拟机是为了执行单个计算机程序而设计出来…

Linux文件编程

目录 1、Linux系统提供的文件编程API 1.1打开文件&#xff1a;open 1.2创建文件creat函数 1.3写入文件write函数 1.4读取文件read函数 1.5文件光标位置lseek函数 2、另外一组文件编程API 2.1文件打开函数fopen 2.2读文件函数fread 2.3写文件函数fwrite 2.4文件光标位…

vscode中使用GitHub Copilot Chat

文章目录 一、什么是Github Copilot Chat二、安装使用三、如何使用1. 聊天功能2. 内联功能 一、什么是Github Copilot Chat GitHub Copilot Chat 由 OpenAI 的 GPT-4 大型多模态模型提供支持&#xff0c;能带来更准确的代码建议、解释和指导。GitHub Copilot Chat 的内联功能可…

计算机毕业设计 基于SpringBoot的高校宣讲会管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

关于Python里xlwings库对Excel表格的操作(十九)

这篇小笔记主要记录如何【取消合并单元格】。 前面的小笔记已整理成目录&#xff0c;可点链接去目录寻找所需更方便。 【目录部分内容如下】【点击此处可进入目录】 &#xff08;1&#xff09;如何安装导入xlwings库&#xff1b; &#xff08;2&#xff09;如何在Wps下使用xlwi…

vscode括号颜色突然变成白色的了,怎么解决

更新版本后发现vscode的各种括号都变成了白色&#xff0c;由于分色括号已经使用习惯&#xff0c;突然变成白色非常不舒服&#xff0c;尝试多次后&#xff0c;为大家提供一下几种解决方式&#xff0c;希望能帮到同样受到此种困惑的你&#xff1a; 第一种&#xff1a; 首先打开…

WebGL开发建筑和设计教育应用

使用 WebGL 开发建筑和设计教育应用可以为学生提供沉浸式的三维体验&#xff0c;使他们能够在虚拟环境中探索建筑结构、材料和设计理念。以下是开发建筑和设计教育应用的一般步骤&#xff0c;希望对大家有所帮助。北京木奇移动技术有限公司&#xff0c;专业的软件外包开发公司&…

计算机视觉基础(13)——深度估计

前言 本节是计算机视觉的最后一节&#xff0c;我们将学习深度估计。从深度的概念和度量入手&#xff0c;依次学习单目深度估计和双目/多目深度估计&#xff0c;需要知道深度估计的经典方法&#xff0c;掌握深度估计的评价标准&#xff0c;注意结合对极几何进行分析和思考。 一、…

【LeetCode刷题笔记】动态规划(四)

背包问题 0-1 背包问题 有一个背包,它的容量为 C现在有 n 种不同的物品,他们的编号分别是 0...n-1。每一种物品只有一个。在这 n 种物品中,第 i 个物品的重量是 w[i],它的价值为 v[i]问题是:可以向这个背包中放哪些物品,使得在不超过背包容量的基础上,背包中物品的总价…

【SpringCloud笔记】(10)消息总线之Bus

Bus 前言 戳我了解Config 学习Config中我们遇到了一个问题&#xff1a; 当我们修改了GitHub上配置文件内容&#xff0c;微服务需要配置动态刷新并且需要手动向客户端发送post请求刷新微服务之后才能获取到GitHub修改过后的内容 假如有多个微服务客户端3355/3366/3377…等等…

Android 手机对于Arduino蓝牙控制解决方案

1、Android系统概述 ​ Android 系统是 Google 公司基于 Linux 内核开发的移动端操作系统,适用于智能手机智能手表平板电脑等设备&#xff0c;最新的版本为 7.1。Android系统具有免费开源的优势,任何企业与个人都可以查阅公开的 API 文档&#xff0c;并在自己开发的应用中通过调…

xlua源码分析(四) lua访问C#的值类型

xlua源码分析&#xff08;四&#xff09; lua访问C#的值类型 上一节我们主要探讨了C#是如何使用interface和delegate访问lua层的table和function的&#xff0c;本节我们跟着Examples 05_NoGc&#xff0c;来看看xlua是如何实现lua层无gc访问C#的值类型的。 首先例子中用到的lua…

List那些坑

很多文章都介绍过这些坑&#xff0c;本文做个记录&#xff0c;并提供解决方案。 1.Arrays.asList的坑 1.1现象 情况1&#xff1a;通过Arrays.asList方法生成的List数据不支持添加操作 使用Arrays.asList方法生成的List数据&#xff0c;不能对其进行删除或者添加操作。代码示例…

【MySQL】数据库之存储引擎

目录 一、什么是存储引擎 MySQL 整个查询执行过程&#xff0c;即MySQL的工作原理&#xff1f; 二、MyISAM 与 InnoDB 的区别&#xff1f; 三、如何查看当前表的存储引擎&#xff1f; 1.查看当前的存储引擎 2.查看数据库支持哪些存储引擎 四、如何设置存储引擎&#xff1f;…