mrr.sj.front/pages/service/components/self-pay.vue

875 lines
22 KiB
Vue

<template>
<view class="self-pay">
<uv-popup ref="popup" mode="bottom" @change="change">
<view class="salf-card">
<view class="pop-card" v-if="serviceType == 1">
<text class="syr-info-address">{{
reservationAddress.server_address
}}</text>
<text class="syr-info-phone">{{
reservationAddress.name + " " + reservationAddress.call_phone
}}</text>
</view>
<view class="pop-card" v-if="serviceType == 1">
<view class="salf-card-between mb-20">
<text class="salf-card-between-text1">到家时间</text>
<text class="salf-card-between-text2">{{
reservationTime.selectedTime
}}</text>
</view>
<view class="salf-card-between">
<text class="salf-card-between-text1">服务人员</text>
<view style="width: 425rpx; justify-content: flex-end" class="flex-row-center">
<image v-if="reservationSyr.head_photo" class="card-right-photo"
:src="reservationSyr.head_photo" />
<text class="salf-card-between-text2" style="width: auto">{{
reservationSyr.name
}}</text>
</view>
</view>
</view>
<view class="pop-card">
<view class="serve-info">
<image :src="serviceInfo.photo[0]" class="serve-info-img" mode="aspectFill"></image>
<view class="serve-info-right">
<text class="serve-info-right-name">{{ serviceInfo.title }}</text>
<view class="serve-info-right-num flex-row-center-between">
<text class="serve-info-right-num-text1">服务数量</text>
<text class="serve-info-right-num-text2">X1</text>
</view>
</view>
</view>
<view class="salf-card-between mb-20" v-if="serviceInfo.line_price">
<text class="salf-card-between-text1">原始价格</text>
<text class="salf-card-between-text2"><text
style="font-size: 22rpx">¥</text>{{ serviceInfo.line_price }}</text>
</view>
<view class="salf-card-between">
<text class="salf-card-between-text1">订单小计</text>
<view>
<text class="salf-card-between-text2"><text
style="font-size: 22rpx">¥</text>{{ isOriginalPrice?serviceInfo.server_price:serviceInfo.team_buy.price}}</text>
</view>
</view>
</view>
<view class="pop-card" v-if="serviceType == 2">
<view class="serve-store">
<image :src="selectStore.head_photo" class="serve-store-img" mode="aspectFill"></image>
<view class="serve-store-right">
<text class="serve-store-right-name">{{ selectStore.name }}</text>
<view class="serve-store-right-num flex-row-center-between">
<view class="flex-row-center">
<text class="serve-store-right-num-text">营业时间:</text>
<text class="serve-store-right-num-text"
style="color: #333333">{{ selectStore.business_time }}</text>
</view>
</view>
</view>
</view>
<view class="serve-store-address flex-row-center">
<view class="serve-store-address-right">
<text class="serve-store-address-right-text">地址{{ selectStore.address }}</text>
<text class="serve-store-address-right-text">电话:{{ selectStore.account }}</text>
</view>
<view class="serve-store-address-left flex-row-center">
<image class="address-left-icon" src="/static/images/icons/adress.png"
@click="openMap(selectStore)"></image>
<image class="address-left-icon ml40" src="/static/images/icons/phone.png"
@click="contactService(selectStore.account)"></image>
</view>
</view>
</view>
<view class="pop-card">
<text class="pop-card-title">选择支付方式</text>
<view class="method-list">
<view class="method-item flex-row-center-between"
:class="{ mb43: index != methodList.length - 1 }" v-for="(item, index) in methodList"
:key="index" @click="selectMethod(item)">
<view class="method-info flex-row-center">
<image :src="item.icon" mode="aspectFit" class="method-icon"></image>
<text class="method-name">{{ item.name }}</text>
</view>
<agree-radio :isAgree="item.selected" :yesImg="`/static/images/agree_y.png`"
:radioSize="`40rpx`" :noImg="`/static/images/icons/no_icon.png`"></agree-radio>
</view>
</view>
</view>
<view class="pop-submit flex-row-center-between">
<view class="pop-submit-left">
<text class="pop-submit-left-text1">应付金额</text>
<text class="pop-submit-left-text2"><text
style="font-size: 24rpx">¥</text>{{ isOriginalPrice?serviceInfo.server_price:serviceInfo.team_buy.price}}</text>
</view>
<view class="pop-submit-btn flex-row-center-center">
<text class="pop-submit-btn-text" @click="submitOrder">立即支付</text>
</view>
</view>
</view>
</uv-popup>
</view>
</template>
<script>
import request from "@/utils/request";
import _public from "@/utils/public";
import locationService from "@/utils/locationService";
import permissionUtils from "@/utils/per";
export default {
name: "AgreeRadio",
props: {
show: {
type: Boolean,
default: false,
},
serviceInfo: {
type: Object,
default: () => ({}),
},
serviceType: {
type: [String, Number],
default: 2,
},
isOriginalPrice: {
type: Boolean,
default: true,
},
},
computed: {
reservationAddress() {
return this.$store.state.reservationAddress;
},
reservationSyr() {
return this.$store.state.reservationSyr;
},
selectStore() {
return this.$store.state.selectStore;
},
reservationTime() {
return this.$store.state.reservationTime;
},
},
data() {
return {
isSubmit: false,
orderInfo: {
id: "",
pay_money: "",
number: "",
},
payType: false,
formData: {},
selectedPayment: "wechat",
methodList: [{
id: 1,
name: "微信",
payment: "wechat",
icon: "/static/images/wechat.png",
selected: true,
},
{
id: 2,
name: "支付宝",
payment: "alipay",
icon: "/static/images/alipay.png",
selected: false,
},
],
};
},
watch: {
show(newVal) {
if (newVal) {
this.open();
} else {
this.close();
}
},
},
methods: {
clearSubmit() {
this.isSubmit = false
},
// 选择支付方式
selectMethod(item) {
this.selectedPayment = item.payment;
this.methodList.forEach((method) => {
method.selected = method.id === item.id;
});
},
open() {
this.$refs.popup.open();
},
close() {
this.$refs.popup.close();
},
change(e) {
this.$emit("change", e);
},
async submitOrder() {
if (this.isSubmit) return;
try {
uni.showLoading({
title: "提交中...",
});
// 提交订单逻辑
let orderData = {};
if (this.serviceType == 2) {
orderData = {
server_id: this.serviceInfo.id, // 测试ID
order_kind: this.serviceType,
order_money: this.serviceInfo.server_price, // 测试ID
server_title: this.serviceInfo.title, // 测试ID
server_type_first_id: this.serviceInfo.first_class_id, // 测试ID
server_type_secod_id: this.serviceInfo.second_class_id, // 测试ID
order_type: 3, // 测试ID
};
} else if (this.serviceType == 1) {
orderData = {
server_id: this.serviceInfo.id, // 测试ID
order_money: this.serviceInfo.server_price, // 测试ID
reservation_time: `${this.reservationTime.selected_date} ${this.reservationTime.selected_time}:00`,
reservation_address_id: this.reservationAddress.id,
server_title: this.serviceInfo.title, // 测试ID
server_type_first_id: this.serviceInfo.first_class_id, // 测试ID
server_type_secod_id: this.serviceInfo.second_class_id, // 测试ID
order_type: 3, // 测试ID
};
if (this.reservationSyr.id_type == 1) {
orderData.order_kind = 1;
}
if (this.reservationSyr.id_type == 2) {
orderData.order_shopid_other = this.reservationSyr.id;
orderData.order_kind = 3;
}
}
if (!this.isOriginalPrice) {
orderData.team_buy_id = this.serviceInfo.team_buy.id
orderData.order_money = this.serviceInfo.team_buy.price
}
console.log("orderData", orderData);
this.isSubmit = true;
let res = await request.post("/user/creatorder", orderData);
console.log("creatorderres", res);
uni.hideLoading();
if (res.code == 200 || res.state == 1) {
this.orderInfo.id = res.data.id;
this.orderInfo.number = res.data.number;
this.orderInfo.pay_money = this.isOriginalPrice ? this.serviceInfo.server_price : this
.serviceInfo.team_buy.price;
console.log("orderInfo", this.orderInfo);
this.confirmPay();
} else {
uni.showToast({
title: res.msg || "提交失败",
icon: "none",
});
this.isSubmit = false;
}
} catch (error) {
uni.hideLoading();
uni.showToast({
title: "提交失败,请重试",
icon: "none",
});
console.error("提交订单失败:", error);
this.isSubmit = false;
}
},
// 确认支付 debounce
async confirmPay() {
let that = this;
try {
uni.showLoading({
title: "支付中...",
});
console.log(that.selectedPayment);
switch (that.selectedPayment) {
case "wechat":
// 调用微信支付
let wechatpayfor = await request.post(
"/user/wechatpayfor",
that.orderInfo
);
console.log("wechatpayfor", wechatpayfor);
if (wechatpayfor.code == 452) {
uni.showToast({
title: wechatpayfor.msg || "支付失败,请重试",
icon: "none",
duration: 2000,
});
this.cancelService();
return;
}
const systemInfo = uni.getSystemInfoSync();
if (systemInfo.platform === "ios") {
let appId = wechatpayfor.data.appid;
delete wechatpayfor.data.appid;
wechatpayfor.data["appId"] = appId;
console.log("wechatpayfor2", wechatpayfor);
}
console.log("================================");
uni.hideLoading();
uni.requestPayment({
provider: "wxpay",
orderInfo: wechatpayfor.data, //微信、支付宝订单数据 【注意微信的订单信息,键值应该全部是小写,不能采用驼峰命名】
success: function(res) {
console.log("success:", res);
console.log(that.orderInfo.id, that.orderInfo.number);
// let rawdata = JSON.parse(res.rawdata);
that.isSubmit = false;
request
.post("/user/wechatsearchorder", {
id: that.orderInfo.id,
number: that.orderInfo.number,
})
.then((orderRes) => {
that.paySuccess();
})
.catch((err) => {
console.log("查询状态", err);
});
},
fail: function(err) {
that.isSubmit = false;
uni.showModal({
title: "提示",
content: "该订单未成功支付",
success: function(res) {
if (res.confirm) {
console.log("用户点击确定");
} else if (res.cancel) {
console.log("用户点击取消");
}
},
});
console.log("fail:", JSON.stringify(err));
},
});
break;
case "alipay":
// 调用支付宝支付
let orderInfo = {
...that.orderInfo,
};
orderInfo.title = that.serviceInfo.title;
console.log("alipayorderInfo", orderInfo);
let alipayfor = await request.post("/user/alipayfor", orderInfo);
if (alipayfor.code == 452) {
uni.showToast({
title: alipayfor.msg || "支付失败,请重试",
icon: "none",
duration: 2000,
});
that.cancelService();
return;
}
console.log("alipayfor", alipayfor);
uni.hideLoading();
uni.requestPayment({
provider: "alipay",
orderInfo: alipayfor.data, //微信、支付宝订单数据 【注意微信的订单信息,键值应该全部是小写,不能采用驼峰命名】
success: function(res) {
that.isSubmit = false;
console.log("success:", res);
console.log(
"id: ",
that.orderInfo.id,
"number: ",
that.orderInfo.number
);
console.log("ali支付成功了====================");
request
.post("/user/alisearchorder", {
id: that.orderInfo.id,
number: that.orderInfo.number,
})
.then((orderRes) => {
console.log("orderRes", orderRes, orderRes.trade_status);
that.paySuccess();
})
.catch((err) => {
console.log("ali报错了】】】】】】】】】】】】】】", err);
console.log("查询状态", err);
});
},
fail: function(err) {
that.isSubmit = false;
uni.showModal({
title: "提示",
content: "该订单未成功支付",
success: function(res) {
if (res.confirm) {
console.log("用户点击确定");
} else if (res.cancel) {
console.log("用户点击取消");
}
},
});
console.log("fail:", JSON.stringify(err));
},
});
break;
}
} catch (error) {
uni.hideLoading();
console.error("支付失败", error);
uni.showToast({
title: "支付失败,请重试",
icon: "none",
});
that.isSubmit = false;
}
},
// 取消订单
async cancelService() {
this.isSubmit = false;
let id = "";
await request
.post("/user/getuser", {
type: 1,
})
.then((res) => {
console.log(res);
id = res.data.id;
});
let data = {
orderNo: this.orderInfo.number,
amount: this.orderInfo.pay_money,
cancel_state: 1,
cancel_id: id,
};
request
.post("/user/cancelorder", data)
.then((res) => {
console.log(22222, res);
})
.catch((err) => {
console.log(err);
})
.finally(() => {
setTimeout(() => {
uni.switchTab({
url: "/pages/order/userorder-list",
});
}, 2000);
});
},
// 支付成功
paySuccess() {
uni.showToast({
title: "支付成功",
icon: "success",
});
setTimeout(() => {
uni.redirectTo({
url: `/pages/order/pay-success?orderId=${this.orderInfo.id}`,
});
}, 50);
this.isSubmit = true;
},
openMap(store) {
if (!store.latitude || !store.longitude) {
uni.showToast({
title: "该门店暂无定位信息",
icon: "none",
});
return;
}
// #ifdef MP-WEIXIN
uni.openLocation({
latitude: parseFloat(store.latitude),
longitude: parseFloat(store.longitude),
name: store.name,
address: store.address,
success: () => console.log("打开地图成功"),
fail: (err) => console.log("打开地图失败:", err),
});
// #endif
// #ifdef APP-PLUS
_public.goMap({
latitude: parseFloat(store.latitude),
longitude: parseFloat(store.longitude),
name: store.name,
address: store.address,
});
// #endif
},
async contactService(phone) {
if (!phone) {
uni.showToast({
title: "暂无联系电话",
icon: "none",
});
return;
}
const systemInfo = uni.getSystemInfoSync();
if (systemInfo.platform === "ios") {
uni.makePhoneCall({
phoneNumber: phone,
});
} else {
try {
const {
granted
} = await permissionUtils.checkPermission(
"phone",
"需要拨打电话权限,方便您联系商家"
);
if (granted) {
uni.makePhoneCall({
phoneNumber: phone,
});
return;
}
const confirm = await this.showPermissionDialog(
"拨打电话权限申请",
"我们需要获取拨打电话权限,以便您直接联系商家"
);
if (!confirm) return;
const result = await permissionUtils.requestPermission(
"phone",
"需要拨打电话权限,方便您联系商家"
);
if (result) {
uni.makePhoneCall({
phoneNumber: phone,
});
} else {
locationService.openAppSettings();
}
} catch (err) {
console.log("联系商家失败:", err);
uni.showToast({
title: "操作失败,请稍后重试",
icon: "none",
});
}
}
},
showPermissionDialog(title, content) {
return new Promise((resolve) => {
uni.showModal({
title,
content,
confirmText: "去设置",
cancelText: "取消",
success: (res) => resolve(res.confirm),
});
});
},
},
};
</script>
<style lang="less">
.self-pay {
.salf-card {
width: 750rpx;
background: #f5f5f5;
border-radius: 30rpx 30rpx 0rpx 0rpx;
padding: 30rpx 20rpx 0rpx 20rpx;
box-sizing: border-box;
.syr-info-address {
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
text-align: left;
font-style: normal;
margin-bottom: 10rpx;
}
.syr-info-phone {
font-weight: 400;
font-size: 28rpx;
color: #999999;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
.salf-card-between {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
.salf-card-between-text1 {
font-weight: 400;
font-size: 28rpx;
color: #666666;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
.salf-card-between-text2 {
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
.card-right-photo {
margin-right: 10rpx;
width: 60rpx;
height: 60rpx;
border-radius: 50%;
}
}
//服务详情样式
.serve-info {
display: flex;
flex-direction: row;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f1f1f1;
margin-bottom: 20rpx;
.serve-info-img {
width: 120rpx;
height: 120rpx;
border-radius: 30rpx;
}
.serve-info-right {
flex: 1;
margin-left: 13rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.serve-info-right-name {
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
.serve-info-right-num {
.serve-info-right-num-text1 {
font-weight: 400;
font-size: 26rpx;
color: #999999;
line-height: 37rpx;
text-align: left;
font-style: normal;
}
.serve-info-right-num-text2 {
font-weight: 400;
font-size: 24rpx;
color: #333333;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
}
}
}
//服务详情样式
.serve-store {
display: flex;
flex-direction: row;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f1f1f1;
margin-bottom: 20rpx;
.serve-store-img {
width: 90rpx;
height: 90rpx;
border-radius: 20rpx;
}
.serve-store-right {
flex: 1;
margin-left: 13rpx;
display: flex;
flex-direction: column;
justify-content: space-between;
.serve-store-right-name {
font-weight: 500;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
.serve-store-right-num {
.serve-store-right-num-text {
font-weight: 400;
font-size: 24rpx;
color: #666666;
line-height: 33rpx;
text-align: left;
font-style: normal;
}
}
}
}
.serve-store-address {
.serve-store-address-right {
flex: 1;
display: flex;
flex-direction: column;
.serve-store-address-right-text {
font-weight: 400;
font-size: 24rpx;
color: #666666;
line-height: 33rpx;
text-align: left;
font-style: normal;
width: 510rpx;
lines: 1;
text-overflow: ellipsis;
}
}
.serve-store-address-left {
.address-left-icon {
width: 43rpx;
height: 43rpx;
}
}
}
.pop-card {
background: #ffffff;
border-radius: 30rpx;
padding: 20rpx;
margin-bottom: 20rpx;
.pop-card-title {
margin-bottom: 30rpx;
font-weight: 400;
font-size: 28rpx;
color: #333333;
line-height: 40rpx;
text-align: left;
font-style: normal;
}
}
.pop-submit {
// position: absolute;
// left: 0;
// right: 0;
// bottom: 0;
padding: 25rpx 25rpx 25rpx 45rpx;
margin: 0 -20rpx;
background: #fff;
.pop-submit-left {
display: flex;
flex-direction: column;
.pop-submit-left-text1 {
font-weight: 500;
font-size: 22rpx;
color: #333333;
line-height: 30rpx;
text-align: left;
font-style: normal;
}
.pop-submit-left-text2 {
font-family: DINPro, DINPro;
font-weight: 500;
font-size: 52rpx;
color: #FF4767;
line-height: 67rpx;
text-align: left;
font-style: normal;
}
}
.pop-submit-btn {
width: 226rpx;
height: 82rpx;
background: #FF4767;
border-radius: 41rpx;
.pop-submit-btn-text {
font-weight: 500;
font-size: 30rpx;
color: #ffffff;
line-height: 82rpx;
text-align: center;
font-style: normal;
}
}
}
}
}
.method-item {}
.method-info {
display: flex;
align-items: center;
}
.method-icon {
width: 38rpx;
height: 38rpx;
margin-right: 20rpx;
}
.method-name {
font-weight: 500;
font-size: 30rpx;
color: #5b5b5b;
line-height: 42rpx;
text-align: left;
font-style: normal;
}
.mb-20 {
margin-bottom: 20rpx;
}
.mb43 {
margin-bottom: 43rpx;
}
.ml40 {
margin-left: 40rpx;
}
.flex-row-center-between {
display: flex;
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.flex-row-center {
display: flex;
flex-direction: row;
align-items: center;
}
.flex-row-center-center {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
}
</style>