207 lines
4.1 KiB
Vue
207 lines
4.1 KiB
Vue
<template>
|
||
<view class="login-container">
|
||
<view class="login-header">
|
||
<text class="app-title">强宝爱记账</text>
|
||
<text class="app-subtitle">智能记账,轻松管理</text>
|
||
</view>
|
||
|
||
<view class="login-form">
|
||
<view class="form-item">
|
||
<input
|
||
v-model="form.username"
|
||
placeholder="请输入用户名"
|
||
class="input"
|
||
maxlength="20"
|
||
/>
|
||
</view>
|
||
|
||
<view class="form-item">
|
||
<input
|
||
v-model="form.password"
|
||
placeholder="请输入密码"
|
||
type="password"
|
||
class="input"
|
||
maxlength="20"
|
||
/>
|
||
</view>
|
||
|
||
<view v-if="isRegister" class="form-item">
|
||
<input
|
||
v-model="form.nickname"
|
||
placeholder="请输入昵称(可选)"
|
||
class="input"
|
||
maxlength="20"
|
||
/>
|
||
</view>
|
||
|
||
<button class="login-btn" @click="handleSubmit" :loading="loading">
|
||
{{ isRegister ? '注册' : '登录' }}
|
||
</button>
|
||
|
||
<view class="switch-mode" @click="switchMode">
|
||
<text>{{ isRegister ? '已有账号?去登录' : '没有账号?去注册' }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { register, login } from '../../api/auth'
|
||
import { useUserStore } from '../../store/user'
|
||
|
||
const userStore = useUserStore()
|
||
|
||
const isRegister = ref(false)
|
||
const loading = ref(false)
|
||
const form = ref({
|
||
username: '',
|
||
password: '',
|
||
nickname: ''
|
||
})
|
||
|
||
const switchMode = () => {
|
||
isRegister.value = !isRegister.value
|
||
form.value = {
|
||
username: '',
|
||
password: '',
|
||
nickname: ''
|
||
}
|
||
}
|
||
|
||
const handleSubmit = async () => {
|
||
if (!form.value.username || !form.value.password) {
|
||
uni.showToast({
|
||
title: '请输入用户名和密码',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
if (isRegister.value && form.value.password.length < 6) {
|
||
uni.showToast({
|
||
title: '密码长度至少6位',
|
||
icon: 'none'
|
||
})
|
||
return
|
||
}
|
||
|
||
loading.value = true
|
||
|
||
try {
|
||
let response
|
||
if (isRegister.value) {
|
||
response = await register({
|
||
username: form.value.username,
|
||
password: form.value.password,
|
||
nickname: form.value.nickname || form.value.username
|
||
})
|
||
} else {
|
||
response = await login({
|
||
username: form.value.username,
|
||
password: form.value.password
|
||
})
|
||
}
|
||
|
||
// 保存token和用户信息
|
||
userStore.login(response.token, {
|
||
username: response.username,
|
||
nickname: response.nickname
|
||
})
|
||
|
||
uni.showToast({
|
||
title: isRegister.value ? '注册成功' : '登录成功',
|
||
icon: 'success'
|
||
})
|
||
|
||
// 跳转到首页
|
||
setTimeout(() => {
|
||
uni.switchTab({
|
||
url: '/pages/index/index'
|
||
})
|
||
}, 1500)
|
||
|
||
} catch (error) {
|
||
console.error('登录失败:', error)
|
||
uni.showToast({
|
||
title: error.message || '操作失败',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style scoped>
|
||
.login-container {
|
||
min-height: 100vh;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 40rpx;
|
||
}
|
||
|
||
.login-header {
|
||
text-align: center;
|
||
margin-bottom: 80rpx;
|
||
}
|
||
|
||
.app-title {
|
||
display: block;
|
||
font-size: 56rpx;
|
||
font-weight: bold;
|
||
color: #fff;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.app-subtitle {
|
||
display: block;
|
||
font-size: 28rpx;
|
||
color: rgba(255, 255, 255, 0.8);
|
||
}
|
||
|
||
.login-form {
|
||
width: 100%;
|
||
max-width: 600rpx;
|
||
}
|
||
|
||
.form-item {
|
||
margin-bottom: 30rpx;
|
||
}
|
||
|
||
.input {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
box-sizing: border-box;
|
||
background: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 0 30rpx;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.login-btn {
|
||
width: 100%;
|
||
height: 88rpx;
|
||
background: #fff;
|
||
color: #667eea;
|
||
border-radius: 12rpx;
|
||
font-size: 32rpx;
|
||
font-weight: bold;
|
||
margin-top: 40rpx;
|
||
border: none;
|
||
}
|
||
|
||
.switch-mode {
|
||
text-align: center;
|
||
margin-top: 40rpx;
|
||
}
|
||
|
||
.switch-mode text {
|
||
color: rgba(255, 255, 255, 0.9);
|
||
font-size: 26rpx;
|
||
}
|
||
</style>
|