首页 > 其他分享 >REDME-dev

REDME-dev

时间:2024-12-13 08:59:48浏览次数:3  
标签:src return res system REDME dev message data

XX后台管理系统

1.技术选型与环境要求

1.1 项目技术选型

1.1.1 前端技术

HTML 5
CSS 3
lavaScript
Vue
Element UI

1.1.2 后端技术

SpringBoot
MyBatis Plus
Spring Security
jwt
DM8

1.2 项目环境要求

1.2.1前端环境要求

node.js
VSCode
git

1.2.2 后端环境要求

jdk8 +
maven 3.6 +
Spring Boot 2+
开发工具:idea
git

2. 搭建前端项目环境

1 环境安装

node

2 脚手架下载

2.1 下载地址

vue-admin-template-master.zip

https://github.com/PanJiaChen/vue-admin-template.git

2.2 项目重命名

解压vue-admin-template-master.zip到指定项目文件夹,不要带中文、空格、特殊字符的文件夹下面。

修改vue-admin-template-master项目名称和文件名称为自己项目名称:x-dm-pc

3 脚手架启动

3.1 进入项目目录

cd x-dm-pc

3.2 安装依赖

npm install

3.3 淘宝镜像

解决依赖下载速度慢的问题,安装淘宝镜像

npm install --registry=https://registry.npm.taobao.org

3.4 启动服务

npm run dev

3.5 浏览器访问

http://localhost:9528

4 项目配置修改

4.1 项目端口修改

vue.config.js

const name = defaultSettings.title || 'XX后台管理系统' // page title
const port = process.env.port || process.env.npm_config_port || 6666 // dev port

4.2 项目名称修改

package.json、package-lock.json

name: x-dm-pc

4.3 项目标题修改

src\settings.js

src\utils\get-page-title.js

title: 'XX后台管理系统'

4.4 项目首页修改

src\router\index.js

{
path: '/',
component: Layout,
redirect: '/dashboard',
children: [{
  path: 'dashboard',
  name: 'Dashboard',
  component: () => import('@/views/dashboard/index'),
  meta: { title: '系统首页', icon: 'dashboard' }
  }]
}

4.5 项目logo修改

src\layout\components\Sidebar\Logo.vue

data() {
  return {
  title: 'XX后台管理系统',
  logo: 'https://wpimg.wallstcn.com/69a1c46c-eb1c-4b46-8bd4-e9e686ef5251.png'
  }
}

5 登录组件修改

5.1 登录框样式修改

src\view\login\Login.vue

<template>
  <div class="login-container">
    <el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on" label-position="left">

      <div class="title-container">
        <h3 class="title">XX后台管理系统</h3>
      </div>

      <el-form-item prop="username">
        <span class="svg-container">
          <svg-icon icon-class="user" />
        </span>
        <el-input
          ref="username"
          v-model="loginForm.username"
          placeholder="请输入用户名"
          name="username"
          type="text"
          tabindex="1"
          auto-complete="on"
        />
      </el-form-item>

      <el-form-item prop="password">
        <span class="svg-container">
          <svg-icon icon-class="password" />
        </span>
        <el-input
          :key="passwordType"
          ref="password"
          v-model="loginForm.password"
          :type="passwordType"
          placeholder="请输入密码"
          name="password"
          tabindex="2"
          auto-complete="on"
          @keyup.enter.native="handleLogin"
        />
        <span class="show-pwd" @click="showPwd">
          <svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
        </span>
      </el-form-item>

      <el-button :loading="loading" type="primary" style="width:100%;margin-bottom:30px;" @click.native.prevent="handleLogin">登 录</el-button>

      <!--  提示不需要注释掉    -->
      <!-- <div class="tips">
        <span style="margin-right:20px;">username: admin</span>
        <span> password: any</span>
      </div> -->

    </el-form>
  </div>
</template>

<script>
import { validUsername } from '@/utils/validate'

export default {
  name: 'Login',
  data() {
    const validateUsername = (rule, value, callback) => {
      if (!validUsername(value)) {
        callback(new Error('请输入正确的用户名'))
      } else {
        callback()
      }
    }
    const validatePassword = (rule, value, callback) => {
      if (value.length < 6) {
        callback(new Error('密码长度不能小于6位'))
      } else {
        callback()
      }
    }
    return {
      loginForm: {
        username: 'admin',
        password: '111111'
      },
      loginRules: {
        username: [{ required: true, trigger: 'blur', validator: validateUsername }],
        password: [{ required: true, trigger: 'blur', validator: validatePassword }]
      },
      loading: false,
      passwordType: 'password',
      redirect: undefined
    }
  },
  watch: {
    $route: {
      handler: function(route) {
        this.redirect = route.query && route.query.redirect
      },
      immediate: true
    }
  },
  methods: {
    showPwd() {
      if (this.passwordType === 'password') {
        this.passwordType = ''
      } else {
        this.passwordType = 'password'
      }
      this.$nextTick(() => {
        this.$refs.password.focus()
      })
    },
    handleLogin() {
      this.$refs.loginForm.validate(valid => {
        if (valid) {
          this.loading = true
          this.$store.dispatch('user/login', this.loginForm).then(() => {
            this.$router.push({ path: this.redirect || '/' })
            this.loading = false
          }).catch(() => {
            this.loading = false
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    }
  }
}
</script>

<style lang="scss">
/* 修复input 背景不协调 和光标变色 */
/* Detail see https://github.com/PanJiaChen/vue-element-admin/pull/927 */

$bg:#283443;
$light_gray:#fff;
$cursor: #fff;

@supports (-webkit-mask: none) and (not (cater-color: $cursor)) {
  .login-container .el-input input {
    color: $cursor;
  }
}

/* reset element-ui css */
.login-container {
  .el-input {
    display: inline-block;
    height: 47px;
    width: 85%;

    input {
      background: transparent;
      border: 0px;
      -webkit-appearance: none;
      border-radius: 0px;
      padding: 12px 5px 12px 15px;
      color: $light_gray;
      height: 47px;
      caret-color: $cursor;

      &:-webkit-autofill {
        box-shadow: 0 0 0px 1000px $bg inset !important;
        -webkit-text-fill-color: $cursor !important;
      }
    }
  }

  .el-form-item {
    border: 1px solid rgba(255, 255, 255, 0.1);
    background: rgba(0, 0, 0, 0.1);
    border-radius: 5px;
    color: #454545;
  }
}
</style>

<style lang="scss" scoped>
$bg:#2d3a4b;
$dark_gray:#889aa4;
$light_gray:#eee;

.login-container {
  min-height: 100%;
  width: 100%;
  background-color: $bg;
  overflow: hidden;
  
  background-image: url('../../assets/img/bg.jpg');
  background-size: 100%;
  display: flex;
  align-items: center;
  .login-form {
    position: relative;
    width: 520px;
    max-width: 100%;
    padding: 35px 35px 0;
    margin: 0 auto;
    overflow: hidden;
    background-color: #2d3a4b;
    border-radius: 10px;
    opacity: 0.6;
  }

  // .login-form {
  //   position: relative;
  //   width: 520px;
  //   max-width: 100%;
  //   padding: 160px 35px 0;
  //   margin: 0 auto;
  //   overflow: hidden;
  // }

  .tips {
    font-size: 14px;
    color: #fff;
    margin-bottom: 10px;

    span {
      &:first-of-type {
        margin-right: 16px;
      }
    }
  }

  .svg-container {
    padding: 6px 5px 6px 15px;
    color: $dark_gray;
    vertical-align: middle;
    width: 30px;
    display: inline-block;
  }

  .title-container {
    position: relative;

    .title {
      font-size: 26px;
      color: $light_gray;
      margin: 0px auto 40px auto;
      text-align: center;
      font-weight: bold;
    }
  }

  .show-pwd {
    position: absolute;
    right: 10px;
    top: 7px;
    font-size: 16px;
    color: $dark_gray;
    cursor: pointer;
    user-select: none;
  }
}
</style>

5.2 背景图片增加

background-image: url('../../assets/img/bg.jpg');
background-size: 100%;
display: flex;
align-items: center;
.login-form {
  position: relative;
  width: 520px;
  max-width: 100%;
  padding: 35px 35px 0;
  margin: 0 auto;
  overflow: hidden;
  background-color: #2d3a4b;
  border-radius: 10px;
  opacity: 0.6;
}

6 用户下拉菜单修改

src\layout\components\Navbar.vue

<el-dropdown-menu slot="dropdown" class="user-dropdown">
  <router-link to="/">
    <el-dropdown-item>
      系统首页
    </el-dropdown-item>
  </router-link>
  <a target="_blank" href="">
    <el-dropdown-item>个人中心</el-dropdown-item>
  </a>
  <a target="_blank" href="">
    <el-dropdown-item>使用手册</el-dropdown-item>
  </a>
  <el-dropdown-item divided
  @click.native="logout">
  <span style="display:block;">注销登录</span>
</el-dropdown-item>

7.系统管理

7.1 新增系统管理组件

在src\view\system\新建系统管理组件

src\view\system\user\index.vue
src\view\system\role\index.vue
src\view\system\menu\index.vue

7.2 菜单路由修改

src\router\index.js
7.2.1 删除不需要的路由
/*
{
  path: '/example',
  component: Layout,
  redirect: '/example/table',
  name: 'Example',
  meta: { title: 'Example', icon: 'el-icon-s-help' },
  children: [
    {
      path: 'table',
      name: 'Table',
      component: () => import('@/views/table/index'),
      meta: { title: 'Table', icon: 'table' }
    },
    {
      path: 'tree',
      name: 'Tree',
      component: () => import('@/views/tree/index'),
      meta: { title: 'Tree', icon: 'tree' }
    }
  ]
},

{
path: '/form',
component: Layout,
children: [
    {
      path: 'index',
      name: 'Form',
      component: () => import('@/views/form/index'),
      meta: { title: 'Form', icon: 'form' }
    }
  ]
},

{
path: '/nested',
component: Layout,
redirect: '/nested/menu1',
name: 'Nested',
meta: {
title: 'Nested',
icon: 'nested'
},
children: [
{
  path: 'menu1',
  component: () => import('@/views/nested/menu1/index'), // Parent router-view
  name: 'Menu1',
  meta: { title: 'Menu1' },
  children: [
  {
    path: 'menu1-1',
    component: () => import('@/views/nested/menu1/menu1-1'),
    name: 'Menu1-1',
    meta: { title: 'Menu1-1' }
  },
  {
  path: 'menu1-2',
  component: () => import('@/views/nested/menu1/menu1-2'),
  name: 'Menu1-2',
  meta: { title: 'Menu1-2' },
  children: [
    {
    path: 'menu1-2-1',
    component: () => import('@/views/nested/menu1/menu1-2/menu1-2-1'),
    name: 'Menu1-2-1',
    meta: { title: 'Menu1-2-1' }
    },
    {
    path: 'menu1-2-2',
    component: () => import('@/views/nested/menu1/menu1-2/menu1-2-2'),
    name: 'Menu1-2-2',
    meta: { title: 'Menu1-2-2' }
    }
  ]
  },
  {
  path: 'menu1-3',
  component: () => import('@/views/nested/menu1/menu1-3'),
  name: 'Menu1-3',
      meta: { title: 'Menu1-3' }
      }
    ]
  },
{
path: 'menu2',
component: () => import('@/views/nested/menu2/index'),
name: 'Menu2',
    meta: { title: 'menu2' }
    }
  ]
},
  
{
path: 'external-link',
component: Layout,
children: [
    {
    path: 'https://panjiachen.github.io/vue-element-admin-site/#/',
    meta: { title: 'External Link', icon: 'link' }
    }
  ]
},  
*/
7.2.2 新增系统管理路由
{
  path: '/system',
  component: Layout,
  redirect: '/system',
  name: 'systemManage',
  meta: { title: '系统管理', icon: 'el-icon-menu' },
  children: [
    {
      path: 'user',
      name: 'user',
      component: () => import('@/views/system/user/index'),
      meta: { title: '用户管理', icon: 'el-icon-user' }
    },
    {
      path: 'role',
      name: 'role',
      component: () => import('@/views/system/role/index'),
      meta: { title: '角色管理', icon: 'el-icon-s-custom' }
    }, 
    {
      path: 'menu',
      name: 'menuList',
      component: () => import('@/views/system/menu/index'),
      meta: { title: '菜单管理', icon: 'el-icon-s-custom' }
    }
  ]
}
7.2.3 导航栏首页标题修改
src\components\Breadcrumb\index.vue
if (!this.isDashboard(first)) {
  matched = [{ path: '/dashboard', meta: { title: '系统首页' }}].concat(matched)
}

8 快捷导航(标签栏导航)

8.1 新增监听路由

src\layout\components\AppMain.vue

<!-- 1. 注释掉原先路由跳转,并新增监听缓存页面的路由跳转 -->
<!-- <router-view :key="key" /> -->
    <keep-alive :include="cachedViews">
    	<router-view :key="key" />
    </keep-alive>
    
computed: {
  key() {
    return this.$route.path
  },
  <!-- 2. 在计算属性中新增缓存的页面 -->
  cachedViews() {
  	// 注意:从state中取cachedViews值的路径,路径错误会导致cachedViews无法读取的错误 		    	// [Vue warn]: Error in render: "TypeError: Cannot read properties of undefined 		// (reading 'cachedViews')"
    // return this.$store.state.tagView.cachedViews
      return this.$store.state.tagsView.cachedViews
  }
}

8.2 复制标签组件

复制集成方案vue-element-admin中的文件到相应的目录中

src\layout\components\TagsView
src\store\modules\tagsView.js
src\store\modules\permission.js

8.3 获取标签组件

修改src\store\getters.js

visitedViews: state => state.tagsView.visitedViews,
cachedViews: state => state.tagsView.cachedViews,
permission_routers: state => state.permission.routers,
addRouters: state => state.permission.addRouters

8.4 将标签组件存入状态管理库

修改src\store\index.js

import permission from './modules/permission'
import tagsView from './modules/tagsView'
modules: {
  app,
  settings,
  user,
  permission,
  tagsView
},

8.5 将标签组件公布成全局组件

src\layout\components\index.js

export { default as TagsView } from './TagsView'

8.6 使用标签组件

src\layout\index.vue

// 1. 导入TagsView标签组件
import { Navbar, Sidebar, AppMain, TagsView } from './components'
components: {
    Navbar,
    Sidebar,
    AppMain,
    TagsView
},
<div :class="{'fixed-header':fixedHeader}">
    <navbar />
    <!-- 2. 导航栏中添加tagsView标签组件 -->
    <tags-view />
</div>

8.7 使用标签组件错误处理

8.7.1 错误一:编译错误

image-20241128084949847

①复制集成方案vue-element-admin中的ParentView到src\components下

②复制集成方案vue-element-admin中的routers.js到src\router下

③修改src\layout\components\index.js中公布标签组件路径

修改:export { default as TagsView } from '../TagsView'

成为:export { default as TagsView } from './TagsView'

ERROR  Failed to compile with 3 errors  
These dependencies were not found:

* @/components/ParentView in ./src/store/modules/permission.js
* @/router/routers in ./src/store/modules/permission.js

To install them, you can run: npm install --save @/components/ParentView @/router/routers

This relative module was not found:

* ../TagsView in ./src/layout/components/index.js
8.7.2 错误二:刷新tab标签丢失

页面刷新后点开的导航标签丢失

8.7.2.1 刷新前

image-20241128094627083

8.7.2.2 刷新后

image-20241128094835945

8.7.2.3 解决步骤

第一步:在 \src\layout\components\TagsView\index.vue添加调用

mounted() {
  this.initTags()
  this.addTags()
  this.tagsViewCache()
},

第二步:添加方法(实现效果)

tagsViewCache() {
  window.addEventListener('beforeunload', () => {
    const tabViews = this.visitedViews.map(item => {
      return {
        fullPath: item.fullPath,
        hash: item.hash,
        meta: { ...item.meta },
        name: item.name,
        params: { ...item.params },
        path: item.path,
        query: { ...item.query },
        title: item.title
      }
    })
    sessionStorage.setItem('tabViews', JSON.stringify(tabViews))
  })
  const oldViews = JSON.parse(sessionStorage.getItem('tabViews')) || []
  if (oldViews.length > 0) {
    this.$store.state.tagsView.visitedViews = oldViews
  }
},
8.7.3 错误三:cachedViews错误

这个问题是由于在AppMain.vue中引用cachedViews错误,解决:修改cachedViews引用路径

image-20241128095349997

// 2. 在计算属性中新增缓存的页面
cachedViews() {
  // TODO 注意:从state中取cachedViews值的路径,路径错误会导致cachedViews无法读取的错误,
  // TODO [Vue warn]: Error in render: "TypeError: Cannot read properties of undefined (reading 'cachedViews')"
  // return this.$store.state.tagView.cachedViews
  return this.$store.state.tagsView.cachedViews
}

image-20241128103455726

8.7.4 错误四:显示上次登录页面

注销的时候删除所有的tagView,重新登录或换用户登录后,会显示上次登录的页面

image-20241128104936021

在 \src\layout\components\Navbar.vue 添加

,
/* async logout() {
  await this.$store.dispatch('user/logout')
  this.$router.push(`/login?redirect=${this.$route.fullPath}`)
} */
async logout() {
  await this.$store.dispatch('user/logout')
  await this.$store.dispatch('tagsView/delAllViews')
  sessionStorage.removeItem('tabViews')
  // 这里如果不改的情况下,重新登录或换用户登录后,会显示上次登录的页面
  // this.$router.push(`/login?redirect=${this.$route.fullPath}`)
  this.$router.push(`/login`)
}

8.7.5 错误四:默认Tab标签可以删除

image-20241128105922944

image-20241128105938199

设置默认Tab标签不能删除

// meta: { title: '系统首页', icon: 'dashboard' }
meta: { title: '系统首页', icon: 'dashboard', affix: true, noCache: false }

image-202411281102125049 登录接口梳理

9.1 登录所需接口

接口名称 url method
登录 /user/login post
获取用户信息 /user/info get
注销 /user/logout post
9.1.1 用户登录
// 请求
http://localhost:8888/dev-api/vue-admin-template/user/login
{username: "admin", password: "111111"}
// 响应
{"code":20000,"data":{"token":"admin-token"}}
9.1.2 获取用户信息
// 请求
http://localhost:8888/dev-api/vue-admin-template/user/info?token=admin-token
{token: "admin-token"}
// 响应
{
  "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"
  }
}
9.1.3 注销登录
// 请求
http://localhost:8888/dev-api/vue-admin-template/user/logout
{token: "admin-token"}
// 响应
{"code":20000,"data":"success"}

10 前后端对接

10.1 修改后端接口规格一致

在src\api\user.js中将前端请求接口地址与后端接口地址一致。

10.1.1 登录接口
前端请求接口地址:url: '/vue-admin-template/user/login' 
后端接口地址:url: '/system/user/login' 
10.1.2 获取用户信息接口
前端请求接口地址:url: '/vue-admin-template/user/info' 
后端接口地址:url: '/system/user/info'
10.1.3 注销登录
前端请求接口地址: url: '/vue-admin-template/user/logout'
后端接口地址:url: '/system/user/logout'

10.2 修改前端请求后端配置

修改配置文件:.env.development

# VUE_APP_BASE_API = '/api'
VUE_APP_BASE_API = 'http://localhost:9999'

10.3 注释mock模拟服务

注释掉 vue.config.js 中mock服务

// before: require('./mock/mock-server.js')

10.4 解决前后端跨越问题

注意,修改后需要重新启动项目,前端请求后端接口会出现跨越问题,可以前端nginx代理解决,也可以后端配置过滤器解决,这里选择的后端配置过滤器解决

Access to XMLHttpRequest at 'http://localhost:9999/system/user/login' from origin 
'http://localhost:9528' has been blocked by CORS policy: Response to preflight request
doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

11 系统管理

用户管理布局中内边距需要在src\App.vue中设置

<style>
.app-main {
  padding: 10px;
}
</style>

Vue.js Devtools 极简插件下载 ,非常友好

https://chrome.zzzmh.cn/info/nhdogjmejiglipccpnnnanhbledajbpd

11.1 用户管理

11.1.1 用户列表

11.1.1 界面布局
<template>
  <div>
    <!-- 搜索栏 -->
    <el-card id="search">
      <el-row>
        <el-col :span="20">
          <el-input v-model="searchModel.username" placeholder="请输入用户名" />
          <el-input v-model="searchModel.phone" placeholder="请输入电话号码" />
          <el-button type="primary" round icon="el-icon-search">搜索</el-button>
        </el-col>
        <el-col :span="4" align="right">
          <el-button type="primary" icon="el-icon-plus" circle />
        </el-col>
      </el-row>
    </el-card>
    <!-- 用户列表 -->
    <el-card>
      <el-table stripe style="width: 100%">
        <el-table-column label="#" width="80" align="center">
          <template slot-scope="scope">
            {{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column prop="" label="账户" align="center" />
        <el-table-column prop="" label="邮箱" align="center" />
        <el-table-column prop="" label="状态" align="center">
          <template slot-scope="scope">
            {{ scope.row.status !== 1 ? '停用' : '启用' }}
          </template>
        </el-table-column>
        <el-table-column prop="" label="电话" align="center" />
        <el-table-column label="操作" width="200" align="center">
          <template>
            <el-button type="primary" icon="el-icon-edit" circle size="small" />
            <el-button type="danger" icon="el-icon-delete" circle size="small" />
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 分页 -->
    <el-pagination
      :current-page="searchModel.pageNo"
      :page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
      :page-size="searchModel.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import userManage from '@/api/system/userManage'

export default {
  name: 'Index',
  data() {
    return {
      userList: [],
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 5,
        username: '',
        phone: ''
      }
    }
  },
  mounted() {
  },
  created() {
  },
  methods: {
  }
}
</script>

<style scoped lang="scss">
#search .el-input {
  width: 160px;
  margin-right: 10px;
}
</style>
11.1.2 用户列表
11.1.2.1 新增请求

第一步: 新增请求后端api接口

src\api\system\userManage.js

import request from '@/utils/request'

export default {
    // 查询用户列表
    getUserList(searchModel) {
        return request({
            url: '/system/user/list',
            method: 'get',
            params: {
                pageNo: searchModel.pageNo,
                pageSize: searchModel.pageSize,
                username: searchModel.username,
                phone: searchModel.phone
            }
        })
    }
}
11.1.2.2 发送请求

第二步: 发送获取用户列表请求

src\views\system\user\index.vue

①引入请求后端api接口

import userManage from "@/api/system/userManage";

②发送获取用户列表请求

// 1.获取用户列表
getUserList()
{
    userManage.getUserList(this.searchModel).then(res => {
            this.userList = res.data.records
            this.total = res.data.total
    })
}
11.1.2.3 数据回显

第三步: 前端用户列表数据展示

①在data中定义userList接收后端返回的用户列表数据

  data() {
    return {
      userList: [],
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 5,
        username: '',
        phone: ''
      },
      userList: []
    };
  },

②将后端查询的用户列表数据赋值给userList数组对象

 getUserList() {
      userManage.getUserList(this.searchModel).then(res => {
        // console.log("1.用户列表",res.data);
        this.userList = res.data.rows;
        this.total = res.data.total;
      });
    },

③将数据赋值表格中的userList,然后将属性值赋值给对应的字段

<el-table :data="userList" stripe style="width: 100%">

全部代码如下:

<template>
  <div>
    <!-- 搜索栏 -->
    <el-card id="search">
      <el-row>
        <el-col :span="20">
          <el-input v-model="searchModel.username" placeholder="请输入用户名" />
          <el-input v-model="searchModel.phone" placeholder="请输入电话号码" />
          <el-button type="primary" round icon="el-icon-search" @click="getUserList">搜索</el-button>
        </el-col>
        <el-col :span="4" align="right">
          <el-button type="primary" icon="el-icon-plus" circle />
        </el-col>
      </el-row>
    </el-card>
    <!-- 用户列表 -->
    <el-card>
      <el-table :data="userList" stripe style="width: 100%">
        <el-table-column label="#" width="80" align="center">
          <template slot-scope="scope">
            {{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column prop="username" label="账户" align="center" />
        <el-table-column prop="email" label="邮箱" align="center" />
        <el-table-column prop="status" label="状态" align="center">
          <template slot-scope="scope">
            {{ scope.row.status !== 1 ? '停用' : '启用' }}
          </template>
        </el-table-column>
        <el-table-column prop="phone" label="电话" align="center" />
        <el-table-column label="操作" width="200" align="center">
          <template>
            <el-button type="primary" icon="el-icon-edit" circle size="small" />
            <el-button type="danger" icon="el-icon-delete" circle size="small" />
          </template>
        </el-table-column>
      </el-table>
    </el-card>

    <!-- 分页 -->
    <el-pagination
      :current-page="searchModel.pageNo"
      :page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
      :page-size="searchModel.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import userManage from '@/api/system/userManage'

export default {
  name: 'Index',
  data() {
    return {
      userList: [],
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 5,
        username: '',
        phone: ''
      }
    }
  },
  mounted() {
    this.getUserList()
  },
  created() {
    this.getUserList()
  },
  methods: {
    // 1.获取用户列表
    getUserList() {
      userManage.getUserList(this.searchModel).then(res => {
        this.userList = res.data.rows
        this.total = res.data.total
      })
    },
    handleSizeChange(pageSize) {
      this.searchModel.pageSize = pageSize
      this.getUserList()
    },
    handleCurrentChange(pageNo) {
      this.searchModel.pageNo = pageNo
      this.getUserList()
    }
  }
}
</script>

<style scoped lang="scss">
#search .el-input {
  width: 160px;
  margin-right: 10px;
}
</style>
11.1.3 新增用户
11.1.3.1 界面布局
<!--  新增用户  -->
<el-dialog title="新增用户" :visible.sync="dialogFormVisible" @close="clearForm">
  <el-form ref="userFormRef" :rules="rules" :model="userForm">
    <el-form-item label="账户" :label-width="formLabelWidth" prop="username">
      <el-input v-model="userForm.username" autocomplete="off" />
    </el-form-item>
    <el-form-item v-if="userForm.id == null || userForm.id == undefined" label="密码" :label-width="formLabelWidth" prop="password">
      <el-input v-model="userForm.password" type="password" autocomplete="off" />
    </el-form-item>
    <el-form-item label="状态" :label-width="formLabelWidth" prop="status">
      <el-switch
        v-model="userForm.status"
        :active-value="0"
        :inactive-value="1"
      />
    </el-form-item>
    <el-form-item label="邮箱" :label-width="formLabelWidth" prop="email">
      <el-input v-model="userForm.email" autocomplete="off" />
    </el-form-item>
    <el-form-item label="电话" :label-width="formLabelWidth" prop="phone">
      <el-input v-model="userForm.phone" autocomplete="off" />
    </el-form-item>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogFormVisible = false">取 消</el-button>
    <el-button type="primary" @click="dialogFormVisible = false">确 定</el-button>
  </div>
</el-dialog>

data函数中规则和接收数组定义

rules: {
  username: [
    { required: true, message: '请输入账户名', trigger: 'blur' }
  ],
  password: [
    { required: true, message: '请输入密码', trigger: 'blur' }
  ],
  email: [
    { required: true, message: '请输入邮箱', trigger: 'blur' },
    { validator: checkEmail, trigger: 'blur' }
  ],
  phone: [
    { required: true, message: '请输入电话', trigger: 'blur' },
    { validator: checkPhone, trigger: 'blur' }
  ]
},
userForm: {
  username: '',
  password: '',
  status: '',
  email: '',
  phone: ''
},
dialogFormVisible: false,
formLabelWidth: '120px',
const checkEmail = (rule, value, callback) => {
  const reg = /^([a-zA-Z]|[0-9])(\w|\-|\.)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
  if (!value) return callback(new Error('请输入收件人邮箱'))
  if (!reg.test(value)) {
    callback(new Error('邮箱格式错误'))
  } else {
    callback()
  }
}
const checkPhone = (rule, value, callback) => {
  const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
  if (!value) return callback(new Error('请输入联系人电话'))
  if (!reg.test(value)) {
    callback(new Error('电话格式错误'))
  } else {
    callback()
  }
}
11.1.3.2 新增请求

①在src\api\system\userManage.js新增请求

// 2.添加用户
addUser(user) {
  return request({
    url: '/system/user',
    method: 'post',
    data: user
  })
}
11.1.3.3 发送请求
// 2.添加用户
saveUser() {
  // 触发表单验证
  this.$refs.userFormRef.validate((valid) => {
    if (valid) {
      // 提交请求给后台
      userManage.addUser(this.userForm).then(res => {
        // 成功提示
        this.$message({
          type: 'success',
          message: res.message
        })
        // 关闭对话框
        this.dialogFormVisible = false
        // 刷新表格数据
        this.getUserList()
      })
    } else {
      console.log('error submit!!')
      return false
    }
  })
},
11.1.3.4 数据回显
<!--  添加用户  -->
<el-dialog title="添加用户" :visible.sync="dialogFormVisible" @close="clearForm">
  <el-form ref="userFormRef" :rules="rules" :model="userForm">
    <el-form-item label="账户" :label-width="formLabelWidth" prop="username">
      <el-input v-model="userForm.username" autocomplete="off" />
    </el-form-item>
    <el-form-item label="密码" :label-width="formLabelWidth" prop="password">
      <el-input v-model="userForm.password" type="password" autocomplete="off" />
    </el-form-item>
    <el-form-item label="状态" :label-width="formLabelWidth" prop="status">
      <el-switch
        v-model="userForm.status"
        :active-value="0"
        :inactive-value="1"
      />
    </el-form-item>
    <el-form-item label="邮箱" :label-width="formLabelWidth" prop="email">
      <el-input v-model="userForm.email" autocomplete="off" />
    </el-form-item>
    <el-form-item label="电话" :label-width="formLabelWidth" prop="phone">
      <el-input v-model="userForm.phone" autocomplete="off" />
    </el-form-item>
  </el-form>
  <div slot="footer" class="dialog-footer">
    <el-button @click="dialogFormVisible = false">取 消</el-button>
    <el-button type="primary" @click="saveUser">确 定</el-button>
  </div>
</el-dialog>

全部代码为:

<template>
  <div>
    <!-- 搜索栏 -->
    <el-card id="search">
      <el-row>
        <el-col :span="20">
          <el-input v-model="searchModel.username" placeholder="请输入用户名" />
          <el-input v-model="searchModel.phone" placeholder="请输入电话号码" />
          <el-button type="primary" round icon="el-icon-search" @click="getUserList">搜索</el-button>
        </el-col>
        <el-col :span="3" align="right">
          <el-button type="primary" icon="el-icon-plus" circle @click="dialogFormVisible = true" />
        </el-col>
      </el-row>
    </el-card>
    <!-- 用户列表 -->
    <el-card>
      <el-table :data="userList" stripe style="width: 100%">
        <el-table-column label="#" width="80" align="center">
          <template slot-scope="scope">
            {{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column prop="username" label="账户" align="center" />
        <el-table-column prop="email" label="邮箱" align="center" />
        <el-table-column prop="status" label="状态" align="center">
          <template slot-scope="scope">
            {{ scope.row.status !== 1 ? '停用' : '启用' }}
          </template>
        </el-table-column>
        <el-table-column prop="phone" label="电话" align="center" />
        <el-table-column label="操作" width="200" align="center">
          <template>
            <el-button type="primary" icon="el-icon-edit" circle size="small" />
            <el-button type="danger" icon="el-icon-delete" circle size="small" />
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!--  添加用户  -->
    <el-dialog title="添加用户" :visible.sync="dialogFormVisible" @close="clearForm">
      <el-form ref="userFormRef" :rules="rules" :model="userForm">
        <el-form-item label="账户" :label-width="formLabelWidth" prop="username">
          <el-input v-model="userForm.username" autocomplete="off" />
        </el-form-item>
        <el-form-item label="密码" :label-width="formLabelWidth" prop="password">
          <el-input v-model="userForm.password" type="password" autocomplete="off" />
        </el-form-item>
        <el-form-item label="状态" :label-width="formLabelWidth" prop="status">
          <el-switch
            v-model="userForm.status"
            :active-value="0"
            :inactive-value="1"
          />
        </el-form-item>
        <el-form-item label="邮箱" :label-width="formLabelWidth" prop="email">
          <el-input v-model="userForm.email" autocomplete="off" />
        </el-form-item>
        <el-form-item label="电话" :label-width="formLabelWidth" prop="phone">
          <el-input v-model="userForm.phone" autocomplete="off" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveUser">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 分页 -->
    <el-pagination
      :current-page="searchModel.pageNo"
      :page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
      :page-size="searchModel.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import userManage from '@/api/system/userManage'
export default {
  name: 'Index',
  data: function() {
    const checkEmail = (rule, value, callback) => {
      const reg = /^([a-zA-Z]|[0-9])(\w|\-|\.)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/
      if (!value) return callback(new Error('请输入收件人邮箱'))
      if (!reg.test(value)) {
        callback(new Error('邮箱格式错误'))
      } else {
        callback()
      }
    }
    const checkPhone = (rule, value, callback) => {
      const reg = /^[1][3,4,5,6,7,8,9][0-9]{9}$/
      if (!value) return callback(new Error('请输入联系人电话'))
      if (!reg.test(value)) {
        callback(new Error('电话格式错误'))
      } else {
        callback()
      }
    }
    return {
      rules: {
        username: [
          { required: true, message: '请输入账户名', trigger: 'blur' }
        ],
        password: [
          { required: true, message: '请输入密码', trigger: 'blur' }
        ],
        email: [
          { required: true, message: '请输入邮箱', trigger: 'blur' },
          { validator: checkEmail, trigger: 'blur' }
        ],
        phone: [
          { required: true, message: '请输入电话', trigger: 'blur' },
          { validator: checkPhone, trigger: 'blur' }
        ]
      },
      userForm: {},
      dialogFormVisible: false,
      formLabelWidth: '120px',
      userList: [],
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 5,
        username: '',
        phone: ''
      }
    }
  },
  created() {
    this.getUserList()
  },
  mounted() {
    this.getUserList()
  },
  methods: {
    clearForm() {
      this.userForm = {}
      this.dialogFormVisible = false
      this.$refs.userFormRef.clearValidate()
    },
    // 2.添加用户
    saveUser() {
      // 触发表单验证
      this.$refs.userFormRef.validate((valid) => {
        if (valid) {
          // 提交请求给后台
          userManage.addUser(this.userForm).then(res => {
            // 成功提示
            this.$message({
              type: 'success',
              message: res.message
            })
            // 关闭对话框
            this.dialogFormVisible = false
            // 刷新表格数据
            this.getUserList()
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    // 1.获取用户列表
    getUserList() {
      userManage.getUserList(this.searchModel).then(res => {
        this.userList = res.data.rows
        this.total = res.data.total
      })
    },
    handleSizeChange(pageSize) {
      this.searchModel.pageSize = pageSize
      this.getUserList()
    },
    handleCurrentChange(pageNo) {
      this.searchModel.pageNo = pageNo
      this.getUserList()
    }
  }
}
</script>

<style scoped lang="scss">
#search .el-input {
  width: 160px;
  margin-right: 10px;
}
</style>
11.1.4 修改用户
11.1.4.1 界面布局

复用添加用户界面,通过点击,是否存在用户ID来判断添加还是修改

①添加用户

<!-- 用户ID为空,判断出该用户不存在,即为添加用户操作  -->
<el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />

②修改用户

<!-- 用户ID不为空,判断出该用户已存在,即为修改用户操作  -->
<el-button type="primary" icon="el-icon-edit" circle size="small" @click="openDialog(scope.row.id)" />
11.1.4.2 新增请求

①根据前端点击修改按钮,传入的用户用户ID查询用户信息,用于回显在修改对话框中进行修改

// 3.根据用户ID查询用户
// 根据前端点击修改按钮,传入的用户用户ID查询用户信息,用于回显在修改对话框中进行修改
getUserById(id) {
  return request({
    // url: '/system/user/' + id,
    url: `/system/user/${id}`,
    method: 'get'
  })
},

②修改用户

// 4.修改用户
updateUser(user) {
  return request({
    url: '/system/user',
    method: 'put',
    data: user
  })
},

③整合添加/修改用户

// 5.整合添加/修改请求后端接口
saveUser(user) {
  // eslint-disable-next-line eqeqeq
  if (user.id == null && user.id === undefined) {
    return this.addUser(user)
  } else {
    return this.updateUser(user)
  }
}
11.1.4.3 发送请求

①根据后端查询是否存在用户ID,判断是添加用户/修改用户操作

<!-- 用户ID为空,判断出该用户不存在,即为添加用户操作  -->
<el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />
title: '',
openDialog(id) {
  if (id == null) {
    this.title = '添加用户'
    this.dialogFormVisible = true
  } else {
    this.title = '修改用户'
    this.dialogFormVisible = true
    userManage.getUserById(id).then(res => {
      this.userForm = res.data
    })
  }
}

②如果是修改用户,密码不需回显到弹出框

<el-form-item v-if="userForm.id == null || userForm.id == undefined" label="密码" :label-width="formLabelWidth" prop="password">
  <el-input v-model="userForm.password" type="password" autocomplete="off" />
</el-form-item>

③添加/修改用户请求

// 2.添加/修改用户
saveUser() {
  // 触发表单验证
  this.$refs.userFormRef.validate((valid) => {
    if (valid) {
      // 提交请求给后台
      userManage.saveUser(this.userForm).then(res => {
        // 成功提示
        this.$message({
          type: 'success',
          message: res.message
        })
        // 关闭对话框
        this.dialogFormVisible = false
        // 刷新表格数据
        this.getUserList()
      })
    } else {
      console.log('error submit!!')
      return false
    }
  })
},
11.1.5 删除用户
11.1.5.1 界面布局
<el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteUser(scope.row.id)" />
11.1.5.2 新增请求
// 3.删除用户
deleteUserById(id) {
  return request({
    url: `/system/user/${id}`,
    method: 'delete'
  })
}
11.1.5.3 发送请求
 deleteUser(user) {
  this.$confirm(`您确认要删除用户:${user.username}`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    userManage.deleteUserById(user.id).then(res => {
      this.$message({
        type: 'success',
        message: res.message
      })
      this.getUserList()
    })
  }).catch(() => {
    this.$message({
      type: 'info',
      message: '已取消删除'
    })
  })
}
11.1.5.4 数据回显

删除后页面刷新

12 角色管理

12.1 界面布局

角色管理界面布局复用用户管理界面,修改后的界面

src\views\system\role\index.vue

<template>
  <div>
    <!-- 搜索栏 -->
    <el-card id="search">
      <el-row>
        <el-col :span="20">
          <el-input v-model="searchModel.roleName" placeholder="请输入角色名" />
          <el-input v-model="searchModel.roleDesc" placeholder="请输入角色描述" />
          <el-button type="primary" round icon="el-icon-search" @click="getRoleList">搜索</el-button>
        </el-col>
        <el-col :span="3" align="right">
          <!-- 角色ID为空,判断出该角色不存在,即为添加角色操作  -->
          <el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />
        </el-col>
      </el-row>
    </el-card>
    <!-- 角色列表 -->
    <el-card>
      <el-table :data="roleList" stripe style="width: 100%">
        <el-table-column label="#" width="80" align="center">
          <template slot-scope="scope">
            {{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column prop="roleName" label="角色名称" align="center" />
        <el-table-column prop="status" label="角色状态" align="center">
          <template slot-scope="scope">
            {{ scope.row.status !== 1 ? '停用' : '启用' }}
          </template>
        </el-table-column>
        <el-table-column prop="roleDesc" label="角色描述" align="center" />
        <el-table-column label="操作" width="200" align="center">
          <template slot-scope="scope">
            <!-- 角色ID不为空,判断出该角色已存在,即为修改角色操作  -->
            <el-button type="primary" icon="el-icon-edit" circle size="small" @click="openDialog(scope.row.id)" />
            <el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteRole(scope.row)" />
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!--  添加/修改角色  -->
    <el-dialog :title="title" :visible.sync="dialogFormVisible" @close="clearForm">
      <el-form ref="roleFormRef" :rules="rules" :model="roleForm">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="roleForm.roleName" autocomplete="off" />
        </el-form-item>
        <el-form-item label="状态" :label-width="formLabelWidth" prop="status">
          <el-switch
            v-model="roleForm.status"
            :active-value="0"
            :inactive-value="1"
          />
        </el-form-item>
        <el-form-item label="角色描述" :label-width="formLabelWidth" prop="roleDesc">
          <el-input v-model="roleForm.roleDesc" autocomplete="off" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveRole">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 分页 -->
    <el-pagination
      :current-page="searchModel.pageNo"
      :page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
      :page-size="searchModel.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import roleManage from '@/api/system/roleManage'
export default {
  name: 'Index',
  data: function() {
    return {
      rules: {
        roleName: [
          { required: true, message: '请输入角色名称', trigger: 'blur' }
        ],
        roleDesc: [
          { required: true, message: '请输入角色描述', trigger: 'blur' }
        ]
      },
      roleForm: {},
      dialogFormVisible: false,
      formLabelWidth: '120px',
      title: '',
      roleList: [],
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 5,
        roleName: '',
        roleDesc: ''
      }
    }
  },
  created() {
    this.getRoleList()
  },
  mounted() {
    this.getRoleList()
  },
  methods: {
    // 3.删除角色
    deleteRole(role) {
      this.$confirm(`您确认要删除角色:${role.roleName}`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        roleManage.deleteRoleById(role.id).then(res => {
          this.$message({
            type: 'success',
            message: res.message
          })
          this.getRoleList()
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    openDialog(id) {
      if (id == null) {
        this.title = '添加角色'
        this.dialogFormVisible = true
      } else {
        this.title = '修改角色'
        this.dialogFormVisible = true
        roleManage.getRoleById(id).then(res => {
          this.roleForm = res.data
        })
      }
    },
    clearForm() {
      this.roleForm = {}
      this.dialogFormVisible = false
      this.$refs.roleFormRef.clearValidate()
    },
    // 2.添加/修改角色
    saveRole() {
      // 触发表单验证
      this.$refs.roleFormRef.validate((valid) => {
        if (valid) {
          // 提交请求给后台
          roleManage.saveRole(this.roleForm).then(res => {
            // 成功提示
            this.$message({
              type: 'success',
              message: res.message
            })
            // 关闭对话框
            this.dialogFormVisible = false
            // 刷新表格数据
            this.getRoleList()
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    // 1.获取角色列表
    getRoleList() {
      roleManage.getRoleList(this.searchModel).then(res => {
        console.log('2.角色列表', res.data.rows)
        this.roleList = res.data.rows
        this.total = res.data.total
      })
    },
    handleSizeChange(pageSize) {
      this.searchModel.pageSize = pageSize
      this.getRoleList()
    },
    handleCurrentChange(pageNo) {
      this.searchModel.pageNo = pageNo
      this.getRoleList()
    }
  }
}
</script>

<style scoped lang="scss">
#search .el-input {
  width: 160px;
  margin-right: 10px;
}
</style>

12.2 新增请求

src\api\system\roleManage.js

import request from '@/utils/request'

export default {
  // 1.角色列表
  getRoleList(searchModel) {
    return request({
      url: '/system/role/list',
      method: 'get',
      params: {
        pageNo: searchModel.pageNo,
        pageSize: searchModel.pageSize,
        roleName: searchModel.roleName,
        roleDesc: searchModel.roleDesc
      }
    })
  },
  // 添加角色
  addRole(role) {
    return request({
      url: '/system/role',
      method: 'post',
      data: role
    })
  },
  // 根据角色ID查询角色
  getRoleById(roleId) {
    return request({
      url: `/system/role/${roleId}`,
      method: 'get'
    })
  },
  // 修改角色
  updateRole(role) {
    return request({
      url: '/system/role/update',
      method: 'put',
      data: role
    })
  },
  // 2.添加/修改角色
  saveRole(role) {
    // eslint-disable-next-line eqeqeq
    if (role.id == null && role.id == undefined) {
      return this.addRole(role)
    } else {
      return this.updateRole(role)
    }
  },
  // 3.删除角色
  deleteRoleById(id) {
    return request({
      url: `/system/role/${id}`,
      method: 'delete'
    })
  }
}

12.3 发送请求

// 3.删除角色
deleteRole(role) {
  this.$confirm(`您确认要删除角色:${role.roleName}`, '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    roleManage.deleteRoleById(role.id).then(res => {
      this.$message({
        type: 'success',
        message: res.message
      })
      this.getRoleList()
    })
  }).catch(() => {
    this.$message({
      type: 'info',
      message: '已取消删除'
    })
  })
},
openDialog(id) {
  if (id == null) {
    this.title = '添加角色'
    this.dialogFormVisible = true
  } else {
    this.title = '修改角色'
    this.dialogFormVisible = true
    roleManage.getRoleById(id).then(res => {
      this.roleForm = res.data
    })
  }
},
// 2.添加/修改角色
saveRole() {
  // 触发表单验证
  this.$refs.roleFormRef.validate((valid) => {
    if (valid) {
      // 提交请求给后台
      roleManage.saveRole(this.roleForm).then(res => {
        // 成功提示
        this.$message({
          type: 'success',
          message: res.message
        })
        // 关闭对话框
        this.dialogFormVisible = false
        // 刷新表格数据
        this.getRoleList()
      })
    } else {
      console.log('error submit!!')
      return false
    }
  })
},
// 1.获取角色列表
getRoleList() {
  roleManage.getRoleList(this.searchModel).then(res => {
    console.log('2.角色列表', res.data.rows)
    this.roleList = res.data.rows
    this.total = res.data.total
  })
},

12.4 数据回显

<template>
  <div>
    <!-- 搜索栏 -->
    <el-card id="search">
      <el-row>
        <el-col :span="20">
          <el-input v-model="searchModel.roleName" placeholder="请输入角色名" />
          <el-input v-model="searchModel.roleDesc" placeholder="请输入角色描述" />
          <el-button type="primary" round icon="el-icon-search" @click="getRoleList">搜索</el-button>
        </el-col>
        <el-col :span="3" align="right">
          <!-- 角色ID为空,判断出该角色不存在,即为添加角色操作  -->
          <el-button type="primary" icon="el-icon-plus" circle @click="openDialog(null)" />
        </el-col>
      </el-row>
    </el-card>
    <!-- 角色列表 -->
    <el-card>
      <el-table :data="roleList" stripe style="width: 100%">
        <el-table-column label="#" width="80" align="center">
          <template slot-scope="scope">
            {{ (searchModel.pageNo - 1) * searchModel.pageSize + scope.$index + 1 }}
          </template>
        </el-table-column>
        <el-table-column prop="roleName" label="角色名称" align="center" />
        <el-table-column prop="status" label="角色状态" align="center">
          <template slot-scope="scope">
            {{ scope.row.status !== 1 ? '停用' : '启用' }}
          </template>
        </el-table-column>
        <el-table-column prop="roleDesc" label="角色描述" align="center" />
        <el-table-column label="操作" width="200" align="center">
          <template slot-scope="scope">
            <!-- 角色ID不为空,判断出该角色已存在,即为修改角色操作  -->
            <el-button type="primary" icon="el-icon-edit" circle size="small" @click="openDialog(scope.row.id)" />
            <el-button type="danger" icon="el-icon-delete" circle size="small" @click="deleteRole(scope.row)" />
          </template>
        </el-table-column>
      </el-table>
    </el-card>
    <!--  添加/修改角色  -->
    <el-dialog :title="title" :visible.sync="dialogFormVisible" @close="clearForm">
      <el-form ref="roleFormRef" :rules="rules" :model="roleForm">
        <el-form-item label="角色名称" prop="roleName">
          <el-input v-model="roleForm.roleName" autocomplete="off" />
        </el-form-item>
        <el-form-item label="状态" :label-width="formLabelWidth" prop="status">
          <el-switch
            v-model="roleForm.status"
            :active-value="0"
            :inactive-value="1"
          />
        </el-form-item>
        <el-form-item label="角色描述" :label-width="formLabelWidth" prop="roleDesc">
          <el-input v-model="roleForm.roleDesc" autocomplete="off" />
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="dialogFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="saveRole">确 定</el-button>
      </div>
    </el-dialog>
    <!-- 分页 -->
    <el-pagination
      :current-page="searchModel.pageNo"
      :page-sizes="[5, 10, 20, 30, 40, 50, 100, 200, 300, 400]"
      :page-size="searchModel.pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script>
import roleManage from '@/api/system/roleManage'
export default {
  name: 'Index',
  data: function() {
    return {
      rules: {
        roleName: [
          { required: true, message: '请输入角色名称', trigger: 'blur' }
        ],
        roleDesc: [
          { required: true, message: '请输入角色描述', trigger: 'blur' }
        ]
      },
      roleForm: {},
      dialogFormVisible: false,
      formLabelWidth: '120px',
      title: '',
      roleList: [],
      total: 0,
      searchModel: {
        pageNo: 1,
        pageSize: 5,
        roleName: '',
        roleDesc: ''
      }
    }
  },
  created() {
    this.getRoleList()
  },
  mounted() {
    this.getRoleList()
  },
  methods: {
    // 3.删除角色
    deleteRole(role) {
      this.$confirm(`您确认要删除角色:${role.roleName}`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      }).then(() => {
        roleManage.deleteRoleById(role.id).then(res => {
          this.$message({
            type: 'success',
            message: res.message
          })
          this.getRoleList()
        })
      }).catch(() => {
        this.$message({
          type: 'info',
          message: '已取消删除'
        })
      })
    },
    openDialog(id) {
      if (id == null) {
        this.title = '添加角色'
        this.dialogFormVisible = true
      } else {
        this.title = '修改角色'
        this.dialogFormVisible = true
        roleManage.getRoleById(id).then(res => {
          this.roleForm = res.data
        })
      }
    },
    clearForm() {
      this.roleForm = {}
      this.dialogFormVisible = false
      this.$refs.roleFormRef.clearValidate()
    },
    // 2.添加/修改角色
    saveRole() {
      // 触发表单验证
      this.$refs.roleFormRef.validate((valid) => {
        if (valid) {
          // 提交请求给后台
          roleManage.saveRole(this.roleForm).then(res => {
            // 成功提示
            this.$message({
              type: 'success',
              message: res.message
            })
            // 关闭对话框
            this.dialogFormVisible = false
            // 刷新表格数据
            this.getRoleList()
          })
        } else {
          console.log('error submit!!')
          return false
        }
      })
    },
    // 1.获取角色列表
    getRoleList() {
      roleManage.getRoleList(this.searchModel).then(res => {
        console.log('2.角色列表', res.data.rows)
        this.roleList = res.data.rows
        this.total = res.data.total
      })
    },
    handleSizeChange(pageSize) {
      this.searchModel.pageSize = pageSize
      this.getRoleList()
    },
    handleCurrentChange(pageNo) {
      this.searchModel.pageNo = pageNo
      this.getRoleList()
    }
  }
}
</script>

<style scoped lang="scss">
#search .el-input {
  width: 160px;
  margin-right: 10px;
}
</style>

13 角色菜单

13.1 菜单列表

13.1.1 界面布局

在src\views\system\role\index.vue添加菜单列表树形组件

<el-form-item :label-width="formLabelWidth" prop="menuIdList" label="权限设置">
  <el-tree
    ref="menuTreeRef"
    :data="menuList"
    :props="menuProps"
    show-checkbox
    default-expand-all
    node-key="id"
    style="width: 85%"
  />
</el-form-item>

在src\views\system\role\index.vue定义接收菜单列表参数

menuList: [],
menuProps: {
  label: 'title',
  children: 'children'
},

在src\views\system\role\index.vue添加请求菜单列表方法

mounted() {
  this.getRoleList()
  this.getMenuList()
},
methods: {
  // 4.菜单列表
  getMenuList() {
    menuManage.getMenuList().then(res => {
      this.menuList = res.data
      console.log('4.菜单列表', res.data)
    })
  },
13.1.2 新增请求

在src\api\system\menuManage.js创建获取菜单列表的方法

// 获取菜单列表
getMenuList() {
  return request({
    url: '/system/menu/list',
    method: 'get'
  })
}
13.1.3 发送请求

在src\views\system\role\index.vue添加请求菜单列表方法

mounted() {
  this.getRoleList()
  this.getMenuList()
},
methods: {
  // 4.菜单列表
  getMenuList() {
    menuManage.getMenuList().then(res => {
      this.menuList = res.data
      console.log('4.菜单数据', res.data)
    })
  },
13.1.4 数据回显

添加/修改弹出框填充自动回显

13.2 添加角色菜单

13.2.1 界面布局

在src\views\system\role\index.vue添加菜单列表树形组件

<el-form-item :label-width="formLabelWidth" prop="menuIdList" label="权限设置">
  <el-tree
    ref="menuTreeRef"
    :data="menuList"
    :props="menuProps"
    show-checkbox
    default-expand-all
    node-key="id"
    style="width: 85%"
  />
</el-form-item>

注意: node-key的值是menuList中的数据

const checkedKeys = this.$refs.menuTreeRef.getCheckedKeys()
const halfCheckedKeys = this.$refs.menuTreeRef.getHalfCheckedKeys()
this.roleForm.menuIdList = checkedKeys.concat(halfCheckedKeys)
13.2.2 新增请求

复用src\api\system\role\roleManage.js中addRole()

// 2.添加/修改角色
saveRole(role) {
  // eslint-disable-next-line eqeqeq
  if (role.id == null && role.id == undefined) {
    return this.addRole(role)
  } else {
    return this.updateRole(role)
  }
},
13.2.3 发送请求

复用src\views\system\role\index.vue中saveRole()

// 提交请求给后台
roleManage.saveRole(this.roleForm).then(res => {
  // 成功提示
  this.$message({
    type: 'success',
    message: res.message
  })
  // 关闭对话框
  this.dialogFormVisible = false
  // 刷新表格数据
  this.getRoleList()
})
13.2.4 数据回显

在openDialog()方法中添加

this.$refs.menuTreeRef.setCheckedKeys(this.roleForm.menuIdList)

openDialog(id) {
  if (id == null) {
    this.title = '添加角色'
    this.dialogFormVisible = true
  } else {
    this.title = '修改角色'
    this.dialogFormVisible = true
    roleManage.getRoleById(id).then(res => {
      this.roleForm = res.data
      this.$refs.menuTreeRef.setCheckedKeys(this.roleForm.menuIdList)
    })
  }
},

14 用户角色

14.1 菜单列表

14.1.1 界面布局

在src\views\system\user\index.vue中添加复选框组件

<el-form-item :label-width="formLabelWidth" prop="roleIdList" label="角色">
  <el-checkbox-group
    v-model="userForm.roleIdList"
    style="width: 85%"
    :min="1"
    :max="10"
  >
    <el-checkbox v-for="role in roleList" :key="role.id" :label="role.id">{{ role.roleDesc }}</el-checkbox>
  </el-checkbox-group>
</el-form-item>

定义接口后端查询用户列表数据参数和页面点选复选框接收参数。

注意:roleList: [] 和 roleIdList: [] 不是同一个接收参数,不能搞混,否则就会出现获取不到页面选中的复选框id,无法传入后端

roleList: [],
userForm: {
  roleIdList: []
},
14.1.2 新增请求

在src\api\system\role\roleManage.js中getAllRoleList()

// 4.角色列表
getAllRoleList() {
  return request({
    url: '/system/role/all',
    method: 'get'
  })
}
14.1.3 发送请求

发送获取角色列表的请求

import roleManage from '@/api/system/roleManage'
// 4.角色列表
getAllRoleList() {
  roleManage.getAllRoleList().then(res => {
    this.roleList = res.data
    console.log('4.角色列表', this.roleList)
  })
},

发送添加用户角色信息的请求

// 2.添加/修改用户
saveUser() {
  // 触发表单验证
  this.$refs.userFormRef.validate((valid) => {
    if (valid) {
      // 提交请求给后台
      userManage.saveUser(this.userForm).then(res => {
        // 成功提示
        this.$message({
          type: 'success',
          message: res.message
        })
        // 关闭对话框
        this.dialogFormVisible = false
        // 刷新表格数据
        this.getUserList()
      })
    } else {
      console.log('error submit!!')
      return false
    }
  })
},
14.1.4 数据回显

页面发送添加用户角色请求,测试是否异常。

标签:src,return,res,system,REDME,dev,message,data
From: https://www.cnblogs.com/mrlumin/p/18604063

相关文章

  • slidev 导出前 安装playwright-chromium失败
    导出幻灯片|Slidev直接参考上述npmi-Dplaywright-chromium报错\[0/1]Installingplaywright-core@1.49.1[npminstall:runscript:error]playwright-chromium@latestruninstallnodeinstall.jserror:Error:Commandfailedwithexitcode1:nodeinstall.js更......
  • Sealos Devbox 云开发框架使用教程
    用过Sealos云开发的同学,想必都很熟悉函数式编程,喜欢Sealos云开发的那种完全不用关心路由,开发快,上线快,调试快,越用越简单越简单越用的感觉。它就像一个温柔的保姆,帮你打理好了所有的家务事(路由、部署、调试),让你专注于写代码的快乐。现在更强大的保姆来了,SealosDevbox新增......
  • 在node.js项目开发时,如何决定一个依赖是dependencies依赖还是devDependencies依赖?例如
    在Node.js项目中,决定一个依赖是dependencies还是devDependencies主要取决于该依赖的用途:它是用于生产环境(生产依赖)还是仅用于开发环境(开发依赖)。1.dependencies(生产依赖)这些依赖是应用程序在运行时所需的。无论是部署到生产环境,还是在开发环境进行测试,应用都会需要这些依......
  • 请说说你对DevOps的理解
    DevOps对前端开发来说至关重要,它旨在通过自动化和协作来缩短开发周期,提高交付速度和质量。我的理解如下:核心目标:更快地交付价值:通过自动化流程,例如构建、测试和部署,可以更快地将新功能和修复交付给用户。提高协作效率:打破开发和运维之间的壁垒,促进团队之间的沟通和协作,减......
  • No space left on device 异常处理
    Author:ACatSmilingSince:2021-01-11有时候,在创建新文件,或者往磁盘写内容时,会提示Nospaceleftondevice异常。一般来说,Linux空间占满有如两种情况:空间占满。inode占满。空间占满通过df-h命令,查看空间的使用情况:$df-hFilesystemSize......
  • 【Azure Developer】使用cmd脚本循环执行curl请求
    问题描述在测试ApplicationInsights的每日上限(DailyCap)功能,想通过最简单的curl脚本来循环发送请求,验证日志摄入量大道设置的300MB(0.03GB)后,是否可以通过调大DailyCap限制值马上恢复数据的摄入! 问题解答一个简单的CMD脚本示例,它会循环执行 curl 命令:@echooff......
  • 怎么禁用 vscode 中点击 go 包名时自动打开浏览器跳转到 pkg.go.dev
    本文引用怎么禁用vscode中点击go包名时自动打开浏览器跳转到pkg.go.dev在vscode设置项中配置gopls的ui.navigation.importShortcut为Definition即可。"gopls":{"ui.navigation.importShortcut":"Definition"}ui.navigation.importShortcut接受的值:"......
  • DevExpress WinForms中文教程:Grid View - 如何实现自动调整宽度模式?
    DevExpressWinForms拥有180+组件和UI库,能为WindowsForms平台创建具有影响力的业务解决方案。DevExpressWinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜任!本文主要介绍如何使用DevExpressWinFormsDataGr......
  • 工业物联网的DevOps,到底要怎么做?
    随着工业物联网领域面临越来越多的挑战,用于工业物联网的DevOps正在帮助企业提高效率。物联网已经成为推动制造业发展的最新技术之一。它定义了与传感器、应用程序和其他技术集成的各种物理设备,以便通过公共互联网与其他系统通信和共享数据。而工业物联网(IIoT)代表了物联网在工业......
  • WX小程序DevTocls调试工具hook注入失败解决方案
    !!!此问题只能解决志远大佬开发的工具相信很多小伙伴遇到hook注入失败的情况,如图:遇到这种,首先你先关闭微信,找到你的微信小程序的安装路径C:\Users\自己的用户\AppData\Roaming\Tencent\WeChat\XPlugin\Plugins\RadiumWMPF然后删除该目录的所有文件夹就行此刻你重新打开微信,再......