优化页面
This commit is contained in:
1 parent
6a822548b1
commit
fb4888188f
5 files changed
+412
-4
No files matched your search
@@ -53,6 +53,12 @@
|
|||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "登录"
|
"navigationBarTitleText": "登录"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"path": "pages/login/register",
|
||||||
|
"style": {
|
||||||
|
"navigationBarTitleText": ""
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -156,6 +156,13 @@ const forgetPassword = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//跳转到注册页面
|
||||||
|
const goRegisterPage = function() {
|
||||||
|
uni.navigateTo({
|
||||||
|
url:'/pages/login/register'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// 显示注册弹窗
|
// 显示注册弹窗
|
||||||
const showRegisterPopup = () => {
|
const showRegisterPopup = () => {
|
||||||
showRegister.value = true;
|
showRegister.value = true;
|
||||||
@@ -469,7 +476,8 @@ const emit = defineEmits(['close', 'success']);
|
|||||||
<!-- 注册链接 -->
|
<!-- 注册链接 -->
|
||||||
<view class="flex justify-center items-center my-8 text-gray-500 text-sm">
|
<view class="flex justify-center items-center my-8 text-gray-500 text-sm">
|
||||||
<text>Don't have an account?</text>
|
<text>Don't have an account?</text>
|
||||||
<text class="text-green-500 ml-2" @tap="showRegisterPopup">立即注册</text>
|
<text class="text-green-500 ml-2" @tap="showRegisterPopup">Create one</text>
|
||||||
|
<text class="text-green-500 ml-2" @tap="goRegisterPage">Create one</text>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 同意条款 -->
|
<!-- 同意条款 -->
|
||||||
|
|||||||
@@ -0,0 +1,393 @@
|
|||||||
|
<script setup>
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { register, sendCodeToEmail, loginByEmail } from './api';
|
||||||
|
import { useUserStore } from '@/store/user.js';
|
||||||
|
|
||||||
|
const userStore = useUserStore();
|
||||||
|
|
||||||
|
// 注册相关变量
|
||||||
|
const registerEmail = ref(''); // 注册邮箱
|
||||||
|
const registerPassword = ref(''); // 注册密码
|
||||||
|
const confirmPassword = ref(''); // 确认密码
|
||||||
|
const verificationCode = ref(''); // 验证码
|
||||||
|
const codeBtnText = ref('获取验证码');
|
||||||
|
const codeBtnDisabled = ref(false);
|
||||||
|
const checked = ref(true); // 同意条款,默认勾选
|
||||||
|
let countdownTimer = null;
|
||||||
|
|
||||||
|
// 邮箱格式验证
|
||||||
|
const validateEmail = (email) => {
|
||||||
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
return emailRegex.test(email);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 同意条款切换
|
||||||
|
const onChange = (e) => {
|
||||||
|
checked.value = e.detail.value; // 更新checked值
|
||||||
|
};
|
||||||
|
|
||||||
|
// 显示用户协议
|
||||||
|
const showAgreement = () => {
|
||||||
|
uni.showModal({
|
||||||
|
title: '用户协议',
|
||||||
|
content: '欢迎使用我们的服务!\n\n本协议规定了您使用我们服务的条款和条件,请仔细阅读。\n\n1. 服务使用条款\n2. 隐私政策\n3. 账户安全\n4. 免责声明\n\n继续使用即表示您同意遵守这些条款。',
|
||||||
|
showCancel: true,
|
||||||
|
confirmText: '同意',
|
||||||
|
cancelText: '取消',
|
||||||
|
success: (res) => {
|
||||||
|
if (res.confirm) {
|
||||||
|
checked.value = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// 获取验证码
|
||||||
|
const getVerificationCode = async () => {
|
||||||
|
if (!registerEmail.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入邮箱',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateEmail(registerEmail.value)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入正确的邮箱',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送验证码
|
||||||
|
try {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '发送中...',
|
||||||
|
mask: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const params = {
|
||||||
|
email: registerEmail.value,
|
||||||
|
register: true
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await sendCodeToEmail(params);
|
||||||
|
|
||||||
|
if (res && res.code === 0) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: '验证码已发送',
|
||||||
|
icon: 'success',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 开始倒计时
|
||||||
|
let timeLeft = 60;
|
||||||
|
codeBtnDisabled.value = true;
|
||||||
|
codeBtnText.value = `${timeLeft}秒`;
|
||||||
|
|
||||||
|
countdownTimer = setInterval(() => {
|
||||||
|
timeLeft--;
|
||||||
|
codeBtnText.value = `${timeLeft}秒`;
|
||||||
|
|
||||||
|
if (timeLeft <= 0) {
|
||||||
|
clearInterval(countdownTimer);
|
||||||
|
codeBtnText.value = '重新获取';
|
||||||
|
codeBtnDisabled.value = false;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: res.msg || '发送失败',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || '发送失败,请重试',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 注册提交
|
||||||
|
const onRegister = async () => {
|
||||||
|
if (!registerEmail.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入邮箱',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validateEmail(registerEmail.value)) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入正确的邮箱',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!verificationCode.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入验证码',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!registerPassword.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请输入密码',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registerPassword.value !== confirmPassword.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '两次输入密码不一致',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (registerPassword.value.length < 6) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '密码至少6位',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!checked.value) {
|
||||||
|
uni.showToast({
|
||||||
|
title: '请先同意用户协议',
|
||||||
|
icon: 'none',
|
||||||
|
duration: 2000,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
uni.showLoading({
|
||||||
|
title: '注册中...',
|
||||||
|
mask: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
// 调用注册API
|
||||||
|
const registerParams = {
|
||||||
|
email: registerEmail.value,
|
||||||
|
verificationCode: verificationCode.value,
|
||||||
|
password: registerPassword.value,
|
||||||
|
confirmPassword: confirmPassword.value
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await register(registerParams);
|
||||||
|
|
||||||
|
if (res && res.code === 0) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: '注册成功',
|
||||||
|
icon: 'success',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 注册成功后自动登录
|
||||||
|
setTimeout(async () => {
|
||||||
|
try {
|
||||||
|
const loginRes = await loginByEmail({
|
||||||
|
email: registerEmail.value,
|
||||||
|
password: registerPassword.value
|
||||||
|
});
|
||||||
|
|
||||||
|
if (loginRes && loginRes.code === 0) {
|
||||||
|
// 存储用户信息到全局状态
|
||||||
|
userStore.setUserInfo(loginRes.data);
|
||||||
|
userStore.setToken(loginRes.data.accessToken);
|
||||||
|
userStore.setLoginStatus(true);
|
||||||
|
|
||||||
|
uni.showToast({
|
||||||
|
title: '登录成功',
|
||||||
|
icon: 'success',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 跳转到首页
|
||||||
|
uni.switchTab({
|
||||||
|
url: '/pages/mine/index'
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
uni.showToast({
|
||||||
|
title: loginRes.msg || '自动登录失败',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 即使自动登录失败也跳转到首页,让用户重新登录
|
||||||
|
uni.switchTab({
|
||||||
|
url: '/pages/mine/index'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('自动登录失败:', error);
|
||||||
|
uni.showToast({
|
||||||
|
title: '自动登录失败,请手动登录',
|
||||||
|
icon: 'none',
|
||||||
|
});
|
||||||
|
|
||||||
|
// 跳转到首页
|
||||||
|
uni.switchTab({
|
||||||
|
url: '/pages/mine/index'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
} else {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: res.msg || '注册失败',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
uni.hideLoading();
|
||||||
|
uni.showToast({
|
||||||
|
title: error.message || '注册失败,请稍后重试',
|
||||||
|
icon: 'error',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 清空输入框
|
||||||
|
const clearInput = (type) => {
|
||||||
|
if (type === 'registerEmail') {
|
||||||
|
registerEmail.value = '';
|
||||||
|
} else if (type === 'registerPassword') {
|
||||||
|
registerPassword.value = '';
|
||||||
|
} else if (type === 'confirmPassword') {
|
||||||
|
confirmPassword.value = '';
|
||||||
|
} else if (type === 'verificationCode') {
|
||||||
|
verificationCode.value = '';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<view class="h-[120vh] p-4 min-h-screen bg-white flex flex-col justify-center">
|
||||||
|
<!-- 标题 -->
|
||||||
|
<view class="mb-12 mt-20 text-center">
|
||||||
|
<image src="/static/tabbar/find.png" class="w-20 h-20 mb-8" mode="aspectFit"></image>
|
||||||
|
<text class="block text-3xl font-bold text-gray-800 mb-4">CREATE ACCOUNT</text>
|
||||||
|
<text class="text-sm text-gray-500">Join Sweekar to get started</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 注册邮箱输入 -->
|
||||||
|
<view class="mb-6">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="email" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent"
|
||||||
|
type="email"
|
||||||
|
placeholder="Email Address"
|
||||||
|
v-model="registerEmail"
|
||||||
|
/>
|
||||||
|
<view
|
||||||
|
v-if="registerEmail"
|
||||||
|
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-black font-bold"
|
||||||
|
@tap="clearInput('registerEmail')"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 验证码输入 -->
|
||||||
|
<view class="mb-6 relative">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="chat" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent pr-32"
|
||||||
|
type="text"
|
||||||
|
placeholder="Verification Code"
|
||||||
|
v-model="verificationCode"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</view>
|
||||||
|
<button
|
||||||
|
class="absolute right-2 top-1/2 transform -translate-y-1/2 h-10 px-4 bg-theme text-white text-xs rounded-full disabled:bg-gray-400 disabled:text-gray-300 flex items-center justify-center"
|
||||||
|
:disabled="codeBtnDisabled"
|
||||||
|
@tap="getVerificationCode"
|
||||||
|
>
|
||||||
|
{{ codeBtnText }}
|
||||||
|
</button>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 注册密码输入 -->
|
||||||
|
<view class="mb-6">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="lock" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent"
|
||||||
|
type="password"
|
||||||
|
placeholder="Password"
|
||||||
|
v-model="registerPassword"
|
||||||
|
/>
|
||||||
|
<view
|
||||||
|
v-if="registerPassword"
|
||||||
|
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-white font-bold"
|
||||||
|
@tap="clearInput('registerPassword')"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 确认密码输入 -->
|
||||||
|
<view class="mb-8">
|
||||||
|
<view class=" flex items-center h-12 bg-gray-100 rounded-lg px-6 gap-1 border border-solid border-round-theme">
|
||||||
|
<u-icon name="lock" class="h-10" color="black" bold="true"></u-icon>
|
||||||
|
<input
|
||||||
|
class="w-full text-base text-gray-800 bg-transparent"
|
||||||
|
type="password"
|
||||||
|
placeholder="Confirm Password"
|
||||||
|
v-model="confirmPassword"
|
||||||
|
/>
|
||||||
|
<view
|
||||||
|
v-if="confirmPassword"
|
||||||
|
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-white font-bold"
|
||||||
|
@tap="clearInput('confirmPassword')"
|
||||||
|
>
|
||||||
|
×
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 注册按钮 -->
|
||||||
|
<view
|
||||||
|
class="w-full h-12 bg-theme rounded-lg text-white text-xl flex items-center justify-center"
|
||||||
|
@click="onRegister"
|
||||||
|
>
|
||||||
|
<text>SIGN UP</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 登录链接 -->
|
||||||
|
<view class="flex justify-center items-center my-8 text-gray-500 text-sm">
|
||||||
|
<text>Already have an account?</text>
|
||||||
|
<text class="text-green-500 ml-2" @click="$Router.push('/pages/login/index')">Sign in</text>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 同意条款 -->
|
||||||
|
<view class="mt-auto text-center">
|
||||||
|
<label class="flex items-center justify-center text-xs text-gray-500 leading-loose">
|
||||||
|
<checkbox
|
||||||
|
class="scale-75 mr-2"
|
||||||
|
:checked="checked"
|
||||||
|
@change="onChange"
|
||||||
|
/>
|
||||||
|
我已阅读并同意
|
||||||
|
<text class="text-green-500 underline" @tap="showAgreement">《用户协议》</text>
|
||||||
|
和
|
||||||
|
<text class="text-green-500 underline" @tap="showAgreement">《隐私政策》</text>
|
||||||
|
</label>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
@@ -182,7 +182,7 @@
|
|||||||
/**
|
/**
|
||||||
* @desc 跳转至登录页面
|
* @desc 跳转至登录页面
|
||||||
*/
|
*/
|
||||||
const toLoginPage = (productId) => {
|
const toLoginPage = () => {
|
||||||
userStore.logout()
|
userStore.logout()
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/login/index',
|
url: '/pages/login/index',
|
||||||
@@ -264,7 +264,8 @@
|
|||||||
</view>
|
</view>
|
||||||
|
|
||||||
<view class="flex flex-col justify-center items-start gap-1">
|
<view class="flex flex-col justify-center items-start gap-1">
|
||||||
<view class="font-bold text-lg text-black" @click="showPopup">{{userName}}</view>
|
<view class="font-bold text-lg text-black" v-if="!userStore.isLogin" @click="toLoginPage">login now</view>
|
||||||
|
<view class="font-bold text-lg text-black" v-if="userStore.isLogin" @click="showPopup">{{userName}}</view>
|
||||||
<view class="text-sm opacity-80 text-black">Sweekar Guardian since 2023</view>
|
<view class="text-sm opacity-80 text-black">Sweekar Guardian since 2023</view>
|
||||||
<!-- 在线状态 -->
|
<!-- 在线状态 -->
|
||||||
<view class="border-round-theme rounded-lg flex justify-center p-1 items-center">
|
<view class="border-round-theme rounded-lg flex justify-center p-1 items-center">
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ export const useUserStore = defineStore(
|
|||||||
const isLoggedIn = computed(() => isLogin.value && token.value !== '');
|
const isLoggedIn = computed(() => isLogin.value && token.value !== '');
|
||||||
|
|
||||||
// 计算属性 - 用户头像
|
// 计算属性 - 用户头像
|
||||||
const userAvatar = computed(() => userInfo.value.avatar || '/static/default-avatar.png');
|
const userAvatar = computed(() => userInfo.value.avatar || '/static/avatar.png');
|
||||||
|
|
||||||
// 计算属性 - 用户昵称
|
// 计算属性 - 用户昵称
|
||||||
const userName = computed(() => userInfo.value.nickName || userInfo.value.trueName || '游客');
|
const userName = computed(() => userInfo.value.nickName || userInfo.value.trueName || '游客');
|
||||||
|
|||||||
Reference in new issue
Block a user