feat: 重构核心租住流程页面与交互体验

统一注册、看房、申请与入住等核心页面的视觉和流程衔接,补齐支付、签约与状态流转闭环,提升移动端操作连贯性。
This commit is contained in:
liangjian
2026-07-29 09:05:38 +08:00
parent da6bdc6a02
commit 1111ac148b
34 changed files with 8734 additions and 2801 deletions

View File

@@ -1,31 +1,51 @@
<template>
<view class="book-viewing-page tn-safe-area-inset-bottom">
<tn-nav-bar :isBack="true" :backTitle="$tr('返回')" backgroundColor="#F0F6FF" :bottomShadow="false" :fixed="true">
<tn-nav-bar
:isBack="true"
:backTitle="$tr('返回')"
:backgroundColor="navBackgroundColor"
fontColor="#1A2233"
:bottomShadow="false"
:fixed="true"
>
<view class="nav-title">{{ $tr('预约现场带看') }}</view>
</tn-nav-bar>
<view class="content-wrapper" :style="{ paddingTop: vuex_custom_bar_height + 'px' }">
<!-- 房型/区域信息 -->
<view class="info-card tn-flex tn-flex-row-between tn-flex-col-center" v-if="displayInfoTitle">
<view class="info-left">
<view class="info-title">{{ displayInfoTitle }}</view>
<view class="info-desc">{{ displayInfoDesc }}</view>
</view>
<view class="info-icon">
<text class="tn-icon-company"></text>
<!-- 顶部信息卡片 -->
<view class="hero-card" v-if="displayInfoTitle">
<view class="hero-glow"></view>
<view class="hero-inner tn-flex tn-flex-row-between tn-flex-col-center">
<view class="hero-content">
<view class="hero-tag">
<text class="tn-icon-company hero-tag-icon"></text>
<text class="hero-tag-text">{{ $tr('专属管家') }}</text>
</view>
<view class="hero-title">{{ displayInfoTitle }}</view>
<view class="hero-desc">{{ displayInfoDesc }}</view>
</view>
<view class="hero-figure">
<view class="figure-ring figure-ring--outer"></view>
<view class="figure-ring figure-ring--inner"></view>
<text class="tn-icon-company figure-icon"></text>
</view>
</view>
<view class="hero-accent"></view>
</view>
<!-- 看房时间卡片 -->
<view class="form-card">
<view class="card-header tn-flex tn-flex-row-between tn-flex-col-bottom">
<view class="header-left tn-flex tn-flex-col-bottom">
<text class="card-title">{{ $tr('选择看房时间') }}</text>
<text class="card-subtitle">{{ $tr('请选择您方便的时间段') }}</text>
<view class="card-header tn-flex tn-flex-col-bottom">
<view class="header-icon header-icon--primary">
<text class="tn-icon-time"></text>
</view>
<view class="header-titles">
<view class="card-title">{{ $tr('选择看房时间') }}</view>
<view class="card-subtitle">{{ $tr('请选择您方便的时间段') }}</view>
</view>
</view>
<view class="section-label">{{ $tr('预约日期') }}</view>
<scroll-view class="date-scroll" scroll-x :show-scrollbar="false">
<view class="date-flex">
<view
@@ -37,10 +57,12 @@
>
<text class="date-week">{{ item.week }}</text>
<text class="date-day">{{ item.label }}</text>
<view class="date-indicator"></view>
</view>
</view>
</scroll-view>
<view class="section-label section-label--time">{{ $tr('可约时段') }}</view>
<scroll-view class="time-scroll" scroll-x :show-scrollbar="false">
<view class="time-flex">
<view
@@ -50,23 +72,43 @@
:class="{ 'time-slot--active': currentTimeIndex === index }"
@click="selectTimeSlot(index)"
>
{{ item }}
<text class="time-slot-text">{{ item }}</text>
</view>
</view>
</scroll-view>
<!-- 已选时间摘要 -->
<view v-if="currentTimeIndex !== -1" class="selected-summary tn-flex tn-flex-col-center">
<view class="summary-line"></view>
<view class="summary-body tn-flex-1 tn-flex tn-flex-row-between tn-flex-col-center">
<view class="summary-info">
<text class="summary-label">{{ $tr('已选时间') }}</text>
<text class="summary-value">{{ selectedDateTimeText }}</text>
</view>
<view class="summary-badge">
<text class="tn-icon-check"></text>
</view>
</view>
</view>
</view>
<!-- 租住需求卡片 -->
<view class="form-card">
<view class="card-header">
<view class="header-left tn-flex tn-flex-col-bottom">
<text class="card-title">{{ $tr('您的租住需求') }}</text>
<text class="card-subtitle">{{ $tr('帮助管家更好地为您推荐房源') }}</text>
<view class="card-header tn-flex tn-flex-col-bottom">
<view class="header-icon header-icon--luxury">
<text class="tn-icon-like"></text>
</view>
<view class="header-titles">
<view class="card-title">{{ $tr('您的租住需求') }}</view>
<view class="card-subtitle">{{ $tr('帮助管家更好地为您推荐房源') }}</view>
</view>
</view>
<view class="field-item">
<view class="field-label">{{ $tr('意向房型') }}</view>
<view class="field-label">
<text class="field-dot field-dot--primary"></text>
<text>{{ $tr('意向房型') }}</text>
</view>
<room-type-selector
v-model="formData.intendedRoomTypeCode"
:initial-area-code="formData.intendedAreaCode"
@@ -75,7 +117,10 @@
</view>
<view class="field-item">
<view class="field-label">{{ $tr('预计租住时长') }}</view>
<view class="field-label">
<text class="field-dot field-dot--luxury"></text>
<text>{{ $tr('预计租住时长') }}</text>
</view>
<view class="tag-grid">
<view
v-for="(item, index) in durationOptions"
@@ -90,9 +135,14 @@
</view>
<view class="field-item">
<view class="field-label">{{ $tr('租金预算 (元/月)') }}</view>
<view class="field-label">
<text class="field-dot field-dot--primary"></text>
<text>{{ $tr('租金预算 (元/月)') }}</text>
</view>
<view class="input-box tn-flex tn-flex-col-center">
<text class="tn-icon-money input-icon"></text>
<view class="input-icon-wrap">
<text class="tn-icon-money input-icon"></text>
</view>
<input
class="custom-input"
v-model="formData.budget"
@@ -103,10 +153,15 @@
</view>
</view>
<view class="field-item">
<view class="field-label">{{ $tr('工作/通勤地点') }}</view>
<view class="field-item field-item--last">
<view class="field-label">
<text class="field-dot field-dot--muted"></text>
<text>{{ $tr('工作/通勤地点') }}</text>
</view>
<view class="input-box tn-flex tn-flex-col-center">
<text class="tn-icon-location input-icon"></text>
<view class="input-icon-wrap">
<text class="tn-icon-location input-icon"></text>
</view>
<input
class="custom-input"
v-model="formData.workplace"
@@ -114,16 +169,26 @@
:placeholder="$tr('请输入主要通勤地点')"
placeholder-style="color: #A1B0C4;"
/>
<view class="input-divider"></view>
<view class="map-btn" @click="chooseWorkplaceLocation">
<text class="tn-icon-map map-btn-icon"></text>
</view>
</view>
</view>
</view>
<!-- 底部占位,避免被 fixed 按钮遮挡 -->
<view class="footer-spacer"></view>
</view>
<!-- 底部操作区 -->
<view class="footer-bar tn-safe-area-inset-bottom">
<view class="submit-btn" @click="handleSubmit">
<text>{{ $tr('提交预约') }}</text>
<view class="footer-inner">
<view class="submit-btn" :class="{ 'submit-btn--active': canSubmit }" @click="handleSubmit">
<text class="submit-btn-icon tn-icon-send"></text>
<text class="submit-btn-text">{{ $tr('提交预约') }}</text>
</view>
<view class="footer-hint">{{ $tr('提交后专属管家将尽快与您联系') }}</view>
</view>
</view>
</view>
@@ -191,6 +256,9 @@ export default {
language() {
return this.$getLanguage()
},
navBackgroundColor() {
return this.scrollTop > 20 ? '#F8FAFF' : 'transparent'
},
displayInfoTitle() {
if (!this.sourceData) {
return ''
@@ -214,6 +282,20 @@ export default {
: (this.sourceData.areaLabel || this.sourceData.areaName || this.sourceData.areaLabelEn || this.sourceData.areaNameEn || '')
const meta = [bannerCopy, areaLabel, localizePayMethodText(this.sourceData.payMethod, this.language)].filter(Boolean).join(' · ')
return meta || this.$tr('专属管家为您提供一对一带看服务')
},
selectedDateTimeText() {
if (this.currentDateIndex === -1 || this.currentTimeIndex === -1) {
return ''
}
const dateItem = this.dateList[this.currentDateIndex]
const timeItem = this.timeSlots[this.currentTimeIndex]
if (!dateItem || !timeItem) {
return ''
}
return `${dateItem.week} ${dateItem.label} ${timeItem}`
},
canSubmit() {
return this.currentTimeIndex !== -1 && this.formData.duration
}
},
data() {
@@ -236,9 +318,13 @@ export default {
workplace: ''
},
sourceData: null,
isSubmitting: false
isSubmitting: false,
scrollTop: 0
}
},
onPageScroll(event) {
this.scrollTop = (event && event.scrollTop) || 0
},
onLoad(options) {
this.syncDurationOptions()
this.generateDates()
@@ -304,13 +390,13 @@ export default {
this.$tr('周五'),
this.$tr('周六')
]
for (let i = 0; i < 7; i++) {
const d = new Date(today)
d.setDate(today.getDate() + i)
const month = String(d.getMonth() + 1).padStart(2, '0')
const day = String(d.getDate()).padStart(2, '0')
let weekStr = weeks[d.getDay()]
if (i === 0) weekStr = this.$tr('今天');
else if (i === 1) weekStr = this.$tr('明天');
@@ -350,6 +436,26 @@ export default {
selectDuration(item) {
this.formData.duration = item
},
chooseWorkplaceLocation() {
uni.chooseLocation({
success: (res) => {
const locationText = res.address || res.name || ''
if (locationText) {
this.formData.workplace = locationText
}
},
fail: (error) => {
const errMsg = (error && error.errMsg) || ''
if (errMsg.includes('cancel') || errMsg.includes('Cancel')) {
return
}
uni.showToast({
title: this.$tr('地图选择失败,请手动输入'),
icon: 'none'
})
}
})
},
handleSubmit() {
if (this.isSubmitting) {
return
@@ -391,8 +497,8 @@ export default {
showCancel: false,
confirmColor: '#01BEFF',
success: () => {
uni.redirectTo({
url: '/pkgService/my_application/my_application'
uni.reLaunch({
url: '/pages/index/index?pageId=stay-service'
})
}
})
@@ -414,174 +520,387 @@ export default {
</script>
<style scoped lang="scss">
/* 设计令牌 */
$hero-bg-start: #0A1628;
$hero-bg-end: #1E3A5F;
$luxury-gold: #D8B56A;
$luxury-gold-soft: rgba(216, 181, 106, 0.12);
$surface: #FFFFFF;
$bg-page: #F5F9FF;
$text-primary: #1A2233;
$text-secondary: #6A7A99;
$text-tertiary: #A1B0C4;
$border-soft: rgba($brand-primary, 0.08);
$shadow-card: 0 16rpx 48rpx rgba(26, 34, 51, 0.06);
$shadow-active: 0 8rpx 24rpx rgba($brand-primary, 0.22);
.book-viewing-page {
min-height: 100vh;
background: linear-gradient(180deg, #F0F6FF 0%, #F8FAFF 100%);
background: linear-gradient(180deg, #EAF4FF 0%, $bg-page 30%, #FFFFFF 100%);
display: flex;
flex-direction: column;
}
.nav-title {
font-size: 34rpx;
font-weight: bold;
color: #1D2129;
font-weight: 700;
color: $text-primary;
letter-spacing: 2rpx;
}
.content-wrapper {
flex: 1;
padding-bottom: calc(140rpx + env(safe-area-inset-bottom));
padding-bottom: calc(180rpx + env(safe-area-inset-bottom));
}
/* 顶部信息卡片 */
.info-card {
margin: 30rpx;
padding: 40rpx;
border-radius: 24rpx;
background: linear-gradient(135deg, #01BEFF 0%, #0099FF 100%);
box-shadow: 0 16rpx 32rpx rgba(1, 190, 255, 0.2);
color: #ffffff;
/* 顶部信息卡片(Hero) */
.hero-card {
position: relative;
margin: 24rpx 30rpx 30rpx;
border-radius: 36rpx;
background: linear-gradient(135deg, $hero-bg-start 0%, $hero-bg-end 100%);
box-shadow: 0 24rpx 60rpx rgba(10, 22, 40, 0.22);
overflow: hidden;
color: #FFFFFF;
}
.info-left {
.hero-glow {
position: absolute;
top: -80rpx;
right: -60rpx;
width: 280rpx;
height: 280rpx;
border-radius: 50%;
background: radial-gradient(circle, rgba($brand-primary, 0.35) 0%, transparent 70%);
filter: blur(20rpx);
}
.hero-inner {
position: relative;
z-index: 2;
padding: 44rpx 36rpx;
}
.hero-content {
flex: 1;
min-width: 0;
}
.info-title {
font-size: 36rpx;
font-weight: bold;
margin-bottom: 12rpx;
letter-spacing: 2rpx;
line-height: 1.3;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
.hero-tag {
display: inline-flex;
align-items: center;
padding: 8rpx 18rpx;
background: rgba(255, 255, 255, 0.12);
border: 1rpx solid rgba(255, 255, 255, 0.18);
border-radius: 24rpx;
margin-bottom: 20rpx;
backdrop-filter: blur(8rpx);
}
.info-desc {
font-size: 24rpx;
opacity: 0.9;
.hero-tag-icon {
font-size: 22rpx;
color: $luxury-gold;
margin-right: 8rpx;
}
.hero-tag-text {
font-size: 22rpx;
font-weight: 600;
color: rgba(255, 255, 255, 0.95);
}
.hero-title {
font-size: 38rpx;
font-weight: 700;
line-height: 1.35;
margin-bottom: 16rpx;
letter-spacing: 1rpx;
line-height: 1.5;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.info-icon {
font-size: 80rpx;
opacity: 0.2;
margin-left: 20rpx;
.hero-desc {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.72);
line-height: 1.55;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
.hero-figure {
position: relative;
width: 136rpx;
height: 136rpx;
margin-left: 24rpx;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
.figure-ring {
position: absolute;
border-radius: 50%;
border: 2rpx solid rgba(255, 255, 255, 0.1);
&--outer {
width: 136rpx;
height: 136rpx;
}
&--inner {
width: 96rpx;
height: 96rpx;
border-color: rgba($luxury-gold, 0.35);
}
}
.figure-icon {
position: relative;
z-index: 2;
font-size: 56rpx;
color: rgba(255, 255, 255, 0.9);
}
.hero-accent {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 4rpx;
background: linear-gradient(90deg, transparent 0%, $luxury-gold 50%, transparent 100%);
opacity: 0.7;
}
/* 通用表单卡片 */
.form-card {
margin: 0 30rpx 30rpx;
padding: 40rpx 30rpx;
border-radius: 24rpx;
background: #ffffff;
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.03);
padding: 36rpx 32rpx;
border-radius: 32rpx;
background: $surface;
box-shadow: $shadow-card;
border: 1rpx solid $border-soft;
}
.card-header {
margin-bottom: 30rpx;
margin-bottom: 32rpx;
}
.header-icon {
width: 64rpx;
height: 64rpx;
border-radius: 20rpx;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
flex-shrink: 0;
&--primary {
background: rgba($brand-primary, 0.1);
color: $brand-primary;
}
&--luxury {
background: $luxury-gold-soft;
color: $luxury-gold;
}
text {
font-size: 32rpx;
}
}
.header-titles {
flex: 1;
min-width: 0;
}
.card-title {
font-size: 34rpx;
font-weight: bold;
color: #1D2129;
margin-right: 16rpx;
font-size: 32rpx;
font-weight: 700;
color: $text-primary;
margin-bottom: 6rpx;
letter-spacing: 1rpx;
}
.card-subtitle {
font-size: 24rpx;
color: #86909C;
color: $text-secondary;
}
.section-label {
font-size: 26rpx;
font-weight: 600;
color: $text-primary;
margin-bottom: 20rpx;
&--time {
margin-top: 36rpx;
}
}
/* 日期选择 */
.date-scroll {
width: 100%;
white-space: nowrap;
margin-bottom: 30rpx;
}
.date-flex {
display: inline-flex;
gap: 20rpx;
padding-bottom: 10rpx;
gap: 18rpx;
padding: 6rpx 4rpx 16rpx;
}
.date-item {
width: 110rpx;
height: 130rpx;
width: 120rpx;
height: 144rpx;
background: #F4F8FF;
border-radius: 16rpx;
border-radius: 24rpx;
flex-shrink: 0;
border: 2rpx solid transparent;
transition: all 0.3s ease;
transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
position: relative;
}
.date-item--active {
background: #EAF0FF;
border-color: #01BEFF;
background: linear-gradient(135deg, $brand-primary 0%, #0099FF 100%);
border-color: rgba($brand-primary, 0.35);
box-shadow: $shadow-active;
transform: translateY(-4rpx);
}
.date-week {
font-size: 24rpx;
color: #86909C;
margin-bottom: 8rpx;
transition: all 0.3s ease;
color: $text-secondary;
margin-bottom: 10rpx;
transition: color 0.25s ease;
}
.date-item--active .date-week {
color: #01BEFF;
font-weight: bold;
color: rgba(255, 255, 255, 0.9);
}
.date-day {
font-size: 28rpx;
color: #1D2129;
font-weight: 500;
transition: all 0.3s ease;
font-size: 30rpx;
color: $text-primary;
font-weight: 700;
transition: color 0.25s ease;
}
.date-item--active .date-day {
color: #01BEFF;
color: #FFFFFF;
}
.date-indicator {
position: absolute;
bottom: 14rpx;
width: 8rpx;
height: 8rpx;
border-radius: 50%;
background: $brand-primary;
opacity: 0;
transform: scale(0);
transition: all 0.25s ease;
}
.date-item--active .date-indicator {
background: #FFFFFF;
opacity: 1;
transform: scale(1);
}
/* 时间段选择 */
.time-scroll {
width: 100%;
white-space: nowrap;
}
.time-flex {
display: inline-flex;
gap: 20rpx;
padding-bottom: 8rpx;
gap: 18rpx;
padding: 6rpx 4rpx 16rpx;
}
.time-slot {
width: 220rpx;
height: 72rpx;
line-height: 72rpx;
text-align: center;
width: 200rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
background: #F4F8FF;
border-radius: 12rpx;
border-radius: 40rpx;
font-size: 26rpx;
color: #4E5969;
color: $text-secondary;
border: 2rpx solid transparent;
transition: all 0.3s ease;
transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
flex-shrink: 0;
}
.time-slot--active {
background: #01BEFF;
color: #ffffff;
font-weight: bold;
box-shadow: 0 8rpx 16rpx rgba(1, 190, 255, 0.2);
background: linear-gradient(135deg, $brand-primary 0%, #0099FF 100%);
color: #FFFFFF;
font-weight: 600;
border-color: rgba($brand-primary, 0.3);
box-shadow: $shadow-active;
}
.time-slot-text {
letter-spacing: 1rpx;
}
/* 已选时间摘要 */
.selected-summary {
margin-top: 10rpx;
padding: 24rpx;
background: linear-gradient(135deg, rgba($brand-primary, 0.06) 0%, rgba($brand-primary, 0.02) 100%);
border-radius: 20rpx;
border: 1rpx solid rgba($brand-primary, 0.1);
}
.summary-line {
width: 4rpx;
height: 40rpx;
border-radius: 2rpx;
background: $brand-primary;
margin-right: 20rpx;
}
.summary-info {
display: flex;
flex-direction: column;
}
.summary-label {
font-size: 22rpx;
color: $text-secondary;
margin-bottom: 6rpx;
}
.summary-value {
font-size: 28rpx;
font-weight: 700;
color: $text-primary;
}
.summary-badge {
width: 44rpx;
height: 44rpx;
border-radius: 50%;
background: $brand-primary;
display: flex;
align-items: center;
justify-content: center;
box-shadow: 0 4rpx 12rpx rgba($brand-primary, 0.25);
text {
font-size: 22rpx;
color: #FFFFFF;
}
}
/* 需求字段 */
@@ -589,15 +908,38 @@ export default {
margin-bottom: 40rpx;
}
.field-item:last-child {
.field-item--last {
margin-bottom: 0;
}
.field-label {
display: flex;
align-items: center;
font-size: 28rpx;
color: #1D2129;
font-weight: bold;
margin-bottom: 24rpx;
font-weight: 700;
color: $text-primary;
margin-bottom: 22rpx;
}
.field-dot {
width: 10rpx;
height: 10rpx;
border-radius: 50%;
margin-right: 12rpx;
&--primary {
background: $brand-primary;
box-shadow: 0 0 10rpx rgba($brand-primary, 0.45);
}
&--luxury {
background: $luxury-gold;
box-shadow: 0 0 10rpx rgba($luxury-gold, 0.45);
}
&--muted {
background: $text-tertiary;
}
}
/* 标签选择 */
@@ -608,42 +950,96 @@ export default {
}
.tag-item {
padding: 0 32rpx;
height: 68rpx;
line-height: 68rpx;
padding: 0 34rpx;
height: 72rpx;
line-height: 72rpx;
background: #F4F8FF;
border-radius: 34rpx;
border-radius: 36rpx;
font-size: 26rpx;
color: #4E5969;
color: $text-secondary;
border: 2rpx solid transparent;
transition: all 0.3s ease;
transition: all 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.tag-item--active {
background: #EAF0FF;
border-color: #01BEFF;
color: #01BEFF;
font-weight: bold;
background: linear-gradient(135deg, rgba($brand-primary, 0.1) 0%, rgba($brand-primary, 0.06) 100%);
border-color: rgba($brand-primary, 0.35);
color: $brand-primary;
font-weight: 600;
box-shadow: 0 6rpx 16rpx rgba($brand-primary, 0.12);
}
/* 输入框 */
.input-box {
background: #F4F8FF;
border-radius: 20rpx;
height: 96rpx;
padding: 0 26rpx;
border: 2rpx solid transparent;
transition: all 0.25s ease;
}
.input-box:focus-within {
background: #FFFFFF;
border-color: rgba($brand-primary, 0.25);
box-shadow: 0 6rpx 20rpx rgba($brand-primary, 0.08);
}
.input-icon-wrap {
width: 52rpx;
height: 52rpx;
border-radius: 16rpx;
height: 88rpx;
padding: 0 30rpx;
background: #FFFFFF;
display: flex;
align-items: center;
justify-content: center;
margin-right: 18rpx;
box-shadow: 0 4rpx 10rpx rgba(0, 0, 0, 0.04);
}
.input-icon {
font-size: 36rpx;
color: #A1B0C4;
margin-right: 16rpx;
font-size: 28rpx;
color: $brand-primary;
}
.input-divider {
width: 2rpx;
height: 36rpx;
background: rgba($text-tertiary, 0.25);
margin: 0 18rpx;
}
.map-btn {
width: 52rpx;
height: 52rpx;
border-radius: 16rpx;
background: rgba($brand-primary, 0.1);
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: all 0.25s ease;
}
.map-btn:active {
background: rgba($brand-primary, 0.2);
transform: scale(0.95);
}
.map-btn-icon {
font-size: 28rpx;
color: $brand-primary;
}
.custom-input {
flex: 1;
font-size: 28rpx;
color: #1D2129;
color: $text-primary;
font-weight: 500;
}
.footer-spacer {
height: 180rpx;
}
/* 底部按钮 */
@@ -652,30 +1048,61 @@ export default {
bottom: 0;
left: 0;
width: 100%;
background: #ffffff;
padding: 24rpx 40rpx;
box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.04);
background: rgba(255, 255, 255, 0.96);
backdrop-filter: blur(20rpx);
padding: 24rpx 40rpx calc(24rpx + env(safe-area-inset-bottom));
box-shadow: 0 -8rpx 32rpx rgba(26, 34, 51, 0.06);
z-index: 100;
}
.footer-inner {
width: 100%;
}
.submit-btn {
width: 100%;
height: 96rpx;
background: linear-gradient(135deg, #01BEFF 0%, #0099FF 100%);
border-radius: 48rpx;
display: flex;
align-items: center;
justify-content: center;
color: #ffffff;
background: linear-gradient(135deg, #A1B0C4 0%, #86909C 100%);
color: #FFFFFF;
font-size: 32rpx;
font-weight: bold;
font-weight: 700;
letter-spacing: 2rpx;
box-shadow: 0 12rpx 24rpx rgba(1, 190, 255, 0.25);
transition: all 0.3s ease;
box-shadow: 0 8rpx 24rpx rgba(134, 144, 156, 0.2);
transition: all 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}
.submit-btn:active {
.submit-btn--active {
background: linear-gradient(135deg, $brand-primary 0%, #0099FF 100%);
box-shadow: 0 16rpx 36rpx rgba($brand-primary, 0.32);
}
.submit-btn--active:active {
transform: scale(0.98);
opacity: 0.9;
box-shadow: 0 8rpx 20rpx rgba($brand-primary, 0.25);
}
.submit-btn-icon {
font-size: 32rpx;
margin-right: 12rpx;
}
.submit-btn-text {
line-height: 1;
}
.footer-hint {
text-align: center;
font-size: 22rpx;
color: $text-tertiary;
margin-top: 16rpx;
}
/* 导航栏背景色滚动过渡 */
.book-viewing-page ::v-deep .tn-custom-nav-bar__bar {
transition: background-color 0.3s ease, box-shadow 0.3s ease;
}
</style>