提交 2a2d7e73 作者: 吴佳伟

fix: 优化登录页面样式

上级 77b370ed
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
const readConfirmShow = ref<boolean>(false) const readConfirmShow = ref<boolean>(false)
const form = ref() const form = ref()
const showSlide = ref(false) const showSlide = ref(false)
const loginMode = ref(1) // 1: 验证码登录, 2: 密码登录
const slideType = ref<'sms' | 'login'>('login') const slideType = ref<'sms' | 'login'>('login')
...@@ -71,35 +70,8 @@ ...@@ -71,35 +70,8 @@
], ],
}, },
], ],
pwdLoginRules: [
{
name: 'username',
rule: ['required'],
msg: ['请输入账号'],
},
{
name: 'password',
rule: ['required'],
msg: ['请输入密码'],
},
{
name: 'read',
validator: [
{
msg: '请阅读并同意服务协议和隐私政策',
method: (value: boolean) => {
if (!value) {
readConfirmShow.value = true
}
return value
},
},
],
},
],
data: { data: {
username: '', username: '',
password: '',
code: '', code: '',
read: false, read: false,
}, },
...@@ -110,17 +82,11 @@ ...@@ -110,17 +82,11 @@
if (isDevMode()) { if (isDevMode()) {
model.form.data.username = 'admin' model.form.data.username = 'admin'
model.form.data.password = 'Yiring=2026#@!'
model.form.data.read = true model.form.data.read = true
} }
function switchMode(mode: number) {
loginMode.value = mode
}
function login() { function login() {
const rules = loginMode.value === 1 ? model.form.codeLoginRules : model.form.pwdLoginRules form?.value.validator(model.form.data, model.form.codeLoginRules).then(async (res: { isPassed: boolean }) => {
form?.value.validator(model.form.data, rules).then(async (res: { isPassed: boolean }) => {
if (res.isPassed) { if (res.isPassed) {
// 登录前先做滑动验证 (Requirement 7) // 登录前先做滑动验证 (Requirement 7)
slideType.value = 'login' slideType.value = 'login'
...@@ -132,7 +98,8 @@ ...@@ -132,7 +98,8 @@
function smsCode() { function smsCode() {
form?.value.validator(model.form.data, model.form.phoneRules).then(async (res: { isPassed: boolean }) => { form?.value.validator(model.form.data, model.form.phoneRules).then(async (res: { isPassed: boolean }) => {
if (res.isPassed) { if (res.isPassed) {
if (model.countdown > 0) return if (model.countdown > 0)
return
slideType.value = 'sms' slideType.value = 'sms'
showSlide.value = true showSlide.value = true
} }
...@@ -165,7 +132,6 @@ ...@@ -165,7 +132,6 @@
function doLogin() { function doLogin() {
model.loading = true model.loading = true
if (loginMode.value === 1) {
// 验证码登录 // 验证码登录
const params = { const params = {
mobile: model.form.data.username, mobile: model.form.data.username,
...@@ -174,16 +140,6 @@ ...@@ -174,16 +140,6 @@
API.phoneLogin(params) API.phoneLogin(params)
.then(handleLoginSuccess) .then(handleLoginSuccess)
.finally(() => (model.loading = false)) .finally(() => (model.loading = false))
} else {
// 密码登录
const params = {
username: model.form.data.username,
password: model.form.data.password,
}
API.sysLogin(params)
.then(handleLoginSuccess)
.finally(() => (model.loading = false))
}
} }
async function handleLoginSuccess(body: any) { async function handleLoginSuccess(body: any) {
...@@ -199,7 +155,8 @@ ...@@ -199,7 +155,8 @@
} }
function startCountdown() { function startCountdown() {
if (countdownTimer) clearInterval(countdownTimer) if (countdownTimer)
clearInterval(countdownTimer)
model.countdown = 60 model.countdown = 60
countdownTimer = setInterval(() => { countdownTimer = setInterval(() => {
model.countdown-- model.countdown--
...@@ -248,7 +205,7 @@ ...@@ -248,7 +205,7 @@
<!-- 顶部设计:数智化农场全景感 --> <!-- 顶部设计:数智化农场全景感 -->
<view class="header-visual"> <view class="header-visual">
<image class="header-scene" src="/static/images/login/farm_base_bg.png" mode="aspectFill" /> <image class="header-scene" src="/static/images/login/farm_base_bg.png" mode="aspectFill" />
<view class="header-overlay"></view> <view class="header-overlay" />
<!-- 顶部装饰元素:漂浮的气象/农业设备(体现数智感) --> <!-- 顶部装饰元素:漂浮的气象/农业设备(体现数智感) -->
<image class="float-icon device-1" src="/static/images/nongchang/device1.png" mode="aspectFit" /> <image class="float-icon device-1" src="/static/images/nongchang/device1.png" mode="aspectFit" />
...@@ -259,10 +216,6 @@ ...@@ -259,10 +216,6 @@
<view class="close-btn" @click="goHome"> <view class="close-btn" @click="goHome">
<fui-icon name="close" :size="48" color="#fff" /> <fui-icon name="close" :size="48" color="#fff" />
</view> </view>
<view class="switch-action" @click="switchMode(loginMode === 1 ? 2 : 1)">
<text>{{ loginMode === 1 ? '密码登录' : '验证码登录' }}</text>
<fui-icon name="arrowright" :size="24" color="#fff" />
</view>
</view> </view>
<!-- 品牌标识与数智概览 --> <!-- 品牌标识与数智概览 -->
...@@ -286,17 +239,17 @@ ...@@ -286,17 +239,17 @@
<fui-form ref="form" top="0" :padding="['0', '0']" background="transparent"> <fui-form ref="form" top="0" :padding="['0', '0']" background="transparent">
<view class="card-header"> <view class="card-header">
<text class="welcome-text">您好,欢迎登录</text> <text class="welcome-text">您好,欢迎登录</text>
<view class="green-line"></view> <view class="green-line" />
</view> </view>
<!-- 输入区域 --> <!-- 输入区域 -->
<view class="input-fields"> <view class="input-fields">
<view class="field-item"> <view class="field-item">
<text class="field-label">{{ loginMode === 1 ? '手机号' : '账号' }}</text> <text class="field-label">手机号</text>
<fui-input <fui-input
v-model="model.form.data.username" v-model="model.form.data.username"
:padding="['24rpx', '0']" :padding="['24rpx', '0']"
:placeholder="loginMode === 1 ? '请输入手机号' : '请输入账号'" placeholder="请输入手机号"
backgroundColor="transparent" backgroundColor="transparent"
borderColor="#F0F0F0" borderColor="#F0F0F0"
borderBottom borderBottom
...@@ -305,7 +258,7 @@ ...@@ -305,7 +258,7 @@
/> />
</view> </view>
<view class="field-item" v-if="loginMode === 1"> <view class="field-item">
<text class="field-label">验证码</text> <text class="field-label">验证码</text>
<view class="code-inner"> <view class="code-inner">
<fui-input <fui-input
...@@ -324,21 +277,6 @@ ...@@ -324,21 +277,6 @@
</view> </view>
</view> </view>
</view> </view>
<view class="field-item" v-if="loginMode === 2">
<text class="field-label">密码</text>
<fui-input
v-model="model.form.data.password"
type="password"
:padding="['24rpx', '0']"
placeholder="请输入密码"
backgroundColor="transparent"
borderColor="#F0F0F0"
borderBottom
height="110rpx"
size="34"
/>
</view>
</view> </view>
<!-- 登录决策 --> <!-- 登录决策 -->
...@@ -371,7 +309,11 @@ ...@@ -371,7 +309,11 @@
@change="(e) => (model.form.data.read = e.checked)" @change="(e) => (model.form.data.read = e.checked)"
/> />
<view class="policy-text"> <view class="policy-text">
同意<text class="link" @click.stop="Link.to(Link.services, '服务协议')">《服务协议》</text>与<text class="link" @click.stop="Link.to(Link.privacy, '隐私政策')">《隐私政策》</text> 同意<text class="link" @click.stop="Link.to(Link.services, '服务协议')"
>《服务协议》</text
><text class="link" @click.stop="Link.to(Link.privacy, '隐私政策')"
>《隐私政策》</text
>
</view> </view>
</fui-label> </fui-label>
</fui-checkbox-group> </fui-checkbox-group>
...@@ -381,13 +323,16 @@ ...@@ -381,13 +323,16 @@
</view> </view>
<!-- 装饰底部:泥土与天空的呼应 --> <!-- 装饰底部:泥土与天空的呼应 -->
<view class="footer-aesthetic"></view> <view class="footer-aesthetic" />
<!-- 功能弹窗 --> <!-- 功能弹窗 -->
<fui-modal <fui-modal
:show="readConfirmShow" :show="readConfirmShow"
title="服务协议及隐私保护" title="服务协议及隐私保护"
:buttons="[{ text: '不同意', plain: true }, { text: '同意', plain: false, color: '#fff' }]" :buttons="[
{ text: '不同意', plain: true },
{ text: '同意', plain: false, color: '#fff' },
]"
@click="onReadConfirm" @click="onReadConfirm"
> >
<view class="modal-notice"> <view class="modal-notice">
...@@ -403,6 +348,19 @@ ...@@ -403,6 +348,19 @@
</template> </template>
<style lang="less" scoped> <style lang="less" scoped>
@keyframes float-slow {
0%,
100% {
transform: translateY(0) rotate(15deg);
}
50% {
transform: translateY(-20rpx) rotate(10deg);
}
}
.login-page { .login-page {
min-height: 100vh; min-height: 100vh;
background-color: #f7faf8; background-color: #f7faf8;
...@@ -433,14 +391,14 @@ ...@@ -433,14 +391,14 @@
height: 100%; height: 100%;
top: 0; top: 0;
left: 0; left: 0;
background: linear-gradient(180deg, rgba(93, 182, 111, 0.4) 0%, rgba(76, 175, 80, 0.8) 100%); background: linear-gradient(180deg, rgb(93 182 111 / 40%) 0%, rgb(76 175 80 / 80%) 100%);
} }
/* 漂浮装饰:增强数智感 */ /* 漂浮装饰:增强数智感 */
.float-icon { .float-icon {
position: absolute; position: absolute;
opacity: 0.6; opacity: 0.6;
filter: drop-shadow(0 4rpx 10rpx rgba(0,0,0,0.2)); filter: drop-shadow(0 4rpx 10rpx rgb(0 0 0 / 20%));
&.device-1 { &.device-1 {
width: 120rpx; width: 120rpx;
...@@ -450,6 +408,7 @@ ...@@ -450,6 +408,7 @@
transform: rotate(15deg); transform: rotate(15deg);
animation: float-slow 4s ease-in-out infinite; animation: float-slow 4s ease-in-out infinite;
} }
&.device-2 { &.device-2 {
width: 100rpx; width: 100rpx;
height: 100rpx; height: 100rpx;
...@@ -464,20 +423,9 @@ ...@@ -464,20 +423,9 @@
position: relative; position: relative;
z-index: 10; z-index: 10;
display: flex; display: flex;
justify-content: space-between; justify-content: flex-start;
align-items: center; align-items: center;
padding: 20rpx 40rpx; padding: 20rpx 40rpx;
.switch-action {
color: #fff;
font-size: 28rpx;
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.2);
padding: 10rpx 24rpx;
border-radius: 40rpx;
backdrop-filter: blur(4px);
}
} }
.brand-hero { .brand-hero {
...@@ -496,7 +444,7 @@ ...@@ -496,7 +444,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
box-shadow: 0 16rpx 32rpx rgba(0,0,0,0.15); box-shadow: 0 16rpx 32rpx rgb(0 0 0 / 15%);
.logo-img { .logo-img {
width: 100rpx; width: 100rpx;
...@@ -513,7 +461,7 @@ ...@@ -513,7 +461,7 @@
font-size: 48rpx; font-size: 48rpx;
font-weight: 800; font-weight: 800;
letter-spacing: 4rpx; letter-spacing: 4rpx;
text-shadow: 0 4rpx 8rpx rgba(0,0,0,0.2); text-shadow: 0 4rpx 8rpx rgb(0 0 0 / 20%);
} }
.app-slogan { .app-slogan {
...@@ -543,33 +491,34 @@ ...@@ -543,33 +491,34 @@
} }
.aesthetic-card { .aesthetic-card {
background: #ffffff; background: #fff;
border-radius: 56rpx; border-radius: 56rpx;
padding: 80rpx 50rpx 60rpx; padding: 50rpx 50rpx 40rpx;
box-shadow: 0 20rpx 60rpx rgba(0, 0, 0, 0.08); box-shadow: 0 20rpx 60rpx rgb(0 0 0 / 8%);
.card-header { .card-header {
margin-bottom: 60rpx; margin-bottom: 36rpx;
.welcome-text { .welcome-text {
font-size: 40rpx; font-size: 36rpx;
font-weight: bold; font-weight: bold;
color: #333; color: #333;
} }
.green-line { .green-line {
width: 60rpx; width: 60rpx;
height: 8rpx; height: 8rpx;
background: #5DB66F; background: #5db66f;
border-radius: 4rpx; border-radius: 4rpx;
margin-top: 16rpx; margin-top: 12rpx;
} }
} }
.field-item { .field-item {
margin-bottom: 44rpx; margin-bottom: 30rpx;
.field-label { .field-label {
font-size: 26rpx; font-size: 24rpx;
color: #999; color: #999;
margin-left: 4rpx; margin-left: 4rpx;
} }
...@@ -581,9 +530,9 @@ ...@@ -581,9 +530,9 @@
.sms-trigger { .sms-trigger {
white-space: nowrap; white-space: nowrap;
font-size: 28rpx; font-size: 26rpx;
color: #5DB66F; color: #5db66f;
padding: 16rpx 32rpx; padding: 12rpx 24rpx;
background: #f1f9f2; background: #f1f9f2;
border-radius: 50rpx; border-radius: 50rpx;
margin-left: 20rpx; margin-left: 20rpx;
...@@ -599,10 +548,10 @@ ...@@ -599,10 +548,10 @@
} }
.action-footer { .action-footer {
margin-top: 80rpx; margin-top: 50rpx;
.secondary-links { .secondary-links {
margin-top: 40rpx; margin-top: 28rpx;
text-align: center; text-align: center;
.auto-hint { .auto-hint {
...@@ -624,7 +573,7 @@ ...@@ -624,7 +573,7 @@
} }
.policy-wrapper { .policy-wrapper {
margin-top: 80rpx; margin-top: 50rpx;
.policy-label { .policy-label {
display: flex; display: flex;
...@@ -639,7 +588,7 @@ ...@@ -639,7 +588,7 @@
} }
.link { .link {
color: #5DB66F; color: #5db66f;
font-weight: 500; font-weight: 500;
} }
} }
...@@ -650,7 +599,7 @@ ...@@ -650,7 +599,7 @@
line-height: 1.8; line-height: 1.8;
.link-inline { .link-inline {
color: #5DB66F; color: #5db66f;
font-weight: bold; font-weight: bold;
} }
} }
...@@ -659,9 +608,4 @@ ...@@ -659,9 +608,4 @@
flex: 1; flex: 1;
background: linear-gradient(180deg, #f7faf8 0%, #edf3ef 100%); background: linear-gradient(180deg, #f7faf8 0%, #edf3ef 100%);
} }
@keyframes float-slow {
0%, 100% { transform: translateY(0) rotate(15deg); }
50% { transform: translateY(-20rpx) rotate(10deg); }
}
</style> </style>
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论