1
This commit is contained in:
356
src/page-reser/components/info-cell.vue
Normal file
356
src/page-reser/components/info-cell.vue
Normal file
@ -0,0 +1,356 @@
|
||||
<template>
|
||||
<view class="order-info-cell" @click.stop="clickAction">
|
||||
<template v-if="cellType === 'text'">
|
||||
<view class="info-top-view">
|
||||
<!-- <image :src="infoIcon" mode="aspectFit" class="cell-icon" /> -->
|
||||
<text v-if="isRequired" class="required">*</text>
|
||||
<view class="title-view">
|
||||
<text class="app-fc-main fs-24">{{ title }}</text>
|
||||
</view>
|
||||
<view class="info-view" v-if="info">
|
||||
<text class="app-fc-main fs-24">{{ info }}</text>
|
||||
</view>
|
||||
<view class="info-view" v-else>
|
||||
<text style="color: #9B939A;" class="app-fc-main fs-24">{{ placeholder }}</text>
|
||||
</view>
|
||||
<image v-if="isCanClick" class="right-icon" :src="`${imgPrefix}right-arrow.png`" mode="widthFix">
|
||||
</image>
|
||||
<view v-else class="right-icon" />
|
||||
</view>
|
||||
</template>
|
||||
<!-- 时间信息-->
|
||||
<template v-if="cellType === 'time'">
|
||||
<view class="info-top-view">
|
||||
<!-- <image :src="infoIcon" mode="aspectFit" class="cell-icon" /> -->
|
||||
<text class="required">*</text>
|
||||
<view class="title-view">
|
||||
<text class="app-fc-main fs-24">{{ title }}</text>
|
||||
</view>
|
||||
<view class="info-bottom-view" v-if="info">
|
||||
<text class="app-fc-main fs-24">{{ info }}</text>
|
||||
</view>
|
||||
<view class="info-view" v-else>
|
||||
<text style="color: #9B939A;" class="app-fc-main fs-24">{{ placeholder }}</text>
|
||||
</view>
|
||||
<image class="right-icon" :src="`${imgPrefix}right-arrow.png`" mode="widthFix"></image>
|
||||
</view>
|
||||
<text v-if="infoTime == 5" class="s">(该时间段需收取夜间费)</text>
|
||||
</template>
|
||||
|
||||
<!-- 地址信息-->
|
||||
<template v-if="cellType === 'address'">
|
||||
<view class="info-top-view">
|
||||
<!-- <image :src="infoIcon" mode="aspectFit" class="cell-icon" /> -->
|
||||
<text class="required">*</text>
|
||||
<view class="title-view">
|
||||
<text class="app-fc-main fs-24">{{ title }}</text>
|
||||
</view>
|
||||
|
||||
<view class="info-bottom-view" style="max-width: 60%;" v-if="addressInfo">
|
||||
<view class="user-info-view">
|
||||
<text class="app-fc-main fs-24 app-font-bold">{{
|
||||
addressInfo.recipient_name
|
||||
}}</text>
|
||||
<text class="app-fc-main fs-24 phone-text app-font-bold">{{
|
||||
addressInfo.phone
|
||||
}}</text>
|
||||
</view>
|
||||
|
||||
<view class="address-view">
|
||||
<text class="app-fc-normal fs-24 address-text">{{
|
||||
`${addressInfo.area_name} ${addressInfo.full_address}`
|
||||
}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-view" v-else>
|
||||
<text style="color: #9B939A;" class="app-fc-main fs-24">{{ placeholder }}</text>
|
||||
</view>
|
||||
|
||||
<image class="right-icon" :src="`${imgPrefix}right-arrow.png`" mode="widthFix"></image>
|
||||
</view>
|
||||
|
||||
<text class="nightFee">以下区域需收取调度费:奉贤区、嘉定区、青浦区、松江区、崇明区、金山区</text>
|
||||
</template>
|
||||
|
||||
<!-- 价格-->
|
||||
<template v-if="cellType === 'price'">
|
||||
<view class="info-top-view">
|
||||
<view class="title-view">
|
||||
<text class="app-fc-main fs-28">{{ title }}</text>
|
||||
</view>
|
||||
<text v-if="price" class="app-fc-mark fs-32 app-font-bold-700">{{
|
||||
`¥${price}`
|
||||
}}</text>
|
||||
<text v-else class="app-fc-main fs-28">---</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<template v-if="cellType === 'park'">
|
||||
<view class="info-top-view">
|
||||
<view class="title-view">
|
||||
<text class="app-fc-main fs-24">{{ title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="list-view">
|
||||
<view class="list-card" v-for="item in park_conditions" :key="item"
|
||||
:class="{ 'selected-list-card': parkState === item }" @click.stop="changeParkState(item)">
|
||||
<text class="fs-24 app-fc-main" :class="{ 'app-fc-mark': parkState === item }">{{ item }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="input-container" v-if="parkState === '其他'">
|
||||
<textarea :focus="true" :value="otherParkState" class="input-view fs-24 app-fc-main"
|
||||
placeholder="点击输入停车信息" placeholder-class="placeholder-class" @input="onChange" />
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import {
|
||||
imgPrefix
|
||||
} from "@/utils/common";
|
||||
/**
|
||||
* info-cell 预约信息显示
|
||||
* @property {String} cellType - 显示类型 (默认text) text/address/time/price/park
|
||||
* @value text 文本类型
|
||||
* @value address 地址类型
|
||||
* @value time 时间类型
|
||||
* @value price 价格类型
|
||||
* @value park 停车状况
|
||||
* @property {String} infoIcon - 左侧图标
|
||||
* @property {String} title - 标题
|
||||
* @property {String} info - 显示内容
|
||||
* @property {Object} addressInfo - 地址信息
|
||||
* @property {String} price - 价格
|
||||
* @property {String} parkState - 停车状况
|
||||
*
|
||||
* @property {String} placeholder - 占位
|
||||
*
|
||||
* @event {Function} clickAction 点击cell触发事件
|
||||
* @event {Function} changeParkState 停车状况改变触发事件
|
||||
*/
|
||||
export default {
|
||||
props: {
|
||||
isCanClick: {
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
cellType: {
|
||||
type: String,
|
||||
default: "info",
|
||||
},
|
||||
infoIcon: {
|
||||
type: String | null,
|
||||
default: require("@/static/images/arrow_right.png"),
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
infoTime: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
info: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
addressInfo: {
|
||||
type: Object | null,
|
||||
default: () => {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
price: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
parkState: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
otherParkState: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: "",
|
||||
},
|
||||
isRequired: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
park_conditions: ["小区", "地库", "路边", "其他"],
|
||||
imgPrefix
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
clickAction() {
|
||||
this.isCanClick && this.$emit("clickAction");
|
||||
},
|
||||
changeParkState(state) {
|
||||
this.$emit("changeParkState", state);
|
||||
},
|
||||
onChange(e) {
|
||||
this.$emit("changeOtherParkState", e.detail.value);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-info-cell {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 36rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 20rpx;
|
||||
right: 20rpx;
|
||||
height: 2rpx;
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
.info-top-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
.cell-icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.title-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
margin-left: 16rpx;
|
||||
width: 10rpx;
|
||||
height: 5rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info-bottom-view {
|
||||
// width: calc(100% - 56rpx);
|
||||
// margin-top: 32rpx;
|
||||
// margin-left: 56rpx;
|
||||
// padding-right: 104rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
box-sizing: border-box;
|
||||
|
||||
.user-info-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.phone-text {
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.address-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.address-text {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nightFee {
|
||||
color: #ff19a0;
|
||||
font-family: PingFangSC;
|
||||
font-size: 20rpx;
|
||||
font-weight: normal;
|
||||
margin-top: 20rpx;
|
||||
}
|
||||
|
||||
.s {
|
||||
color: #ff19a0;
|
||||
font-family: PingFangSC;
|
||||
font-size: 24rpx;
|
||||
margin: 6rpx 0 0 52rpx;
|
||||
}
|
||||
|
||||
.list-view {
|
||||
margin-top: 16rpx;
|
||||
width: 100%;
|
||||
padding-right: 30rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
align-items: center;
|
||||
gap: 24rpx;
|
||||
|
||||
.list-card {
|
||||
padding: 12rpx 20rpx;
|
||||
border-radius: 182px;
|
||||
background-color: #f5f5f5;
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.selected-list-card {
|
||||
background-color: #fee9f3;
|
||||
}
|
||||
}
|
||||
|
||||
.input-container {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
padding: 0 30rpx 0 0;
|
||||
box-sizing: border-box;
|
||||
margin-top: 32rpx;
|
||||
|
||||
.input-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 32rpx;
|
||||
border-radius: 30rpx;
|
||||
color: #333;
|
||||
box-sizing: border-box;
|
||||
background-color: #f9f7f9;
|
||||
}
|
||||
|
||||
.placeholder-class {
|
||||
color: #666262;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.required {
|
||||
color: #FF19A0;
|
||||
}
|
||||
</style>
|
||||
184
src/page-reser/components/order-goods-modal.vue
Normal file
184
src/page-reser/components/order-goods-modal.vue
Normal file
@ -0,0 +1,184 @@
|
||||
<template>
|
||||
<select-modal @close="closeAction" title="随车购商品" class="order-goods-modal">
|
||||
<view class="goods-container">
|
||||
<scroll-view class="goods-scroll-view" :scroll-y="true">
|
||||
<view class="goods-item" v-for="item in goodsList" :key="item.order_id" @click.stop="gotoDetail(item)">
|
||||
<image mode="aspectFit" class="goods-img" :src="item.goods_pic"/>
|
||||
<view class="goods-info-view">
|
||||
<text class="app-fc-main fs-32 app-font-bold-500 app-text-ellipse">
|
||||
{{ item.goods_name || '--' }}
|
||||
</text>
|
||||
<text class="app-fc-normal fs-24 goods-num-text">{{ `数量X${item.number}` }}</text>
|
||||
<text class="app-fc-main fs-28 goods-price-text" >实付款
|
||||
<text class="fs-28 app-fc-alarm">{{ `¥${item.goods_price}` }}</text>
|
||||
</text>
|
||||
</view>
|
||||
<image src="@/static/images/arrow_right_black.png" mode="aspectFit" class="good-arrow"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="goods-price-container">
|
||||
<view class="goods-left-view">
|
||||
<view class="price-view">
|
||||
<text class="app-fc-main fs-28">¥</text>
|
||||
<text class="app-fc-main app-font-bold-700 fs-50 price-text">{{ price }}</text>
|
||||
</view>
|
||||
<view class="price-tips-view">
|
||||
<image src="/pageHome/static/tips.png" mode="aspectFit" class="tips-img"/>
|
||||
<text class="fs-24">商品总价</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="submit-btn" @click.stop="closeAction">
|
||||
<text class="app-fc-white fs-30">确定</text>
|
||||
</view>
|
||||
</view>
|
||||
</select-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectModal from "@/components/select-modal.vue";
|
||||
|
||||
export default {
|
||||
components: { SelectModal },
|
||||
props: {
|
||||
goodsList: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
price: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
options: {
|
||||
styleIsolation: "shared",
|
||||
},
|
||||
methods: {
|
||||
closeAction() {
|
||||
this.$emit('close');
|
||||
},
|
||||
gotoDetail(item){
|
||||
this.$emit('gotoDetail', item.goods_id);
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-goods-modal {
|
||||
|
||||
::v-deep {
|
||||
.selected-modal .model-container {
|
||||
background: #fff0f5;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.goods-container {
|
||||
width: 100%;
|
||||
height: 800rpx;
|
||||
position: relative;
|
||||
|
||||
.goods-scroll-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
padding: 0 32rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.goods-item {
|
||||
width: 100%;
|
||||
height: 200rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: #fff;
|
||||
border-radius: 40rpx;
|
||||
margin-top: 32rpx;
|
||||
padding: 20rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.goods-img {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.goods-info-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: calc(100% - 160rpx - 24rpx - 40rpx);
|
||||
.goods-num-text {
|
||||
margin-top: 16rpx;
|
||||
}
|
||||
|
||||
.goods-price-text {
|
||||
margin-top: 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.good-arrow {
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.goods-price-container {
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
padding: 26rpx 32rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
|
||||
.goods-left-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.price-view {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
|
||||
.price-text {
|
||||
margin-left: 8rpx;
|
||||
line-height: 50rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.price-tips-view {
|
||||
margin-top: 10rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.tips-img {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-right: 2rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: 260rpx;
|
||||
height: 92rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background-color: #FE019B;
|
||||
border-radius: 46rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
</style>
|
||||
49
src/page-reser/components/price-description-modal.vue
Normal file
49
src/page-reser/components/price-description-modal.vue
Normal file
@ -0,0 +1,49 @@
|
||||
<template>
|
||||
<select-modal @close="closeAction" title="价格说明">
|
||||
<view class="price-description-container">
|
||||
<view class="price-info">
|
||||
<text class="app-fc-main fs-32">{{priceInfo.desc}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</select-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectModal from "@/components/select-modal.vue";
|
||||
|
||||
export default {
|
||||
components: { SelectModal },
|
||||
props: {
|
||||
priceInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {};
|
||||
},
|
||||
methods: {
|
||||
closeAction() {
|
||||
this.$emit('close');
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.price-description-container {
|
||||
width: 100%;
|
||||
padding: 0 40rpx 10rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.price-info {
|
||||
width: 100%;
|
||||
padding: 36rpx 0;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 1px solid #F7F3F7;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
230
src/page-reser/components/select-address-modal.vue
Normal file
230
src/page-reser/components/select-address-modal.vue
Normal file
@ -0,0 +1,230 @@
|
||||
<template>
|
||||
<select-modal @close="closeAction" title="选择服务地址">
|
||||
<view class="select-address-container">
|
||||
<view v-if="!isLoading && addressList.length" class="address-container">
|
||||
<scroll-view class="scroll-view" scroll-y @scrolltolower="loadMoreAction"
|
||||
refresher-background="transparent">
|
||||
<view class="address-item" v-for="(item, index) in addressList" :key="item.id"
|
||||
@click.stop="changeAddress(item)">
|
||||
<view class="address-info-view">
|
||||
<view class="address-name-view">
|
||||
<text v-if="item.is_default" class="default-address fs-18">默认</text>
|
||||
<text class="app-fc-main fs-30 app-font-bold name-text">{{ item.recipient_name }}</text>
|
||||
<text class="app-fc-main fs-30 app-font-bold">{{ item.phone }}</text>
|
||||
</view>
|
||||
<text class="app-fc-normal fs-26">{{ getAddressText(item) }}</text>
|
||||
</view>
|
||||
<image @click.stop="goToEditAddress(item)" src="@/static/images/address_edit.png" mode="aspectFit" class="address-edit-icon"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="address-container flex-center" v-if="isLoading">
|
||||
<uni-load-more status="loading" :show-text="false"/>
|
||||
</view>
|
||||
<view v-if="addressList.length === 0 && !isLoading" class="address-container">
|
||||
<image src="https://activity.wagoo.live/no_address.png" class="no-address-img" mode="widthFix"/>
|
||||
<!-- <text class="app-fc-normal fs-32 no-text">暂无地址信息</text> -->
|
||||
</view>
|
||||
<view class="add-btn" @click.stop="gotoAddAddress">
|
||||
<image class="add-icon" src="@/static/images/add.png" mode="aspectFit"/>
|
||||
<text class="app-fc-white fs-30">添加地址</text>
|
||||
</view>
|
||||
</view>
|
||||
</select-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectModal from "@/components/select-modal.vue";
|
||||
import { getAddressList } from "@/api/address";
|
||||
|
||||
export default {
|
||||
components: { SelectModal },
|
||||
props: {
|
||||
selectAddress: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
addressList: [],
|
||||
isLoading: true,
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
isLoadMore: false,
|
||||
isNoMore: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
userInfo() {
|
||||
return this.$store.state?.user?.userInfo || {};
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.pageNumber = 1;
|
||||
this.getData();
|
||||
},
|
||||
methods: {
|
||||
closeAction() {
|
||||
this.$emit('close');
|
||||
},
|
||||
changeAddress(address) {
|
||||
this.$emit('changeAddress', address);
|
||||
},
|
||||
loadMoreAction() {
|
||||
if (this.isNoMore || this.isLoadMore) {
|
||||
return;
|
||||
}
|
||||
this.pageNumber++;
|
||||
this.isLoadMore = true;
|
||||
this.getData()
|
||||
},
|
||||
getData() {
|
||||
getAddressList({ user_id: this.userInfo.userID }).then((res) => {
|
||||
let list = res?.data || [];
|
||||
if (this.pageNumber === 1) {
|
||||
this.addressList = list;
|
||||
} else {
|
||||
this.addressList = [...this.addressList, ...list];
|
||||
}
|
||||
this.isLoading = false;
|
||||
this.isLoadMore = false;
|
||||
this.isNoMore = list.length < this.pageSize;
|
||||
}).catch(() => {
|
||||
if (this.pageNumber !== 1) {
|
||||
this.pageNumber--;
|
||||
}
|
||||
this.isLoading = false;
|
||||
this.isLoadMore = false;
|
||||
})
|
||||
},
|
||||
getAddressText(item) {
|
||||
// 组合地址信息:省市区 + 详细地址
|
||||
const region = [item.province, item.city, item.district].filter(Boolean).join('');
|
||||
return region ? `${region}${item.full_address}` : item.full_address;
|
||||
},
|
||||
gotoAddAddress() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/address/edit?isAdd=1`,
|
||||
events: {
|
||||
refreshAddress: () => {
|
||||
this.isLoading = true;
|
||||
this.isNoMore = false;
|
||||
this.isLoadMore = false;
|
||||
this.pageNumber = 1;
|
||||
this.getData();
|
||||
},
|
||||
},
|
||||
})
|
||||
},
|
||||
goToEditAddress(item){
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/address/edit?id=${item?.id || ""}`,
|
||||
events: {
|
||||
refreshAddress: () => {
|
||||
this.isLoading = true;
|
||||
this.isNoMore = false;
|
||||
this.isLoadMore = false;
|
||||
this.pageNumber = 1;
|
||||
this.getData();
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.select-address-container {
|
||||
width: 100%;
|
||||
padding: 0 56rpx 10rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.address-container {
|
||||
width: 100%;
|
||||
height: 444rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 18rpx;
|
||||
|
||||
.no-address-img {
|
||||
margin-top: 30rpx;
|
||||
width: 348rpx;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.no-text {
|
||||
margin: 0 0 24rpx;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.address-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 30rpx 0rpx;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 2rpx solid #F7F3F7;
|
||||
|
||||
.address-info-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
margin-right: 30rpx;
|
||||
|
||||
.address-name-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.default-address {
|
||||
padding: 2rpx 6rpx;
|
||||
color: #40ae36;
|
||||
background: rgba(64, 174, 54, 0.2);
|
||||
border-radius: 6rpx;
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
|
||||
.name-text {
|
||||
margin-right: 16rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.address-edit-icon {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 45rpx;
|
||||
background-color: $app_color_main;
|
||||
|
||||
.add-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
201
src/page-reser/components/select-pet-modal.vue
Normal file
201
src/page-reser/components/select-pet-modal.vue
Normal file
@ -0,0 +1,201 @@
|
||||
<template>
|
||||
<select-modal @close="closeAction" title="选择宠物">
|
||||
<view class="select-pet-container">
|
||||
<view v-if="!isLoading && petList.length" class="pet-container">
|
||||
<scroll-view class="scroll-view" scroll-y @scrolltolower="loadMoreAction"
|
||||
refresher-background="transparent">
|
||||
<view class="pet-item" v-for="(item, index) in petList" :key="item.chongwu_id" @click.stop="changePet(item)">
|
||||
<image v-if="item.chongwu_pic_url" class="pet-icon" mode="scaleToFill" :src="item.chongwu_pic_url"/>
|
||||
<image v-else mode="scaleToFill" class="pet-icon" src="https://activity.wagoo.live/record_avator.png"/>
|
||||
<view class="pet-name-view">
|
||||
<text class="app-fc-main fs-32 app-font-bold-500">{{ item.name }}</text>
|
||||
</view>
|
||||
<image
|
||||
v-if="selectPetInfo.chongwu_id === item.chongwu_id"
|
||||
src="@/static/images/cart_checked.png"
|
||||
mode="widthFix"
|
||||
class="select-icon"
|
||||
/>
|
||||
<image
|
||||
v-else
|
||||
src="@/static/images/unchecked.png"
|
||||
mode="widthFix"
|
||||
class="select-icon"
|
||||
/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="pet-container flex-center" v-if="isLoading">
|
||||
<uni-load-more status="loading" :show-text="false"/>
|
||||
</view>
|
||||
<view v-if="petList.length === 0 && !isLoading" class="pet-container" @click.stop="gotoAddPet">
|
||||
<image src="https://activity.wagoo.live/no_pet.png" class="no-pet-img" mode="heightFix" />
|
||||
</view>
|
||||
<view class="add-btn" @click.stop="gotoAddPet">
|
||||
<image class="add-icon" src="@/static/images/add.png" mode="aspectFit"/>
|
||||
<text class="app-fc-white fs-30">添加宠物</text>
|
||||
</view>
|
||||
</view>
|
||||
</select-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectModal from "@/components/select-modal.vue";
|
||||
import { getPetList } from "@/api/common";
|
||||
import appConfig from '../../constants/app.config';
|
||||
|
||||
export default {
|
||||
components: { SelectModal },
|
||||
props: {
|
||||
petType: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
selectPetInfo: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isLoading: true,
|
||||
pageNumber: 1,
|
||||
pageSize: 10,
|
||||
petList: [],
|
||||
isLoadMore: false,
|
||||
isNoMore: false,
|
||||
appConfig,
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.pageNumber = 1;
|
||||
this.getData();
|
||||
},
|
||||
methods: {
|
||||
closeAction() {
|
||||
this.$emit('close');
|
||||
},
|
||||
changePet(pet) {
|
||||
this.$emit('changePet', pet);
|
||||
},
|
||||
loadMoreAction() {
|
||||
if (this.isNoMore || this.isLoadMore) {
|
||||
return;
|
||||
}
|
||||
this.pageNumber++;
|
||||
this.isLoadMore = true;
|
||||
this.getData()
|
||||
},
|
||||
getData() {
|
||||
getPetList(null, this.pageNumber, this.pageSize).then((res) => {
|
||||
let list = res?.info || [];
|
||||
if (this.pageNumber === 1) {
|
||||
this.petList = list;
|
||||
} else {
|
||||
this.petList = [...this.petList, ...list];
|
||||
}
|
||||
this.isLoading = false;
|
||||
this.isLoadMore = false;
|
||||
this.isNoMore = list.length < this.pageSize;
|
||||
}).catch(() => {
|
||||
if (this.pageNumber !== 1) {
|
||||
this.pageNumber--;
|
||||
}
|
||||
this.isLoading = false;
|
||||
this.isLoadMore = false;
|
||||
})
|
||||
},
|
||||
gotoAddPet() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/record/edit?type=${this.petType }&typeId=aaa`,
|
||||
events: {
|
||||
addPetSuccess: () => {
|
||||
this.isLoading = true;
|
||||
this.isNoMore = false;
|
||||
this.isLoadMore = false;
|
||||
this.pageNumber = 1;
|
||||
this.getData();
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.select-pet-container {
|
||||
width: 100%;
|
||||
padding: 0 60rpx 10rpx;
|
||||
box-sizing: border-box;
|
||||
|
||||
.pet-container {
|
||||
width: 100%;
|
||||
height: 444rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 18rpx;
|
||||
|
||||
.no-pet-img {
|
||||
height: calc(1289 / 1363 * 550rpx);
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.no-text {
|
||||
margin: 44rpx 0 26rpx;
|
||||
align-self: center;
|
||||
}
|
||||
|
||||
.scroll-view {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.pet-item {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 34rpx 22rpx;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 2rpx solid #F7F3F7;
|
||||
|
||||
.pet-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 40rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pet-name-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
|
||||
.select-icon {
|
||||
width: 27rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-btn {
|
||||
width: 100%;
|
||||
height: 90rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 45rpx;
|
||||
background-color: $app_color_main;
|
||||
|
||||
.add-icon {
|
||||
width: 34rpx;
|
||||
height: 34rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 18rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
262
src/page-reser/components/select-reservation-time-modal.vue
Normal file
262
src/page-reser/components/select-reservation-time-modal.vue
Normal file
@ -0,0 +1,262 @@
|
||||
<template>
|
||||
<select-modal @close="closeAction" title="选择预约时间">
|
||||
<view class="select-time-container">
|
||||
<view class="calendar-container">
|
||||
<uni-calendar
|
||||
:insert="true"
|
||||
class="uni-calendar--hook"
|
||||
:start-date="startDate"
|
||||
:end-date="endDate"
|
||||
:date="selectDate"
|
||||
:showMonth="false"
|
||||
@change="changeDate"/>
|
||||
</view>
|
||||
<view class="tips-view">
|
||||
<image src="/pageHome/static/tips.png" class="tips-img" mode="aspectFit"></image>
|
||||
<text class="fs-24 app-fc-normal">
|
||||
{{isAfternoon? '可以预约的时间范围是后天及之后的 14 天' : '可以预约的时间范围是明天及之后的 14 天' }}
|
||||
</text>
|
||||
</view>
|
||||
<text class="fs-32 app-fc-main time-header-text">可预约时段</text>
|
||||
<view class="time-list-container">
|
||||
<scroll-view v-if="!isLoading && dateList.length" class="list-scroll-view" :scroll-y="true">
|
||||
<view
|
||||
@click.stop="changeTimeAction(item)"
|
||||
class="time-item"
|
||||
:class="{'selected-time-item': selectTimeRange.shiduan_id === item.shiduan_id, 'disabled-time-item': item.num === 0}"
|
||||
v-for="item in dateList"
|
||||
:key="item.shiduan_id">
|
||||
<text class="fs-28 app-fc-main">{{ `${item.start}-${item.end}` }}</text>
|
||||
<text class="fs-28 app-fc-main">{{ item.num === 0 ? '已约满' : `剩余${item.num}个` }}</text>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<view v-if="isLoading" class="loading-view">
|
||||
<uni-load-more status="loading"/>
|
||||
</view>
|
||||
<view v-if="!isLoading && dateList.length === 0" class="loading-view">
|
||||
<text class="fs-28 app-fc-main">无可预约时间</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="submit-btn" @click.stop="changeReservationTime">
|
||||
<text class="app-fc-white fs-30">确定</text>
|
||||
</view>
|
||||
</view>
|
||||
</select-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectModal from "@/components/select-modal.vue";
|
||||
import moment from "moment";
|
||||
import "moment/locale/zh-cn";
|
||||
import { getYuYueTimeList } from "@/api/order";
|
||||
|
||||
export default {
|
||||
components: { SelectModal },
|
||||
props: {
|
||||
selectTime: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectTimeRange: {},
|
||||
isLoading: false,
|
||||
selectDate: moment().isAfter(moment().format('YYYY-MM-DD 12:00:00')) ? moment().add(2, 'days').format('YYYY-MM-DD') : moment().add(1, 'days').format('YYYY-MM-DD'),
|
||||
startDate: moment().isAfter(moment().format('YYYY-MM-DD 12:00:00')) ? moment().add(2, 'days').format('YYYY-MM-DD') : moment().add(1, 'days').format('YYYY-MM-DD'),
|
||||
endDate: moment().isAfter(moment().format('YYYY-MM-DD 12:00:00')) ? moment().add(16, 'days').format('YYYY-MM-DD') : moment().add(15, 'days').format('YYYY-MM-DD'),
|
||||
dateList: [],
|
||||
//是下午
|
||||
isAfternoon: moment().isAfter(moment().format('YYYY-MM-DD 12:00:00'))
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
moment.locale('zh-cn'); // 设置中文本地化
|
||||
if (Object.keys(this.selectTime).length > 0) {
|
||||
this.selectDate = this.selectTime.date;
|
||||
this.selectTimeRange = this.selectTime;
|
||||
this.getTimeArray(this.selectTime.date)
|
||||
} else {
|
||||
this.getTimeArray(this.selectDate)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
closeAction() {
|
||||
this.$emit('close');
|
||||
},
|
||||
changeDate(e) {
|
||||
console.log(e,'--')
|
||||
this.selectTimeRange = {};
|
||||
this.selectDate = e.fulldate;
|
||||
this.getTimeArray(e.fulldate)
|
||||
},
|
||||
changeTimeAction(item) {
|
||||
if (item.num === 0) {
|
||||
uni.showToast({
|
||||
title: '当前时间已约满',
|
||||
icon: 'none'
|
||||
})
|
||||
} else {
|
||||
this.selectTimeRange = item;
|
||||
}
|
||||
},
|
||||
changeReservationTime() {
|
||||
if (this.dateList.length === 0) {
|
||||
uni.showToast({
|
||||
title: '暂无可预约时间',
|
||||
icon: 'none'
|
||||
})
|
||||
return;
|
||||
}
|
||||
if (Object.keys(this.selectTimeRange).length === 0) {
|
||||
uni.showToast({
|
||||
title: '请选择一个预约时段',
|
||||
icon: 'none'
|
||||
})
|
||||
return;
|
||||
}
|
||||
let dateLabel;
|
||||
if (moment().format('YYYY-MM-DD') === moment(this.selectDate).format('YYYY-MM-DD')) {
|
||||
dateLabel = `今天${moment(this.selectDate).format('M月D日')}`
|
||||
} else if (moment().add(1, "days").format('YYYY-MM-DD') === moment(this.selectDate).format('YYYY-MM-DD')) {
|
||||
dateLabel = `明天${moment(this.selectDate).format('M月D日')}`
|
||||
} else if (moment().add(2, "days").format('YYYY-MM-DD') === moment(this.selectDate).format('YYYY-MM-DD')) {
|
||||
dateLabel = `后天${moment(this.selectDate).format('M月D日')}`
|
||||
} else {
|
||||
dateLabel = `${moment(this.selectDate).format('M月D日')}`
|
||||
}
|
||||
this.$emit('changeReservationTime', {
|
||||
dateLabel,
|
||||
date: this.selectDate,
|
||||
...this.selectTimeRange,
|
||||
});
|
||||
},
|
||||
getTimeArray(t) {
|
||||
this.isLoading = true
|
||||
this.dateList = [];
|
||||
let isCurrent = moment().format('YYYY-MM-DD') === t;
|
||||
return getYuYueTimeList(t).then((res) => {
|
||||
let list = (res?.info || []).map((item) => {
|
||||
return {
|
||||
...item,
|
||||
start: item.start.substring(0, 5),
|
||||
end: item.end.substring(0, 5),
|
||||
};
|
||||
});
|
||||
this.dateList = list.filter((item) => {
|
||||
let end = moment(item.end, 'HH:mm');
|
||||
let now = moment();
|
||||
if (isCurrent) {
|
||||
return end.isAfter(now);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
this.isLoading = false;
|
||||
return Promise.resolve();
|
||||
}).catch(() => {
|
||||
this.isLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.select-time-container {
|
||||
width: 100%;
|
||||
height: 82vh;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.calendar-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.tips-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 24rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #F5F5F5;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.tips-img {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
margin-right: 6rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.time-header-text {
|
||||
margin-left: 28rpx;
|
||||
}
|
||||
|
||||
.time-list-container {
|
||||
margin-left: 28rpx;
|
||||
width: calc(100% - 56rpx);
|
||||
margin-top: 20rpx;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
|
||||
.loading-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.list-scroll-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
.time-item {
|
||||
width: 100%;
|
||||
height: 102rpx;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-radius: 20rpx;
|
||||
border: 2rpx solid #E5E7EB;
|
||||
background-color: #fff;
|
||||
opacity: 1;
|
||||
margin-bottom: 22rpx;
|
||||
padding: 0 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.selected-time-item {
|
||||
border: 2rpx solid $app_color_main;
|
||||
background-color: $app_color_mark_bg_color;
|
||||
}
|
||||
|
||||
.disabled-time-item {
|
||||
background-color: #FBF7FC;
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submit-btn {
|
||||
width: calc(100% - 120rpx);
|
||||
margin-left: 60rpx;
|
||||
margin-bottom: 10rpx;
|
||||
height: 90rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 45rpx;
|
||||
background-color: $app_color_main;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
79
src/page-reser/constants/home.js
Normal file
79
src/page-reser/constants/home.js
Normal file
@ -0,0 +1,79 @@
|
||||
export const ORDER_STATUS_UNPAY = 1; // 未支付
|
||||
export const ORDER_STATUS_RESERVED = 2; // 已预约
|
||||
export const ORDER_STATUS_SEND = 3; // 已派单
|
||||
export const ORDER_STATUS_SERVICE = 4; //服务中
|
||||
export const ORDER_STATUS_COMPLETED = 5; // 已完成
|
||||
export const ORDER_STATUS_CANCELED = 6; // 已取消
|
||||
export const ORDER_STATUS_REFUND = 7; // 退款中
|
||||
|
||||
export const PRICE_DIFF_TYPE_SERVICE = '1'; //差价类型 服务
|
||||
|
||||
|
||||
export const orderStatusList = [
|
||||
{
|
||||
value: ORDER_STATUS_UNPAY,
|
||||
label: '未支付',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_RESERVED,
|
||||
label: '已预约',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_SEND,
|
||||
label: '已派单',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_SERVICE,
|
||||
label: '服务中',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_COMPLETED,
|
||||
label: '已完成',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_CANCELED,
|
||||
label: '已取消',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_REFUND,
|
||||
label: '退款中',
|
||||
},
|
||||
]
|
||||
|
||||
//展示的状态
|
||||
export const showOrderStatus = [
|
||||
{
|
||||
value: '',
|
||||
label: '全部',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_RESERVED,
|
||||
label: '已预约',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_SERVICE,
|
||||
label: '服务中',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_COMPLETED,
|
||||
label: '已完成',
|
||||
},
|
||||
{
|
||||
value: ORDER_STATUS_CANCELED,
|
||||
label: '已取消',
|
||||
},
|
||||
]
|
||||
|
||||
//充值相关
|
||||
export const rechargeStatus = [
|
||||
{
|
||||
value: '1',
|
||||
label: '充值',
|
||||
},
|
||||
{
|
||||
value: '2',
|
||||
label: '充值记录',
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
851
src/page-reser/order/order-detail-page.vue
Normal file
851
src/page-reser/order/order-detail-page.vue
Normal file
@ -0,0 +1,851 @@
|
||||
<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>
|
||||
<view class="info-cell info-cell-guanjia" v-if="carNumber || managerPhoneNum || managerName">
|
||||
<image v-if="managerPic" :src="managerPic" mode="aspectFit" class="head-icon"/>
|
||||
<image v-else src="/pageHome/static/head.png" mode="aspectFit" class="head-icon"/>
|
||||
<view class="guan-jia-info-container">
|
||||
<text class="app-fc-main fs-32 app-font-bold-700">{{ carNumber }}</text>
|
||||
<text class="app-fc-normal fs-24">{{ `${managerName}管家` }}</text>
|
||||
</view>
|
||||
<view class="phone-view" v-if="managerPhoneNum" @click.stop="isShowCallManagerModal = true">
|
||||
<image src="../static/phone.png" mode="aspectFit" class="call-img"/>
|
||||
<text class="app-fc-main fs-24">电话</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-cell">
|
||||
<view class="info-title-view">
|
||||
<image src="@/static/images/address.png" mode="aspectFit" class="info-icon"/>
|
||||
<text class="app-fc-main fs-28">{{ addressInfo.name }}</text>
|
||||
<text class="app-fc-main fs-28 phone-text">{{ addressInfo.phone }}</text>
|
||||
</view>
|
||||
<view class="address-view">
|
||||
<view class="info-icon"/>
|
||||
<text class="app-fc-normal fs-24 address-text">
|
||||
{{ orderInfo.address || `${addressInfo.area_name}${addressInfo.address}` || '--' }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-cell pet-info-container">
|
||||
<view class="pet-info-cell">
|
||||
<image v-if="petInfo.chongwu_pic" mode="scaleToFill" class="pet-icon"
|
||||
:src="petInfo.chongwu_pic"/>
|
||||
<image v-else mode="scaleToFill" class="pet-icon" src="https://activity.wagoo.live/record_avator.png"/>
|
||||
<view class="pet-info-view">
|
||||
<text class="fs-26 app-fc-main app-font-bold-700">{{ petInfo.name }}</text>
|
||||
<text class="app-fc-normal fs-24">{{ petDesc }}</text>
|
||||
<text class="app-fc-normal fs-24">{{ `出生日期:${petInfo.birthday}` }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="order-goods-container" v-if="goodsList.length" @click.stop="isShowGoodsModal = true">
|
||||
<view class="order-goods-view">
|
||||
<scroll-view class="goods-scroll-view" scroll-x>
|
||||
<image :src="goods.goods_pic" mode="aspectFit" class="good-icon" v-for="goods in goodsList"
|
||||
:key="goods.goods_id"/>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<view class="order-goods-num-view">
|
||||
<text class="app-fc-main fs-24">{{ `随车购商品x${goodsNum}` }}</text>
|
||||
<image class="arrow-icon" src="@/static/images/arrow_right_black.png" mode="aspectFit"/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="info-cell info-cell-gap-20">
|
||||
<detail-cell title="实际宠物重量区间" :content="orderInfo.new_weight_name || orderInfo.weight_name"/>
|
||||
<view class="order-price-view">
|
||||
<detail-cell title="预约支付金额" :content="`¥${orderInfo.price}`" :content-mark="false"/>
|
||||
<detail-cell v-if="orderInfo.dikou_id" title="优惠券" :content="`-¥${couponPrice}`" :content-mark="false"/>
|
||||
<detail-cell v-if="orderInfo.fuwuquan_id" title="服务券金额" :content="`¥${servicePrice}`"
|
||||
:content-mark="false"/>
|
||||
</view>
|
||||
<template v-if="orderInfo.new_weight_name && orderInfo.weight_chajia">
|
||||
<detail-cell v-if="Number(orderInfo.weight_chajia) < 0" title="附加服务费退款金额"
|
||||
:content="`¥${orderInfo.weight_chajia}`"/>
|
||||
<detail-cell v-else title="附加服务费支付金额" :content="`¥${orderInfo.weight_chajia}`"/>
|
||||
</template>
|
||||
<view class="line-view"/>
|
||||
<detail-cell title="金额合计" :content="`¥${totalMoney}`" :title-mark="true" :content-mark="true"
|
||||
:custom-content-style="{'color': '#E70E0E'}"/>
|
||||
</view>
|
||||
|
||||
<view class="info-cell info-cell-gap-20">
|
||||
<detail-cell title="服务订单编号" :content="orderInfo.order_no" :content-mark="false"/>
|
||||
<view class="line-view"/>
|
||||
<detail-cell v-if="isShowReservationTime" title="预约时间" :content="reservationTime" :content-mark="false"/>
|
||||
<detail-cell v-if="!isUnPay && payTime" title="付款时间" :content="payTime" :content-mark="false"/>
|
||||
<detail-cell v-if="serviceStartTime" title="服务开始时间" :content="serviceStartTime" :content-mark="false"/>
|
||||
<detail-cell v-if="serviceEndTime" title="服务完成时间" :content="serviceEndTime" :content-mark="false"/>
|
||||
<view class="line-view"/>
|
||||
<detail-cell title="停车状况" :content="orderInfo.tingche_desc" :content-mark="false"/>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<add-service-pay-modal
|
||||
v-if="isShowPayModal"
|
||||
@close="hidePayModal"
|
||||
:order-info="orderInfo"
|
||||
:new-weight="otherWeight"
|
||||
@changeWeight="selectWeight"
|
||||
@paymentConfirm="paymentConfirm"
|
||||
/>
|
||||
<select-weight-modal
|
||||
v-if="isShowWeight"
|
||||
:weight-list="weightList"
|
||||
:pet-weight="otherWeight"
|
||||
@close="closeWeightModal"
|
||||
@changeWeight="changeOtherWeight"
|
||||
/>
|
||||
<pay-success-modal
|
||||
v-if="isShowPaySuccessModal"
|
||||
@close="isShowPaySuccessModal = false"
|
||||
@ok="okPayAction"
|
||||
/>
|
||||
</view>
|
||||
<view class="bottom-view" v-if="isHasHandle">
|
||||
<view class="handle-btn" v-if="isCanCancelOrder" @click.stop="clickCancel">
|
||||
<text class="fs-24 app-fc-main">取消预约</text>
|
||||
</view>
|
||||
<view class="handle-btn" v-if="isService" @click.stop="showGoods">
|
||||
<text class="app-fc-main fs-24">随车购商品</text>
|
||||
</view>
|
||||
<view class="handle-btn handle-mark-btn" v-if="isCanAddService" @click.stop="showAddService">
|
||||
<text class="fs-24 app-fc-white">调整服务费</text>
|
||||
</view>
|
||||
<view class="handle-btn" v-if="isUnPay" @click.stop="payOrderAction">
|
||||
<text class="fs-24 app-fc-main">立即支付</text>
|
||||
</view>
|
||||
<view class="handle-btn" v-if="isNeedPayService" @click.stop="payNewWeightOrderAction">
|
||||
<text class="fs-24 app-fc-main">支付服务费</text>
|
||||
</view>
|
||||
<view class="handle-btn" v-if="isCompleted" @click.stop="isShowCallModal = true">
|
||||
<text class="app-fc-main fs-24">联系售后</text>
|
||||
</view>
|
||||
<view class="handle-btn " v-if="isHasWashImgs" @click.stop="isShowCompareModal = true">
|
||||
<text class="app-fc-main fs-24">洗护对比图</text>
|
||||
</view>
|
||||
<view class="handle-btn handle-mark-btn" v-if="isCompleted" @click.stop="gotoEvaluate">
|
||||
<text class="fs-24 app-fc-white">{{ orderInfo.pinglun_id ? '查看评价' : '去评价' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<call-modal
|
||||
:phone-number="orderInfo.phone"
|
||||
v-if="isShowCallModal"
|
||||
@close="isShowCallModal = false"
|
||||
/>
|
||||
<call-modal
|
||||
:phone-number="managerPhoneNum"
|
||||
v-if="isShowCallManagerModal"
|
||||
@close="isShowCallManagerModal = false"
|
||||
/>
|
||||
<order-goods-modal
|
||||
v-if="isShowGoodsModal"
|
||||
@close="isShowGoodsModal = false"
|
||||
@gotoDetail="gotoGoodsDetail"
|
||||
:goods-list="goodsList"
|
||||
:price="goodsPrice"
|
||||
/>
|
||||
<CompareModal
|
||||
v-if="isShowCompareModal"
|
||||
@close="isShowCompareModal = false"
|
||||
:is-can-share="true"
|
||||
:is-can-remark="!orderInfo.pinglun_id"
|
||||
:after-imgs="afterImages"
|
||||
:before-imgs="beforeImages"
|
||||
@add="selectImgsChange"
|
||||
@share="shareToCommunity"
|
||||
/>
|
||||
<pop-up-modal
|
||||
v-if="isShowCancelModal"
|
||||
content="确定要取消预约吗?"
|
||||
@confirm="cancelOrder"
|
||||
@cancel="isShowCancelModal = false"
|
||||
/>
|
||||
<success-modal
|
||||
v-if="showSuccessModal"
|
||||
title="转发成功"
|
||||
message="请前往宠圈查看"
|
||||
@ok="jumpToCommunity"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetailCell from "@/components/petOrder/detail-cell.vue";
|
||||
import {
|
||||
ORDER_STATUS_CANCELED,
|
||||
ORDER_STATUS_COMPLETED,
|
||||
ORDER_STATUS_RESERVED,
|
||||
ORDER_STATUS_SEND,
|
||||
ORDER_STATUS_SERVICE,
|
||||
ORDER_STATUS_UNPAY,
|
||||
PRICE_DIFF_TYPE_SERVICE
|
||||
} from "@/pageHome/constants/home";
|
||||
import { addServicePay, cancelOrder, getOrderDetail, payOrder } from "@/api/order";
|
||||
import {
|
||||
ORDER_TYPE_PET_SERVICE, ORDER_TYPE_RESERVATION, PET_HAIR_LONG,
|
||||
PET_IS_STERILIZE_YES,
|
||||
PET_SEX_MALE,
|
||||
PET_TYPE_CAT,
|
||||
PET_TYPE_DOG
|
||||
} from "@/constants/app.business";
|
||||
import { shareCommunity } from '../../api/community';
|
||||
import { cancelPetOrderRefund } from "../../api/login";
|
||||
|
||||
import AddServicePayModal from "@/components/petOrder/add-service-pay-modal.vue";
|
||||
import SelectWeightModal from "@/components/petOrder/select-weight-modal.vue";
|
||||
import { getWeightList } from "@/api/common";
|
||||
import appConfig from '@/constants/app.config'
|
||||
import PaySuccessModal from "@/components/petOrder/pay-success-modal.vue";
|
||||
import moment from "moment";
|
||||
import CallModal from "@/components/petOrder/call-modal.vue";
|
||||
import OrderGoodsModal from "@/pageHome/components/order-goods-modal.vue";
|
||||
import CompareModal from "@/components/CompareModal.vue";
|
||||
import PopUpModal from "@/components/PopUpModal.vue";
|
||||
import SuccessModal from "@/components/SuccessModal.vue";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
PopUpModal,
|
||||
CompareModal,
|
||||
OrderGoodsModal,
|
||||
CallModal,
|
||||
SelectWeightModal,
|
||||
AddServicePayModal,
|
||||
DetailCell,
|
||||
PaySuccessModal,
|
||||
SuccessModal
|
||||
},
|
||||
onLoad(option) {
|
||||
uni.$on('createRemarkSuccess', this.refreshOrderDetail)
|
||||
if (option.orderId) {
|
||||
this.orderId = option.orderId;
|
||||
}
|
||||
},
|
||||
onShow() {
|
||||
this.getData();
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
orderId: '',
|
||||
isLoading: true,
|
||||
orderInfo: {},
|
||||
isShowPayModal: false,
|
||||
otherWeight: {},
|
||||
isShowWeight: false,
|
||||
allWeightList: [],
|
||||
appConfig,
|
||||
isShowPaySuccessModal: false,
|
||||
isShowCallModal: false,
|
||||
isShowGoodsModal: false,
|
||||
isShowCallManagerModal: false,
|
||||
isShowCompareModal: false,
|
||||
isShowCancelModal: false,
|
||||
showSuccessModal: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
goodsList() {
|
||||
return this.orderInfo?.order_list || [];
|
||||
},
|
||||
goodsPrice() {
|
||||
const price = this.goodsList.reduce((total, item) => {
|
||||
return total + item.goods_price * item.number;
|
||||
}, 0);
|
||||
return +price.toFixed(2)
|
||||
},
|
||||
goodsNum() {
|
||||
let num = 0
|
||||
this.goodsList.forEach(item => {
|
||||
num = num + item.number;
|
||||
})
|
||||
return num;
|
||||
},
|
||||
addressInfo() {
|
||||
return this.orderInfo?.address_info || {};
|
||||
},
|
||||
petInfo() {
|
||||
return this.orderInfo?.chongwu_info || {};
|
||||
},
|
||||
weightInfo() {
|
||||
return this.orderInfo?.weight_info || {};
|
||||
},
|
||||
varietyInfo() {
|
||||
return this.orderInfo?.pinzhong_info || {};
|
||||
},
|
||||
isShowReservationTime() {
|
||||
return `${this.orderInfo?.order_type}` === `${ORDER_TYPE_RESERVATION}`
|
||||
},
|
||||
reservationTime() {
|
||||
return `${this.orderInfo?.yuyue_date} ${this.orderInfo?.yuyue_time}`
|
||||
},
|
||||
petDesc() {
|
||||
const varietyName = this.varietyInfo?.pinzhong_name || '';
|
||||
const sex = `${this.petInfo.sex}` === `${PET_SEX_MALE}` ? '男生' : '女生';
|
||||
const pet = `${this.petInfo.type}` === `${PET_TYPE_CAT}` ? '猫' : '狗';
|
||||
let hair = '';
|
||||
if (`${this.petInfo.type}` === `${PET_TYPE_CAT}`) {
|
||||
hair = `/${`${this.petInfo.maofa}` === `${PET_HAIR_LONG}` ? '长毛' : '短毛'}`
|
||||
}
|
||||
const sterilize = `${this.petInfo.is_jueyu}` === `${PET_IS_STERILIZE_YES}` ? '已绝育' : '未绝育';
|
||||
const birthDate = new Date(this.petInfo.birthday);
|
||||
const today = new Date();
|
||||
let age = today.getFullYear() - birthDate.getFullYear();
|
||||
const monthDiff = today.getMonth() - birthDate.getMonth();
|
||||
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birthDate.getDate())) {
|
||||
age--;
|
||||
}
|
||||
const weightName = this.weightInfo?.weight_name || '';
|
||||
return `${varietyName}${hair}/${sex}${pet}/${sterilize}/${age}岁/${weightName}`;
|
||||
},
|
||||
isCompleted() {
|
||||
return this.orderInfo?.status === ORDER_STATUS_COMPLETED
|
||||
},
|
||||
isReceived() {
|
||||
return this.orderInfo?.status === ORDER_STATUS_RESERVED || this.orderInfo?.status === ORDER_STATUS_SEND
|
||||
},
|
||||
//已取消
|
||||
isCanceled() {
|
||||
return this.orderInfo?.status === ORDER_STATUS_CANCELED
|
||||
},
|
||||
//服务中
|
||||
isService() {
|
||||
return this.orderInfo?.status === ORDER_STATUS_SERVICE
|
||||
},
|
||||
isCanCancelOrder() {
|
||||
return this.isReceived
|
||||
},
|
||||
isCanAddService() {
|
||||
return (this.isReceived || this.isService) && !this.isHasNewWeight
|
||||
},
|
||||
isUnPay() {
|
||||
return this.orderInfo?.status === ORDER_STATUS_UNPAY
|
||||
},
|
||||
isNeedPayService() {
|
||||
return this.isReceived && this.isHasNewWeight && `${this.orderInfo.new_weight_status}` !== `${ORDER_STATUS_RESERVED}`
|
||||
},
|
||||
weightList() {
|
||||
if (this.allWeightList.length && this.orderInfo) {
|
||||
//使用优惠券后付款为0后 只增不减
|
||||
if (this.orderInfo.dikou_id && Number(this.orderInfo.pay_price) === 0) {
|
||||
const currentWeightSort = this.allWeightList.find((item) => item.weight_id === this.orderInfo.weight_id)?.sort || 0;
|
||||
if (this.orderInfo.type === PET_TYPE_DOG) {
|
||||
return this.allWeightList.filter((item) => item.type === this.orderInfo.type && item.weight_id !== this.orderInfo.weight_id && Number(item.sort) > Number(currentWeightSort));
|
||||
} else {
|
||||
return this.allWeightList.filter((item) => item.type === this.orderInfo.type && item.weight_id !== this.orderInfo.weight_id && item.maofa === this.petInfo.maofa && Number(item.sort) > Number(currentWeightSort));
|
||||
}
|
||||
} else {
|
||||
if (this.orderInfo.type === PET_TYPE_DOG) {
|
||||
return this.allWeightList.filter((item) => item.type === this.orderInfo.type && item.weight_id !== this.orderInfo.weight_id);
|
||||
} else {
|
||||
return this.allWeightList.filter((item) => item.type === this.orderInfo.type && item.weight_id !== this.orderInfo.weight_id && item.maofa === this.petInfo.maofa);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return []
|
||||
}
|
||||
},
|
||||
isHasNewWeight() {
|
||||
return this.orderInfo?.new_weight_name && this.orderInfo?.weight_chajia
|
||||
},
|
||||
totalMoney() {
|
||||
let changeMoney = Number(this.orderInfo.weight_chajia || 0);
|
||||
let price = Number(this.orderInfo.pay_price || 0);
|
||||
return (price + changeMoney).toFixed(2);
|
||||
},
|
||||
isHasHandle() {
|
||||
return !this.isLoading && (this.isCanCancelOrder || this.isCanAddService || this.isNeedPayService || this.isUnPay || this.isCompleted || this.isService)
|
||||
},
|
||||
payTime() {
|
||||
if (this.orderInfo.pay_time) {
|
||||
return moment.unix(this.orderInfo.pay_time).format('YYYY-MM-DD HH:mm');
|
||||
}
|
||||
return ''
|
||||
},
|
||||
couponPrice() {
|
||||
return +this.orderInfo.dikou_price || 0;
|
||||
},
|
||||
servicePrice() {
|
||||
return +this.orderInfo.fuwuquan_price || 0;
|
||||
},
|
||||
carNumber() {
|
||||
return this.orderInfo?.car_info?.car_no || ''
|
||||
},
|
||||
managerPhoneNum() {
|
||||
return this.orderInfo?.guanjia_info?.mobile || ''
|
||||
},
|
||||
managerName() {
|
||||
return this.orderInfo?.guanjia_info?.name || ''
|
||||
},
|
||||
isHasWashImgs() {
|
||||
return this.isCompleted && (this.orderInfo.json_hou || this.orderInfo.json_qian);
|
||||
},
|
||||
afterImages() {
|
||||
const houUrlList = (this.orderInfo?.json_hou || '').split(',')
|
||||
const houFullUrlList = this.orderInfo?.hou_list || []
|
||||
return houUrlList.map((v, i) => ({
|
||||
url: v,
|
||||
fullUrl: houFullUrlList[i]
|
||||
}))
|
||||
},
|
||||
beforeImages() {
|
||||
const qianUrlList = (this.orderInfo?.json_qian || '').split(',')
|
||||
const qianFullUrlList = this.orderInfo?.qian_list || []
|
||||
return qianUrlList.map((v, i) => ({
|
||||
url: v,
|
||||
fullUrl: qianFullUrlList[i]
|
||||
}))
|
||||
},
|
||||
serviceStartTime() {
|
||||
if (this.orderInfo.fuwu_time) {
|
||||
return moment.unix(this.orderInfo.fuwu_time).format('YYYY-MM-DD HH:mm');
|
||||
}
|
||||
return ''
|
||||
},
|
||||
serviceEndTime() {
|
||||
if (this.orderInfo.over_time) {
|
||||
return moment.unix(this.orderInfo.over_time).format('YYYY-MM-DD HH:mm');
|
||||
}
|
||||
return ''
|
||||
},
|
||||
managerPic() {
|
||||
return this.orderInfo?.guanjia_info?.guanjia_pic || ''
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
uni.$off('createRemarkSuccess', this.refreshOrderDetail);
|
||||
const eventChannel = this.getOpenerEventChannel();
|
||||
eventChannel.emit('refreshList');
|
||||
},
|
||||
methods: {
|
||||
// 一键转发到宠圈
|
||||
shareToCommunity(data) {
|
||||
const { front = [], end = [] } = data;
|
||||
uni.showLoading({
|
||||
title: "处理中...",
|
||||
mask: true,
|
||||
})
|
||||
shareCommunity({
|
||||
order_id: this.orderInfo.order_id,
|
||||
old_pic: front.join(','),
|
||||
new_pic: end.join(',')
|
||||
}).then(() => {
|
||||
uni.hideLoading()
|
||||
this.isShowCompareModal = false
|
||||
this.showSuccessModal = true
|
||||
})
|
||||
},
|
||||
jumpToCommunity() {
|
||||
this.showSuccessModal = false
|
||||
uni.navigateTo({
|
||||
url: '/pages/client/index/index?activePageId=communityPage'
|
||||
})
|
||||
},
|
||||
refreshOrderDetail() {
|
||||
this.isLoading = true;
|
||||
this.getData();
|
||||
},
|
||||
getData() {
|
||||
getWeightList().then((res) => {
|
||||
this.allWeightList = res?.info || [];
|
||||
})
|
||||
getOrderDetail(this.orderId).then((res) => {
|
||||
this.orderInfo = res?.info || {};
|
||||
this.isLoading = false;
|
||||
}).catch(() => {
|
||||
this.isLoading = false;
|
||||
})
|
||||
},
|
||||
showAddService() {
|
||||
this.isShowPayModal = true;
|
||||
},
|
||||
hidePayModal() {
|
||||
this.isShowPayModal = false;
|
||||
this.otherWeight = {};
|
||||
},
|
||||
selectWeight() {
|
||||
this.isShowPayModal = false;
|
||||
this.isShowWeight = true;
|
||||
},
|
||||
closeWeightModal() {
|
||||
this.isShowWeight = false;
|
||||
this.isShowPayModal = true;
|
||||
},
|
||||
changeOtherWeight(data) {
|
||||
this.otherWeight = data;
|
||||
this.isShowWeight = false;
|
||||
this.isShowPayModal = true;
|
||||
},
|
||||
paymentConfirm(data) {
|
||||
this.isShowPayModal = false;
|
||||
uni.showLoading({
|
||||
title: '处理中',
|
||||
mask: true
|
||||
})
|
||||
addServicePay(this.orderId, this.otherWeight.weight_id)
|
||||
.then((res) => {
|
||||
const { code, msg } = res;
|
||||
if (`${code}` === '-121') {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: msg,
|
||||
icon: 'none',
|
||||
duration: 4000
|
||||
})
|
||||
} else {
|
||||
this.wxPayAction(data.needRefund, PRICE_DIFF_TYPE_SERVICE)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.showToast({
|
||||
title: err || '创建订单失败',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.hideLoading();
|
||||
})
|
||||
},
|
||||
clickCancel() {
|
||||
this.isShowCancelModal = true;
|
||||
},
|
||||
cancelOrder() {
|
||||
this.isShowCancelModal = false;
|
||||
uni.showLoading({
|
||||
title: '正在取消订单',
|
||||
mask: true
|
||||
});
|
||||
const data = {
|
||||
business_id:this.orderId,
|
||||
business_type:2
|
||||
}
|
||||
cancelPetOrderRefund(data).then(() => {
|
||||
uni.hideLoading();
|
||||
this.isShowPaySuccessModal = true;
|
||||
}).catch((err) => {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: err || '取消订单失败',
|
||||
icon: 'none'
|
||||
});
|
||||
})
|
||||
},
|
||||
payOrderAction() {
|
||||
uni.showLoading({
|
||||
title: '正在支付',
|
||||
mask: true
|
||||
});
|
||||
this.wxPayAction(false);
|
||||
},
|
||||
payNewWeightOrderAction() {
|
||||
uni.showLoading({
|
||||
title: '正在支付',
|
||||
mask: true
|
||||
});
|
||||
this.wxPayAction(false, PRICE_DIFF_TYPE_SERVICE);
|
||||
},
|
||||
wxPayAction(needRefund, chaJiaType) {
|
||||
if (needRefund) {
|
||||
uni.hideLoading();
|
||||
this.isShowPaySuccessModal = true;
|
||||
return;
|
||||
}
|
||||
payOrder(this.orderId, chaJiaType).then((res) => {
|
||||
const payData = res?.info?.pay_data || {};
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: payData.timeStamp,
|
||||
nonceStr: payData.nonceStr,
|
||||
package: payData.package,
|
||||
signType: payData.signType,
|
||||
paySign: payData.sign,
|
||||
success: (res) => {
|
||||
console.log('success:' + JSON.stringify(res));
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: '支付成功',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.navigateBack()
|
||||
},
|
||||
fail: (err) => {
|
||||
console.log('fail:' + JSON.stringify(err));
|
||||
uni.showToast({
|
||||
title: err?.msg || '支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
}).catch((err) => {
|
||||
uni.showToast({
|
||||
title: err || '支付失败',
|
||||
icon: 'none'
|
||||
})
|
||||
})
|
||||
},
|
||||
okPayAction() {
|
||||
this.isShowPaySuccessModal = false;
|
||||
uni.navigateBack()
|
||||
},
|
||||
gotoEvaluate() {
|
||||
if (this.orderInfo.pinglun_id) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/remark/details?remarkId=${this.orderInfo.pinglun_id}`,
|
||||
});
|
||||
} else {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/order/remark?orderId=${this.orderId}&orderType=${ORDER_TYPE_PET_SERVICE}`,
|
||||
});
|
||||
}
|
||||
},
|
||||
showGoods() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/category/index?petOrderId=${this.orderId}&addressId=${this.addressInfo.address_id}`,
|
||||
});
|
||||
},
|
||||
gotoGoodsDetail(goods_id) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/shop/details?id=${goods_id}&petOrderId=${this.orderId}&petOrderAddressId=${this.addressInfo.address_id}`,
|
||||
});
|
||||
},
|
||||
selectImgsChange(imgs) {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/order/remark?orderId=${this.orderId}&orderType=${ORDER_TYPE_PET_SERVICE}`,
|
||||
success: (res) => {
|
||||
res.eventChannel.emit('remarkInfo', {
|
||||
remarkImages: imgs,
|
||||
afterImages: this.afterImages,
|
||||
beforeImages: this.beforeImages,
|
||||
})
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.order-detail-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #F7F8FA;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.detail-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
margin: 20rpx 32rpx;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.scroll-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
|
||||
.info-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
padding: 40rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 30rpx;
|
||||
background-color: #FFFFFF;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
.order-price-view {
|
||||
width: 100%;
|
||||
padding: 20rpx 24rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #F5F5F5;
|
||||
border-radius: 30rpx;
|
||||
}
|
||||
|
||||
.info-title-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.phone-text {
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.address-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.address-text {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.line-view {
|
||||
width: 100%;
|
||||
height: 2rpx;
|
||||
background-color: #ECECEC;
|
||||
margin: 20rpx 0 18rpx;
|
||||
}
|
||||
|
||||
.head-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 16rpx;
|
||||
overflow: hidden;
|
||||
border-radius: 40rpx;
|
||||
}
|
||||
|
||||
.guan-jia-info-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.phone-view {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
||||
.call-img {
|
||||
width: 60rpx;
|
||||
height: 60rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
.info-cell-guanjia {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-cell-gap-20 {
|
||||
padding: 20rpx 36rpx;
|
||||
}
|
||||
|
||||
.pet-info-container {
|
||||
padding: 40rpx 36rpx;
|
||||
}
|
||||
|
||||
.pet-info-cell {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
flex-direction: row;
|
||||
|
||||
.pet-icon {
|
||||
width: 136rpx;
|
||||
height: 136rpx;
|
||||
flex-shrink: 0;
|
||||
border-radius: 20rpx;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.pet-info-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.order-goods-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-top: 30rpx;
|
||||
|
||||
.order-goods-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
height: 76rpx;
|
||||
flex-direction: row;
|
||||
position: relative;
|
||||
|
||||
.goods-scroll-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
white-space: nowrap;
|
||||
|
||||
.good-icon {
|
||||
width: 76rpx;
|
||||
height: 76rpx;
|
||||
margin-right: 20rpx;
|
||||
background-color: #E5E7EB;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.order-goods-num-view {
|
||||
display: flex;
|
||||
flex-shrink: 0;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-left: 20rpx;
|
||||
|
||||
.arrow-icon {
|
||||
width: 18rpx;
|
||||
height: 18rpx;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-view {
|
||||
width: 100%;
|
||||
padding: 36rpx 16rpx;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-end;
|
||||
background-color: #FFFFFF;
|
||||
|
||||
.handle-btn {
|
||||
width: 152rpx;
|
||||
height: 64rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 2rpx solid #9B939A;
|
||||
border-radius: 32rpx;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.handle-mark-btn {
|
||||
border: 2rpx solid $app_color_main;
|
||||
background-color: $app_color_main;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
</style>
|
||||
939
src/page-reser/reservation/index.vue
Normal file
939
src/page-reser/reservation/index.vue
Normal file
@ -0,0 +1,939 @@
|
||||
<template>
|
||||
<view class="reservation-container">
|
||||
<nav-bar title="预约" />
|
||||
<view class="body-container">
|
||||
<scroll-view class="scroll-view" :scroll-y="true">
|
||||
<view class="form-content">
|
||||
<view class="order-tab-list">
|
||||
<view :class="orderType === ORDER_TYPE_RESERVATION ? 'activeItem' : 'tabItem'"
|
||||
@click.stop="selectOrderType(ORDER_TYPE_RESERVATION)">
|
||||
预约单
|
||||
</view>
|
||||
<view :class="orderType === ORDER_TYPE_SITE ? 'activeItem' : 'tabItem'"
|
||||
@click.stop="selectOrderType(ORDER_TYPE_SITE)">
|
||||
现场单
|
||||
</view>
|
||||
</view>
|
||||
<view class="reservation-info-container">
|
||||
<!-- 其他内容 -->
|
||||
<view class="formWrapper">
|
||||
|
||||
|
||||
<view class="info-top-view" v-if="orderType != ORDER_TYPE_RESERVATION">
|
||||
<view class="top">
|
||||
<view class="title-view">
|
||||
<text class="required">*</text>
|
||||
<text class="app-fc-main fs-24">服务码</text>
|
||||
</view>
|
||||
<view class="info-view">
|
||||
<input class="identity-input fs-24" type="number" v-model="xwID"
|
||||
placeholder="请输入或者扫一扫服务码">
|
||||
<image :src='`${imgPrefix}scan.png`' mode="aspectFit" class="scan-img"
|
||||
@click="scanCode" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="form-section form-section-pet">
|
||||
<view class="form-label-row">
|
||||
<text class="required">*</text>
|
||||
<text class="form-label">选择宠物</text>
|
||||
</view>
|
||||
<view class="add-pet-wrapper">
|
||||
<view v-for="(pet, index) in selectedPetsDisplay" :key="pet.id || index"
|
||||
class="selected-pet-avatar">
|
||||
<image class="pet-avatar-img"
|
||||
:src="(pet.chongwu_pic || pet.pet_avatar || pet.avatar) || `${imgPrefix}record_avator.png`"
|
||||
mode="aspectFill" />
|
||||
<view class="remove-pet-btn" @click.stop="removePet(index)">×</view>
|
||||
<text class="pet-avatar-name">{{ getPetShortName(pet) }}</text>
|
||||
</view>
|
||||
<view class="add-pet-cell" @click="goToSelectPet">
|
||||
<view class="add-pet-btn">
|
||||
<text class="plus-icon">+</text>
|
||||
</view>
|
||||
<text class="add-pet-text">添加宠物</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- <info-cell key="weight" cell-type="text" title="宠物重量区间" :info="petInfo.weight_name"
|
||||
placeholder='先选择宠物' :is-can-click="false" />
|
||||
<info-cell v-if="selectedPetType === PET_TYPE_CAT" key="mofa" cell-type="text" title="宠物毛发"
|
||||
:info="petInfo.hairName" placeholder='先选择宠物' :is-can-click="false" /> -->
|
||||
<info-cell v-if="orderType === ORDER_TYPE_RESERVATION" key="time" cell-type="time"
|
||||
title="选择预约时间" :info="Object.keys(reservationTime).length > 0
|
||||
? `${reservationTime.dateLabel} ${reservationTime.start}-${reservationTime.end}`
|
||||
: ''
|
||||
" :infoTime="reservationTime.shiduan_id" @clickAction="goToSelectTime" placeholder='请选择' />
|
||||
<info-cell key="address" cell-type="address"
|
||||
title="选择服务地址" :address-info="address" @clickAction="goToSelectAddress"
|
||||
placeholder='请选择' />
|
||||
<info-cell v-if="orderType != ORDER_TYPE_SITE" key="park" cell-type="park" title="停车状况"
|
||||
:park-state="parkState" :other-park-state="otherParkState"
|
||||
@changeParkState="changeParkState" @changeOtherParkState="changeOtherParkState" />
|
||||
</view>
|
||||
|
||||
<view v-if="tip" class="tip-view">
|
||||
<image class="tip-icon" :src="imgPrefix + 'reservationTime-notice.png'" mode="aspectFit" />
|
||||
<text class="tip-text">{{ tip }}</text>
|
||||
</view>
|
||||
<view class="payFooter">
|
||||
<view class="leftPay">
|
||||
<view class="priceWrapper">
|
||||
<text class="text">预估:</text>
|
||||
<text class="unitText">
|
||||
¥<text class="price">{{ totalDisplayPrice }}</text>
|
||||
</text>
|
||||
</view>
|
||||
<!-- <view class="vipPrice" v-if="discount === 0">
|
||||
<view>
|
||||
<image :src="`${imgPrefix}vipPrice.png`" mode="widthFix"
|
||||
class="vip-price-img" />
|
||||
<text style="font-size: 24rpx;">¥{{ price && discount ? (price *
|
||||
discount).toFixed(2) : (price ? (price *
|
||||
0.8).toFixed(2) : "0.00") }}</text>
|
||||
</view>
|
||||
</view> -->
|
||||
</view>
|
||||
<view class="payBtn" @click.stop="paymentConfirm">
|
||||
下一步
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 广告 -->
|
||||
<view class="ad-container">
|
||||
<image :src='imgPrefix + "1.png"' mode="widthFix" class="ad-image"></image>
|
||||
<image :src='imgPrefix + "2.png"' mode="widthFix" class="ad-image"></image>
|
||||
<image :src='imgPrefix + "3.png"' mode="widthFix" class="ad-image"></image>
|
||||
<image :src='imgPrefix + "4.png"' mode="widthFix" class="ad-image"></image>
|
||||
<image :src='imgPrefix + "5.png"' mode="widthFix" class="ad-image"></image>
|
||||
<image :src='imgPrefix + "6.png"' mode="widthFix" class="ad-image"></image>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import InfoCell from "@/page-reser/components/info-cell.vue";
|
||||
import {
|
||||
gitDiscountfee
|
||||
} from "../../api/login";
|
||||
import {
|
||||
ARTICLE_TYPE_RESERVATION_CAT,
|
||||
ARTICLE_TYPE_RESERVATION_DOG,
|
||||
ORDER_TYPE_RESERVATION,
|
||||
ORDER_TYPE_SITE,
|
||||
PET_HAIR_LONG,
|
||||
PET_TYPE_CAT,
|
||||
PET_TYPE_DOG,
|
||||
} from "@/constants/app.business";
|
||||
import {
|
||||
getArticleDetail
|
||||
} from "@/api/article";
|
||||
import appConfig from "@/constants/app.config";
|
||||
import {
|
||||
getCityIsOpen,
|
||||
checkWaExists
|
||||
} from "@/api/order";
|
||||
import {
|
||||
imgPrefix
|
||||
} from "@/utils/common";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
InfoCell,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
imgPrefix,
|
||||
xwID: '',
|
||||
PET_TYPE_CAT,
|
||||
PET_TYPE_DOG,
|
||||
ORDER_TYPE_RESERVATION,
|
||||
ORDER_TYPE_SITE,
|
||||
orderType: ORDER_TYPE_RESERVATION,
|
||||
selectedPetType: PET_TYPE_CAT, // 默认选中“猫”
|
||||
petInfo: {}, // 兼容下游,取 selectedPets[0]
|
||||
selectedPets: [], // 多选宠物列表
|
||||
parkState: "",
|
||||
otherParkState: "",
|
||||
price: "",
|
||||
discount: '',
|
||||
discount_price: [], // 接口返回的折扣价数组,展示为数组之和
|
||||
reservationTime: {},
|
||||
address: null,
|
||||
catHtmlData: "",
|
||||
dogHtmlData: "",
|
||||
tip: ''
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initData();
|
||||
},
|
||||
computed: {
|
||||
// 展示价格:discount_price 数组相加的总和
|
||||
totalDisplayPrice() {
|
||||
const arr = Array.isArray(this.discount_price) ? this.discount_price : [];
|
||||
const sum = arr.reduce((s, p) => s + Number(p || 0), 0);
|
||||
return sum.toFixed(2);
|
||||
},
|
||||
selectedPetsDisplay() {
|
||||
return this.selectedPets && this.selectedPets.length > 0 ? this.selectedPets : [];
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getPetShortName(pet) {
|
||||
const n = pet.name || pet.pet_name || pet.pet_nickname || '';
|
||||
return n.length > 2 ? n.slice(0, 2) + '…' : n.slice(0, 2);
|
||||
},
|
||||
initData() {
|
||||
getArticleDetail(ARTICLE_TYPE_RESERVATION_CAT).then((res) => {
|
||||
this.catHtmlData = this.processHtmlContent(res?.info?.content || "");
|
||||
});
|
||||
},
|
||||
processHtmlContent(html) {
|
||||
return html.replace(/max-width/g, "width");
|
||||
},
|
||||
|
||||
selectOrderType(orderType) {
|
||||
if (this.orderType === orderType) {
|
||||
return;
|
||||
}
|
||||
this.reservationTime = {};
|
||||
this.parkState = "";
|
||||
this.address = null;
|
||||
this.price = "";
|
||||
this.discount_price = [];
|
||||
this.tip = "";
|
||||
this.petInfo = {};
|
||||
this.selectedPets = [];
|
||||
this.orderType = orderType;
|
||||
},
|
||||
changeParkState(state) {
|
||||
this.parkState = state;
|
||||
this.otherParkState = "";
|
||||
},
|
||||
changeOtherParkState(state) {
|
||||
this.otherParkState = state;
|
||||
},
|
||||
goToSelectPet() {
|
||||
// 跳转到选择宠物页面(多选:每次返回添加一只)
|
||||
const selectPetInfo = this.selectedPets.length > 0
|
||||
? encodeURIComponent(JSON.stringify(this.selectedPets[0]))
|
||||
: '';
|
||||
uni.navigateTo({
|
||||
url: `/pageHome/selectPet/index?petType=${this.selectedPetType}${selectPetInfo ? `&selectPetInfo=${selectPetInfo}` : ''}`,
|
||||
events: {
|
||||
changePet: (pet) => {
|
||||
this.changePet(pet);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
changePet(item) {
|
||||
item.hairName = item.hair === 1 ? '长毛' : '短毛';
|
||||
const exists = this.selectedPets.some(p => p.id === item.id);
|
||||
if (!exists) {
|
||||
this.selectedPets.push(item);
|
||||
}
|
||||
this.petInfo = this.selectedPets[0] || {};
|
||||
this.tryFetchDiscount();
|
||||
},
|
||||
removePet(index) {
|
||||
this.selectedPets.splice(index, 1);
|
||||
this.petInfo = this.selectedPets[0] || {};
|
||||
this.tryFetchDiscount();
|
||||
},
|
||||
goToSelectAddress() {
|
||||
const selectAddress = this.address && Object.keys(this.address).length > 0
|
||||
? encodeURIComponent(JSON.stringify(this.address))
|
||||
: '';
|
||||
uni.navigateTo({
|
||||
url: `/pageHome/selectAddress/index${selectAddress ? `?selectAddress=${selectAddress}` : ''}`,
|
||||
events: {
|
||||
changeAddress: (address) => {
|
||||
this.changeAddress(address);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
changeAddress(address) {
|
||||
address.area_name = `${address.province} ${address.city} ${address.district}`;
|
||||
this.address = address;
|
||||
this.tryFetchDiscount();
|
||||
},
|
||||
scanCode() {
|
||||
uni.scanCode({
|
||||
success: (res) => {
|
||||
this.xwID = res.result;
|
||||
uni.showToast({
|
||||
title: '扫码成功',
|
||||
icon: 'success'
|
||||
});
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('扫码失败:', err);
|
||||
uni.showToast({
|
||||
title: '扫码失败',
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
goToSelectTime() {
|
||||
const selectTime = this.reservationTime && Object.keys(this.reservationTime).length > 0 ?
|
||||
encodeURIComponent(JSON.stringify(this.reservationTime)) :
|
||||
'';
|
||||
uni.navigateTo({
|
||||
url: `/pageHome/selectTime/index${selectTime ? `?selectTime=${selectTime}` : ''}`,
|
||||
events: {
|
||||
changeReservationTime: (timeData) => {
|
||||
this.changeReservationTime(timeData);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
changeReservationTime(timeData) {
|
||||
this.reservationTime = timeData;
|
||||
this.tryFetchDiscount();
|
||||
},
|
||||
// 仅当「选择宠物」「选择服务地址」「选择预约时间」三者都选好时调用 gitDiscountfee
|
||||
tryFetchDiscount() {
|
||||
const hasPet = this.selectedPets && this.selectedPets.length > 0;
|
||||
const petIds = hasPet ? this.selectedPets.map(p => +p.id) : [];
|
||||
const hasAddress = this.address && Object.keys(this.address).length > 0;
|
||||
const hasTime = this.reservationTime && Object.keys(this.reservationTime).length > 0;
|
||||
const regionId = this.address?.region_id;
|
||||
// 现场单:只需宠物即可拉取价格
|
||||
if (this.orderType === this.ORDER_TYPE_SITE) {
|
||||
if (hasPet && hasAddress) {
|
||||
gitDiscountfee({
|
||||
pet_id: petIds,
|
||||
region_id: regionId
|
||||
}).then((res) => {
|
||||
const discountArr = Array.isArray(res.data.discount_price) ? res.data.discount_price : [res.data.discount_price];
|
||||
const originArr = Array.isArray(res.data.price) ? res.data.price : [res.data.price];
|
||||
// 按顺序将价格赋值给对应宠物:原价 + 折后价
|
||||
discountArr.forEach((discountPrice, index) => {
|
||||
if (this.selectedPets[index]) {
|
||||
const originPrice = originArr[index] != null ? originArr[index] : discountPrice;
|
||||
this.selectedPets[index].basePrice = Number(originPrice || 0); // 原价
|
||||
this.selectedPets[index].discountBasePrice = Number(discountPrice || 0); // 折后价
|
||||
}
|
||||
});
|
||||
// 计算总价:用折后价数组
|
||||
this.price = discountArr.reduce((sum, p) => sum + Number(p || 0), 0);
|
||||
this.discount = res.data.discount;
|
||||
this.discount_price = Array.isArray(res.data.discount_price) ? res.data.discount_price : (res.data.discount_price != null ? [res.data.discount_price] : []);
|
||||
this.tip = res.data.tip;
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
// 预约单:三个都选了才调用
|
||||
if (hasPet && hasAddress && hasTime) {
|
||||
gitDiscountfee({
|
||||
region_id: regionId,
|
||||
pet_id: petIds,
|
||||
order_date: this.reservationTime.date
|
||||
}).then((res) => {
|
||||
const discountArr = Array.isArray(res.data.discount_price) ? res.data.discount_price : [res.data.discount_price];
|
||||
const originArr = Array.isArray(res.data.price) ? res.data.price : [res.data.price];
|
||||
// 按顺序将价格赋值给对应宠物:原价 + 折后价
|
||||
discountArr.forEach((discountPrice, index) => {
|
||||
if (this.selectedPets[index]) {
|
||||
const originPrice = originArr[index] != null ? originArr[index] : discountPrice;
|
||||
this.selectedPets[index].basePrice = Number(originPrice || 0); // 原价
|
||||
this.selectedPets[index].discountBasePrice = Number(discountPrice || 0); // 折后价
|
||||
}
|
||||
});
|
||||
// 计算总价:用折后价数组
|
||||
this.price = discountArr.reduce((sum, p) => sum + Number(p || 0), 0);
|
||||
this.discount = res.data.discount;
|
||||
this.discount_price = Array.isArray(res.data.discount_price) ? res.data.discount_price : (res.data.discount_price != null ? [res.data.discount_price] : []);
|
||||
this.tip = res.data.tip;
|
||||
});
|
||||
}
|
||||
},
|
||||
paymentConfirm() {
|
||||
if (!this.selectedPets.length) {
|
||||
uni.showToast({
|
||||
title: "请选择宠物",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (
|
||||
Object.keys(this.reservationTime).length === 0 &&
|
||||
this.orderType === ORDER_TYPE_RESERVATION
|
||||
) {
|
||||
uni.showToast({
|
||||
title: "请选择预约时间",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 预约单、现场单均需校验服务地址
|
||||
if (!this.address) {
|
||||
uni.showToast({
|
||||
title: "请选择服务地址",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 仅预约单校验停车状况
|
||||
if (this.orderType !== ORDER_TYPE_SITE) {
|
||||
if (!this.parkState) {
|
||||
uni.showToast({
|
||||
title: "请选择停车状况",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
if (this.parkState === "其他" && !this.otherParkState) {
|
||||
uni.showToast({
|
||||
title: "请输入停车信息",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
// 如果是现场单,需要校验服务码
|
||||
if (this.orderType === ORDER_TYPE_SITE) {
|
||||
if (!this.xwID || !this.xwID.trim()) {
|
||||
uni.showToast({
|
||||
title: "请输入服务码",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 校验服务码是否为数字
|
||||
const waCode = Number(this.xwID.trim());
|
||||
if (isNaN(waCode) || waCode <= 0) {
|
||||
uni.showToast({
|
||||
title: "服务码格式不正确",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 调用接口校验服务码
|
||||
uni.showLoading({
|
||||
title: "校验服务码中...",
|
||||
mask: true,
|
||||
});
|
||||
checkWaExists({ wa_code: waCode })
|
||||
.then((res) => {
|
||||
if (!res.data.exists) {
|
||||
uni.showToast({
|
||||
title: "服务码错误",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
} else {
|
||||
this.navigateToAdditional();
|
||||
}
|
||||
uni.hideLoading();
|
||||
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: err.msg || "服务码校验失败,请检查服务码是否正确",
|
||||
icon: "none",
|
||||
duration: 2000,
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 非现场单,直接跳转
|
||||
this.navigateToAdditional();
|
||||
},
|
||||
navigateToAdditional() {
|
||||
uni.navigateTo({
|
||||
url: "/pageHome/order/additional",
|
||||
// url: '/pageHome/reservation/payment-confirm-page',
|
||||
success: (res) => {
|
||||
res.eventChannel.emit("reservationInfo", {
|
||||
petInfo: this.petInfo,
|
||||
selectedPets: this.selectedPets,
|
||||
orderInfo: {
|
||||
parkState: this.otherParkState || this.parkState,
|
||||
orderType: this.orderType,
|
||||
xwID: this.xwID
|
||||
},
|
||||
addresInfo: this.address,
|
||||
reservationTime: this.reservationTime,
|
||||
price: this.totalDisplayPrice, // 全部价格
|
||||
discount: this.discount,
|
||||
discount_price: this.discount_price,
|
||||
});
|
||||
},
|
||||
events: {
|
||||
clearData: () => {
|
||||
this.selectedPetType = PET_TYPE_CAT;
|
||||
this.petInfo = {};
|
||||
this.selectedPets = [];
|
||||
this.parkState = "";
|
||||
this.price = "";
|
||||
this.reservationTime = {};
|
||||
this.address = null;
|
||||
},
|
||||
},
|
||||
});
|
||||
},
|
||||
// paymentConfirm() {
|
||||
// if (!this.petInfo.chongwu_id) {
|
||||
// uni.showToast({
|
||||
// title: "请选择宠物",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// if (
|
||||
// Object.keys(this.reservationTime).length === 0 &&
|
||||
// this.orderType === ORDER_TYPE_RESERVATION
|
||||
// ) {
|
||||
// uni.showToast({
|
||||
// title: "请选择预约时间",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// if (!this.address) {
|
||||
// uni.showToast({
|
||||
// title: "请选择服务地址",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// if (!this.parkState) {
|
||||
// uni.showToast({
|
||||
// title: "请选择停车状况",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// if (this.parkState === "其他" && !this.otherParkState) {
|
||||
// uni.showToast({
|
||||
// title: "请输入停车信息",
|
||||
// icon: "none",
|
||||
// });
|
||||
// return;
|
||||
// }
|
||||
// const data = {
|
||||
// user_id:this.petInfo.member_id,
|
||||
// pet_id:this.petInfo.chongwu_id,
|
||||
// };
|
||||
// isPet(data).then((res) => {
|
||||
// if(res.data){
|
||||
// uni.navigateTo({
|
||||
// url: "/pageHome/order/additional",
|
||||
// success: (res) => {
|
||||
// res.eventChannel.emit("reservationInfo", {
|
||||
// petInfo: this.petInfo,
|
||||
// parkState: this.otherParkState || this.parkState,
|
||||
// petWeight: this.petWeight,
|
||||
// reservationTime: this.reservationTime,
|
||||
// address: this.address,
|
||||
// price: this.price,
|
||||
// discount:this.discount,
|
||||
// estimatePrice: this.totalDisplayPrice,
|
||||
// orderType: this.orderType,
|
||||
// chongwu_id: this.petInfo.chongwu_id,
|
||||
// });
|
||||
// },
|
||||
// events: {
|
||||
// clearData: () => {
|
||||
// this.selectedPetType = PET_TYPE_CAT;
|
||||
// this.petInfo = {};
|
||||
// this.parkState = "";
|
||||
// this.petWeight = {};
|
||||
// this.price = "";
|
||||
// this.reservationTime = {};
|
||||
// this.address = null;
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
// }else{
|
||||
// uni.showModal({
|
||||
// content: '该宠物必须与会员卡绑定才能享受会员折扣',
|
||||
// showCancel: true,
|
||||
// cancelText: '取消',
|
||||
// confirmText: '去绑定',
|
||||
// success: res => {
|
||||
// if (res.confirm) {
|
||||
// uni.navigateTo({
|
||||
// url: `/pages/client/recharge/my-card?user_id=${this.petInfo.member_id}`,
|
||||
// })
|
||||
// } else {
|
||||
// console.log('用户取消操作');
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
// });
|
||||
// },
|
||||
},
|
||||
onShareAppMessage(res) {
|
||||
return {
|
||||
title: appConfig.appShareName,
|
||||
path: "/pages/client/index/index",
|
||||
};
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.reservation-container {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #ffecf3;
|
||||
|
||||
.body-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
|
||||
.scroll-view {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
box-sizing: border-box;
|
||||
|
||||
.form-content {
|
||||
padding: 0 20rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.order-tab-list {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
margin-top: 20rpx;
|
||||
|
||||
.tabItem {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
background-color: #ffd8e6;
|
||||
border-radius: 16rpx 16rpx 0px 0px;
|
||||
height: 92rpx;
|
||||
line-height: 92rpx;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
|
||||
.activeItem {
|
||||
background-color: #fff;
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
height: 92rpx;
|
||||
line-height: 92rpx;
|
||||
border-radius: 16rpx 16rpx 0px 0px;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.reservation-info-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.formWrapper {
|
||||
background-color: #fff;
|
||||
padding: 0;
|
||||
border-radius: 0px 0px 16rpx 16rpx;
|
||||
overflow: hidden;
|
||||
|
||||
.info-top-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
// flex-direction: row;
|
||||
// align-items: center;
|
||||
box-sizing: border-box;
|
||||
height: 104rpx;
|
||||
padding: 0 20rpx;
|
||||
position: relative;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 20rpx;
|
||||
right: 20rpx;
|
||||
height: 2rpx;
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
.top {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
// flex-direction: column;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
box-sizing: border-box;
|
||||
|
||||
.title-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.info-view {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
align-items: center;
|
||||
justify-content: flex-end;
|
||||
|
||||
.identity-input {
|
||||
text-align: right;
|
||||
// direction: rtl;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.right-icon {
|
||||
margin-left: 16rpx;
|
||||
width: 10rpx;
|
||||
height: 5rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.form-section-pet {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: calc(100% - 40rpx);
|
||||
margin: 0 auto;
|
||||
padding: 36rpx 0;
|
||||
border-bottom: 2rpx solid #ececec;
|
||||
}
|
||||
|
||||
.form-label-row {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 28rpx;
|
||||
color: #333;
|
||||
margin-left: 4rpx;
|
||||
}
|
||||
|
||||
.add-pet-wrapper {
|
||||
display: flex;
|
||||
// align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-top: 20rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.selected-pet-avatar {
|
||||
position: relative;
|
||||
width: 64rpx;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.pet-avatar-img {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #f0f0f0;
|
||||
}
|
||||
|
||||
.pet-avatar-name {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-top: 8rpx;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
max-width: 64rpx;
|
||||
}
|
||||
|
||||
.remove-pet-btn {
|
||||
position: absolute;
|
||||
top: -8rpx;
|
||||
right: -8rpx;
|
||||
width: 32rpx;
|
||||
height: 32rpx;
|
||||
border-radius: 50%;
|
||||
background-color: #FF19A0;
|
||||
color: #fff;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 24rpx;
|
||||
line-height: 1;
|
||||
border: 2rpx solid #fff;
|
||||
}
|
||||
|
||||
.add-pet-cell {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.add-pet-btn {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border: 1rpx dashed #3D3D3D;
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: #EBEBEB;
|
||||
}
|
||||
|
||||
.plus-icon {
|
||||
font-size: 60rpx;
|
||||
color: #999;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.add-pet-text {
|
||||
font-size: 24rpx;
|
||||
color: #666;
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// .content-section :last-child {
|
||||
// border-bottom:none;
|
||||
// /* CSS 规则 */
|
||||
// }
|
||||
|
||||
.tip-view {
|
||||
background-color: #fff;
|
||||
padding: 12rpx 20rpx;
|
||||
margin-top: 16rpx;
|
||||
border-radius: 16rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
}
|
||||
|
||||
.tip-icon {
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.tip-text {
|
||||
color: #FF19A0;
|
||||
font-size: 24rpx;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.payFooter {
|
||||
background-color: #fff;
|
||||
border-radius: 16rpx;
|
||||
margin-top: 16rpx;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 20rpx;
|
||||
|
||||
.leftPay {
|
||||
.priceWrapper {
|
||||
.text {
|
||||
font-size: 24rpx;
|
||||
color: #272427;
|
||||
}
|
||||
|
||||
.unitText {
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
color: #FF19A0;
|
||||
}
|
||||
|
||||
.price {
|
||||
color: #FF19A0;
|
||||
font-size: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.vipPrice {
|
||||
margin-top: 14rpx;
|
||||
font-size: 20rpx;
|
||||
color: #9B939A;
|
||||
|
||||
view {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.vip-price-img {
|
||||
width: 43px;
|
||||
height: 14px;
|
||||
margin-right: 8rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.payBtn {
|
||||
background-color: #FF19A0;
|
||||
color: #fff;
|
||||
padding: 30rpx 80rpx;
|
||||
border-radius: 100px;
|
||||
font-size: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.ad-container {
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 16rpx;
|
||||
padding-bottom: 20rpx;
|
||||
|
||||
.ad-image {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ad-image:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.ad-view {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.required {
|
||||
color: #FF19A0;
|
||||
}
|
||||
|
||||
.scan-img {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
margin-left: 8rpx;
|
||||
}
|
||||
</style>
|
||||
447
src/page-reser/reservation/payment-confirm-page.vue
Normal file
447
src/page-reser/reservation/payment-confirm-page.vue
Normal file
@ -0,0 +1,447 @@
|
||||
<template>
|
||||
<view class="payment-confirm-container" v-if="!initializing">
|
||||
<view class="payment-body-container">
|
||||
<view class="info-cell" v-if="reservationInfo.address">
|
||||
<view class="info-title-view">
|
||||
<image src="@/static/images/address.png" mode="aspectFit" class="info-icon"/>
|
||||
<text class="app-fc-main fs-28">{{ reservationInfo.address.name }}</text>
|
||||
<text class="app-fc-main fs-28 phone-text">{{ reservationInfo.address.phone }}</text>
|
||||
</view>
|
||||
<view class="address-view">
|
||||
<view class="info-icon"/>
|
||||
<text class="app-fc-normal fs-24 address-text">
|
||||
{{ `${reservationInfo.address.area_name} ${reservationInfo.address.address}` }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-cell">
|
||||
<view class="info-title-view">
|
||||
<image src="/pageHome/static/time.png" mode="aspectFit" class="info-icon"/>
|
||||
<text class="app-fc-main fs-28">{{ reservationTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-cell info-pet-cell">
|
||||
<detail-cell title="宠物类型" :content="petType"/>
|
||||
<detail-cell v-if="petHair" title="毛型分类" :content="petHair"/>
|
||||
<detail-cell title="宠物姓名" :content="petName"/>
|
||||
<detail-cell title="宠物重量区间" :content="petWeight.weight_name"/>
|
||||
<detail-cell v-if="Object.keys(selectCoupon).length === 0" title="优惠券"
|
||||
:content="couponList.length === 0 ? '暂无可用' : '未选优惠券'" :is-show-arrow="true"
|
||||
:custom-content-style="{'color': '#9B939A'}" @clickAction="isShowCouponModal=true"/>
|
||||
<detail-cell v-else title="优惠券" :content="showCoupon" :is-show-arrow="true"
|
||||
:custom-content-style="{'color': '#FF19A0'}" @clickAction="isShowCouponModal=true"/>
|
||||
<detail-cell v-if="Object.keys(selectService).length === 0" title="服务券"
|
||||
:content="serviceList.length === 0 ? '暂无可用' : '未选服务券'"
|
||||
:is-show-arrow="true"
|
||||
:custom-content-style="{'color': '#9B939A'}" @clickAction="isShowServiceModal=true"/>
|
||||
<detail-cell v-else title="服务券" :content="showService" :is-show-arrow="true"
|
||||
:custom-content-style="{'color': '#FF19A0'}" @clickAction="isShowServiceModal=true"/>
|
||||
<view class="line-view"></view>
|
||||
<detail-cell title="费用预估" :content="`¥${showPrice || '0.00'}`" :title-mark="true"/>
|
||||
</view>
|
||||
<view class="info-cell info-pet-cell">
|
||||
<detail-cell title="停车状况" :content="reservationInfo.parkState" :content-mark="false" :title-mark="true"/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="handle-view">
|
||||
<view class="handle-info">
|
||||
<view class="handle-info-cell">
|
||||
<text class="app-fc-main fs-30">¥</text>
|
||||
<text class="app-fc-main fs-40 app-font-bold">{{ showPrice || '0.00' }}</text>
|
||||
</view>
|
||||
<view class="handle-info-cell tip-cell">
|
||||
<image src="/static/images/notice.png" mode="aspectFit" class="tips-icon"/>
|
||||
<text class="app-fc-normal fs-24">以实际服务宠物的重量为准</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="handle-btn" @click.stop="createPetOrder">
|
||||
<text class="app-fc-white fs-30">确认支付</text>
|
||||
</view>
|
||||
</view>
|
||||
<RechargeCouponModal
|
||||
v-if="isShowCouponModal"
|
||||
:couponList="couponList"
|
||||
:price="reservationInfo.price"
|
||||
:selected-item="selectCoupon"
|
||||
@useCoupon="useCoupon"
|
||||
@close="isShowCouponModal = false"
|
||||
/>
|
||||
<ServiceCouponModal
|
||||
v-if="isShowServiceModal"
|
||||
:service-list="serviceList"
|
||||
@useService="useService"
|
||||
@close="isShowServiceModal = false"
|
||||
:weight-id="petWeight.weight_id"
|
||||
:price="reservationInfo.price"
|
||||
:selected-item="selectService"
|
||||
/>
|
||||
<success-modal
|
||||
v-if="showSuccessModal"
|
||||
:img-src="'https://activity.wagoo.live/order_success.png'"
|
||||
:img-style="{width: '200rpx', height: '200rpx'}"
|
||||
title="预约成功"
|
||||
message="预约状态可在订单中进行查看"
|
||||
@ok="paySuccessAction"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import DetailCell from "@/components/petOrder/detail-cell.vue";
|
||||
import {
|
||||
COUPON_TYPE_PET,
|
||||
ORDER_TYPE_SITE,
|
||||
PET_HAIR_LONG,
|
||||
PET_TYPE_CAT
|
||||
} from "@/constants/app.business";
|
||||
import { createOrder, payOrder } from "@/api/order";
|
||||
import {
|
||||
getCouponListByOrderPrice,
|
||||
getServiceCouponListByWeightId
|
||||
} from "@/api/coupon";
|
||||
import RechargeCouponModal from "@/components/coupon/RechargeCouponModal.vue";
|
||||
import ServiceCouponModal from "@/components/coupon/ServiceCouponModal.vue";
|
||||
import SuccessModal from "@/components/SuccessModal.vue";
|
||||
import moment from "moment";
|
||||
import { ORDER_STATUS_RESERVED } from "@/pageHome/constants/home";
|
||||
|
||||
export default {
|
||||
components: { SuccessModal, ServiceCouponModal, RechargeCouponModal, DetailCell },
|
||||
onLoad(option) {
|
||||
const eventChannel = this.getOpenerEventChannel();
|
||||
eventChannel.on('reservationInfo', (data) => {
|
||||
this.initializing = false;
|
||||
this.reservationInfo = data;
|
||||
Promise.all([this.getMyServiceList(), this.getMyCouponList()]).then((result) => {
|
||||
if (this.serviceList.length) {
|
||||
let selectService = this.serviceList[0];
|
||||
this.serviceList.map((data) => {
|
||||
if (Number(data.price) > Number(selectService.price)) {
|
||||
selectService = data;
|
||||
}
|
||||
});
|
||||
this.selectService = selectService;
|
||||
} else if (this.couponList.length) {
|
||||
let selectCoupon = this.couponList[0]
|
||||
this.couponList.map((data) => {
|
||||
if (Number(data.card_money) > Number(selectCoupon.card_money)) {
|
||||
selectCoupon = data;
|
||||
}
|
||||
});
|
||||
this.selectCoupon = selectCoupon;
|
||||
}
|
||||
})
|
||||
})
|
||||
},
|
||||
computed: {
|
||||
petType() {
|
||||
return `${this.reservationInfo?.petInfo?.type}` === `${PET_TYPE_CAT}` ? '喵喵' : '汪汪'
|
||||
},
|
||||
petName() {
|
||||
return this.reservationInfo?.petInfo?.name || '';
|
||||
},
|
||||
petWeight() {
|
||||
return this.reservationInfo?.petWeight || {};
|
||||
},
|
||||
petHair() {
|
||||
if (`${this.reservationInfo?.petInfo?.type}` === `${PET_TYPE_CAT}`) {
|
||||
return `${this.reservationInfo?.petInfo.maofa}` === `${PET_HAIR_LONG}` ? '长毛' : '短毛';
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
reservationTime() {
|
||||
if (this.reservationInfo.orderType === ORDER_TYPE_SITE) {
|
||||
return '今天 ' + moment().format('M月D日');
|
||||
}
|
||||
return `${this.reservationInfo?.reservationTime?.dateLabel} ${this.reservationInfo?.reservationTime?.start}-${this.reservationInfo?.reservationTime?.end}`
|
||||
},
|
||||
showService() {
|
||||
return this.selectService.name || '';
|
||||
},
|
||||
showCoupon() {
|
||||
return '-¥' + (+this.selectCoupon.card_money || 0);
|
||||
},
|
||||
showPrice() {
|
||||
if (Object.keys(this.selectService).length) {
|
||||
return '0.00'
|
||||
} else {
|
||||
let couponMoney = this.selectCoupon?.card_money || 0;
|
||||
return (Number(this.reservationInfo.price) - couponMoney).toFixed(2);
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
reservationInfo: {},
|
||||
initializing: true,
|
||||
serviceList: [],
|
||||
selectService: {},
|
||||
isShowServiceModal: false,
|
||||
couponList: [],
|
||||
selectCoupon: {},
|
||||
isShowCouponModal: false,
|
||||
showSuccessModal: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
getMyCouponList() {
|
||||
return getCouponListByOrderPrice(this.reservationInfo.price,COUPON_TYPE_PET).then((res)=>{
|
||||
this.couponList = res?.info || [];
|
||||
return Promise.resolve();
|
||||
}).catch(()=>{
|
||||
this.couponList = [];
|
||||
this.selectCoupon = {};
|
||||
return Promise.resolve();
|
||||
})
|
||||
},
|
||||
getMyServiceList() {
|
||||
return getServiceCouponListByWeightId(this.reservationInfo?.petWeight?.weight_id).then((res)=>{
|
||||
this.serviceList = res?.info || [];
|
||||
return Promise.resolve();
|
||||
}).catch(()=>{
|
||||
this.serviceList = []
|
||||
this.selectService = {};
|
||||
return Promise.resolve();
|
||||
})
|
||||
},
|
||||
useCoupon(item) {
|
||||
if (this.selectCoupon.fafang_id === item.fafang_id) {
|
||||
this.selectCoupon = {};
|
||||
} else {
|
||||
this.selectCoupon = item;
|
||||
this.isShowCouponModal = false;
|
||||
}
|
||||
},
|
||||
useService(item) {
|
||||
if (this.selectService.order_id === item.order_id) {
|
||||
this.selectService = {};
|
||||
} else {
|
||||
this.selectService = item;
|
||||
this.isShowServiceModal = false;
|
||||
}
|
||||
},
|
||||
createPetOrder() {
|
||||
if (Object.keys(this.selectService).length && Object.keys(this.selectCoupon).length) {
|
||||
uni.showToast({
|
||||
title: '服务券和优惠券不能同时使用',
|
||||
icon: 'none'
|
||||
})
|
||||
return;
|
||||
}
|
||||
uni.showLoading({
|
||||
title: '正在创建订单',
|
||||
mask: true
|
||||
});
|
||||
const data = {
|
||||
chongwu_id: this.reservationInfo?.petInfo?.chongwu_id,
|
||||
type: this.reservationInfo?.petInfo?.type,
|
||||
weight_id: this.reservationInfo?.petWeight?.weight_id,
|
||||
address_id: this.reservationInfo?.address?.address_id,
|
||||
shiduan_id: this.reservationInfo.orderType === ORDER_TYPE_SITE ? 0 : this.reservationInfo?.reservationTime?.shiduan_id,
|
||||
yuyue_date: this.reservationInfo.orderType === ORDER_TYPE_SITE ? moment().format('YYYY-MM-DD') : this.reservationInfo?.reservationTime?.date,
|
||||
tingche_desc: this.reservationInfo.parkState,
|
||||
desc: '',
|
||||
order_type: this.reservationInfo.orderType,
|
||||
}
|
||||
if (this.selectCoupon.fafang_id) {
|
||||
data.dikou_id = this.selectCoupon.fafang_id;
|
||||
}
|
||||
if (this.selectService.order_id) {
|
||||
data.fuwuquan_id = this.selectService.order_id;
|
||||
}
|
||||
if (`${this.reservationInfo?.petInfo?.type}` === `${PET_TYPE_CAT}`) {
|
||||
data.maofa = this.reservationInfo?.petInfo.maofa;
|
||||
}
|
||||
createOrder(data).then((res) => {
|
||||
if (Object.keys(this.selectService).length || `${this.showPrice}` === '0.00') {
|
||||
const eventChannel = this.getOpenerEventChannel();
|
||||
eventChannel.emit('clearData')
|
||||
uni.hideLoading();
|
||||
this.showSuccessModal = true;
|
||||
} else {
|
||||
this.weixinPay(res.info)
|
||||
}
|
||||
}).catch(() => {
|
||||
uni.showToast({
|
||||
title: '创建订单失败',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.hideLoading();
|
||||
});
|
||||
},
|
||||
weixinPay(orderId) {
|
||||
payOrder(orderId).then((res) => {
|
||||
const payData = res?.info?.pay_data || {};
|
||||
uni.requestPayment({
|
||||
provider: 'wxpay',
|
||||
timeStamp: payData.timeStamp,
|
||||
nonceStr: payData.nonceStr,
|
||||
package: payData.package,
|
||||
signType: payData.signType,
|
||||
paySign: payData.sign,
|
||||
success: (res) => {
|
||||
uni.hideLoading();
|
||||
const eventChannel = this.getOpenerEventChannel();
|
||||
eventChannel.emit('clearData')
|
||||
this.showSuccessModal = true;
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.showToast({
|
||||
title: '创建订单失败',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.hideLoading();
|
||||
}
|
||||
});
|
||||
}).catch(() => {
|
||||
uni.showToast({
|
||||
title: '创建订单失败',
|
||||
icon: 'none'
|
||||
})
|
||||
uni.hideLoading();
|
||||
})
|
||||
},
|
||||
paySuccessAction() {
|
||||
uni.redirectTo({
|
||||
url:'/pages/client/petOrder/index',
|
||||
complete() {
|
||||
uni.$emit('changeTabBar', {
|
||||
pageId: 'orderPage',
|
||||
orderState: ORDER_STATUS_RESERVED
|
||||
})
|
||||
}
|
||||
});
|
||||
// uni.navigateBack({
|
||||
// delta: 1,
|
||||
// complete() {
|
||||
// uni.$emit('changeTabBar', {
|
||||
// pageId: 'orderPage',
|
||||
// orderState: ORDER_STATUS_RESERVED
|
||||
// })
|
||||
// }
|
||||
// })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.payment-confirm-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
background-color: #FBF8FC;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.payment-body-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
padding: 20rpx 32rpx;
|
||||
|
||||
.info-cell {
|
||||
width: 100%;
|
||||
padding: 40rpx;
|
||||
box-sizing: border-box;
|
||||
border-radius: 30rpx;
|
||||
background-color: #FFFFFF;
|
||||
margin-bottom: 32rpx;
|
||||
|
||||
.info-title-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.phone-text {
|
||||
margin-left: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.address-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
.address-text {
|
||||
margin-top: 12rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.info-icon {
|
||||
width: 36rpx;
|
||||
height: 36rpx;
|
||||
flex-shrink: 0;
|
||||
margin-right: 20rpx;
|
||||
}
|
||||
|
||||
.info-view {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.line-view {
|
||||
width: 100%;
|
||||
height: 2rpx;
|
||||
background-color: #ECECEC;
|
||||
margin: 20rpx 0;
|
||||
}
|
||||
}
|
||||
|
||||
.info-pet-cell {
|
||||
padding: 20rpx 40rpx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.handle-view {
|
||||
width: 100%;
|
||||
padding: 20rpx 36rpx 20rpx;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
.handle-info {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
|
||||
.handle-info-cell {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: flex-end;
|
||||
width: 100%;
|
||||
|
||||
.tips-icon {
|
||||
width: 24rpx;
|
||||
height: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.tip-cell {
|
||||
align-items: center;
|
||||
}
|
||||
}
|
||||
|
||||
.handle-btn {
|
||||
width: 260rpx;
|
||||
height: 90rpx;
|
||||
border-radius: 45rpx;
|
||||
background-color: $app_color_main;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user