login.vue 6.89 KB
<template>
	<view class="login-container">
		<!-- 状态栏占位 -->
		<view class="status-bar" :style="{ height: statusBarHeight + 'px' }"></view>
		
		<!-- 登录卡片容器 -->
		<view class="login-card">
			<!-- 头部区域 -->
			<view class="login-header">
				<view class="title">绿纤协同平台</view>
				<view class="subtitle">用户登录</view>
			</view>
			
			<!-- 登录表单 -->
			<view class="login-form">
				<view class="form-group">
					<view class="form-label">用户名</view>
					<view class="input-wrapper">
						<u-icon name="account" size="20" color="#6a9c6a" class="input-icon"></u-icon>
						<u-input 
							v-model="formData.username" 
							placeholder="请输入用户名"
							:clearable="true"
							border="none"
							class="custom-input"
						></u-input>
					</view>
				</view>
				
				<view class="form-group">
					<view class="form-label">密码</view>
					<view class="input-wrapper">
						<u-icon name="lock" size="20" color="#6a9c6a" class="input-icon"></u-icon>
						<u-input 
							v-model="formData.password" 
							placeholder="请输入密码"
							:password="!showPassword"
							:clearable="true"
							border="none"
							class="custom-input"
						></u-input>
						<u-icon 
							:name="showPassword ? 'eye-off' : 'eye'" 
							size="20" 
							color="#6a9c6a"
							@click="togglePassword"
							class="password-toggle"
						></u-icon>
					</view>
				</view>
				
				<view class="form-actions">
				<!-- 	type="success"
					:loading="loading" -->
					<button 
					
						:disabled="loading"
						@click="handleLogin"
						class="login-btn"
					>
						{{ loading ? '登录中...' : '登录' }}
					</button>
				</view>
			</view>
		</view>
		
		<!-- 底部信息 -->
		<view class="footer">
			<view class="footer-text">绿纤协同办公平台 v1.0.0</view>
		</view>
	</view>
</template>

<script>
import md5 from '@/service/md5.js'
export default {
	data() {
		return {
			statusBarHeight: 0,
			loading: false,
			showPassword: false,
			formData: {
				username: '',
				password: ''
			}
		}
	},
	
	onLoad() {
		this.getSystemInfo()
	},
	methods: {
		// 获取系统信息
		getSystemInfo() {
			uni.getSystemInfo({
				success: (res) => {
					this.statusBarHeight = res.statusBarHeight
				}
			})
		},
		// 切换密码显示
		togglePassword() {
			this.showPassword = !this.showPassword
		},
		
		// 表单验证
		validateForm() {
			if (!this.formData.username.trim()) {
				uni.showToast({
					title: '请输入用户名',
					icon: 'none'
				})
				return false
			}
			
			if (!this.formData.password.trim()) {
				uni.showToast({
					title: '请输入密码',
					icon: 'none'
				})
				return false
			}
			
			return true
		},
		async getuser(){
			await this.API.getCurrentUser().then(res=>{
				console.error(res)
				if(res.code === 200){
					let date = new Date();
					uni.setStorageSync('userInfo', res.data.userInfo)
				}
			})
		},
		// 处理登录
		async handleLogin() {
			if (!this.validateForm()) {
				return
			}
			
			this.loading = true
			
			try {
				// 对密码进行MD5加密
				const password = md5.hex_md5(this.formData.password)
				const res = await this.API.AppLogin({
					account: this.formData.username,
					password: password
				})
				
				if (res.code === 200 || res.success) {
					// 登录成功
					const { token} = res.data
					
					// 保存token和用户信息
					uni.setStorageSync('token', token)
					await this.getuser()
					uni.showToast({
						title: '登录成功',
						icon: 'success'
					})

					// 延迟跳转
					setTimeout(() => {
						uni.reLaunch({
							url: '/pages/index/index'
						})
					}, 1500)
					
				} else {
					// 登录失败
					uni.showToast({
						title: res.message || '登录失败,请重试',
						icon: 'none'
					})
				}
				
			} catch (error) {
				console.error('登录失败:', error)
				uni.showToast({
					title: '网络错误,请稍后重试',
					icon: 'none'
				})
			} finally {
				this.loading = false
			}
		}
	}
}
</script>

<style lang="scss" scoped>
.login-container {
	min-height: 100vh;
	background: linear-gradient(135deg, #e8f5e9 0%, #b2dfdb 100%);
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	padding: 40rpx;
}

.status-bar {
	background: linear-gradient(120deg, #43e97b 0%, #38f9d7 100%);
}

.login-card {
	width: 100%;
	max-width: 840rpx;
	background: #fff;
	border-radius: 36rpx;
	box-shadow: 0 8rpx 48rpx 0 rgba(76, 175, 80, 0.10), 0 3rpx 12rpx 0 rgba(76, 175, 80, 0.08);
	border: 3rpx solid #c8e6c9;
	overflow: hidden;
}

.login-header {
	background: linear-gradient(120deg, #43e97b 0%, #38f9d7 100%);
	padding: 64rpx 48rpx 48rpx 48rpx;
	text-align: center;
	position: relative;
}

.login-header::after {
	content: '';
	position: absolute;
	bottom: -40rpx;
	left: 50%;
	transform: translateX(-50%);
	width: 80rpx;
	height: 80rpx;
	background: #fff;
	border-radius: 50%;
	box-shadow: 0 4rpx 24rpx 0 rgba(67, 233, 123, 0.08);
}

.title {
	color: #fff;
	font-size: 56rpx;
	font-weight: bold;
	letter-spacing: 4rpx;
	margin-bottom: 16rpx;
}

.subtitle {
	color: #e0f2f1;
	font-size: 30rpx;
	margin-bottom: 0;
}

.login-form {
	padding: 80rpx 48rpx 64rpx 48rpx;
}

.form-group {
	margin-bottom: 40rpx;
}

.form-group:last-child {
	margin-bottom: 0;
}

.form-label {
	display: block;
	margin-bottom: 16rpx;
	font-weight: bold;
	color: #388e3c;
	letter-spacing: 2rpx;
	font-size: 30rpx;
}

.input-wrapper {
	position: relative;
	display: flex;
	align-items: center;
	background: #f9fff9;
	border: 3rpx solid #c8e6c9;
	border-radius: 20rpx;
	padding: 0 24rpx;
	height: 88rpx;
	transition: all 0.2s ease;
}

.input-wrapper:focus-within {
	border-color: #43a047;
	box-shadow: 0 0 0 6rpx rgba(67, 233, 123, 0.15);
	background: #fff;
}

.input-icon {
	position: absolute;
	left: 24rpx;
	z-index: 2;
}

.custom-input {
	flex: 1;
	margin: 0 16rpx 0 80rpx;
}

.password-toggle {
	position: absolute;
	right: 24rpx;
	z-index: 2;
}

.form-actions {
	margin-top: 16rpx;
}

.login-btn {
	width: 100%;
	height: 88rpx;
	background: linear-gradient(90deg, #43a047 60%, #66bb6a 100%);
	border-radius: 20rpx;
	font-size: 34rpx;
	font-weight: bold;
	letter-spacing: 4rpx;
	box-shadow: 0 4rpx 16rpx #a5d6a7;
	transition: all 0.2s ease;
	color: #fff;
}

.login-btn:active {
	background: linear-gradient(90deg, #388e3c 60%, #43a047 100%);
	box-shadow: 0 8rpx 32rpx #a5d6a7;
	transform: translateY(-2rpx);
	color: #fff;
}

.login-btn:disabled {
	background: #ccc;
	cursor: not-allowed;
	transform: none;
	box-shadow: none;
	color: #fff;
}

.footer {
	text-align: center;
	padding: 40rpx;
	margin-top: 40rpx;
}

.footer-text {
	color: #6a9c6a;
	font-size: 24rpx;
	opacity: 0.8;
}

/* 移动端适配 */
// @media (max-width: 750rpx) {
// 	.login-container {
// 		padding: 32rpx;
// 	}
	
// 	.login-header {
// 		padding: 48rpx 40rpx 40rpx 40rpx;
// 	}
	
// 	.login-form {
// 		padding: 64rpx 40rpx 48rpx 40rpx;
// 	}
	
// 	.title {
// 		font-size: 52rpx;
// 	}
// }
</style>