springboot + Vue前后端项目(第十六记)

项目实战第十六记

  • 写在前面
  • 1 第一个bug
    • 1.1 完整的Role.vue
  • 2 第二个bug
    • 2.1 修改路由router下面的index.js
  • 总结
  • 写在最后

写在前面

  • 发现bug,修复bug

1 第一个bug

分配菜单时未加入父id,导致分配菜单失效

<!-- :check-strictly="true"   默认是false,父子关联;true 是不关联需手动勾选父选择框
-->
<el-tree:props="props":data="menuData"show-checkboxnode-key="id"ref="tree":check-strictly="true":default-expanded-keys="expends":default-checked-keys="checks"><span class="custom-tree-node" slot-scope="{ node, data }"><span><i :class="data.icon"></i> {{ data.name }}</span></span></el-tree>

1.1 完整的Role.vue

<template><div><!-- 设计的查询 --><div style="margin: 10px 0"><el-inputstyle="width: 200px"placeholder="请输入名称"suffix-icon="el-icon-search"v-model="name"/><el-button type="primary" icon="el-icon-search" class="ml-5" @click="getList">搜索</el-button><el-button type="warning" icon="el-icon-reset" @click="resetQuery">重置</el-button></div><div style="margin: 10px 0"><el-button type="primary" @click="handleAdd">新增 <i class="el-icon-circle-plus-outline"></i></el-button><el-button type="warning" plain icon="el-icon-edit" size="mini" :disabled="single" @click="handleUpdate">修改</el-button><el-button type="danger" :disabled="multiple" @click="handleDelete">删除 <i class="el-icon-remove-outline"></i></el-button></div><el-table :data="tableData" @selection-change="handleSelectionChange"><el-table-column type="selection" width="55" /><el-table-column prop="id" label="角色ID" width="80"></el-table-column><el-table-column prop="roleKey" label="唯一标识"></el-table-column><el-table-column prop="name" label="角色名称"></el-table-column><el-table-column prop="description" label="角色描述"></el-table-column><el-table-column label="操作"><template v-slot="scope"><el-buttontype="info"icon="el-icon-menu"@click="openMenuAllocDialog(scope.row.id)">分配菜单</el-button><el-button type="success" @click="handleUpdate(scope.row)">编辑 <i class="el-icon-edit"></i></el-button><el-button type="danger" @click="handleDelete(scope.row)">删除 <i class="el-icon-remove-outline"></i></el-button></template></el-table-column></el-table><div style="padding: 10px 0"><el-pagination@size-change="handleSizeChange"@current-change="handleCurrentChange":current-page="pageNum":page-sizes="[5, 10, 15]":page-size="pageSize"layout="total, sizes, prev, pager, next, jumper":total="total"></el-pagination></div><!-- 角色添加对话框 --><el-dialog title="角色信息" :visible.sync="dialogFormVisible" width="30%"><el-form :model="form"><el-form-item label="唯一标识" :label-width="formLabelWidth"><el-input v-model="form.roleKey" autocomplete="off"></el-input></el-form-item><el-form-item label="角色名称" :label-width="formLabelWidth"><el-input v-model="form.name" autocomplete="off"></el-input></el-form-item><el-form-item label="描述" :label-width="formLabelWidth"><el-input v-model="form.description" autocomplete="off"></el-input></el-form-item></el-form><div slot="footer" class="dialog-footer"><el-button @click="dialogFormVisible = false">取 消</el-button><el-button type="primary" @click="save">确 定</el-button></div></el-dialog><!-- 分配菜单 --><el-dialog title="菜单分配" :visible.sync="menuDialogVis" width="30%"><el-tree:props="props":data="menuData"show-checkboxnode-key="id"ref="tree":check-strictly="true":default-expanded-keys="expends":default-checked-keys="checks"><span class="custom-tree-node" slot-scope="{ node, data }"><span><i :class="data.icon"></i> {{ data.name }}</span></span></el-tree><div slot="footer" class="dialog-footer"><el-button @click="menuDialogVis = false">取 消</el-button><el-button type="primary" @click="saveRoleMenu">确 定</el-button></div></el-dialog></div>
</template>
<script>
export default {name: "Role",data() {return {name: "",tableData: [],total: 0,pageSize: 5,pageNum: 1,dialogFormVisible: false,menuDialogVis: false,formLabelWidth: "80px",ids: [],// 非单个禁用single: true,// 非多个禁用multiple: true,form: {id: "",name: "",description: "",},menuData: [],props: {label: 'name',},expends: [],checks: [],roleId: undefined,};},//页面一创建成功created() {//请求分页查询数据this.getList();},methods: {getList() {this.request.get("/role/page", {params: {pageNum: this.pageNum,pageSize: this.pageSize,name: this.name,},}).then((res) => {if(res.code === "200"){this.tableData = res.data.records;this.total = res.data.total;}else{this.$message.error(res.msg);}});},//分配菜单openMenuAllocDialog(id){this.menuDialogVis = true;// 角色id赋值this.roleId = id;//请求菜单数据this.request.get("/menu",{params: {name: ""}}).then(res => {this.menuData = res.data;//展开菜单数据this.expends = this.menuData.map(v => v.id);})// 展开已拥有的菜单this.request.get("/role/roleMenu/"+id).then(res => {this.checks = res.data;})},//保存角色下的菜单saveRoleMenu(){console.log('======',this.$refs.tree.getCheckedKeys());this.request.post("/role/roleMenu/"+ this.roleId, this.$refs.tree.getCheckedKeys()).then(res => {if(res.code === "200"){this.$message.success("保存成功");this.menuDialogVis = false;}else {this.$message.error("保存失败");}})},// 重置按钮resetQuery(){this.username = "";this.pageNum = 1;this.pageSize = 5;this.getList();},handleSizeChange(val) {this.pageSize = val;},handleCurrentChange(val) {this.pageNum = val;this.getList();},// 多选框选中数据handleSelectionChange(selection) {this.ids = selection.map(item => item.id);this.single = selection.length != 1;this.multiple = !selection.length;},// 新增handleAdd(){this.dialogFormVisible = true;this.form = {};},save(){this.request.post("/role",this.form).then(res => {if(res.code === "200" || res.code === 200){this.$message.success("操作成功")}else {this.$message.error("操作失败")}this.dialogFormVisible = false;this.getList();})},// 修改handleUpdate(row){// 表单置空this.reset();// 重新查询数据const roleId = row.id || this.ids;this.request.get('/role/'+roleId).then(response => {this.form = response.data;this.dialogFormVisible = true;});},reset(){this.form.roleKey = undefined;this.form.name = undefined;this.form.description = undefined;},// 删除handleDelete(row){let _this = this;const roleIds = row.id || this.ids;this.$confirm('是否确认删除角色编号为"' + roleIds + '"的数据项?', '删除角色', {confirmButtonText: '确定',cancelButtonText: '取消',type: 'warning'}).then(() => {_this.request.delete("/role/"+roleIds).then(res=>{if(res.code === "200" || res.code === 200){_this.$message.success("删除成功")}else {_this.$message.error("删除失败")}this.getList();})}).catch(() => {});}},
};
</script>

2 第二个bug

启动成功前端访问地址,弹出的是404页面不是登录页面
在这里插入图片描述

2.1 修改路由router下面的index.js

修改的地方

// 第一处
{path: '/404',name: '404',component: () => import('../views/404.vue')}// 第二处
// 路由守卫
router.beforeEach((to, from, next) => {// localStorage.setItem('currentPathName',to.name);   // 设置当前的路由名称,为了在Header组件中去使用// store.commit('setPath')    // 触发store的数据更新// 未找到路由情况if(!to.matched.length){const storeMenus = localStorage.getItem("menus");if(storeMenus){   // 有菜单没有找到路由,跳转至 404页面next("/404")}else {    // // 没有菜单,直接跳转至登录页next("/login")}}next()   // 放行路由
})

完整的代码

import Vue from 'vue'
import VueRouter from 'vue-router'
import Manage from '../views/Manage.vue'
import store from "@/store";Vue.use(VueRouter)
//定义一个路由对象数组
const routes = [{path: '/login',name: '登录',component: () => import('../views/Login.vue')},{path: '/register',name: '注册',component: () => import('../views/Register.vue')},{path: '/404',name: '404',component: () => import('../views/404.vue')}]//使用路由对象数组创建路由实例,供main.js引用
const router = new VueRouter({mode: 'history',base: process.env.BASE_URL,routes
})// 注意:刷新页面会导致页面路由重置
export const setRoutes = () => {const storeMenus = localStorage.getItem("menus");if (storeMenus) {// 获取当前的路由对象名称数组const currentRouteNames = router.getRoutes().map(v => v.name)if (!currentRouteNames.includes('Manage')) {// 拼装动态路由const manageRoute = { path: '/', name: 'Manage', component: () => import('../views/Manage.vue'), redirect: "/home", children: [{ path: 'person', name: '个人信息', component: () => import('../views/Person.vue')},// { path: 'password', name: '修改密码', component: () => import('../views/Password.vue')}] }const menus = JSON.parse(storeMenus)menus.forEach(item => {if (item.path) {  // 当且仅当path不为空的时候才去设置路由let itemMenu = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.pagePath + '.vue'),meta: { title: item.name }}manageRoute.children.push(itemMenu)} else if(item.children.length) {item.children.forEach(item => {if (item.path) {let itemMenu = { path: item.path.replace("/", ""), name: item.name, component: () => import('../views/' + item.pagePath + '.vue'),meta: { title: item.name }}manageRoute.children.push(itemMenu)}})}})// 动态添加到现在的路由对象中去router.addRoute(manageRoute)}}
}// 重置我就再set一次路由
setRoutes()// 路由守卫
router.beforeEach((to, from, next) => {// localStorage.setItem('currentPathName',to.name);   // 设置当前的路由名称,为了在Header组件中去使用// store.commit('setPath')    // 触发store的数据更新// 未找到路由情况if(!to.matched.length){const storeMenus = localStorage.getItem("menus");if(storeMenus){   // 有菜单没有找到路由,跳转至 404页面next("/404")}else {    // // 没有菜单,直接跳转至登录页next("/login")}}// 其他情况next()   // 放行路由
})export default router

总结

  • 动态菜单完结,基本项目也快接近尾声。

写在最后

如果此文对您有所帮助,请帅戈靓女们务必不要吝啬你们的Zan,感谢!!不懂的可以在评论区评论,有空会及时回复。
文章会一直更新

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

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

相关文章

什么是期权(Options)?以实际例子理解看涨期权(Call)和看跌期权(Put)

什么是期权&#xff1f; 中文版 期权的详细介绍 期权&#xff08;Option&#xff09;是一种金融衍生工具&#xff0c;它赋予持有人在特定时间以预定价格买入或卖出标的资产&#xff08;如股票、债券、商品等&#xff09;的权利&#xff0c;但不负有必须买入或卖出的义务。期…

图的应用之最小生成树

大纲 生成树介绍 特点 但n个 种类 最小生成树 应用 构造算法 MST性质 Prim算法 依次选择与顶点相邻的不会构成回路的最小边对应的顶点 Kruskal算法 依次选不会构成环的最小边 区别 Prim算法有n个顶点进行选择&#xff0c;每个顶点有n个选择&#xff0c;复杂度为O(n*n) K…

C51学习归纳13 --- AD/DA转换

AD/DA转换实现了计算机和模拟信号的连接&#xff0c;扩展了计算机的应用场景&#xff0c;为模拟信号数字化提供了底层支持。 AD转换通常是多个输入通道&#xff0c;使用多路选择器连接到AD开关&#xff0c;实现AD多路复用的目的&#xff0c;提高利用率。 AD/DA转换可以使用串口…

Java创建线程的方式

继承Thread类 这是创建线程的基本方式之一。你需要创建一个新的类&#xff0c;该类继承自Thread类&#xff0c;并重写run()方法。然后&#xff0c;你可以创建这个类的一个实例并调用它的start()方法来启动新线程。 public class MyThread extends Thread { Override public vo…

Ubuntu 移除netplan

Ubuntu 移除netplan 鉴于netplan现在还不成熟&#xff0c;桌面版还是NetworkManager的天下&#xff0c;故移除之。 云服务器用netplan的多(深度学习租卡一般docker不用考虑) 仅限于你能物理上直接使用Ubuntu&#xff0c;云服务器谨慎操作&#xff01;&#xff01;&#xff01…

我的创作纪念日(1825天)

Ⅰ、机缘 1. 记得是大一、大二的时候就听学校的大牛说&#xff0c;可以通过写 CSDN 博客&#xff0c;来提升自己的代码和逻辑能力&#xff0c;虽然即将到了写作的第六个年头&#xff0c;但感觉这句话依旧受用; 2、今年一整年的创作都没有停止&#xff0c;本年度几乎是每周都来…

UniApp或微信小程序中scroll-view组件使用show-scrollbar在真机Android或IOS中隐藏不了滚动条的解决办法

show-scrollbar 属性 不论是使用 变量 还是直接使用 布尔值或者直接使用 css 都是在 ios、Android 上是都没有效果。。 真机中还是出现滚动条 解决办法 添加下面CSS ::-webkit-scrollbar {display: none;width: 0 !important;height: 0 !important;-webkit-appearance: no…

盛世古董乱世金-数据库稳定到底好不好?

是不是觉得这个还用问&#xff1f; 是的要问。因为这个还是一个有争议的问题。但是争议双方都没有错。这就像辩论&#xff0c;有正反双方。大家都说的有道理&#xff0c;但是很难说谁对谁错。 正方观点&#xff1a;数据库稳定好 其实这个是用户的观点&#xff0c;应用开发人…

17个关键方法指南,保护您的web站点安全!

了解如何让您的web应用程序或网站安全&#xff0c;对于网站所有者来说至关重要。以下是一些关键步骤&#xff0c;可以帮助您保护网站免受攻击和数据泄露。 1.使用公钥加密技术 当数据以明文形式传输时&#xff0c;它容易受到中间人 &#xff08;MitM&#xff09; 攻击。这意味…

北航第六次数据结构与程序设计作业(查找与排序)选填题

一、 顺序查找的平均查找长度ASL&#xff08;1 2 …… n&#xff09;/ n (n 1&#xff09;/ 2 二、 这半查找法的平均查找次数和判定树的深度有关系。若查找一个不存在的元素&#xff0c;说明进行了深度次比较。 注意&#xff0c;判定树不是满二叉树&#xff0c;因此深…

安卓网络通信(多线程、HTTP访问、图片加载、即时通信)

本章介绍App开发常用的以下网络通信技术&#xff0c;主要包括&#xff1a;如何以官方推荐的方式使用多线程技术&#xff0c;如何通过okhttp实现常见的HTTP接口访问操作&#xff0c;如何使用Dlide框架加载网络图片&#xff0c;如何分别运用SocketIO和WebSocket实现及时通信功能等…

HTTP协议 快速入门

http概述 无状态性&#xff1a;HTTP是一个无状态协议&#xff0c;这意味着服务器不会在请求之间保存任何会话信息。每个请求都是独立的&#xff0c;服务器不会记住之前的请求。 请求-响应模型&#xff1a;HTTP通信是基于客户端发送请求和服务器返回响应的模型。客户端&#xf…

程序员入职一家新的公司的注意事项

1.心态 我把心态放在了第一位&#xff0c;是因为&#xff0c;良好的心态是成功的关键&#xff0c;刚入职一家公司&#xff0c;领导给你一个老破旧的项目&#xff0c;不要着急&#xff0c;你能把项目中的问题很好的解决了就是你的本事&#xff0c;我碰到过很多这样的情况&#…

Spark常见的可以优化的点

Shuffle 复用 # 1.以下操作会复用的shuffle结果&#xff0c;只会读一遍数据源 val rdd1 sc.textFile("hdfs://zjyprc-hadoop/tmp/hive-site.xml").flatMap(_.split(" ")).map(x > (x,1)).reduceByKey(_ _).filter(_._2 > 1) rdd1.count() rdd1.fil…

华为od-C卷200分题目2 - 找城市

华为od-C卷200分题目2 - 找城市 题目描述 一个城市规划问题&#xff0c;一个地图有很多城市&#xff0c;两个城市之间只有一种路径&#xff0c;切断通往一 个城市i的所有路径之后&#xff0c;其他的城市形成了独立的城市群&#xff0c;这些城市群里最大的城 市数量&#xff0…

JavaFX 场景

JavaFX场景对象是 JavaFX 场景图的根。换句话说&#xff0c;JavaFX 场景包含其中的所有可视 JavaFX GUI 组件。JavaFX 场景由类表示 javafx.scene.Scene。必须在JavaFX StageScene上设置对象 才能可见。在本 JavaFX教程中&#xff0c;我将向您展示如何创建 对象并向其添加 GUI …

什么是中断?STM32F407中断处理

什么是中断&#xff1f; 中断&#xff08;Interrupt&#xff09;是一种处理器处理异步事件的方法。当某个事件&#xff08;如外部设备的信号、定时器溢出等&#xff09;发生时&#xff0c;处理器可以暂停当前正在执行的任务&#xff0c;去处理这个事件&#xff0c;然后再返回继…

会声会影色彩校正在哪里 会声会影色彩素材栏在哪 会声会影中文免费版下载

会声会影是一款功能强大的视频编辑软件&#xff0c;它可以帮助用户轻松地编辑和制作视频。在进行视频编辑时&#xff0c;色彩校正是一个重要的步骤&#xff0c;它可以调整视频的色调、亮度和对比度等参数&#xff0c;使视频更加生动和鲜明。在会声会影中&#xff0c;色彩校正功…

使用shell脚本在Linux中管理Java应用程序

文章目录 前言一、目录结构二、脚本实现1. 脚本内容2. 使用说明2.1 配置脚本2.2 脚本部署2.3 操作你的Java应用 总结 前言 在日常开发和运维工作中&#xff0c;管理基于Java的应用程序是一项基础且频繁的任务。本文将通过一个示例脚本&#xff0c;展示如何利用Shell脚本简化这…

【Python/Pytorch - 网络模型】-- TV Loss损失函数

文章目录 文章目录 00 写在前面01 基于Pytorch版本的TV Loss代码02 论文下载 00 写在前面 在医学图像重建过程中&#xff0c;经常在代价方程中加入TV 正则项&#xff0c;该正则项作为去噪项&#xff0c;对于重建可以起到很大帮助作用。但是对于一些纹理细节要求较高的任务&am…