1037 lines
27 KiB
Vue
1037 lines
27 KiB
Vue
<template>
|
||
<view class="order-detail-container">
|
||
<view class="detail-container">
|
||
<uni-load-more v-if="isLoading" status="loading" :show-text="false" />
|
||
<scroll-view v-if="!isLoading" class="scroll-view" :scroll-y="true">
|
||
<!-- 用户和地址信息 -->
|
||
<view class="info-cell address-cell">
|
||
<view class="info-title-view">
|
||
<image src="@/static/images/address.png" mode="aspectFit" class="info-icon" />
|
||
<text class="app-fc-main fs-28">{{ userName || '--' }}</text>
|
||
<text class="app-fc-main fs-28 phone-text" style="color: #666262;">{{ userPhone || '--' }}</text>
|
||
<text class="default-tag">默认</text>
|
||
</view>
|
||
<view class="address-view">
|
||
<view class="info-icon" />
|
||
<text class="app-fc-normal fs-24 address-text">{{ (orderInfo && orderInfo.order && orderInfo.order.address)
|
||
|| '--' }}</text>
|
||
<!-- <text class="modify-btn" @click="handleModifyAddress">修改</text> -->
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 备注信息(统一白色容器) -->
|
||
<view class="info-cell remark-cell">
|
||
<view class="remark-row">
|
||
<text class="info-label">WIFI密码</text>
|
||
<text class="remark-text">
|
||
{{ (orderInfo && orderInfo.order && orderInfo.order.wifi_password) || '暂无备注' }}
|
||
</text>
|
||
</view>
|
||
<view class="remark-row">
|
||
<text class="info-label">停车状况</text>
|
||
<text class="remark-text">
|
||
{{ (orderInfo && orderInfo.order && orderInfo.order.park_desc) || '暂无备注' }}
|
||
</text>
|
||
</view>
|
||
<view class="remark-row">
|
||
<text class="info-label">宠物备注</text>
|
||
<text class="remark-text">{{ petRemark || '暂无备注' }}</text>
|
||
</view>
|
||
<view class="remark-row">
|
||
<text class="info-label">钥匙交接备注</text>
|
||
<text class="remark-text">
|
||
{{ (orderInfo && orderInfo.order && orderInfo.order.key_handover_remark) || '暂无备注' }}
|
||
</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 按日期显示的服务详情 -->
|
||
<view class="service-dates-section">
|
||
<view class="service-summary-header">
|
||
<text class="service-days-text">上门服务{{ serviceDays }}天</text>
|
||
<text class="pet-count-text">{{ petCount }}只{{ petTypeName }}</text>
|
||
</view>
|
||
<view v-for="(dateGroup, dateIndex) in groupedSlots" :key="dateIndex" class="date-service-cell">
|
||
<view class="date-header" @click="toggleDate(dateIndex)">
|
||
<view class="date-info">
|
||
<text class="date-text">{{ dateGroup.date }}</text>
|
||
<text class="service-name">{{ getServiceName() }}</text>
|
||
<text class="service-price">¥{{ dateGroup.price || '0.00' }}</text>
|
||
<text class="toggle-btn">{{ dateGroup.expanded ? '收起' : '展开' }}</text>
|
||
</view>
|
||
</view>
|
||
<view v-if="dateGroup.expanded" class="date-detail">
|
||
<view v-for="(pet, petIndex) in (orderInfo && orderInfo.pets) || []" :key="petIndex"
|
||
class="pet-detail-item">
|
||
<image :src="pet.pet_avatar" mode="aspectFit" class="pet-avatar" />
|
||
<view class="pet-info">
|
||
<text class="pet-name">{{ pet.pet_name || '--' }}</text>
|
||
<text class="pet-desc">{{ getPetDesc(pet) }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="service-list">
|
||
<view v-for="(service, serviceIndex) in (orderInfo && orderInfo.order && orderInfo.order.rules) || []" :key="serviceIndex" class="service-item">
|
||
<text class="service-item-name">{{ service.name }}</text>
|
||
<text class="service-item-count">{{ service.value }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
<!-- 夜间费和合计 -->
|
||
<!-- <view class="price-row night-fee-row">
|
||
<text class="price-label">夜间费<text class="remaining-count">(剩余{{ nightFeeRemaining }}次)</text></text>
|
||
<view class="night-fee-info">
|
||
<text class="night-fee-discount-tag">会员{{ memberDiscount }}折优惠</text>
|
||
<text class="night-fee-original">¥{{ nightFeeOriginal }}</text>
|
||
<text class="night-fee-price">¥{{ nightFeePrice }}</text>
|
||
</view>
|
||
</view> -->
|
||
<view class="price-row total-row">
|
||
<text class="price-total">合计</text>
|
||
<view class="discount-info">
|
||
<text class="discount-price">¥{{ originalTotalPrice }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 价格明细 -->
|
||
<view class="info-cell price-cell">
|
||
<view class="price-row">
|
||
<text class="price-label">订单总价</text>
|
||
<text class="price-value">¥{{ orderTotalPrice }}</text>
|
||
</view>
|
||
<!-- <view class="price-row">
|
||
<text class="price-label">优惠总价</text>
|
||
<text class="price-value discount">-¥{{ discountTotal }}</text>
|
||
</view> -->
|
||
<view class="price-divider"></view>
|
||
|
||
<view class="price-row final-row">
|
||
<text class="price-label">需付款</text>
|
||
<text class="price-value final-price">¥{{ finalAmount }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 支付方式 -->
|
||
<view class="info-cell payment-method-cell">
|
||
<view class="payment-option" @click="selectPaymentMethod('wechat')">
|
||
<image src="@/static/images/douy.png" mode="aspectFit" class="payment-icon" />
|
||
<text class="payment-name">抖音支付</text>
|
||
<!-- 未选中状态 -->
|
||
<image v-if="paymentMethod !== 'wechat'" src="@/static/images/w.png" mode="widthFix" class="not-selected" />
|
||
<!-- 选中状态 -->
|
||
<image v-if="paymentMethod === 'wechat'" src="@/static/images/y.png" mode="widthFix" class="not-selected" />
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 预定须知 -->
|
||
<view class="info-cell notice-cell">
|
||
<text class="notice-title">预定须知</text>
|
||
<text class="notice-content">
|
||
请确认您的{{ petTypeName }}已接种疫苗,性格温顺无攻击性,不在发情期、怀孕期或哺乳期,且无任何生命体征或致命性传染性疾病等服务协议中所提及的情况。请确认您填写的信息真实、完整、无误,并符合平台上门服务要求。
|
||
</text>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 底部付款区域 -->
|
||
<view class="footer-actions" v-if="!isLoading">
|
||
<!-- 第一排:协议文本 -->
|
||
<view class="agreement-text">
|
||
<text class="agreement-item">下单默认同意</text>
|
||
<text class="agreement-item agreement-link" @click="viewServiceRefundsAgreement">《服务与退款协议》</text>
|
||
<text class="agreement-item">和</text>
|
||
<text class="agreement-item agreement-link" @click="viewServiceRefundAgreement">《喂养服务保障协议》</text>
|
||
</view>
|
||
<!-- 第二排:价格和支付按钮 -->
|
||
<view class="footer-bottom-row">
|
||
<view class="footer-price-info">
|
||
<text class="footer-price">¥{{ finalAmount }}</text>
|
||
<text class="footer-original-price">¥{{ originalTotalPrice }}</text>
|
||
<!-- <text class="footer-discount">共优惠¥{{ discountTotal }}</text> -->
|
||
</view>
|
||
<view class="pay-btn" @click="handlePay">
|
||
<text class="pay-btn-text">付款</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
import { getOrderWideDetail, payOrder } from '@/api/order';
|
||
import moment from 'moment';
|
||
import { imgPrefix } from '@/utils/common';
|
||
|
||
export default {
|
||
name: 'HomeServiceOrderDetail',
|
||
data() {
|
||
return {
|
||
isLoading: false,
|
||
orderInfo: null,
|
||
orderId: '',
|
||
source: 'home_service',
|
||
petRemark: '',
|
||
paymentMethod: 'wechat',
|
||
nightFeeRemaining: 1,
|
||
nightFeeOriginal: '285',
|
||
nightFeePrice: '60',
|
||
memberDiscount: 10,
|
||
expandedDates: {}
|
||
};
|
||
},
|
||
computed: {
|
||
userName() {
|
||
// 从订单信息中获取用户名,如果没有则从其他地方获取
|
||
return this.orderInfo?.order?.user_name || '--';
|
||
},
|
||
userPhone() {
|
||
// 从订单信息中获取用户电话
|
||
return this.orderInfo?.order?.phone || '--';
|
||
},
|
||
serviceDays() {
|
||
return this.orderInfo?.slots?.length || 0;
|
||
},
|
||
petCount() {
|
||
return this.orderInfo?.pets?.length || 0;
|
||
},
|
||
petTypeName() {
|
||
// 根据服务类型判断宠物类型
|
||
const serviceType = this.orderInfo?.order?.service_type;
|
||
if (serviceType === 'FEED') {
|
||
// 上门喂养显示猫咪
|
||
return '猫咪';
|
||
} else if (serviceType === 'WALK') {
|
||
// 上门遛宠显示狗狗
|
||
return '狗狗';
|
||
}
|
||
},
|
||
groupedSlots() {
|
||
if (!this.orderInfo?.slots) return [];
|
||
|
||
// 按日期分组
|
||
const grouped = {};
|
||
this.orderInfo.slots.forEach((slot, index) => {
|
||
const date = moment(slot.service_date).format('YYYY-MM-DD');
|
||
if (!grouped[date]) {
|
||
// 第一个日期默认展开
|
||
const isFirstDate = index === 0;
|
||
grouped[date] = {
|
||
date: date,
|
||
slots: [],
|
||
expanded: this.expandedDates[date] !== undefined ? this.expandedDates[date] : isFirstDate,
|
||
price: this.orderInfo?.order?.service_actual_price || '0.00',
|
||
services: this.getServiceList(),
|
||
};
|
||
}
|
||
grouped[date].slots.push(slot);
|
||
});
|
||
|
||
return Object.values(grouped);
|
||
},
|
||
originalTotalPrice() {
|
||
// 原始总价
|
||
const basePrice = parseFloat(this.orderInfo?.order?.service_actual_price || 0);
|
||
const days = this.serviceDays;
|
||
return (basePrice * days).toFixed(2);
|
||
},
|
||
discountTotalPrice() {
|
||
// 会员折扣后的价格
|
||
const original = parseFloat(this.originalTotalPrice);
|
||
return (original * this.memberDiscount / 10).toFixed(2);
|
||
},
|
||
orderTotalPrice() {
|
||
// 订单总价(折扣后的价格)
|
||
return this.discountTotalPrice;
|
||
},
|
||
// discountTotal() {
|
||
// // 优惠总价
|
||
// const original = parseFloat(this.originalTotalPrice);
|
||
// const discounted = parseFloat(this.discountTotalPrice);
|
||
// return (original - discounted).toFixed(2);
|
||
// },
|
||
finalAmount() {
|
||
// 需付款金额
|
||
const total = parseFloat(this.orderTotalPrice);
|
||
// const discount = parseFloat(this.discountTotal);
|
||
// return (total - discount).toFixed(2);
|
||
return total.toFixed(2);
|
||
},
|
||
petAvatar() {
|
||
// 宠物头像,这里使用默认图片
|
||
return require('@/static/images/dog.png');
|
||
}
|
||
},
|
||
onLoad(options) {
|
||
|
||
// 获取订单ID(URL参数名可能是 orderId 或 order_id)
|
||
if (options.order_id) {
|
||
this.orderId = options.order_id;
|
||
} else if (options.orderId) {
|
||
this.orderId = options.orderId;
|
||
}
|
||
// 如果有 source 参数,使用它
|
||
if (options.source) {
|
||
this.source = options.source;
|
||
}
|
||
|
||
// 调用订单详情接口
|
||
if (this.orderId) {
|
||
this.getOrderDetail();
|
||
}
|
||
},
|
||
methods: {
|
||
getOrderDetail() {
|
||
if (!this.orderId) {
|
||
return;
|
||
}
|
||
this.isLoading = true;
|
||
uni.showLoading({
|
||
title: '加载中...'
|
||
});
|
||
getOrderWideDetail({
|
||
source: this.source,
|
||
order_id: parseInt(this.orderId)
|
||
}).then(res => {
|
||
uni.hideLoading();
|
||
this.isLoading = false;
|
||
// 处理订单详情数据
|
||
if (res.code === 0 && res.data) {
|
||
console.log('订单详情:', res.data);
|
||
// 更新订单数据
|
||
this.orderInfo = res.data;
|
||
// 设置宠物备注
|
||
if (res.data.order?.remark) {
|
||
this.petRemark = res.data.order.remark;
|
||
}
|
||
} else {
|
||
uni.showToast({
|
||
title: res.msg || res.message || '获取订单详情失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
}).catch(err => {
|
||
uni.hideLoading();
|
||
this.isLoading = false;
|
||
console.error('获取订单详情失败:', err);
|
||
uni.showToast({
|
||
title: '获取订单详情失败',
|
||
icon: 'none'
|
||
});
|
||
});
|
||
},
|
||
toggleDate(dateIndex) {
|
||
const dateGroup = this.groupedSlots[dateIndex];
|
||
if (dateGroup) {
|
||
this.$set(this.expandedDates, dateGroup.date, !this.expandedDates[dateGroup.date]);
|
||
}
|
||
},
|
||
getServiceName() {
|
||
// 根据服务类型返回服务名称
|
||
const serviceType = this.orderInfo?.order?.service_type;
|
||
if (serviceType === 'WALK') {
|
||
return '遛宠服务';
|
||
} else if (serviceType === 'FEED') {
|
||
return '喂养服务';
|
||
}
|
||
return this.orderInfo?.order?.service_name || '上门服务';
|
||
},
|
||
getServiceList() {
|
||
// 返回服务项目列表
|
||
return [
|
||
{ name: '实时视频' },
|
||
{ name: '喂食' },
|
||
{ name: '换水' },
|
||
{ name: '猫砂盆清理' },
|
||
{ name: '15分钟陪玩' },
|
||
{ name: '健康监测' },
|
||
{ name: '实时反馈' }
|
||
];
|
||
},
|
||
getPetDesc(pet) {
|
||
// 构建宠物描述信息(不包含宠物名称,因为已单独显示)
|
||
// 这里需要根据实际数据结构来构建
|
||
return `${pet.breed_name}/${pet.gender === 'male' ? '男生' : '女生'}/${pet.age}岁`
|
||
},
|
||
handleModifyAddress() {
|
||
// 修改地址
|
||
uni.showToast({
|
||
title: '修改地址功能开发中',
|
||
icon: 'none'
|
||
});
|
||
},
|
||
selectPaymentMethod(method) {
|
||
this.paymentMethod = method;
|
||
},
|
||
viewServiceRefundsAgreement() {
|
||
// 跳转到服务与退款协议 webview 页面
|
||
const url = imgPrefix + 'servicesRefunds.html';
|
||
uni.navigateTo({
|
||
url: `/pages/webview/index?url=${encodeURIComponent(url)}&title=${encodeURIComponent('服务与退款协议')}`
|
||
});
|
||
},
|
||
viewServiceRefundAgreement() {
|
||
// 跳转到服务与退款协议 webview 页面
|
||
const url = imgPrefix + 'feedingServiceAgreement.html';
|
||
uni.navigateTo({
|
||
url: `/pages/webview/index?url=${encodeURIComponent(url)}&title=${encodeURIComponent('喂养服务保障协议')}`
|
||
});
|
||
},
|
||
handlePay() {
|
||
// 检查是否选择了支付方式
|
||
if (this.paymentMethod !== 'wechat') {
|
||
uni.showToast({
|
||
title: '请选择支付方式',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 检查订单信息
|
||
if (!this.orderInfo || !this.orderInfo.order) {
|
||
uni.showToast({
|
||
title: '订单信息不存在',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
const order = this.orderInfo.order;
|
||
const orderId = order.id;
|
||
const orderNo = order.order_no;
|
||
const totalFee = parseFloat(this.finalAmount);
|
||
|
||
if (!orderId || !orderNo) {
|
||
uni.showToast({
|
||
title: '订单信息不完整',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 显示加载提示
|
||
uni.showLoading({
|
||
title: '正在支付...',
|
||
mask: true
|
||
});
|
||
|
||
// 调用支付接口
|
||
// 根据服务类型确定 type: WALK(遛宠) 或 FEED(喂宠) 可能对应不同的 type
|
||
// 这里先使用 type: 7 (参考 training-booking.vue),可能需要根据实际情况调整
|
||
const paymentType = order.service_type === 'WALK' ? 8 : (order.service_type === 'FEED' ? 9 : 7);
|
||
|
||
payOrder({
|
||
type: 7,
|
||
order_id: orderId,
|
||
order_no: orderNo,
|
||
total_fee: totalFee
|
||
}).then((res) => {
|
||
uni.hideLoading();
|
||
|
||
if (res.code !== 0) {
|
||
uni.showToast({
|
||
title: res.msg || res.message || '支付失败',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
tt.pay({
|
||
orderInfo: {
|
||
order_id:res.data.orderInfo.order_id,
|
||
order_token:res.data.orderInfo.order_token,
|
||
},
|
||
service:5,
|
||
success: (payRes) => {
|
||
console.log('支付成功:', payRes);
|
||
uni.showToast({
|
||
title: '支付成功',
|
||
icon: 'success'
|
||
});
|
||
|
||
// 支付成功后跳转到订单列表页面并刷新
|
||
setTimeout(() => {
|
||
// 触发刷新事件,通知订单列表页面刷新
|
||
uni.$emit('refreshOrderList');
|
||
// 跳转到订单列表页面
|
||
uni.redirectTo({
|
||
url: '/pages/client/petOrder/index'
|
||
});
|
||
}, 800);
|
||
},
|
||
fail: (err) => {
|
||
console.error('支付失败:', err);
|
||
uni.showToast({
|
||
title: '支付失败',
|
||
icon: 'none'
|
||
});
|
||
}
|
||
});
|
||
}).catch((err) => {
|
||
uni.hideLoading();
|
||
console.error('支付接口调用失败:', err);
|
||
uni.showToast({
|
||
title: err.msg || err.message || '支付失败',
|
||
icon: 'none'
|
||
});
|
||
});
|
||
}
|
||
}
|
||
};
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.order-detail-container {
|
||
width: 100%;
|
||
height: 100vh;
|
||
background-color: #fbf8fc;
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-sizing: border-box;
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.detail-container {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
padding-bottom: 240rpx;
|
||
}
|
||
|
||
.scroll-view {
|
||
flex: 1;
|
||
height: 100%;
|
||
}
|
||
|
||
.order-info-section {
|
||
padding: 20rpx;
|
||
}
|
||
|
||
.info-cell {
|
||
background-color: #fff;
|
||
border-radius: 16rpx;
|
||
padding: 20rpx;
|
||
margin-bottom: 20rpx;
|
||
box-sizing: border-box;
|
||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||
}
|
||
|
||
.address-cell {
|
||
.info-title-view {
|
||
display: flex;
|
||
align-items: center;
|
||
margin-bottom: 16rpx;
|
||
|
||
.info-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.phone-text {
|
||
margin-left: 16rpx;
|
||
}
|
||
|
||
.default-tag {
|
||
margin-left: 16rpx;
|
||
padding: 4rpx 12rpx;
|
||
background-color: #fee9f3;
|
||
color: #FF19A0;
|
||
border-radius: 4rpx;
|
||
font-size: 20rpx;
|
||
}
|
||
}
|
||
|
||
.address-view {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
|
||
.info-icon {
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
margin-right: 16rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.address-text {
|
||
flex: 1;
|
||
line-height: 1.6;
|
||
}
|
||
|
||
.modify-btn {
|
||
color: #FF19A0;
|
||
font-size: 28rpx;
|
||
margin-left: 16rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.remark-cell {
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.remark-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: flex-start;
|
||
margin-bottom: 16rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.info-label {
|
||
font-size: 24rpx;
|
||
color: #9B939A;
|
||
font-weight: 500;
|
||
margin-right: 24rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.remark-text {
|
||
font-size: 24rpx;
|
||
font-weight: 500;
|
||
color: #272427;
|
||
max-width: 60%;
|
||
word-break: break-all;
|
||
white-space: normal;
|
||
}
|
||
}
|
||
}
|
||
|
||
.service-dates-section {
|
||
background-color: #fff;
|
||
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.04);
|
||
border-radius: 24rpx;
|
||
padding: 20rpx;
|
||
|
||
.price-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding-top: 32rpx;
|
||
|
||
&.night-fee-row {
|
||
|
||
.night-fee-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
|
||
.night-fee-discount-tag {
|
||
font-size: 20rpx;
|
||
color: #FF19A0;
|
||
background-color: #fee9f3;
|
||
padding: 4rpx 8rpx;
|
||
border-radius: 4rpx;
|
||
}
|
||
|
||
.night-fee-original {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
.night-fee-price {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
&.total-row {
|
||
.discount-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
|
||
.price-total {
|
||
font-size: 26rpx;
|
||
color: #3D3D3D;
|
||
}
|
||
|
||
.original-price {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
.discount-price {
|
||
font-size: 32rpx;
|
||
color: #FF19A0;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.discount-tag {
|
||
font-size: 20rpx;
|
||
color: #FF19A0;
|
||
background-color: #fee9f3;
|
||
padding: 4rpx 8rpx;
|
||
border-radius: 4rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.price-label {
|
||
font-size: 24rpx;
|
||
color: #9B939A;
|
||
|
||
.remaining-count {
|
||
font-size: 24rpx;
|
||
color: #FF19A0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.service-summary-header {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 32rpx;
|
||
|
||
.service-days-text {
|
||
font-size: 28rpx;
|
||
color: #272427;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.pet-count-text {
|
||
font-size: 24rpx;
|
||
color: #272427;
|
||
}
|
||
}
|
||
|
||
.date-service-cell {
|
||
background: #F5F5F5;
|
||
padding: 20rpx;
|
||
border-radius: 20rpx;
|
||
margin-bottom: 16rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.date-header {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.date-info {
|
||
flex: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
|
||
.date-text {
|
||
font-size: 24rpx;
|
||
color: #9B939A;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.service-name {
|
||
font-size: 24rpx;
|
||
color: #272427;
|
||
}
|
||
|
||
.service-price {
|
||
font-size: 24rpx;
|
||
color: #272427;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.toggle-btn {
|
||
color: #FF19A0;
|
||
font-size: 24rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.date-detail {
|
||
margin-top: 24rpx;
|
||
|
||
.pet-detail-item {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
margin-bottom: 24rpx;
|
||
|
||
.pet-avatar {
|
||
width: 52rpx;
|
||
height: 52rpx;
|
||
border-radius: 50%;
|
||
margin-right: 8rpx;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.pet-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
|
||
.pet-name {
|
||
font-size: 24rpx;
|
||
color: #333333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.pet-desc {
|
||
font-size: 20rpx;
|
||
color: #666;
|
||
}
|
||
}
|
||
}
|
||
|
||
.service-list {
|
||
.service-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
margin-bottom: 24rpx;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.service-item-name {
|
||
font-size: 24rpx;
|
||
color: #9B939A;
|
||
}
|
||
|
||
.service-item-count {
|
||
font-size: 24rpx;
|
||
color: #272427;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
.price-cell {
|
||
margin-top: 20rpx;
|
||
|
||
.price-row {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 24rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
&.night-fee-row {
|
||
.night-fee-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
|
||
.night-fee-discount-tag {
|
||
font-size: 20rpx;
|
||
color: #FF19A0;
|
||
background-color: #fee9f3;
|
||
padding: 4rpx 8rpx;
|
||
border-radius: 4rpx;
|
||
}
|
||
|
||
.night-fee-original {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
.night-fee-price {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
|
||
&.total-row {
|
||
.discount-info {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
|
||
.original-price {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
.discount-price {
|
||
font-size: 32rpx;
|
||
color: #FF19A0;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.discount-tag {
|
||
font-size: 20rpx;
|
||
color: #FF19A0;
|
||
background-color: #fee9f3;
|
||
padding: 4rpx 8rpx;
|
||
border-radius: 4rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
&.final-row {
|
||
.final-price {
|
||
font-size: 36rpx;
|
||
color: #FF19A0;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.price-label {
|
||
font-size: 26rpx;
|
||
color: #3D3D3D;
|
||
}
|
||
}
|
||
|
||
.price-label {
|
||
font-size: 24rpx;
|
||
color: #9B939A;
|
||
}
|
||
|
||
.price-value {
|
||
font-size: 24rpx;
|
||
color: #272427;
|
||
|
||
&.discount {
|
||
color: #FF19A0;
|
||
}
|
||
}
|
||
}
|
||
|
||
.price-divider {
|
||
height: 1px;
|
||
background-color: #f0f0f0;
|
||
margin-top: 24rpx;
|
||
margin-bottom: 32rpx;
|
||
}
|
||
}
|
||
|
||
.payment-method-cell {
|
||
.payment-option {
|
||
display: flex;
|
||
align-items: center;
|
||
|
||
.payment-icon {
|
||
width: 48rpx;
|
||
height: 48rpx;
|
||
margin-right: 16rpx;
|
||
}
|
||
|
||
.payment-name {
|
||
flex: 1;
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.not-selected {
|
||
width: 36rpx;
|
||
height: 36rpx;
|
||
}
|
||
}
|
||
}
|
||
|
||
.notice-cell {
|
||
.notice-title {
|
||
font-size: 24rpx;
|
||
color: #000000;
|
||
font-weight: 500;
|
||
margin-bottom: 16rpx;
|
||
display: block;
|
||
}
|
||
|
||
.notice-content {
|
||
font-size: 24rpx;
|
||
color: #808080;
|
||
line-height: 1.6;
|
||
}
|
||
}
|
||
|
||
.footer-actions {
|
||
position: fixed;
|
||
bottom: 0;
|
||
left: 0;
|
||
right: 0;
|
||
background-color: #fff;
|
||
padding: 24rpx 32rpx;
|
||
padding-bottom: calc(24rpx + env(safe-area-inset-bottom));
|
||
box-shadow: 0 -4rpx 20rpx rgba(0, 0, 0, 0.08);
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
flex-direction: column;
|
||
gap: 16rpx;
|
||
border-radius: 32rpx 32rpx 0px 0px;
|
||
|
||
.agreement-text {
|
||
color: #9B939A;
|
||
text-align: center;
|
||
width: 100%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
flex-wrap: wrap;
|
||
|
||
.agreement-item {
|
||
font-size: 22rpx;
|
||
}
|
||
|
||
.agreement-link {
|
||
color: #FF19A0;
|
||
}
|
||
}
|
||
|
||
.footer-bottom-row {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
width: 100%;
|
||
}
|
||
|
||
.footer-price-info {
|
||
display: flex;
|
||
gap: 4rpx;
|
||
flex: 1;
|
||
align-items: flex-end;
|
||
|
||
.footer-price {
|
||
font-size: 48rpx;
|
||
color: #FF19A0;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.footer-original-price {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
text-decoration: line-through;
|
||
}
|
||
|
||
.footer-discount {
|
||
font-size: 24rpx;
|
||
color: #FF19A0;
|
||
}
|
||
}
|
||
|
||
.pay-btn {
|
||
width: 238rpx;
|
||
height: 96rpx;
|
||
background-color: #FF19A0;
|
||
border-radius: 44rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
margin-left: 24rpx;
|
||
flex-shrink: 0;
|
||
|
||
.pay-btn-text {
|
||
font-size: 32rpx;
|
||
color: #fff;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
}
|
||
</style>
|