hugray-partner-miniapp/pages/login/index.vue
@@ -39,7 +39,7 @@
                        v-model="form.password"
                        class="field-input"
                        password
                        placeholder="请输入验证码"
                        placeholder="请输入密码"
                        placeholder-style="color:#b8bec7;font-size:28rpx"
                    />
                </view>
@@ -66,6 +66,20 @@
        <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>
@@ -88,6 +102,9 @@
// 登录请求进行中标记,防止重复提交
const logging = ref(false)
// 未勾选协议时确认弹窗的显示状态
const showAgreementModal = ref(false)
// 状态栏高度(px),用于自定义导航栏顶部留白
const statusBarHeight = uni.getSystemInfoSync().statusBarHeight || 0
@@ -97,17 +114,34 @@
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
    }
@@ -330,4 +364,70 @@
    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>