cmdb前端添加展示页面

时间:July 10, 2019 分类:

目录:

随便搞的首页

src/components/Dashboard.vue

<template>
  <div class="demo-image">
    <div class="block" v-for="fit in fits" :key="fit">
      <span class="demonstration">{{ fit }}</span>
      <el-image
        style="width: 100px; height: 100px"
        :src="url"
        :fit="fit"></el-image>
    </div>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        url: 'https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg'
      }
    }
  }
</script>

登录页

在最开始的router.beforeEach中定义了如果没有权限或者登陆就会跳转到登录页

src/components/Login.vue

<template>
  <div class="login-form">
    <el-row>
      <!-- 标题 -->
      <el-col :offset="8" :span="8">
        <el-alert title="Welcome to gaea!" center type="info" :closable="false"></el-alert>
      </el-col>
      <el-col :offset="8" :span="8">
        <!-- 表单loginForm -->
        <el-form status-icon :model="loginForm" :rules="rules" ref="loginForm">
          <el-form-item label="用户名" prop="username">
            <!-- 表单字段 -->
            <el-input v-model="loginForm.username"></el-input>
          </el-form-item>
          <el-form-item label="密码" prop="password">
            <el-input type="password" v-model="loginForm.password"></el-input>
          </el-form-item>
          <el-form-item>
            <!--  提交触发submitForm -->
            <el-button type="primary" @click="submitForm('loginForm')">登陆 <i class="fas fa-sign-in-alt"></i></el-button>
            <el-button @click="resetForm('loginForm')">清除 <i class="fas fa-eraser"></i></el-button>
          </el-form-item>
        </el-form>
      </el-col>
    </el-row>
  </div>
</template>
<script>
  export default {
    data: function () {
      // 初始化表单数据
      return {
        loginForm: {
          username: '',
          password: ''
        },
        rules: {
          username: [
            { required: true, message: '请输入用户名', trigger: 'blur' }
          ],
          password: [
            { required: true, message: '请输入密码', trigger: 'blur' }
          ]
        }
      }
    },
    methods: {
      submitForm: function (formName) {
        // js缺陷,this不能调用this
        var _this = this;
        // validate jquery的字段验证方法
        this.$refs[formName].validate((valid) => {
          if (valid) {
            this.$http.post('/api/account/login/', this.loginForm).then(function (response) {
              // 登录成功更新store数据
              _this.$store.dispatch('setLoggedIn', response.data.loggedIn);
              _this.$store.dispatch('setUser', response.data.user);
              _this.$store.dispatch('setPermissions', response.data.permissions);
              _this.$router.push({path: '/machineManagement'});
            }).catch(function (error) {
              _this.$message.error('用户名或者密码错误');
            });
          } else {
            _this.$message.error('登陆发生错误,请联系管理员');
            return false;
          }
        });
      },
      // ref类似dom绑定,直接定位元素
      resetForm: function (formName) {
        this.$refs[formName].resetFields();
      }
    }
  }
</script>

<style scoped>
  .login-form {
    margin-top: 150px;
  }
</style>

用户管理

用户管理组件

src/components/UserManagement.vue

<template>
  <div>
    <div class="div-header">
      <el-row>
        <!-- 添加用户 -->
        <el-col :span="3">
          <el-button type="primary" size="mini" icon="el-icon-plus"
            // 如果存储的权限里没有则隐藏
            :disabled="$store.state.permissions.indexOf('account.add_user') < 0"
            @click="handleAdd">
            添加用户
          </el-button>
        </el-col>
        <!-- 删除用户 -->
        <el-col :span="3">
          <el-badge :value="multipleSelection.length"
            <!-- 检测存储权限 -->
            :hidden="$store.state.permissions.indexOf('account.delete_user') < 0 ||
            <!-- 或者选择的人 -->
            !multipleSelection.length > 0"
            :max="100" class="item">
            <el-button type="danger" size="mini" icon="el-icon-delete"
              :disabled="$store.state.permissions.indexOf('account.delete_user') < 0 ||
              !multipleSelection.length > 0" @click="deleteMutiple">
              批量删除
            </el-button>
          </el-badge>
        </el-col>
        <el-col :offset="13" :span="4">
          <el-input placeholder="请输入搜索内容" clearable size="mini" suffix-icon="el-icon-search" v-model="search" @input="handleSearch">
          </el-input>
        </el-col>
      </el-row>
    </div>
    <!-- element-ui的v-loading element-loading-text="拼命加载中" -->
    <el-table stripe border :data="tableData" style="width: 100%" v-loading="loading" element-loading-text="拼命加载中" @selection-change="handleSelectionChange" @sort-change="sortChange">
      <el-table-column type="selection"></el-table-column>
      <!-- prop传入子组件 -->
      <el-table-column prop="id" sortable="custom" label="ID"></el-table-column>
      <el-table-column prop="username" sortable="custom" label="用户名"></el-table-column>
      <el-table-column prop="fullname" sortable="custom" label="姓名"></el-table-column>
      <el-table-column prop="mobile" sortable="custom" label="手机"></el-table-column>
      <el-table-column prop="email" sortable="custom" label="邮件"></el-table-column>
      <el-table-column prop="isActive" sortable="custom" label="状态">
        <!-- scope整体数据 -->
        <template slot-scope="scope">
          <el-tag v-if="scope.row.isActive" type="primary">正常</el-tag>
          <el-tag v-else type="warning">禁用</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="isSuperuser" sortable="custom" label="超级管理员">
        <template slot-scope="scope">
          <el-tag v-if="scope.row.isSuperuser" type="danger">是</el-tag>
          <el-tag v-else type="info">否</el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="userGroups" sortable="custom" label="用户组">
        <template slot-scope="scope">
          <!-- key为了唯一标识 -->
          <el-tag v-for="(group, index) in scope.row.userGroups" :key="index" type="info">
            {{ group.groupName }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="dateJoined" sortable="custom" label="注册时间"></el-table-column>
      <el-table-column prop="lastLogin" sortable="custom" label="最后登陆"></el-table-column>
      <el-table-column label="操作" width="210">
        <template slot-scope="scope">
          <el-button size="mini" icon="el-icon-edit"
            :disabled="$store.state.permissions.indexOf('account.change_user') < 0"
            @click="handleEdit(scope.$index, scope.row)">
            编辑
          </el-button>
          <el-button size="mini" icon="el-icon-delete" type="danger"
            :disabled="$store.state.permissions.indexOf('account.delete_user') < 0"
            @click="handleDelete(scope.$index, scope.row)">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <!-- 添加编辑组件 -->
    <!-- sync允许子组件的数据传递到父组件 -->
    <userEdit :title="title" :userFormVisible.sync="userFormVisible"
      :changeMode="changeMode" :groupOptions="groupOptions" :userForm="userForm"
      @reloadTable="reloadTable">
    </userEdit>
    <!-- 分页组件 -->
    <pagination :total="total" :pageSizes="[20, 50, 100]" :pageSize.sync="size"
      :currentPage.sync="page" @reloadTable="reloadTable">
    </pagination>
  </div>
</template>

<script>
  import userEdit from '@/components/UserEdit.vue';
  import pagination from '@/components/Pagination.vue';
  export default {
    components: {
      'userEdit': userEdit,
      'pagination': pagination
    },
    data: function () {
      return {
        loading: false,
        // 勾选的数据
        multipleSelection: [],
        tableData: [],
        total: 0,
        title: '',
        // 用于显示添加用户表单
        userFormVisible: false,
        changeMode: false,
        groupOptions: [],
        userForm: {
          id: '',
          username: '',
          fullname: '',
          mobile: '',
          email: '',
          isActive: '1',
          isSuperuser: '0',
          groupIdList: []
        },
        size: 20,
        page: 1,
        search: '',
        orderBy: '',
        order: ''
      };
    },
    methods: {
      handleSelectionChange: function (val) {
        // 增减选中数据
        this.multipleSelection = val;
      },
      // 刷新表单
      reloadTable: function () {
        var _this = this;
        var url = '/api/account/getUsers/' + '?search=' + this.search + '&orderBy=' + this.orderBy + '&order=' + this.order + '&size=' + this.size + '&page=' + this.page;
        // 展示reload界面
        this.loading = true;
        this.$http.get(url).then(function (response) {
          _this.groupOptions = response.data.groupOptions;
          _this.tableData = response.data.tableData;
          _this.total = response.data.total;
          // 取消reload界面
          _this.loading = false;
        }).catch(function (error) {
          _this.$message.error('获取用户列表失败');
          _this.loading = false;
        });
      },
      // 打开更新用户表单
      handleEdit: function (index, row) {
        // 更新表单数据
        this.userForm.id = row.id;
        this.userForm.username = row.username;
        this.userForm.fullname = row.fullname;
        this.userForm.mobile = row.mobile;
        this.userForm.email = row.email;
        row.isActive ? (this.userForm.isActive = '1') : (this.userForm.isActive = '0');
        row.isSuperuser ? (this.userForm.isSuperuser = '1') : (this.userForm.isSuperuser = '0');
        this.userForm.groupIdList = row.userGroups.map( (item) => { return item.groupId });
        // 用于传入子组件(根据title)
        this.title = '编辑用户';
        this.changeMode = true;
        // 显示编辑界面
        this.userFormVisible = true;
      },
      // 直接删除一条数据
      handleDelete: function (index, row) {
        var idList = [row.id];
        this.deleteSubmit(idList);
      },
      // 批量删除
      deleteMutiple: function () {
        var idList = []
        this.multipleSelection.forEach(v => {idList.push(v.id)});
        this.deleteSubmit(idList);
      },
      // 打开添加用户表单
      handleAdd: function () {
        this.title = '添加用户';
        this.userForm.username = '';
        this.userForm.fullname = '';
        this.userForm.mobile = '';
        this.userForm.email = '';
        this.userForm.isActive = '1';
        this.userForm.isSuperuser = '0';
        this.userForm.groupIdList = [];
        this.changeMode = false;
        this.userFormVisible = true;
      },
      // 删除用户的ajax方法
      deleteSubmit: function (idList) {
        var _this = this;
        // confirm用于弹出 https://element.eleme.io/#/zh-CN/component/message-box
        this.$confirm('删除用户信息: [' + idList.toString() + '], 是否继续?', '确认', {
          confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'}).then(() => {
            this.$http.post('/account/deleteUser/', {'idList': idList}).then(function (response) {
              _this.$notify({ title: '成功', message: '删除用户信息成功', type: 'success'});
              _this.reloadTable();
            }).catch(function (error) {
              if (error.response.status === 403) {
                // 显示message https://element.eleme.io/#/zh-CN/component/message
                _this.$message.warning('没有权限操作');
              } else {
                _this.$message.error('删除用户信息失败');
              }
            });
          }).catch(() => {
            this.$message({type: 'info', message: '已取消删除'});
          }
        );
      },
      sortChange: function (sort) {
        this.orderBy = sort.prop;
        this.order = sort.order;
        this.reloadTable();
      },
      handleSearch: function () {
        setTimeout(this.reloadTable, 500);
      }
    },
    mounted: function () {
      this.reloadTable();
    }
  }
</script>

用户编辑组件

这边主要是element的dialogform两个组件

src/components/UserEdit.vue

<template>
  <el-dialog :title="title" :visible="userFormVisible" @close="handleClose">
    <el-form label-position="left" status-icon ref="userForm" :model="userForm" :rules="rules" label-width="100px">
      <el-form-item v-if="changeMode" label="ID" prop="id">
        <el-input :disabled="changeMode" v-model="userForm.id"></el-input>
      </el-form-item>
      <!-- 当是编辑的时候会有父组件传入原来的数据 -->
      <el-form-item label="用户名" prop="username">
        <el-input v-model.trim="userForm.username"></el-input>
      </el-form-item>
      <el-form-item label="姓名" prop="fullname">
        <el-input v-model.trim="userForm.fullname"></el-input>
      </el-form-item>
      <el-form-item label="手机" prop="mobile">
        <el-input v-model="userForm.mobile"></el-input>
      </el-form-item>
      <el-form-item label="邮件" prop="email">
        <el-input v-model="userForm.email"></el-input>
      </el-form-item>
      <el-form-item v-if="changeMode" label="禁用" prop="isActive">
        <el-select v-model="userForm.isActive" placeholder="是否禁用">
          <el-option label="是" value="0"></el-option>
          <el-option label="否" value="1"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="超级管理员" prop="isSuperuser">
        <el-select v-model="userForm.isSuperuser" placeholder="是否超级管理员">
          <el-option label="否" value="0"></el-option>
          <el-option label="是" value="1"></el-option>
        </el-select>
      </el-form-item>
      <el-form-item label="用户组" prop="group">
        <el-select v-model="userForm.groupIdList" multiple clearable filterable placeholder="选择用户组">
          <el-option v-for="(group, index) in groupOptions" :key="index" :label="group.name"
            :value="group.id">
          </el-option>
        </el-select>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="handleClose">取消</el-button>
      <el-button type="primary" @click="saveSubmit('userForm')">保存</el-button>
    </div>
  </el-dialog>
</template>

<script>
  export default {
    props: ['title', 'userFormVisible', 'changeMode', 'groupOptions', 'userForm'],
    data: function () {
      var validateMobile = (rule, value, callback) => {
        if (isNaN(value)) {
          callback(new Error('请输入有效手机号'));
        } else {
          if (value.length > 30) {
            callback(new Error('长度不得超过30位'));
          }
        callback();
        }
      };
      return {
        // 填入值的规则
        rules: {
          username: [
            { required: true, message: '请输入用户名', trigger: 'blur' },
            { max: 50, message: '长度不得超过50个字符', trigger: 'blur' }
          ],
          fullname: [
            { required: true, message: '请输入姓名', trigger: 'blur' },
            {max: 100, message: '长度不得超过100个字符', trigger: 'blur'}
          ],
          mobile: [
            { validator: validateMobile, trigger: 'blur' }
          ],
          email: [
            { type: 'email', required: true, message: '请输入邮箱', trigger: 'blur' }
          ],
          isActive: [
            { required: true, message: '请选择是否禁用', trigger: 'change' }
          ],
          isSuperuser: [
            { required: true, message: '请选择是否超级管理员', trigger: 'change' }
          ]
        }
      }
    },
    methods: {
      saveSubmit: function (formName) {
        var _this = this;
        this.$refs[formName].validate((valid) => {
          if (valid) {
            var url = '';
            this.changeMode ? url = '/api/account/changeUser/' : url = '/api/account/addUser/';
            this.$http.post(url, this.userForm).then(function (response) {
              _this.$notify({ title: '成功', message: '保存用户信息成功', type: 'success'});
              _this.handleClose();
              _this.$emit('reloadTable');
            }).catch(function (error) {
              if (error.response.status === 403) {
                _this.$message.warning('没有权限操作');
              } else {
                _this.$message.error('保存用户信息失败');
              }
            });
          } else {
            _this.$message.error('未通过表单验证');
            return false;
          }
        });
      },
      handleClose: function () {
        // 触发父组件的数据更新
        this.$emit('update:userFormVisible', false);
      }
    }
  }
</script>

<style scoped>
  .el-select {
    width: 100%;
  }
</style>

分页

分页pagination是由子组件通过触发

src/components/Pagination.vue

<template>
  <div align="center" class="div-pagination">
    <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
      :current-page="currentPage"
      :page-sizes="pageSizes"
      :page-size="pageSize"
      layout="total, sizes, prev, pager, next, jumper"
      :total="total">
    </el-pagination>
  </div>
</template>
<script>
  export default {
    props: ['total', 'pageSizes', 'pageSize', 'currentPage'],
    data: function () {
      return {
      }
    },
    methods: {
      handleSizeChange: function (size) {
        this.$emit('update:pageSize', size);
        this.$emit('reloadTable');
      },
      handleCurrentChange: function (page) {
        this.$emit('update:currentPage', page);
        this.$emit('reloadTable');
      }
    }
  }
</script>
<style scoped>
    .div-pagination {
        margin: 5px;
    }
</style>

用户组管理

用户组管理界面

src/components/GroupManagement.vue

<template>
  <div>
    <div class="div-header">
      <el-row>
        <el-col :span="3">
          <el-button type="primary" size="mini" icon="el-icon-plus"
            :disabled="$store.state.permissions.indexOf('auth.add_group') < 0"
            @click="handleAdd">
            添加用户组
          </el-button>
        </el-col>
        <el-col :span="3">
          <el-badge :value="multipleSelection.length"
          :hidden="$store.state.permissions.indexOf('auth.delete_group') < 0 ||
          !multipleSelection.length > 0"
            :max="100" class="item">
            <el-button type="danger" size="mini" icon="el-icon-delete"
              :disabled="$store.state.permissions.indexOf('auth.delete_group') < 0 ||
              !multipleSelection.length > 0" @click="deleteMutiple">
              批量删除
            </el-button>
          </el-badge>
        </el-col>
        <el-col :offset="13" :span="4">
          <el-input placeholder="请输入搜索内容" clearable size="mini" suffix-icon="el-icon-search"
            v-model="search" @input="handleSearch">
          </el-input>
        </el-col>
      </el-row>
    </div>
    <el-table border :data="tableData" style="width: 100%" v-loading="loading"
      element-loading-text="拼命加载中" :span-method="groupSpan"
      @selection-change="handleSelectionChange" @sort-change="sortChange">
      <el-table-column type="selection"></el-table-column>
      <el-table-column prop="id" sortable="custom" label="ID"></el-table-column>
      <el-table-column prop="name" sortable="custom" label="用户组名"></el-table-column>
      <el-table-column prop="username" label="用户成员" :formatter="formatter"></el-table-column>
      <el-table-column label="操作" width="210">
        <template slot-scope="scope">
          <el-button size="mini" icon="el-icon-edit"
            :disabled="$store.state.permissions.indexOf('auth.change_group') < 0"
            @click="handleEdit(scope.$index, scope.row)">
            编辑
          </el-button>
          <el-button size="mini" icon="el-icon-delete" type="danger"
            :disabled="$store.state.permissions.indexOf('auth.delete_group') < 0"
            @click="handleDelete(scope.$index, scope.row)">
            删除
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <groupEdit :title="title" :groupFormVisible.sync="groupFormVisible" :changeMode="changeMode"
      :userOptions="userOptions" :groupForm="groupForm" @reloadTable="reloadTable">
    </groupEdit>
    <pagination :total="total" :pageSizes="[20, 50, 100]" :pageSize.sync="size"
      :currentPage.sync="page" @reloadTable="reloadTable">
    </pagination>
  </div>
</template>

<script>
  import groupEdit from '@/components/GroupEdit.vue';
  import pagination from '@/components/Pagination.vue';
  export default {
    components: {
      'groupEdit': groupEdit,
      'pagination': pagination
    },
    data: function () {
      return {
        loading: false,
        multipleSelection: [],
        tableData: [],
        total: 0,
        title: '',
        groupFormVisible: false,
        changeMode: false,
        userOptions: [],
        groupForm: {
          id: '',
          name: '',
          userIdList: []
        },
        size: 20,
        page: 1,
        search: '',
        orderBy: '',
        order: ''
      };
    },
    methods: {
      groupSpan: function ({ row, column, rowIndex, columnIndex }) {
        var count = 0;
        this.tableData.forEach((v) => {
          if (v.id === row.id) {
            count++;
          }
        });
        if (columnIndex !== 3) {
          if (rowIndex === 0) {
            return [count, 1];
          }else if (this.tableData[rowIndex].id !== this.tableData[rowIndex-1].id) {
            return [count, 1];
          } else {
            return [0, 0];
          }
        }
      },
      formatter: function (row, column) {
        if (row.username) {
          return row.username + '(' + row.fullname + ')';
        } else {
          return '';
        }
      },
      handleSelectionChange: function (val) {
        this.multipleSelection = val;
      },
      reloadTable: function () {
        var _this = this;
        var url = '/api/account/getGroups/' + '?search=' + this.search + '&orderBy=' + this.orderBy + '&order=' + this.order + '&size=' + this.size + '&page=' + this.page;
        this.loading = true;
        this.$http.get(url).then(function (response) {
          _this.userOptions = response.data.userOptions;
          _this.tableData = response.data.tableData;
          _this.total = response.data.total;
          _this.loading = false;
        }).catch(function (error) {
          _this.$message.error('获取用户组列表失败');
          _this.loading = false;
        });
      },
      handleEdit: function (index, row) {
        this.groupForm.id = row.id;
        this.groupForm.name = row.name;
        var _this = this;
        this.$http.get('/api/account/getUsersByGroupId/?id=' + row.id).then(function (response) {
          _this.groupForm.userIdList = response.data.userIdList;
        }).catch(function (error) {
          _this.$message.error('获取组用户列表失败');
        });
        this.title = '编辑用户组';
        this.changeMode = true;
        this.groupFormVisible = true;
      },
      handleDelete: function (index, row) {
        var idList = [row.id];
        this.deleteSubmit(idList);
      },
      deleteMutiple: function () {
        var idList = []
        this.multipleSelection.forEach(v => {idList.push(v.id)});
        this.deleteSubmit(idList);
      },
      handleAdd: function () {
        this.title = '添加用户组';
        this.groupForm.name = '';
        this.groupForm.userIdList = [];
        this.changeMode = false;
        this.groupFormVisible = true;
      },
      deleteSubmit: function (idList) {
        var _this = this;
        this.$confirm('删除用户组信息: [' + idList.toString() + '], 是否继续?', '确认', {
          confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning'}).then(() => {
            this.$http.post('/api/account/deleteGroup/', {'idList': idList}).then(
              function (response) {
                _this.$notify({ title: '成功', message: '删除用户组信息成功', type: 'success'});
                _this.reloadTable();
              }
            ).catch(function (error) {
              if (error.response.status === 403) {
                _this.$message.warning('没有权限操作');
              } else {
                _this.$message.error('删除用户组信息失败');
              }
            }
          );
        }).catch(() => {
          this.$message({type: 'info', message: '已取消删除'});
        });
      },
      sortChange: function (sort) {
        this.orderBy = sort.prop;
        this.order = sort.order;
        this.reloadTable();
      },
      handleSearch: function () {
        setTimeout(this.reloadTable, 500);
      }
    },
    mounted: function () {
      this.reloadTable();
    }
  }
</script>

编辑用户组

src/components/GroupEdit.vue

<template>
  <el-dialog :title="title" :visible="groupFormVisible" @close="handleClose">
    <el-form label-position="left" status-icon ref="groupForm" :model="groupForm" :rules="rules" label-width="100px">
      <el-form-item v-if="changeMode" label="ID" prop="id">
        <el-input :disabled="changeMode" v-model="groupForm.id"></el-input>
      </el-form-item>
        <el-form-item label="用户组名" prop="name">
        <el-input v-model.trim="groupForm.name"></el-input>
      </el-form-item>
      <el-form-item label="用户成员" prop="lastName">
        <el-select v-model="groupForm.userIdList" multiple clearable filterable placeholder="请选择">
          <el-option v-for="(user, index) in userOptions" :key="index" :label="user.username + '(' + user.fullname + ')'" :value="user.id">
          </el-option>
        </el-select>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="handleClose">取消</el-button>
      <el-button type="primary" @click="saveSubmit('groupForm')">保存</el-button>
    </div>
</el-dialog>
</template>

<script>
  export default {
    props: ['title', 'groupFormVisible', 'changeMode', 'userOptions', 'groupForm'],
    data: function () {
      return {
        rules: {
          name: [
            { required: true, message: '请输入用户组名', trigger: 'blur' },
            { max: 80, message: '长度不得超过80个字符', trigger: 'blur' }
          ]
        }
      }
    },
    methods: {
      saveSubmit: function (formName) {
        var _this = this;
        this.$refs[formName].validate((valid) => {
          if (valid) {
            var url = '';
            this.changeMode ? url = '/api/account/changeGroup/' : url = '/api/account/addGroup/';
            this.$http.post(url, this.groupForm).then(function (response) {
              _this.$notify({ title: '成功', message: '保存用户组信息成功', type: 'success'});
              _this.handleClose();
              _this.$emit('reloadTable');
            }).catch(function (error) {
              if (error.response.status === 403) {
                _this.$message.warning('没有权限操作');
              } else {
                _this.$message.error('保存用户组信息失败');
              }
            });
          } else {
            _this.$message.error('未通过表单验证');
            return false;
          }
        });
      },
      handleClose: function () {
        this.$emit('update:groupFormVisible', false);
      }
    }
  }
</script>

<style scoped>
  .el-select {
    width: 100%;
  }
</style>

权限管理

权限管理和用户组管理同理的

src/components/PermissionManagement.vue

<template>
  <div>
    <div class="div-header">
      <el-row>
        <el-col :offset="19" :span="4">
          <el-input placeholder="请输入搜索内容" clearable size="mini" suffix-icon="el-icon-search" v-model="search" @input="handleSearch">
          </el-input>
        </el-col>
      </el-row>
    </div>
    <el-table border :data="tableData" style="width: 100%" v-loading="loading" element-loading-text="拼命加载中" :span-method="groupSpan" @sort-change="sortChange">
      <el-table-column prop="id" sortable="custom" label="ID"></el-table-column>
      <el-table-column prop="name" sortable="custom" label="用户组名"></el-table-column>
      <el-table-column prop="permissionName" label="权限"></el-table-column>
      <el-table-column label="操作" width="130">
        <template slot-scope="scope">
          <el-button size="mini" icon="el-icon-edit"
            :disabled="$store.state.permissions.indexOf('auth.change_permission') < 0"
            @click="handleEdit(scope.$index, scope.row)">
            编辑
          </el-button>
        </template>
      </el-table-column>
    </el-table>
    <permissionEdit :permissionFormVisible.sync="permissionFormVisible"
      :permissionOptions="permissionOptions" :permissionForm="permissionForm"
      @reloadTable="reloadTable">
    </permissionEdit>
    <pagination :total="total" :pageSizes="[20, 50, 100]" :pageSize.sync="size"
      :currentPage.sync="page" @reloadTable="reloadTable">
    </pagination>
  </div>
</template>

<script>
  import permissionEdit from '@/components/PermissionEdit.vue';
  import pagination from '@/components/Pagination.vue';
  export default {
    components: {
      'permissionEdit': permissionEdit,
      'pagination': pagination
    },
    data: function () {
      return {
        loading: false,
        multipleSelection: [],
        tableData: [],
        total: 0,
        permissionFormVisible: false,
        permissionOptions: [],
        permissionForm: {
          id: '',
          name: '',
          permissionList: []
        },
        size: 20,
        page: 1,
        search: '',
        orderBy: '',
        order: ''
      };
    },
    methods: {
      groupSpan: function ({ row, column, rowIndex, columnIndex }) {
        var count = 0;
        this.tableData.forEach((v) => {
          if (v.id === row.id) {
            count++;
          }
        });
        if (columnIndex !== 2) {
          if (rowIndex === 0) {
            return [count, 1];
          }else if (this.tableData[rowIndex].id !== this.tableData[rowIndex-1].id) {
            return [count, 1];
          } else {
            return [0, 0];
          }
        }
      },
      reloadTable: function () {
        var _this = this;
        var url = '/api/account/getPermissions/' + '?search=' + this.search + '&orderBy=' + this.orderBy + '&order=' + this.order + '&size=' + this.size + '&page=' + this.page;
        this.loading = true;
        this.$http.get(url).then(function (response) {
          _this.permissionOptions = response.data.permissionOptions;
          _this.tableData = response.data.tableData;
          _this.total = response.data.total;
          _this.loading = false;
        }).catch(function (error) {
          _this.$message.error('获取用户组权限列表失败');
          _this.loading = false;
        });
      },
      handleEdit: function (index, row) {
        this.permissionForm.id = row.id;
        this.permissionForm.name = row.name;
        var _this = this;
        this.$http.get('/api/account/getPermissionsByGroupId/?id=' + row.id).then(
          function (response) {
            _this.permissionForm.permissionList = response.data.permissionList;
            if (_this.permissionForm.permissionList.length === _this.permissionOptions.length) {
              _this.checkAll = true;
            } else {
              _this.checkAll = false;
            }
          }
        ).catch(function (error) {
          _this.$message.error('获取组权限列表失败');
        });
        this.title = '编辑用户组权限';
        this.permissionFormVisible = true;
      },
      sortChange: function (sort) {
        this.orderBy = sort.prop;
        this.order = sort.order;
        this.reloadTable();
      },
      handleSearch: function () {
        setTimeout(this.reloadTable, 500);
      }
    },
    mounted: function () {
      this.reloadTable();
    }
  }
</script>

src/components/PermissionEdit.vue

<template>
  <el-dialog title="编辑权限" width="90%" :visible="permissionFormVisible" @close="handleClose">
    <el-form label-position="left" status-icon ref="permissionForm" :model="permissionForm"
      label-width="100px">
      <el-form-item label="ID" prop="id">
        <el-input disabled v-model="permissionForm.id"></el-input>
      </el-form-item>
      <el-form-item label="用户组名" prop="name">
        <el-input disabled v-model="permissionForm.name"></el-input>
      </el-form-item>
      <el-form-item label="权限" prop="permissionList">
        <el-checkbox v-model="checkAll" @change="handleCheck">全选</el-checkbox>
        <el-checkbox-group v-model="permissionForm.permissionList">
          <el-checkbox v-for="(permission, index) in permissionOptions" :key="index"
            :label="permission.id"> {{ permission.name }}
          </el-checkbox>
        </el-checkbox-group>
      </el-form-item>
    </el-form>
    <div slot="footer" class="dialog-footer">
      <el-button @click="handleClose">取消</el-button>
      <el-button type="primary" @click="saveSubmit('permissionForm')">保存</el-button>
    </div>
  </el-dialog>
</template>

<script>
  export default {
    props: ['permissionFormVisible', 'permissionOptions', 'permissionForm'],
    data: function () {
      return {
        checkAll: false,
      }
    },
    methods: {
      idList: function(optList) {
        var ids = [];
        for(var opt in optList){
          ids.push(optList[opt]['id'])
        }
        return ids;
      },
      handleCheck: function () {
        if (this.checkAll) {
          this.permissionForm.permissionList = this.idList(this.permissionOptions); 
        } else {
          this.permissionForm.permissionList = [];
        }
      },
      saveSubmit: function (formName) {
        var _this = this;
        this.$refs[formName].validate((valid) => {
          if (valid) {
            var url = '/api/account/changePermission/';
            this.$http.post(url, this.permissionForm).then(function (response) {
              _this.$notify({ title: '成功', message: '保存用户组权限信息成功', type: 'success'});
              _this.handleClose();
              _this.$emit('reloadTable');
            }).catch(function (error) {
              if (error.response.status === 403) {
                _this.$message.warning('没有权限操作');
              } else {
                _this.$message.error('保存用户组权限信息失败');
              }
            });
          } else {
            _this.$message.error('未通过表单验证');
            return false;
          }
        });
      },
      handleClose: function () {
        this.$emit('update:permissionFormVisible', false);
      }
    }
  }
</script>

修改密码

src/components/PasswordChange.vue

<template>
  <div>
    <el-alert title="修改密码" center type="warning" :closable="false"></el-alert>
    <div class="div-form">
      <el-form :model="passwordForm" status-icon :rules="rules" ref="passwordForm" label-width="100px">
        <el-form-item label="用户" prop="userId">
          <el-select v-if="$store.state.user.isSuperuser" v-model="passwordForm.userId"
            clearable filterableplaceholder="请选择用户">
            <el-option v-for="(user, index) in userOptions" :key="index" :label="user.username + '(' + user.fullname + ')'" :value="user.id">
            </el-option>
          </el-select>
          <el-input v-else disabled v-model="$store.state.user.username + ' (' + $store.state.user.fullname + ')'">
          </el-input>
        </el-form-item>
        <el-form-item v-show="$store.state.user.id === passwordForm.userId" label="原密码"
          prop="oldPassword">
          <el-input type="password" v-model="passwordForm.oldPassword" auto-complete="off"></el-input>
        </el-form-item>
        <el-form-item label="新密码" prop="newPassword">
          <el-input type="password" v-model="passwordForm.newPassword" auto-complete="off"></el-input>
        </el-form-item>
        <el-form-item label="确认新密码" prop="confirmPassword">
          <el-input type="password" v-model="passwordForm.confirmPassword" auto-complete="off"></el-input>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="submitForm('passwordForm')">提交</el-button>
          <el-button @click="resetForm('passwordForm')">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
  export default {
    data: function () {
      var validateOldPass = (rule, value, callback) => {
        if (this.$store.state.user.id === this.passwordForm.userId) {
          if (value === '') {
            callback(new Error('请输入原密码'));
          } else {
            callback();
          }
        } else {
          callback();
        }
      };
      var validateNewPass = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请输入新密码'));
        } else {
          if (this.passwordForm.confirmPassword !== '') {
            this.$refs.passwordForm.validateField('confirmPassword');
          }
          callback();
        }
      };
      var confirmNewPass = (rule, value, callback) => {
        if (value === '') {
          callback(new Error('请再次输入密码'));
        } else if (value !== this.passwordForm.newPassword) {
          callback(new Error('两次输入密码不一致!'));
        } else {
          callback();
        }
      };
      return {
        passwordForm: {
          userId: '',
          oldPassword: '',
          newPassword: '',
          confirmPassword: ''
        },
        userOptions: [],
        rules: {
          oldPassword: [
            { validator: validateOldPass, trigger: 'blur'}
          ],
          newPassword: [
            { validator: validateNewPass, trigger: 'blur' }
          ],
          confirmPassword: [
            { validator: confirmNewPass, trigger: 'blur' }
          ]
        }
      };
    },
    methods: {
      submitForm(formName) {
        var _this = this;
        this.$refs[formName].validate((valid) => {
          if (valid) {
            this.$http.post('/api/account/updatePassword/', this.passwordForm).then(
              function (response) {
                if (_this.$store.state.user.id === _this.passwordForm.userId) {
                  _this.$alert('修改密码成功', '提示', {
                    confirmButtonText: '确定',
                    callback: action => {
                      _this.$store.dispatch('setLoggedIn', false);
                      _this.$router.push({path: '/Login'});
                    }
                  });
                } else {
                  _this.$notify({title: '提示', message: '密码修改成功', type: 'success'});
                }
              }
            ).catch(function (error) {
              _this.$message.error('修改密码失败');
            });
          } else {
            _this.$message.error('未通过表单验证');
            return false;
          }
        });
      },
      resetForm(formName) {
        this.$refs[formName].resetFields();
      }
    },
    mounted: function () {
      if (this.$store.state.user.isSuperuser) {
        var _this = this;
        this.$http.get('/api/account/getUserList/').then(function (response) {
          _this.userOptions = response.data;
        }).catch(function (error) {
          if (error.response.status === 403) {
            _this.$message.warning('没有权限操作');
          } else {
            _this.$message.error('获取用户信息失败');
          }
        });
      }
      this.passwordForm.userId = this.$store.state.user.id;
    }
  }
</script>

<style scoped>
  .div-form {
    margin-top: 20px;
    margin-left: 25%;
    margin-right: 25%;
  }
  .el-input {
    width: 90%;
  }
  .el-select {
    width: 90%;
  }
</style>


运行项目

添加导入的css到static目录

static连接

启动项目

$ npm run dev