将组件级 i18n 对象重构为统一由全局 locales/messages.js 管理,确保中英文语言切换时正确显示对应文本。 - 新增 utils/i18n.js 国际化工具函数 - 更新 store/$t.mixin.js 翻译混入逻辑 - 迁移 pkgService、pkgBooking、pkgAccount、pkgExplore、pages 等共 58 个组件的中英文文本至全局消息表
682 lines
18 KiB
Vue
682 lines
18 KiB
Vue
<template>
|
|
<view class="book-viewing-page tn-safe-area-inset-bottom">
|
|
<tn-nav-bar :isBack="true" :backTitle="$tr('返回')" backgroundColor="#F0F6FF" :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>
|
|
</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>
|
|
</view>
|
|
|
|
<scroll-view class="date-scroll" scroll-x :show-scrollbar="false">
|
|
<view class="date-flex">
|
|
<view
|
|
v-for="(item, index) in dateList"
|
|
:key="index"
|
|
class="date-item tn-flex tn-flex-direction-column tn-flex-col-center tn-flex-row-center"
|
|
:class="{ 'date-item--active': currentDateIndex === index }"
|
|
@click="selectDate(index)"
|
|
>
|
|
<text class="date-week">{{ item.week }}</text>
|
|
<text class="date-day">{{ item.label }}</text>
|
|
</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<scroll-view class="time-scroll" scroll-x :show-scrollbar="false">
|
|
<view class="time-flex">
|
|
<view
|
|
v-for="(item, index) in timeSlots"
|
|
:key="index"
|
|
class="time-slot"
|
|
:class="{ 'time-slot--active': currentTimeIndex === index }"
|
|
@click="selectTimeSlot(index)"
|
|
>
|
|
{{ item }}
|
|
</view>
|
|
</view>
|
|
</scroll-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>
|
|
</view>
|
|
|
|
<view class="field-item">
|
|
<view class="field-label">{{ $tr('意向房型') }}</view>
|
|
<room-type-selector
|
|
v-model="formData.intendedRoomTypeCode"
|
|
:initial-area-code="formData.intendedAreaCode"
|
|
@change="handleRoomTypeChange"
|
|
/>
|
|
</view>
|
|
|
|
<view class="field-item">
|
|
<view class="field-label">{{ $tr('预计租住时长') }}</view>
|
|
<view class="tag-grid">
|
|
<view
|
|
v-for="(item, index) in durationOptions"
|
|
:key="index"
|
|
class="tag-item"
|
|
:class="{ 'tag-item--active': formData.duration === item }"
|
|
@click="selectDuration(item)"
|
|
>
|
|
{{ item }}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="field-item">
|
|
<view class="field-label">{{ $tr('租金预算 (元/月)') }}</view>
|
|
<view class="input-box tn-flex tn-flex-col-center">
|
|
<text class="tn-icon-money input-icon"></text>
|
|
<input
|
|
class="custom-input"
|
|
v-model="formData.budget"
|
|
type="digit"
|
|
:placeholder="$tr('请输入您的心理价位')"
|
|
placeholder-style="color: #A1B0C4;"
|
|
/>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="field-item">
|
|
<view class="field-label">{{ $tr('工作/通勤地点') }}</view>
|
|
<view class="input-box tn-flex tn-flex-col-center">
|
|
<text class="tn-icon-location input-icon"></text>
|
|
<input
|
|
class="custom-input"
|
|
v-model="formData.workplace"
|
|
type="text"
|
|
:placeholder="$tr('请输入主要通勤地点')"
|
|
placeholder-style="color: #A1B0C4;"
|
|
/>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
</view>
|
|
|
|
<!-- 底部操作区 -->
|
|
<view class="footer-bar tn-safe-area-inset-bottom">
|
|
<view class="submit-btn" @click="handleSubmit">
|
|
<text>{{ $tr('提交预约') }}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { submitViewingApplicationForm } from '@/api/index.js'
|
|
import { resolveExistingBookingNavigationTarget } from '../../utils/booking-entry'
|
|
import { getSessionSnapshot } from '../../utils/app-state'
|
|
import { syncLoginStayState } from '../../utils/session-sync'
|
|
import { compactEnglishText, localizePayMethodText } from '../../utils/select-room-normalizers'
|
|
import RoomTypeSelector from './components/RoomTypeSelector.vue'
|
|
|
|
function buildViewingDateTime(date = '', time = '', isEnd = false) {
|
|
if (!date || !time) {
|
|
return null
|
|
}
|
|
const range = String(time).split('-')
|
|
const selected = isEnd ? range[1] : range[0]
|
|
if (!selected) {
|
|
return null
|
|
}
|
|
return `${date}T${selected}:00`
|
|
}
|
|
|
|
function formatDatePart(value) {
|
|
return String(value).padStart(2, '0')
|
|
}
|
|
|
|
function shiftDate(date = '', days = 0) {
|
|
if (!date) {
|
|
return ''
|
|
}
|
|
const next = new Date(`${date}T00:00:00`)
|
|
if (!Number.isFinite(next.getTime())) {
|
|
return ''
|
|
}
|
|
next.setDate(next.getDate() + days)
|
|
return `${next.getFullYear()}-${formatDatePart(next.getMonth() + 1)}-${formatDatePart(next.getDate())}`
|
|
}
|
|
|
|
function buildExpectedStayRange(date = '', durationIndex = 0) {
|
|
if (!date) {
|
|
return {
|
|
start: null,
|
|
end: null
|
|
}
|
|
}
|
|
|
|
const durationDays = [90, 180, 270, 365, 365]
|
|
const normalizedIndex = durationIndex >= 0 ? durationIndex : 0
|
|
const endDate = shiftDate(date, durationDays[normalizedIndex] || durationDays[0])
|
|
|
|
return {
|
|
start: `${date}T00:00:00`,
|
|
end: endDate ? `${endDate}T23:59:59` : null
|
|
}
|
|
}
|
|
|
|
export default {
|
|
components: {
|
|
RoomTypeSelector
|
|
},
|
|
computed: {
|
|
language() {
|
|
return this.$getLanguage()
|
|
},
|
|
displayInfoTitle() {
|
|
if (!this.sourceData) {
|
|
return ''
|
|
}
|
|
if (this.language === 'en') {
|
|
return this.sourceData.roomTypeNameEnDisplay
|
|
|| this.sourceData.roomNameEnDisplay
|
|
|| compactEnglishText(this.sourceData.roomTypeNameEn || this.sourceData.roomNameEn || this.sourceData.bannerTitleEn || this.sourceData.bannerTitle || this.sourceData.areaLabelEn || this.sourceData.areaLabel || this.sourceData.areaNameEn || this.sourceData.areaName || '', 24)
|
|
}
|
|
return this.sourceData.roomTypeName || this.sourceData.roomName || this.sourceData.bannerTitle || this.sourceData.areaLabel || this.sourceData.areaName || ''
|
|
},
|
|
displayInfoDesc() {
|
|
if (!this.sourceData) {
|
|
return this.$tr('专属管家为您提供一对一带看服务')
|
|
}
|
|
const bannerCopy = this.language === 'en'
|
|
? compactEnglishText(this.sourceData.bannerSubtitleEn || this.sourceData.bannerDescEn || this.sourceData.bannerSubtitle || this.sourceData.bannerDesc || '', 48)
|
|
: (this.sourceData.bannerSubtitle || this.sourceData.bannerDesc || this.sourceData.bannerSubtitleEn || this.sourceData.bannerDescEn || '')
|
|
const areaLabel = this.language === 'en'
|
|
? (this.sourceData.areaLabelEnDisplay || this.sourceData.areaNameEnDisplay || compactEnglishText(this.sourceData.areaLabelEn || this.sourceData.areaLabel || this.sourceData.areaNameEn || this.sourceData.areaName || '', 26))
|
|
: (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('专属管家为您提供一对一带看服务')
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
dateList: [],
|
|
timeSlots: [
|
|
'10:00-11:00', '11:00-12:00', '12:00-13:00',
|
|
'13:00-14:00', '14:00-15:00', '15:00-16:00',
|
|
'16:00-17:00', '17:00-18:00', '18:00-19:00',
|
|
'19:00-20:00'
|
|
],
|
|
durationOptions: [],
|
|
currentDateIndex: 0,
|
|
currentTimeIndex: -1,
|
|
formData: {
|
|
intendedAreaCode: '',
|
|
intendedRoomTypeCode: '',
|
|
budget: '',
|
|
duration: '',
|
|
workplace: ''
|
|
},
|
|
sourceData: null,
|
|
isSubmitting: false
|
|
}
|
|
},
|
|
onLoad(options) {
|
|
this.syncDurationOptions()
|
|
this.generateDates()
|
|
if (options.payload) {
|
|
try {
|
|
this.sourceData = JSON.parse(decodeURIComponent(options.payload))
|
|
this.formData.intendedAreaCode = this.sourceData && this.sourceData.areaCode ? this.sourceData.areaCode : ''
|
|
this.formData.intendedRoomTypeCode = this.sourceData && this.sourceData.roomTypeCode ? this.sourceData.roomTypeCode : ''
|
|
} catch (e) {
|
|
console.error('Failed to parse payload', e)
|
|
}
|
|
}
|
|
this.redirectIfBookingUnavailable()
|
|
},
|
|
methods: {
|
|
redirectIfBookingUnavailable() {
|
|
const session = getSessionSnapshot()
|
|
if (!session.isLogin) {
|
|
return Promise.resolve(false)
|
|
}
|
|
|
|
return syncLoginStayState({
|
|
language: this.$getLanguage(),
|
|
force: true
|
|
})
|
|
.then((stayState) => {
|
|
const targetUrl = resolveExistingBookingNavigationTarget(stayState)
|
|
if (!targetUrl) {
|
|
return false
|
|
}
|
|
|
|
if (/^\/pages\/index\/index(?:\?|$)/.test(targetUrl)) {
|
|
uni.reLaunch({ url: targetUrl })
|
|
return true
|
|
}
|
|
|
|
uni.redirectTo({ url: targetUrl })
|
|
return true
|
|
})
|
|
.catch((error) => {
|
|
console.error('check viewing booking entry failed', error)
|
|
return false
|
|
})
|
|
},
|
|
syncDurationOptions() {
|
|
this.durationOptions = [
|
|
this.$tr('1-3个月'),
|
|
this.$tr('4-6个月'),
|
|
this.$tr('7-9个月'),
|
|
this.$tr('10-12个月'),
|
|
this.$tr('1年以上')
|
|
]
|
|
},
|
|
generateDates() {
|
|
const dates = []
|
|
const today = new Date()
|
|
const weeks = [
|
|
this.$tr('周日'),
|
|
this.$tr('周一'),
|
|
this.$tr('周二'),
|
|
this.$tr('周三'),
|
|
this.$tr('周四'),
|
|
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('明天');
|
|
|
|
dates.push({
|
|
date: `${d.getFullYear()}-${month}-${day}`,
|
|
label: `${month}/${day}`,
|
|
week: weekStr
|
|
})
|
|
}
|
|
this.dateList = dates
|
|
},
|
|
selectDate(index) {
|
|
this.currentDateIndex = index
|
|
this.currentTimeIndex = -1
|
|
},
|
|
selectTimeSlot(index) {
|
|
this.currentTimeIndex = index
|
|
},
|
|
handleRoomTypeChange({ area, roomType }) {
|
|
this.formData.intendedAreaCode = area && area.code ? area.code : ''
|
|
this.formData.intendedRoomTypeCode = roomType && roomType.code ? roomType.code : ''
|
|
if (!this.sourceData) {
|
|
this.sourceData = {}
|
|
}
|
|
if (area) {
|
|
this.sourceData.areaCode = area.code || ''
|
|
this.sourceData.areaName = area.name || ''
|
|
this.sourceData.areaNameEn = area.nameEn || ''
|
|
}
|
|
if (roomType) {
|
|
this.sourceData.roomTypeCode = roomType.code || ''
|
|
this.sourceData.roomTypeName = roomType.name || ''
|
|
this.sourceData.roomTypeNameEn = roomType.nameEn || ''
|
|
}
|
|
},
|
|
selectDuration(item) {
|
|
this.formData.duration = item
|
|
},
|
|
handleSubmit() {
|
|
if (this.isSubmitting) {
|
|
return
|
|
}
|
|
if (this.currentTimeIndex === -1) {
|
|
uni.showToast({ title: this.$tr('请选择看房时间段'), icon: 'none' })
|
|
return
|
|
}
|
|
if (!this.formData.duration) {
|
|
uni.showToast({ title: this.$tr('请选择预计租住时长'), icon: 'none' })
|
|
return
|
|
}
|
|
|
|
const selectedDate = this.dateList[this.currentDateIndex].date
|
|
const selectedTime = this.timeSlots[this.currentTimeIndex]
|
|
const appointmentViewingTime = buildViewingDateTime(selectedDate, selectedTime, false)
|
|
const durationIndex = this.durationOptions.findIndex(item => item === this.formData.duration)
|
|
const expectedStayRange = buildExpectedStayRange(selectedDate, durationIndex)
|
|
const payload = {
|
|
intendedAreaCode: this.formData.intendedAreaCode || (this.sourceData && this.sourceData.areaCode ? this.sourceData.areaCode : null),
|
|
intendedRoomTypeCode: this.formData.intendedRoomTypeCode || (this.sourceData && this.sourceData.roomTypeCode ? this.sourceData.roomTypeCode : null),
|
|
roomSlotHeight: 1,
|
|
hobbiesAndInterestsTagKeys: null,
|
|
lifestyleHabitsTagKeys: null,
|
|
remark: null,
|
|
start: expectedStayRange.start,
|
|
end: expectedStayRange.end,
|
|
appointmentViewingTime
|
|
}
|
|
|
|
this.isSubmitting = true
|
|
uni.showLoading({ title: this.$tr('提交中...'), mask: true })
|
|
return submitViewingApplicationForm(payload)
|
|
.then(() => {
|
|
uni.hideLoading()
|
|
uni.showModal({
|
|
title: this.$tr('预约成功'),
|
|
content: this.$tr('您的预约看房申请已提交,请等待管家联系'),
|
|
showCancel: false,
|
|
confirmColor: '#01BEFF',
|
|
success: () => {
|
|
uni.redirectTo({
|
|
url: '/pkgService/my_application/my_application'
|
|
})
|
|
}
|
|
})
|
|
})
|
|
.catch((error) => {
|
|
console.error('submit viewing application failed', error)
|
|
uni.hideLoading()
|
|
uni.showToast({
|
|
title: (error && (error.message || error.msg)) || this.$tr('预约提交失败'),
|
|
icon: 'none'
|
|
})
|
|
})
|
|
.finally(() => {
|
|
this.isSubmitting = false
|
|
})
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style scoped lang="scss">
|
|
.book-viewing-page {
|
|
min-height: 100vh;
|
|
background: linear-gradient(180deg, #F0F6FF 0%, #F8FAFF 100%);
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.nav-title {
|
|
font-size: 34rpx;
|
|
font-weight: bold;
|
|
color: #1D2129;
|
|
}
|
|
|
|
.content-wrapper {
|
|
flex: 1;
|
|
padding-bottom: calc(140rpx + 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;
|
|
}
|
|
|
|
.info-left {
|
|
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;
|
|
}
|
|
|
|
.info-desc {
|
|
font-size: 24rpx;
|
|
opacity: 0.9;
|
|
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;
|
|
}
|
|
|
|
/* 通用表单卡片 */
|
|
.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);
|
|
}
|
|
|
|
.card-header {
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.card-title {
|
|
font-size: 34rpx;
|
|
font-weight: bold;
|
|
color: #1D2129;
|
|
margin-right: 16rpx;
|
|
}
|
|
|
|
.card-subtitle {
|
|
font-size: 24rpx;
|
|
color: #86909C;
|
|
}
|
|
|
|
/* 日期选择 */
|
|
.date-scroll {
|
|
width: 100%;
|
|
white-space: nowrap;
|
|
margin-bottom: 30rpx;
|
|
}
|
|
|
|
.date-flex {
|
|
display: inline-flex;
|
|
gap: 20rpx;
|
|
padding-bottom: 10rpx;
|
|
}
|
|
|
|
.date-item {
|
|
width: 110rpx;
|
|
height: 130rpx;
|
|
background: #F4F8FF;
|
|
border-radius: 16rpx;
|
|
flex-shrink: 0;
|
|
border: 2rpx solid transparent;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.date-item--active {
|
|
background: #EAF0FF;
|
|
border-color: #01BEFF;
|
|
}
|
|
|
|
.date-week {
|
|
font-size: 24rpx;
|
|
color: #86909C;
|
|
margin-bottom: 8rpx;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.date-item--active .date-week {
|
|
color: #01BEFF;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.date-day {
|
|
font-size: 28rpx;
|
|
color: #1D2129;
|
|
font-weight: 500;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.date-item--active .date-day {
|
|
color: #01BEFF;
|
|
}
|
|
|
|
/* 时间段选择 */
|
|
.time-scroll {
|
|
width: 100%;
|
|
}
|
|
|
|
.time-flex {
|
|
display: inline-flex;
|
|
gap: 20rpx;
|
|
padding-bottom: 8rpx;
|
|
}
|
|
|
|
.time-slot {
|
|
width: 220rpx;
|
|
height: 72rpx;
|
|
line-height: 72rpx;
|
|
text-align: center;
|
|
background: #F4F8FF;
|
|
border-radius: 12rpx;
|
|
font-size: 26rpx;
|
|
color: #4E5969;
|
|
border: 2rpx solid transparent;
|
|
transition: all 0.3s ease;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.time-slot--active {
|
|
background: #01BEFF;
|
|
color: #ffffff;
|
|
font-weight: bold;
|
|
box-shadow: 0 8rpx 16rpx rgba(1, 190, 255, 0.2);
|
|
}
|
|
|
|
/* 需求字段 */
|
|
.field-item {
|
|
margin-bottom: 40rpx;
|
|
}
|
|
|
|
.field-item:last-child {
|
|
margin-bottom: 0;
|
|
}
|
|
|
|
.field-label {
|
|
font-size: 28rpx;
|
|
color: #1D2129;
|
|
font-weight: bold;
|
|
margin-bottom: 24rpx;
|
|
}
|
|
|
|
/* 标签选择 */
|
|
.tag-grid {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 20rpx;
|
|
}
|
|
|
|
.tag-item {
|
|
padding: 0 32rpx;
|
|
height: 68rpx;
|
|
line-height: 68rpx;
|
|
background: #F4F8FF;
|
|
border-radius: 34rpx;
|
|
font-size: 26rpx;
|
|
color: #4E5969;
|
|
border: 2rpx solid transparent;
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.tag-item--active {
|
|
background: #EAF0FF;
|
|
border-color: #01BEFF;
|
|
color: #01BEFF;
|
|
font-weight: bold;
|
|
}
|
|
|
|
/* 输入框 */
|
|
.input-box {
|
|
background: #F4F8FF;
|
|
border-radius: 16rpx;
|
|
height: 88rpx;
|
|
padding: 0 30rpx;
|
|
}
|
|
|
|
.input-icon {
|
|
font-size: 36rpx;
|
|
color: #A1B0C4;
|
|
margin-right: 16rpx;
|
|
}
|
|
|
|
.custom-input {
|
|
flex: 1;
|
|
font-size: 28rpx;
|
|
color: #1D2129;
|
|
}
|
|
|
|
/* 底部按钮 */
|
|
.footer-bar {
|
|
position: fixed;
|
|
bottom: 0;
|
|
left: 0;
|
|
width: 100%;
|
|
background: #ffffff;
|
|
padding: 24rpx 40rpx;
|
|
box-shadow: 0 -4rpx 24rpx rgba(0, 0, 0, 0.04);
|
|
z-index: 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;
|
|
font-size: 32rpx;
|
|
font-weight: bold;
|
|
letter-spacing: 2rpx;
|
|
box-shadow: 0 12rpx 24rpx rgba(1, 190, 255, 0.25);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.submit-btn:active {
|
|
transform: scale(0.98);
|
|
opacity: 0.9;
|
|
}
|
|
</style>
|