登录注册

master
fuxiaochun 2023-08-11 20:13:34 +08:00
parent fce6730fb1
commit d7e2c8ac22
19 changed files with 810 additions and 28 deletions

5
.env.development 100644
View File

@ -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'

5
.env.production 100644
View File

@ -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'

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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
});

View File

@ -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 服务端请求错误

67
src/io/request.js 100644
View File

@ -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

View File

@ -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);
})

View File

@ -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");

View File

@ -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>

View File

@ -24,9 +24,7 @@ export default defineConfig({
}),
Components({
resolvers: [
VantResolver({
importStyle: false, // css in js
}),
VantResolver(),
],
}),
],