spring boot+iview 前后端分离架构之首页退出和修改密码的实现(二十三)

65 篇文章 5 订阅
42 篇文章 2 订阅

spring boot 与 iview 前后端分离架构之首页退出和修改密码的实现(二十三)

公众号

在这里插入图片描述
大家可以直接微信扫描上面的二维码关注我的公众号,然后回复【bg23】 里面就会给到源代码的下载地址同时会附上相应的视频教程,并定期在我的公众号上给大家推送相应的技术文章,欢迎大家关注我的公众号。

首页退出和修改密码的实现

通过上一章节我们已经实现了动态加载菜单栏和,动态显示我们的面包屑导航了,但是我们的首页还缺少退出以及修改密码的选项,因此本章将为大家讲解如何实现退出和修改密码的实现。

添加修改密码的mock数据

由于我们现在的前端一直都是使用的mock数据,因此我们需要添加修改密码的mock数据,在我们的以下目录底下新增一个user.changePassword.js文件
在这里插入图片描述

{
  "code": 200,
  "msg": "密码更新成功",
  "obj": null
}

接着在mock.js文件中引入修改密码的mock,新增代码如下:

import changePassword from './json/user/user.changePassword'
Mock.mock('/user/changePassword', 'post', changePassword);

修改密码的实现

接着我们在main目录底下创建一个changePassword.vue实现密码的修改,代码如下:

<template>
  <Modal v-model="show" title="修改密码" @on-ok="ok" :loading="loading" :mask-closable="false">
    <Form ref="changePasswordForm" :model="changePasswordForm" :rules="changePasswordFormRule">
      <FormItem label="当前密码" prop="oldPassword">
        <Input type="password" :maxlength=50 v-model="changePasswordForm.oldPassword" placeholder="请输入当前密码"/>
      </FormItem>
      <FormItem label="新密码" prop="newPassword">
        <Input type="password" :maxlength=50 v-model="changePasswordForm.newPassword" placeholder="请输入新密码"/>
      </FormItem>
      <FormItem label="新密码二次确认" prop="checkNewPassword">
        <Input type="password" :maxlength=50 v-model="changePasswordForm.checkNewPassword" placeholder="请再次输入上面的密码"/>
      </FormItem>
    </Form>
  </Modal>
</template>
<script>

  import {changePassword} from '../../api/sys/user/user.api'

  export default {
    name: "addDict",
    props: {
      value: {
        type: Boolean,
        default: false
      }
    },
    data() {
      return {
        show: this.value,
        loading: true,
        changePasswordForm: {
          oldPassword: '',
          newPassword: '',
          checkNewPassword: ''
        },
        changePasswordFormRule: {
          oldPassword: [
            {required: true, message: '请输入旧的密码', trigger: 'blur'},
            {type: 'string', max: 50, min: 6, message: '密码最小长度为6', trigger: 'blur'}
          ],
          newPassword: [
            {required: true, message: '请输入新密码', trigger: 'blur'},
            {type: 'string', max: 50, min: 6, message: '密码最小长度为6', trigger: 'blur'}
          ],
          checkNewPassword:[
            {required: true, message: '请再次输入密码', trigger: 'blur'},
            {type: 'string', max: 50, min: 6, message: '密码最小长度为6', trigger: 'blur'},
            {
              validator:this.validatorPassword({
                response: 'exist'
              }), trigger: 'blur'
            }
          ]
        }
      }
    },
    methods: {
      ok() {
        this.$refs['changePasswordForm'].validate((valid) => {
          if (valid) {
            changePassword(this.changePasswordForm).then(res => {
              if (res.code == 200) {
                this.$Message.success(res.msg);
                // 提交表单数据成功则关闭当前的modal框
                this.closeModal(false);
              } else {
                this.$Message.error( res.msg);
              }
            })
          }
          setTimeout(() => {
            this.loading = false;
            this.$nextTick(() => {
              this.loading = true;
            });
          }, 1000);
        })
      },
      closeModal(val) {
        this.$emit('input', val);
      },
      validatorPassword(){
        let _this = this;
        return function (rule, value, callback) {
          let newPassword = _this.changePasswordForm.newPassword;
          let checkNewPassword = _this.changePasswordForm.checkNewPassword;
          if(newPassword!=''&&checkNewPassword!=''){
              if(newPassword!=checkNewPassword){
                callback(new Error("两次输入的密码不匹配"));
              }else{
                callback();
              }
          }else{
            callback();
          }
        }
      }
    },
    watch: {
      value(val) {
        this.show = val;
      },
      show(val) {
        //当重新显示增加数据的时候重置整个form表单
        if (val) {
          this.$refs['changePasswordForm'].resetFields();
        } else {// 反之则关闭页面
          this.closeModal(val);
        }
      }
    }
  }
</script>

接着我们改造我们的main.vue页面,改造完成以后的代码如下:

<template>
  <div class="layout">
    <Layout>
      <!--  Header 表示头部的位置-->
      <Header id="layout-header-scroll">
        <Menu mode="horizontal" theme="dark" active-name="1">
          <div class="layout-logo">
            [外链图片转存失败(img-RxJEOSUf-1562209731086)(https://mp.csdn.net/assets/logo.png)]
          </div>
          <div class="layout-nav">
            <Dropdown @on-click="userAction">
              <a href="javascript:void(0)" style="color: white">
                {{this.nickName}}
              </a>
              <DropdownMenu slot="list">
                <DropdownItem name="regPass">修改密码</DropdownItem>
                <DropdownItem name="loginOut" divided>退出登录</DropdownItem>
              </DropdownMenu>
            </Dropdown>
          </div>
          <div class="layout-nav">
            <language @on-lang-change="setLanguage" style="margin-right: 10px;" :lang="local"/>
          </div>
          <div class="layout-nav">
            <template v-for="item in menuList">
              <Submenu :name="item.meta.code" v-if="item.children.length>0">
                <template slot="title">
                  <Icon :type="item.meta.icon"/>
                  {{item.meta.title}}
                </template>
                <template v-for="childrenItem in item.children">
                  <MenuItem :name=childrenItem.meta.code :to="item.path+'/'+childrenItem.path">
                    <Icon :type=childrenItem.meta.icon>
                    </Icon>
                    {{childrenItem.meta.title}}
                  </MenuItem>
                </template>
              </Submenu>
              <MenuItem :name="item.meta.code" v-else>
                <Icon :type="item.meta.icon"/>
                {{item.meta.title}}
              </MenuItem>
            </template>
          </div>
        </Menu>
      </Header>
      <!-- 此处表示的是左侧的菜单栏的布局 -->
      <Layout>
        <Sider hide-trigger :style="{background: '#fff'}">
          <Menu active-name="1-2" theme="light" width="auto" :open-names="['system-manage']">
            <template v-for="item in menuList">
              <Submenu :name=item.meta.code>
                <template slot="title">
                  <Icon :type=item.meta.icon></Icon>
                  {{item.meta.title}}
                </template>
                <template v-for="childrenItem in item.children">
                  <MenuItem :name=childrenItem.meta.code :to="item.path+'/'+childrenItem.path">
                    <Icon :type=childrenItem.meta.icon>
                    </Icon>
                    {{childrenItem.meta.title}}
                  </MenuItem>
                </template>
              </Submenu>
            </template>
          </Menu>
        </Sider>
        <Layout :style="{padding: '0 24px 24px'}">
          <!--  此处是面包屑导航条 -->
          <Breadcrumb :style="{margin: '24px 0'}">
            <BreadcrumbItem>
              <Icon type="ios-home-outline"></Icon>
              首页
            </BreadcrumbItem>
            <BreadcrumbItem v-for="item in breadCrumbList" v-bind:key="item.name" v-if="item.meta && item.meta.title">
              <Icon :type="item.icon"></Icon>
              {{showBreadcrumbItem(item)}}
            </BreadcrumbItem>
          </Breadcrumb>
          <!-- 此处存放的是文本内容的区域 -->
          <Content :style="{padding: '24px', minHeight: '280px', background: '#fff'}">
            <router-view/>
          </Content>
        </Layout>
      </Layout>
    </Layout>
    <changePassword v-model="showChangePassword"></changePassword>
  </div>
</template>
<script>
  import Language from '../../components/language';
  import {mapMutations, mapActions} from 'vuex';
  import changePassword from './changePassword';

  export default {
    components: {
      Language,
      changePassword
    },
    data() {
      return {
        local: localStorage.getItem("lang"),
        showChangePassword: false
      }
    },
    methods: {
      ...mapMutations([
        'setBreadCrumb'
      ]),
      ...mapActions([
        'handleLogOut'
      ]),
      /**
       * 顶部跟随着滚动条的变化而滚动
       */
      handleScroll() {
        let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
        if (scrollTop >= 60) {
          document.querySelector('#layout-header-scroll').style.top = scrollTop + 'px';
        } else {
          document.querySelector('#layout-header-scroll').style.top = '0px';
        }
      },
      userAction(name) {
        // 实现退出登录
        if (name == 'loginOut') {
          this.handleLogOut();
          this.turnToView('login');
          // 实现修改密码
        } else if (name == 'regPass') {
          this.showChangePassword = true;
        }
      },
      setLanguage(lang) {
        this.local = lang
        localStorage.setItem('lang', lang)
      },
      showBreadcrumbItem(item) {
        return (item.meta && item.meta.title) || item.name
      },
      turnToView(name) {
        this.$router.push({
          name: name
        })
      }
    },
    watch: {
      '$route'(newRoute) {
        this.setBreadCrumb(newRoute.matched)
      }
    },
    computed: {
      breadCrumbList() {
        return this.$store.state.app.breadCrumbList
      },
      menuList() {
        return this.$store.getters.menuList;
      },
      nickName() {
        return this.$store.getters.nickName;
      }
    },
    mounted() {
      /**
       * 监听滚动条的滚动事件
       */
      window.addEventListener('scroll', this.handleScroll)
    }
  }
</script>
<style scoped>
  .layout-header {
    position: relative;
    z-index: 999;
    height: 60px;
  }

  .layout {
    border: 1px solid #d7dde4;
    background: #f5f7f9;
    position: relative;
    border-radius: 4px;
    overflow: hidden;
  }

  .layout-logo {
    width: 100px;
    height: 30px;
    border-radius: 10px;
    float: left;
    position: relative;
    left: 20px;
    top: 5px;
  }

  .layout-nav {
    width: auto;
    float: right;
    margin: 0 auto;
    margin-right: 20px;
  }
</style>

最后我们运行我们的项目,大家会看到如下的页面则说明我们的集成以及成功了。
在这里插入图片描述
到此为止我们就完成了首页面包屑的实现了。
上一篇文章地址:spring boot+iview 前后端分离架构之首页菜单栏的实现(二十二)
下一篇文章地址:spring boot+iview 前后端分离架构之后端鉴权体系的实现(二十四)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
1. 首先,在项目中引入iviewvue-resource: ``` import Vue from 'vue' import iView from 'iview' import 'iview/dist/styles/iview.css' import VueResource from 'vue-resource' Vue.use(iView) Vue.use(VueResource) ``` 2. 在vue文件中使用iview的Select组件实现省市选择: ``` <template> <div> <Select v-model="province" @on-change="getCityList"> <Option v-for="(item, index) in provinceList" :value="item.id" :key="index">{{ item.name }}</Option> </Select> <Select v-model="city"> <Option v-for="(item, index) in cityList" :value="item.id" :key="index">{{ item.name }}</Option> </Select> </div> </template> <script> export default { data () { return { province: '', city: '', provinceList: [], cityList: [] } }, mounted () { this.getProvinceList() }, methods: { // 获取省份列表 getProvinceList () { this.$http.get('/api/province').then(res => { this.provinceList = res.data }) }, // 获取城市列表 getCityList () { this.$http.get('/api/city', { params: { province: this.province } }).then(res => { this.cityList = res.data }) } } } </script> ``` 3. 在后台实现省市数据接口: 省份接口: ``` app.get('/api/province', function(req, res) { res.json([ {id: 1, name: '北京'}, {id: 2, name: '上海'}, {id: 3, name: '广东省'}, {id: 4, name: '湖南省'} ]) }) ``` 城市接口: ``` app.get('/api/city', function(req, res) { var provinceId = req.query.province var cityList = [] switch(provinceId) { case '1': cityList = [ {id: 101, name: '北京市'}, {id: 102, name: '海淀区'}, {id: 103, name: '朝阳区'}, {id: 104, name: '东城区'}, {id: 105, name: '西城区'} ] break case '2': cityList = [ {id: 201, name: '上海市'}, {id: 202, name: '浦东新区'}, {id: 203, name: '徐汇区'}, {id: 204, name: '黄浦区'}, {id: 205, name: '静安区'} ] break case '3': cityList = [ {id: 301, name: '广州市'}, {id: 302, name: '深圳市'}, {id: 303, name: '珠海市'}, {id: 304, name: '佛山市'}, {id: 305, name: '东莞市'} ] break case '4': cityList = [ {id: 401, name: '长沙市'}, {id: 402, name: '株洲市'}, {id: 403, name: '湘潭市'}, {id: 404, name: '衡阳市'}, {id: 405, name: '邵阳市'} ] break default: break } res.json(cityList) }) ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

笨_鸟_不_会_飞

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值