人力资源智能化管理项目(day03:主页模块)

学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject

觉得有帮助的同学,可以点心心支持一下哈

主页权限验证(permission.js)

import router from '@/router'
import nprogress from 'nprogress' // 进度条
import 'nprogress/nprogress.css' // 进度条样式
import store from '@/store'
/**
 * 前置守卫
 *
 */
// 白名单
const whiteList = ['/login', '/404']
router.beforeEach((to, from, next) => {
  nprogress.start() // 开启进度条
  if (store.getters.token) {
    // 存在token
    if (to.path === '/login') {
      // 跳转到主页
      next('/') // 中转到主页
      // next有地址的话并没有执行后置守卫
      nprogress.done()
    } else {
      next() // 放过
    }
  } else {
    // 没有token
    if (whiteList.includes(to.path)) {
      next() // 放过
    } else {
      next('/login') // 中转到登录页
      nprogress.done()
    }
  }
})

/**
 * 后置守卫
 *
 */
router.afterEach(() => {
  console.log(123)
  nprogress.done() // 关闭进度条
})

获取用户资料在Vuex中共享

获取资料action的调用位置

1.封装API请求

export function getUserInfo () {
  // request执行之后会得到promise对象(再通过使用async和await可以获取结果)
  return request({
    url: '/sys/profile',
    method: 'GET'
  })
}

2.Vuex应用

// 存放数据
const state = {
  token: getToken(), // 从缓存中读取初始值
  userInfo: {} // 存储用户基本资料状态
}

  setUserInfo (state, userInfo) {
    state.userInfo = userInfo
  }

  // 获取用户的基本资料
  async getUserInfo (context) {
    const result = await getUserInfo()
    context.commit('setUserInfo', result)
  }

3.getters声明userId

userId: state => state.user.userInfo.userId, // 取用户id,用于判断页面是否获取过资料

4.权限拦截处调用action

// 如果不是则放过
      // 判断是否获取过资料
      if (!store.getters.userId) {
        // 如果没有则获取资料
        await store.dispatch('user/getUserInfo')
      }
      next()

显示用户头像和用户名

1.Vuex使用getters暴露属性

avatar: state => state.user.userInfo.staffPhoto, // 用户头像
name: state => state.user.userInfo.username // 用户姓名

2.Navbar组件引入

// 辅助函数,自动引入getters中的属性
    // 引入用户头像和名称
    ...mapGetters(['sidebar', 'avatar', 'name'])
  },

3.Navbar设置

<!-- 用户头像 -->
          <img :src="avatar" class="user-avatar" />
          <!-- 用户名称 -->
          <span class="name">{{ name }}</span>
          <!-- 图标 -->
          <i class="el-icon-setting" />

4.设置样式

.avatar-wrapper {
        margin-top: 5px;
        position: relative;
        display: flex;
        align-items: center;
        .name {
          // 用户名称距离右侧的距离
          margin-right: 10px;
          font-size: 16px;
        }
        .user-avatar {
          cursor: pointer;
          width: 30px;
          height: 30px;
          border-radius: 50%;
        }
        .el-icon-setting {
          font-size: 20px;
        }

处理用户头像为空的场景

实例代码

 <!-- 用户头像 -->
<img v-if="avatar" :src="avatar" class="user-avatar" />
<span v-else class="username">{{ name?.charAt(0) }}</span>

   
        .username {
          width: 30px;
          height: 30px;
          line-height: 30px;
          text-align: center;
          background-color: #04c9be;
          color: #fff;
          border-radius: 50%;
          margin-right: 4px;
        }

npm i vue@2.7.0 vue-template-compiler@2.7.0

处理token失效

实例代码

// 判断token值是否等于401
    if (error.response.status === 401) {
      Message({ type: 'warning', message: '登录超时了' })
      // token超时了
      await store.dispatch('user/logout') // 退出登录action
      router.push('/login') // 跳到登录页
      return Promise.reject(error)
    }

 // 退出登录
  logout (context) {
    // 1.删除token
    context.commit('removeToken')
    // 2.删除用户信息
    context.commit('setUserInfo', {})
  }

调整下拉菜单,实现退出登录

<!-- native事件修饰符 -->
          <!-- 注册组件的根元素的原生事件 -->
          <el-dropdown-item @click.native="logout">
            <span style="display: block">退出登录</span>
          </el-dropdown-item>


    async logout () {
      // 调用退出登录的action
      await this.$store.dispatch('user/logout')
      this.$router.push('/login')
    }

修改密码功能实现

修改密码-弹出层

<!-- prevent阻止默认事件 -->
          <a target="_blank" @click.prevent="updatePassword">
            <el-dropdown-item>修改密码</el-dropdown-item>
          </a>


  <!-- 放置dialog -->
    <!-- sync可以接收子组件传过来的事件和值 -->
    <el-dialog width="500px" title="修改密码" :visible.sync="showDialog">
      <!-- 放置表单 -->
    </el-dialog>
            

    showDialog: true // 控制弹层的显示和隐藏
            
            
    updatePassword () {
      this.showDialog = true // 显示弹层
    }

修改密码-表单结构

<!-- 放置表单 -->
      <el-form label-width="120px">
        <el-form-item label="旧密码">
          <el-input type="password" size="small" />
        </el-form-item>
        <el-form-item label="新密码">
          <el-input type="password" size="small" />
        </el-form-item>
        <el-form-item label="重复密码">
          <el-input type="password" size="small" />
        </el-form-item>
        <el-form-item>
          <el-button size="mini" type="primary">确认密码</el-button>
          <el-button size="mini">取消</el-button>
        </el-form-item>
      </el-form>

修改密码-表单校验

rules: {
        // 旧密码
        oldPassword: [
          { required: true, message: '旧密码不能为空', trigger: 'blur' }
        ], // 新密码
        newPassword: [
          { required: true, message: '新密码不能为空', trigger: 'blur' },
          {
            trigger: 'blur',
            min: 6,
            max: 16,
            message: '新密码的长度6-16位之间'
          }
        ], // 确认密码字段
        confirmPassword: [
          { required: true, message: '重复密码不能为空', trigger: 'blur' },
          {
            trigger: 'blur',
            validator: (rule, value, callback) => {
              if (this.passForm.newPassword === value) {
                callback()
              } else {
                callback(new Error('重复密码和新密码输入不一致'))
              }
            }
          }
        ]
      }

修改密码-确定和取消

btnOk () {
      this.$refs.passForm.validate(async isOk => {
        if (isOk) {
          // 调用接口
          await updatePassword(this.passForm)
          this.$message.success('修改密码成功')
          this.btnCancel()
        }
      })
    },
    btnCancel () {
      // 成功之后重置表单
      this.$refs.passForm.resetFields()
      // 关闭弹层
      this.showDialog = false
    }


  @close="btnCancel"
  

  /**
 * 更新密码
 */
export function updatePassword (data) {
  return request({
    url: '/sys/user/updatePass',
    method: 'PUT',
    data
  })
}

清理组件和路由并创建项目所需组件和路由

删除多余的组件和路由

业务模块

实例代码(department)

<template>
  <div class="container">
    <div class="app-container">
      组织架构
    </div>
  </div>
</template>
<script>
export default {
  name: 'Department'
}
</script>



import layout from '@/layout'
export default {
  // 路由信息
  path: '/department',
  component: layout, // 一级路由
  children: [{
    path: '', // 二级路由地址为空时 表示 /department 显示一级路由 + 二级路由
    component: () => import('@/views/department'),
    name: 'department', // 可以用来跳转 也可以标记路由
    meta: {
      // 路由元信息 存储数据的
      icon: 'tree', // 图标
      title: '组织' // 标题
    }
  }]
}




import Layout from '@/layout'
import department from './modules/department'
import approval from './modules/approval'
import attendance from './modules/attendance'
import employee from './modules/employee'
import permission from './modules/permission'
import role from './modules/role'
import salary from './modules/salary'
import social from './modules/social'


  {
    path: '/',
    component: Layout,
    redirect: '/dashboard',
    children: [
      {
        path: 'dashboard',
        name: 'Dashboard',
        component: () => import('@/views/dashboard/index'),
        meta: { title: '首页', icon: 'dashboard' }
      }
    ]
  },
  department,
  role,
  employee,
  permission,
  attendance,
  approval,
  salary,
  social,

解析左侧菜单

显示项目logo

<router-link key="collapse" class="sidebar-logo-link" to="/">
        <img src="@/assets/common/logo.png" class="sidebar-logo" />
      </router-link>


                      
    & .sidebar-logo {
      width: 140px;
      vertical-align: middle;
      margin-right: 12px;
    }
        &.collapse {
    .sidebar-logo {
      margin-right: 0px;
      width: 32px;
      height: 32px;
    }
  }


\src\settings.js
sidebarLogo: true
  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值