0 the introduction

It has been a month and a half since the author used vue-element-admin project to integrate the background Spring-boot project to open the left menu function of the front and back end permission control home page. Recently in the project team, with are huawei since the research of new technologies, and huawei’s IT system integration is very much since the inquiry system, for a long time made the author feel touched not pure way, especially in spirit finches system represented by the low code platform, some don’t need how to write the code, just allocation model and the service choreography, Then the page binding model and service are OK. The amount of code is much less, but the door is much higher. Therefore, I didn’t have much time to develop my own open source project because I worked too much overtime for more than a month. But I recently found the time to implement the promised features. In this paper, the author will lead you to realize how to use element-UI open source UI framework to call the Spring-boot project to achieve the background interface to achieve the function of paging query user information and view the role of the user, and the page effect will be displayed at the end.

Vue – Element-admin implements dynamic rendering of role-based menu resources with SpringBoot.

Talk about prototyping requirements

In the IT industry, almost all development is based on certain requirements. Product managers usually form a requirements document after docking with customers, which not only has detailed requirements specifications and descriptions, but also includes low-fidelity and high-fidelity diagrams designed by prototypes. Low-fidelity graphics are typically done by the product’s best efforts with prototyping tools such as MockPlus and Sketch, while high-fidelity is done by dedicated UCD staff. UCD is shorthand for user-Centered Design, which translates into “user-centered Design” in Chinese.

First of all, we complete the two interfaces in the background according to the requirements of the prototype design drawing, which are the interface of paging query user information data and query user role list according to the user ID. The first interface corresponds to the front UI function for user management under the left menu of permission management, the default page query user information list is displayed, and the user list can also be queried through the form form. On the second interface, when you click the view existing roles link in the user data operation bar of each row, the pop-up box displays the list of existing roles of the selected user.

Figure 1 User management interface

Figure 2 Click to view existing roles the pop-up box shows the list of existing roles of the selected user

Note: due to the author is not skilled in the use of product design tools, so the use of partial effect as a prototype

2. Back-end interface development

According to the requirements of the prototype interface split to complete the development of two background interface, according to the idea of hierarchical design to complete the two interface coding.

2.1 Complete the interface for paging user information Query

2.1.1 DaoLayer code

UserMapper.java

// Query the number of qualified users
int queryUserCountsByCondition(@Param("userParam") QueryUserParam userParam);
// paging query
    List<User> queryPageUsersByCondition(@Param("startIndex") int startIndex,@Param("endIndex") int endIndex,
                                         @Param("userParam") QueryUserParam userParam);
Copy the code

UserMapper.xml

<select id="queryUserCountsByCondition" resultType="int">
        select count(*) from user
        <include refid="userConditionSql" />
    </select>
    <! SQL > select * from SQL;
    <sql id="userConditionSql">
        where enabled=1
        <if test="userParam.username! =null and userParam.username! = "">
            and  username like  concat('%',#{userParam.username,jdbcType=VARCHAR},'%')
        </if>
        <if test="userParam.nickname! =null and userParam.nickname! = "">
            and  nickname like concat('%',#{userParam.nickname,jdbcType=VARCHAR},'%')
        </if>
        <if test="userParam.email! =null and userParam.email! = "">
            and email like concat('%',#{userParam.email,jdbcType=VARCHAR},'%')
        </if>
        <if test="userParam.regStartTime! =null and userParam.regStartTime! = "">and regTime <! [CDATA[>=]]> #{userParam.regStartTime}</if>
        <if test="userParam.regEndTime! =null and userParam.regEndTime! = "">and regTime <! [CDATA[<=]]> #{userParam.regEndTime}</if>
    </sql>
    <! SQL > select * from user where user = 'user';
    <select id="queryPageUsersByCondition" resultType="org.sang.pojo.User">
        select t.id,t.username,t.nickname,t.enabled,t.email,t.regTime
        from
        (select id, username,nickname,enabled,email,regTime
        from user
        <include refid="userConditionSql" />
        ) t limit #{startIndex,jdbcType=INTEGER},#{endIndex,jdbcType=INTEGER}
    </select>
Copy the code
2.1.2 ServiceLayer code

UserService.java

public RespBean queryPageUsersByCondition(PageVo<User> pageVo, QueryUserParam userParam){
        logger.info("currPage={},pageSize={},queryUserParam={}",
                pageVo.getCurrPage(),pageVo.getPageSize(), JSON.toJSON(userParam));
        int totalRows = userMapper.queryUserCountsByCondition(userParam);
        pageVo.setTotalRows(totalRows);
    // If the end index is greater than the total number, the total number is assigned to the end index
        if(pageVo.getEndIndex()>totalRows){
            pageVo.setEndIndex(totalRows);
        }
    // Set the total number of pages
        pageVo.setTotalPage((totalRows/pageVo.getPageSize())+1);
        List<User> pageUsers = userMapper.queryPageUsersByCondition(pageVo.getStartIndex(),pageVo.getEndIndex(),userParam);
        pageVo.setResult(pageUsers);
        RespBean respBean = new RespBean(200."success");
        respBean.setData(pageVo);
        return respBean;
    }
Copy the code

Add the @jsonFormat annotation to the user object date property to display the foreground date as a string

User.java

@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
    private Date regTime;
Copy the code
2.1.3 ControllerLayer code

UserController.java

@RequestMapping(value = "/pageQuery/users/{currPage}/{pageSize}",method = RequestMethod.POST)
    public RespBean queryPageUsersByCondition(@PathVariable("currPage") int currPage, @PathVariable("pageSize") int pageSize,
                                              @RequestBody QueryUserParam userParam){
        PageVo<User> pageVo = new PageVo<>(currPage,pageSize);
        RespBean respBean = userService.queryPageUsersByCondition(pageVo,userParam);
        returnrespBean; } # # # #2 2.The interface for querying the user role list by user ID ##### is complete2.21.'Dao' layer code 'rolemapper.java ` ```java
List<Role> getRolesByUid(Long uid);
Copy the code

RoleMapper

    <select id="getRolesByUid" parameterType="java.lang.Long" resultType="org.sang.pojo.Role">
        SELECT r.id,
               r.role_code as roleCode,
               r.role_name as roleName
        FROM roles r
        where r.id in
        (select rid
         from roles_user
         where uid = #{uid,jdbcType=BIGINT}
         )
    </select>

Copy the code
2.2.2 ServiceLayer code

RoleService.java

    @Autowired
    private RolesMapper rolesMapper;

    public List<Role> getRolesByUid(Long uid){

        List<Role> roles = rolesMapper.getRolesByUid(uid);
        // In ascending order by ID
        if(roles.size()>1){
            roles.sort(Comparator.comparing(Role::getId));
        }
        return roles;
    }

Copy the code
2.2.3 ControllerLayer code

RoleController.java

@GetMapping("/getUserRoles")
    public RespBean getUserRoles(@RequestParam("uid") Long uid) {
        logger.info("uid={}",uid);
        List<Role> roles = roleService.getRolesByUid(uid);
        RespBean respBean = new RespBean(200."success");
        respBean.setData(roles);
        return respBean;
    }
Copy the code

After the interface development is complete, after starting the background service, you can test the interface through Postman. There are a lot of previous articles about how to use Postman this interface UI tool to test the developed API, here I will not demonstrate.

3 Front-end interface and button functions

3.1 Added the API export configuration of two Background interfaces

src/api/user.js

export function queryUserInfosByPage(queryParam, pageParam) {
  return request({
    url: `pageQuery/users/${pageParam.currPage}/${pageParam.pageSize}`.method: 'post'.data: queryParam
  })
}
Copy the code

src/api/role.js

export function getRolesByUid(uid) {
  return request({
    url: `/role/getUserRoles? uid=${uid}`.method: 'get'})}Copy the code

3.2 Complete the user management VUE component coding

According to the prototype design, we need to develop a user-managed component. We can create a new usermanage. vue file in the SRC /views/ Permission directory of our front-end project vue-element-admin. The author refers to the component demo source code of Element-UI official website to complete the user management component coding, and its source code is as follows:

<!--组件html模板-->
<template>
  <div id="userAccoutTemplate">
      <!--查询表单-->
    <el-form :model="searchForm" label-width="120px" ref="searchForm" class="search-ruleForm">
      <div class="form-line">
        <el-form-item label="账号:" class="user-account" prop="username">
          <el-input v-model="searchForm.username"></el-input>
        </el-form-item>
        <el-form-item label="用户昵称:" class="nickname" prop="nickname">
            <el-input v-model="searchForm.nickname"></el-input>
        </el-form-item>
        <el-form-item label="邮箱:" class="email" prop="email">
            <el-input v-model="searchForm.email"></el-input>
        </el-form-item>
        </div>
        <div class="date-time-line form-line">
            <!--日期时间范围组件-->
          <el-form-item label="时间范围" class="timeRange" prop="timeRange">
              <el-date-picker v-model="searchForm.dateTimes" type="datetimerange"
                range-separator="至" start-placeholder="开始时间" end-placeholde="结束时间" align="right" 
               format="yyyy-MM-dd HH:mm:ss" value-format="yyyy-MM-dd HH:mm:ss" :picker-options="pickOptions">
              </el-date-picker>
          </el-form-item>
        </div>
        <div class="button-line">
            <el-button type="primary" @click="submitForm('searchForm')">查询</el-button>
            <el-button @click="resetForm('searchForm')">重置</el-button>
        </div>
    </el-form>
      <!--数据列表-->
    <el-table border :data="userAccounts" style="width: 100%">
        <el-table-column prop="username" label="用户账号" width="200"></el-table-column>
        <el-table-column prop="nickname" label="用户名称" width="200"></el-table-column>
        <el-table-column prop="email" label="邮箱" width="250"></el-table-column>
        <el-table-column prop="regTime" label="注册时间" width="250"></el-table-column>
        <el-table-column width="350"
        label="操作">
        <template slot-scope="scope">
          <el-button @click="openQueryDialog(scope.row)" type="text" size="small">查看已有角色</el-button>
          <el-button type="text" @click="openEditDialog(scope.row)" size="small">分配角色</el-button>  
        </template>
      </el-table-column>
    </el-table>
    <!-- 分页组件-->
    <el-pagination @size-change="hadleSizeChange" @current-change="handleCurrentChange"
      :current-page="currentPage" :page-sizes="pageSizes" :page-size="pageSize"
       layout="total, sizes, prev, pager, next, jumper" :total="totalCounts">    
    </el-pagination>
     <!--用于显示用户角色列表的弹框-->
    <el-dialog class="query-dialog" title="用户已有角色" :visible.sync="queryDialogVisible" 
      width="35%">
      <el-table ref="qeuryDialogTable" :data="userRoles" highlight-current-row 
        @current-change="handleCurrentRowChange" style="width: 100%"
      >
         <el-table-column property="id" label="角色ID" width="80">
         </el-table-column>
         <el-table-column property="roleCode" label="角色编码" width="120">
         </el-table-column>
         <el-table-column property="roleName" label="角色名称" width="120">
         </el-table-column>
      </el-table>
      <span slot="footer" class="dialog-footer">
        <el-button @click="closeQueryDialog">取 消</el-button>
        <el-button type="primary" @click="closeQueryDialog">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>
<!--javascript脚本-->
<script>
import {queryUserInfosByPage} from '@/api/user'
import {getRolesByUid} from '@/api/role'
import { Message } from 'element-ui'

export default {
    // 数据模型
  data() {
    let startDate = new Date()
    // 默认选中最近一周的时间
    startDate.setTime(startDate.getTime() -  3600 * 1000 * 24 * 7)
    const endDate =new Date()
    const startYear = startDate.getFullYear()
    const startMonth = startDate.getMonth()>8?''+(startDate.getMonth()+1):'0'+(startDate.getMonth()+1)
    const startMonthDay = startDate.getDate()>9?''+startDate.getDate():'0'+startDate.getDate()
    const startHours = startDate.getHours()>9?''+startDate.getHours():'0'+startDate.getHours()
    const startMinutes = startDate.getMinutes()>9?''+startDate.getMinutes():'0'+startDate.getMinutes()
    const startSeconds = startDate.getSeconds()>9?''+startDate.getSeconds():'0'+startDate.getSeconds()
    const startDateTimeStr = startYear+'-'+startMonth+'-'+startMonthDay+' '+startHours+':'+startMinutes+':'+startSeconds
    const endYear = endDate.getFullYear()
    const endMonth = endDate.getMonth()>8?''+(endDate.getMonth()+1):'0'+(endDate.getMonth()+1)
    const endMonthDay = endDate.getDate()>9?''+endDate.getDate():'0'+endDate.getDate()
    const endHours = endDate.getHours()>9?''+endDate.getHours():'0'+endDate.getHours()
    const endMinutes = endDate.getMinutes()>9?''+endDate.getMinutes():'0'+endDate.getMinutes()
    const endSeconds = endDate.getSeconds()>9?''+endDate.getSeconds():'0'+endDate.getSeconds()
    const endDateTimeStr = endYear+'-'+endMonth+'-'+endMonthDay+' '+endHours+':'+endMinutes+':'+endSeconds
    return {
      searchForm: {
        username: '',
        nickname: '',
        email: '',
        dateTimes: [startDateTimeStr,endDateTimeStr]
      },
      userAccounts: [{ id: 1, username: 'zhangsan', nickname: '张三', email: '[email protected]', regTime: '2021-06-20 23:58:48' },
        { id: 2, username: 'heshengfu', nickname: '程序员阿福', email: '[email protected]', regTime: '2021-06-21 00:00:13' },
        { id: 3, username: 'lisi', nickname: '李四', email: '[email protected]', regTime: '2021-08-04 00:45:38' }],
      pickOptions: {
        shortcuts: [{
            text: '最近一周',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 7);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近一个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 30);
              picker.$emit('pick', [start, end]);
            }
          }, {
            text: '最近三个月',
            onClick(picker) {
              const end = new Date();
              const start = new Date();
              start.setTime(start.getTime() - 3600 * 1000 * 24 * 90);
              picker.$emit('pick', [start, end]);
            }
          }]
      },
      currentPage: 1,
      pageSizes: [10,20,50,100,500],
      pageSize: 10,
      totalCounts: 120,
      queryDialogVisible: false,
      currentRoleRow: 0,
      userRoles: [
        {id:1,roleCode:'admin',roleName:'管理员'},
        {id:2,roleCode:'user',roleName:'普通用户'}
        ]
    }
      
  },
  methods: {
      // 提交查询表单
      submitForm(formName) {
      console.log(formName)
      const formData = this.searchForm
      const queyParam = {
        username: formData.username,
        nickname: formData.nickname,
        email: formData.email,
        regStartTime: formData.dateTimes[0],
        regEndTime: formData.dateTimes[1]
      }
      console.log(queyParam)
      // 分页参数
      const pageParam = {
        currPage: this.currentPage,
        pageSize: this.pageSize
      }
      console.log(pageParam)
      // 发送axios请求查询用户数据    
      queryUserInfosByPage(queyParam, pageParam).then(res=>{
          if(res.status===200 && res.data.status===200){
            const pageData = res.data.data
            this.totalCounts = pageData.totalRows
            this.userAccounts = pageData.result
          }else{
            Message.error('queryUserInfosByPage, status:'+res.data.status+', message:'+res.data.msg)
          }
      }).catch(err=>{
        Message.error(err)
      })
    },
    // 表单重置时间   
    resetForm(formName) {
      this.$refs[formName].resetFields()
    },
   // 分页条数改变事件   
    hadleSizeChange(val) {
      console.log(val);
      this.pageSize = val
      this.submitForm('searchForm')
    },
    // 当前页改变事件  
    handleCurrentChange(val){
       console.log(val);
       this.currentPage = val
       this.submitForm('searchForm')
    },
    // 打开查询用户已有角色对话框事件
    openQueryDialog(row) {
      console.log(row)
      this.queryDialogVisible = true
      const uid = row.id
      getRolesByUid(uid).then(res=>{
        if(res.status===200 && res.data.status===200){
          this.userRoles = res.data.data
        }else{
          this.userRoles = []
           Message.error('getRolesByUid, status:'+res.data.status+', message:'+res.data.msg)
        }
      }).catch(err=>{
         console.error(err)
      })
    },
    openEditDialog(row){
      console.log(row)
    },
    closeQueryDialog(){
      this.queryDialogVisible = false
    },
    // 当前行改变事件  
    handleCurrentRowChange(row){
      this.currentRoleRow = row
      this.$refs['qeuryDialogTable'].setCurrentRow(row)
    }
  }
}
</script>
<!--页面样式,通过调试模式在浏览器中调试出效果后复制过来-->
<style lang="scss" scoped>
  .search-ruleForm{
    width: 100%;
    height: 180px;
    .el-form-item__label {
      text-align: right;
    }
    .form-line {
      height: 32px;
      width: 100%;
      margin-bottom: 20px;
      .el-form-item {
        width: 32%;
        float: left;
      }
    }
    .button-line {
      height: 40px;
      width: 100%;
      margin-top: 25px;
    }
  }
</style>
Copy the code

3.3 Modifying the source code of the Permission Management Portal Component

src/views/page.vue

<template>
  <div class="app-container">
    <user-manage></user-manage>
  </div>
</template>
<script>
// import SwitchRoles from './components/SwitchRoles'
import UserManage from './components/UserManage.vue'

export default {
  name: 'PagePermission'.components: { UserManage },
  methods: {
    // handleRolesChange() {
    // this.$router.push({ path: '/permission/index' })
    // }}}</script>
Copy the code

You need to add the user management component in the permission management portal and shield the original role switching component

3.4 Modifying a Route Array

src/router/index.js

export const asyncRoutes = [
  {
    id: '15'.path: '/permission'.component: Layout,
    redirect: '/permission/page'.alwaysShow: true.// will always show the root menu
    name: 'Permission'.meta: {
      title: 'Permission Management'.icon: 'lock'
    // roles: ['admin', 'editor']
    },
    children: [{id: '16'.path: 'page'.component: () = > import('@/views/permission/page'),
        name: 'PagePermission'.meta: {
          title: 'User Management'}}, {id: '17'.path: 'directive'.component: () = > import('@/views/permission/directive'),
        name: 'DirectivePermission'.meta: {
          title: 'Directive Permission'
          // if do not set roles, means: this page does not require permission}}, {id: '18'.path: 'role'.component: () = > import('@/views/permission/role'),
        name: 'RolePermission'.meta: {
          title: 'Role Management'.roles: ['admin']}}]},/ /... Other Routing Components
]
Copy the code

In order to display the permission control menu in Chinese, the title field data corresponding to the permission related data of the routing component data is modified

4 Effect Experience

In the vue-element-admin root directory, use git bash or CMD to open the console and run the NPM run dev command to start the script.

If the following logs are displayed on the console, the front-end service is successfully started:

98% after emitting CopyPlugin DONE  Compiled successfully in1072 ms 8:04:51 App running in the morning at: - Local: http://localhost:3000/ - Network: http://192.168.1.235:3000/Copy the code

Enter http://localhost:3000/ in Google Browser to enter the login interface. After successful login, enter the project home page, and then click Permission Management -> User Management in the left menu bar to see the following interface effect picture

Figure 3 Effect diagram of user management interface

Click the event range selection box to quickly select the last three months, and then click the query button, you can see the interface displays the user information data queried from the background database, and displays 10 items per page. You can enter your account name, nickname, and email address as the search criteria to query the data that meets the search criteria. You can also click to switch the current page and the number of pages to view the desired data on the page.

Figure 4. Paging query data in the form

Click the View existing roles link in the action bar of each user record and a dialog box will pop up showing the roles assigned by the user

Figure 5 Viewing the user’s existing roles

5 subtotal

This article followed my last original article vue-element-admin integration of SpringBoot to achieve dynamic rendering of role-based menu resources pit record (integration of the front and back end) developed the user management interface function in the custom permission design module, involving two functions such as paging to view user information and pop-ups to display the user’s existing roles. It has few features, but it can help readers quickly learn the skills of separating the front and back ends, as well as elemental-UI, a UI framework for developing elegant, minimalist Web interfaces. In my next article, I will soon introduce functions such as assigning roles to users and assigning page routing resources to roles, so stay tuned!

This article front and back end project has been uploaded to the personal Gitee warehouse, need source friends welcome to pay attention to the author’s wechat public number AH Fu about Web programming, send the keyword VUe-element-admin to get the front-end project warehouse address; Send keyword blog-server to get the back-end project address.

6 Reference Links

Element – UI official website component development Demo)

This article first personal wechat public number fu about Web programming, welcome to read here friends add a wechat article, regularly share project combat and interview summary dry goods article, a technical class of public number you are worth paying attention to, hand in hand with readers on the road of technology growing!