261 lines
5.4 KiB
Vue
261 lines
5.4 KiB
Vue
<template>
|
|
<view class="unauth-login-panel" :class="{ compact }">
|
|
<view class="brand-section">
|
|
<image class="brand-logo" src="/static/brand/logo.png" mode="aspectFit" />
|
|
<text class="brand-name">大兴区冰上运动中心</text>
|
|
</view>
|
|
|
|
<view class="login-card">
|
|
<view class="unauth-copy" v-if="title || description">
|
|
<text class="unauth-title" v-if="title">{{ title }}</text>
|
|
<text class="unauth-description" v-if="description">{{ description }}</text>
|
|
</view>
|
|
|
|
<button
|
|
class="login-button"
|
|
:class="{ disabled: loading }"
|
|
:loading="loading"
|
|
:disabled="loading"
|
|
@tap="handleLoginTap"
|
|
>
|
|
{{ primaryText }}
|
|
</button>
|
|
|
|
<view class="agreement-checks">
|
|
<view class="acceptance-row acceptance-user" @tap="toggleUserAgreement">
|
|
<view class="checkbox" :class="{ checked: hasAcceptedUserAgreement }">
|
|
<text v-if="hasAcceptedUserAgreement">✓</text>
|
|
</view>
|
|
<text class="acceptance-text">我已阅读并同意</text>
|
|
<text class="agreement-inline-link" @tap.stop="openUserAgreement">用户协议</text>
|
|
</view>
|
|
<view class="acceptance-row acceptance-privacy" @tap="togglePrivacyPolicy">
|
|
<view class="checkbox" :class="{ checked: hasAcceptedPrivacyPolicy }">
|
|
<text v-if="hasAcceptedPrivacyPolicy">✓</text>
|
|
</view>
|
|
<text class="acceptance-text">我已阅读并同意</text>
|
|
<text class="agreement-inline-link" @tap.stop="openPrivacyPolicy">隐私政策</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<AgreementLinks ref="agreementLinksRef" :show-entry="false" />
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { computed, ref } from 'vue'
|
|
import AgreementLinks from '@/components/AgreementLinks.vue'
|
|
|
|
defineProps({
|
|
title: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
description: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
primaryText: {
|
|
type: String,
|
|
default: '点击登录'
|
|
},
|
|
loading: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
compact: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
})
|
|
|
|
const emit = defineEmits(['login'])
|
|
|
|
const hasAcceptedUserAgreement = ref(false)
|
|
const hasAcceptedPrivacyPolicy = ref(false)
|
|
const agreementLinksRef = ref(null)
|
|
|
|
const canLogin = computed(() => hasAcceptedUserAgreement.value && hasAcceptedPrivacyPolicy.value)
|
|
|
|
const toggleUserAgreement = () => {
|
|
hasAcceptedUserAgreement.value = !hasAcceptedUserAgreement.value
|
|
}
|
|
|
|
const togglePrivacyPolicy = () => {
|
|
hasAcceptedPrivacyPolicy.value = !hasAcceptedPrivacyPolicy.value
|
|
}
|
|
|
|
const openUserAgreement = () => {
|
|
agreementLinksRef.value?.openUserAgreement()
|
|
}
|
|
|
|
const openPrivacyPolicy = () => {
|
|
agreementLinksRef.value?.openPrivacyPolicy()
|
|
}
|
|
|
|
const handleLoginTap = () => {
|
|
if (!canLogin.value) {
|
|
uni.showToast({
|
|
title: '请先勾选用户协议和隐私政策',
|
|
icon: 'none'
|
|
})
|
|
return
|
|
}
|
|
emit('login')
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.unauth-login-panel {
|
|
min-height: calc(100vh - 176rpx - env(safe-area-inset-bottom));
|
|
padding: 0 $spacing-lg 48rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
text-align: center;
|
|
gap: 58rpx;
|
|
position: relative;
|
|
overflow: hidden;
|
|
background: transparent;
|
|
|
|
&.compact {
|
|
min-height: 640rpx;
|
|
padding: 0 $spacing-lg 40rpx;
|
|
gap: 44rpx;
|
|
}
|
|
}
|
|
|
|
.brand-section {
|
|
width: 100%;
|
|
position: relative;
|
|
z-index: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
}
|
|
|
|
.brand-logo {
|
|
width: 144rpx;
|
|
height: 144rpx;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.brand-name {
|
|
margin-top: 34rpx;
|
|
font-size: 40rpx;
|
|
line-height: 1.26;
|
|
font-weight: 900;
|
|
color: $text-color-main;
|
|
}
|
|
|
|
.login-card {
|
|
width: 100%;
|
|
max-width: 560rpx;
|
|
position: relative;
|
|
z-index: 1;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.unauth-copy {
|
|
margin-bottom: 24rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
gap: $spacing-sm;
|
|
max-width: 560rpx;
|
|
}
|
|
|
|
.unauth-title {
|
|
font-size: 30rpx;
|
|
line-height: 1.35;
|
|
font-weight: 800;
|
|
color: $text-color-main;
|
|
}
|
|
|
|
.unauth-description {
|
|
font-size: 24rpx;
|
|
line-height: 1.6;
|
|
color: $text-color-muted;
|
|
}
|
|
|
|
.login-button {
|
|
width: 100%;
|
|
height: 88rpx;
|
|
border-radius: $border-radius-base;
|
|
color: #FFFFFF;
|
|
background-color: $text-color-main;
|
|
font-size: 28rpx;
|
|
font-weight: 700;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
|
|
&::after {
|
|
border: none;
|
|
}
|
|
|
|
&.disabled,
|
|
&[disabled] {
|
|
color: #FFFFFF;
|
|
background-color: $text-color-light;
|
|
}
|
|
}
|
|
|
|
.agreement-checks {
|
|
margin-top: 24rpx;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 18rpx;
|
|
align-items: center;
|
|
}
|
|
|
|
.acceptance-row {
|
|
display: flex;
|
|
align-items: center;
|
|
min-height: 38rpx;
|
|
text-align: left;
|
|
align-self: center;
|
|
}
|
|
|
|
.checkbox {
|
|
width: 30rpx;
|
|
height: 30rpx;
|
|
margin-right: 12rpx;
|
|
flex-shrink: 0;
|
|
border: 2rpx solid $border-color;
|
|
border-radius: 8rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: #FFFFFF;
|
|
font-size: 20rpx;
|
|
line-height: 1;
|
|
font-weight: 900;
|
|
background-color: #FFFFFF;
|
|
|
|
&.checked {
|
|
border-color: $text-color-main;
|
|
background-color: $text-color-main;
|
|
}
|
|
}
|
|
|
|
.acceptance-text,
|
|
.agreement-inline-link {
|
|
font-size: 24rpx;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.acceptance-text {
|
|
color: $text-color-muted;
|
|
}
|
|
|
|
.agreement-inline-link {
|
|
color: $text-color-main;
|
|
font-weight: 700;
|
|
}
|
|
</style>
|