Files
account/resources/mobile/pages/ucenter/login/index.vue
2026-01-18 17:42:46 +08:00

408 lines
8.1 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.
<template>
<view class="login-container">
<view class="login-content">
<!-- Logo 区域 -->
<view class="logo-section">
<image src="/static/logo.png" class="logo" mode="aspectFit"></image>
<text class="app-name">家庭记账</text>
<text class="welcome-text">欢迎使用家庭记账</text>
</view>
<!-- 表单区域 -->
<view class="form-section">
<view class="form-item">
<uni-icons type="person" size="20" color="#999"></uni-icons>
<input class="input" type="text" v-model="formData.username" placeholder="请输入用户名"
placeholder-class="input-placeholder" maxlength="30" />
</view>
<view class="form-item">
<uni-icons type="locked" size="20" color="#999"></uni-icons>
<input class="input" :type="showPassword ? 'text' : 'password'" v-model="formData.password"
placeholder="请输入密码" placeholder-class="input-placeholder" />
<uni-icons :type="showPassword ? 'eye-slash' : 'eye'" size="20" color="#999"
@tap="togglePassword"></uni-icons>
</view>
<view class="form-options">
<view class="checkbox-item" @tap="toggleRemember">
<uni-icons :type="formData.remember ? 'checkbox-filled' : 'circle'"
:color="formData.remember ? '#4CAF50' : '#999'" size="20"></uni-icons>
<text class="checkbox-text">记住密码</text>
</view>
<text class="forget-password" @tap="handleForgetPassword">忘记密码?</text>
</view>
<button class="login-btn" type="primary" @tap="handleLogin" :loading="loading">
{{ loading ? '登录中...' : '登录' }}
</button>
<view class="register-tip">
<text class="tip-text">还没有账号</text>
<text class="register-link" @tap="goToRegister">立即注册</text>
</view>
</view>
<!-- 其他登录方式 -->
<view class="other-login" v-if="false">
<view class="divider">
<text class="divider-text">其他登录方式</text>
</view>
<view class="social-login">
<view class="social-item" @tap="handleWechatLogin">
<uni-icons type="weixin" size="32" color="#07C160"></uni-icons>
<text class="social-text">微信登录</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script>
import authApi from '@/api/modules/auth'
export default {
data() {
return {
// 不需要登录验证
needLogin: false,
formData: {
username: '',
password: '',
remember: false
},
showPassword: false,
loading: false
}
},
onLoad() {
// 检查是否有记住的密码
const savedUsername = uni.getStorageSync('savedUsername')
const savedPassword = uni.getStorageSync('savedPassword')
if (savedUsername && savedPassword) {
this.formData.username = savedUsername
this.formData.password = savedPassword
this.formData.remember = true
}
},
methods: {
// 切换密码显示/隐藏
togglePassword() {
this.showPassword = !this.showPassword
},
// 切换记住密码
toggleRemember() {
this.formData.remember = !this.formData.remember
},
// 登录
async handleLogin() {
// 表单验证
if (!this.validateForm()) {
return
}
try {
this.loading = true
// 调用登录接口
const result = await authApi.login.post({
username: this.formData.username,
password: this.formData.password
})
// 保存 token 和用户信息
if (result.code == 1) {
this.$store.commit('setUserLogin', result.data)
const user = await authApi.info.get()
this.$store.commit('setUserInfo', user.data)
// 记住密码
if (this.formData.remember) {
uni.setStorageSync('savedUsername', this.formData.username)
uni.setStorageSync('savedPassword', this.formData.password)
} else {
uni.removeStorageSync('savedUsername')
uni.removeStorageSync('savedPassword')
}
uni.showToast({
title: '登录成功',
icon: 'success',
duration: 1500
})
// 跳转到首页
setTimeout(() => {
uni.switchTab({
url: '/pages/index/index'
})
}, 1500)
} else {
uni.showToast({
title: result.message,
icon: 'success',
duration: 1500
})
}
} catch (error) {
console.error('登录失败:', error)
} finally {
this.loading = false
}
},
// 表单验证
validateForm() {
const { username, password } = this.formData
if (!username) {
uni.showToast({
title: '请输入用户名',
icon: 'none',
duration: 2000
})
return false
}
if (username.length < 3) {
uni.showToast({
title: '用户名至少3个字符',
icon: 'none',
duration: 2000
})
return false
}
if (!password) {
uni.showToast({
title: '请输入密码',
icon: 'none',
duration: 2000
})
return false
}
if (password.length < 6) {
uni.showToast({
title: '密码长度不能少于6位',
icon: 'none',
duration: 2000
})
return false
}
return true
},
// 忘记密码
handleForgetPassword() {
uni.showToast({
title: '功能开发中',
icon: 'none',
duration: 2000
})
},
// 跳转到注册页
goToRegister() {
uni.navigateTo({
url: '/pages/ucenter/register/index'
})
},
// 微信登录
handleWechatLogin() {
uni.showToast({
title: '微信登录功能开发中',
icon: 'none',
duration: 2000
})
}
}
}
</script>
<style lang="scss" scoped>
.login-container {
min-height: 100vh;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
padding: 0 60rpx;
box-sizing: border-box;
}
.login-content {
padding-top: 120rpx;
}
.logo-section {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 80rpx;
.logo {
width: 160rpx;
height: 160rpx;
margin-bottom: 30rpx;
border-radius: 20rpx;
background: rgba(255, 255, 255, 0.9);
padding: 20rpx;
}
.app-name {
font-size: 48rpx;
font-weight: bold;
color: #fff;
margin-bottom: 20rpx;
}
.welcome-text {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
}
.form-section {
.form-item {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.95);
border-radius: 16rpx;
padding: 30rpx 40rpx;
margin-bottom: 30rpx;
.input {
flex: 1;
margin-left: 20rpx;
margin-right: 20rpx;
font-size: 32rpx;
color: #333;
}
.input-placeholder {
color: #999;
}
}
.form-options {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 40rpx;
padding: 0 10rpx;
.checkbox-item {
display: flex;
align-items: center;
.checkbox-text {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
margin-left: 10rpx;
}
}
.forget-password {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
}
.login-btn {
width: 100%;
height: 100rpx;
line-height: 100rpx;
border-radius: 50rpx;
background: linear-gradient(90deg, #f093fb 0%, #f5576c 100%);
color: #fff;
font-size: 36rpx;
font-weight: bold;
border: none;
box-shadow: 0 8rpx 20rpx rgba(245, 87, 108, 0.4);
margin-bottom: 40rpx;
&::after {
border: none;
}
}
.register-tip {
display: flex;
justify-content: center;
align-items: center;
.tip-text {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.9);
}
.register-link {
font-size: 28rpx;
color: #fff;
font-weight: bold;
margin-left: 10rpx;
text-decoration: underline;
}
}
}
.other-login {
margin-top: 100rpx;
.divider {
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 60rpx;
position: relative;
&::before,
&::after {
content: '';
position: absolute;
width: 200rpx;
height: 1rpx;
background: rgba(255, 255, 255, 0.3);
}
&::before {
left: 0;
}
&::after {
right: 0;
}
.divider-text {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.6);
padding: 0 20rpx;
}
}
.social-login {
display: flex;
justify-content: center;
.social-item {
display: flex;
flex-direction: column;
align-items: center;
.social-text {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.9);
margin-top: 20rpx;
}
}
}
}
</style>