旭锋科技制造信息管理系统-角色模块

旭锋科技制造信息管理系统-角色管理模块

一、模块功能

该模块主要解决把使用本系统的用户分类,不同类别的用户访问不同的页面。该模块同样完成角色的CRUD,启用、禁用,展示系统支持的角色数据。

二、模块分析

2.1 组件说明

  • 角色管理组件:RoleMngr.vue
    • 作用:提供展示角色原始数据UI;提供 查询|新增|更新|删除|启用|禁用 菜单UI;提供查询UI。完成获取菜单原始数据,查询、删除、启用、禁用功能。
  • 角色新增或更新组件: AddOrUpdateRole.vue
    • 作用:提供新增|更新UI,完成新增|更新操作。

2.2 UI选择

  • 数据展示使用el-table
  • 组件内部菜单使用el-button
  • 数据获取使用el-form

三、模块初始构建

3.1 构建客户端

3.1.1 构建 RoleMngr.vue 组件

<template>
  <div>
    <a-card title="角色管理" size="small" style="height: 813px; padding: 0 10px 0 10px ">
      <el-row type="flex" justify="space-between" style="margin-top: 10px">
        <!--该列提供查询UI-->
        <el-col :span="12">
          <el-form ref="rlQuery" :model="rlQueryInfo" :rules="rlQueryRule" inline size="small" status-icon >
            <el-form-item prop="queryType">
              <el-select v-model="rlQueryInfo.queryType" placeholder="请选择查询方式...">
                <el-option value="0" label="角色名称"></el-option>
                <el-option value="1" label="角色状态"></el-option>
              </el-select>
            </el-form-item>

            <el-form-item prop="queryKey">
              <el-input v-model="rlQueryInfo.queryKey" placeholder="请输入查询关键字..." clearable></el-input>
            </el-form-item>

            <el-form-item>
              <el-button-group>
                <el-button type="primary" :disabled="menuStatus.query"><i class="fas fa-search"></i> 查询</el-button>
                <el-button><i class="fas fa-redo-alt"></i> 重置</el-button>
              </el-button-group>
            </el-form-item>
          </el-form>
        </el-col>
        <!--独立菜单区:新增菜单-->
        <el-col :span="2" align="end">
          <el-button type="success" size="small" :disabled="menuStatus.add"><i class="fas fa-plus"></i> 新增</el-button>
        </el-col>
      </el-row>
      <el-divider></el-divider>
      <!--角色数据展示-->
      <el-row type="flex" justify="center">
        <el-table :data="roleData" size="small" :header-cell-style="{background:'#7dbcea',color:'#606266'}" max-height="600" :row-key="setRowKey">
          <el-table-column label="角色ID"></el-table-column>
          <el-table-column label="角色标识"></el-table-column>
          <el-table-column label="角色名称"></el-table-column>
          <el-table-column label="角色说明"></el-table-column>
          <el-table-column label="角色状态"></el-table-column>
          <el-table-column label="创建时间"></el-table-column>
          <el-table-column label="创建人"></el-table-column>
          <el-table-column label="修改时间"></el-table-column>
          <el-table-column label="修改人"></el-table-column>
          <el-table-column label="操作"></el-table-column>
        </el-table>
      </el-row>
			<el-row type="flex" justify="end" style="margin-top: 15px">
        <el-col :span="12" align="end">
          <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :page-sizes="[1, 2, 5, 10, 20]"
                         :page-size="pagination.pageSize" :current-page.sync="pagination.currentPage" layout="total, sizes, prev, pager, next, jumper" :total="dataTotal"></el-pagination>
        </el-col>
      </el-row>
    </a-card>
  </div>
</template>
<script>
export default {
 name: "RoleMngr",
  inject: ["getChildrenMenuStatus"],
  data(){
    return{
      /*查询UI绑定变量*/
      rlQueryInfo: {
        queryType: undefined,
        queryKey: ""
      },
      rlQueryRule: {},
      /*待展示的角色数据*/
      roleData: [],
      /*页面菜单状态*/
      menuStatus: {
        add: true,
        update: true,
        delete: true,
        forbid: true,
        enable: true,
        query: true,
      },
      /*分页插件所需变量*/
      pagination: {
        pageSize: 1,
        currentPage: 1
      },
      dataTotal: 0
    }
  },
  methods: {
    /*设置表格的rowKey*/
    setRowKey(row) {
      return row.id;
    },
    /*分页处理函数*/
    handleSizeChange(value)
    {
      this.pagination.pageSize=value;
    },
    handleCurrentChange(value)
    {
      this.pagination.currentPage=value;
    },
}
<style scoped>
.el-divider {
  margin-top: 0!important;
}

</style>

3.1.2 构建路由组件在 /home 路由组件的 children 属性中

{
    path: "/role",
    component: _ => import("../views/role/RoleMngr"),
    meta:[{title: "系统设置"},{title: "角色管理", permission: "sys:role:mngr", type: 0, path: "/role",  roleId: [1]}]
}

3.1.3 构建效果

在这里插入图片描述

3.2 构建数据表 sys_role

在这里插入图片描述

3.3 服务器端构建

3.3.1 定义封装数据库信息的实体类 SysRolePojo

package org.wjk.pojo;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;

@EqualsAndHashCode(callSuper = true)
@Data
@Accessors(chain = true)
@TableName("sys_role")
public class SysRolePojo extends BasePojo
{
    private static final long serialVersionUID = -2091659483715729866L;
    @TableId(type = IdType.AUTO)
    private Integer id;
    private String name;
    private String alias;
    private String note;
    private Boolean enabled = true;
    private String createdUser;
    private String modifiedUser;

3.3.2 控制层 构建

package org.wjk.controller;

import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/role")
// 目的:生成一个全参构造,使用构造方式完成依赖注入。
// @AutoWired特性:当一个类的对象由Spring管理时,该类有且只有一个构造函数时,该构造函数默认被@AutroWird标识。
@AllArgsConstructor 
public class SysRoleCtrller
{
}

3.3.3 业务层 构建

  • service层接口: SysRoleSvs
package org.wjk.service;

public interface SysRoleSvs
{
}
  • service层接口的实现类: SysRoleSvsImpl
package org.wjk.service.impl;

import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.wjk.service.SysRoleSvs;

@Service
@AllArgsConstructor
public class SysRoleSvsImpl implements SysRoleSvs
{
}

3.3.4 持久层 构建

package org.wjk.dao;

import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.wjk.pojo.SysRolePojo;

@Mapper
public interface SysRoleDao extends BaseMapper<SysRolePojo>
{
}

3.3.5 Sql映射文件构建 SysRole.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="org.wjk.dao.SysRoleDao">
    <!--查询语句的书写顺序:[on Expr][where Expr][group by][having][order by][limit]-->

</mapper>

四、业务实现

4.1 RoleMngr.vue 初始化菜单状态

  • RoleMngr.vuemethods属性中 定义设置页面菜单状态函数,并在 created() 属性中调用该方法。

    /*设置菜单状态方法*/
       async setMenuStatus() {
      let menuStatus = await this.getChildrenMenuStatus(this.$route.path);
      let currentUser = JSON.parse(sessionStorage.getItem("currentUser"));
      if (menuStatus && currentUser) {
        let permissions = currentUser.permissions;
        for (let item of menuStatus) {
          switch (item.name) {
            case "新增":
              this.menuStatus.add = !(item.enabled && permissions.includes("sys:role:add"));
              break;
            case "更新":
              this.menuStatus.update = !(item.enabled && permissions.includes("sys:role:update"));
              break;
            case "删除":
              this.menuStatus.delete = !(item.enabled && permissions.includes("sys:role:delete"));
              break;
            case "查询":
              this.menuStatus.query = !(item.enabled && permissions.includes("sys:role:query"));
              break;
            case "启用":
              this.menuStatus.enable = !(item.enabled && permissions.includes("sys:role:forbid"));
              break;
            case "禁用":
              this.menuStatus.forbid = !(item.enabled && permissions.includes("sys:role:enable"));
              break;
          }
        }
      }
    }
    
    created() {
        this.setMenuStatus();
      }
    

4.2 角色新增业务

4.2.1RoleMngr 的新增按钮绑定点击事件

<!--独立菜单区:新增菜单-->
<el-col :span="2" align="end">
	<el-button type="success" size="small" :disabled="menuStatus.add" @click="handlerAddButtonClickEvent"><i class="fas fa-plus"></i> 新增</el-button>
</el-col>

4.2.2 在 methods 属性中定义点击事件处理函数 handlerAddButtonClickEvent

/*新增按钮点击事件处理函数*/
    handlerAddButtonClickEvent()
    {
      this.$router.push("/role/add");
    },

4.2.3在路由 index.js 中的 home 路由组件的 children 属性中定义子路由组件,完成页面跳转

{
    path: "/role/add",
    component: _ => import("../views/role/AddOrUpdateRole"),
    meta:[{title: "系统设置"},{title: "角色管理", permission: "sys:role:mngr", type: 0, path: "/role",  roleId: [1]},{title: "角色新增", permission: "sys:role:add",  roleId: [1]}]
}

4.2.4构建 AddOrUpdateRole.vue 组件

<template>
  <a-card :title="pageTitle" size="small" style="height: 813px; padding: 0 10px 0 10px ">
    <el-link slot="extra" type="primary" @click="returnToPreviousMenu"><i class="fas fa-fast-backward"></i> 返回</el-link>
    <el-form ref="roleForm" :model="roleInfo" :rules="roleRules" label-width="100px" status-icon>
      <el-row type="flex" justify="space-between" style="margin-top: 50px">
        <el-col :span="12">
          <el-form-item label="角色标识" prop="name">
            <a-tooltip placement="topLeft" title="角色在系统中的英文标识">
              <el-input v-model="roleInfo.name" placeholder="请输入角色标识..." maxlength="8" show-word-limit clearable @blur="roleInfo.name=roleInfo.name.trim()"></el-input>
            </a-tooltip>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item label="角色名称" prop="alias">
            <a-tooltip placement="topLeft" title="角色的中文名称">
              <el-input v-model="roleInfo.alias" placeholder="请输入角色名称..." maxlength="16" show-word-limit clearable @blur="roleInfo.alias=roleInfo.alias.trim()"></el-input>
            </a-tooltip>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row type="flex" justify="center">
        <el-col :span="24">
          <el-form-item label="功能说明" prop="note">
            <el-input type="textarea" v-model="roleInfo.note" :rows="3" placeholder="请输入角色功能说明..." maxlength="128" show-word-limit 
											clearable @blur="roleInfo.note=roleInfo.note.trim()"></el-input>
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <!--取消及确定按钮-->
    <el-row type="flex" justify="end" style="margin-top: 400px">
      <el-col :span="4" align="center">
        <el-button>取消</el-button>
        <el-button type="primary">确定</el-button>
      </el-col>
    </el-row>

  </a-card>
</template>
<script>
export default {
  name: "AddOrUpdateRole",
  inject: ["returnToPreviousMenu"],
  data(){
    return{
      pageTitle: "菜单新增",
      /*执行操作:更新为1,新增为undefined*/
      option: undefined,
      /*录入角色信息表单*/
      roleInfo: {
        id: undefined,
        name: "",
        alias: "",
        note: "",
        createdUser: undefined,
        enabled: true,
        modifiedUser: undefined,
      },
      roleRules: {
        name: [
          {required: true, message: "角色标识不能为空,请输入!", trigger: "blur"}
        ],
        alias: [
          {required: true, message: "角色名称不能为空,请输入!", trigger: "blur"}
        ]
      }
    }
  }
}
</script>

4.2.5初始化 AddOrUpdateRole

  1. 业务逻辑
    • 该组件由 角色新增业务与 角色更新 业务共用,由组件变更 option 来区分操作。
      • optionundefined 时:是新增操作。
      • option1 时:是更新操作。
      • 该变量的值来源于路由组件的 path 属性。
  2. methods 中定义页面初始化方法 initComponent
/*初始化组件*/
    initThisComponent()
    {
      /*设置card的title属性。*/
      this.pageTitle = this.$route.meta[this.$route.meta.length -1].title;
      /*设置当前操作标识。*/
      if("/role/update" === this.$route.path)
      {
        this.option = 1;
      }
    },
  1. created() 钩子函数中调用初始化方法
created() 
{
    this.initThisComponent();
}
  • 完成用户输入的二次校验
    1. 业务逻辑
      • 校验成功:发起请求,将用户输入的角色信息发送给服务器端。
      • 校验失败:提示用户输入无效,按照提示输入用户信息。
    2. 为该页面的 确定取消 按钮绑定点击事件。
      <!--取消及确定按钮-->
          <el-row type="flex" justify="end" style="margin-top: 400px">
            <el-col :span="4" align="center">
              <el-button @click="cancelHandler">取消</el-button>
              <el-button type="primary" @click="submitRoleData">确定</el-button>
            </el-col>
          </el-row>
      
    3. 在组件的 methods 中定义该点击事件处理方法: submitRoleData()
      /*确定按钮点击事件*/
          submitRoleData()
          {
            /*二次校验用户输入信息*/
            this.$refs.roleForm.validate(val => {
              if(!val)
              {
                /*校验失败的处理逻辑*/
                this.$message.error("您输入的角色信息无效,请重新输入!");
                return;
              }
              /*校验成功的处理逻辑*/
              let that = this;
              let currentUser = JSON.parse(sessionStorage.getItem("currentUser")).username;
              this.$confirm({
                title: this.title, content:   "该操作将永久"+ (that.option ? "修改指定的" : "保存录入的")+"角色信息,是否继续?", okText: "确定", cancelText: "取消",
                async onOk()
                {
                  let resStatus, resMessage;
                  /*新增角色处理逻辑*/
                  if(!that.option)
                  {
                    that.roleInfo.createdUser = currentUser;
                    const {data : res} = await that.$axios.post("/role", that.roleInfo);
                    resStatus = res.status;
                    resMessage = res.message;
                    if(2000 === res.status)
                    {
                      that.cancelHandler();
                    }
                  }
                  else
                  {
                    /*更新角色处理逻辑*/
                  }
                  that.resMessage(resStatus, resMessage);
                },
                onCancel()
                {
                  that.resMessage(2000, "操作终止成功!");
                }
              })
            })
          }
      
    4. 在组件的 methods 中定义该点击事件处理方法: cancelHandler()
      /*取消按钮点击事件处理函数*/
          cancelHandler()
          {
            this.$refs.roleForm.resetFields();
          }
      

4.2.6服务器端处理

  • SysRoleCtrllr 定义处理新增请求方法

    /*处理新增角色请求*/
        @PostMapping
        public ResPackaging addNewRole(@RequestBody @Validated SysRolePojo rolePojo)
        {
            System.out.println(rolePojo);
            return ResPackaging.success("成功添加该角色信息,请求继续添加下条,退出请按返回键!");
        }
    
  • SysRoleSvs 声明处理新增业务函数并在实现该方法在 SysRoleSvsImpl

    void addNewRole(SysRolePojo rolePojo);
    
    /*新增角色功能*/
        @Override
        public void addNewRole(SysRolePojo rolePojo)
        {
            /*新增规则,不能新增同名的角色*/
            Integer isExist = roleDao.selectExistElementByRoleName(rolePojo.getName());
            if(null != isExist)
                throw new ServiceException(ExcInfo.DATA_NAME_ALREADY_EXISTS);
            int istCnts = roleDao.insert(rolePojo);
            if(istCnts != 1)
                throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT);
        }
    
  • SysRoleDao 中声明所需方法

    Integer selectExistElementByRoleName(String name);
    
  • SysRole.xml 定义对应的动态Sql

    <select id="selectExistElementByRoleName" resultType="Integer">
        select 1 from sys_role where name=#{name} limit 1;
    </select>
    

4.3 角色数据展示

4.3.1 业务说明

通过分页查询的方法,获取数据中角色数据,前在客户端中展示,并实现Redis缓存。

4.3.2 客户端发起获取角色数据请求

  1. RoleMngr.vuemethods 属性中定义获取角色数据函数

    /*角色数据获取函数*/
        async getAllRoleDatas() {
          const {data: res} = await this.$axios.get("/role", {params: this.pagination});
          if (2000 === res.status && res.data.data && res.data.data.length > 0)
          {
            this.roleData = res.data.data;
            this.dataTotal = res.data.totalCounts;
          }
        }
    
  2. RoleMngr.vuecreated 生命周期钩子中调用上述方法

    created() {
        this.setMenuStatus();
        this.getAllRoleDatas();
      }
    

4.3.3服务器端处理请求

  1. SysRoleCtrllr 中定义请求处理的方法 getAllRolesDataHandler

    /*处理获取角色数据请求*/
        @GetMapping
        public ResPackaging getAllRolesDataHandler(@Validated @NotNull Integer pageSize, @Validated @NotNull Integer currentPage)
        {
            return ResPackaging.success("OK!", roleSvs.getAllRolesData(pageSize, currentPage));
        }
    
  2. SysRoleSvs 中声明获取角色数据的业务处理函数,并在 SysRoleSvsImpl 中实现该方法

    PaginationResPackagin getAllRolesData(Integer pageSize, Integer currentPage);
    
    /*角色数据获取业务*/
        @Override
        @CacheReader("ROLE::")
        public PaginationResPackagin getAllRolesData(Integer pageSize, Integer currentPage)
        {
            /*获取总数据数*/
            int totalData = Math.toIntExact(roleDao.selectCount(null));
            if(totalData <= 0)
                throw new ServiceException(ExcInfo.NO_DATA_AVAILABLE);
            /*计算当前起始索引*/
            int index = (currentPage - 1) * pageSize;
            List<SysRolePojo> res = roleDao.getAllRolesData(index, pageSize);
            if(res.isEmpty())
                throw new ServiceException(ExcInfo.NO_DATA_AVAILABLE);
            return new PaginationResPackagin(totalData, res);
        }
    
  3. SysRoleDao 中声明访问持久层方法

    List<SysRolePojo> getAllRolesData(Integer index, Integer pageSize);
    
  4. SysRole.xml 中定义相关映射Sql

    <select id="getAllRolesData" resultType="org.wjk.pojo.SysRolePojo">
            select id, name, alias, note, enabled, created_time, created_user, modified_time, modified_user from sys_role limit #{index}, #{pageSize}
        </select>
    

4.3.4 客户端展示数据及分页处理

  1. 客户端展示数据:修改 el-table

    				<el-table :data="roleData" size="small" :header-cell-style="{background:'#7dbcea',color:'#606266'}" max-height="600" :row-key="setRowKey">
              <el-table-column type="index" label="序号" align="center" min-width="5%"></el-table-column>
              <el-table-column prop="name" label="角色标识" align="center" min-width="8%"></el-table-column>
              <el-table-column prop="alias" label="角色名称" align="center" min-width="10%"></el-table-column>
              <el-table-column prop="note" label="角色说明" show-overflow-tooltip align="center" min-width="18%"></el-table-column>
              <el-table-column prop="enabled" label="角色状态" align="center" min-width="7%">
                <template v-slot="item">
                  <el-tag v-if="item.row.enabled" type="seccus" size="small">正常</el-tag>
                  <el-tag v-else type="error" size="small">禁用</el-tag>
                </template>
              </el-table-column>
              <el-table-column prop="createdTime" label="创建时间" align="center" min-width="10%"></el-table-column>
              <el-table-column prop="createdUser" label="创建人" align="center" min-width="10%"></el-table-column>
              <el-table-column prop="modifiedTime" label="修改时间" align="center" min-width="10%">
                <template v-slot="item">
                  {{item.row.modifiedTime ? item.row.modifiedTime : "无"}}
                </template>
              </el-table-column>
              <el-table-column prop="modifiedUser" label="修改人" align="center" min-width="10%">
                <template v-slot="item">
                  {{item.row.modifiedUser ? item.row.modifiedUser : "无"}}
                </template>
              </el-table-column>
              <el-table-column label="操作" align="center" min-width="17%">
                <template v-slot="item">
                  <el-link type="warning" :disabled="menuStatus.update"><i class="fas fa-edit"></i> 更新</el-link>
                  <el-divider direction="vertical"/>
                  <el-link type="danger" :disabled="menuStatus.delete"><i class="fas fa-trash-alt"></i> 删除</el-link>
                  <el-divider direction="vertical"/>
                  <el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid"><i class="fas fa-redo-alt"></i> 禁用</el-link>
                  <el-link v-else type="seccuss" :disabled="menuStatus.enable"><i class="fas fa-redo-alt"></i> 启用</el-link>
                </template>
              </el-table-column >
            </el-table>
    
  2. RoleMngr.vuemethods 属性中定义分页页面更新时处理函数 handleSizeChange

    handleSizeChange(value)
        {
          this.pagination.pageSize=value;
          this.getAllRoleDatas();
        },
    
  3. RoleMngr.vuemethods 属性中定义分页页面更新时处理函数 handleCurrentChange

    handleCurrentChange(value)
        {
          this.pagination.currentPage=value;
          this.getAllRoleDatas();
        },
    

4.4 角色更新业务

4.4.1 业务需要

修改已有的角色信息,并修改后的角色标识不能同已有的角色标识同名。

4.4.2 RoleMngr 组件业务实现

  • 更新 按钮绑定点击事件
<el-table-column label="操作" align="center" min-width="17%">
  <template v-slot="item">
    <el-link type="warning" :disabled="menuStatus.update" @click="updateButtonClickHandler(item.row)"><i class="fas fa-edit"></i> 更新</el-link>
    <el-divider direction="vertical"/>
    <el-link type="danger" :disabled="menuStatus.delete"><i class="fas fa-trash-alt"></i> 删除</el-link>
    <el-divider direction="vertical"/>
    <el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid"><i class="fas fa-redo-alt"></i> 禁用</el-link>
    <el-link v-else type="seccuss" :disabled="menuStatus.enable"><i class="fas fa-redo-alt"></i> 启用</el-link>
    </template>
</el-table-column >
  • methods 属性内定义更新点击事件处理函数
    • 主要功能:手动触发路由,完成页面跳转 AddOrUpdateRole 页面,并将该行的角色数据通过 sessionStorage 传递给 AddOrUpdateRole 组件。
/*更新按钮点击事件处理函数*/
    updateButtonClickHandler(value)
    {
      sessionStorage.setItem("role", JSON.stringify(value));
      this.$router.push("/role/update")
    }
  • home 路由组件中定义 /role/update 子路由组件
{
   path: "/role/update",
   component: _ => import("../views/role/AddOrUpdateRole"),
   meta:[{title: "系统设置"},{title: "角色管理", permission: "sys:role:mngr", type: 0, path: "/role",  roleId: [1]},{title: "角色更新", permission: "sys:role:update",  roleId: [1]}]
}

4.4.3 AddOrUpdateRole 组件业务实现

  • 完成该组件 更新 操作的初始化
    • 获取 sessionStorage 中参数,copy到form表单绑定的变量中。
    • 方法:修改已定义的 initThisComponent() 方法中的更新时业务逻辑
/*初始化组件*/
    initThisComponent()
    {
      /*设置card的title属性。*/
      this.pageTitle = this.$route.meta[this.$route.meta.length -1].title;
      /*设置当前操作标识。*/
      if("/role/update" === this.$route.path)
      {
        this.option = 1;
        let role = JSON.parse(sessionStorage.getItem("role"));
        if(role)
        {
          this.roleInfo = {... role};
        }
      }
    },
  • 修改组件 methods 属性中 submitRoleData() ,发起更新请求,并在处理响应。
/*确定按钮点击事件*/
    submitRoleData()
    {
      /*二次校验用户输入信息*/
      this.$refs.roleForm.validate(val => {
        if(!val)
        {
          /*校验失败的处理逻辑*/
          this.$message.error("您输入的角色信息无效,请重新输入!");
          return;
        }
        /*校验成功的处理逻辑*/
        let that = this;
        let currentUser = JSON.parse(sessionStorage.getItem("currentUser")).username;
        this.$confirm({
          title: this.title, content:   "该操作将永久"+ (that.option ? "修改指定的" : "保存录入的")+"角色信息,是否继续?", okText: "确定", cancelText: "取消",
          async onOk()
          {
            let resStatus, resMessage;
            /*新增角色处理逻辑*/
            if(!that.option)
            {
              that.roleInfo.createdUser = currentUser;
              const {data : res} = await that.$axios.post("/role", that.roleInfo);
              resStatus = res.status;
              resMessage = res.message;
              if(2000 === resStatus)
              {
                that.cancelHandler();
              }
            }
            else
            {
              /*更新角色处理逻辑*/
              that.roleInfo.modifiedUser = currentUser;
              const {data : res} = await that.$axios.put("role", that.roleInfo);
              resStatus = res.status;
              resMessage = res.message;
              if(2000 === resStatus)
              {
                sessionStorage.removeItem("role");
                that.$router.go(-1);
              }
            }
            that.resMessage(resStatus, resMessage);
          },
          onCancel()
          {
            that.resMessage(2000, "操作已终止!");
          }
        })
      })
    },

4.4.4 服务器端处理请求,完成响应

  • SysRoleCtrllr 中定义处理更新请求的方法并设置权限
/*处理角色更新请求*/
    @PutMapping
    @PreAuthorize("hasAuthority('sys:role:update')")
    public ResPackaging updateSpecificRoleHanlder(@RequestBody @Validated(SysRolePojo.update.class) SysRolePojo rolePojo)
    {
        roleSvs.updateSpecificRole(rolePojo);
        return ResPackaging.success("角色信息修改成功!");
    }
  • SysRoleSvs 中声明处理更新的业务方法,并在 SysRoleSvsImpl 中实现该方法前刷新缓存。
void updateSpecificRole(SysRolePojo rolePojo);
@Override
    @CacheWriter("ROLE")
    public void updateSpecificRole(SysRolePojo rolePojo)
    {
        Integer extId = roleDao.selectExistElementByRoleName(rolePojo.getName());
        if(null != extId && !extId.equals(rolePojo.getId()))
            throw new ServiceException(ExcInfo.DATA_NAME_ALREADY_EXISTS);
        //int updtCnts = roleDao.update(rolePojo, new UpdateWrapper<SysRolePojo>().eq("id", rolePojo.getId()));
        int updtCnts = roleDao.updateById(rolePojo);
        if(1 != updtCnts)
            throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT);
    }

4.5 删除角色数据实现

4.5.1 业务需求

当有权限的操作人点击某一角色对应的删除按钮时,如果该角色没有对应的用户时,则服务器删除该角色数据;如果有对应用户,则会提醒操作人该角色不能删除。

4.5.2 RoleMngr 组件业务实现

  • 删除 按钮绑定点击事件
<el-table-column label="操作" align="center" min-width="17%">
   <template v-slot="item">
    <el-link type="warning" :disabled="menuStatus.update" @click="updateButtonClickHandler(item.row)"><i class="fas fa-edit"></i> 更新</el-link>
    <el-divider direction="vertical"/>
    <el-link type="danger" :disabled="menuStatus.delete" @click="deleteBtnClkHandler(item.row.id)"><i class="fas fa-trash-alt"></i> 删除</el-link>
    <el-divider direction="vertical"/>
    <el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 禁用</el-link>
    <el-link v-else type="seccuss" :disabled="menuStatus.enable" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 启用</el-link>
  </template>
</el-table-column >
  • 组件 methods 属性中定义删除按钮点击事件处理函数 deleteBtnClkHandler(value)
/*删除按钮点击事件处理函数*/
    deleteBtnClkHandler(param)
    {
      let that = this;
      this.$confirm({
        title: "角色删除", content: "该操作将永久删除此角色信息,是否继续?", okText: "确定", cancelText: "取消",
        async onOk()
        {
          const {data : res} = await that.$axios.delete(`/role/${param}`);
          if(2000 === res.status)
          {
            that.pagination.pageSize = 5;
            that.pagination.currentPage = 1;
            await that.getAllRoleDatas();
          }
          that.resMessage(res.status, res.message);
        },
        onCancel()
        {
          that.resMessage(2000, "操作已终止!");
        }
      })
    },

4.5.3 服务器端处理请求,返回响应

  • SysRoleCtrllr 中定义处理删除请求的方法并设置权限
/*处理角色删除请求*/
    @DeleteMapping("/{roleId}")
    @PreAuthorize("hasAuthority('sys:role:delete')")
    public ResPackaging deleteSepcificRoleHandler(@PathVariable @Validated @NotNull Integer roleId)
    {
        roleSvs.deleteSepcificRole(roleId);
        return ResPackaging.success("角色信息删除成功!");
    }
  • SysRoleSvs 中声明处理删除的业务方法,并在 SysRoleSvsImpl 中实现该方法前刷新缓存。
void deleteSepcificRole(Integer roleId);
/*删除角色业务*/
    @Override
    @CacheWriter("ROLE")
    public void deleteSepcificRole(Integer roleId)
    {
        /*查找是否有该角色类型的用户*/
        Integer extUsr = roleDao.isExistUserByRoleId(roleId);
        /*如果有则提示操作人不能删除该角色*/
        if(null != extUsr)
            throw new ServiceException(ExcInfo.EXIST_USER_BY_ROLE);
        /*如果没有则删除角色*/
        int dltCnts = roleDao.deleteById(roleId);
        if(1 != dltCnts)
            throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT);
    }
  • SysRoleDao 中声明辅助方法 isExistUserByRoleId(roleId)
Integer isExistUserByRoleId(Integer roleId);
  • SysRole.xml 中定义映射Sql
<select id="isExistUserByRoleId" resultType="Integer">
   select id from sys_user where role_id=#{roleId} limit 1;
</select>

4.6 启用|禁用角色实现

4.6.1 业务需求

  • 当有权限的操作人点击某一角色对应的 禁用 按钮时,如果该角色没有对应的用户时,则服务器禁用该角色;如果有对应用户,则会提醒操作人该角色不能禁用。
  • 当有权限的操作人点击某一角色对应的 启用 按钮时,服务器直接启用该角色。

4.6.2 RoleMngr 组件业务实现

  • 禁用|启用 按钮绑定点击事件
<el-table-column label="操作" align="center" min-width="17%">
   <template v-slot="item">
    <el-link type="warning" :disabled="menuStatus.update" @click="updateButtonClickHandler(item.row)"><i class="fas fa-edit"></i> 更新</el-link>
    <el-divider direction="vertical"/>
    <el-link type="danger" :disabled="menuStatus.delete" @click="deleteBtnClkHandler(item.row.id)"><i class="fas fa-trash-alt"></i> 删除</el-link>
    <el-divider direction="vertical"/>
    <el-link v-if="item.row.enabled" type="warning" :disabled="menuStatus.forbid" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 禁用</el-link>
    <el-link v-else type="seccuss" :disabled="menuStatus.enable" @click="fbdOrEablBtnClkHandler(item.row.id, item.row.enabled)"><i class="fas fa-redo-alt"></i> 启用</el-link>
  </template>
</el-table-column >
  • 组件 methods 属性中定义禁用|启用按钮点击事件处理函数 fbdOrEablBtnClkHandler(id, enabled)
/*禁用|启用按钮点击事件处理函数*/
    fbdOrEablBtnClkHandler(id, enabled)
    {
      let that = this;
      this.$confirm({
        title: enabled ? "角色禁用" : "角色启用", content: "该操作将永久"+(enabled ? "禁用" : "启用")+"此角色,是否继续?", okText: "确定", cancelText: "取消",
        async onOk()
        {
          const {data : res} = await that.$axios.put(`/role/enable/${id}/${enabled}`);
          if(2000 === res.status)
          {
            that.pagination.pageSize = 5;
            that.pagination.currentPage = 1;
            await that.getAllRoleDatas();
          }
          that.resMessage(res.status, res.message);
        },
        onCancel()
        {
          that.resMessage(2000, "操作已终止!");
        }
      })

    }

4.6.3 服务器端处理请求,返回响应

  • SysRoleCtrllr 中定义处理禁用|启用请求的方法并设置权限
/*处理角色启用禁用请求*/
    @PutMapping("/enable/{id}/{enable}")
    @PreAuthorize("hasAnyAuthority('sys:role:enable', 'sys:role:forbid')")
    public ResPackaging enOrForSpecificRoleHandler(@PathVariable @Validated @NotNull Integer id, @PathVariable @Validated @NotNull Boolean enable)
    {
        roleSvs.enOrForSpecificRole(id, enable);
        return ResPackaging.success((enable ? "禁用" : "启用") + "该角色成功!");
    }
  • SysRoleSvs 中声明处理禁用|启用的业务方法,并在 SysRoleSvsImpl 中实现该方法前刷新缓存。
void enOrForSpecificRole(Integer id, Boolean enable);
		@Override
    @CacheWriter("ROLE")
    public void enOrForSpecificRole(Integer id, Boolean enable)
    {
        if(enable)
        {
            Integer extUsr = roleDao.isExistUserByRoleId(id);
            if(null != extUsr)
                throw new ServiceException(ExcInfo.EXIST_USER_BY_ROLE);
        }
        int updtCnts = roleDao.enOrForSpecificRole(id, !enable);
        if(updtCnts != 1)
            throw new ServiceException(ExcInfo.ILLEGAL_DB_CONNECT);
    }
  • SysRoleDao 中声明禁用|启用方法 enOrForSpecificRole(id, enable)
int enOrForSpecificRole(Integer id, boolean b);
  • SysRole.xml 中定义映射Sql
<update id="enOrForSpecificRole">
   update sys_role set enabled=#{b} where id=#{id}
</update>

4.7 角色查询

4.7.1 业务需求

  • 根据查询方式及查询关键字构成的查询条件,查询对应的角色数据。并将数据展示在表中。
  • 当点击重置时,清空查询信息,并显示原始分页角色数据。

4.7.2 RoleMngr 组件业务实现

  • 查询重置 绑定点击事件
<el-form-item>
  <el-button-group>
    <el-button type="primary" :disabled="menuStatus.query" @click="queryBtnClckHandler"><i class="fas fa-search"></i> 查询</el-button>
    <el-button @click="resetBtnClkHandler"><i class="fas fa-redo-alt"></i> 重置</el-button>
  </el-button-group>
</el-form-item>
  • 在组件 methods 属性中定义两个点击事件处理函数

    • 查询按钮点击事件函数 queryBtnClckHandler
    /*查询按钮点击事件*/
        queryBtnClckHandler()
        {
          this.$refs.rlQuery.validate( async value=>{
            if(!value)
            {
              this.resMessage(0, "您的查询信息无效,请重新输入查询条件!");
              return;
            }
            const {data : res} = await this.$axios.get(`/role/query/${this.rlQueryInfo.queryType}/${this.rlQueryInfo.queryKey}/5/1`);
            if(2000 === res.status && res.data.data && res.data.data.length > 0)
            {
              this.pagination.pageSize=5;
              this.pagination.currentPage=1;
              this.dataTotal = res.data.totalCounts;
              this.roleData = res.data.data;
            }
            else
            {
              this.resMessage(res.status, res.message);
            }
          })
        },
    
    • 重置按钮点击事件处理函数 resetBtnClkHandler
    /*重置按钮点击事件*/
        resetBtnClkHandler()
        {
          this.$refs.rlQuery.resetFields();
          this.pagination.pageSize = 5;
          this.pagination.currentPage = 1;
          this.getAllRoleDatas();
        }
    

4.7.3 服务器端处理请求及响应结果

  • SysRoleCtrllr 定义处理查询请求方法
@GetMapping("/query/{type}/{key}/{pgSize}/{crrntPg}")
    @PreAuthorize("hasAuthority('sys:role:query')")
    public ResPackaging queryRoleDataByConditionHandler(@PathVariable @Validated @NotNull Integer type, @PathVariable @Validated @NotEmpty String key,
             @PathVariable @Validated @NotNull Integer pgSize, @PathVariable @Validated @NotNull Integer crrntPg)
    {
        return ResPackaging.success("ok", roleSvs.queryRoleDataByCondition(type, key, pgSize, crrntPg));
    }
  • SysRoleSvs 声明处理角色查询的业务方法并在实现类 SysRolesSvsImpl 中实现该方法
PaginationResPackaging queryRoleDataByCondition(Integer type, String key, Integer pgSize, Integer crrntPg);
@Override
    public PaginationResPackaging queryRoleDataByCondition(Integer type, String key, Integer pgSize, Integer crrntPg)
    {
        int dataTotal = roleDao.getDataTotalCountsValidateCondition(type, key);
        if(0 == dataTotal)
            throw new ServiceException(ExcInfo.NO_DATA_AVAILABLE);
        int index = (crrntPg - 1) * pgSize;
        List<SysRolePojo> rs = roleDao.queryRoleDataByCondition(type, key, pgSize, index);
        if(rs.isEmpty())
            throw new ServiceException(ExcInfo.SYSTEM_INTERNAL_ERROR);
        return new PaginationResPackaging(dataTotal, rs);
    }
  • SysRoleDao 声明相关映射方法
int getDataTotalCountsValidateCondition(Integer type, String key);

List<SysRolePojo> queryRoleDataByCondition(Integer type, String key, Integer pgSize, Integer index);
  • SysRole.xml 定义映射Sql
<select id="getDataTotalCountsValidateCondition" resultType="Integer">
        select count(*) from sys_role
            <where>
                <choose>
                    <when test="type==0">
                        instr(name, #{key})<!--该方法据资料上说可以优化模糊查询-->
                    </when>
                    <when test="type==1">
                        instr(alias, #{key})
                    </when>
                    <when test="type==2">
                        <choose>
                            <when test="key=='正常'">
                                enabled=1
                            </when>
                            <when test="key=='正常'">
                                enabled=0
                            </when>
                            <otherwise>
                                enabled=200
                            </otherwise>
                        </choose>
                    </when>
                </choose>
            </where>
    </select>
    <select id="queryRoleDataByCondition" resultType="org.wjk.pojo.SysRolePojo">
        select id, name, alias, note, enabled, created_time, created_user, modified_time, modified_user from sys_role
        <where>
            <choose>
                <when test="type==0">
                    instr(name, #{key})
                </when>
                <when test="type==1">
                    instr(alias, #{key})
                </when>
                <when test="type==2">
                    <choose>
                        <when test="key=='正常'">
                            enabled=1
                        </when>
                        <when test="key=='正常'">
                            enabled=0
                        </when>
                        <otherwise>
                            enabled=200
                        </otherwise>
                    </choose>
                </when>
            </choose>
        </where>
        limit #{index}, #{pgSize}
    </select>

四、业务总结

到此,角色模块已完成,需要思考的是,当项目处于生产环境时,角色的 新增更新、 删除的存在是否合理。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值