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

发布于:2024-06-16 ⋅ 阅读:(22) ⋅ 点赞:(0)

写在前面

  • 发现bug,修复bug

1 第一个bug

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

<!-- 
    :check-strictly="true"   默认是false,父子关联;true 是不关联
    需手动勾选父选择框
-->
<el-tree
          :props="props"
          :data="menuData"
          show-checkbox
          node-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-input
          style="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-button
              type="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-checkbox
          node-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,感谢!!不懂的可以在评论区评论,有空会及时回复。
文章会一直更新


网站公告

今日签到

点亮在社区的每一天
去签到