Spring boot+Shiro+ spring MVC+swagger UI +Mybatis+mysql+Vue +Element UI 之三 vue简单页面实战

本文利用现在要进行的日志中心模块展示vue的基本用法。


1. 后台开发

新建LogController,和LogService 实现,包括mapper等,由于本文主要研究vue的基本语法及开发流程,后台不详细展开。Controller代码如下:

  @GetMapping(value = "allLogs")
    @ApiOperation(value = "获取日志列表或者查询日志接口", httpMethod = "GET", response = String.class, notes = "获取日志列表或者查询日志接口")
    public Response<Object> getRolesList(@RequestParam(required = false) String logKeyWord, @RequestHeader String token) {
        LOGGER.info("获取日志列表或者查询日志接口,userid:{},logKeyWord:{}", logKeyWord);
        Response<Object> response = new Response<>();
        List<VoLog> voLogList = new ArrayList<>();
        long userId = CommonUtils.getManageCurUserId(token);
        List<UserOperateLog> userOperateLogList = logService.getAllLogs();
        if (userOperateLogList != null && !userOperateLogList.isEmpty()) {
            for (UserOperateLog userOperateLog : userOperateLogList) {
                VoLog voLog = BaseMappingUtils.populateTbyDByCglib(userOperateLog, VoLog.class);
                voLogList.add(voLog);
            }

        }
        response.setData(voLogList);
        response.setCode(ResponseCodeEnum.C200.getCode());
        response.setMsg(ResponseCodeEnum.C200.getDescription());
        LOGGER.info("获取角色列表接口出参rel:{}", response.toString());
        return response;

    }


2. 前端页面开发

后台数据库菜单信息中,配置菜单路径为/logCenter.

'21', '日志中心', '日志中心', '/logCenter', '#', '0', '5', '0', '1', NULL, '2017-12-18 16:33:32', NULL, NULL, NULL

在logCenter目录下,新建index.vue文件

-logCenter

 ----index.vue


index.vue内容如下:

<template>
  <section>
    <div  v-loading='loading'>
      <el-col :span='24' class='toolbar' style='padding-bottom: 0px;'>
        <el-form :inline='true'>
          <el-form-item>
            <el-input v-model='logKeyWord' placeholder='请输入关键字' clearable></el-input>
          </el-form-item>
          <el-form-item>
            <el-button type='primary' v-on:click='getAllLogs'>查询</el-button>
          </el-form-item>

        </el-form>
      </el-col>

      <el-table :data='logLists' stripe style='width: 100%; margin: 0 auto; text-align:center;'>
        <el-table-column label='ID'>
          <template slot-scope='scope'>
            <label>{{scope.row.id}}
              <span></span>
            </label>
          </template>
        </el-table-column>
         <el-table-column label='时间'>
          <template slot-scope='scope'>
            <label>{{scope.row.createTime}}
              <span></span>
            </label>
          </template>
         </el-table-column>
          <el-table-column label='操作'>
           <template slot-scope='scope'>
             <label>{{scope.row.operateContent}}
               <span></span>
             </label>
           </template>
          </el-table-column>
          <el-table-column label='操作人'>
            <template slot-scope='scope'>
              <label>{{scope.row.userId}}
                <span></span>
              </label>
            </template>
          </el-table-column>
         <el-table-column label='操作结果'>
            <template slot-scope='scope'>
              <label>{{scope.row.displayName}}
                <span></span>
              </label>
            </template>
          </el-table-column>
      </el-table>

    </div>
  </section>
</template>
<style rel='stylesheet/scss' lang='scss'>
.el-table thead tr th {
  background-color: rgba(28,148,255,0.6) !important;
  color: #fff;
}
.el-table th{
  text-align: center;
}
.addBtn {
  background: #fff;
  color: #1C94FF;
}
</style>
<script lang='babel'>
import webapi from '../../api/webapi'
import {mapState} from 'vuex'

export default {
  name: 'role',
  data () {
    return {
      roleName: '',
      logLists: [],
      loading: false,
      textMap: {
        update: '编辑',
        create: '新增',
        delete: '删除账号'
      },
      dialogFormVisible: false,
      dialogLoading: false,
      temp: {
        role: ''
      },
      dialogStatus: '',
      disabledFlag: true // 角色是否可更改
    }
  },
  computed: {
    ...mapState({
      menuList: state => state.menuList.menuList
    })
  },

  mounted () {
    this.getAllLogs()
  },
  methods: {
    handleEdit (index, row) {
      this.getRoles(row)
      this.temp = Object.assign({}, row) // copy obj
      this.dialogStatus = 'update'
      this.dialogFormVisible = true
    },
    async handleDelete (index, row) {
      try {
        let temp = Object.assign({}, row)
        const params = {
          roleId: temp.id
        }
        const res = await webapi.manage.roles(params)
        if (res.code === '200') {
          this.getRoleInfo()
          this.$message({
            title: '成功',
            message: '删除成功',
            type: 'success',
            duration: 2000
          })
        } else {
          this.$message({
            title: '失败',
            message: res.msg,
            type: 'error',
            duration: 2000
          })
        }
      } catch (e) {
        console.log(e)
      }
    },

    async getAllLogs () {
      try {
        this.loading = true
        const params = {
          logKeyWord: this.logKeyWord
        }
        const res = await webapi.manage.allLogs(params)
        if (res.code === '200') {
          this.logLists = res.data
        } else {
          this.logLists = []
        }
      } catch (e) {
        console.log(e)
      } finally {
        this.loading = false
      }
    },
    itemClick (node) {
      console.log('node', JSON.stringify(node.model))
    }
  }
}
</script>


配置rest api路径,在webapiconfig.js文件中

const BaseUrlV1 = '/api/v1'

const config = {
  user: {
    sendMsg: {
      path: `${BaseUrlV1}/user/sendMsg`,
      method: 'post',
      description: '获取短信验证码'
    },
    getPicVerCode: {
      path: `${BaseUrlV1}/user/getPicVerCode/{mobile}`,
      method: 'get',
      description: '获取图片验证码',
      rest: true
    },
    login: {
      path: `${BaseUrlV1}/user/login`,
      method: 'post',
      description: '用户登录'
    },
    getDataForManageUser: {
      path: `${BaseUrlV1}/user/getDataForManageUser`,
      method: 'post',
      description: '账号管理获取数据'
    },
    editUser: {
      path: `${BaseUrlV1}/user/editUser`,
      method: 'post',
      description: '编辑账号'
    },
    deleteUser: {
      path: `${BaseUrlV1}/user/deleteUser`,
      method: 'post',
      description: '删除账号'
    },
    editUserState: {
      path: `${BaseUrlV1}/user/editUserState`,
      method: 'post',
      description: '更新账号状态'
    },
    addUser: {
      path: `${BaseUrlV1}/user/addUser`,
      method: 'post',
      description: '新增账号'
    },
    logout: {
      path: `${BaseUrlV1}/user/logout`,
      method: 'post',
      description: '退出登录'
    }
  },
  menu: {
    getMenus: {
      path: `${BaseUrlV1}/menu/getMenus`,
      method: 'get',
      description: '获取功能菜单',
      rest: true
    }
  },
  manage: {
    allRoles: {
      path: `${BaseUrlV1}/manage/allRoles`,
      method: 'get',
      description: '获取角色列表'
    },
    roles: {
      path: `${BaseUrlV1}/manage/roles/{roleId}`,
      method: 'delete',
      description: '删除角色'
    },
    createRoles: {
      path: `${BaseUrlV1}/manage/roles`,
      method: 'post',
      description: '新增角色'
    },
    updateRoles: {
      path: `${BaseUrlV1}/manage/roles/{roleId}`,
      method: 'put',
      description: '修改角色'
    },
    getRoles: {
      path: `${BaseUrlV1}/manage/roles/{roleId}`,
      method: 'get',
      description: '查询角色权限',
      rest: true
    },
    getCustomerSInfo: {
      path: `${BaseUrlV1}/manage/customerscfgs`,
      method: 'get',
      description: '获取客群配置列表'
    },
    updateCustomerSInfo: {
      path: `${BaseUrlV1}/manage/customerscfgs/batch`,
      method: 'put',
      description: '更新客群参数配置'
    },
    getFlowInfo: {
      path: `${BaseUrlV1}/manage/fluxcfgs`,
      method: 'get',
      description: '获取流量配置信息'
    },
    updateFlowInfo: {
      path: `${BaseUrlV1}/manage/fluxcfgs/batch`,
      method: 'put',
      description: '更新流量配置信息'
    },
    allLogs: {
      path: `${BaseUrlV1}/manage/allLogs`,
      method: 'get',
      description: '获取全部log列表'
    }

  },
  product: {
    getBasicConInfo: {
      path: `${BaseUrlV1}/product/getDataForManageProductBaseInfo`,
      method: 'post',
      description: '获取产品配置基础配置'
    },
    updateBasicConInfo: {
      path: `${BaseUrlV1}/product/editManageProductBaseInfo`,
      method: 'post',
      description: '更新产品配置基础配置'
    }
  }
}

export default {
  ...config
}


上述代码已运行ok,下面逐个分析。


3. index vue文件分析

3.1 const 定义变量

let:代码块内有效,不存在变量提升情况
const:全局有效,一旦声明,不可改变
var:全局有效,存在变量提升情况,即没有定义前可以使用,值为undefined。

ES5 只有两种声明变量的方法:var命令和function命令。ES6 除了添加letconst命令,后面章节还会提到,另外两种声明变量的方法:import命令和class命令。所以,ES6 一共有 6 种声明变量的方法。



3.2 export 

export default {
  ...config
}

到处config变量,在webapi.js里面导入

//此处导入
import config from './webapiConfig'
import { getToken } from '../utils/auth'
import * as utils from '../utils/utils'
require('whatwg-fetch')
class WebApi {
  constructor () {
    // 网络异常回调
    this.NetErrorCallBack = null
    // hook
    this.beforEach = null
    this.afterEach = null

    this.entry = {}

    this._initWebApi()
  }

  /**
   * url参数解决器 /core/{id}/{class} to /core/1/abc
   * @param path
   * @param params
   * @returns {string}
   * @private
   */
  _pathParamResolve (path, params) {
    if (!utils.isObject(params)) throw new Error('参数必须为 {} 对象')

    let _path = path
    Object.keys(params).forEach(name => {
      _path = _path.replace('{' + name + '}', encodeURIComponent(params[name]))
    })
    return _path
  }

  // ======================================
  // 私有方法
  // ======================================
  /**
   * 异步post方法
   * @param url
   * @param _param
   * @returns {promise}
   * @private
   */
  _requestAsync (_config, _param = {}, _payload = {}) {
    this.beforEach && this.beforEach()
    let url = _config.path
    // 如果参数在url中
    if (url.match(/\{.+\}/i)) {
      url = this._pathParamResolve(url, _param)
    }
    const option = {
      method: _config.method,
      headers: {
        Accept: 'application/json',
        'Content-Type': 'application/json; charset=utf-8',
        token: getToken()
      },
      credentials: 'include'
    }
    /* if (_config.method.toLowerCase() === 'post' && Object.keys(_payload).length) {
      option['body'] = JSON.stringify(_payload)
    } else if (_config.method === 'get' && Object.keys(_payload).length) {
      url += '?' + utils.serialize(_param)
    } */
    if ((_config.method.toLowerCase() === 'post' || _config.method.toLowerCase() === 'put') && Object.keys(_payload).length) {
      option['body'] = JSON.stringify(_payload)
    } else if (_config.method.toLowerCase() === 'get' && Object.keys(_payload).length) {
      if (!(_config.rest && _config.rest === true)) url += '?' + utils.serialize(_param)
    }

    let req = fetch(url, option)
      .then(response => {   // 统一处理401
        if (response && response.status && response.status === 200) {
          return Promise.resolve(response)
        }
        if (response && response.status && response.status === 401) {
          return Promise.reject()
        } else {
          return Promise.reject()
        }
      })
      .then(response => {
        this.afterEach && this.afterEach()
        return response.json()
      })
      .catch(err => {
        if (this.NetErrorCallBack) {
          this.NetErrorCallBack(err)
        }
      })
    return req
  }

  _initWebApi () {
    let self = this
    Object.keys(config).map((key) => {
      self[key] = {}
      Object.keys(config[key]).map((ckey) => {
        self[key][ckey] = (param) => self._requestAsync(config[key][ckey], param, param)
      })
    })
  }
}
export default new WebApi()

3.3 computed,mounted和methods


稍后研究具体细节

3.4 async 方法调用rest api

    async getAllLogs () {
      try {
        this.loading = true
        const params = {
          logKeyWord: this.logKeyWord
        }
        const res = await webapi.manage.allLogs(params)
        if (res.code === '200') {
          this.logLists = res.data
        } else {
          this.logLists = []
        }
      } catch (e) {
        console.log(e)
      } finally {
        this.loading = false
      }
    },


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值