项目进度:
最近一直在搭建环境,都没写什么:登陆页面采用登陆注册在同一个界面,用v-if进行渲染,并且借助validation插件中的yup神器进行校验,
<script setup>
// import { ref } from 'vue'
import * as yup from 'yup'
import { Form, Field, ErrorMessage } from 'vee-validate'
import { ref, watch } from 'vue'
// import { useUserStore } from '@/stores/index'
// import { useRouter } from 'vue-router'
import { userRegisterService, userLoginService } from '@/api/user'
const isRegister = ref(true)
const isSendingCode = ref(false)
// 注册功能,整个的用于提交的form对象
// 设置预校验
// const userStore = useUserStore()
const formValidate = ref()
// const router = useRouter()
const login = async () => {
await formValidate.value.validate()
const res = userLoginService(loginFormModel.value)
// userStore.setToken(res.data.token)
ElMessage.success('登录成功')
console.log('开始登录', res)
// router.push('/')
}
const register = async () => {
await formValidate.value.validate()
await userRegisterService(formModel.value)
ElMessage.success('注册成功')
isRegister.value = false
}
const formModel = ref({
email: '',
password: '',
repassword: '',
confirm: ''
})
const loginFormModel = ref({
userAccount: null,
password: ''
})
watch(isRegister, () => {
formModel.value = {
email: '',
password: '',
repassword: ''
}
loginFormModel.value = {
userAccount: '',
password: ''
}
})
const simpleSchema = yup.object({
email: yup
.string()
.trim()
.required('该选项不能为空')
.matches('^[1-9]\\d{4,10}@qq\\.com$', '输入的内容不满足邮箱格式'),
password: yup
.string()
.trim()
.required('该选项不能为空')
.min(8, '密码必须为至少8位字符')
.test('test2', '与第一次输入的密码不匹配', function (password) {
const repassword = this.parent.repassword
if (password !== repassword) {
return this.createError({ path: 'confirmPassword' })
}
return true
}),
repassword: yup
.string()
.trim()
.required('该选项不能为空')
.test('test1', '与第一次输入的密码不匹配', function (repassword) {
const password = this.parent.password
if (password !== repassword) {
return false
}
return true
}),
// 要么是数字要么是字符串2选1,trim是字符串特有的,只有number不能专门提示
userAccount: yup
.number()
.required('输入的必须为非空数字')
.min(10, '账号必须是10位数字哦')
})
</script>
<template>
<div class="layoutLogin">
<img
class="loginBackground"
src="https://pic1.zhimg.com/80/v2-9140eb49073346f74f04b6628c77c3fc_1440w.webp"
alt="背景图"
/>
<Form
@submit="submit"
:validation-schema="simpleSchema"
:model="formModel"
class="form"
v-if="isRegister"
ref="formValidate"
>
<div class="title">注册</div>
<div class="frame">
<Field
type="email"
v-model="formModel.email"
name="email"
placeholder="请输入你的邮箱"
/>
<br />
<ErrorMessage name="email" />
</div>
<div class="frame">
<Field
name="password"
v-model="formModel.password"
type="password"
placeholder="请输入你想要的密码"
/>
<br />
<ErrorMessage name="password" />
</div>
<div class="frame">
<Field
name="repassword"
type="password"
placeholder="请再次确认你输入的密码"
v-model="formModel.repassword"
/>
<br />
<ErrorMessage name="repassword" />
</div>
<div class="frame">
<Field
name="repassword"
type="password"
placeholder="请输入验证码"
v-model="formModel.confirm"
class="confirmInput"
/>
<span class="getConfirm" :disabled="isSendingCode">验证码</span>
</div>
<button @click="register">注册</button>
<div class="toWhere">
<a href="#" class="toLogin">已有帐号?去登录</a>
<br />
<a href="#" class="toModify">忘记密码?</a>
</div>
</Form>
<!-- 切换的时候重置表单内容 -->
<Form
@submit="submit"
:validation-schema="simpleSchema"
:model="loginFormModel"
class="form"
ref="formValidate"
v-else
>
<div class="title">登录</div>
<div class="frame">
<Field
type="text"
v-model="loginFormModel.userAccount"
name="userAccount"
placeholder="请输入你的账号"
/>
<br />
<ErrorMessage name="userAccount" />
</div>
<div class="frame">
<Field
name="password"
v-model="loginFormModel.password"
type="password"
placeholder="请输入密码"
/>
<br />
<ErrorMessage name="password" />
</div>
<button @click="login">登录</button>
<div class="toWhere">
<a href="#" class="toLogin">新用户?去注册</a>
<br />
<a href="#" class="toModify">忘记密码?</a>
</div>
</Form>
</div>
</template>
<style scoped>
* {
outline: none;
padding: none;
margin: 0;
}
.form {
width: 30vw;
min-height: 40vh;
font-family: 'YouYuan';
box-shadow: 2px 4px 8px 4px rgba(49, 110, 64, 0.387);
border-radius: 10px;
}
.title {
font-size: 40px;
font-family: 'STCaiyun';
text-shadow: 5px 5px 3px rgba(0, 0, 0, 0.329);
color: whitesmoke;
margin-top: 0.5em;
margin-bottom: 0.2em;
margin-left: 4em;
}
.layoutLogin {
display: flex;
height: 100vh;
width: 100vw;
justify-content: center;
align-items: center;
}
/* 对于Field,本质上是input,所以还是要改变这个 */
input {
height: 2em;
width: 20em;
border: rgba(41, 202, 143, 0.089) solid 1.5px;
box-shadow: 0px 1px 8px 2px rgba(0, 0, 0, 0.223);
border-radius: 1em;
background-color: rgba(240, 255, 255, 0);
}
.confirmInput {
width: 12em;
}
.getConfirm {
padding: 0.6em;
border-radius: 2em;
border: rgba(28, 172, 131, 0.295) solid 1px;
box-shadow: 0px 1px 8px 2px rgba(0, 0, 0, 0.223);
margin-left: 3em;
color: white;
cursor: pointer;
}
.getConfirm:hover {
background-color: rgba(240, 248, 255, 0.315);
}
.frame {
margin: 30px 5em;
}
.loginBackground {
position: absolute;
height: 100vh;
width: 100vw;
z-index: -1;
}
span {
color: red;
font-size: 0.8em;
}
button:hover {
background-color: rgba(234, 236, 230, 0.421);
}
button {
margin: 0.5em 12.5em;
margin-top: 1em;
border: rgba(26, 120, 121, 0.377);
background-color: rgba(143, 212, 198, 0.216);
width: 5em;
height: 2.5em;
border-radius: 1em;
color: aliceblue;
box-shadow: 0px 1px 8px 2px rgba(0, 0, 0, 0.223);
}
.toWhere {
font-size: 0.5em;
margin-left: 1.5em;
margin-bottom: 20px;
}
.toLogin,
.toModify {
color: aliceblue;
}
.toLogin:hover,
.toModify:hover {
color: rgb(205, 242, 255);
}
</style>
对于请求进行封装,设置请求拦截器和响应拦截器:
import { useUserStore } from '@/stores'
import { ElMessage } from 'element-plus'
import router from '@/router'
import axios from 'axios'
const baseURL = 'https://big-event-vue-api-t.itheima.net'
const instance = axios.create({
baseURL,
timeout: 10000
// headers: { 'X-Custom-Header': 'foobar' }
})
// Add a request interceptor
axios.interceptors.request.use(
(config) => {
// 携带token
// Do something before request is sent
const useStore = useUserStore()
if (useStore.token) {
config.headers.Authorization = useStore.token
}
return config
},
function (error) {
// Do something with request error
return Promise.reject(error)
}
)
// Add a response interceptor
axios.interceptors.response.use(
function (response) {
// Any status code that lie within the range of 2xx cause this function to trigger
// Do something with response data
if (response.data.code === 0) {
return response
}
ElMessage.error(response.data.message || '服务异常')
return Promise.reject(response.data)
},
function (error) {
// Any status codes that falls outside the range of 2xx cause this function to trigger
// Do something with response error
//错误的特殊情况401 权限不足或者token过期=》拦截到登录
if (error.response?.status === 401) {
router.push('/login')
}
//错误的默认情况
ElMessage.error(error.response.data.message || '服务异常')
return Promise.reject(error)
}
)
export default instance
export { baseURL }
封装接口:
import request from '@/utils/request'
//注册接口
export const userRegisterService = ({ email, password, repassword }) => {
return request.post('/api/reg', { email, password, repassword })
}
//登录接口
export const userLoginService = ({ userAccount, password }) => {
return request.post('/api/login', { userAccount, password })
}
这周答辩过后实在是看到了很大的不足,从这周起要开始认真了;这周的话应该要写完登陆注册jwt和修改个人资料,然后如果能多写一点的话可以适当加上一个搜索分页;
然后,激励自己: