五、前后端分离通用权限系统(5)

news2024/11/15 12:13:21

🌻🌻 目录

  • 一、前端框架
    • 1.1、vue-element-admin
      • 1.1.1、Vue 概述
      • 1.1.2、Element-ui 概述
      • 1.1.3、ES6 概述
    • 1.2、vue-admin-template
      • 1.2.1、简介
      • 1.2.2、下载
      • 1.2.3、安装
      • 1.2.4、源码目录结构(了解)
      • 1.2.5、改造登录&退出功能
        • 1.2.5.1、服务器端增加接口
        • 1.2.5.2、前端配置修改
  • 二、角色列表
    • 2.1、修改路由
    • 2.2、创建vue组件
    • 2.3、定义api(含 es6 拼接)
    • 2.4、初始化 vue 组件
    • 2.5、定义 data,methods
    • 2.6、表格渲染
    • 2.7、日期格式化
    • 2.8、分页组件
    • 2.9、顶部查询表单
  • 三、角色删除和添加
    • 3.1、定义 api,methods
    • 3.2、测试
    • 3.3、角色添加
      • 3.3.1、定义api
      • 3.3.2、定义添加按钮 和 弹出层
      • 3.3.3、实现功能
      • 3.3.4、 测试:
  • 四、角色修改与数据回显
    • 4.1、定义 api,组件中调用 api
    • 4.2、测试
  • 五、批量删除
    • 5.1、定义api,初始化组件
    • 5.2、实现功能
    • 5.3、功能测试

一、前端框架

1.1、vue-element-admin

vue-element-admin是基于VueElement-ui 的一套后台管理系统集成方案。

  • 功能:https://panjiachen.github.io/vue-element-admin-site/zh/guide/#功能
  • GitHub地址:https://github.com/PanJiaChen/vue-element-admin
  • 项目在线预览:https://panjiachen.gitee.io/vue-element-admin

1.1.1、Vue 概述

Vue (读音 /vjuː/,类似于 view) 是一套用于构建用户界面的渐进式框架。

Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链以及各种支持类库结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。

官方网站:https://cn.vuejs.org

在这里插入图片描述

1.1.2、Element-ui 概述

element-ui饿了么前端出品的基于 Vue.js的 后台组件库,方便程序员进行页面快速布局和构建

官网: https://element.eleme.cn/#/zh-CN

在这里插入图片描述

在这里插入图片描述

1.1.3、ES6 概述

ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

1.2、vue-admin-template

1.2.1、简介

vue-admin-template是基于vue-element-admin的一套后台管理系统基础模板(最少精简版),可作为模板进行二次开发。

建议:你可以在 vue-admin-template 的基础上进行二次开发,把 vue-element-admin当做工具箱,想要什么功能或者组件就去 vue-element-admin 那里复制过来。

1.2.2、下载

  • GitHub地址:https://github.com/PanJiaChen/vue-admin-template

在这里插入图片描述

在这里插入图片描述

解压重命名为 gansu-system-front 并放到工作区 GANSU-SYSTEM-FRONT 下面

在这里插入图片描述

打开 VSCode 如下所示:

在这里插入图片描述

1.2.3、安装

# 安装依赖
npm install
# 启动。执行后,浏览器自动弹出并访问http://localhost:9528/
npm run dev


在这里插入图片描述

在这里插入图片描述

③ 浏览器显示如下

在这里插入图片描述

④ 登录进去如下所示

在这里插入图片描述

1.2.4、源码目录结构(了解)

|-dist 生产环境打包生成的打包项目
|-mock 产生模拟数据
|-public 包含会被自动打包到项目根路径的文件夹
	|-index.html 唯一的页面
|-src
	|-api 包含接口请求函数模块
		|-table.js  表格列表mock数据接口的请求函数
		|-user.js  用户登陆相关mock数据接口的请求函数
	|-assets 组件中需要使用的公用资源
		|-404_images 404页面的图片
	|-components 非路由组件
		|-SvgIcon svg图标组件
		|-Breadcrumb 面包屑组件(头部水平方向的层级组件)
		|-Hamburger 用来点击切换左侧菜单导航的图标组件
	|-icons
		|-svg 包含一些svg图片文件
		|-index.js 全局注册SvgIcon组件,加载所有svg图片并暴露所有svg文件名的数组
	|-layout
		|-components 组成整体布局的一些子组件
		|-mixin 组件中可复用的代码
		|-index.vue 后台管理的整体界面布局组件
	|-router
		|-index.js 路由器
	|-store
		|-modules
			|-app.js 管理应用相关数据
			|-settings.js 管理设置相关数据
			|-user.js 管理后台登陆用户相关数据
		|-getters.js 提供子模块相关数据的getters计算属性
		|-index.js vuex的store
	|-styles
		|-xxx.scss 项目组件需要使用的一些样式(使用scss)
	|-utils 一些工具函数
		|-auth.js 操作登陆用户的token cookie
		|-get-page-title.js 得到要显示的网页title
		|-request.js axios二次封装的模块
		|-validate.js 检验相关工具函数
		|-index.js 日期和请求参数处理相关工具函数
	|-views 路由组件文件夹
		|-dashboard 首页
		|-login 登陆
	|-App.vue 应用根组件
	|-main.js 入口js
	|-permission.js 使用全局守卫实现路由权限控制的模块
	|-settings.js 包含应用设置信息的模块
|-.env.development 指定了开发环境的代理服务器前缀路径
|-.env.production 指定了生产环境的代理服务器前缀路径
|-.eslintignore eslint的忽略配置
|-.eslintrc.js eslint的检查配置
|-.gitignore git的忽略配置
|-.npmrc 指定npm的淘宝镜像和sass的下载地址
|-babel.config.js babel的配置
|-jsconfig.json 用于vscode引入路径提示的配置
|-package.json 当前项目包信息
|-package-lock.json 当前项目依赖的第三方包的精确信息
|-vue.config.js webpack相关配置(如: 代理服务器)

在这里插入图片描述

1.2.5、改造登录&退出功能

1.2.5.1、服务器端增加接口

① 到前端登录页,按 Fn+F12 根据如下创建接口

在这里插入图片描述

上面两种响应里面如下所示:

login:
{"code":20000,"data":{"token":"admin-token"}}
info:
{
    "code": 20000,
    "data": {
        "roles": [
            "admin"
        ],
        "introduction": "I am a super administrator",
        "avatar": "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif",
        "name": "Super Admin"
    }
}

② 在后端 service-system 模块下操作,创建 IndexController.java

在这里插入图片描述

package com.gansu.system.controller;

import com.gansu.common.result.Result;
import io.swagger.annotations.Api;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

@Api(tags = "后台登录管理")
@RestController
@RequestMapping("/admin/system/index")
public class IndexController {

    //1.login登录方式
    @PostMapping("login") //根据浏览器请求方法决定
    public Result login(){
        Map<String,Object> map = new HashMap<>();
        map.put("token","admin-token");
        return Result.ok(map);
    }

    //2.info 登录方式
    @GetMapping("info")
    public Result info(){
        Map<String,Object> map = new HashMap<>();
        map.put("roles","[admin]");
        map.put("introduction","I am a super administrator");
        map.put("avatar","https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        map.put("name","Super Admin");
        return Result.ok(map);
    }
}
1.2.5.2、前端配置修改

修改 ① vue.config.js(直接复制即可)

  • 注释掉mock接口配置
  • 配置代理转发请求到目标接口

在这里插入图片描述

// before: require('./mock/mock-server.js')
proxy: {
  '/dev-api': { // 匹配所有以 '/dev-api'开头的请求路径
    target: 'http://localhost:8800',
    changeOrigin: true, // 支持跨域
    pathRewrite: { // 重写路径: 去掉路径中开头的'/dev-api'
      '^/dev-api': ''
    }
  }
}

解析跨域:访问协议,地址ip,端口号不一致都属于跨域;

在这里插入图片描述

修改 ② src/utils/request.js

在这里插入图片描述

修改 ③ src/api/user.js

在这里插入图片描述

修改 ④ 可增加一个标识 ,然后启动后端,再次启动前端,查看是否可以登录进去。

在这里插入图片描述

登录ok,但是没法退出

在这里插入图片描述

解决:

  • 方式一:前端修改接口地址,后端加接口

在这里插入图片描述

  • 方式二:直接注释掉下面这四行也可以

在这里插入图片描述

再次启动就可以顺利退出。

二、角色列表

2.1、修改路由

修改 src/router/index.js

① 复制修改路由,删除多余的路由

在这里插入图片描述

2.2、创建vue组件

src/views文件夹下创建以下文件夹和文件

views下面分别创建 system/sysRole/list.vue,system/sysUser/list.vue

在这里插入图片描述

分别添加如下:

<template>
  <div class="app-container">
    角色列表
  </div>
</template>

③ 刷新查看浏览器

在这里插入图片描述

2.3、定义api(含 es6 拼接)

es6 特性如下(拼接)

在这里插入图片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=<device-width>, initial-scale=1.0">
    <title>Document</title>
</head>
<body>

    <script>

        let a = 'a';  //es6 定义变量
        const b = 'b' //es6 定义常量

        let c = `${a}`+"#"+`${b}`

        console.log(c)

    </script>
    
</body>
</html>

在api目录中创建文件 src/api/system/sysRole.js*

在这里插入图片描述

import request from '@/utils/request'
//角色管理相关的API请求函数
const api_name  = '/admin/system/sysrole/'

export default{

    getPageList(page,limit,searchObject){

      return request({

        url: `${api_name}/${page}/${limit}`,
  
        method: 'get',
  
        params: searchObject
  
      })
    }
}

2.4、初始化 vue 组件

src/views/system/sysRole/list.vue

在这里插入图片描述

<template>
  <div class="app-container">
    角色列表
  </div>
</template>

<script>
//引入
import api from '@/system/sysRole.js'
export default {
//定义数据模型
  data(){
    return{

    }
  },
  //页面渲染前获取数据
  created(){

  },
  //定义方法
  methods:{
      fetchData(){

      }
  }
  
}
</script>

2.5、定义 data,methods

在这里插入图片描述

<template>
  <div class="app-container">
    角色列表
  </div>
</template>
<script>
//引入
import api from '@/api/system/sysRole'
export default {
//定义数据模型
  data(){
    return{
        listLoading:true,//数据是否正在加载
        list:[],//角色列表
        total:0,//总记录数,默认为0
        page:1,//页码
        limit:3,//每页显示的条数 自定义3条
        searchObj:{} //查询条件
    }
  },
  //页面渲染前获取数据
  created(){
      this.fetchData()
  },
  //定义方法
  methods:{
      fetchData(pageNum =1){
        this.page = pageNum
        // 调用api
          api.getPageList(this.page,this.limit,this.searchObj)
          .then(Response =>{
            console.log(Response)
          })
      }
  } 
}
</script>

浏览器查看:

在这里插入图片描述

优化 methods 方法

在这里插入图片描述

//定义方法
methods:{
    fetchData(pageNum =1){
      this.page = pageNum
      // 调用api
        api.getPageList(this.page,this.limit,this.searchObj)
        .then(Response =>{
          //console.log(Response)
          debugger
          this.listLoading = false
            //每页数据的列表
            this.list = Response.data.records,
            //总记录数
            this.total = Response.data.total
        })
    }
} 

2.6、表格渲染

在这里插入图片描述

建议直接复制我 code,涉及 element-ui https://element.eleme.cn/#/zh-CN 表格。

在这里插入图片描述

<div class="app-container">
  <!-- 表格 -->
  <el-table
    v-loading="listLoading"
    :data="list"
    stripe
    border
    style="width: 100%;margin-top: 10px;">

    <el-table-column
      label="序号"
      width="70"
      align="center">
      <template slot-scope="scope">
        {{ (page - 1) * limit + scope.$index + 1 }}
      </template>
    </el-table-column>

    <el-table-column prop="roleName" label="角色名称" />
    <el-table-column prop="roleCode" label="角色编码" />
    <el-table-column prop="createTime" label="创建时间" width="160"/>
    <el-table-column label="操作" width="200" align="center">
      <template slot-scope="scope">
        <el-button type="primary" icon="el-icon-edit" size="mini" @click="edit(scope.row.id)" title="修改"/>
        <el-button type="danger" icon="el-icon-delete" size="mini" @click="removeDataById(scope.row.id)" title="删除"/>
      </template>
    </el-table-column>
  </el-table>
</div>

如下显示:

在这里插入图片描述

2.7、日期格式化

服务器端添加配置:application-dev.yml

在这里插入图片描述

spring:
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

重启服务再次查看:

在这里插入图片描述

2.8、分页组件

建议直接复制我 code,涉及 element-ui https://element.eleme.cn/#/zh-CN 表单 。

在这里插入图片描述

在这里插入图片描述

<!-- 分页组件 -->
<el-pagination
  :current-page="page"
  :total="total"
  :page-size="limit"
  style="padding: 30px 0; text-align: center;"
  layout="total, prev, pager, next, jumper"
  @current-change="fetchData"
/>

显示效果如下:

在这里插入图片描述

2.9、顶部查询表单

在这里插入图片描述

在这里插入图片描述

<!--查询表单-->
<div class="search-div">
 <el-form label-width="70px" size="small">
   <el-row>
     <el-col :span="24">
       <el-form-item label="角色名称">
         <el-input style="width: 100%" v-model="searchObj.roleName" placeholder="角色名称"></el-input>
       </el-form-item>
     </el-col>
   </el-row>
   <el-row style="display:flex">
     <el-button type="primary" icon="el-icon-search" size="mini"  @click="fetchData()">搜索</el-button>
     <el-button icon="el-icon-refresh" size="mini" @click="resetData">重置</el-button>
   </el-row>
 </el-form>
</div>

在这里插入图片描述

重置表单方法

在这里插入图片描述

//重置
resetData(){
//清空
this.searchObj = {},
//刷新页面或查询全部
this.fetchData()
},

在这里插入图片描述

三、角色删除和添加

在这里插入图片描述

3.1、定义 api,methods

在这里插入图片描述

src/api/system/sysRole.js

//删除功能
removeById(id) {

 return request({

   url: `${api_name}/removeRole/${id}`,

   method: 'delete'

 })
}

src/views/system/sysRole/list.vue

使用MessageBox 弹框组件

在这里插入图片描述

在这里插入图片描述

//删除
removeDataById(id){

    this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 点击确定,远程调用ajax
   api.removeById(id).then(Response =>{
      this.$message({
      type: 'success',
      message: '删除成功!'
    });
       //刷新页面或查询全部
       this.fetchData()
     })
  })
},

3.2、测试

问题 ① 无法删除,如下显示

在这里插入图片描述

  • 分析报错(后端打断点

后端没有报错,则打断点排查:

在这里插入图片描述

javascript默认为16位即2的正负53次方,而我们生成的为19位,所以改为String解决。

在这里插入图片描述

解决:

在这里插入图片描述

问题 ②:后端报错 Failed to convert value of type 'java.lang.String' to required type 'java.lang.Long'; nested exception is java.lang.NumberFormatException: For input string: "null"

在这里插入图片描述

在这里插入图片描述

分析与解决:SysRoleMapper.xml里面sql写的有问题

成功测试如下所示:

在这里插入图片描述

测试后数据库:

在这里插入图片描述

3.3、角色添加

定义 apimethods

3.3.1、定义api

src/api/system/sysRole.js

在这里插入图片描述

//添加角色
saveRole(role) {
  return request({
      url: `${api_name}/addSysRole`,
      method: 'post',
      data: role
  })
},

3.3.2、定义添加按钮 和 弹出层

在这里插入图片描述

src/views/system/sysRole/list.vue

表格上面添加按钮,分页组件或添加按钮下面直接添加弹出层

在这里插入图片描述

<!-- 工具条 -->
<div class="tools-div">
  <el-button type="success" icon="el-icon-plus" size="mini" @click="add">添 加</el-button>
</div>
<!-- 定义弹出层 -->
<el-dialog title="添加/修改" :visible.sync="dialogVisible" width="40%" >
  <el-form ref="dataForm" :model="sysRole" label-width="150px" size="small" style="padding-right: 40px;">
    <el-form-item label="角色名称">
      <el-input v-model="sysRole.roleName" placeholder="请输入角色名称" />
    </el-form-item>
    <el-form-item label="角色编码">
      <el-input v-model="sysRole.roleCode" placeholder="请输入角色编码"/>
    </el-form-item>
  </el-form>
  <span slot="footer" class="dialog-footer">
    <el-button @click="dialogVisible = false" size="small" icon="el-icon-refresh-right">取 消</el-button>
    <el-button type="primary" icon="el-icon-check" @click="saveOrUpdate()" size="small">确 定</el-button>
  </span>
</el-dialog>

② 在public目录的index.html页面中添加样式

在这里插入图片描述

<!-- 添加按钮样式 -->
<style>
  .search-div {
      padding:10px;border: 1px solid #EBEEF5;border-radius:3px;
  }
  .tools-div {
      margin-top: 10px;padding:10px;border: 1px solid #EBEEF5;border-radius:3px;
  }
</style>

3.3.3、实现功能

src/views/system/sysRole/list.vue

在这里插入图片描述

<script>

import api from '@/api/system/sysRole'
export default {
    
   data(){
      return{

        listLoading:false,//数据是否正在加载
        list:[],//角色列表
        total:0,//总记录数,默认为0
        page:1,//页码
        limit:3,//每页显示的条数 自定义3条
        searchObj:{}, //查询条件
        dialogVisible:false, //取消弹出角色的页面框
        sysRole:{} //添加角色 这个与上面的 v-model="sysRole.xx" 进行了双向绑定
      }
   },
   created(){
        this.fetchData()
   },
   methods:{
          //添加修改角色,弹出后确定
          saveOrUpdate(){
              if(!this.sysRole.id){
                    this.saveRole()
              }else{
                updateSysRole()
              }  
          },
          //修改角色,弹出后确定
          updateSysRole(){},
          //添加角色,弹出后确定
          saveRole(){
            if(this.sysRole.roleName != null && this.sysRole.roleCode != null){
              api.saveRole(this.sysRole).then(Response=>{
                      //1.提示
                      this.$message({
                      type: 'success',
                      message: '添加成功!'
                       });
                //2.关闭弹框
                this.dialogVisible = false,
                //3.刷新页面或查询全部
                this.fetchData()
              })
            }else{
              alert("请输入要添加的角色名称和角色编码!!!")
            }
          },
          //添加角色,弹出按钮
          add(){
              this.dialogVisible = true,
              this.sysRole = {}
          },

          // 根据id删除数据
          removeDataById(id){

              this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              // 点击确定,远程调用ajax
            api.removeById(id).then(Response =>{
                this.$message({
                type: 'success',
                message: '删除成功!'
                });
                //刷新页面或查询全部
                this.fetchData()
              })
            })
          },

        //重置
        resetData(){
            this.searchObj = {}
            this.fetchData()
        },

        //角色列表显示
        fetchData(pageNum = 1){
            this.page = pageNum;
            api.getPageList(this.page,this.limit,this.searchObj)
            .then(Response=>{
                this.list = Response.data.records
                this.total = Response.data.total
            })
        }
   }
}
</script>

3.3.4、 测试:

在这里插入图片描述

添加成功如下显示:

在这里插入图片描述

在这里插入图片描述

四、角色修改与数据回显

4.1、定义 api,组件中调用 api

src/api/system/sysRole.js

src/views/system/sysRole/list.vue

在这里插入图片描述

src/api/system/sysRole.js

// 修改角色:① 回显数据
findSysRoleById(id) {
 return request({
     url: `${api_name}/findSysRoleById/${id}`,
     method: 'get',
 })
},
//修改角色:② 修改并保存数据
updateById(role) {
return request({
 url: `${api_name}/updateById`,
 method: 'put',
 data:role
})

src/views/system/sysRole/list.vue

<script>

import api from '@/api/system/sysRole'
export default {
    
   data(){
      return{

        listLoading:false,//数据是否正在加载
        list:[],//角色列表
        total:0,//总记录数,默认为0
        page:1,//页码
        limit:3,//每页显示的条数 自定义3条
        searchObj:{}, //查询条件
        dialogVisible:false, //取消弹出角色的页面框
        sysRole:{} //添加角色 这个与上面的 v-model="sysRole.xx" 进行了双向绑定
      }
   },
   created(){
        this.fetchData()
   },
   methods:{
          //添加修改角色,弹出后确定
          saveOrUpdate(){
              if(!this.sysRole.id){
                    this.saveRole()
              }else{
                updateSysRole()
              }  
          },

          updateSysRole(){
            api.updateById(this.sysRole)
            .then(response=>{
                //1.提示
                this.$message({
                type: 'success',
                message: '修改成功!'
                });
                //2.关闭弹框
                this.dialogVisible = false,
                //3.刷新页面或查询全部
                this.fetchData()
            })
          },
          //修改角色,弹出后确定
          edit(id){
              this.dialogVisible = true
              api.findSysRoleById(id).then(Response=>{
                   this.sysRole = Response.data
              })
          },
          //添加角色,弹出后确定
          saveRole(){
            if(this.sysRole.roleName != null && this.sysRole.roleCode != null){
              api.saveRole(this.sysRole).then(Response=>{
                      //1.提示
                      this.$message({
                      type: 'success',
                      message: '添加成功!'
                       });
                //2.关闭弹框
                this.dialogVisible = false,
                //3.刷新页面或查询全部
                this.fetchData()
              })
            }else{
              alert("请输入要添加的角色名称和角色编码!!!")
            }
          },
          //添加角色,弹出按钮
          add(){
              this.dialogVisible = true,
              this.sysRole = {}
          },


          // 根据id删除数据
          removeDataById(id){

              this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              // 点击确定,远程调用ajax
            api.removeById(id).then(Response =>{
                this.$message({
                type: 'success',
                message: '删除成功!'
                });
                //刷新页面或查询全部
                this.fetchData()
              })
            })
          },

        //重置
        resetData(){
            this.searchObj = {}
            this.fetchData()
        },

        //角色列表显示
        fetchData(pageNum = 1){

            this.page = pageNum;
            api.getPageList(this.page,this.limit,this.searchObj)
            .then(Response=>{
                console.log(Response)
                this.list = Response.data.records
                this.total = Response.data.total
            })
        }
   }
}
</script>

4.2、测试

在这里插入图片描述

修改后:

在这里插入图片描述

五、批量删除

5.1、定义api,初始化组件

src/api/system/sysRole.js

src/views/system/sysRole/list.vue

在这里插入图片描述

//批量删除
batchDeleteById(idList) {
  return request({
    url: `${api_name}/batchDeleteById`,
    method: 'delete',
    data:idList
  })
}

② 在table组件上添加 批量删除 按钮

<!-- 工具条 -->
<div class="tools-div">
  <el-button type="success" icon="el-icon-plus" size="mini" @click="add">添 加</el-button>
  <el-button class="btn-add" size="mini" @click="batchRemove()" >批量删除</el-button>
</div>

在table组件上添加复选框

<el-table
  v-loading="listLoading"
  :data="list"
  stripe
  border
  style="width: 100%;margin-top: 10px;"
  @selection-change="handleSelectionChange">
  <el-table-column type="selection"/>

在这里插入图片描述

5.2、实现功能

data定义数据

在这里插入图片描述

 idList:[] //将所有选中的行存储到数组中,如 [1,2,3] 批量删除选中的记录列表

完善方法

在这里插入图片描述

//选中要批量删除的行
handleSelectionChange(selection){
    //将选中的行存入到selectValue数组中
    this.selectValue = selection
    //console.log(this.selectValue)
},

//批量删除
batchRemove(){
  if(this.selectValue.length == 0){
    //alert('请选择要删除的记录!')
    this.$message.warning('请选择要删除的记录!')
    return
  }
  
  this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    //定义一个空数组
    var idList = [];
    //获取多个复选框对应的id值,封装到数组里面
    //遍历数组
    for(var i=0;i<this.selectValue.length;i++){
        //遍历数组
        var obj = this.selectValue[i]
        var id = obj.id
        // alert(id) 选中所有的 id 
        idList.push(id)
    }
    //TODO
    // 点击确定,远程调用ajax
    api.batchDeleteById(idList).then(Response=>{
          this.$message({
          type: 'success',
          message: '删除成功!'
          });
          //刷新页面或查询全部
          this.fetchData()
        })
    })
},

5.3、功能测试

测试效果①

在这里插入图片描述

测试效果②

在这里插入图片描述

在这里插入图片描述

附完整源码:

  • src/api/system/sysRole.js
  • src/views/system/sysRole/list.vue

src/api/system/sysRole.js

import request from '@/utils/request'

const api_name = '/admin/system/sysrole';

export default {

      getPageList(page, limit, searchObj) {
          return request({
              url: `${api_name}/${page}/${limit}`,
              method: 'get',
              params: searchObj
          })
      },
      //角色删除
      removeById(id) {
          return request({
            url: `${api_name}/removeRole/${id}`,
            method: 'delete'
          })
    },
    //添加角色
    saveRole(role) {
      return request({
          url: `${api_name}/addSysRole`,
          method: 'post',
          data: role
      })
    },

      // 修改角色:① 回显数据
      getRoleById(id) {
        return request({
            url: `${api_name}/findSysRoleById/${id}`,
            method: 'post',
        })
      },
      //修改角色:② 修改并保存数据
      updateById(sysRole) {
        return request({
          url: `${api_name}/updateById`,
          method: 'put',
          data: sysRole
        })
      },
    //批量删除
    batchDeleteById(idList) {
      return request({
        url: `${api_name}/batchDeleteById`,
        method: 'delete',
        data:idList
      })
    }    
}

src/views/system/sysRole/list.vue

<template>
  <div class="app-container">

    <!--查询表单-->
    <div class="search-div">
      <el-form label-width="70px" size="small">
        <el-row>
          <el-col :span="24">
            <el-form-item label="角色名称">
              <el-input style="width: 100%" v-model="searchObj.roleName" placeholder="角色名称"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row style="display:flex">
          <el-button type="primary" icon="el-icon-search" size="mini"  @click="fetchData()">搜索</el-button>
          <el-button icon="el-icon-refresh" size="mini" @click="resetData">重置</el-button>
        </el-row>
      </el-form>
    </div>

    <!-- 工具条 -->
    <div class="tools-div">
      <el-button type="success" icon="el-icon-plus" size="mini" @click="add">添 加</el-button>
      <el-button class="btn-add" size="mini" @click="batchRemove()" >批量删除</el-button>
    </div>

    <el-dialog title="添加/修改" :visible.sync="dialogVisible" width="40%" >
      <el-form ref="dataForm" :model="sysRole" label-width="150px" size="small" style="padding-right: 40px;">
        <el-form-item label="角色名称">
          <el-input v-model="sysRole.roleName" placeholder="请输入角色名称" />
        </el-form-item>
        <el-form-item label="角色编码">
          <el-input v-model="sysRole.roleCode" placeholder="请输入角色编码"/>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false" size="small" icon="el-icon-refresh-right">取 消</el-button>
        <el-button type="primary" icon="el-icon-check" @click="saveOrUpdate()" size="small">确 定</el-button>
      </span>
    </el-dialog>

    <!-- 表格 -->
    <el-table
      v-loading="listLoading"
      :data="list"
      stripe
      border
      style="width: 100%;margin-top: 10px;"
      @selection-change="handleSelectionChange">  
       <!-- 添加复选框 -->
      <el-table-column type="selection"/>
       
      <el-table-column
        label="序号"
        width="70"
        align="center">
        <template slot-scope="scope">
          {{ (page - 1) * limit + scope.$index + 1 }}
        </template>
      </el-table-column>

      <el-table-column prop="roleName" label="角色名称" />
      <el-table-column prop="roleCode" label="角色编码" />
      <el-table-column prop="createTime" label="创建时间" width="160"/>
      <el-table-column prop="updateTime" label="更新时间" width="160"/>
      <el-table-column label="操作" width="200" align="center">
        <template slot-scope="scope">
          <el-button type="primary" icon="el-icon-edit" size="mini" @click="edit(scope.row.id)" title="修改"/>
          <el-button type="danger" icon="el-icon-delete" size="mini" @click="removeDataById(scope.row.id)" title="删除"/>
        </template>
      </el-table-column>
    </el-table>

      <!-- 分页组件 -->
      <el-pagination
        :current-page="page"
        :total="total"
        :page-size="limit"
        style="padding: 30px 0; text-align: center;"
        layout="total, prev, pager, next, jumper"
        @current-change="fetchData"
      />
  </div>
  
</template>
<script>

import api from '@/api/system/sysRole'
export default {
    
   data(){
      return{

        listLoading:false,//数据是否正在加载
        list:[],//角色列表
        total:0,//总记录数,默认为0
        page:1,//页码
        limit:3,//每页显示的条数 自定义3条
        searchObj:{}, //查询条件
        dialogVisible:false, //取消弹出角色的页面框
        sysRole:{},//添加角色 这个与上面的 v-model="sysRole.xx" 进行了双向绑定
        idList:[] //将所有选中的行存储到数组中,如 [1,2,3] 批量删除选中的记录列表
      }
   },
   created(){
        this.fetchData()
   },
   methods:{
          //选中要批量删除的行
          handleSelectionChange(selection){
              //将选中的行存入到selectValue数组中
              this.selectValue = selection
              //console.log(this.selectValue)
          },

          //批量删除
          batchRemove(){
            if(this.selectValue.length == 0){
              //alert('请选择要删除的记录!')
              this.$message.warning('请选择要删除的记录!')
              return
            }
            
            this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              //定义一个空数组
              var idList = [];
              //获取多个复选框对应的id值,封装到数组里面
              //遍历数组
              for(var i=0;i<this.selectValue.length;i++){
                  //遍历数组
                  var obj = this.selectValue[i]
                  var id = obj.id
                  // alert(id) 选中所有的 id 
                  idList.push(id)
              }
              //TODO
              // 点击确定,远程调用ajax
              api.batchDeleteById(idList).then(Response=>{
                    this.$message({
                    type: 'success',
                    message: '删除成功!'
                    });
                    //刷新页面或查询全部
                    this.fetchData()
                  })
              })
          },

          //添加修改角色,弹出后确定
          saveOrUpdate(){
              if(!this.sysRole.id){
                  this.saveRole()
              }else{
                
                this.updateSysRole()
              }  
          },

          updateSysRole(){
            api.updateById(this.sysRole)
            .then(Response=>{
                //1.提示
                this.$message({
                type: 'success',
                message: '修改成功!'
                });
                //2.关闭弹框
                this.dialogVisible = false,
                //3.刷新页面或查询全部
                this.fetchData()
            })
          },
          //修改角色,弹出后确定
          edit(id){

              api.getRoleById(id).then(Response=>{

                 //弹出框
                  this.dialogVisible = true
                  
                  this.sysRole  = Response.data
              })
          },
          //添加角色,弹出后确定
          saveRole(){
            if(this.sysRole.roleName != null && this.sysRole.roleCode != null){
              api.saveRole(this.sysRole).then(Response=>{
                      //1.提示
                      this.$message({
                      type: 'success',
                      message: '添加成功!'
                       });
                //2.关闭弹框
                this.dialogVisible = false,
                //3.刷新页面或查询全部
                this.fetchData()
              })
            }else{
              alert("请输入要添加的角色名称和角色编码!!!")
            }
          },
          //添加角色,弹出按钮
          add(){
              this.dialogVisible = true,
              this.sysRole = {}
          },

          // 根据id删除数据
          removeDataById(id){

              this.$confirm('此操作将永久删除该角色, 是否继续?', '提示', {
              confirmButtonText: '确定',
              cancelButtonText: '取消',
              type: 'warning'
            }).then(() => {
              // 点击确定,远程调用ajax
            api.removeById(id).then(Response =>{
                this.$message({
                type: 'success',
                message: '删除成功!'
                });
                //刷新页面或查询全部
                this.fetchData()
              })
            })
          },

        //重置
        resetData(){
            this.searchObj = {}
            this.fetchData()
        },

        //角色列表显示
        fetchData(pageNum = 1){

            this.page = pageNum;
            api.getPageList(this.page,this.limit,this.searchObj)
            .then(Response=>{
                console.log(Response)
                this.list = Response.data.records
                this.total = Response.data.total
            })
        }
   }
}
</script>

文章源码

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

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

相关文章

跨域解决 | 面试常问问题

跨域解决 | 面试常问问题 跨域问题一直是前端开发中不可避免的一部分&#xff0c;它涉及到浏览器的同源策略和安全机制。本文将深入解析跨域问题的本质&#xff0c;并探讨前端和后端的多种解决方案&#xff0c;同时分享一些扩展与高级技巧。最后&#xff0c;我们还将总结跨域解…

K8S系列——(二)、K8S部署RocketMQ集群

1、环境准备 要将RocketMQ部署到K8S上&#xff0c;首先你需要提前准备一个K8S集群环境&#xff0c;如图我已经准备好了一个版本为 v1.28.13 的 K8S 集群&#xff08;其他版本也没问题&#xff09;&#xff1a; 角色IPMaster192.168.6.220Node-1192.168.6.221Node-2192.168.6.…

浏览器不开梯子无法上网,检查代理或防火墙或者找不到服务器ip地址

1、代理没有关闭 检查代理是否关闭 检查方法1&#xff1a; 在控制面版中找到Internet选项&#xff0c;点击连接栏&#xff0c;在连接栏中选择局域网设置。之后将代理服务器下面的框选中的对勾取消。最终如下 检查方法2&#xff1a; 打开设置&#xff0c;找到网络和internet…

书生浦语大模型实战营:LMDeploy量化部署

1.任务&#xff1a; 使用结合W4A16量化与kv cache量化的internlm2_5-1_8b-chat模型封装本地API并与大模型进行一次对话。 2.背景&#xff1a; 1.计算模型需要的权重大小&#xff1a; 1B代表10个亿参数&#xff0c;假如是16位浮点数&#xff08;f16&#xff09;&#xff0c;也…

计算机视觉概念科普

计算机视觉&#xff08;Computer Vision, CV&#xff09;是一门多学科交叉的科学&#xff0c;旨在让计算机具备“看”的能力&#xff0c;即通过图像或视频数据来理解世界。它结合了信号处理、图像处理、模式识别、机器学习等多个领域的技术&#xff0c;让计算机能够执行诸如识别…

【Python学习手册(第四版)】学习笔记20.2-迭代和解析(二)-迭代解析、迭代方法的计时比较、函数陷阱

个人总结难免疏漏&#xff0c;请多包涵。更多内容请查看原文。本文以及学习笔记系列仅用于个人学习、研究交流。 本文较简单&#xff0c;主要是概括了解析语法&#xff08;列表解析、生成器、集合、字典解析&#xff09;&#xff0c;以及对前面的各种迭代进行计时比较&#xf…

通过python解决原神解密

最近楼主玩原神世界任务做到稻妻了&#xff0c;在稻妻有很多解密游戏&#xff0c;但是博主最头疼的就是稻妻的石头解密QAQ&#xff08;如图&#xff09; 就在昨晚&#xff0c;楼主又碰到了石头解密&#xff0c;瞎打&#xff0c;半天解不出来。于是就想&#xff0c;有没有什么严…

如何在Windows下使用make编译Makefile

最近有小伙伴咨询我去编译运行一个程序。我一开始以为是CMakeLists&#xff0c;结果发现是makefile。 什么是Makefile ‌Makefile是一种用于自动化构建和管理程序的工具‌&#xff0c;它定义了项目中文件的依赖关系和构建步骤&#xff0c;帮助程序员自动化编译、链接和打包程序…

Ps:创建帧动画

在 Photoshop 中&#xff0c;帧动画 Frame Animation是一种通过在“时间轴”面板中创建和管理多个帧来实现动画效果的方式。 所谓帧动画&#xff0c;也就是传统意义上的逐帧动画&#xff0c;依次播放每个帧而构成的动画形式。每个帧记录了“图层”面板上所有图层的属性状态&…

QT Mainwindow下指定控件的setMouseTracking(true)和mousemoveevent函数失效-问题解决

目录&#xff1a; 一&#xff0c;问题描述二&#xff0c;解决方法2.1解决依据2.2方法实操 三&#xff0c;参考资料 一&#xff0c;问题描述 ☀️之前碰到过的一个问题&#xff0c;现在分享出来&#xff1a;想在qt哪里搞个鼠标移动在控件显示的图片上&#xff0c;然后实时显示对…

[数据集][目标检测]红外场景下车辆和行人检测数据集VOC+YOLO格式19069张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;19069 标注数量(xml文件个数)&#xff1a;19069 标注数量(txt文件个数)&#xff1a;19069 标…

一文带你画PCB板,有手就行

背景 最近写Autosar网络唤醒功能&#xff0c;想在实际硬件上验证&#xff0c;但是市面上没有找到板子验证&#xff0c;只能找人帮忙画PCB板。但是这里遇到比较大的问题&#xff0c;1、整个周期会比较长&#xff0c;板子不太可能一次就能完成&#xff0c;中间会出现修改的地方&…

C#/.NET/.NET Core技术前沿周刊 | 第 1 期(2024年8.12-8.18)

前言 C#/.NET/.NET Core技术前沿周刊&#xff0c;你的每周技术指南针&#xff01;记录、追踪C#/.NET/.NET Core领域、生态的每周最新、最实用的技术文章、社区动态、优质项目和学习资源等。让你时刻站在技术前沿&#xff0c;助力技术成长与视野拓宽。 欢迎投稿&#xff0c;推荐…

【蓝牙协议栈】【BLE】【GATT】精讲GATT Profile架构(图文并茂精华版)

目录 1. 蓝牙BLE通用属性协议&#xff08;GATT&#xff09; 2.GATT角色介绍 3.GATT 层级和Profile架构 4. GATT Server架构&#xff08;重点内容&#xff09; 5. Characteristic架构&#xff08;重点内容&#xff09; 6. (Characteristic Properties)特性属性详解&#x…

一款免费的目录以及文件对比工具,替代Beyond Compare

Beyond Compare是一款功能强大的文件对比工具&#xff0c;但是由于是付费软件&#xff0c;很多没有购买的企业用户无法使用。CCompare就是一款替代Beyond Compare的免费方案&#xff0c;一款来自中国的可替换beycond compare, 免费使用的代码同步对比工具。 CCompare 是一款功…

【科研绘图】【分条热力图】:附Origin详细画图流程 + 案例分析

目录 No.1 理解分条热力图 No.2 画图流程 1 导入数据&#xff0c;绘制图形 2 设置绘图细节 3 色阶控制 4 设置坐标轴 5 效果图 No.3 案例分析 1 案例一 2 案例二 No.1 理解分条热力图 分条热力图&#xff0c;基于数据映射和颜色编码&#xff0c;是在热力图的基础上进…

聚星文社下载地址

聚星文社绘唐科技是一个文化传媒公司&#xff0c;以绘制唐朝相关的科技设备和场景为主题。该公司致力于通过插画、动画、游戏等形式&#xff0c;栩栩如生地展现唐朝时期的科技发展和生活场景。 聚星文社下载地址https://iimenvrieak.feishu.cn/docx/ZhRNdEWT6oGdCwxdhOPcdds7n…

unity Standard Assets资源商店无法安装解决方案

Unity游戏开发 “好读书&#xff0c;不求甚解&#xff1b;每有会意&#xff0c;便欣然忘食。” 本文目录&#xff1a; Unity游戏开发 Unity游戏开发unity中国 嗨嗨嗨&#xff0c;我来啦。 这几天的川渝之旅已经圆满结束了&#xff0c;今天开始正常给大家更新&#xff1a; Unity…

TiggerRamDisk绕过激活界面,支持最新iOS17.4.1绕过

iOS15等待越狱的日子实在太久了&#xff01;checkra1n越狱目前还未发布iOS15系统越狱。 可很多朋友不小心或者大意已经升级到了最新iOS15系统。一般来说这并没有什么大碍&#xff0c;但如果是绕过激活的设备&#xff0c;或者忘记账户密码而刷机的设备&#xff0c;就会面临无法…

【计算机组成原理】强化部分笔记

第一章 计算机系统概述 考点1 计算机系统层次结构 1.计算机发展历程已从大纲中删去 2. 3.指令和数据都存放在存储器中&#xff0c;通过指令周期不同来区分&#xff08;比如取指周期和执行周期&#xff09; 现代的计算机以存储器为中心 4. 5. 6.汇编语言&#xff1a;STORE、L…