login.vue 7.2 KB
<template>
	<view class="login-container">
		<image class="login-bg" src="@/static/images/start/login-bg-mob.png" mode="widthFix"></image>
		<view class="login_form">
			<view class="form-title">Login</view>
			<u-form :model="logForm" ref="logForm" labelPosition="top" label-width="auto" :labelStyle="formLabelStyle">
				<u-form-item prop="username" label="用户名">
					<u--input
						v-model="logForm.username"
						placeholder="请输入用户名"
						prefixIcon="account-fill"
						prefixIconStyle="font-size: 44rpx;color: #fff"
						:placeholderStyle="{color: '#fff'}"
						color="#fff"
						border="bottom"
						:customStyle="{ borderColor: '#fff!important' }"
					/>
				</u-form-item>
				<u-form-item prop="password" label="密码">
					<u--input 
						v-model="logForm.password"
						type="password"
						prefixIcon="lock-fill"
						:password="true"
						prefixIconStyle="font-size: 44rpx;color: #fff"
						placeholder="请输入密码"
						color="#fff"
						:placeholderStyle="{color: '#fff'}"
						border="bottom"
						:customStyle="{ borderColor: '#fff!important' }"
					/>
				</u-form-item>
				<u-form-item>
					<u-checkbox-group>
						<u-checkbox v-model="checked" shape="circle" size="mini" active-color="$uni-color-primary"></u-checkbox>
						<text class="agreement">已阅并同意《用户协议》及《隐私协议》</text>
					</u-checkbox-group>
				</u-form-item>
			</u-form>
			<view class="login_btn" @click="submit">登录</view>
			<view class="toggle_box">
				<view class="divider">切换身份</view>
				<view class="toggle_nav">
					<view v-for="(item, index) in identityList" :key="index" class="toggle_item" @click="current = index">
						<view class="icon_content">
							<view
								class="iconfont item_icon"
								:class="[item.iconName]"
								:style="{color: current == index ? '#fff' : '#4d4d4d'}"
							></view>
							<view
								class="filled" 
								:style="{
									backgroundColor: item.colorStyle,
									height: current == index ? '100%' : 0
								}"
							></view>
						</view>
						<text>{{ item.text }}</text>
					</view>
				</view>
			</view>
			<view class="tip">
				没有账号?<text style="color: #FFEB3B;" @click="goReg">去注册</text>
			</view>
		</view>
	</view>
</template>

<script>
	import { userLogin } from '@/api/user.js'
	export default {
		data() {
			return {
				logForm: { username: '', password: ''},
				checked: false,
				current: 0,
				formLabelStyle: {
					fontSize: '36rpx',
					color: '#fff',
					textAlign: 'center'
				},
				identityList: [
					{ text: '用户', iconName: 'icon-yonghu', colorStyle: '#d0b640' },
					{ text: '教练', iconName: 'icon-jiaolian', colorStyle: '#d0b640' },
					{ text: '机构', iconName: 'icon-jigou', colorStyle: '#d0b640' }
				],
				logRules: {
					username: [
						{ required: true, message: '请填写用户名', trigger: ['blur']},
						{ pattern: /^[0-9a-zA-Z]*$/g, transform(value) { return String(value) }, message: '只能包含字母或数字', trigger: 'change' },
						{ min: 4, max: 12, message: '长度在6-12个字符之间', trigger: 'change' }
					],
					password: [
						{ required: true, message: '请填写密码', trigger: ['blur']},
						// { pattern: /^(?=.*[A-Z])[a-zA-Z0-9]+$/, transform(value) { return String(value) }, message: '字母数字组成且必须包含大写字母', trigger: ['change', 'blur'] },
						{ min: 6, max: 8, message: '长度在6-16个字符之间',  trigger: ['change'] },
					]
				}
			}
		},
		// 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
		onReady() {
			this.$refs.logForm.setRules(this.logRules);
		},
		methods: {
			goReg(){
				uni.navigateTo({
					url: '/pages/register/register'
				})
			},
			// 提交登录
			submit() {
				this.$refs.logForm.validate().then(valid => {
					if (valid) {
						this.$store.dispatch('Login', this.logForm).then(res => {
							uni.switchTab({
								url: '/pages/home/home'
							})
						})
					} else {
						console.log('验证失败');
					}
				});
			}
		}
	}
</script>

<style lang="scss" scoped>
.login-container {
	position: relative;
	height: 100vh;
	font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
	.login-bg{
		width: 100%;
		max-height: 100vh;
		position: absolute;
		top: 0;
		left: 0;
	}
	.login_form{
		position: relative;
		width: 80%;
		height: 70%;
		left: 50%;
		top: 50%;
		transform: translate(-50%,-50%);
		z-index: 10;
		padding: 30rpx;
		.form-title{
			font-size: 64rpx;
			color: #fff;
			text-align: center;
			margin-bottom: 20rpx;
			font-weight: 700;
			text-shadow: 0 2px 8px rgba(0,0,0,0.3);
		}
		.agreement{
			color: #fff;
			line-height: 38rpx;
			font-size: 24rpx;
			font-weight: 600;
			font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
		}
		.login_btn{
			width: 100%;
			height: 80rpx;
			border: 1px solid #fff;
			margin: 60rpx 0 40rpx 0;
			border-radius: 20rpx;
			text-align: center;
			line-height: 80rpx;
			color: #fff;
			font-size: 40rpx;
			font-family: Verdana, Geneva, Tahoma, sans-serif;
		}
		.toggle_box{
			width: 100%;
			position: absolute;
			left: 50%;
			transform: translateX(-50%);
			bottom: 10%;
			.divider{
				position: relative;
				text-align: center;
				font-size: 28rpx;
				color: #fff;
				font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
				margin-bottom: 40rpx;
				&::before{
					content: '';
					width: 30%;
					height: 1px;
					position: absolute;
					background-color: #fff;
					left: 30rpx;
					top: 50%;
					transform: translateY(-50%);
				}
				&::after{
					content: '';
					width: 30%;
					height: 1px;
					position: absolute;
					background-color: #fff;
					right: 30rpx;
					top: 50%;
					transform: translateY(-50%);
				}
			}
		}
		.toggle_nav{
			width: 100%;
			display: flex;
			align-items: center;
			justify-content: space-around;
			padding: 0 30rpx;
			.toggle_item{
				flex: 1;
				display: flex;
				flex-direction: column;
				align-items: center;
				gap: 20rpx;
				color: #fff;
				font-size: 28rpx;
				font-family: Cambria, Cochin, Georgia, Times, 'Times New Roman', serif;
				.icon_content{
					position: relative;
					overflow: hidden;
					display: flex;
					justify-content: center;
					align-items: center;
					width: 100rpx;
					height: 100rpx;
					border-radius: 20%;
					color: #4d4d4d;
					background-color: #ffff;
					transition: all 0.3s ease-in-out;
					.filled {
						position: absolute;
						top: auto;
						bottom: 0;
						left: 0;
						width: 100%;
						height: 0;
						transition: all 0.3s ease-in-out;
					}
					.item_icon{
						position: relative;
						z-index: 1;
						font-size: 60rpx;
					}
				}
			}
		}
		.tip{
			width: 100%;
			position: absolute;
			left: 50%;
			transform: translateX(-50%);
			bottom: 40rpx;
			font-size: 28rpx;
			text-align: center;
			color: #fff;
		}
		&::before{
			position: absolute;
			top: 0;
			left: 0;
			z-index: -1;
			content: '';
			display: block;
			width: 100%;
			height: 100%;
			background: rgba(143, 143, 143, 0.25);
			box-shadow: 0 16rpx 64rpx 0 rgba(31, 38, 135, 0.37);
			backdrop-filter: blur(6rpx);
			border-radius: 40rpx;
		}
	}
}

/deep/ .input-placeholder{
	color: #fff;
}
</style>