| | |
| | | v-model="form.password" |
| | | class="field-input" |
| | | password |
| | | placeholder="请输入验证码" |
| | | placeholder="请输入密码" |
| | | placeholder-style="color:#b8bec7;font-size:28rpx" |
| | | /> |
| | | </view> |
| | |
| | | <view class="bottom-bar"> |
| | | <view class="login-btn" @tap="_handleLogin">登录</view> |
| | | </view> |
| | | |
| | | <!-- 未勾选协议时的确认弹窗 --> |
| | | <view v-if="showAgreementModal" class="modal-mask"> |
| | | <view class="modal-box"> |
| | | <text class="modal-title">用户协议与隐私权限</text> |
| | | <text class="modal-content">请确认已同意《用户协议》、《隐私与权限协议》</text> |
| | | <view class="modal-actions"> |
| | | <view class="modal-btn modal-btn--cancel" @tap="_handleAgreementCancel">取消</view> |
| | | <view class="modal-btn modal-btn--confirm" @tap="_handleAgreementConfirm"> |
| | | 我已阅读并同意 |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </view> |
| | | </template> |
| | | |
| | |
| | | // 登录请求进行中标记,防止重复提交 |
| | | const logging = ref(false) |
| | | |
| | | // 未勾选协议时确认弹窗的显示状态 |
| | | const showAgreementModal = ref(false) |
| | | |
| | | // 状态栏高度(px),用于自定义导航栏顶部留白 |
| | | const statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 0 |
| | | |
| | |
| | | const _validateForm = () => { |
| | | if (!form.username.trim()) return '请输入账号' |
| | | if (!form.password.trim()) return '请输入密码' |
| | | if (!agreed.value) return '请先阅读并同意用户协议' |
| | | return '' |
| | | } |
| | | |
| | | /** 执行登录:校验 → 调接口 → 写入 token → 跳转首页 */ |
| | | /** 关闭协议确认弹窗 */ |
| | | const _handleAgreementCancel = () => { |
| | | showAgreementModal.value = false |
| | | } |
| | | |
| | | /** 同意协议:自动勾选并继续登录 */ |
| | | const _handleAgreementConfirm = () => { |
| | | showAgreementModal.value = false |
| | | agreed.value = true |
| | | _handleLogin() |
| | | } |
| | | |
| | | /** 执行登录:校验 → 协议确认 → 调接口 → 写入 token → 跳转首页 */ |
| | | const _handleLogin = async () => { |
| | | if (logging.value) return |
| | | |
| | | const errorMsg = _validateForm() |
| | | if (errorMsg) { |
| | | uni.showToast({ title: errorMsg, icon: 'none' }) |
| | | return |
| | | } |
| | | |
| | | // 未勾选协议:先弹窗二次确认,用户同意后再继续登录 |
| | | if (!agreed.value) { |
| | | showAgreementModal.value = true |
| | | return |
| | | } |
| | | |
| | |
| | | font-size: 32rpx; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | /* ======================== 未勾选协议确认弹窗 ======================== */ |
| | | |
| | | /* 遮罩层:全屏半透明,居中承载弹窗 */ |
| | | .modal-mask { |
| | | position: fixed; |
| | | left: 0; |
| | | top: 0; |
| | | right: 0; |
| | | bottom: 0; |
| | | background-color: rgba(0, 0, 0, 0.45); |
| | | display: flex; |
| | | align-items: center; |
| | | justify-content: center; |
| | | z-index: 999; |
| | | } |
| | | |
| | | .modal-box { |
| | | width: 560rpx; |
| | | background-color: #ffffff; |
| | | border-radius: 16rpx; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | /* 标题:绿色居中,下方带分隔线 */ |
| | | .modal-title { |
| | | display: block; |
| | | padding: 40rpx 32rpx 30rpx; |
| | | font-size: 34rpx; |
| | | font-weight: 600; |
| | | color: #8bc34a; |
| | | text-align: center; |
| | | border-bottom: 1rpx solid #ececec; |
| | | } |
| | | |
| | | /* 正文:灰色居中的提示文案 */ |
| | | .modal-content { |
| | | display: block; |
| | | padding: 44rpx 48rpx; |
| | | font-size: 28rpx; |
| | | line-height: 42rpx; |
| | | color: #9aa1ab; |
| | | text-align: center; |
| | | } |
| | | |
| | | /* 按钮行:取消 / 我已阅读并同意 各占一半 */ |
| | | .modal-actions { |
| | | display: flex; |
| | | align-items: center; |
| | | padding-bottom: 24rpx; |
| | | } |
| | | |
| | | .modal-btn { |
| | | flex: 1; |
| | | text-align: center; |
| | | font-size: 30rpx; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .modal-btn--cancel { |
| | | color: #1f2329; |
| | | } |
| | | |
| | | .modal-btn--confirm { |
| | | color: #8bc34a; |
| | | } |
| | | </style> |