760 lines
19 KiB
Vue
760 lines
19 KiB
Vue
<template>
|
||
<view class="page">
|
||
<view class="scenic-card">
|
||
<image class="scenic-img" :src="scenic.image" mode="aspectFill" />
|
||
<view class="scenic-info">
|
||
<text class="scenic-name">{{ scenic.name }}</text>
|
||
<view class="scenic-row">
|
||
<view class="scenic-icon scenic-icon--pin" />
|
||
<text class="scenic-text">{{ scenic.address }}</text>
|
||
</view>
|
||
<view class="scenic-row">
|
||
<view class="scenic-icon scenic-icon--clock" />
|
||
<text class="scenic-text">{{ scenic.hours }}</text>
|
||
</view>
|
||
<text class="scenic-tip">持{{ cardModelName }}免费入园,单人单日仅可预约1次</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="date-card">
|
||
<text class="section-title">选择预约日期</text>
|
||
<scroll-view scroll-x class="date-scroll">
|
||
<view class="date-list">
|
||
<view
|
||
v-for="d in dateOptions"
|
||
:key="d.key"
|
||
class="date-item"
|
||
:class="{
|
||
'date-item--active': selectedDate === d.key,
|
||
'date-item--disabled': d.disabled || (d.stock != null && d.stock <= 0)
|
||
}"
|
||
@tap="!(d.disabled || (d.stock != null && d.stock <= 0)) && (selectedDate = d.key)"
|
||
>
|
||
<text class="date-week">{{ d.week }}</text>
|
||
<text class="date-day">{{ d.label }}</text>
|
||
<text v-if="d.disabled" class="date-stock date-stock--empty">不可约</text>
|
||
<text v-else-if="d.stock == null" class="date-stock">无限库存</text>
|
||
<text v-else-if="d.stock >= 50" class="date-stock">可预约</text>
|
||
<text v-else-if="d.stock > 0" class="date-stock">余{{ d.stock }}位</text>
|
||
<text v-else class="date-stock date-stock--empty">已约满</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<view v-if="selectedSessions.length > 0" class="session-section">
|
||
<text class="session-title">选择入园场次</text>
|
||
<view class="session-list">
|
||
<view
|
||
v-for="s in selectedSessions"
|
||
:key="s.id"
|
||
class="session-item"
|
||
:class="{
|
||
'session-item--active': selectedSession === s.id && (s.stock == null || s.stock > 0),
|
||
'session-item--disabled': s.stock != null && s.stock <= 0
|
||
}"
|
||
@tap="(s.stock == null || s.stock > 0) && (selectedSession = s.id)"
|
||
>
|
||
<text class="session-time">{{ s.time }}</text>
|
||
<text v-if="s.stock == null" class="session-stock session-stock--available">可预约</text>
|
||
<text v-else-if="s.stock >= 50" class="session-stock session-stock--available">可预约</text>
|
||
<text v-else-if="s.stock > 0" class="session-stock session-stock--limited">余{{ s.stock }}位</text>
|
||
<text v-else class="session-stock session-stock--empty">已约满</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view v-else-if="selectedDateObj?.disabled" class="no-session-tip">
|
||
<text class="no-session-tip__text no-session-tip__text--error">{{ selectedDateObj.reason || '该日期不可预约' }}</text>
|
||
</view>
|
||
<view v-else-if="selectedDate && selectedDateStock === 0" class="no-session-tip">
|
||
<text class="no-session-tip__text">该日期已约满</text>
|
||
</view>
|
||
<view v-else-if="selectedDate && selectedDateStock > 0 && !selectedSessions.length" class="no-session-tip">
|
||
<text class="no-session-tip__text">该日期无需选择场次,直接预约即可</text>
|
||
</view>
|
||
<text class="date-tip">仅可预约近{{ appointmentDays || 3 }}日内时段</text>
|
||
</view>
|
||
|
||
<view class="user-card">
|
||
<text class="section-title">预约人信息</text>
|
||
<view class="user-row">
|
||
<text class="user-label">姓名</text>
|
||
<text class="user-value">{{ userName }}</text>
|
||
</view>
|
||
<view class="user-row">
|
||
<text class="user-label">身份证号</text>
|
||
<text class="user-value">{{ userIdCard }}</text>
|
||
</view>
|
||
<text class="user-warn">预约信息必须与持卡实名一致,不可更换他人</text>
|
||
</view>
|
||
|
||
<view class="notice-card" v-if="bookingNotice">
|
||
<text class="notice-title">预约须知</text>
|
||
<view class="notice-list">
|
||
<view class="notice-item">
|
||
<view class="notice-dot" />
|
||
<text class="notice-text">{{ bookingNotice }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="notice-link" @tap="goFaq">
|
||
<text class="notice-link__text">查看完整FAQ</text>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="safe-bottom" />
|
||
|
||
<view class="bottom-bar">
|
||
<button
|
||
class="btn-submit"
|
||
:class="{ 'btn-submit--disabled': !selectedDate }"
|
||
:disabled="!selectedDate"
|
||
@tap="handleSubmit"
|
||
>
|
||
<text class="btn-submit__text">提交预约</text>
|
||
</button>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref, computed } from 'vue'
|
||
import { onLoad } from '@dcloudio/uni-app'
|
||
import { post } from '../../../../api/request'
|
||
import { BASE_URL } from '../../../../config'
|
||
|
||
interface ReserveOptionSession {
|
||
id: string | number
|
||
time: string
|
||
stock: number
|
||
}
|
||
|
||
interface DateOption {
|
||
key: string
|
||
week: string
|
||
label: string
|
||
stock: number | null
|
||
sessions: ReserveOptionSession[]
|
||
disabled?: boolean
|
||
reason?: string
|
||
}
|
||
|
||
const scenic = ref({ name: '', address: '', hours: '', image: '' })
|
||
const userName = ref('')
|
||
const userIdCard = ref('')
|
||
const bookingNotice = ref('')
|
||
const cardModelName = ref('')
|
||
const appointmentDays = ref<number | null>(null)
|
||
|
||
const reserveParams = ref({
|
||
scenicId: 0,
|
||
channel: '',
|
||
thirdId: '',
|
||
cardNum: '',
|
||
mobile: '',
|
||
cardModelName: ''
|
||
})
|
||
|
||
const dateOptions = ref<DateOption[]>([])
|
||
const selectedDate = ref('')
|
||
const selectedSession = ref<string | number>('')
|
||
const submitting = ref(false)
|
||
|
||
const weekNames = ['周日', '周一', '周二', '周三', '周四', '周五', '周六']
|
||
|
||
function formatDateDisplay(dateStr: string): { week: string; label: string } {
|
||
const d = new Date(dateStr)
|
||
const today = new Date()
|
||
today.setHours(0, 0, 0, 0)
|
||
const tomorrow = new Date(today)
|
||
tomorrow.setDate(tomorrow.getDate() + 1)
|
||
const diff = Math.round((d.getTime() - today.getTime()) / 86400000)
|
||
const week = diff === 1 ? '明天' : diff === 2 ? '后天' : weekNames[d.getDay()]
|
||
const label = `${d.getMonth() + 1}月${d.getDate()}日`
|
||
return { week, label }
|
||
}
|
||
|
||
const selectedDateObj = computed(() => {
|
||
if (!selectedDate.value) return null
|
||
return dateOptions.value.find(o => o.key === selectedDate.value) || null
|
||
})
|
||
|
||
const selectedSessions = computed(() => {
|
||
if (!selectedDate.value || selectedDateObj.value?.disabled) return []
|
||
const d = dateOptions.value.find(d => d.key === selectedDate.value)
|
||
const sessions = d?.sessions || []
|
||
if (sessions.length > 0 && !sessions.find(s => s.id === selectedSession.value)) {
|
||
const available = sessions.find(s => s.stock == null || s.stock > 0)
|
||
selectedSession.value = available ? available.id : ''
|
||
}
|
||
return sessions
|
||
})
|
||
|
||
const selectedDateStock = computed(() => {
|
||
if (!selectedDate.value) return -1
|
||
const d = dateOptions.value.find(o => o.key === selectedDate.value)
|
||
if (!d) return 0
|
||
return d.stock == null ? 1 : d.stock
|
||
})
|
||
|
||
onLoad(async (query: any) => {
|
||
const resourceId = query?.resourceId
|
||
if (!resourceId) return
|
||
const cardNumber = query?.cardNumber || ''
|
||
const cardModelId = query?.cardModelId || ''
|
||
const phone = (uni.getStorageSync('phone') as string) || ''
|
||
|
||
try {
|
||
const res = await post<any>('/mpReserve/queryReserveOptions', {
|
||
resourceId: parseInt(resourceId),
|
||
phone,
|
||
cardNumber: cardNumber || undefined,
|
||
})
|
||
if (res) {
|
||
scenic.value = {
|
||
name: res.scenicName || '',
|
||
address: res.address || '',
|
||
hours: res.hours || '',
|
||
image: res.scenicImage || ''
|
||
}
|
||
userName.value = res.userName || ''
|
||
userIdCard.value = res.userIdCard || ''
|
||
bookingNotice.value = Array.isArray(res.bookingNotice) ? res.bookingNotice.join('\n') : (res.bookingNotice || '')
|
||
cardModelName.value = res.cardModelName || ''
|
||
appointmentDays.value = (res.dates || []).length
|
||
reserveParams.value = {
|
||
scenicId: parseInt(resourceId),
|
||
channel: 'Channel_SZH',
|
||
thirdId: cardModelId,
|
||
cardNum: cardNumber,
|
||
mobile: phone,
|
||
cardModelName: res.cardModelName || ''
|
||
}
|
||
dateOptions.value = (res.dates || []).map((d: any) => ({
|
||
key: d.key,
|
||
week: d.week,
|
||
label: d.label,
|
||
stock: d.stock,
|
||
sessions: d.sessions || [],
|
||
disabled: d.disabled,
|
||
reason: d.reason,
|
||
}))
|
||
const firstAvailable = dateOptions.value.find(d => d.stock == null || d.stock > 0)
|
||
if (firstAvailable) selectedDate.value = firstAvailable.key
|
||
}
|
||
} catch (err: any) {
|
||
const mockStocks: (number | null)[] = [null, 200, 0]
|
||
const mockSessions: Record<string, ReserveOptionSession[]> = {
|
||
['mock0']: [
|
||
{ id: 's1', time: '08:00-10:00', stock: 56 },
|
||
{ id: 's2', time: '10:00-12:00', stock: 42 },
|
||
{ id: 's3', time: '14:00-16:00', stock: 58 },
|
||
],
|
||
['mock1']: [
|
||
{ id: 's4', time: '08:00-12:00', stock: 100 },
|
||
{ id: 's5', time: '12:00-18:00', stock: 100 },
|
||
],
|
||
}
|
||
dateOptions.value = Array.from({ length: 3 }, (_, i) => {
|
||
const d = new Date()
|
||
d.setDate(d.getDate() + i + 1)
|
||
const month = d.getMonth() + 1
|
||
const day = d.getDate()
|
||
const key = `${d.getFullYear()}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`
|
||
const { week, label } = formatDateDisplay(key)
|
||
return {
|
||
key,
|
||
week,
|
||
label,
|
||
stock: mockStocks[i],
|
||
sessions: mockSessions[`mock${i}`] || [],
|
||
}
|
||
})
|
||
appointmentDays.value = 3
|
||
scenic.value = {
|
||
name: '武功山金顶景区',
|
||
address: '江西省萍乡市芦溪县武功山风景名胜区',
|
||
hours: '08:00-18:00',
|
||
image: 'https://images.unsplash.com/photo-1513415564515-763d91423bdd?fm=jpg&q=80&w=800&h=400&fit=crop',
|
||
}
|
||
bookingNotice.value = '请提前10分钟到达景区检票口;\n入园需出示预约码和身份证;\n如无法按时入园请提前取消预约。'
|
||
userName.value = '张三'
|
||
userIdCard.value = '360302199001011234'
|
||
cardModelName.value = '赣湘全域旅游年卡'
|
||
const firstAvailable = dateOptions.value.find(d => d.stock == null || d.stock > 0)
|
||
if (firstAvailable) selectedDate.value = firstAvailable.key
|
||
}
|
||
})
|
||
|
||
async function handleSubmit() {
|
||
if (!selectedDate.value || submitting.value) return
|
||
|
||
const dateObj = dateOptions.value.find(d => d.key === selectedDate.value)
|
||
if (dateObj?.disabled) {
|
||
uni.showToast({ title: dateObj.reason || '该日期不可预约', icon: 'none' })
|
||
return
|
||
}
|
||
if (dateObj && dateObj.stock != null && dateObj.stock <= 0) {
|
||
uni.showToast({ title: '该日期已约满', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
submitting.value = true
|
||
try {
|
||
const session = selectedSessions.value.find(s => s.id === selectedSession.value)
|
||
const p = reserveParams.value
|
||
const result = await post<any>(`${BASE_URL}/zhy-api/cardBag/appoint`, {
|
||
scenicId: String(p.scenicId),
|
||
channel: p.channel,
|
||
thirdId: p.thirdId,
|
||
cardNum: p.cardNum,
|
||
mobile: p.mobile,
|
||
cardModelName: p.cardModelName,
|
||
appointDate: selectedDate.value,
|
||
timeId: session ? String(session.id) : '',
|
||
name: userName.value,
|
||
idNo: userIdCard.value,
|
||
})
|
||
uni.showToast({ title: '预约成功', icon: 'success' })
|
||
setTimeout(() => {
|
||
uni.navigateTo({
|
||
url: `/packages/user/pages/reserve/success?appointId=${result}&cardNumber=${p.cardNum}&cardModelId=${p.thirdId}`
|
||
})
|
||
}, 1500)
|
||
} catch (e: any) {
|
||
uni.showToast({ title: e?.message || '预约失败', icon: 'none' })
|
||
} finally {
|
||
submitting.value = false
|
||
}
|
||
}
|
||
|
||
function goFaq() {
|
||
uni.navigateTo({ url: '/packages/content/pages/faq' })
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
$bar-height: 120rpx;
|
||
|
||
.page {
|
||
min-height: 100vh;
|
||
background: $color-background;
|
||
padding-bottom: calc(#{$bar-height} + env(safe-area-inset-bottom));
|
||
font-family: $font-family-body;
|
||
}
|
||
|
||
.scenic-card {
|
||
margin: 24rpx 24rpx 0;
|
||
background: $color-card;
|
||
border-radius: $radius-lg;
|
||
overflow: hidden;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.scenic-img {
|
||
width: 100%;
|
||
height: 280rpx;
|
||
}
|
||
|
||
.scenic-info {
|
||
padding: 28rpx;
|
||
}
|
||
|
||
.scenic-name {
|
||
display: block;
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-base;
|
||
font-weight: $font-weight-bold;
|
||
color: $uv-main-color;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.scenic-row {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.scenic-icon {
|
||
width: 24rpx;
|
||
height: 24rpx;
|
||
margin-right: 8rpx;
|
||
flex-shrink: 0;
|
||
|
||
&--pin {
|
||
border: 3rpx solid $uv-tips-color;
|
||
border-radius: 50% 50% 50% 0;
|
||
transform: rotate(-45deg);
|
||
position: relative;
|
||
&::after {
|
||
content: '';
|
||
width: 10rpx;
|
||
height: 10rpx;
|
||
border-radius: 50%;
|
||
border: 2rpx solid $uv-tips-color;
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
transform: translate(-50%, -50%);
|
||
}
|
||
}
|
||
|
||
&--clock {
|
||
border: 3rpx solid $uv-tips-color;
|
||
border-radius: 50%;
|
||
position: relative;
|
||
&::before {
|
||
content: '';
|
||
width: 2rpx;
|
||
height: 10rpx;
|
||
background: $uv-tips-color;
|
||
position: absolute;
|
||
top: 4rpx;
|
||
left: 50%;
|
||
transform: translateX(-50%);
|
||
}
|
||
&::after {
|
||
content: '';
|
||
width: 8rpx;
|
||
height: 2rpx;
|
||
background: $uv-tips-color;
|
||
position: absolute;
|
||
top: 50%;
|
||
left: 50%;
|
||
}
|
||
}
|
||
}
|
||
|
||
.scenic-text {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-sm;
|
||
color: $uv-tips-color;
|
||
}
|
||
|
||
.scenic-tip {
|
||
display: block;
|
||
font-family: $font-family-body;
|
||
font-size: 22rpx;
|
||
color: $uv-placeholder-color;
|
||
margin-top: 16rpx;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.date-card {
|
||
margin: 24rpx 32rpx 0;
|
||
background: $color-card;
|
||
border-radius: $radius-lg;
|
||
padding: 32rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.section-title {
|
||
display: block;
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-lg;
|
||
font-weight: $font-weight-medium;
|
||
color: $uv-main-color;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.date-scroll {
|
||
white-space: nowrap;
|
||
}
|
||
|
||
.date-list {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.date-item {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 16rpx 12rpx;
|
||
border-radius: 16rpx;
|
||
border: 2rpx solid $uv-primary;
|
||
transition: all $transition-fast;
|
||
|
||
&--active {
|
||
background: $uv-primary;
|
||
border-color: $uv-primary;
|
||
}
|
||
}
|
||
|
||
.date-week {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-xxs;
|
||
color: $uv-tips-color;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.date-item--active .date-week {
|
||
color: rgba(255, 255, 255, 0.8);
|
||
}
|
||
|
||
.date-day {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-xs;
|
||
font-weight: $font-weight-bold;
|
||
color: $uv-main-color;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.date-item--active .date-day {
|
||
color: #ffffff;
|
||
}
|
||
|
||
.date-stock {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-xxs;
|
||
color: $uv-main-color;
|
||
|
||
&--empty {
|
||
color: $uv-placeholder-color;
|
||
}
|
||
}
|
||
|
||
.date-item--active .date-stock {
|
||
color: rgba(255, 255, 255, 0.7);
|
||
}
|
||
|
||
.date-item--disabled {
|
||
border-color: $uv-border-color;
|
||
|
||
.date-week,
|
||
.date-day,
|
||
.date-stock {
|
||
color: $uv-placeholder-color;
|
||
}
|
||
}
|
||
|
||
.session-section {
|
||
margin-top: 24rpx;
|
||
padding-top: 24rpx;
|
||
border-top: 1rpx solid $uv-border-color;
|
||
}
|
||
|
||
.session-title {
|
||
display: block;
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-sm;
|
||
font-weight: $font-weight-medium;
|
||
color: $uv-main-color;
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.session-list {
|
||
display: flex;
|
||
flex-wrap: wrap;
|
||
gap: 16rpx;
|
||
}
|
||
|
||
.session-item {
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
padding: 16rpx 28rpx;
|
||
border-radius: 12rpx;
|
||
border: 2rpx solid $uv-border-color;
|
||
transition: all $transition-fast;
|
||
|
||
&--active {
|
||
background: rgba(60, 156, 255, 0.08);
|
||
border-color: $uv-primary;
|
||
}
|
||
|
||
&--disabled {
|
||
opacity: 0.5;
|
||
}
|
||
}
|
||
|
||
.session-time {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-xs;
|
||
font-weight: $font-weight-medium;
|
||
color: $uv-main-color;
|
||
margin-bottom: 4rpx;
|
||
}
|
||
|
||
.session-item--active .session-time {
|
||
color: $uv-primary;
|
||
}
|
||
|
||
.session-stock {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-xxs;
|
||
color: $uv-placeholder-color;
|
||
|
||
&--empty {
|
||
color: $uv-error;
|
||
}
|
||
}
|
||
|
||
.no-session-tip {
|
||
margin-top: 24rpx;
|
||
padding-top: 24rpx;
|
||
border-top: 1rpx solid $uv-border-color;
|
||
}
|
||
|
||
.no-session-tip__text {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-xxs;
|
||
color: $uv-placeholder-color;
|
||
}
|
||
|
||
.no-session-tip__text--error {
|
||
color: $uv-error;
|
||
font-weight: $font-weight-medium;
|
||
}
|
||
|
||
.date-tip {
|
||
display: block;
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-xxs;
|
||
color: $uv-placeholder-color;
|
||
margin-top: 16rpx;
|
||
}
|
||
|
||
.user-card {
|
||
margin: 24rpx 32rpx 0;
|
||
background: $color-card;
|
||
border-radius: $radius-lg;
|
||
padding: 32rpx;
|
||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.user-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 16rpx 0;
|
||
}
|
||
|
||
.user-label {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-sm;
|
||
color: $uv-main-color;
|
||
}
|
||
|
||
.user-value {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-sm;
|
||
color: $uv-content-color;
|
||
}
|
||
|
||
.user-warn {
|
||
display: block;
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-sm;
|
||
color: $uv-error;
|
||
margin-top: 12rpx;
|
||
}
|
||
|
||
.notice-card {
|
||
margin: 24rpx 32rpx 0;
|
||
background: #eef4ff;
|
||
border-radius: $radius-lg;
|
||
padding: 32rpx;
|
||
}
|
||
|
||
.notice-title {
|
||
display: block;
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-lg;
|
||
font-weight: $font-weight-bold;
|
||
color: $uv-main-color;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.notice-list {
|
||
margin-bottom: 16rpx;
|
||
}
|
||
|
||
.notice-item {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.notice-dot {
|
||
width: 8rpx;
|
||
height: 8rpx;
|
||
border-radius: 50%;
|
||
background: $uv-primary;
|
||
flex-shrink: 0;
|
||
margin-top: 14rpx;
|
||
margin-right: 12rpx;
|
||
}
|
||
|
||
.notice-text {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-sm;
|
||
color: $uv-tips-color;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.notice-link {
|
||
&:active { opacity: 0.7; }
|
||
}
|
||
|
||
.notice-link__text {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-sm;
|
||
color: $uv-primary;
|
||
font-weight: $font-weight-medium;
|
||
}
|
||
|
||
.safe-bottom {
|
||
height: 24rpx;
|
||
}
|
||
|
||
.bottom-bar {
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
width: 100%;
|
||
box-sizing: border-box;
|
||
min-height: $bar-height;
|
||
background: $color-card;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20rpx 48rpx;
|
||
padding-bottom: env(safe-area-inset-bottom);
|
||
box-shadow: 0 -4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||
z-index: 100;
|
||
}
|
||
|
||
.btn-submit {
|
||
width: 100%;
|
||
height: 80rpx;
|
||
border-radius: 40rpx;
|
||
background: $uv-primary;
|
||
border: none;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
transition: all $transition-fast;
|
||
|
||
&::after { display: none; }
|
||
|
||
&:active:not(.btn-submit--disabled) {
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
&--disabled {
|
||
background: $uv-bg-color;
|
||
}
|
||
}
|
||
|
||
.btn-submit__text {
|
||
font-family: $font-family-body;
|
||
font-size: $font-size-lg;
|
||
font-weight: $font-weight-bold;
|
||
color: #ffffff;
|
||
}
|
||
|
||
.btn-submit--disabled .btn-submit__text {
|
||
color: $uv-placeholder-color;
|
||
}
|
||
</style>
|