Files
jiapuapp/pages/auth/a02-login.vue
T
2026-07-13 17:31:11 +08:00

322 lines
7.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 页面编号A-02用途账号登录当前仅保留已确认的本地登录界面 -->
<template>
<view class="auth-page login-page">
<!-- A01 共用的登录页底图层先不透明纸纹后透明山水 -->
<image class="paper-background" src="/static/assets/foundation/opaque/auth-page-paper.jpg" mode="aspectFill" />
<image class="scenery-background" src="/static/assets/foundation/transparent/auth-ink-scenery.png" mode="aspectFill" />
<view class="auth-content">
<view class="auth-header">
<image class="header-background" src="/static/assets/foundation/opaque/auth-header.png" mode="aspectFill" />
<image class="header-seal" src="/static/assets/foundation/transparent/brand-seal.png" mode="aspectFit" />
</view>
<view class="login-panel">
<view class="page-heading">
<view class="back-button" hover-class="back-hover" @click="goBack"></view>
<view>
<text class="page-title">登录家谱</text>
<text class="page-subtitle">欢迎回到家族记忆</text>
</view>
</view>
<view class="login-tabs">
<view class="login-tab" :class="{ active: activeTab === 'password' }" @click="activeTab = 'password'">
<text>账号密码登录</text>
</view>
<view class="login-tab" :class="{ active: activeTab === 'sms' }" @click="activeTab = 'sms'">
<text>手机验证码登录</text>
</view>
</view>
<view v-if="activeTab === 'password'" class="form-content">
<view class="input-row">
<text class="input-label">账号</text>
<input v-model.trim="account" class="auth-input" placeholder="请输入账号或手机号" placeholder-class="placeholder" />
</view>
<view class="input-row">
<text class="input-label">密码</text>
<input v-model="password" class="auth-input" password placeholder="请输入密码" placeholder-class="placeholder" />
</view>
<view class="secondary-action" hover-class="text-hover" @click="prepareForgotPassword">忘记密码</view>
</view>
<view v-else class="form-content">
<view class="input-row">
<text class="input-label">手机</text>
<input v-model.trim="smsPhone" class="auth-input" type="number" maxlength="11" placeholder="请输入手机号" placeholder-class="placeholder" />
</view>
<view class="input-row code-row">
<text class="input-label">验证码</text>
<input v-model.trim="verificationCode" class="auth-input" type="number" maxlength="6" placeholder="请输入验证码" placeholder-class="placeholder" />
<view class="get-code" hover-class="text-hover" @click="prepareGetCode">获取验证码</view>
</view>
</view>
<view class="login-submit" hover-class="button-hover" @click="submitLogin">登录</view>
<text class="agreement-reminder">请先在登录引导页阅读并确认协议</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
const activeTab = ref('password')
const account = ref('')
const password = ref('')
const smsPhone = ref('')
const verificationCode = ref('')
const agreedFromEntry = ref(false)
onLoad((options) => {
agreedFromEntry.value = options?.agreed === '1'
})
const goBack = () => {
uni.navigateBack()
}
const prepareForgotPassword = () => {
uni.showToast({ title: '忘记密码页面准备中', icon: 'none' })
}
const prepareGetCode = () => {
uni.showToast({ title: '获取验证码功能待接入', icon: 'none' })
}
const canSubmit = () => {
if (agreedFromEntry.value) return true
uni.showToast({ title: '请先返回登录引导确认协议', icon: 'none' })
return false
}
const submitLogin = () => {
if (!canSubmit()) return
if (activeTab.value === 'password') {
if (!account.value) {
uni.showToast({ title: '请输入账号或手机号', icon: 'none' })
return
}
if (!password.value) {
uni.showToast({ title: '请输入密码', icon: 'none' })
return
}
} else {
if (!/^1\d{10}$/.test(smsPhone.value)) {
uni.showToast({ title: '请输入正确手机号', icon: 'none' })
return
}
if (!verificationCode.value) {
uni.showToast({ title: '请输入验证码', icon: 'none' })
return
}
}
uni.showToast({ title: '登录接口待接入', icon: 'none' })
}
</script>
<style scoped lang="scss">
.auth-page {
position: relative;
min-height: 100vh;
background: #f7f1e6;
}
.paper-background,
.scenery-background {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.paper-background { opacity: 0.96; }
.scenery-background { opacity: 0.76; }
.auth-content {
position: relative;
z-index: 1;
box-sizing: border-box;
min-height: 100vh;
padding-bottom: calc(44rpx + env(safe-area-inset-bottom));
}
.auth-header {
position: relative;
height: 196rpx;
overflow: hidden;
}
.header-background {
width: 100%;
height: 100%;
}
.header-seal {
position: absolute;
top: 34rpx;
left: 50%;
width: 124rpx;
height: 124rpx;
transform: translateX(-50%);
}
.login-panel {
margin: 68rpx 56rpx 0;
padding: 46rpx 38rpx 54rpx;
border: 2rpx solid #d6ad6c;
border-radius: 10rpx;
background: rgba(255, 252, 246, 0.78);
box-shadow: inset 0 0 0 5rpx rgba(255, 255, 255, 0.55);
}
.page-heading {
display: flex;
align-items: center;
}
.back-button {
display: flex;
align-items: center;
justify-content: center;
width: 48rpx;
height: 48rpx;
margin-right: 20rpx;
border: 1rpx solid #d7ae70;
border-radius: 50%;
color: #9d5b28;
font-size: 52rpx;
font-weight: 300;
line-height: 40rpx;
}
.back-hover { opacity: 0.62; }
.page-title,
.page-subtitle {
display: block;
}
.page-title {
color: #3f2c1d;
font-family: STKaiti, KaiTi, serif;
font-size: 46rpx;
font-weight: 700;
letter-spacing: 4rpx;
}
.page-subtitle {
margin-top: 8rpx;
color: #8c7864;
font-size: 22rpx;
letter-spacing: 2rpx;
}
.login-tabs {
display: flex;
margin-top: 54rpx;
border-bottom: 1rpx solid #dcc29a;
}
.login-tab {
position: relative;
flex: 1;
padding: 0 0 24rpx;
color: #89715a;
font-family: STKaiti, KaiTi, serif;
font-size: 29rpx;
text-align: center;
}
.login-tab.active {
color: #a7160c;
font-weight: 700;
}
.login-tab.active::after {
position: absolute;
right: 28rpx;
bottom: -1rpx;
left: 28rpx;
height: 4rpx;
border-radius: 4rpx;
background: #b7170d;
content: '';
}
.form-content { margin-top: 26rpx; }
.input-row {
display: flex;
align-items: center;
min-height: 96rpx;
border-bottom: 1rpx solid #e5d4b7;
}
.input-label {
width: 92rpx;
color: #674b35;
font-family: STKaiti, KaiTi, serif;
font-size: 30rpx;
}
.auth-input {
flex: 1;
height: 88rpx;
color: #3f2c1d;
font-size: 28rpx;
}
.placeholder { color: #b3a895; }
.code-row .auth-input { min-width: 0; }
.get-code {
flex: 0 0 auto;
padding-left: 20rpx;
border-left: 1rpx solid #ddc7a3;
color: #a7160c;
font-size: 25rpx;
}
.secondary-action {
margin-top: 28rpx;
color: #a7160c;
font-size: 25rpx;
text-align: right;
}
.text-hover { opacity: 0.64; }
.login-submit {
display: flex;
align-items: center;
justify-content: center;
height: 100rpx;
margin-top: 60rpx;
border: 2rpx solid #9e170e;
border-radius: 8rpx;
background: #b7170d;
box-shadow: inset 0 0 0 4rpx #d69b5f;
color: #fffaf0;
font-family: STKaiti, KaiTi, serif;
font-size: 36rpx;
letter-spacing: 6rpx;
}
.button-hover { opacity: 0.84; }
.agreement-reminder {
display: block;
margin-top: 26rpx;
color: #9a8773;
font-size: 22rpx;
text-align: center;
}
</style>