1238 lines
36 KiB
Plaintext
1238 lines
36 KiB
Plaintext
<template>
|
||
<view class="booking-page-shell">
|
||
<view class="detail-fixed-header">
|
||
<ServicePageHeader title="康养预约" fallback-url="/pages/mall/consumer/home-service/index"></ServicePageHeader>
|
||
</view>
|
||
<view class="detail-header-placeholder" :style="{ height: headerHeight + 'px' }"></view>
|
||
<scroll-view class="detail-scroll" scroll-y="true">
|
||
<view class="summary-card">
|
||
<view class="summary-top-row">
|
||
<view class="summary-cover">
|
||
<text class="summary-cover-text">{{ serviceImageText }}</text>
|
||
</view>
|
||
<view class="summary-main">
|
||
<text class="summary-title">{{ serviceTitle }}</text>
|
||
<text class="summary-desc">{{ serviceSubtitle }}</text>
|
||
<text class="summary-meta">服务时长:{{ serviceDuration }}</text>
|
||
<text class="summary-meta">有效期:{{ serviceValidity }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="summary-tag-row">
|
||
<text v-for="tag in summaryGuaranteeTags" :key="tag.id" class="summary-tag">{{ tag.label }}</text>
|
||
</view>
|
||
<view class="summary-price-row">
|
||
<text class="summary-price-prefix">¥</text>
|
||
<text class="summary-price">{{ minPriceText }}</text>
|
||
<text class="summary-price-unit">起</text>
|
||
</view>
|
||
</view>
|
||
|
||
<ServicePanel title="Step1 服务地址" subtitle="确认上门地址、楼层与入户条件。">
|
||
<view class="form-item">
|
||
<text class="label">上门地址</text>
|
||
<view class="value-card" @click="selectAddress">
|
||
<text class="value-card-text">{{ addressLineText }}</text>
|
||
<text class="value-card-action">点击更换</text>
|
||
</view>
|
||
</view>
|
||
<view class="form-grid">
|
||
<view class="form-grid-item">
|
||
<text class="label">所在区域</text>
|
||
<input v-model="careArea" class="input" placeholder="请输入区域" />
|
||
</view>
|
||
<view class="form-grid-item">
|
||
<text class="label">楼层</text>
|
||
<input v-model="careFloor" class="input" placeholder="如 6 楼" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item form-item-last">
|
||
<text class="label">是否有电梯</text>
|
||
<view class="pill-row">
|
||
<view :class="['pill', careHasElevator ? 'pill-active' : '']" @click="setElevator(true)">
|
||
<text :class="['pill-text', careHasElevator ? 'pill-text-active' : '']">有电梯</text>
|
||
</view>
|
||
<view :class="['pill', !careHasElevator ? 'pill-active' : '']" @click="setElevator(false)">
|
||
<text :class="['pill-text', !careHasElevator ? 'pill-text-active' : '']">无电梯</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="Step2 服务机构 / 服务人员" subtitle="当前优先展示平台推荐机构,后续可接入真实选择接口。">
|
||
<view class="agency-card">
|
||
<view class="agency-top-row">
|
||
<view>
|
||
<text class="agency-name">{{ agency.name }}</text>
|
||
<text class="agency-meta">{{ agency.distance }} | 评分 {{ agency.rating }}</text>
|
||
</view>
|
||
<text class="agency-badge">平台认证</text>
|
||
</view>
|
||
<text class="agency-desc">{{ agency.summary }}</text>
|
||
<text class="agency-desc">服务资质:护理员上门、服务留痕、预约前电话确认</text>
|
||
<view class="action-row">
|
||
<view class="ghost-btn" @click="handleAgencyReplace"><text class="ghost-btn-text">更换机构</text></view>
|
||
<view class="ghost-btn" @click="handleAgencyContact"><text class="ghost-btn-text">立即联系</text></view>
|
||
<view class="ghost-btn" @click="handleAgencyNavigate"><text class="ghost-btn-text">立即导航</text></view>
|
||
</view>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="Step3 上门时间" subtitle="先选日期和时间段,再提交预约。">
|
||
<scroll-view class="booking-day-scroll" direction="horizontal" :show-scrollbar="false">
|
||
<view class="booking-day-row">
|
||
<view
|
||
v-for="item in bookingDays"
|
||
:key="item.id"
|
||
:class="['booking-day-card', selectedDayId == item.id ? 'booking-day-card-active' : '']"
|
||
@click="selectDay(item.id)"
|
||
>
|
||
<text :class="['booking-day-label', selectedDayId == item.id ? 'booking-day-label-active' : '']">{{ item.label }}</text>
|
||
<text :class="['booking-day-date', selectedDayId == item.id ? 'booking-day-date-active' : '']">{{ item.dateText }}</text>
|
||
<text :class="['booking-day-weekday', selectedDayId == item.id ? 'booking-day-weekday-active' : '']">{{ item.weekday }}</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
<view class="booking-slot-grid">
|
||
<view
|
||
v-for="item in bookingSlots"
|
||
:key="item.id"
|
||
:class="['booking-slot-card', selectedSlotId == item.id ? 'booking-slot-card-active' : '', item.available ? '' : 'booking-slot-card-disabled']"
|
||
@click="selectSlot(item.id, item.available)"
|
||
>
|
||
<text :class="['booking-slot-label', selectedSlotId == item.id ? 'booking-slot-label-active' : '']">{{ item.label }}</text>
|
||
</view>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="Step4 服务对象信息" subtitle="补全被照护人情况,便于机构判断服务方案。">
|
||
<view class="form-grid">
|
||
<view class="form-grid-item">
|
||
<text class="label">服务对象姓名</text>
|
||
<input v-model="recipientName" class="input" placeholder="请输入姓名" />
|
||
</view>
|
||
<view class="form-grid-item">
|
||
<text class="label">年龄</text>
|
||
<input v-model="recipientAgeText" class="input" type="number" placeholder="请输入年龄" />
|
||
</view>
|
||
</view>
|
||
<view class="form-grid">
|
||
<view class="form-grid-item">
|
||
<text class="label">性别</text>
|
||
<view class="pill-row">
|
||
<view :class="['pill', recipientGender == '男' ? 'pill-active' : '']" @click="setRecipientGender('男')">
|
||
<text :class="['pill-text', recipientGender == '男' ? 'pill-text-active' : '']">男</text>
|
||
</view>
|
||
<view :class="['pill', recipientGender == '女' ? 'pill-active' : '']" @click="setRecipientGender('女')">
|
||
<text :class="['pill-text', recipientGender == '女' ? 'pill-text-active' : '']">女</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-grid-item">
|
||
<text class="label">与下单人关系</text>
|
||
<input v-model="recipientRelation" class="input" placeholder="如 母亲 / 父亲 / 本人" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">身体情况</text>
|
||
<textarea v-model="recipientHealthStatus" class="textarea" placeholder="请输入身体情况,如术后恢复、慢病随访、行动不便"></textarea>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">行动能力</text>
|
||
<input v-model="recipientMobilityLevel" class="input" placeholder="如 需要搀扶 / 轮椅出行 / 可自理" />
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">风险标签</text>
|
||
<view class="tag-row">
|
||
<view
|
||
v-for="item in careRiskOptions"
|
||
:key="item.id"
|
||
:class="['tag-chip', item.selected ? 'tag-chip-active' : '']"
|
||
@click="toggleRiskOption(item.id)"
|
||
>
|
||
<text :class="['tag-chip-text', item.selected ? 'tag-chip-text-active' : '']">{{ item.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item form-item-last">
|
||
<text class="label">家属陪同</text>
|
||
<view class="pill-row">
|
||
<view :class="['pill', recipientNeedFamilyPresent ? 'pill-active' : '']" @click="setFamilyPresent(true)">
|
||
<text :class="['pill-text', recipientNeedFamilyPresent ? 'pill-text-active' : '']">需要家属在场</text>
|
||
</view>
|
||
<view :class="['pill', !recipientNeedFamilyPresent ? 'pill-active' : '']" @click="setFamilyPresent(false)">
|
||
<text :class="['pill-text', !recipientNeedFamilyPresent ? 'pill-text-active' : '']">可独立服务</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="Step5 联系人信息" subtitle="保留现有提交流程所需联系人字段。">
|
||
<view class="form-grid">
|
||
<view class="form-grid-item">
|
||
<text class="label">联系人姓名</text>
|
||
<input v-model="contactName" class="input" placeholder="请输入联系人姓名" />
|
||
</view>
|
||
<view class="form-grid-item">
|
||
<text class="label">联系电话</text>
|
||
<input v-model="contactPhone" class="input" type="number" placeholder="请输入联系电话" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">性别</text>
|
||
<view class="pill-row">
|
||
<view :class="['pill', contactGender == '先生' ? 'pill-active' : '']" @click="setContactGender('先生')">
|
||
<text :class="['pill-text', contactGender == '先生' ? 'pill-text-active' : '']">先生</text>
|
||
</view>
|
||
<view :class="['pill', contactGender == '女士' ? 'pill-active' : '']" @click="setContactGender('女士')">
|
||
<text :class="['pill-text', contactGender == '女士' ? 'pill-text-active' : '']">女士</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-grid">
|
||
<view class="form-grid-item">
|
||
<text class="label">紧急联系人</text>
|
||
<input v-model="emergencyName" class="input" placeholder="请输入紧急联系人姓名" />
|
||
</view>
|
||
<view class="form-grid-item">
|
||
<text class="label">紧急联系人电话</text>
|
||
<input v-model="emergencyPhone" class="input" type="number" placeholder="请输入紧急联系人电话" />
|
||
</view>
|
||
</view>
|
||
<view class="form-item form-item-last">
|
||
<text class="label">补充备注</text>
|
||
<textarea v-model="remarkText" class="textarea" placeholder="如老人作息、注意事项、上门前沟通重点"></textarea>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="Step6 服务需求" subtitle="选择服务方案和重点需求,仍然兼容现有申请接口。">
|
||
<view class="package-list">
|
||
<view
|
||
v-for="item in servicePackages"
|
||
:key="item.id"
|
||
:class="['package-card', item.selected ? 'package-card-active' : '']"
|
||
@click="selectServicePackage(item.id)"
|
||
>
|
||
<view class="package-top-row">
|
||
<text :class="['package-name', item.selected ? 'package-name-active' : '']">{{ item.name }}</text>
|
||
<text class="package-price">¥{{ formatPrice(item.price) }}</text>
|
||
</view>
|
||
<text class="package-desc">{{ item.desc }}</text>
|
||
<text class="package-duration">{{ item.duration }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="form-item">
|
||
<text class="label">需求标签</text>
|
||
<view class="tag-row">
|
||
<view
|
||
v-for="item in careNeedOptions"
|
||
:key="item.id"
|
||
:class="['tag-chip', item.selected ? 'tag-chip-active' : '']"
|
||
@click="toggleCareNeedOption(item.id)"
|
||
>
|
||
<text :class="['tag-chip-text', item.selected ? 'tag-chip-text-active' : '']">{{ item.label }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<view class="form-item form-item-last">
|
||
<text class="label">详细需求</text>
|
||
<textarea v-model="demandDetailText" class="textarea" placeholder="请输入更详细的服务需求,如血压监测频次、陪诊时间、康复重点"></textarea>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<ServicePanel title="服务说明与保障" subtitle="展示适用人群、免责项与平台保障信息。">
|
||
<view class="info-item">
|
||
<text class="info-label">适用人群</text>
|
||
<text class="info-value">{{ serviceSuitableFor }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="info-label">不包含项目</text>
|
||
<text class="info-value">{{ serviceExcludeText }}</text>
|
||
</view>
|
||
<view class="tag-row tag-row-last">
|
||
<text v-for="item in guaranteeTags" :key="item.id" class="summary-tag">{{ item.label }}</text>
|
||
<text class="summary-tag">上门前确认</text>
|
||
</view>
|
||
</ServicePanel>
|
||
|
||
<view class="detail-page-bottom-space"></view>
|
||
</scroll-view>
|
||
|
||
<view class="booking-bottom-bar">
|
||
<view>
|
||
<text class="booking-bottom-price">¥{{ minPriceText }} 起</text>
|
||
<text class="booking-bottom-time">{{ selectedTimeText }}</text>
|
||
</view>
|
||
<view class="booking-submit-btn" @click="submitBooking">
|
||
<text class="booking-submit-btn-text">立即预约</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { computed, ref } from 'vue'
|
||
import { onLoad } from '@dcloudio/uni-app'
|
||
import ServicePageHeader from '@/components/homeService/ServicePageHeader.uvue'
|
||
import ServicePanel from '@/components/homeService/ServicePanel.uvue'
|
||
import { createHomeServiceApplication, fetchHomeServiceCatalog } from '@/services/homeServiceService.uts'
|
||
import { HomeServiceApplicationDraftType, HomeServiceCatalogType } from '@/types/home-service.uts'
|
||
import {
|
||
BookingDayOptionType,
|
||
BookingTimeSlotType,
|
||
HomeServiceAgencyType,
|
||
HomeServiceGuaranteeItemType,
|
||
getBookingDayOptions,
|
||
getBookingTimeSlots,
|
||
getHomeServiceItems,
|
||
getRecommendedAgency,
|
||
getServiceExcludes,
|
||
getServiceGuarantees
|
||
} from '@/utils/homeServiceUiMock.uts'
|
||
|
||
type CareRecipientInfoType = {
|
||
name: string
|
||
age: number
|
||
gender: string
|
||
relation: string
|
||
healthStatus: string
|
||
mobilityLevel: string
|
||
needFamilyPresent: boolean
|
||
}
|
||
|
||
type CareContactInfoType = {
|
||
contactName: string
|
||
contactPhone: string
|
||
contactGender: string
|
||
emergencyName: string
|
||
emergencyPhone: string
|
||
}
|
||
|
||
type CareAddressInfoType = {
|
||
address: string
|
||
detailAddress: string
|
||
area: string
|
||
floor: string
|
||
hasElevator: boolean
|
||
}
|
||
|
||
type CareNeedOptionType = {
|
||
id: string
|
||
label: string
|
||
selected: boolean
|
||
}
|
||
|
||
type ServicePackageOptionType = {
|
||
id: string
|
||
name: string
|
||
desc: string
|
||
price: number
|
||
duration: string
|
||
selected: boolean
|
||
}
|
||
|
||
type CareRiskOptionType = {
|
||
id: string
|
||
label: string
|
||
selected: boolean
|
||
}
|
||
|
||
const serviceId = ref('svc-001')
|
||
const headerHeight = ref(116)
|
||
const serviceTitle = ref('基础上门护理')
|
||
const serviceSubtitle = ref('覆盖生命体征监测、基础照护、风险提醒。')
|
||
const servicePrice = ref(168)
|
||
const serviceDuration = ref('约 2 小时')
|
||
const serviceValidity = ref('预约后 30 天内可服务')
|
||
const serviceSuitableFor = ref('行动不便、术后恢复、慢病随访老人')
|
||
const serviceImageText = ref('照护')
|
||
const serviceExcludeText = ref('高风险处置、住院陪护、急诊陪诊')
|
||
|
||
const bookingDays = ref<Array<BookingDayOptionType>>([])
|
||
const bookingSlots = ref<Array<BookingTimeSlotType>>([])
|
||
const guaranteeTags = ref<Array<HomeServiceGuaranteeItemType>>([])
|
||
const agency = ref<HomeServiceAgencyType>({
|
||
id: 'agency-001',
|
||
name: '梅江居家护理服务中心',
|
||
distance: '距您 1.2km',
|
||
rating: '4.9',
|
||
summary: '提供基础照护、上门护理和长者陪伴服务。'
|
||
})
|
||
|
||
const defaultCareRecipient: CareRecipientInfoType = {
|
||
name: '李奶奶',
|
||
age: 78,
|
||
gender: '女',
|
||
relation: '母亲',
|
||
healthStatus: '行动不便,需基础照护与血压监测',
|
||
mobilityLevel: '需要搀扶',
|
||
needFamilyPresent: true
|
||
}
|
||
|
||
const defaultCareContact: CareContactInfoType = {
|
||
contactName: '李晓兰',
|
||
contactPhone: '13800138000',
|
||
contactGender: '女士',
|
||
emergencyName: '李先生',
|
||
emergencyPhone: '13900139000'
|
||
}
|
||
|
||
const defaultCareAddress: CareAddressInfoType = {
|
||
address: '梅州市梅江区学海路 18 号',
|
||
detailAddress: '2 栋 602',
|
||
area: '梅江区',
|
||
floor: '6 楼',
|
||
hasElevator: true
|
||
}
|
||
|
||
const careNeedOptions = ref<Array<CareNeedOptionType>>([])
|
||
const careRiskOptions = ref<Array<CareRiskOptionType>>([])
|
||
const servicePackages = ref<Array<ServicePackageOptionType>>([])
|
||
|
||
const selectedDayId = ref('day-1')
|
||
const selectedSlotId = ref('slot-1')
|
||
|
||
const careAddress = ref(defaultCareAddress.address)
|
||
const careDetailAddress = ref(defaultCareAddress.detailAddress)
|
||
const careArea = ref(defaultCareAddress.area)
|
||
const careFloor = ref(defaultCareAddress.floor)
|
||
const careHasElevator = ref(defaultCareAddress.hasElevator)
|
||
|
||
const recipientName = ref(defaultCareRecipient.name)
|
||
const recipientAgeText = ref(defaultCareRecipient.age.toString())
|
||
const recipientGender = ref(defaultCareRecipient.gender)
|
||
const recipientRelation = ref(defaultCareRecipient.relation)
|
||
const recipientHealthStatus = ref(defaultCareRecipient.healthStatus)
|
||
const recipientMobilityLevel = ref(defaultCareRecipient.mobilityLevel)
|
||
const recipientNeedFamilyPresent = ref(defaultCareRecipient.needFamilyPresent)
|
||
|
||
const contactName = ref(defaultCareContact.contactName)
|
||
const contactPhone = ref(defaultCareContact.contactPhone)
|
||
const contactGender = ref(defaultCareContact.contactGender)
|
||
const emergencyName = ref(defaultCareContact.emergencyName)
|
||
const emergencyPhone = ref(defaultCareContact.emergencyPhone)
|
||
const remarkText = ref('老人需要基础照护与血压监测。')
|
||
const demandDetailText = ref('请优先安排上午上门,家属希望同步了解老人近期血压情况。')
|
||
|
||
try {
|
||
const windowInfo = uni.getWindowInfo()
|
||
const statusBar = windowInfo.statusBarHeight
|
||
const unit = windowInfo.windowWidth / 750
|
||
headerHeight.value = statusBar + Math.round(124 * unit)
|
||
} catch (error) {
|
||
headerHeight.value = 116
|
||
}
|
||
|
||
function buildDefaultNeedOptions(currentServiceId: string): Array<CareNeedOptionType> {
|
||
if (currentServiceId == 'svc-002') {
|
||
return [
|
||
{ id: 'rehab', label: '康复指导', selected: true },
|
||
{ id: 'basic_care', label: '基础照护', selected: false },
|
||
{ id: 'blood_pressure', label: '血压监测', selected: false },
|
||
{ id: 'medicine', label: '用药提醒', selected: false },
|
||
{ id: 'escort', label: '陪诊陪护', selected: false },
|
||
{ id: 'chronic', label: '慢病随访', selected: true }
|
||
]
|
||
}
|
||
if (currentServiceId == 'svc-003') {
|
||
return [
|
||
{ id: 'basic_care', label: '基础照护', selected: false },
|
||
{ id: 'blood_pressure', label: '血压监测', selected: true },
|
||
{ id: 'medicine', label: '用药提醒', selected: true },
|
||
{ id: 'rehab', label: '康复指导', selected: false },
|
||
{ id: 'escort', label: '陪诊陪护', selected: false },
|
||
{ id: 'chronic', label: '慢病随访', selected: true }
|
||
]
|
||
}
|
||
return [
|
||
{ id: 'basic_care', label: '基础照护', selected: true },
|
||
{ id: 'blood_pressure', label: '血压监测', selected: true },
|
||
{ id: 'medicine', label: '用药提醒', selected: false },
|
||
{ id: 'rehab', label: '康复指导', selected: false },
|
||
{ id: 'escort', label: '陪诊陪护', selected: false },
|
||
{ id: 'chronic', label: '慢病随访', selected: true }
|
||
]
|
||
}
|
||
|
||
function buildDefaultRiskOptions(currentServiceId: string): Array<CareRiskOptionType> {
|
||
if (currentServiceId == 'svc-002') {
|
||
return [
|
||
{ id: 'post_op', label: '术后恢复', selected: true },
|
||
{ id: 'fall', label: '跌倒风险', selected: true },
|
||
{ id: 'chronic', label: '慢病管理', selected: false }
|
||
]
|
||
}
|
||
if (currentServiceId == 'svc-003') {
|
||
return [
|
||
{ id: 'post_op', label: '术后恢复', selected: false },
|
||
{ id: 'fall', label: '跌倒风险', selected: false },
|
||
{ id: 'chronic', label: '慢病管理', selected: true }
|
||
]
|
||
}
|
||
return [
|
||
{ id: 'post_op', label: '术后恢复', selected: false },
|
||
{ id: 'fall', label: '跌倒风险', selected: true },
|
||
{ id: 'chronic', label: '慢病管理', selected: true }
|
||
]
|
||
}
|
||
|
||
function buildDefaultPackages(currentServiceId: string, basePrice: number, durationText: string): Array<ServicePackageOptionType> {
|
||
// TODO: 后续接入真实服务套餐与机构报价接口,当前先使用页面内 mock 方案。
|
||
if (currentServiceId == 'svc-002') {
|
||
return [
|
||
{ id: 'pkg_rehab_assess', name: '康复基础评估', desc: '动作评估、居家训练建议、康复重点说明', price: Math.max(basePrice - 30, 128), duration: '约 1.5 小时', selected: true },
|
||
{ id: 'pkg_rehab_plus', name: '上门康复训练', desc: '动作陪练、训练纠正、阶段性康复记录', price: basePrice, duration: durationText, selected: false },
|
||
{ id: 'pkg_rehab_follow', name: '连续康复计划', desc: '适合术后恢复阶段,支持持续跟踪与复盘', price: basePrice + 58, duration: '约 2.5 小时', selected: false }
|
||
]
|
||
}
|
||
if (currentServiceId == 'svc-003') {
|
||
return [
|
||
{ id: 'pkg_chronic_basic', name: '慢病基础随访', desc: '血压血糖记录、用药核对、风险提醒', price: Math.max(basePrice - 20, 98), duration: '约 1 小时', selected: true },
|
||
{ id: 'pkg_chronic_plus', name: '慢病加强随访', desc: '增加生活方式建议和家属宣教内容', price: basePrice, duration: durationText, selected: false },
|
||
{ id: 'pkg_chronic_family', name: '家庭联合随访', desc: '适合需要家属共同参与的连续照护场景', price: basePrice + 36, duration: '约 1.5 小时', selected: false }
|
||
]
|
||
}
|
||
return [
|
||
{ id: 'pkg_basic_home', name: '基础照护', desc: '生命体征观察、协助起居、用药提醒', price: Math.max(basePrice - 20, 148), duration: '约 1.5 小时', selected: true },
|
||
{ id: 'pkg_basic_nursing', name: '标准照护', desc: '适合日常陪护与护理观察,支持家属沟通', price: basePrice, duration: durationText, selected: false },
|
||
{ id: 'pkg_basic_plus', name: '加强照护', desc: '增加翻身协助、环境提醒和风险沟通', price: basePrice + 48, duration: '约 2.5 小时', selected: false }
|
||
]
|
||
}
|
||
|
||
const addressLineText = computed((): string => {
|
||
const fullAddress = careAddress.value + ' ' + careDetailAddress.value
|
||
return fullAddress.trim() != '' ? fullAddress : '请选择上门服务地址'
|
||
})
|
||
|
||
const selectedTimeText = computed((): string => {
|
||
let selectedDayLabel = ''
|
||
for (let i = 0; i < bookingDays.value.length; i++) {
|
||
if (bookingDays.value[i].id == selectedDayId.value) {
|
||
selectedDayLabel = bookingDays.value[i].label + ' ' + bookingDays.value[i].dateText
|
||
break
|
||
}
|
||
}
|
||
let selectedSlotLabel = ''
|
||
for (let i = 0; i < bookingSlots.value.length; i++) {
|
||
if (bookingSlots.value[i].id == selectedSlotId.value) {
|
||
selectedSlotLabel = bookingSlots.value[i].label
|
||
break
|
||
}
|
||
}
|
||
if (selectedDayLabel == '' || selectedSlotLabel == '') {
|
||
return '请选择上门时间'
|
||
}
|
||
return selectedDayLabel + ' ' + selectedSlotLabel
|
||
})
|
||
|
||
const minPriceValue = computed((): number => {
|
||
let minPrice = servicePrice.value
|
||
for (let i = 0; i < servicePackages.value.length; i++) {
|
||
if (i == 0 || servicePackages.value[i].price < minPrice) {
|
||
minPrice = servicePackages.value[i].price
|
||
}
|
||
}
|
||
return minPrice
|
||
})
|
||
|
||
const minPriceText = computed((): string => {
|
||
return formatPrice(minPriceValue.value)
|
||
})
|
||
|
||
const summaryGuaranteeTags = computed((): Array<HomeServiceGuaranteeItemType> => {
|
||
const result: Array<HomeServiceGuaranteeItemType> = []
|
||
for (let i = 0; i < guaranteeTags.value.length && result.length < 3; i++) {
|
||
result.push(guaranteeTags.value[i])
|
||
}
|
||
return result
|
||
})
|
||
|
||
function formatPrice(price: number): string {
|
||
const rounded = Math.round(price)
|
||
if (Math.abs(price - rounded) < 0.001) {
|
||
return rounded.toString()
|
||
}
|
||
return price.toFixed(2)
|
||
}
|
||
|
||
function getSelectedPackageName(): string {
|
||
for (let i = 0; i < servicePackages.value.length; i++) {
|
||
if (servicePackages.value[i].selected) {
|
||
return servicePackages.value[i].name
|
||
}
|
||
}
|
||
return ''
|
||
}
|
||
|
||
function getSelectedRiskText(): string {
|
||
let text = ''
|
||
for (let i = 0; i < careRiskOptions.value.length; i++) {
|
||
if (careRiskOptions.value[i].selected) {
|
||
if (text != '') {
|
||
text = text + '、'
|
||
}
|
||
text = text + careRiskOptions.value[i].label
|
||
}
|
||
}
|
||
return text
|
||
}
|
||
|
||
function getSelectedNeedText(): string {
|
||
let text = ''
|
||
for (let i = 0; i < careNeedOptions.value.length; i++) {
|
||
if (careNeedOptions.value[i].selected) {
|
||
if (text != '') {
|
||
text = text + '、'
|
||
}
|
||
text = text + careNeedOptions.value[i].label
|
||
}
|
||
}
|
||
return text
|
||
}
|
||
|
||
function buildDemandSummary(): string {
|
||
const selectedNeeds = getSelectedNeedText()
|
||
const selectedRisks = getSelectedRiskText()
|
||
const packageName = getSelectedPackageName()
|
||
const familyPresentText = recipientNeedFamilyPresent.value ? '需要家属在场' : '可独立服务'
|
||
const elevatorText = careHasElevator.value ? '有电梯' : '无电梯'
|
||
return '服务对象:' + recipientName.value
|
||
+ ',年龄:' + recipientAgeText.value
|
||
+ ',性别:' + recipientGender.value
|
||
+ ',关系:' + recipientRelation.value
|
||
+ ',身体情况:' + recipientHealthStatus.value
|
||
+ ',行动能力:' + recipientMobilityLevel.value
|
||
+ ',风险标签:' + selectedRisks
|
||
+ ',是否需家属在场:' + familyPresentText
|
||
+ ',服务地址:' + addressLineText.value
|
||
+ ',区域:' + careArea.value
|
||
+ ',楼层:' + careFloor.value
|
||
+ ',电梯:' + elevatorText
|
||
+ ',套餐:' + packageName
|
||
+ ',服务需求:' + selectedNeeds
|
||
+ ',详细需求:' + demandDetailText.value
|
||
+ ',紧急联系人:' + emergencyName.value + ' ' + emergencyPhone.value
|
||
+ ',备注:' + remarkText.value
|
||
}
|
||
|
||
async function loadData() {
|
||
bookingDays.value = getBookingDayOptions()
|
||
bookingSlots.value = getBookingTimeSlots()
|
||
guaranteeTags.value = getServiceGuarantees()
|
||
agency.value = getRecommendedAgency(serviceId.value)
|
||
serviceExcludeText.value = getServiceExcludes(serviceId.value).join(';')
|
||
careNeedOptions.value = buildDefaultNeedOptions(serviceId.value)
|
||
careRiskOptions.value = buildDefaultRiskOptions(serviceId.value)
|
||
servicePackages.value = buildDefaultPackages(serviceId.value, servicePrice.value, serviceDuration.value)
|
||
|
||
const catalog = await fetchHomeServiceCatalog()
|
||
let matchedService: HomeServiceCatalogType | null = null
|
||
for (let i = 0; i < catalog.length; i++) {
|
||
if (catalog[i].id == serviceId.value) {
|
||
matchedService = catalog[i]
|
||
break
|
||
}
|
||
}
|
||
if (matchedService == null) {
|
||
const fallbackItems = getHomeServiceItems(catalog)
|
||
if (fallbackItems.length > 0) {
|
||
serviceTitle.value = fallbackItems[0].title
|
||
serviceSubtitle.value = fallbackItems[0].subtitle
|
||
servicePrice.value = fallbackItems[0].price
|
||
serviceSuitableFor.value = fallbackItems[0].suitableFor
|
||
serviceImageText.value = fallbackItems[0].imageText
|
||
}
|
||
servicePackages.value = buildDefaultPackages(serviceId.value, servicePrice.value, serviceDuration.value)
|
||
return
|
||
}
|
||
serviceTitle.value = matchedService.name
|
||
serviceSubtitle.value = matchedService.summary
|
||
servicePrice.value = matchedService.price
|
||
serviceDuration.value = matchedService.durationText
|
||
serviceSuitableFor.value = matchedService.suitableFor
|
||
const mappedItems = getHomeServiceItems([matchedService])
|
||
if (mappedItems.length > 0) {
|
||
serviceImageText.value = mappedItems[0].imageText
|
||
}
|
||
servicePackages.value = buildDefaultPackages(serviceId.value, servicePrice.value, serviceDuration.value)
|
||
}
|
||
|
||
function selectAddress() {
|
||
if (careAddress.value == '' || careDetailAddress.value == '') {
|
||
careAddress.value = defaultCareAddress.address
|
||
careDetailAddress.value = defaultCareAddress.detailAddress
|
||
careArea.value = defaultCareAddress.area
|
||
careFloor.value = defaultCareAddress.floor
|
||
careHasElevator.value = defaultCareAddress.hasElevator
|
||
uni.showToast({ title: '已填入示例地址', icon: 'none' })
|
||
return
|
||
}
|
||
uni.navigateTo({ url: '/pages/mall/consumer/address-list' })
|
||
}
|
||
|
||
function handleAgencyReplace() {
|
||
uni.showToast({ title: '服务机构选择建设中', icon: 'none' })
|
||
}
|
||
|
||
function handleAgencyContact() {
|
||
uni.showToast({ title: '已为你联系服务机构', icon: 'none' })
|
||
}
|
||
|
||
function handleAgencyNavigate() {
|
||
uni.showToast({ title: '导航功能建设中', icon: 'none' })
|
||
}
|
||
|
||
function selectDay(dayId: string) {
|
||
selectedDayId.value = dayId
|
||
}
|
||
|
||
function selectSlot(slotId: string, available: boolean) {
|
||
if (!available) {
|
||
uni.showToast({ title: '该时段暂不可约', icon: 'none' })
|
||
return
|
||
}
|
||
selectedSlotId.value = slotId
|
||
}
|
||
|
||
function setRecipientGender(gender: string) {
|
||
recipientGender.value = gender
|
||
}
|
||
|
||
function setContactGender(gender: string) {
|
||
contactGender.value = gender
|
||
}
|
||
|
||
function setFamilyPresent(needFamilyPresent: boolean) {
|
||
recipientNeedFamilyPresent.value = needFamilyPresent
|
||
}
|
||
|
||
function setElevator(hasElevator: boolean) {
|
||
careHasElevator.value = hasElevator
|
||
}
|
||
|
||
function toggleRiskOption(optionId: string) {
|
||
for (let i = 0; i < careRiskOptions.value.length; i++) {
|
||
if (careRiskOptions.value[i].id == optionId) {
|
||
careRiskOptions.value[i].selected = !careRiskOptions.value[i].selected
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
function toggleCareNeedOption(optionId: string) {
|
||
let selectedCount = 0
|
||
let targetIndex = -1
|
||
for (let i = 0; i < careNeedOptions.value.length; i++) {
|
||
if (careNeedOptions.value[i].selected) {
|
||
selectedCount++
|
||
}
|
||
if (careNeedOptions.value[i].id == optionId) {
|
||
targetIndex = i
|
||
}
|
||
}
|
||
if (targetIndex == -1) {
|
||
return
|
||
}
|
||
if (careNeedOptions.value[targetIndex].selected && selectedCount <= 1) {
|
||
uni.showToast({ title: '请至少保留一个服务需求', icon: 'none' })
|
||
return
|
||
}
|
||
careNeedOptions.value[targetIndex].selected = !careNeedOptions.value[targetIndex].selected
|
||
}
|
||
|
||
function selectServicePackage(packageId: string) {
|
||
for (let i = 0; i < servicePackages.value.length; i++) {
|
||
servicePackages.value[i].selected = servicePackages.value[i].id == packageId
|
||
}
|
||
}
|
||
|
||
async function submitBooking() {
|
||
if (careAddress.value == '' || careDetailAddress.value == '') {
|
||
uni.showToast({ title: '请选择上门服务地址', icon: 'none' })
|
||
return
|
||
}
|
||
if (recipientName.value == '') {
|
||
uni.showToast({ title: '请填写服务对象姓名', icon: 'none' })
|
||
return
|
||
}
|
||
if (contactPhone.value == '' || contactName.value == '') {
|
||
uni.showToast({ title: '请补全联系人信息', icon: 'none' })
|
||
return
|
||
}
|
||
if (emergencyName.value == '' || emergencyPhone.value == '') {
|
||
uni.showToast({ title: '请补全紧急联系人信息', icon: 'none' })
|
||
return
|
||
}
|
||
if (selectedTimeText.value == '请选择上门时间') {
|
||
uni.showToast({ title: '请选择上门时间', icon: 'none' })
|
||
return
|
||
}
|
||
|
||
let parsedAge = parseInt(recipientAgeText.value)
|
||
if (isNaN(parsedAge)) {
|
||
parsedAge = 0
|
||
}
|
||
|
||
const draft: HomeServiceApplicationDraftType = {
|
||
serviceId: serviceId.value,
|
||
serviceName: serviceTitle.value,
|
||
applicantName: contactName.value,
|
||
elderName: recipientName.value,
|
||
age: parsedAge,
|
||
phone: contactPhone.value,
|
||
address: addressLineText.value,
|
||
preferredTime: selectedTimeText.value,
|
||
demandSummary: buildDemandSummary()
|
||
}
|
||
|
||
const created = await createHomeServiceApplication(draft)
|
||
uni.showToast({ title: '预约已提交', icon: 'success' })
|
||
uni.navigateTo({ url: '/pages/mall/consumer/home-service/order-detail?id=' + created.id })
|
||
}
|
||
|
||
onLoad((options) => {
|
||
const id = options['id']
|
||
if (id != null) {
|
||
serviceId.value = id as string
|
||
}
|
||
const mode = options['mode']
|
||
if (mode != null && mode == 'booking') {
|
||
careAddress.value = defaultCareAddress.address
|
||
careDetailAddress.value = defaultCareAddress.detailAddress
|
||
careArea.value = defaultCareAddress.area
|
||
}
|
||
loadData()
|
||
})
|
||
</script>
|
||
|
||
<style scoped>
|
||
.booking-page-shell {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background: #f7f8fb;
|
||
overflow: hidden;
|
||
}
|
||
|
||
.detail-fixed-header {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
z-index: 100;
|
||
background: #f3f7f9;
|
||
}
|
||
|
||
.detail-header-placeholder {
|
||
width: 100%;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.detail-scroll {
|
||
flex: 1;
|
||
min-height: 0;
|
||
width: 100%;
|
||
}
|
||
|
||
.summary-card {
|
||
background: linear-gradient(180deg, #fff0f4 0%, #fff7f9 100%);
|
||
border-radius: 28rpx;
|
||
padding: 28rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 12rpx 24rpx rgba(15, 23, 42, 0.06);
|
||
}
|
||
|
||
.summary-top-row,
|
||
.summary-tag-row,
|
||
.summary-price-row,
|
||
.booking-bottom-bar,
|
||
.booking-day-row,
|
||
.form-grid,
|
||
.pill-row,
|
||
.tag-row,
|
||
.booking-slot-grid,
|
||
.agency-top-row,
|
||
.action-row,
|
||
.package-top-row {
|
||
flex-direction: row;
|
||
align-items: center;
|
||
}
|
||
|
||
.summary-top-row,
|
||
.agency-top-row,
|
||
.booking-bottom-bar,
|
||
.package-top-row {
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.summary-cover {
|
||
width: 144rpx;
|
||
height: 144rpx;
|
||
border-radius: 24rpx;
|
||
background: linear-gradient(180deg, #dff6f1 0%, #ecf3ff 100%);
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.summary-cover-text {
|
||
font-size: 36rpx;
|
||
font-weight: 700;
|
||
color: #0f766e;
|
||
}
|
||
|
||
.summary-main {
|
||
flex: 1;
|
||
min-width: 0;
|
||
margin-left: 22rpx;
|
||
}
|
||
|
||
.summary-title {
|
||
font-size: 34rpx;
|
||
font-weight: 700;
|
||
color: #16324f;
|
||
line-height: 44rpx;
|
||
}
|
||
|
||
.summary-desc,
|
||
.summary-meta,
|
||
.agency-meta,
|
||
.agency-desc,
|
||
.booking-bottom-time,
|
||
.package-desc,
|
||
.package-duration,
|
||
.info-value,
|
||
.value-card-text {
|
||
margin-top: 10rpx;
|
||
font-size: 24rpx;
|
||
line-height: 34rpx;
|
||
color: #64748b;
|
||
}
|
||
|
||
.summary-tag-row,
|
||
.pill-row,
|
||
.tag-row {
|
||
flex-wrap: wrap;
|
||
margin-top: 18rpx;
|
||
}
|
||
|
||
.summary-tag,
|
||
.agency-badge,
|
||
.tag-chip {
|
||
padding: 10rpx 16rpx;
|
||
border-radius: 999rpx;
|
||
font-size: 22rpx;
|
||
margin-right: 12rpx;
|
||
margin-bottom: 12rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.summary-tag {
|
||
background: #ffffff;
|
||
color: #ff5a7a;
|
||
}
|
||
|
||
.agency-badge {
|
||
background: #eafbf7;
|
||
color: #0f766e;
|
||
}
|
||
|
||
.summary-price-row {
|
||
margin-top: 12rpx;
|
||
align-items: flex-end;
|
||
}
|
||
|
||
.summary-price-prefix,
|
||
.summary-price,
|
||
.booking-bottom-price,
|
||
.package-price {
|
||
font-size: 40rpx;
|
||
font-weight: 700;
|
||
color: #ff5a7a;
|
||
}
|
||
|
||
.summary-price-unit {
|
||
font-size: 22rpx;
|
||
color: #64748b;
|
||
margin-left: 8rpx;
|
||
margin-bottom: 6rpx;
|
||
}
|
||
|
||
.form-item {
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.form-item-last,
|
||
.tag-row-last {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.label,
|
||
.agency-name,
|
||
.info-label,
|
||
.package-name {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: #16324f;
|
||
margin-bottom: 12rpx;
|
||
}
|
||
|
||
.value-card,
|
||
.agency-card,
|
||
.package-card {
|
||
background: #f8fbfc;
|
||
border-radius: 22rpx;
|
||
padding: 22rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.value-card {
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #eef2f6;
|
||
}
|
||
|
||
.value-card-action {
|
||
margin-top: 14rpx;
|
||
font-size: 22rpx;
|
||
color: #ff5a7a;
|
||
}
|
||
|
||
.form-grid {
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.form-grid-item {
|
||
width: 48.5%;
|
||
margin-bottom: 24rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.input,
|
||
.textarea {
|
||
width: 100%;
|
||
background: #f8fbfc;
|
||
border-radius: 18rpx;
|
||
font-size: 28rpx;
|
||
color: #23384d;
|
||
box-sizing: border-box;
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #eef2f6;
|
||
}
|
||
|
||
.input {
|
||
height: 84rpx;
|
||
padding: 0 24rpx;
|
||
}
|
||
|
||
.textarea {
|
||
padding: 22rpx 24rpx;
|
||
height: 160rpx;
|
||
}
|
||
|
||
.pill {
|
||
height: 64rpx;
|
||
padding: 0 24rpx;
|
||
border-radius: 999rpx;
|
||
background: #f3f6f8;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 12rpx;
|
||
margin-bottom: 12rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.pill-active {
|
||
background: #fff0f4;
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #ffc7d3;
|
||
}
|
||
|
||
.pill-text,
|
||
.tag-chip-text,
|
||
.booking-slot-label,
|
||
.booking-day-label,
|
||
.booking-day-date,
|
||
.booking-day-weekday,
|
||
.ghost-btn-text {
|
||
font-size: 24rpx;
|
||
color: #476072;
|
||
}
|
||
|
||
.pill-text-active,
|
||
.tag-chip-text-active,
|
||
.booking-slot-label-active,
|
||
.booking-day-label-active,
|
||
.booking-day-date-active,
|
||
.booking-day-weekday-active {
|
||
color: #ff5a7a;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.tag-chip {
|
||
background: #f3f6f8;
|
||
padding-left: 20rpx;
|
||
padding-right: 20rpx;
|
||
}
|
||
|
||
.tag-chip-active {
|
||
background: #fff0f4;
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #ffc7d3;
|
||
}
|
||
|
||
.action-row {
|
||
margin-top: 20rpx;
|
||
flex-wrap: wrap;
|
||
}
|
||
|
||
.ghost-btn {
|
||
padding: 0 22rpx;
|
||
height: 68rpx;
|
||
border-radius: 999rpx;
|
||
background: #ffffff;
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #ffd5de;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-right: 12rpx;
|
||
margin-bottom: 12rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.ghost-btn-text {
|
||
color: #ff5a7a;
|
||
font-weight: 700;
|
||
}
|
||
|
||
.booking-day-scroll {
|
||
height: 156rpx;
|
||
}
|
||
|
||
.booking-day-row {
|
||
padding-right: 20rpx;
|
||
}
|
||
|
||
.booking-day-card {
|
||
width: 160rpx;
|
||
padding: 20rpx;
|
||
border-radius: 24rpx;
|
||
background: #f8fbfc;
|
||
margin-right: 16rpx;
|
||
box-sizing: border-box;
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #eef2f6;
|
||
}
|
||
|
||
.booking-day-card-active {
|
||
background: #fff0f4;
|
||
border-color: #ffc7d3;
|
||
}
|
||
|
||
.booking-day-date,
|
||
.booking-day-weekday {
|
||
display: block;
|
||
margin-top: 6rpx;
|
||
}
|
||
|
||
.booking-slot-grid {
|
||
flex-wrap: wrap;
|
||
justify-content: space-between;
|
||
margin-top: 20rpx;
|
||
}
|
||
|
||
.booking-slot-card {
|
||
width: 48.5%;
|
||
height: 82rpx;
|
||
border-radius: 22rpx;
|
||
background: #f8fbfc;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-bottom: 16rpx;
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #eef2f6;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.booking-slot-card-active {
|
||
background: #fff0f4;
|
||
border-color: #ffc7d3;
|
||
}
|
||
|
||
.booking-slot-card-disabled {
|
||
opacity: 0.55;
|
||
background: #f1f5f9;
|
||
}
|
||
|
||
.package-list {
|
||
margin-bottom: 22rpx;
|
||
}
|
||
|
||
.package-card {
|
||
margin-bottom: 16rpx;
|
||
border-width: 1rpx;
|
||
border-style: solid;
|
||
border-color: #eef2f6;
|
||
}
|
||
|
||
.package-card-active {
|
||
background: #fff8fa;
|
||
border-color: #ffc7d3;
|
||
}
|
||
|
||
.package-name-active {
|
||
color: #ff5a7a;
|
||
}
|
||
|
||
.info-item {
|
||
margin-bottom: 22rpx;
|
||
}
|
||
|
||
.detail-page-bottom-space {
|
||
height: 180rpx;
|
||
}
|
||
|
||
.booking-bottom-bar {
|
||
position: fixed;
|
||
left: 24rpx;
|
||
right: 24rpx;
|
||
bottom: 28rpx;
|
||
background: #ffffff;
|
||
border-radius: 30rpx;
|
||
padding: 20rpx 22rpx;
|
||
box-shadow: 0 12rpx 28rpx rgba(15, 23, 42, 0.12);
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.booking-bottom-time {
|
||
display: block;
|
||
}
|
||
|
||
.booking-submit-btn {
|
||
height: 84rpx;
|
||
padding: 0 34rpx;
|
||
border-radius: 999rpx;
|
||
background: #16a085;
|
||
align-items: center;
|
||
justify-content: center;
|
||
box-sizing: border-box;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.booking-submit-btn-text {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: #ffffff;
|
||
}
|
||
</style> |