Files
sweekar-app/pages/login/index.vue
T
2026-01-21 11:31:56 +08:00

257 lines
6.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { ref } from 'vue';
import { loginByEmail } from './api';
import { useUserStore } from '@/store/user.js';
const email = ref(''); // 邮箱
const password = ref(''); // 密码
const checked = ref(true); // 同意条款,默认勾选
const isLoading = ref(false); // 加载状态
const userStore = useUserStore();
// 邮箱格式验证
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
// 登录函数
const onLogin = async() => {
if (!checked.value) {
uni.showToast({
title: 'Please agree to the user agreement',
icon: 'none',
duration: 2000,
});
return;
}
if (!email.value) {
uni.showToast({
title: 'Please enter email',
icon: 'none',
});
return;
}
if (!password.value) {
uni.showToast({
title: 'Please enter password',
icon: 'none',
});
return;
}
// 邮箱格式验证
if (!validateEmail(email.value)) {
uni.showToast({
title: 'Please enter a valid email',
icon: 'none',
});
return;
}
// 密码长度验证
if (password.value.length < 6) {
uni.showToast({
title: 'Password must be at least 6 characters',
icon: 'none',
});
return;
}
// 防止重复提交
if (isLoading.value) return;
isLoading.value = true;
try {
uni.showLoading({
title: 'Logging in...',
mask: true,
});
const params = {
email: email.value,
password: password.value
};
const res = await loginByEmail(params);
if (res && res.code === 0) { // 修改为code===0判断
// 存储用户信息到全局状态
userStore.setUserInfo(res.data);
userStore.setToken(res.data.accessToken);
userStore.setLoginStatus(true);
uni.showToast({
title: 'Login successful',
icon: 'success',
});
uni.switchTab({
url:'/pages/mine/index'
})
} else {
uni.showToast({
title: res.msg || 'Login failed',
icon: 'error',
});
}
} catch (error) {
console.error('Login error:', error);
uni.showToast({
title: error.message || 'Login failed, please try again',
icon: 'error',
});
} finally {
uni.hideLoading();
isLoading.value = false;
}
};
// 同意条款切换
const onChange = (e) => {
checked.value = e.detail.value; // 更新checked值
};
// 显示用户协议
const showAgreement = () => {
uni.showModal({
title: 'User Agreement',
content: 'Welcome to our service!\n\nThis agreement sets forth the terms and conditions for your use of our services, please read carefully.\n\n1. Terms of Service\n2. Privacy Policy\n3. Account Security\n4. Disclaimer\n\nContinuing to use means you agree to comply with these terms.',
showCancel: true,
confirmText: 'Agree',
cancelText: 'Cancel',
success: (res) => {
if (res.confirm) {
checked.value = true;
}
}
});
};
// 忘记密码
const forgetPassword = function() {
uni.navigateTo({
url: '/pages/login/changePassword'
});
};
//跳转到注册页面
const goRegisterPage = function() {
uni.navigateTo({
url:'/pages/login/register'
})
}
// 清空输入框
const clearInput = (type) => {
if (type === 'email') {
email.value = '';
} else if (type === 'password') {
password.value = '';
}
};
// 监听输入变化,清除错误状态
const onInputChange = (type) => {
if (type === 'email') {
// 移除邮箱错误状态
} else if (type === 'password') {
// 移除密码错误状态
}
};
</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">WELCOME BACK</text>
<text class="text-sm text-gray-500">Sign in to connect with Sweekar</text>
</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="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="email"
@input="onInputChange('email')"
/>
<view
v-if="email"
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-black font-bold"
@tap="clearInput('email')"
>
×
</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="Password"
v-model="password"
@input="onInputChange('password')"
/>
<view
v-if="password"
class="absolute right-6 w-8 h-8 flex items-center justify-center bg-gray-400 rounded-full text-white font-bold"
@tap="clearInput('password')"
>
×
</view>
</view>
</view>
<!-- 忘记密码链接 -->
<view class="flex justify-end mb-8">
<text class="text-blue-500 text-sm" @tap="forgetPassword">Forget Password?</text>
</view>
<!-- 登录按钮 -->
<view
class="w-full h-12 bg-theme rounded-lg text-white text-xl flex items-center justify-center "
:disabled="isLoading"
@click="onLogin"
>
<text v-if="!isLoading">SIGN IN</text>
<view v-else class="w-8 h-8 border-2 border-white border-t-transparent rounded-full animate-spin"></view>
</view>
<!-- 注册链接 -->
<view class="flex justify-center items-center my-8 text-gray-500 text-sm">
<text>Don't have an account?</text>
<text class="text-green-500 ml-2" @tap="goRegisterPage">Create one</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"
/>
I have read and agree to the
<text class="text-green-500 underline" @tap="showAgreement"> User Agreement</text>
and
<text class="text-green-500 underline" @tap="showAgreement"> Privacy Policy</text>
</label>
</view>
</view>
</template>