503 lines
12 KiB
Vue
503 lines
12 KiB
Vue
<template>
|
||
<view class="login-container">
|
||
<!-- 背景图 -->
|
||
<image class="bg-image" src="/static/image/login.png" mode="aspectFill"></image>
|
||
|
||
<!-- 返回按钮 -->
|
||
<wd-navbar left-arrow custom-style="background-color: transparent !important;" safeAreaInsetTop @click-left="back"></wd-navbar>
|
||
|
||
<view class="content">
|
||
<!-- Logo -->
|
||
<view class="logo-container">你好!!</view>
|
||
|
||
<!-- 欢迎文字 -->
|
||
<view class="welcome-text">
|
||
<view>欢迎来到</view>
|
||
<view class="welcome-tag">苗草古方</view>
|
||
</view>
|
||
|
||
<!-- Tab切换 -->
|
||
<view class="tabs" v-if="type == 'login'">
|
||
<view class="tab-item" :class="{ active: activeTab === 'password' }" @click="switchTabs('password')">
|
||
<text>密码登录</text>
|
||
<view class="underline" v-if="activeTab === 'password'"></view>
|
||
</view>
|
||
<view class="tab-item" :class="{ active: activeTab === 'code' }" @click="switchTabs('code')">
|
||
<text>验证码登录</text>
|
||
<view class="underline" v-if="activeTab === 'code'"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 表单 -->
|
||
<view class="form-container">
|
||
<!-- 登录 -->
|
||
<view v-if="type == 'login'">
|
||
<view class="input-item">
|
||
<input
|
||
placeholder="请输入用户名"
|
||
style="font-weight: 600; font-size: 36rpx"
|
||
v-model="formData.mobile"
|
||
placeholder-style="color: #999999;font-size: 28rpx;font-weight: 400 !important;"
|
||
type="number"
|
||
/>
|
||
</view>
|
||
<view class="input-item" v-if="activeTab === 'password'">
|
||
<input placeholder="请输入密码" v-model="formData.password" password placeholder-style="color: #999999;;font-size: 28rpx;" />
|
||
</view>
|
||
|
||
<view class="input-item code-input" v-else>
|
||
<input placeholder="请输入验证码" v-model="formData.code" placeholder-style="color: #999999;;font-size: 28rpx;" />
|
||
<view class="get-code" @click="getCode(1)">{{ current.seconds || codeIngo }}</view>
|
||
</view>
|
||
</view>
|
||
<!-- 注册 -->
|
||
<view v-if="type == 'register'">
|
||
<view class="input-item">
|
||
<input
|
||
placeholder="请输入用户名"
|
||
type="number"
|
||
style="font-weight: 600; font-size: 36rpx"
|
||
v-model="registerInfo.mobile"
|
||
placeholder-style="color: #999999;font-size: 28rpx;font-weight: 400 !important;"
|
||
/>
|
||
</view>
|
||
<view class="input-item code-input">
|
||
<input placeholder="请输入验证码" v-model="registerInfo.code" placeholder-style="color: #999999;;font-size: 28rpx;" />
|
||
<view class="get-code" @click="getCode(2)">{{ current.seconds || codeIngo }}</view>
|
||
</view>
|
||
<view class="input-item">
|
||
<input placeholder="请输入您的密码" v-model="registerInfo.password" password placeholder-style="color: #999999;;font-size: 28rpx;" />
|
||
</view>
|
||
<view class="input-item">
|
||
<input placeholder="请再次输入您的密码" v-model="registerInfo.passwordNew" password placeholder-style="color: #999999;;font-size: 28rpx;" />
|
||
</view>
|
||
<view class="input-item">
|
||
<input placeholder="请输入邀请码(非必填)" v-model="registerInfo.inviteCode" placeholder-style="color: #999999;;font-size: 28rpx;" />
|
||
</view>
|
||
</view>
|
||
<!-- 注册链接 -->
|
||
<view class="register-text" @click="type = 'login'" v-if="type == 'register'">
|
||
<text>已有账号?</text>
|
||
<text class="register-link">立即登录</text>
|
||
</view>
|
||
<!-- 登录链接 -->
|
||
<view class="register-text" @click="type = 'register'" v-if="type == 'login'">
|
||
<text>还没有账号?</text>
|
||
<text class="register-link">立即注册</text>
|
||
</view>
|
||
<!-- 登录按钮 -->
|
||
<button class="login-btn" :loading="submitLoading" :disabled="submitLoading" @click="login">
|
||
{{ type == 'register' ? '注册' : '登录' }}
|
||
</button>
|
||
<!-- 底部声明 -->
|
||
<!-- <view class="agreement" v-if="type == 'login'">
|
||
<text>登录即表示接受</text>
|
||
<navigator url="/pages/protocol/protocol" class="agreement-link">《版权声明》</navigator>
|
||
<text>和</text>
|
||
<navigator url="/pages/protocol/protocol" class="agreement-link">《隐私保护》</navigator>
|
||
</view> -->
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref } from 'vue';
|
||
import api from '@/api/index';
|
||
import { toast } from '@/utils/fun.js';
|
||
import { useCountDown } from '@/uni_modules/wot-design-uni';
|
||
import { Store } from '@/store';
|
||
import { onLoad } from '@dcloudio/uni-app';
|
||
|
||
const store = Store();
|
||
const { start, pause, reset, current } = useCountDown({
|
||
time: 60 * 1000,
|
||
onChange(current) {},
|
||
onFinish() {
|
||
codeIngo.value = '重新发送';
|
||
}
|
||
});
|
||
|
||
const initialRegisterInfo = {
|
||
mobile: '',
|
||
password: '',
|
||
code: '',
|
||
inviteCode: '',
|
||
passwordNew: ''
|
||
};
|
||
const registerInfo = ref({ ...initialRegisterInfo });
|
||
|
||
onLoad(() => {
|
||
if (uni.getStorageSync('inviteCode')) {
|
||
registerInfo.value.inviteCode = uni.getStorageSync('inviteCode');
|
||
console.log(registerInfo.value.inviteCode);
|
||
}else{
|
||
console.log('未取到邀请码');
|
||
}
|
||
});
|
||
|
||
const resetRegisterInfo = () => {
|
||
registerInfo.value = { ...initialRegisterInfo };
|
||
};
|
||
|
||
const type = ref('login');
|
||
const codeIngo = ref('点击获取验证码');
|
||
// 定义当前激活的tab
|
||
const activeTab = ref('password');
|
||
|
||
const formData = ref({
|
||
mobile: '',
|
||
password: '',
|
||
code: ''
|
||
});
|
||
|
||
const submitLoading = ref(false);
|
||
|
||
// 返回上一页
|
||
const back = () => {
|
||
uni.navigateBack();
|
||
};
|
||
|
||
const switchTabs = (v) => {
|
||
activeTab.value = v;
|
||
formData.value = {};
|
||
};
|
||
|
||
// 获取验证码方法
|
||
const getCode = (e) => {
|
||
if (!formData.value.mobile && e == 1) {
|
||
toast('请输入手机号');
|
||
return;
|
||
}
|
||
|
||
if (!registerInfo.value.mobile && e == 2) {
|
||
toast('请输入手机号');
|
||
return;
|
||
}
|
||
|
||
if (current.value.seconds) {
|
||
toast('请等待倒计时结束');
|
||
return;
|
||
}
|
||
|
||
api.smsCode({
|
||
mobile: e == 2 ? registerInfo.value.mobile : formData.value.mobile,
|
||
scene: 1
|
||
})
|
||
.then((res) => {
|
||
start();
|
||
toast('验证码发送成功');
|
||
})
|
||
.catch((err) => {
|
||
console.log(err);
|
||
toast('验证码发送失败');
|
||
});
|
||
};
|
||
|
||
// 登录方法
|
||
const login = () => {
|
||
// 注册
|
||
if (type.value == 'register') {
|
||
if (!registerInfo.value.mobile) return toast('请输入手机号码');
|
||
if (!registerInfo.value.code) return toast('请输入验证码');
|
||
if (!registerInfo.value.password) return toast('请输入密码');
|
||
if (!registerInfo.value.passwordNew) return toast('请再次输入密码');
|
||
if (registerInfo.value.password != registerInfo.value.passwordNew) return toast('两次密码输入不一致');
|
||
// if (!registerInfo.value.inviteCode) return toast('请输入邀请码');
|
||
api.registerApi(registerInfo.value).then((res) => {
|
||
uni.showModal({
|
||
title: '提示',
|
||
content: '注册成功',
|
||
showCancel: false,
|
||
success: (res) => {
|
||
type.value = 'login';
|
||
resetRegisterInfo();
|
||
}
|
||
});
|
||
});
|
||
} else {
|
||
if (!formData.value.mobile) return toast('请输入手机号码');
|
||
if (activeTab.value === 'password') {
|
||
if (!formData.value.password) return toast('请输入登录密码');
|
||
api.loginApi(formData.value).then((res: any) => {
|
||
uni.setStorageSync('Authorization', res.accessToken);
|
||
store.setUserId(res.userId);
|
||
store.usersGetInfo();
|
||
back();
|
||
});
|
||
} else {
|
||
if (!formData.value.code) return toast('请输入验证码');
|
||
api.smsLoginApi(formData.value).then((res: any) => {
|
||
uni.setStorageSync('Authorization', res.accessToken);
|
||
store.setUserId(res.userId);
|
||
store.usersGetInfo();
|
||
back();
|
||
});
|
||
}
|
||
}
|
||
|
||
// if (activeTab.value === 'code') {
|
||
// if (!formData.value?.phone) {
|
||
// uni.showToast({
|
||
// title: '请输入手机号',
|
||
// icon: 'none'
|
||
// });
|
||
// return;
|
||
// }
|
||
// if (!formData.value?.code) {
|
||
// uni.showToast({
|
||
// title: '请输入验证码',
|
||
// icon: 'none'
|
||
// });
|
||
// return;
|
||
// }
|
||
// } else {
|
||
// if (!formData.value?.mobile) {
|
||
// uni.showToast({
|
||
// title: '请输入用户名',
|
||
// icon: 'none'
|
||
// });
|
||
// return;
|
||
// }
|
||
// if (!formData.value?.password) {
|
||
// uni.showToast({
|
||
// title: '请输入密码',
|
||
// icon: 'none'
|
||
// });
|
||
// return;
|
||
// }
|
||
// }
|
||
|
||
// submitLoading.value = true;
|
||
// uni.showLoading({
|
||
// title: '登录中...'
|
||
// });
|
||
|
||
// wx.login({
|
||
// success(loginRes) {
|
||
// if (loginRes.code) {
|
||
// //发起网络请求
|
||
// formData.value.socialCode = loginRes.code;
|
||
// // formData.value.socialState = ""
|
||
// loginApi({ ...formData.value })
|
||
// .then((res) => {
|
||
// if (res?.accessToken) {
|
||
// uni.hideLoading();
|
||
// store.commit('setToken', res.accessToken);
|
||
// getUser()
|
||
// .then((resUser) => {
|
||
// uni.hideLoading();
|
||
// store.commit('setUserInfo', { id: res.userId, ...resUser });
|
||
// // uni.switchTab({ url: "/pages/mine/mine" })
|
||
// navigateBackOrUrl('/pages/mine/mine', true);
|
||
// submitLoading.value = false;
|
||
// uni.showToast({
|
||
// title: '登录成功',
|
||
// icon: 'success'
|
||
// });
|
||
// })
|
||
// .catch((err) => {
|
||
// uni.showToast({
|
||
// title: '获取用户信息失败',
|
||
// icon: 'none'
|
||
// });
|
||
// uni.hideLoading();
|
||
// submitLoading.value = false;
|
||
// });
|
||
// } else {
|
||
// uni.showToast({
|
||
// title: '登录失败',
|
||
// icon: 'none'
|
||
// });
|
||
// uni.hideLoading();
|
||
// submitLoading.value = false;
|
||
// }
|
||
// })
|
||
// .catch((err) => {
|
||
// uni.hideLoading();
|
||
// submitLoading.value = false;
|
||
// });
|
||
// } else {
|
||
// console.log('登录失败!' + loginRes.errMsg);
|
||
// }
|
||
// },
|
||
// fail(err) {
|
||
// console.log('wx.login err', err);
|
||
// }
|
||
// });
|
||
};
|
||
|
||
// 跳转到注册页
|
||
const toRegister = () => {
|
||
uni.navigateTo({
|
||
url: '/pages/login/register'
|
||
});
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.login-container {
|
||
position: relative;
|
||
width: 100%;
|
||
height: 100vh;
|
||
}
|
||
|
||
.bg-image {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
z-index: -1;
|
||
}
|
||
|
||
.back-btn {
|
||
position: absolute;
|
||
top: 100rpx;
|
||
left: 40rpx;
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
z-index: 10;
|
||
}
|
||
|
||
.content {
|
||
padding: 0 65rpx;
|
||
margin-top: 180rpx;
|
||
position: absolute;
|
||
}
|
||
|
||
.logo-container {
|
||
margin-bottom: 8rpx;
|
||
font-weight: bold;
|
||
font-size: 44rpx;
|
||
color: #232323;
|
||
}
|
||
|
||
.logo {
|
||
width: 180rpx;
|
||
height: 180rpx;
|
||
}
|
||
|
||
.welcome-text {
|
||
font-weight: bold;
|
||
font-size: 44rpx;
|
||
color: #232323;
|
||
text-align: center;
|
||
margin-bottom: 60rpx;
|
||
display: flex;
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.welcome-tag {
|
||
color: #5d7a4e;
|
||
margin-left: 12rpx;
|
||
font-size: 44rpx;
|
||
}
|
||
|
||
.tabs {
|
||
display: flex;
|
||
margin-bottom: 40rpx;
|
||
}
|
||
|
||
.tab-item {
|
||
position: relative;
|
||
margin-right: 60rpx;
|
||
// padding-bottom: 20rpx;
|
||
}
|
||
|
||
.tab-item text {
|
||
font-weight: bold;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.tab-item.active text {
|
||
color: #232323;
|
||
}
|
||
|
||
.tab-item:not(.active) text {
|
||
color: #999999;
|
||
}
|
||
|
||
.underline {
|
||
width: 104rpx;
|
||
height: 4rpx;
|
||
background: #5d7a4e;
|
||
border-radius: 170rpx;
|
||
}
|
||
|
||
.form-container {
|
||
width: 100%;
|
||
}
|
||
|
||
.input-item {
|
||
width: 620rpx;
|
||
height: 90rpx;
|
||
background: #ffffff;
|
||
border-radius: 14rpx;
|
||
border: 2rpx solid #f6f6f6;
|
||
margin-bottom: 30rpx;
|
||
padding: 0 30rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
}
|
||
|
||
.input-item input {
|
||
width: 100%;
|
||
height: 100%;
|
||
font-size: 28rpx;
|
||
color: #333333;
|
||
}
|
||
|
||
.code-input {
|
||
input {
|
||
flex: 1;
|
||
}
|
||
.get-code {
|
||
font-size: 24rpx;
|
||
color: #8e8e8e;
|
||
margin-left: 20rpx;
|
||
}
|
||
}
|
||
|
||
.register-text {
|
||
display: flex;
|
||
margin-bottom: 210rpx;
|
||
font-size: 26rpx;
|
||
color: #232323;
|
||
}
|
||
|
||
.register-link {
|
||
color: #5d7a4e;
|
||
margin-left: 10rpx;
|
||
}
|
||
|
||
.login-btn {
|
||
width: 474rpx;
|
||
height: 78rpx;
|
||
line-height: 78rpx;
|
||
border-radius: 39rpx;
|
||
text-align: center;
|
||
color: #fff !important;
|
||
font-size: 28rpx;
|
||
margin: 0 auto;
|
||
margin-bottom: 40rpx;
|
||
background: #5d7a4e !important;
|
||
|
||
&::after {
|
||
border: none;
|
||
}
|
||
}
|
||
|
||
.agreement {
|
||
display: flex;
|
||
justify-content: center;
|
||
font-size: 24rpx;
|
||
color: #999999;
|
||
}
|
||
|
||
.agreement-link {
|
||
color: #5d7a4e;
|
||
margin: 0 10rpx;
|
||
}
|
||
</style>
|