登录功能
All checks were successful
Docker Build & Deploy / Build Docker Image (push) Successful in 30s
Docker Build & Deploy / Deploy to Production (push) Successful in 5s

This commit is contained in:
孙诚
2025-12-25 13:27:23 +08:00
parent ebb49577dd
commit 728c39f43d
16 changed files with 395 additions and 23 deletions

107
Web/src/views/LoginView.vue Normal file
View File

@@ -0,0 +1,107 @@
<template>
<div class="login-container">
<div class="login-box">
<h1 class="login-title">账单</h1>
<div class="login-form">
<van-field
v-model="password"
type="password"
placeholder="请输入密码"
clearable
:border="true"
@keyup.enter="handleLogin"
>
<template #left-icon>
<van-icon name="lock" />
</template>
</van-field>
<van-button
type="primary"
block
round
:loading="loading"
@click="handleLogin"
class="login-button"
>
登录
</van-button>
</div>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { showToast } from 'vant'
import { useAuthStore } from '@/stores/auth'
const router = useRouter()
const authStore = useAuthStore()
const password = ref('')
const loading = ref(false)
const handleLogin = async () => {
if (!password.value) {
showToast('请输入密码')
return
}
loading.value = true
try {
await authStore.login(password.value)
showToast({ type: 'success', message: '登录成功' })
router.push('/')
} catch (error) {
showToast({ type: 'fail', message: error.message || '登录失败' })
} finally {
loading.value = false
}
}
</script>
<style scoped>
.login-container {
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
}
.login-box {
width: 90%;
max-width: 400px;
border-radius: 20px;
padding: 40px 30px;
}
.login-title {
text-align: center;
font-size: 28px;
font-weight: bold;
margin-bottom: 40px;
}
.login-form {
display: flex;
flex-direction: column;
gap: 20px;
}
.login-button {
margin-top: 10px;
height: 44px;
font-size: 16px;
}
:deep(.van-field) {
border-radius: 12px;
padding: 12px 16px;
}
:deep(.van-field__control) {
font-size: 15px;
}
</style>

View File

@@ -18,14 +18,25 @@
<van-cell-group inset>
<van-cell title="智能分类" is-link />
</van-cell-group>
<div class="detail-header">
<p>账户</p>
</div>
<van-cell-group inset>
<van-cell title="退出登录" is-link @click="handleLogout" />
</van-cell-group>
</div>
</template>
<script setup>
import { ref } from 'vue'
import { showLoadingToast, showSuccessToast, showToast, closeToast } from 'vant'
import { useRouter } from 'vue-router'
import { showLoadingToast, showSuccessToast, showToast, closeToast, showConfirmDialog } from 'vant'
import { uploadBillFile } from '@/api/billImport'
import { useAuthStore } from '@/stores/auth'
const router = useRouter()
const authStore = useAuthStore()
const fileInputRef = ref(null)
const currentType = ref('')
@@ -89,6 +100,25 @@ const handleFileChange = async (event) => {
event.target.value = ''
}
}
/**
* 处理退出登录
*/
const handleLogout = async () => {
try {
await showConfirmDialog({
title: '提示',
message: '确定要退出登录吗?',
})
authStore.logout()
showSuccessToast('已退出登录')
router.push({ name: 'login' })
} catch (error) {
console.error('取消退出登录:', error)
showToast('已取消退出登录')
}
}
</script>
<style scoped>