山东大学项目实训Web实验室(WebLab)(五)密码相关界面

山东大学项目实训Web实验室(WebLab)(五)密码相关界面

前言

项目仓库
本项目是为开发一套容器化的开发、运行、测试环境,用以支持Web开发、程序设计等课程的实验教学。

任务目标

设计并且编写主界面
主界面内容:

  • 忘记找回密码界面
  • 更改密码界面
  • 更新导航条

代码

App.vue

<!--按照路由进行画面跳转-->
<template>
  <div>
    <router-view/>
  </div>
</template>

router/index.js

import { createRouter, createWebHistory } from 'vue-router';
import HomeView from "../views/HomeView.vue";


const router = createRouter({
  history: createWebHistory(import.meta.env.BASE_URL),
  routes: [
    {
      path: "/",
      name: "home",
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import("../views/coding-view.vue"),
      // children: [
      //   {
      //     path: '../layout/btn',
      //     name: 'btns',
      //     component: btns => import("../views/coding-view.vue"),
      //   },
      //   {
      //     path: 'questionDescription',
      //     name: 'questionDescription',
      //     component: questionDescription
      //   },]
    },
    {
      path: "/register",
      name: "register-view",
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import("../views/register-view.vue"),
    },
    {
      path: "/login",
      name: "login-view",
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import("../views/login-view.vue")
    },
    {
    path: "/logout",
    name: "coding-view",
    // route level code-splitting
    // this generates a separate chunk (About.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    component: () => import("../views/coding-view.vue"),
    },
    {
      path: "/forget_password",
      name: "forgetpassw-view",
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import("../views/forgetpassw-view.vue"),
    },
    {
      path: "/update_password",
      name: "update_password",
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import("../views/updatepassw-view.vue"),
    },
    {
      path: "/login_home",
      name: "login_home",
      // route level code-splitting
      // this generates a separate chunk (About.[hash].js) for this route
      // which is lazy-loaded when the route is visited.
      component: () => import("../views/loginhome.vue"),
    },
  ],
});

export default router;

views/updatepassw-view.vue

<template>
  <div class="login-wrap">
    <el-form
      ref="uptFormRef"
      class="login-container"
      :model="uptForm"
      :rules="uptRules"
      label-position="right"
      label-width="80px"
    >
      <el-form-item label></el-form-item>
      <el-form-item label="旧的密码" prop="oldPass">
        <el-input v-model="uptForm.oldPass" placeholder="请输入旧密码" type="password" show-password />
      </el-form-item>
      <el-form-item label="新的密码" prop="newPass">
        <el-input v-model="uptForm.newPass" placeholder="请输入新密码" type="password" show-password />
      </el-form-item>
      <el-form-item label="确认密码" prop="checkPass">
        <el-input v-model="uptForm.checkPass" placeholder="请输入新密码" type="password" show-password />
      </el-form-item>
      <el-button style="margin-top: 12px" :disabled="btnDisabled" @click="next">确认</el-button>
    </el-form>
  </div>
</template>

<script lang="ts">
import { ref, defineComponent, reactive, unref } from 'vue'
import { useRouter } from "vue-router";
import { ElMessage } from "element-plus";
import { useLoginStore } from "@/stores/store";
export default defineComponent({
  setup() {
    const btnDisabled = ref(false);
    const router = useRouter();
    const store = useLoginStore();
    //表单内容
    const uptForm = reactive({
      oldPass: '',
      newPass: '',
      checkPass: '',
    })
    const uptFormRef = ref();

    const validateOldPass = (rule: any, value: any, callback: any) => {

      //发送获取密码请求(肖同学完成)
      const storedPass = store.getUserPassword;
      if (value != storedPass) {
        callback(new Error('输入密码错误'));
      }

      callback();

    }
    const validateNewPass = (rule: any, value: any, callback: any) => {
      const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
      if (!reg.test(value)) {
        callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
      }
      if (uptForm.checkPass != null && uptForm.checkPass !== '') {
        if (!uptFormRef.value) return
        uptFormRef.value.validateField('checkPass', () => null)
      }
      callback();

    }
    const validateCheckPass = (rule: any, value: any, callback: any) => {
      const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
      if (value !== uptForm.newPass) {
        callback(new Error('输入密码不一致'));
      }
      if (!reg.test(value)) {
        callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
      }
      callback();
    }
    // 定义校验规则(肖同学完成)
    const uptRules = reactive({
      oldPass: [
        { required: true, message: '密码不能为空', trigger: 'blur' },
        { min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
        { validator: validateOldPass, trigger: 'blur' }
      ],
      newPass: [
        { required: true, message: '密码不能为空', trigger: 'blur' },
        { min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
        { validator: validateNewPass, trigger: 'blur' }
      ],
      checkPass: [
        { required: true, message: '密码不能为空', trigger: 'blur' },
        { min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
        { validator: validateCheckPass, trigger: 'blur' }
      ],
    })
    const next = async () => {
      const form = unref(uptFormRef);
      if (!form) return
      try {
        await form.validate();

        //todo: 发送修改请求
        store.updateUserPassword(uptForm.newPass);
        btnDisabled.value = true;
        ElMessage({
          showClose: true,
          message: '修改密码成功',
          type: 'success',
          center: true,
          grouping: true,
          onClose: () => { router.push({ path: "/login_home" }); }
        });
      } catch (error: any) {
        ElMessage({
          showClose: true,
          message: '输入格式不正确',
          type: 'error',
          center: true,
          grouping: true,
        })
      }
    }
    return {
      btnDisabled,
      uptForm,
      uptFormRef,
      uptRules,
      next,
    }
  }
})
</script>

<style>
.login-wrap {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding-top: 10%;
}

.login-container {
  border-radius: 10px;
  margin: 0px auto;
  width: 350px;
  padding: 30px 35px 15px 35px;
  background: #fff;
  border: 1px solid #eaeaea;
  text-align: left;
  box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}

.title {
  margin: 0px auto 40px auto;
  text-align: center;
  color: #505458;
}
.grid-content {
  border-radius: 4px;
  min-height: 36px;
}
</style>

views/forgetpassw-view.vue

<template>
  <div class="email-wrap" v-if="showEmail == 1">
    <el-form ref="emailRef" :model="emailForm" :rules="emailRules" class="login-container">
      <el-steps :active="0" finish-status="success" simple style="margin-top: 20px">
        <el-step title="Step 1" />
        <el-step title="Step 2" />
        <el-step title="Step 3" />
      </el-steps>
      <el-form-item label></el-form-item>
      <el-form-item label="用户邮箱" prop="email">
        <el-input type="email" placeholder="请输入邮箱" v-model="emailForm.email" />
      </el-form-item>
      <el-button style="margin-top: 12px" @click="getCheckCode">获取邮箱验证码</el-button>
    </el-form>
  </div>
  <div class="email-check-wrap" v-else-if="showEmail == 2">
    <el-form
      ref="emailCheckFormRef"
      :model="emailCheckForm"
      :rules="emailCheckRules"
      class="email-container"
    >
      <el-steps :active="1" finish-status="success" simple style="margin-top: 20px">
        <el-step title="Step 1" />
        <el-step title="Step 2" />
        <el-step title="Step 3" />
      </el-steps>
      <el-form-item label></el-form-item>
      <el-form-item label="邮箱验证码" prop="checkCode">
        <el-input v-model="emailCheckForm.checkCode" placeholder="请输入验证码" />
      </el-form-item>
      <el-button style="margin-top: 12px" @click="next">下一步</el-button>
    </el-form>
  </div>
  <div class="password-wrap" v-else>
    <el-form ref="resetFormRef" :model="resetForm" :rules="resetRules" class="password-container">
      <el-steps :active="2" finish-status="success" simple style="margin-top: 20px">
        <el-step title="Step 1" />
        <el-step title="Step 2" />
        <el-step title="Step 3" />
      </el-steps>
      <el-form-item label></el-form-item>
      <el-form-item label="新的密码" prop="newPass">
        <el-input v-model="resetForm.newPass" placeholder="请输入新密码" type="password" show-password />
      </el-form-item>
      <el-form-item label="确认密码" prop="checkPass">
        <el-input v-model="resetForm.checkPass" placeholder="请输入新密码" type="password" show-password />
      </el-form-item>
      <el-button style="margin-top: 12px" :disabled="btnDisabled" @click="goHome()">确认</el-button>
    </el-form>
  </div>
</template>

<script lang="ts">
import { ref, defineComponent, reactive, unref } from 'vue'
import { Edit, UploadFilled, Picture } from '@element-plus/icons-vue'
import { useRouter } from "vue-router";
import { ElMessage } from 'element-plus';
import { useLoginStore } from '@/stores/store';
export default defineComponent({
  setup() {
    const btnDisabled = ref(false);
    const store = useLoginStore();
    const router = useRouter();
    const showEmail = ref(1);
    const emailRef = ref();
    const emailForm = reactive({
      email: '',
    })

    const emailRules = reactive({
      email: [
        { required: true, message: '邮箱不能为空', trigger: 'blur' },
        { type: 'email', message: '邮箱格式不正确', trigger: 'blur' }
      ],
    })

    const emailCheckFormRef = ref();
    const emailCheckForm = reactive({
      checkCode: '',
    })
    const resetFormRef = ref();
    const resetForm = reactive({
      newPass: '',
      checkPass: '',
    })

    const validateCheckCode = (rule: any, value: any, callback: any) => {

      //发送获取验证码请求(肖同学完成)
      const checkCode = '123';
      if (value != checkCode) {
        callback(new Error('验证码错误'));
      }
      callback();
    }
    const validateNewPass = (rule: any, value: any, callback: any) => {
      const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
      if (!reg.test(value)) {
        callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
      }
      if (resetForm.checkPass != null && resetForm.checkPass !== '') {
        if (!resetFormRef.value) return
        resetFormRef.value.validateField('checkPass', () => null)
      }
      callback();

    }
    const validateCheckPass = (rule: any, value: any, callback: any) => {
      const reg = /^(?=.*\d)(?=.*[a-zA-Z])[\da-zA-Z]{8,15}$/;
      if (value !== resetForm.newPass) {
        callback(new Error('输入密码不一致'));
      }
      if (!reg.test(value)) {
        callback(new Error('长度为8~15位,必须同时包含大小写字母及数字'));
      }
      callback();
    }

    const emailCheckRules = reactive({
      checkCode: [
        { required: true, message: '请输入验证码', trigger: 'blur' },
        { validator: validateCheckCode, trigger: 'blur' },
      ],
    })
    const resetRules = reactive({
      newPass: [
        { required: true, message: '密码不能为空', trigger: 'blur' },
        { min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
        { validator: validateNewPass, trigger: 'blur' }
      ],
      checkPass: [
        { required: true, message: '密码不能为空', trigger: 'blur' },
        { min: 8, max: 15, message: '密码位数只能在8~15之间', trigger: 'blur' },
        { validator: validateCheckPass, trigger: 'blur' }
      ],
    })

    const getCheckCode = async () => {
      //发送邮箱验证码
      const form = unref(emailRef);
      if (!form) return
      try {
        await form.validate();
        showEmail.value = 2;
      } catch (error: any) {
        ElMessage({
          showClose: true,
          message: '输入格式不正确',
          type: 'error',
          center: true,
          grouping: true,
        })
      }
    }

    const next = async () => {
      const form = unref(emailCheckFormRef);
      if (!form) return
      try {
        await form.validate();
        showEmail.value = 3;
      } catch (error) {
        ElMessage({
          showClose: true,
          message: '验证码不正确',
          type: 'error',
          center: true,
          grouping: true
        })
      }
    };
    const goHome = async () => {
      const form = unref(resetFormRef);
      if (!form) return
      try {
        await form.validate();

        //todo 发送修改密码请求
        store.updateUserPassword(resetForm.newPass);
        btnDisabled.value = true;

        ElMessage({
          showClose: true,
          message: '修改密码成功',
          type: 'success',
          center: true,
          grouping: true,
          onClose: () => { router.push({ path: '/login' }) }
        })
      } catch (error) {
        ElMessage({
          showClose: true,
          message: '密码格式错误',
          type: 'error',
          center: true,
          grouping: true
        })
      }

    }
    return {
      btnDisabled,
      showEmail,
      emailRef,
      emailForm,
      emailRules,
      emailCheckFormRef,
      emailCheckForm,
      emailCheckRules,
      resetForm,
      resetRules,
      resetFormRef,
      getCheckCode,
      next,
      goHome,

    }
  },
})

</script>

<style>
.email-wrap {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding-top: 10%;
}
.email-check-wrap {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding-top: 10%;
}
.email-container {
  border-radius: 10px;
  margin: 0px auto;
  width: 400px;
  padding: 30px 35px 15px 35px;
  background: #fff;
  border: 1px solid #eaeaea;
  text-align: left;
  box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}
.password-wrap {
  box-sizing: border-box;
  width: 100%;
  height: 100%;
  padding-top: 10%;
}

.password-container {
  border-radius: 10px;
  margin: 0px auto;
  width: 400px;
  padding: 30px 35px 15px 35px;
  background: #fff;
  border: 1px solid #eaeaea;
  text-align: left;
  box-shadow: 0 0 20px 2px rgba(0, 0, 0, 0.1);
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值