1
This commit is contained in:
398
src/pages/client/service/details.vue
Normal file
398
src/pages/client/service/details.vue
Normal file
@ -0,0 +1,398 @@
|
||||
<template>
|
||||
<view class="shop-details-container">
|
||||
<view class="banner-swiper" v-if="bannerList.length">
|
||||
<swiper
|
||||
class="swiper-wrapper"
|
||||
circular
|
||||
:indicator-dots="false"
|
||||
:autoplay="true"
|
||||
@change="bannerChange"
|
||||
>
|
||||
<swiper-item v-for="(banner, i) in bannerList" :key="i">
|
||||
<image class="swiper-img" :src="banner" mode="aspectFill" />
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
<view class="flex-row-center dot-box">
|
||||
<view
|
||||
v-for="(banner, index) in bannerList"
|
||||
:key="index"
|
||||
class="dot-item"
|
||||
:class="{ active: bannerIndex === index }"
|
||||
></view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="good-info">
|
||||
<view class="info-cell">
|
||||
<view class="flex-row-between">
|
||||
<view class="">
|
||||
<text class="app-fc-mark fs-24">¥</text>
|
||||
<text class="app-fc-mark fs-44">{{ details.price || 0 }}</text>
|
||||
<text class="fs-24 origin-price">
|
||||
¥{{ details.old_price || 0 }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex-row-end">
|
||||
<text class="fs-22 app-fc-cancel">
|
||||
已售 {{ details.xiaoliang || 0 }}件
|
||||
</text>
|
||||
<view class="fs-22 app-fc-cancel split-line">|</view>
|
||||
<text class="fs-22 app-fc-cancel">
|
||||
剩余{{ details.kucun || 0 }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="fs-36 app-font-bold app-fc-main good-name">
|
||||
{{ details.name || "" }}
|
||||
</view>
|
||||
<view class="flex-row-start">
|
||||
<text
|
||||
class="fs-20 sale-btn"
|
||||
v-for="(label, i) in labelList"
|
||||
:key="i"
|
||||
:class="[i > 0 ? 'sale-today app-fc-mark' : 'app-fc-white']"
|
||||
>
|
||||
{{ label }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-cell">
|
||||
<view class="flex-row-start cell-inner">
|
||||
<text class="fs-26 postage-info">使用区间</text>
|
||||
<text class="fs-26 app-fc-main flex-1">
|
||||
{{ details.weight_name || "-" }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex-row-start cell-inner">
|
||||
<text class="fs-26 postage-info">有效时间</text>
|
||||
<text class="fs-26 app-fc-main flex-1">
|
||||
{{ details.youxiao_time || "-" }}
|
||||
</text>
|
||||
</view>
|
||||
<view class="flex-row-start cell-inner" @click="showGuideModal = true">
|
||||
<text class="fs-26 postage-info">使用规则</text>
|
||||
<text class="fs-26 app-fc-main flex-1 app-text-ellipse">
|
||||
{{ details.desc || "-" }}
|
||||
</text>
|
||||
<image
|
||||
class="arrow-icon"
|
||||
:src="require('@/static/images/arrow_right_black.png')"
|
||||
mode="widthFix"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="info-cell" v-if="remarkList.length">
|
||||
<view class="width-fill flex-row-between">
|
||||
<text class="fs-28 postage-info">
|
||||
用户评价
|
||||
<text class="fs-24 app-fc-normal"> ({{ remarkCount }}) </text>
|
||||
</text>
|
||||
<view class="flex-row-end" @click="jumpToRemark">
|
||||
<text class="fs-26 app-fc-main">查看全部</text>
|
||||
<image
|
||||
class="arrow-icon"
|
||||
:src="require('@/static/images/arrow_right_black.png')"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view class="remark-list">
|
||||
<remark-item v-for="item in remarkList" :key="item.id" :data="item" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="fs-36 app-fc-normal rich-text-title">—— 服务详情 ——</view>
|
||||
<view class="rich-text-content" v-html="details.content"></view>
|
||||
<view class="place-view"></view>
|
||||
|
||||
<view class="flex-row-between details-bottom">
|
||||
<text class="fs-30 app-fc-main">
|
||||
¥<text class="fs-48 app-fc-main app-font-bold">{{ payPrice }}</text>
|
||||
</text>
|
||||
<view
|
||||
class="flex-center fs-30 app-fc-white app-font-bold opt-btn"
|
||||
@click="createOrder"
|
||||
>
|
||||
立即购买
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<use-guide-modal
|
||||
v-if="showGuideModal"
|
||||
title="使用规则"
|
||||
:content="details.desc"
|
||||
@ok="showGuideModal = false"
|
||||
/>
|
||||
|
||||
<success-modal
|
||||
v-if="showSuccessModal"
|
||||
title="购买成功"
|
||||
ok-text="立即预约"
|
||||
@ok="paySuccessAction"
|
||||
/>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getServiceCouponDetail } from "@/api/coupon";
|
||||
import { getRemarkList } from "../../../api/shop";
|
||||
import { ORDER_TYPE_PET_SERVICE } from '@/constants/app.business';
|
||||
import {
|
||||
serviceCouponCreateOrder,
|
||||
serviceCouponOrderPay,
|
||||
} from "../../../api/coupon";
|
||||
|
||||
import UseGuideModal from "@/components/coupon/UseGuideModal.vue";
|
||||
import SuccessModal from "@/components/SuccessModal";
|
||||
import RemarkItem from "@/components/goods/RemarkItem";
|
||||
|
||||
export default {
|
||||
components: {
|
||||
UseGuideModal,
|
||||
SuccessModal,
|
||||
RemarkItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
couponId: "",
|
||||
details: {},
|
||||
bannerList: [],
|
||||
bannerIndex: 0,
|
||||
remarkList: [],
|
||||
showGuideModal: false,
|
||||
showSuccessModal: false,
|
||||
remarkCount : 0
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
labelList() {
|
||||
return (this.details?.label || "").split(",").filter((v) => !!v);
|
||||
},
|
||||
payPrice() {
|
||||
return +this.details.price || 0;
|
||||
},
|
||||
},
|
||||
onLoad(options) {
|
||||
this.couponId = options.id;
|
||||
this.getDetails();
|
||||
this.getRemarkListData();
|
||||
},
|
||||
methods: {
|
||||
// 获取服务券详情
|
||||
getDetails() {
|
||||
getServiceCouponDetail(this.couponId).then((res) => {
|
||||
this.details = res?.info || {};
|
||||
this.bannerList = (this.details.fuwuquan_pic || []).split(',').filter(v => !!v);
|
||||
});
|
||||
},
|
||||
// 获取评论列表
|
||||
getRemarkListData() {
|
||||
getRemarkList({ p: 1, num: 1, type: ORDER_TYPE_PET_SERVICE, guanlian_id: this.couponId }).then(
|
||||
(res) => {
|
||||
this.remarkList = res?.info || [];
|
||||
this.remarkCount = res?.count || 0;
|
||||
}
|
||||
);
|
||||
},
|
||||
// 轮播图
|
||||
bannerChange(e) {
|
||||
this.bannerIndex = e.detail.current;
|
||||
},
|
||||
stripTags(html = "") {
|
||||
return html.replace(/<[^>]+>/g, "");
|
||||
},
|
||||
jumpToRemark() {
|
||||
uni.navigateTo({
|
||||
url: `/pages/client/remark/list?shopId=${this.couponId}&type=${ORDER_TYPE_PET_SERVICE}`,
|
||||
});
|
||||
},
|
||||
// 下单
|
||||
createOrder() {
|
||||
uni.showLoading({
|
||||
title: "处理中",
|
||||
icon: "none",
|
||||
mask: true,
|
||||
});
|
||||
serviceCouponCreateOrder(this.couponId).then((res) => {
|
||||
this.pay(res?.info);
|
||||
});
|
||||
},
|
||||
// 支付
|
||||
pay(orderId) {
|
||||
serviceCouponOrderPay(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();
|
||||
this.showSuccessModal = true;
|
||||
},
|
||||
fail: (err) => {
|
||||
uni.hideLoading();
|
||||
uni.showToast({
|
||||
title: err?.msg || "支付失败",
|
||||
icon: "none",
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
},
|
||||
paySuccessAction(){
|
||||
this.showSuccessModal = false;
|
||||
uni.redirectTo({
|
||||
url: '/pageHome/reservation/index'
|
||||
})
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.shop-details-container {
|
||||
height: 100%;
|
||||
background: #f7f8fa;
|
||||
|
||||
.banner-swiper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 750rpx;
|
||||
.swiper-wrapper {
|
||||
width: 100%;
|
||||
height: 750rpx;
|
||||
.swiper-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
.dot-box {
|
||||
position: absolute;
|
||||
bottom: 30rpx;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
.dot-item {
|
||||
width: 12rpx;
|
||||
height: 12rpx;
|
||||
border-radius: 12rpx;
|
||||
background: rgba(255, 255, 255, 0.6);
|
||||
margin-right: 12rpx;
|
||||
&.active {
|
||||
width: 28rpx;
|
||||
height: 12rpx;
|
||||
background: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.good-info {
|
||||
margin: 24rpx 32rpx;
|
||||
|
||||
.info-cell {
|
||||
background: #fff;
|
||||
border-radius: 20rpx;
|
||||
padding: 36rpx 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
|
||||
.split-line {
|
||||
margin: 0 10rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.cell-inner {
|
||||
padding: 12rpx 0;
|
||||
|
||||
.info-arrow-icon {
|
||||
width: 40rpx;
|
||||
height: 20rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.origin-price {
|
||||
color: #726e71;
|
||||
text-decoration: line-through;
|
||||
margin-left: 18rpx;
|
||||
line-height: 44rpx;
|
||||
}
|
||||
|
||||
.good-name {
|
||||
margin: 30rpx 0;
|
||||
}
|
||||
|
||||
.sale-btn {
|
||||
padding: 6rpx 12rpx;
|
||||
background: $app_color_main;
|
||||
border-radius: 4rpx;
|
||||
border: 1rpx solid $app_color_main;
|
||||
margin-right: 12rpx;
|
||||
margin-bottom: 24rpx;
|
||||
&.sale-today {
|
||||
background: transparent;
|
||||
}
|
||||
}
|
||||
|
||||
.postage-info {
|
||||
color: #9b939a;
|
||||
margin-right: 32rpx;
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
width: 30rpx;
|
||||
height: 18rpx;
|
||||
margin-left: 20rpx;
|
||||
}
|
||||
|
||||
.remark-list {
|
||||
border-top: 2rpx solid #ebebeb;
|
||||
margin-top: 36rpx;
|
||||
::v-deep {
|
||||
.remark-item {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 40rpx 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.rich-text-title {
|
||||
margin: 32rpx 0 24rpx;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.rich-text-content {
|
||||
background: #fff;
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.place-view {
|
||||
height: 190rpx;
|
||||
}
|
||||
|
||||
.details-bottom {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
padding-bottom: 20rpx;
|
||||
padding-bottom: constant(safe-area-inset-bottom);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
padding-top: 20rpx;
|
||||
padding-left: 40rpx;
|
||||
padding-right: 36rpx;
|
||||
left: 0;
|
||||
width: 100vw;
|
||||
background: #fff;
|
||||
box-sizing: border-box;
|
||||
|
||||
.opt-btn {
|
||||
width: 260rpx;
|
||||
height: 92rpx;
|
||||
background: $app_color_main;
|
||||
border-radius: 92rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user