|
|
<template>
|
|
|
<view class="login-container">
|
|
|
<!-- 背景图片 -->
|
|
|
<image src="/static/cancel_bg.png" class="background-image" mode="aspectFill"></image>
|
|
|
|
|
|
<!-- 标题区域 -->
|
|
|
<view class="login-header">
|
|
|
<view class="header-content">
|
|
|
<image src="/static/logo-index.png" class="header-logo" mode="aspectFit"></image>
|
|
|
<view class="header-text">
|
|
|
<text class="welcome-title">Hello!</text>
|
|
|
<text class="welcome-subtitle">欢迎登录访客管理系统</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 登录表单 -->
|
|
|
<view class="login-form">
|
|
|
<view class="form-item">
|
|
|
<view class="input-wrapper">
|
|
|
<image src="/static/username.png" class="input-icon" mode="aspectFit"></image>
|
|
|
<view class="input-divider"></view>
|
|
|
<input
|
|
|
v-model="form.username"
|
|
|
placeholder="请输入用户名"
|
|
|
class="form-input"
|
|
|
:disabled="loading"
|
|
|
@input="clearError" />
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<view class="form-item">
|
|
|
<view class="input-wrapper">
|
|
|
<image src="/static/pwd.png" class="input-icon" mode="aspectFit"></image>
|
|
|
<view class="input-divider"></view>
|
|
|
<input
|
|
|
v-model="form.password"
|
|
|
placeholder="请输入密码"
|
|
|
password
|
|
|
class="form-input"
|
|
|
:disabled="loading"
|
|
|
@input="clearError"
|
|
|
@confirm="handleLogin" />
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<view v-if="errorMsg" class="error-message">
|
|
|
<text>{{ errorMsg }}</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
|
|
|
<!-- 登录按钮 -->
|
|
|
<view class="login-actions">
|
|
|
<button
|
|
|
@click="handleLogin"
|
|
|
class="login-btn"
|
|
|
:class="{ 'loading': loading }"
|
|
|
:disabled="loading">
|
|
|
{{ loading ? '登录中...' : '立即登录' }}
|
|
|
</button>
|
|
|
</view>
|
|
|
|
|
|
<view class="footer">
|
|
|
<text class="copyright">© BD管理系统</text>
|
|
|
</view>
|
|
|
</view>
|
|
|
</template>
|
|
|
|
|
|
<script>
|
|
|
export default {
|
|
|
data() {
|
|
|
return {
|
|
|
form: {
|
|
|
username: '',
|
|
|
password: ''
|
|
|
},
|
|
|
loading: false,
|
|
|
errorMsg: ''
|
|
|
}
|
|
|
},
|
|
|
|
|
|
onLoad() {
|
|
|
// 检查是否已经登录
|
|
|
this.checkLoginStatus()
|
|
|
},
|
|
|
|
|
|
methods: {
|
|
|
// 检查登录状态
|
|
|
checkLoginStatus() {
|
|
|
try {
|
|
|
const lifeData = uni.getStorageSync('mkwcancel_lifeData')
|
|
|
if (lifeData && lifeData.vuex_token) {
|
|
|
// 已登录,直接跳转
|
|
|
uni.reLaunch({
|
|
|
url: '/pages/index/index'
|
|
|
})
|
|
|
}
|
|
|
} catch (e) {
|
|
|
console.error('检查登录状态失败:', e)
|
|
|
}
|
|
|
},
|
|
|
|
|
|
// 清除错误信息
|
|
|
clearError() {
|
|
|
this.errorMsg = ''
|
|
|
},
|
|
|
|
|
|
// 表单验证
|
|
|
validateForm() {
|
|
|
if (!this.form.username.trim()) {
|
|
|
this.errorMsg = '请输入用户名'
|
|
|
return false
|
|
|
}
|
|
|
if (!this.form.password.trim()) {
|
|
|
this.errorMsg = '请输入密码'
|
|
|
return false
|
|
|
}
|
|
|
if (this.form.username.length < 2) {
|
|
|
this.errorMsg = '用户名至少2个字符'
|
|
|
return false
|
|
|
}
|
|
|
if (this.form.password.length < 4) {
|
|
|
this.errorMsg = '密码至少4个字符'
|
|
|
return false
|
|
|
}
|
|
|
return true
|
|
|
},
|
|
|
|
|
|
// 登录处理
|
|
|
async handleLogin() {
|
|
|
if (this.loading) return
|
|
|
|
|
|
if (!this.validateForm()) {
|
|
|
return
|
|
|
}
|
|
|
|
|
|
this.loading = true
|
|
|
this.errorMsg = ''
|
|
|
|
|
|
try {
|
|
|
// 调用登录接口
|
|
|
const loginRes = await this.$u.api.login({
|
|
|
username: this.form.username,
|
|
|
password: this.form.password
|
|
|
})
|
|
|
|
|
|
console.log('登录结果:', loginRes)
|
|
|
|
|
|
if (loginRes && loginRes.access_token) {
|
|
|
// 登录成功,存储access_token
|
|
|
const token = loginRes.access_token
|
|
|
|
|
|
// 存储到vuex和本地存储
|
|
|
this.$u.vuex('vuex_token', token)
|
|
|
|
|
|
// 获取用户信息
|
|
|
try {
|
|
|
const userRes = await this.$u.api.user()
|
|
|
console.log('用户信息:', userRes)
|
|
|
|
|
|
if (userRes && userRes) {
|
|
|
// 存储用户信息
|
|
|
this.$u.vuex('vuex_user', userRes)
|
|
|
|
|
|
// 登录成功提示
|
|
|
uni.showToast({
|
|
|
title: '登录成功',
|
|
|
icon: 'success'
|
|
|
})
|
|
|
|
|
|
// 延迟跳转,让用户看到成功提示
|
|
|
setTimeout(() => {
|
|
|
uni.reLaunch({
|
|
|
url: '/pages/index/index'
|
|
|
})
|
|
|
}, 1500)
|
|
|
|
|
|
} else {
|
|
|
this.errorMsg = userRes?.errmsg || '获取用户信息失败'
|
|
|
// 清除token
|
|
|
this.$u.vuex('vuex_token', '')
|
|
|
}
|
|
|
} catch (userError) {
|
|
|
console.error('获取用户信息失败:', userError)
|
|
|
this.errorMsg = '获取用户信息失败,请重试'
|
|
|
// 清除token
|
|
|
this.$u.vuex('vuex_token', '')
|
|
|
}
|
|
|
|
|
|
} else {
|
|
|
this.errorMsg = loginRes?.errmsg || '登录失败,请检查用户名和密码'
|
|
|
}
|
|
|
|
|
|
} catch (error) {
|
|
|
console.error('登录失败:', error)
|
|
|
this.errorMsg = '网络错误,请检查网络连接后重试'
|
|
|
} finally {
|
|
|
this.loading = false
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
.login-container {
|
|
|
min-height: 100vh;
|
|
|
position: relative;
|
|
|
width: 100%;
|
|
|
padding: 40rpx;
|
|
|
box-sizing: border-box;
|
|
|
}
|
|
|
|
|
|
.background-image {
|
|
|
position: absolute;
|
|
|
top: 0;
|
|
|
left: 0;
|
|
|
width: 100%;
|
|
|
height: 100%;
|
|
|
z-index: 0;
|
|
|
object-fit: cover;
|
|
|
}
|
|
|
|
|
|
.login-header {
|
|
|
position: absolute;
|
|
|
top: 10%;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
z-index: 1;
|
|
|
|
|
|
.header-content {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
|
|
|
.header-logo {
|
|
|
width: 80rpx;
|
|
|
height: 80rpx;
|
|
|
margin-right: 24rpx;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
width: 64rpx;
|
|
|
height: 64rpx;
|
|
|
margin-right: 20rpx;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.header-text {
|
|
|
display: flex;
|
|
|
flex-direction: column;
|
|
|
|
|
|
.welcome-title {
|
|
|
font-size: 64rpx;
|
|
|
font-weight: bold;
|
|
|
color: #333;
|
|
|
margin-bottom: 8rpx;
|
|
|
line-height: 1;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
font-size: 48rpx;
|
|
|
color: #fff;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.welcome-subtitle {
|
|
|
font-size: 32rpx;
|
|
|
color: #333;
|
|
|
line-height: 1;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
font-size: 28rpx;
|
|
|
color: #fff;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.login-form {
|
|
|
width: 100%;
|
|
|
max-width: 600rpx;
|
|
|
position: absolute;
|
|
|
top: 50%;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
z-index: 1;
|
|
|
|
|
|
.form-item {
|
|
|
margin-bottom: 40rpx;
|
|
|
|
|
|
&:last-child {
|
|
|
margin-bottom: 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.input-wrapper {
|
|
|
display: flex;
|
|
|
align-items: center;
|
|
|
background: #f0f0f0;
|
|
|
border-radius: 44rpx;
|
|
|
padding: 0 24rpx;
|
|
|
border: none;
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
&:focus-within {
|
|
|
background: #ffffff;
|
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
|
|
|
}
|
|
|
|
|
|
.input-icon {
|
|
|
width: 36rpx;
|
|
|
height: 36rpx;
|
|
|
margin-right: 20rpx;
|
|
|
opacity: 0.7;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
width: 32rpx;
|
|
|
height: 32rpx;
|
|
|
margin-right: 16rpx;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.input-divider {
|
|
|
width: 2rpx;
|
|
|
height: 60rpx;
|
|
|
background-color: #d0d0d0;
|
|
|
margin-right: 20rpx;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
height: 50rpx;
|
|
|
margin-right: 16rpx;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
border-radius: 40rpx;
|
|
|
}
|
|
|
|
|
|
.form-input {
|
|
|
flex: 1;
|
|
|
height: 88rpx;
|
|
|
font-size: 32rpx;
|
|
|
color: #333;
|
|
|
background: transparent;
|
|
|
border: none;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
height: 80rpx;
|
|
|
font-size: 28rpx;
|
|
|
}
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
height: 100rpx;
|
|
|
font-size: 36rpx;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.error-message {
|
|
|
background: #fef0f0;
|
|
|
border: 1rpx solid #fcdcdc;
|
|
|
border-radius: 8rpx;
|
|
|
padding: 20rpx 24rpx;
|
|
|
margin-bottom: 30rpx;
|
|
|
|
|
|
text {
|
|
|
color: #f56c6c;
|
|
|
font-size: 26rpx;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
font-size: 24rpx;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.login-actions {
|
|
|
position: absolute;
|
|
|
top: 75%;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
z-index: 1;
|
|
|
width: 100%;
|
|
|
max-width: 600rpx;
|
|
|
|
|
|
.login-btn {
|
|
|
width: 100%;
|
|
|
height: 88rpx;
|
|
|
background: #18284b;
|
|
|
color: #ffffff;
|
|
|
border: none;
|
|
|
border-radius: 44rpx;
|
|
|
font-size: 32rpx;
|
|
|
font-weight: 600;
|
|
|
transition: all 0.3s ease;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
height: 80rpx;
|
|
|
font-size: 28rpx;
|
|
|
border-radius: 40rpx;
|
|
|
}
|
|
|
|
|
|
@media (min-width: 768px) {
|
|
|
height: 100rpx;
|
|
|
font-size: 36rpx;
|
|
|
}
|
|
|
|
|
|
&:not(:disabled):active {
|
|
|
transform: translateY(2rpx);
|
|
|
box-shadow: 0 4rpx 12rpx rgba(0, 69, 147, 0.3);
|
|
|
}
|
|
|
|
|
|
&:disabled {
|
|
|
opacity: 0.6;
|
|
|
cursor: not-allowed;
|
|
|
}
|
|
|
|
|
|
&.loading {
|
|
|
background: #c0c4cc;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.footer {
|
|
|
text-align: center;
|
|
|
position: absolute;
|
|
|
bottom: 8%;
|
|
|
left: 50%;
|
|
|
transform: translateX(-50%);
|
|
|
z-index: 1;
|
|
|
width: 100%;
|
|
|
|
|
|
.copyright {
|
|
|
font-size: 24rpx;
|
|
|
color: #666666;
|
|
|
|
|
|
@media (max-width: 750px) {
|
|
|
font-size: 22rpx;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
/* 响应式优化 */
|
|
|
@media (max-width: 750px) {
|
|
|
.login-container {
|
|
|
padding: 20rpx;
|
|
|
}
|
|
|
|
|
|
.login-card {
|
|
|
padding: 40rpx 30rpx;
|
|
|
}
|
|
|
|
|
|
.login-header {
|
|
|
margin-bottom: 40rpx;
|
|
|
}
|
|
|
|
|
|
.login-actions {
|
|
|
margin-top: 40rpx;
|
|
|
}
|
|
|
}
|
|
|
</style> |