登录注册
|
|
@ -0,0 +1,5 @@
|
|||
VITE_PUBLIC_PATH = /
|
||||
|
||||
VITE_API_BASE_URL = 'http://test-admin.haituaigc.com'
|
||||
|
||||
VITE_API_CHAT_URL = 'http://openai-test.haituaigc.com'
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
VITE_PUBLIC_PATH = /
|
||||
|
||||
VITE_API_BASE_URL = 'http://test-admin.haituaigc.com'
|
||||
|
||||
VITE_API_CHAT_URL = 'http://openai-test.haituaigc.com'
|
||||
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,371 @@
|
|||
<template>
|
||||
<div class="loginBox">
|
||||
<div class="banner">
|
||||
<h2>您好!欢迎使用海兔AIGC!</h2>
|
||||
<p>请输入您的相关信息进行登录!</p>
|
||||
</div>
|
||||
<ul class="tabBox">
|
||||
<li :class="{ active: loginType == 'tel' }" @click="loginType = 'tel'"><i class="icon-code"></i>短信验证</li>
|
||||
<li :class="{ active: loginType == 'email' }" @click="loginType = 'email'"><i class="icon-email"></i>邮箱验证</li>
|
||||
<li :class="{ active: loginType == 'password' }" @click="loginType = 'password'"><i class="icon-pwd"></i>密码登录
|
||||
</li>
|
||||
</ul>
|
||||
<div class="formBox" v-if="loginType === 'tel'">
|
||||
<div class="item">
|
||||
<div class="label">手机号码</div>
|
||||
<div class="val">
|
||||
<van-field type="tel" :clearable="true" class="txt" v-model="tel" placeholder="请输入手机号码" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="label">验证码</div>
|
||||
<div class="val">
|
||||
<van-field type="digit" :clearable="true" class="stxt" v-model="msgCode" placeholder="请输入验证码" />
|
||||
<van-button class="sbtn" type="primary" :disabled="telCountDown !== getCodeTime" @click="getTelCode">{{
|
||||
telBtnTxt }}</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formBox" v-if="loginType === 'email'">
|
||||
<div class="item">
|
||||
<div class="label">邮箱</div>
|
||||
<div class="val">
|
||||
<van-field :clearable="true" class="txt" v-model="email" placeholder="请输入邮箱" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="label">验证码</div>
|
||||
<div class="val">
|
||||
<van-field :clearable="true" class="stxt" v-model="emailCode" placeholder="请输入验证码" />
|
||||
<van-button class="sbtn" type="primary" :disabled="emailCountDown !== getCodeTime"
|
||||
@click="getEmailCode">{{ emailBtnTxt }}</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="formBox" v-if="loginType === 'password'">
|
||||
<div class="item">
|
||||
<div class="label">手机号/邮箱</div>
|
||||
<div class="val">
|
||||
<van-field :clearable="true" class="txt" v-model="account" placeholder="请输入手机号/邮箱" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="label">密码</div>
|
||||
<div class="val">
|
||||
<van-field type="password" class="pwdInput" v-model="password" placeholder="请输入密码" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="submitBtn">
|
||||
<van-button type="primary" @click="onLogin">登录</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import { useAuthModal } from '@/stores/authModal';
|
||||
import { useUserInfo } from '@/stores/userInfo';
|
||||
import { showToast } from 'vant';
|
||||
import http from '@/io/http';
|
||||
import { localCache } from '@/io/cache';
|
||||
import md5 from 'md5';
|
||||
|
||||
const authModal = useAuthModal();
|
||||
const userInfo = useUserInfo();
|
||||
|
||||
const loginType = ref('tel');
|
||||
const tel = ref();
|
||||
const msgCode = ref();
|
||||
const email = ref();
|
||||
const emailCode = ref();
|
||||
const account = ref();
|
||||
const password = ref();
|
||||
|
||||
const getCodeTime = 60;
|
||||
const telBtnTxt = ref('获取验证码');
|
||||
const telCountDown = ref(getCodeTime);
|
||||
const telTimer = ref(0);
|
||||
const emailBtnTxt = ref('获取验证码');
|
||||
const emailCountDown = ref(getCodeTime);
|
||||
const emailTimer = ref(0);
|
||||
|
||||
const telReg = /^1[3-9]\d{9}$/;
|
||||
const emailReg = /^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$/;
|
||||
|
||||
const isGetTelCode = ref(false);
|
||||
const isGetEmailCode = ref(false);
|
||||
|
||||
|
||||
const getTelCode = () => {
|
||||
if (!telReg.test(tel.value)) {
|
||||
showToast('请输入正确的手机号!');
|
||||
return false;
|
||||
}
|
||||
if(isGetTelCode.value){
|
||||
return false;
|
||||
}
|
||||
isGetTelCode.value = true;
|
||||
http('/api/sms/phone', { phone: tel.value, type: 'login' }, 'POST').then(res => {
|
||||
reRenderTelGetcodebtn();
|
||||
}).catch(err => {
|
||||
showToast(err.message);
|
||||
}).finally(()=>{
|
||||
isGetTelCode.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const getEmailCode = () => {
|
||||
if (!emailReg.test(email.value)) {
|
||||
showToast('请输入正确的邮箱地址!');
|
||||
return false;
|
||||
}
|
||||
if (isGetEmailCode.value) {
|
||||
return false;
|
||||
}
|
||||
isGetEmailCode.value = true;
|
||||
|
||||
http('/api/sms/email', { email: email.value, type: 'login' }).then(res => {
|
||||
reRenderEmailGetcodebtn();
|
||||
}).catch(err => {
|
||||
showToast(err.message);
|
||||
}).finally(() => {
|
||||
isGetEmailCode.value = false;
|
||||
});
|
||||
};
|
||||
|
||||
const reRenderTelGetcodebtn = () => {
|
||||
let time = --telCountDown.value;
|
||||
telBtnTxt.value = `${time}s后重新获取`;
|
||||
if (time == 0) {
|
||||
clearTimeout(telTimer.value);
|
||||
telBtnTxt.value = '获取验证码';
|
||||
telCountDown.value = getCodeTime;
|
||||
} else {
|
||||
telTimer.value = setTimeout(reRenderTelGetcodebtn, 1000);
|
||||
}
|
||||
}
|
||||
const reRenderEmailGetcodebtn = () => {
|
||||
let time = --emailCountDown.value;
|
||||
emailBtnTxt.value = `${time}s后重新获取`;
|
||||
if (time == 0) {
|
||||
clearTimeout(emailTimer.value);
|
||||
emailBtnTxt.value = '获取验证码';
|
||||
emailCountDown.value = getCodeTime;
|
||||
} else {
|
||||
emailTimer.value = setTimeout(reRenderEmailGetcodebtn, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
const validate = () => {
|
||||
if (loginType == 'tel') {
|
||||
if (!telReg.test(tel.value)) {
|
||||
showToast('请输入正确的手机号!');
|
||||
return false;
|
||||
}
|
||||
if (!msgCode.value) {
|
||||
showToast('请输入短信验证码!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (loginType == 'email') {
|
||||
if (!emailReg.test(email.value)) {
|
||||
showToast('请输入正确的邮箱地址!');
|
||||
return false;
|
||||
}
|
||||
if (!emailCode.value) {
|
||||
showToast('请输入邮箱验证码!');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
const onLogin = () => {
|
||||
if (!validate()) {
|
||||
return false;
|
||||
}
|
||||
let formData = {};
|
||||
switch (loginType.value) {
|
||||
case 'tel':
|
||||
formData.username = tel.value;
|
||||
formData.code = msgCode.value;
|
||||
break;
|
||||
case 'email':
|
||||
formData.username = email.value;
|
||||
formData.code = emailCode.value;
|
||||
break;
|
||||
case 'password':
|
||||
formData.username = account.value;
|
||||
formData.password = md5(password.value).toLocaleLowerCase();
|
||||
break;
|
||||
}
|
||||
http('/api/auth/login', formData).then(res => {
|
||||
let nowTime = Date.now();
|
||||
let overTime = nowTime + res.data.expires_in * 1000;
|
||||
let authData = { ...res.data, expires_time: overTime };
|
||||
localCache.set('auth', authData);
|
||||
|
||||
authModal.hideAuthModal();
|
||||
getUserInfo();
|
||||
}).catch(err => {
|
||||
showToast(err.message);
|
||||
})
|
||||
};
|
||||
|
||||
const getUserInfo = () => {
|
||||
http('/api/user/profile', {}, 'get').then(res => {
|
||||
localCache.set('userInfo', res.data);
|
||||
userInfo.updateUserInfo(res.data);
|
||||
// window.location.reload();
|
||||
}).catch(err => {
|
||||
showToast(err.message);
|
||||
})
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.loginBox {
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
padding: 0 .6rem .6rem .6rem;
|
||||
|
||||
.banner {
|
||||
text-align: center;
|
||||
|
||||
h2 {
|
||||
font-size: .3rem;
|
||||
margin-bottom: .1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.5;
|
||||
font-size: .23rem;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.tabBox {
|
||||
height: .5rem;
|
||||
width: 100%;
|
||||
padding: .3rem 0;
|
||||
box-sizing: content-box;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
li {
|
||||
width: 1.75rem;
|
||||
height: .48rem;
|
||||
border: .01rem solid #414548;
|
||||
opacity: 0.4;
|
||||
border-radius: .02rem;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
font-size: .23rem;
|
||||
|
||||
&:hover,
|
||||
&.active {
|
||||
opacity: 1;
|
||||
color: #FFF;
|
||||
border-color: #3662FE;
|
||||
|
||||
i.icon-code {
|
||||
background-image: url('../../assets/images/icon_msg_h.png');
|
||||
}
|
||||
|
||||
i.icon-email {
|
||||
background-image: url('../../assets/images/icon_email_h.png');
|
||||
}
|
||||
|
||||
i.icon-pwd {
|
||||
background-image: url('../../assets/images/icon_pwd_h.png');
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
display: inline-block;
|
||||
margin-right: .1rem;
|
||||
background-size: contain;
|
||||
background-repeat: no-repeat;
|
||||
background-position: center;
|
||||
width: .3rem;
|
||||
height: .3rem;
|
||||
|
||||
&.icon-code {
|
||||
background-image: url('../../assets/images/icon_msg.png');
|
||||
}
|
||||
|
||||
&.icon-email {
|
||||
background-image: url('../../assets/images/icon_email.png');
|
||||
}
|
||||
|
||||
&.icon-pwd {
|
||||
background-image: url('../../assets/images/icon_pwd.png');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.formBox {
|
||||
.item {
|
||||
margin-top: 0.15rem;
|
||||
|
||||
.label {
|
||||
line-height: .66rem;
|
||||
font-size: .28rem;
|
||||
}
|
||||
|
||||
.val {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.txt,
|
||||
.stxt,
|
||||
.pwdInput {
|
||||
border: .01rem solid rgba($color: #414548, $alpha: 0.4);
|
||||
border-radius: .02rem;
|
||||
background: none;
|
||||
color: #FFF;
|
||||
|
||||
:deep(input) {
|
||||
background: none;
|
||||
color: #FFF;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.van-cell:after){
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sbtn {
|
||||
width: 4rem;
|
||||
margin-left: .1rem;
|
||||
font-size: .23rem;
|
||||
|
||||
&:disabled{
|
||||
opacity: 1;
|
||||
color: #FFF;
|
||||
border: .02rem solid #FFF;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submitBtn {
|
||||
margin-top: 1rem;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,211 @@
|
|||
<template>
|
||||
<div class="registerBox">
|
||||
<div class="banner">
|
||||
<h2>您好!欢迎使用海兔AIGC!</h2>
|
||||
<p>请输入您的相关信息进行注册!</p>
|
||||
</div>
|
||||
<div class="formBox">
|
||||
<div class="item">
|
||||
<div class="label">手机号/邮箱</div>
|
||||
<div class="val">
|
||||
<van-field :clearable="true" class="txt" v-model="account" placeholder="请输入手机号/邮箱" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="label">验证码</div>
|
||||
<div class="val">
|
||||
<van-field :clearable="true" type="digit" class="stxt" v-model="code" placeholder="请输入验证码" />
|
||||
<van-button class="sbtn" type="primary" :disabled="countDown !== getCodeTime" @click="getCode">{{ btnTxt
|
||||
}}</van-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="label">密码</div>
|
||||
<div class="val">
|
||||
<van-field type="password" class="pwdInput" v-model="password" placeholder="请输入密码" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<div class="label">再次输入密码</div>
|
||||
<div class="val">
|
||||
<van-field type="password" class="pwdInput" v-model="checkPassword" placeholder="请再次输入密码" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="submitBtn">
|
||||
<van-button type="primary" @click="onRegister">注册</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue';
|
||||
import http from '@/io/http';
|
||||
import { showToast } from 'vant';
|
||||
import { localCache } from '@/io/cache';
|
||||
import { useRouter } from 'vue-router';
|
||||
import { useAuthModal } from '@/stores/authModal';
|
||||
import md5 from 'md5';
|
||||
|
||||
const authModal = useAuthModal();
|
||||
const getCodeTime = 60;
|
||||
const account = ref();
|
||||
const code = ref();
|
||||
const password = ref();
|
||||
const checkPassword = ref();
|
||||
const btnTxt = ref('获取验证码');
|
||||
const countDown = ref(getCodeTime);
|
||||
const timer = ref(0);
|
||||
|
||||
const getCode = () => {
|
||||
let telReg = /^1[3-9]\d{9}$/;
|
||||
let emailReg = /^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$/;
|
||||
if (!(telReg.test(account.value) || emailReg.test(account.value))) {
|
||||
showToast('请输入正确的手机号或邮箱!');
|
||||
return false;
|
||||
}
|
||||
|
||||
http('/api/sms/send', { receiver: account.value, type: 'register' }).then(res => {
|
||||
reRenderGetcodebtn();
|
||||
}).catch(err => {
|
||||
showToast(err.message);
|
||||
})
|
||||
};
|
||||
|
||||
const reRenderGetcodebtn = () => {
|
||||
let time = --countDown.value;
|
||||
btnTxt.value = `${time}s后重新获取`;
|
||||
if (time == 0) {
|
||||
clearTimeout(timer.value);
|
||||
btnTxt.value = '获取验证码';
|
||||
countDown.value = getCodeTime;
|
||||
} else {
|
||||
timer.value = setTimeout(reRenderGetcodebtn, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
const validate = () => {
|
||||
let telReg = /^1[3-9]\d{9}$/;
|
||||
let emailReg = /^[\w\.-]+@[a-zA-Z\d\.-]+\.[a-zA-Z]{2,}$/;
|
||||
if (!(telReg.test(account.value) || emailReg.test(account.value))) {
|
||||
showToast('请输入正确的手机号或邮箱!');
|
||||
return false;
|
||||
}
|
||||
if (!code.value) {
|
||||
showToast('请输入验证码!');
|
||||
return false;
|
||||
}
|
||||
if (!password.value) {
|
||||
showToast('请输入密码!');
|
||||
return false;
|
||||
}
|
||||
if (!checkPassword.value) {
|
||||
showToast('请再次输入确认密码!');
|
||||
return false;
|
||||
}
|
||||
if (checkPassword.value !== password.value) {
|
||||
showToast('两次密码不一致,请重新输入!');
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
const onRegister = () => {
|
||||
if (!validate()) {
|
||||
return false;
|
||||
}
|
||||
let params = {
|
||||
username: account.value,
|
||||
code: code.value,
|
||||
password: md5(password.value).toLocaleLowerCase(),
|
||||
password_confirmation: md5(checkPassword.value).toLocaleLowerCase()
|
||||
};
|
||||
http('/api/auth/register', params).then(res => {
|
||||
showToast('注册成功!请登录!');
|
||||
localCache.set('auth', res.data);
|
||||
authModal.setAuthModalType('login');
|
||||
}).catch(err => {
|
||||
showToast(err.message);
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.registerBox {
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
padding: 0 .6rem .6rem .6rem;
|
||||
|
||||
.banner {
|
||||
text-align: center;
|
||||
|
||||
h2 {
|
||||
font-size: .3rem;
|
||||
margin-bottom: .1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.5;
|
||||
font-size: .23rem;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.formBox {
|
||||
.item {
|
||||
margin-top: 0.28rem;
|
||||
|
||||
.label {
|
||||
line-height: .5rem;
|
||||
font-size: .28rem;
|
||||
}
|
||||
|
||||
.val {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.txt,
|
||||
.stxt,
|
||||
.pwdInput {
|
||||
border: .01rem solid rgba($color: #414548, $alpha: 0.4);
|
||||
border-radius: .02rem;
|
||||
background: none;
|
||||
color: #FFF;
|
||||
|
||||
:deep(input) {
|
||||
background: none;
|
||||
color: #FFF;
|
||||
|
||||
&::placeholder {
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
}
|
||||
:deep(.van-cell:after){
|
||||
display: none;
|
||||
}
|
||||
|
||||
.sbtn {
|
||||
width: 4rem;
|
||||
margin-left: .1rem;
|
||||
font-size: .23rem;
|
||||
|
||||
&:disabled{
|
||||
opacity: 1;
|
||||
color: #FFF;
|
||||
border: .02rem solid #FFF;
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submitBtn {
|
||||
margin-top: .7rem;
|
||||
|
||||
button {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<template>
|
||||
<van-popup v-model:show="authModal.isShow" closeable style="background: none;width:6.93rem;">
|
||||
<div class="formBox" v-if="authModal.authModalType == 'login'">
|
||||
<div class="actionFlag" @click="onMethodChange('register')"><span>注册</span></div>
|
||||
<Login/>
|
||||
</div>
|
||||
<div class="formBox" v-if="authModal.authModalType == 'register'">
|
||||
<div class="actionFlag" @click="onMethodChange('login')"><span>登录</span></div>
|
||||
<Register/>
|
||||
</div>
|
||||
</van-popup>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import { useAuthModal } from '@/stores/authModal';
|
||||
import { useUserInfo } from '@/stores/userInfo';
|
||||
import { localCache } from '@/io/cache';
|
||||
import http from '@/io/http';
|
||||
import { useRouter } from 'vue-router';
|
||||
|
||||
const authModal = useAuthModal();
|
||||
const userInfo = useUserInfo();
|
||||
|
||||
const onMethodChange = (val) => {
|
||||
authModal.setAuthModalType(val);
|
||||
};
|
||||
|
||||
const handleCancel = () => {
|
||||
authModal.setAuthModalType('login');
|
||||
authModal.hideAuthModal();
|
||||
};
|
||||
const handleOk = () => {
|
||||
authModal.setAuthModalType('login');
|
||||
authModal.hideAuthModal();
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.formBox{
|
||||
position: relative;
|
||||
line-height: 1;
|
||||
padding-top: .5rem;
|
||||
color: #FFF;
|
||||
width: 100%;
|
||||
background: #161718;
|
||||
border-radius: .06rem;
|
||||
.actionFlag{
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
z-index: 2;
|
||||
width: 1.45rem;
|
||||
height: 1.4rem;
|
||||
border-radius: .1rem 0 0 0;
|
||||
overflow: hidden;
|
||||
color: #FFF;
|
||||
cursor: pointer;
|
||||
span{
|
||||
font-size: 0.26rem;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
top: .22rem;
|
||||
left: .16rem;
|
||||
}
|
||||
&::before{
|
||||
content: '';
|
||||
position: absolute;
|
||||
z-index: 0;
|
||||
top: -0.75rem;
|
||||
left: -0.7rem;
|
||||
width: 1.7rem;
|
||||
height: 1.7rem;
|
||||
background: #304FED;
|
||||
border-radius: 10px;
|
||||
transform: rotateZ(45deg);
|
||||
box-shadow: 0 0 20px rgba($color: #304FED, $alpha: 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
@ -16,6 +16,11 @@ const http = (url = '', data = {}, type = 'POST', otherConfig = {}) => {
|
|||
promise = axios({
|
||||
method: type,
|
||||
url,
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
'Accept': 'application/json; charset=UTF-8',
|
||||
'isLoading': config.isLoading,
|
||||
},
|
||||
params: data,
|
||||
timeout: config.timeout
|
||||
});
|
||||
|
|
|
|||
|
|
@ -7,15 +7,35 @@
|
|||
import axios from 'axios';
|
||||
import { localCache } from './cache';
|
||||
import router from "@/router";
|
||||
import hostAPI from '@/config/host.config'
|
||||
import { showToast } from 'vant';
|
||||
import { useAuthModal } from '@/stores/authModal';
|
||||
import hostAPI from '@/config/host.config'
|
||||
|
||||
export default function () {
|
||||
let _token = '';
|
||||
let requestCount = 0;//请求数量
|
||||
|
||||
const authModal = useAuthModal();
|
||||
|
||||
const showLoading = ()=>{
|
||||
if (requestCount === 0) {
|
||||
let renderDom = document.createElement('div');
|
||||
renderDom.style.cssText = 'width:100%; height: 100%; position: absolute;left:0;top:0;z-index:9999;background-color: rgba(0,0,0,0.5);display: flex;justify-content: center; align-items: center;'
|
||||
renderDom.setAttribute('id', 'requestLoading');
|
||||
renderDom.innerHTML = 'loading...';
|
||||
document.body.appendChild(renderDom);
|
||||
}
|
||||
requestCount++;
|
||||
}
|
||||
const hideLoading = ()=>{
|
||||
requestCount--;
|
||||
if (requestCount === 0) {
|
||||
document.body.removeChild(document.getElementById('requestLoading'));
|
||||
}
|
||||
};
|
||||
|
||||
// axios.defaults.baseURL = '//' + window.location.host;
|
||||
axios.defaults.baseURL = hostAPI;
|
||||
axios.defaults.baseURL = import.meta.env.VITE_API_BASE_URL;
|
||||
|
||||
// 请求超时时间为10秒
|
||||
axios.defaults.timeout = 10000;
|
||||
|
|
@ -23,7 +43,6 @@ export default function () {
|
|||
// 请求发送拦截,并在头部加入token
|
||||
axios.interceptors.request.use(
|
||||
function (config) {
|
||||
|
||||
let nextToken = localCache.get('auth') && localCache.get('auth').token;
|
||||
let toeknType = localCache.get('auth') && localCache.get('auth').token_type;
|
||||
if (config.url.indexOf('/auth/login') > -1) {
|
||||
|
|
@ -39,11 +58,11 @@ export default function () {
|
|||
if (_token) {
|
||||
config.headers['Authorization'] = `${toeknType} ${_token}`; // 存在将token写入请求头
|
||||
}
|
||||
// if (config.headers.isLoading !== false) showLoading();
|
||||
if (config.headers.isLoading !== false) showLoading();
|
||||
return config;
|
||||
},
|
||||
function (error) {
|
||||
// if (error.config.headers.isLoading !== false) hideLoading();
|
||||
if (error.config.headers.isLoading !== false) hideLoading();
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
|
@ -58,18 +77,19 @@ export default function () {
|
|||
showToast('账号过期或异地登录, 请重新登录');
|
||||
localCache.remove('auth');
|
||||
localCache.remove('userInfo');
|
||||
window.location.pathname='/home';
|
||||
authModal.setAuthModalType('login');
|
||||
authModal.showAuthModal();
|
||||
// router.replace({name: 'Home', params: {auth: 'over'}});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
showToast('后台' + response.data.status + '错误返回格式不正确');
|
||||
}
|
||||
// if (response.config.headers.isLoading !== false) hideLoading();
|
||||
if (response.config.headers.isLoading !== false) hideLoading();
|
||||
return response;
|
||||
},
|
||||
function (error) {
|
||||
// if (error.config.headers.isLoading !== false) hideLoading();
|
||||
if (error.config.headers.isLoading !== false) hideLoading();
|
||||
if (error.response) {
|
||||
switch (error.response.data.status) {
|
||||
case 401:
|
||||
|
|
@ -77,7 +97,8 @@ export default function () {
|
|||
showToast('账号过期或异地登录, 请重新登录');
|
||||
localCache.remove('auth');
|
||||
localCache.remove('userInfo');
|
||||
window.location.pathname='/home';
|
||||
authModal.setAuthModalType('login');
|
||||
authModal.showAuthModal();
|
||||
break;
|
||||
case 500:
|
||||
// 500 服务端请求错误
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
|
||||
import axios from 'axios'
|
||||
import { localCache } from '@/io/cache'
|
||||
import { message } from 'ant-design-vue'
|
||||
const service = axios.create({
|
||||
baseURL: import.meta.env.VITE_API_BASE_URL,
|
||||
timeout: 200000,
|
||||
withCredentials: true
|
||||
})
|
||||
|
||||
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
const token = localCache.get('auth') && localCache.get('auth').token;
|
||||
if (token) {
|
||||
config.headers[
|
||||
'Authorization'
|
||||
] = `Bearer ${token}`
|
||||
}
|
||||
if (config.requestBaseUrl == 'chat') {
|
||||
config.baseURL = import.meta.env.VITE_API_CHAT_URL
|
||||
}
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
service.interceptors.response.use(
|
||||
|
||||
response => {
|
||||
const { requestBaseUrl } = response.config
|
||||
const res = response.data
|
||||
if (requestBaseUrl == 'chat') {
|
||||
return res
|
||||
} else {
|
||||
if (res.status != 0) {
|
||||
message.error(res.msg || 'Error')
|
||||
return Promise.reject(res.message || 'Error')
|
||||
} else {
|
||||
return res.data
|
||||
}
|
||||
}
|
||||
},
|
||||
error => {
|
||||
const res = error.response.data
|
||||
const { requestBaseUrl } = error.config
|
||||
if (requestBaseUrl == 'chat') {
|
||||
if (res.errcode == 401) {
|
||||
// localCache.remove('auth');
|
||||
// localCache.remove('userInfo');
|
||||
}
|
||||
message.error(res.errmsg || 'Error')
|
||||
return Promise.reject(res)
|
||||
} else {
|
||||
|
||||
message.error(res.errmsg || 'Error')
|
||||
return Promise.reject(error)
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
export default service
|
||||
|
|
@ -3,13 +3,13 @@
|
|||
<div class="logo">logo</div>
|
||||
<div class="title">首页</div>
|
||||
<div class="nav">
|
||||
<div class="navBtn" @click="toggleMenu"><van-icon name="wap-nav" size=".37rem" /></div>
|
||||
<div class="menuBox" v-if="showMenu">
|
||||
<template v-if="isLogin">
|
||||
<div class="navBtn" @click.stop="toggleMenu"><van-icon name="wap-nav" size=".37rem" /></div>
|
||||
<div class="menuBox" @click.stop="" v-if="showMenu">
|
||||
<template v-if="userInfo.userData && userInfo.userData.id">
|
||||
<div class="menuHeader">
|
||||
<div class="userInfo">
|
||||
<div class="avatar"><img src="" alt=""></div>
|
||||
<div class="name">大王叫我来巡山大王叫我来巡山</div>
|
||||
<div class="avatar"><img :src="userInfo.userData.avatar || defaultAvatar"></div>
|
||||
<div class="name">{{ userInfo.userData.name || userInfo.userData.phone || userInfo.userData.email }}</div>
|
||||
</div>
|
||||
<div class="navIcon" @click="toggleMenu"><van-icon name="wap-nav" size=".37rem" /></div>
|
||||
</div>
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
<div class="menuHeader">
|
||||
<div class="userInfo">
|
||||
<div class="avatar"><img src="" alt=""></div>
|
||||
<div class="name">大王叫我来巡山大王叫我来巡山</div>
|
||||
<div class="name">未登录</div>
|
||||
</div>
|
||||
<div class="navIcon" @click="toggleMenu"><van-icon name="wap-nav" size=".37rem" /></div>
|
||||
</div>
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<Auth />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -49,36 +50,53 @@ import { localCache } from '@/io/cache';
|
|||
import http from '@/io/http';
|
||||
import { useRouter, useRoute } from 'vue-router';
|
||||
import { showToast } from 'vant';
|
||||
import Auth from '@/components/auth/index.vue';
|
||||
import { useAuthModal } from '@/stores/authModal';
|
||||
|
||||
|
||||
const userInfo = useUserInfo();
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const authModal = useAuthModal();
|
||||
|
||||
const isLogin = ref(false);
|
||||
const showMenu = ref(false);
|
||||
|
||||
onMounted(()=>{
|
||||
document.body.addEventListener('click', ()=>{
|
||||
showMenu.value = false;
|
||||
});
|
||||
|
||||
let userInfoData = localCache.get('userInfo') || {};
|
||||
if (userInfoData.id) {
|
||||
userInfo.updateUserInfo(userInfoData);
|
||||
}
|
||||
});
|
||||
|
||||
const toggleMenu = ()=>{
|
||||
console.log(showMenu.value);
|
||||
showMenu.value = !showMenu.value;
|
||||
};
|
||||
|
||||
|
||||
const onLogin = ()=>{
|
||||
|
||||
showMenu.value = false;
|
||||
authModal.setAuthModalType('login');
|
||||
authModal.showAuthModal();
|
||||
};
|
||||
|
||||
const onRegister = ()=>{
|
||||
|
||||
showMenu.value = false;
|
||||
authModal.setAuthModalType('register');
|
||||
authModal.showAuthModal();
|
||||
};
|
||||
|
||||
const onLogout = ()=>{
|
||||
showMenu.value = false;
|
||||
http('/api/auth/logout').then(res => {
|
||||
localCache.remove('userInfo');
|
||||
localCache.remove('auth');
|
||||
userInfo.updateUserInfo();
|
||||
showToast('已退出登录!');
|
||||
isLogin.value = false;
|
||||
window.location.replace('/');
|
||||
// window.location.replace('/');
|
||||
}).catch(err => {
|
||||
showToast(err.message);
|
||||
})
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ import httpConfig from "./io/httpConfig";
|
|||
import 'vant/es/toast/style';
|
||||
|
||||
|
||||
httpConfig();
|
||||
|
||||
const app = createApp(App);
|
||||
|
||||
|
|
@ -22,4 +21,5 @@ registerSvgIcon(app);
|
|||
app.use(createPinia());
|
||||
app.use(router);
|
||||
|
||||
httpConfig();
|
||||
app.mount("#app");
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div class="page">
|
||||
移动端
|
||||
移动端首页
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -9,7 +9,7 @@ import { onMounted } from 'vue';
|
|||
import { showToast } from 'vant';
|
||||
|
||||
onMounted(()=>{
|
||||
showToast('页面初始化');
|
||||
// showToast('页面初始化');
|
||||
});
|
||||
|
||||
</script>
|
||||
|
|
@ -18,7 +18,6 @@ onMounted(()=>{
|
|||
.page{
|
||||
width: 7.5rem;
|
||||
height: 1rem;
|
||||
background: #CCC;
|
||||
font-size: .22rem;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -24,9 +24,7 @@ export default defineConfig({
|
|||
}),
|
||||
Components({
|
||||
resolvers: [
|
||||
VantResolver({
|
||||
importStyle: false, // css in js
|
||||
}),
|
||||
VantResolver(),
|
||||
],
|
||||
}),
|
||||
],
|
||||
|
|
|
|||