【前端——项目实战-权限管理系统】:动态路由菜单、查询部门列表、新增部门

发布于:2023-01-11 ⋅ 阅读:(670) ⋅ 点赞:(0)

一、动态路由菜单

1.动态获取菜单数据

api/user.js中添加getMenuList()方法

/**
 * 获取菜单数据
 */
 export async function getMenuList(){
  return await http.get("/api/sysUser/getMenuList")
}

src/store/modules/permission.js

const actions = {
  /**
   * 动态生成路由
   * @returns 
   */
  generateRoutes({ commit }, roles) {
    return new Promise((resolve,reject) => {
      getMenuList().then(res=>{
        let accessedRoutes//存放对应权限的路由信息
        //如果状态码为200,则表示成功
      if (res.code===200) {
        accessedRoutes = filterAsyncRoutes(res.data,roles);
      } 
      //将路由信息保存到store中
      commit('SET_ROUTES', accessedRoutes)
      resolve(accessedRoutes)
    }).catch(error=>{
         reject(error)
    })
      })
      
  }
}

2.生成动态路由

src/views下创建系统模块的文件夹及页面

 store/modules/premission.js

export function filterAsyncRoutes(routes, roles) {
  const res = []
  routes.forEach(route => {
    const tmp = { ...route }
    //判断是否有相应的权限
    if (hasPermission(roles, tmp)) {
      //获取组件
      const component=tmp.component;
      //判断该路由使用有组件
      if (route.component) {
        //判断是否有根组件
        if(component==='Layout'){
          tmp.component = Layout
      }else{
        //获取对应的具体的组件信息
      tmp.component=(resolve)=>require([`@/views${component}`],reslove)
      }
      //判断是否有子菜单
      if(tmp.children){
        tmp.children=filterAsyncRoutes(tmp.children,roles)
      }
        }      
      res.push(tmp)
    }
  })
  return res
}

二、部门管理模块

1.查询部门列表

src/views/system/department/department.vue

<template>
  <el-main>
    <!-- 查询条件 -->
    <el-form
      ref="searchForm"
      label-width="80px"
      :inline="true"
      size="small"
      >
      <el-form-item>
        <el-input palceholder="请输入部门名称"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search">查询</el-button>
        <el-button icon="el-icon-refresh-right">重置</el-button>
        <el-button type="success" icon="el-icon-plus">新增</el-button>
      </el-form-item>
    </el-form>
    <!-- 数据表格 -->
    <el-table
      :data="tableData"
      border
      stripe
      style="width:100px; margin-bottom:20px"
      row-key="id"
      default-expand-all
      :tree-props="{children:'children'}"
      >
      <el-table-column prop ="name" label="部门名称"></el-table-column>
      <el-table-column prop ="parentName" label="所属部门"></el-table-column>
      <el-table-column prop ="deptCode" label="部门编码"></el-table-column>
      <el-table-column prop ="depPhone" label="部门电话"></el-table-column>
      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <el-button
            icon="el-icon-edit-outline"
            type="primary"
            size="small"
            @click="handleEdit(scope.row)"
            >编辑
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-main>
</template>

<script>
export default {
  name:'department',
  data(){
return{
  tableDate:[]//表格数据列表
   }
  },
  methods:{
    /**
     * 编辑部门
     * @param row
     */
    handleEdit(row){

    },
    /**
     * 删除部门
     * @param row
     */
    handleDelete(row){

    }
  },
  created(){
    
  }
}
</script>
<style lang="scss" scoped >
  
</style>

src/api目录下创建department.js脚本文件

import http from '@utils/request';

export default{
  /**
   * 查询部门列表
   * @param param
   * @returns
   */
  async getDepartmentList(param){
    return await http.get("/api/department/list",param)
  }
}

src/views/system/department/department.vue

<template>
  <el-main>
    <!-- 查询条件 -->
    <el-form :model="searchModel" ref="searchForm" label-width="80px"
      :inline="true" size="small">
      <el-form-item>
        <el-input palceholder="请输入部门名称" v-model="searchModel.departmentName"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
        <el-button icon="el-icon-refresh-right" @click="resetValue()">重置</el-button>
        <el-button type="success" icon="el-icon-plus">新增</el-button>
      </el-form-item>
    </el-form>
    <!-- 数据表格 -->
    <!-- 
      data:表格数据
      border属性:表格边框
      stripe:表格斑马线
      row-key:行数据的key,用来优化Table的渲染
      default-expand-all默认展开树形表格数据
      tree-props:树形表格配置属性选型
     -->
    <el-table
      :data="tableData"
      border
      stripe
      style="width:100%; margin-bottom:20px"
      row-key="id"
      default-expand-all
      :tree-props="{children:'children'}"
      >
      <!-- prop:填写数据的属性名称 -->
      <!-- label:表格表头标题 -->
      <el-table-column prop ="name" label="部门名称"></el-table-column>
      <el-table-column prop ="parentName" label="所属部门"></el-table-column>
      <el-table-column prop ="depPhone" label="部门电话"></el-table-column>
      <el-table-column prop ="address" label="部门位置"></el-table-column>
      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <el-button
            icon="el-icon-edit-outline"
            type="primary"
            size="small"
            @click="handleEdit(scope.row)"
            >编辑
          </el-button>
          <el-button
            icon="el-icon-close"
            type="danger"
            size="small"
            @click="handleDelete(scope.row)"
            >删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
  </el-main>
</template>

<script>
import departmentApi from "@/api/department";

export default {
  name:'department',
  data(){
return{
  searchModel:{
    departmentName:""//部门名称
  },
  tableDate:[]//表格数据列表
   }
  },
  methods:{
    /**
     * 查询部门列表
     * @param row
     */
    async search(){
      //发送查询请求
      let res =await departmentApi.getDepartmentList(this.searchmodel);
      //判断是否存在数据
      if(res.success){
        //获取数据
        this.tableDate=res.data;
      }
    },
    /**
     * 重置
     */
    resetValue(){
      this.searchModel={};//清空数据
      this.search();//重新调用方法
    }
  },
    // handleEdit(row){

    // },
  //   /**
  //    * 删除部门
  //    * @param row
  //    */
  //   handleDelete(row){

  //   }
  // },
  //初始化时执行
  created(){
    //调用查询部门列表方法
    this.search();
  }
};
</script>
<style lang="scss" scoped >
  
</style>

2.新增部门

src/components下创建system目录,并且在system目录下创建SystemDialog.vue组件

<template>
  <div>
    <el-dialog
      top="5vh"
      :title="title"
      :visible.sync="visible"
      :width="width+'px'"
      :before-close="onClose"
      :close-on-click-modal="false"
    >
      <div class ="container" :style="{height:height+'px'}">
        <slot name="content>"></slot>
      </div>
      <span slot="footer" class="dialong-footer">
        <el-button @click="onClose">取 消</el-button>
        <el-button type="primary" @click="conConfirm">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  props:{
    title:{
      type:String,
      default:"标题",
    },
  visible:{
    type:Boolean,
    default:false,
  },
  width:{
    type:Number,
    default:250,
  },
  },
  data(){
    return{}
  },
  methods:{
    onClose(){
      this.$emit("onClose");
    },
    onConfirm(){
      this.$emit("onConfirm");
    }
  }
}
</script>

<style lang="scss" scoped>
.container{
  overflow-x:initial;
  overflow-y:auto;
}
.el-dialog__wrapper{
  ::v-deep .eldialog{
    border-top-left-radius:7px !important;
     border-top-right-radius:7px !important;
     .el-dialog__header{
      border-top-left-radius:7px !important;
      border-top-right-radius:7px !important;
      background-color: #1890ff;
      .el-dialog__title{
        color:#fff;
        font-size:15px;
        font-weight:700;
      }
      .el-dialog__close{
        color:#fff;
      }
     }
     .el-dialog__body{
      padding:10 px 10px !important;
     }
     .el-dialog__footer{
      border-top:1px solid #e8eaec !important;
      padding:10px !important;
     }
  }
}

</style>

src/views/system/department/department.vue

<template>
  <el-main>
    <!-- 查询条件 -->
    <el-form :model="searchModel" ref="searchForm" label-width="80px"
      :inline="true" size="small">
      <el-form-item>
        <el-input palceholder="请输入部门名称" v-model="searchModel.departmentName"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
        <el-button icon="el-icon-refresh-right" @click="resetValue()">重置</el-button>
        <el-button type="success" icon="el-icon-plus">新增</el-button>
      </el-form-item>
    </el-form>
    <!-- 数据表格 -->
    <!-- 
      data:表格数据
      border属性:表格边框
      stripe:表格斑马线
      row-key:行数据的key,用来优化Table的渲染
      default-expand-all默认展开树形表格数据
      tree-props:树形表格配置属性选型
     -->
    <el-table
      :data="tableData"
      border
      stripe
      style="width:100%; margin-bottom:20px"
      row-key="id"
      default-expand-all
      :tree-props="{children:'children'}"
      >
      <!-- prop:填写数据的属性名称 -->
      <!-- label:表格表头标题 -->
      <el-table-column prop ="name" label="部门名称"></el-table-column>
      <el-table-column prop ="parentName" label="所属部门"></el-table-column>
      <el-table-column prop ="depPhone" label="部门电话"></el-table-column>
      <el-table-column prop ="address" label="部门位置"></el-table-column>
      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <el-button
            icon="el-icon-edit-outline"
            type="primary"
            size="small"
            @click="handleEdit(scope.row)"
            >编辑
          </el-button>
          <el-button
            icon="el-icon-close"
            type="danger"
            size="small"
            @click="handleDelete(scope.row)"
            >删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 添加和编辑部门窗口 -->
    <system-dialog
      :title="deptDialog.title"
      :visible="deptDialog.visible"
      :width="deptDialog.width"
      :height="deptDialog.height"
      @onClose="onClose"
      @onConfirm="onConfirm"
    >
      <div slot="content">
        <el-form
        :model="dept"
        ref="deptFrom"
        :rules="rules"
        label-width="80px"
        :inline="true"
        size="small"
      >
        <el-form-item label="所属部门" prop="parentName">
          <el-input
            v-model="dept.parentName"
            @click.native="selectDepartment()"
            :readonly="true"
          ></el-input>
        </el-form-item>
        <el-form-item label="部门名称" prop="departmentName">
          <el-input v-model="dept.deparmentName"></el-input>
        </el-form-item>
        <el-form-item label="部门电话" >
          <el-input v-model="dept.phone"></el-input>
        </el-form-item>
       <el-form-item label="部门地址" >
          <el-input v-model="dept.address"></el-input>
        </el-form-item>
        <el-form-item label="序号" >
          <el-input v-model="dept.orderNum"></el-input>
        </el-form-item>
      </el-form>
    </div>
  </system-dialog>
  </el-main>
</template>

<script>
import departmentApi from "@/api/department";
//导入对话框组件
import SystemDialog from '@/components/system/SystemDialog.vue'

export default {
  name:'department',
  //注册组件
  components:{
    SystemDialog
  },
  data(){
return{
  searchModel:{
    departmentName:""//部门名称
  },
  tableDate:[],//表格数据列表
  deptDialog:{
    title:"",//窗口标题
    visible:false,//是否显示窗口
    width:560,//窗口宽度
    height:170//窗口高度
  },
  //部门对象
  dept:{
    id:"",
    pid:"",//所属部门id
    parentName:"",//所属部门名称
    address:"",//地址
    phone:"",//电弧
    orderNum:"",//序号
  },
  //表单验证规则
  rules:{
parentName:[{required:true, tigger:"change", message:"请选择所属部门"}],
departmnet:[{required:true, tigger:"blur", message:"请输入部门名称"}],
  }
   }
  },
  //初始化时调用
  created(){
    //调用查询部门列表
    this.search();
  },
  methods:{

    /**
     * 查询部门列表
     * @param row
     */
    async search(){
      //发送查询请求
      let res =await departmentApi.getDepartmentList(this.searchmodel);
      //判断是否存在数据
      if(res.success){
        //获取数据
        this.tableDate=res.data;
      }
    },
    /**
     * 弹窗取消事件
     */
    onClose(){
      //关闭窗口
      thise.deptDialog.visible=false;
    },
    /**
     * 弹窗确定事件
     */
    onConfirm(){
      //表单验证
      this.$refs.deptForm.validate((valid)=>{
        //如果验证通过
        if(valid){
          //关闭窗口
          this.deptDialog.visible=false;
        }
      })
    },
    /**
     * 打开添加部门窗口
     */
    openAddWindow(){
      //设置窗口标题
      this.deptDialog.title="新增部门"
      //显示添加部门窗口
      this.deptDialog.visible=true
    },
    /**
     * 选择所属部门
     */
    selctDepartment(){},
  }
};
</script>
<style lang="scss" scoped >
  
</style>

编写选择所属部门代码

src/api/department.js

/**
   * 获取所属部门列表
   */
  async getParentTreeList(){
    return await http.get("/api/department/parent/list")
  }

src/views/system/department/department.vue

<template>
  <el-main>
    <!-- 查询条件 -->
    <el-form :model="searchModel" ref="searchForm" label-width="80px"
      :inline="true" size="small">
      <el-form-item>
        <el-input palceholder="请输入部门名称" v-model="searchModel.departmentName"></el-input>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" icon="el-icon-search" @click="search()">查询</el-button>
        <el-button icon="el-icon-refresh-right" @click="resetValue()">重置</el-button>
        <el-button type="success" icon="el-icon-plus" @click="openAddWindow()">新增</el-button>
      </el-form-item>
    </el-form>
    <!-- 数据表格 -->
    <!-- 
      data:表格数据
      border属性:表格边框
      stripe:表格斑马线
      row-key:行数据的key,用来优化Table的渲染
      default-expand-all默认展开树形表格数据
      tree-props:树形表格配置属性选型
     -->
    <el-table
      :data="tableData"
      border
      stripe
      style="width:100%; margin-bottom:20px"
      row-key="id"
      default-expand-all
      :tree-props="{children:'children'}"
      >
      <!-- prop:填写数据的属性名称 -->
      <!-- label:表格表头标题 -->
      <el-table-column prop ="name" label="部门名称"></el-table-column>
      <el-table-column prop ="parentName" label="所属部门"></el-table-column>
      <el-table-column prop ="depPhone" label="部门电话"></el-table-column>
      <el-table-column prop ="address" label="部门位置"></el-table-column>
      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <el-button
            icon="el-icon-edit-outline"
            type="primary"
            size="small"
            @click="handleEdit(scope.row)"
            >编辑
          </el-button>
          <el-button
            icon="el-icon-close"
            type="danger"
            size="small"
            @click="handleDelete(scope.row)"
            >删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 添加和编辑部门窗口 -->
    <system-dialog
      :title="deptDialog.title"
      :visible="deptDialog.visible"
      :width="deptDialog.width"
      :height="deptDialog.height"
      @onClose="onClose"
      @onConfirm="onConfirm">
      <div slot="content">
        <el-form
        :model="dept"
        ref="deptFrom"
        :rules="rules"
        label-width="80px"
        :inline="true"
        size="small"
      >
        <el-form-item label="所属部门" prop="parentName">
          <el-input
            v-model="dept.parentName"
            @click.native="openSelectDepartment()"
            :readonly="true"
          ></el-input>
        </el-form-item>
        <el-form-item label="部门名称" prop="departmentName">
          <el-input v-model="dept.deparmentName"></el-input>
        </el-form-item>
        <el-form-item label="部门电话" >
          <el-input v-model="dept.phone"></el-input>
        </el-form-item>
       <el-form-item label="部门地址" >
          <el-input v-model="dept.address"></el-input>
        </el-form-item>
        <el-form-item label="序号" >
          <el-input v-model="dept.orderNum"></el-input>
        </el-form-item>
      </el-form>
    </div>
  </system-dialog>
  <!-- 选择所属部门的窗口 -->
    <system-dialog
      :title="parentDialog.title"
      :visible="parentDialog.visible"
      :width="parentDialog.width"
      :height="parentDialog.height"
      @onClose="parentOnClose()"
      @onConfirm="parentOnConfirm()">
      <div slot="content">
        <el-tree
          ref="parentTree"
          :data="treeList"
          node-key="id"
          :props="defaultProps"
          :default-expand-all="true"
          :highlight-current="true"
          :expand-on-click-node="false"
          @node-click="handleNodeClick"
        >
          <div class="custome-tree-node" slot-scope="{node,data}">
            <!-- 判断当前节点的子节点长度是否为0 -->
            <span v-if="data.childrren.length===0">
              <i class="el-icon-document"></i>
            </span>
            <span v-else>
              <svg-icon v-if="data.open" icon-class="add-s"></svg-icon>
              <svg-icon v-else icon-class="sub-s"></svg-icon>
            </span>
            <span style="margin-left:3px">{{node.label}}</span>
          </div>
        </el-tree>
      </div>
    </system-dialog>
  </el-main>
</template>
  
<script>
import departmentApi from "@/api/department";
//导入对话框组件
import SystemDialog from '@/components/system/SystemDialog.vue'

export default {
  name:'department',
  //注册组件
  components:{
    SystemDialog
  },

  data(){
   return{
  searchModel:{
    departmentName:""//部门名称
  },
  tableDate:[],//表格数据列表
  deptDialog:{
    title:"",//窗口标题
    visible:false,//是否显示窗口
    width:560,//窗口宽度
    height:170//窗口高度
  },
  //部门对象
  dept:{
    id:"",
    departmentName:"",
    pid:"",//所属部门id
    parentName:"",//所属部门名称
    address:"",//地址
    phone:"",//电弧
    orderNum:"",//序号
  },
  //表单验证规则
  rules:{
parentName:[{required:true, tigger:"change", message:"请选择所属部门"}],
departmnet:[{required:true, tigger:"blur", message:"请输入部门名称"}],
  },
  //选择所属部门窗口属性
  parentDialog:{
    title:"选择部门",
    visible:false,
    width:300,
    height:400,
  },
  treeList:[],//树形数据
  //树形组件默认属性值
  defaultProps:{
    children:'children',
    label:'departmentName'
  }
   };
  },
  //初始化时调用
  created(){
    //调用查询部门列表
    this.search();
  },
  methods:{

    /**
     * 查询部门列表
     * @param row
     */
    async search(){
      //发送查询请求
      let res =await departmentApi.getDepartmentList(this.searchmodel);
      //判断是否存在数据
      if(res.success){
        //获取数据
        this.tableDate=res.data;
      }
    },
    /**
     * 弹窗取消事件
     */
    onClose(){
      //关闭窗口
      thise.deptDialog.visible=false;
    },
    /**
     * 弹窗确定事件
     */
    onConfirm(){
      //表单验证
      this.$refs.deptForm.validate((valid)=>{
        //如果验证通过
        if(valid){
          //关闭窗口
          this.deptDialog.visible=false;
        }
      })
    },
     /**
     * 选择所属部门取消事件
     */
    onParentClose(){
      this.parentDialog.visible=false;
    },
    /**
     * 选择所属部门确定事件
     */
    onParentConfirm(){
      this.parentDialog.visible=false;
    },
    /**
     * 打开添加部门窗口
     */
    openAddWindow(){
      //设置窗口标题
      this.deptDialog.title="新增部门"
      //显示添加部门窗口
      this.deptDialog.visible=true
    },
    /**
     * 打开选择所属部门
     */
   async openSelectDepartment(){
      //设置窗口属性
      this.parentDialog.visible=true;
      //查询所属部门列表
      let res = await departmentApi.getParentTreeList();
      //判断是否成功
      if(res.success){
        this.treeList=res.data;
      }
    },
    /**
     * 点击树节点加减号时触发
     */
    changeicon(data){
      //修改折叠状态
      data.open=!data.open;
      this.$refs.parentTree.store.nodesMap[data.id].expanded-!data.open;
    },
    /**
     * 树节点点击事件
     */
    handleNodeClick(data){
      //将选中的部门赋值给dept对象
      this.dept.id=data.id;
      this.dept.parentName=data.departmentName;
    },
  }
};
</script>
<style lang="scss" scoped >
  ::v-deep .el-tree{
    .el-tree-node{
      position:relative;
      padding-left:10px;
    }
    .el-tree-node__children{
      padding-left:20px;
    }
    .el-tree-node:last-child:before{
      height:40px;
    }
    .el-tree> .el-tree-node:after{
      border-top:none;
    }
    .el-tree-node:before,
    .el-tree-node:after{
      content:"";
      left: -4px;
      position:absolute;
      right:auto;
      border-width:1px;
    }
    .tree :first-children .el-tree-node:before{
      border-left:none;
    }
    .el-tree-node:before{
      border-left:1px dotted #d9d9d9;
      bottom:0px;
      height:100%;
      top:-25px;
      width:1px;
    }
    .el-tree-node:after{
      border-top:1px dotted #d9d9d9;
      height:20px;
      top:14px;
      width:24px;
    }
    .el-tree-node__expand-icon.is-leaf{
      width:8px;
    }
    .el-tree-node__content{
      line-height:30px;
      height:30px;
      padding-left:1px!important;
    }
  }
  ::v-deep .el-tree > div{
    &::before{
      display:none;
    }
    &::after{
      display:none;
    }
  }
</style>

表单数据快速清空

src/utils创建resetForm.js脚本文件

//重置表单和表单数据
export default function resetForm(fromName,obj){
  //清空表单
  if(this.$refs[fromName]){
    this.$refs[fromName].resetFields();
  }
  //清空数据
  Object.keys(obj).forEach(key=>{
    obj[key]='';
  })
}

src/main.js

//导入清空表单工具
import resetForm from '@/utils/resetForm'
Vue.prototype.$myconfirm=myconfirm;

src/views/system/department/department.vue

openAddWindow(){
      //清空表单数据
      this.$resetForm("deptForm",this.dept);
      //设置窗口标题
      this.deptDialog.title="新增部门"
      //显示添加部门窗口
      this.deptDialog.visible=true
    },

新增部门

src/api/department.js

  /**
   * 添加部门
   */
  async addDept(params){
    return await http.post("/api/department/add",params);
  }
}

src/views/system/department/department.vue

/**
     * 弹窗确定事件
     */
     onConfirm(){
      //表单验证
      this.$refs.deptForm.validate(async(valid)=>{
        //如果验证通过
        if(valid){
          //发送添加请求
          let res = await departmentApi.addDept(this.dept)
          //判断是否成功
          if(res.success){
            //提示成功
            this.$message.success(res.message);
            //刷新
            this.search();
          //关闭窗口
          this.deptDialog.visible=false;
          }else{
            //提示失败
            this.$message.error(res.message);
          }
          
        }
      })
    },

8.18-8.19学习汇报与总结

1.学习体会与感受

    接口测试和视频不一样,自己不会写。还是太菜了,就算知道解决方法,自己也不会写,不管怎样辗转几天的端口问题,最后总归找到笨笨的解决办法是借后端代码直接测试,由于这两天没有端口测试,估计后面改bug问题不小,希望自己导入后端文件顺利,能快点开始联调找问题。

  2.8.20-8.21学习计划

完成后端文件导入进行测试,抓紧完成前端部分代码交给后端测试接口。


网站公告

今日签到

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