jiangchengfeiyi-xiaochengxu/pages/book/photoProductsOrderDetail/photoProductsOrderDetail.vue
2025-03-24 11:43:51 +08:00

718 lines
18 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="flex-col justify-start relative page" :style="{ backgroundImage: 'url(' + bkgPubilcPath + ')' }">
<view class="shrink-0 section" :style="{ backgroundImage: 'url(' + bkgPubilcPath + ')'}"></view>
<view class="flex-col section_2 pos">
<view class="flex-row justify-between group">
<view class="flex-col justify-start items-center text-wrapper" @click="changeState(0)">
<text class="font text">全部</text>
<view class="flex-col justify-start items-center" v-if="isShow[0]" style="border: 1.88rpx solid #E79EA1; width: 90rpx; margin-top: 5rpx;"></view>
</view>
<view class="flex-col justify-start" @click="changeState(1)">
<text class="font text_2">待拍摄</text>
<view class="flex-col justify-start items-center" v-if="isShow[1]" style="border: 1.88rpx solid #E79EA1; width: 90rpx; margin-top: 5rpx;"></view>
</view>
<view class="flex-col justify-start" @click="changeState(2)">
<text class="font text_3">已完成</text>
<view class="flex-col justify-start items-center" v-if="isShow[2]" style="border: 1.88rpx solid #E79EA1; width: 90rpx; margin-top: 5rpx;"></view>
</view>
</view>
<!-- <view class="flex-col justify-start items-center group_2"><view class="section_3"></view></view> -->
</view>
<view class="flex-col pos_2">
<view class="flex-col mt-20 list-item" v-for="(item, index) in advanceOrderList" :key="index" @click="gotoDetailPage(item.id)">
<view class="flex-col">
<view class="flex-row items-center group_3" style="display: flex; justify-content: space-between; align-items: center;">
<view style="display: flex; align-items: center; height: 30rpx;">
<view class="group_4">
<text class="font_2">订单号</text>
<text class="font_3 text_4"></text>
</view>
<view><text class="font_4 text_5">{{ item.orderNumber }}</text></view>
</view>
<view>
<text v-if="item.orderStatus === '待支付'" class="font_5 text_6">{{ item.countdown }}</text>
<text class="font_6 text_7">{{ item.orderStatus }}</text>
</view>
</view>
<view class="flex-row group_5">
<image
class="image" mode="aspectFill"
:src="publicPath + item.photoProductsSnapshot.introImg"
/>
<view class="flex-col items-start flex-1 group_6 ml-19">
<text class="font_7 text_8">{{ item.photoProductsSnapshot.name}}</text>
<text class="font_8 mt-43">¥{{ item.totalAmount.toFixed(2) }}</text>
</view>
</view>
</view>
<view class="flex-col mt-17">
<view class="flex-col section_4">
<text class="self-start font_7 text_9">预约信息</text>
<view class="mt-8 flex-col self-stretch">
<text class="self-start font_7 text_10">预约门店:哈尔滨师范大学</text>
<view class="flex-row justify-between items-center self-stretch group_7">
<text class="font_7 text_11">到店时间:{{ item.specificDate }} {{ item.timePoint }}</text>
<image
class="image_2"
:src="bookUrl + '/photoProductsOrderDetail/nav.png'"
@click.stop="nav"
/>
</view>
<view class="flex-row justify-between items-baseline self-stretch">
<text class="font_9">妆造服务:{{ item.isMakeup === 1 ? '本店上妆' : '无需妆造' }}</text>
<text class="font_10 text_12" @click.stop="nav">导航</text>
</view>
</view>
<text class="mt-8 self-start font_7 text_13">拍摄场地:{{ item.isIndoors == 1 ? '室内' : '室外' }}</text>
</view>
<view class="flex-row justify-end items-center group_8">
<text class="font_2 text_14">实付款:</text>
<text class="font_8">¥{{ item.totalAmount.toFixed(2) }}</text>
</view>
<view class="flex-row justify-center group_9">
<view style="opacity: 0; border: none" v-if="item.orderStatus !== '待支付'" class="ml-10 flex-col justify-start items-center text-wrapper_2">
</view>
<view style="opacity: 0; border: none" v-if="item.orderStatus !== '待支付'" class="ml-10 flex-col justify-start items-center text-wrapper_3">
</view>
<view @click.stop>
<button v-if="item.orderStatus !== '交易关闭'" open-type="contact" bindcontact="handleContact" session-from="sessionFrom" class="flex-col justify-start items-center text-wrapper_2">
<text class="font_6 text_15">联系客服</text>
</button>
</view>
<view v-if="item.orderStatus === '交易关闭'" class="ml-10 flex-col justify-start items-center text-wrapper_2" @click.stop="openDeleteBookingOrderPopup(item.id)">
<text class="font_6">删除订单</text>
</view>
<view v-if="item.orderStatus === '待支付'" class="ml-10 flex-col justify-start items-center text-wrapper_2" @click.stop="openCancelBookingOrderPopup(item.id)">
<text class="font_6">取消订单</text>
</view>
<view v-if="item.orderStatus === '待支付'" @click.stop="wxPay(item.id)" class="ml-10 flex-col justify-start items-center text-wrapper_3">
<text class="font_11 text_16">去付款</text>
</view>
</view>
</view>
</view>
</view>
</view>
<uni-popup ref="cancelBookingOrder" :maskClick="false" :animation="false">
<view class="cancel-booking-order">
<cancelOrderVue></cancelOrderVue>
</view>
</uni-popup>
<uni-popup ref="deleteBookingOrder" :maskClick="false" :animation="false">
<view class="cancel-booking-order">
<deleteOrderVue></deleteOrderVue>
</view>
</uni-popup>
<!-- 遮罩层 -->
<view v-if="isShowMask" class="overlay"></view>
</template>
<script setup lang="ts">
import {nextTick, onBeforeUnmount, onMounted, onUnmounted, ref} from 'vue'
import { bookUrl } from '../../../common/globalImagesUrl';
import emitter from '../../../utils/emitter';
import cancelOrderVue from '../component/cancelOrder.vue';
import deleteOrderVue from '../component/deleteOrder.vue';
import { onLoad } from "@dcloudio/uni-app";
import { baseUrl } from '../../../api/request';
import { getFonts } from '../../../common/globalFont';
import { publicPath,bkgPubilcPath } from '../../../common/globalImagesUrl';
const cookie = wx.getStorageSync("cookie") //请求头
const isShow = ref([true, false, false])
const cancelBookingOrder = ref(null)
const deleteBookingOrder = ref(null)
const advanceOrderList = ref([])
const tempAdvanceOrderList = ref([])
const isShowMask = ref(false)
onLoad((options) => {})
const bkgUrl = ref(bookUrl + '/photoProductsOrderDetail/bkg.png')
onLoad(() => {
getFonts()
})
const gotoDetailPage = (val) => {
uni.navigateTo({
url: '/pages/book/myPhotoProductsOrderDetail/myPhotoProductsOrderDetail?id=' + val
})
}
const flushAdvanceOrderListHandler = () => {
getAdvanceOrder()
};
const closeCancelOrderPopupHandler = () => {
nextTick(() => {
if (cancelBookingOrder.value) {
cancelBookingOrder.value.close()
}
})
}
const closeDeleteOrderPopupHandler = () => {
nextTick(() => {
if (deleteBookingOrder.value) {
deleteBookingOrder.value.close()
}
})
}
onMounted( async () => {
getFonts()
await getAdvanceOrder()
emitter.on('closeCancelOrderPopup', closeCancelOrderPopupHandler)
emitter.on('closeDeleteOrderPopup', closeDeleteOrderPopupHandler)
emitter.on('flushAdvanceOrderList', flushAdvanceOrderListHandler)
})
onUnmounted(() => {
console.log('组件已卸载')
emitter.off('closeCancelOrderPopup', closeCancelOrderPopupHandler)
emitter.off('closeDeleteOrderPopup', closeDeleteOrderPopupHandler)
emitter.off('flushAdvanceOrderList', flushAdvanceOrderListHandler)
})
const openCancelBookingOrderPopup = (orderId:any) => {
emitter.emit('sendBookingOrderId', orderId)
cancelBookingOrder.value.open('center')
}
const openDeleteBookingOrderPopup = (orderId:any) => {
emitter.emit('sendDeleteOrderId', orderId)
deleteBookingOrder.value.open('center')
}
const changeState = async (index:any) => {
if (!isShow.value[index]) {
for (var i = 0; i < 3; i ++ ) {
if (i == index) {
isShow.value[i] = true
} else {
isShow.value[i] = false
}
}
}
if (index === 0) {
advanceOrderList.value = tempAdvanceOrderList.value
}
if (index === 1) {
advanceOrderList.value = tempAdvanceOrderList.value.filter(item => item.orderStatus === '待发货')
}
if (index === 2) {
advanceOrderList.value = tempAdvanceOrderList.value.filter(item => item.orderStatus === '交易成功')
}
}
const nav = () => {
wx.openLocation({
latitude: 45.867741,
longitude: 126.560037,
name: '哈尔滨师范大学(松北校区)',
address: '黑龙江省哈尔滨市呼兰区利民经济开发区师大路1号',
success: (res) => {
console.log(res)
}
})
}
const wxPay = async ( oid )=> { //传入订单id
showLoading()
isShowMask.value = true
try {
const res = await uni.request({
url: baseUrl + '/wechat/payment/photo/create',
method: 'POST',
header: {
'cookie': wx.getStorageSync("cookie")
},
data: { id: oid }
})
const paymentData = res.data.data
wx.requestPayment({
appid: paymentData.appId,
nonceStr: paymentData.nonceStr,
package: paymentData.packageVal,
paySign: paymentData.paySign,
timeStamp: paymentData.timeStamp,
signType: paymentData.signType,
success(res) {
uni.showModal({
content: '支付成功',
showCancel: false
})
console.log('支付成功res--->',res);
},
fail(e) {
uni.showModal({
content: '支付失败,原因为:' + e.errMsg,
showCancel: false
})
// console.log('e.errMsg--->',e.errMsg);
},
complete() {
uni.redirectTo({
url: '/pages/book/myPhotoProductsOrderDetail/myPhotoProductsOrderDetail?id=' + oid
})
}
})
}catch(error) {
console.error('支付请求失败',error);
uni.showModal({
content: '支付请求失败,请重试',
showCancel: false
})
}
}
let loading = false;
function showLoading() {
if (!loading) {
wx.showLoading({
title: '加载中...',
});
loading = true;
}
}
function hideLoading() {
if (loading) {
wx.hideLoading();
loading = false;
}
}
const getAdvanceOrder = async () => {
advanceOrderList.value.forEach(order => {
if (order.countdownInterval) {
clearInterval(order.countdownInterval); // 清除定时器
}
})
const res = await uni.request({
url: baseUrl + '/advanceOrder/list/my',
method: 'POST',
header: {
cookie
}
})
advanceOrderList.value = res.data.data
tempAdvanceOrderList.value = res.data.data
console.log('订单列表打印==================>')
advanceOrderList.value.forEach(order => {
if (order.orderStatus === '待支付') {
startCountdown(order)
}
});
}
// 启动每个订单的倒计时(仅对待支付订单有效)
const startCountdown = (order) => {
if (order.orderStatus === '待支付') {
order.endTime = add30Minutes(order.createTime); // 设置最终取消时间
order.countdownInterval = setInterval(() => {
const now = Math.floor(Date.now() / 1000); // 获取当前时间的时间戳(秒)
const remainingTime = order.endTime - now;
if (remainingTime <= 0) {
order.countdown = '00:00';
clearInterval(order.countdownInterval); // 清除定时器
order.orderStatus = '交易关闭'
uni.showModal({
title: '提示',
content: '订单超时未支付,已取消',
showCancel: false
})
} else {
const minutes = Math.floor(remainingTime / 60); // 计算剩余分钟
const seconds = remainingTime % 60; // 计算剩余秒数
order.countdown = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}`;
}
}, 1000);
}
};
// 时间格式化函数,处理后端返回的时间
const parseDate = (dateString) => {
const [date, time] = dateString.split(' ');
const [year, month, day] = date.split('-').map(Number);
const [hour, minute, second] = time.split(':').map(Number);
return new Date(year, month - 1, day, hour, minute, second); // JavaScript Date的月份是从0开始的
};
// 给订单创建时间加上30分钟
const add30Minutes = (createdTime) => {
const date = parseDate(createdTime);
date.setMinutes(date.getMinutes() + 1); // 加上30分钟
return Math.floor(date.getTime() / 1000); // 返回时间戳(秒)
};
// 在组件卸载时清除所有定时器,避免内存泄漏
onBeforeUnmount(() => {
advanceOrderList.value.forEach(order => {
if (order.countdownInterval) {
clearInterval(order.countdownInterval); // 清除定时器
}
})
});
const routerJump = (val:any) => {
let pages = getCurrentPages();
var num = pages.length
if (num == 1) return ;
console.log(pages)
//当前页面栈总数
var backnum = num
for( var i = 0; i < num; i ++ ) {
//循环找到指定页面路由所在的页数
if(pages[i].route == val){
//'pages/mypage/mypage'替换成A页面的路由地址
backnum = num - i - 1
//计算返回的层数,总数-指定页面页数-1
}
}
uni.navigateBack({
delta:backnum
//返回的页面数,如果 delta 大于现有页面数,则返回到首页。
})
}
onUnmounted(() => {
// routerJump('/pages/book/myPhotoProductDetail/myPhotoProductDetail')
})
</script>
<style scoped lang="scss">
button {
padding: 0;
margin: 0;
background-color: #fff;
}
button::after{
border: none;
}
.overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.4); /* 半透明黑色背景 */
z-index: 999;
}
.cancel-booking-order {
// height: 800rpx;
margin-top: -150rpx;
}
.ml-19 {
margin-left: 35.63rpx;
}
.mt-43 {
margin-top: 80.63rpx;
}
.mt-17 {
margin-top: 31.88rpx;
}
.page {
background-color: #ffffff;
overflow: hidden;
background-size: 100% 100%;
background-repeat: no-repeat;
width: 100%;
overflow-y: auto;
overflow-x: hidden;
height: 100%;
}
.section {
background-size: 100% 100%;
background-repeat: no-repeat;
width: 750rpx;
height: 100vh;
}
.section_2 {
padding-left: 80.63rpx;
padding-right: 71.25rpx;
background-color: #EBE7E4;
}
.pos {
position: fixed;
left: 0;
right: 0;
top: 0;
z-index: 99;
}
.group {
padding: 13.75rpx 0 0rpx;
}
.text-wrapper {
width: 91.88rpx;
}
.font {
font-size: 30rpx;
font-family: FangZhengFonts;
color: #000000;
}
.text {
line-height: 48.48rpx;
}
.text_2 {
line-height: 48.24rpx;
}
.text_3 {
line-height: 47.43rpx;
}
.group_2 {
// border-left: solid 99.38rpx #e79ea1;
// border-right: solid 99.38rpx #e79ea1;
}
.section_3 {
background-color: #e79ea1;
width: 99.38rpx;
height: 5.63rpx;
}
.pos_2 {
position: absolute;
left: 15rpx;
right: 15rpx;
top: 100.5rpx;
}
.list-item {
padding: 22.5rpx;
box-sizing: content-box;
background-color: #fff;
border-radius: 18.75rpx;
}
.list-item:first-child {
margin-top: 0;
}
.list-item:last-child {
margin-bottom: 50rpx;
}
.group_3 {
padding: 0 15rpx 18.75rpx;
border-bottom: solid 1.88rpx #dbdbdb;
}
.group_4 {
line-height: 25.84rpx;
height: 25.84rpx;
}
.font_2 {
font-size: 26.25rpx;
font-family: FangZhengFonts;
line-height: 25.84rpx;
color: #323232;
}
.font_3 {
font-size: 26.25rpx;
font-family: Open Sans;
line-height: 17.53rpx;
color: #323232;
}
.text_4 {
line-height: 16.8rpx;
}
.font_4 {
font-size: 26.25rpx;
font-family: FangZhengFonts;
line-height: 17.53rpx;
color: #323232;
}
.text_5 {
font-size: 28.13rpx;
line-height: 25.84rpx;
}
.font_5 {
font-size: 26.25rpx;
font-family: FangZhengFonts;
line-height: 17.53rpx;
color: #e79ea1;
}
.text_6 {
// margin-left: 45rpx;
}
.font_6 {
font-size: 26.25rpx;
font-family: FangZhengFonts;
line-height: 25.84rpx;
color: #e79ea1;
}
.text_7 {
margin-left: 3.75rpx;
line-height: 24.71rpx;
}
.group_5 {
padding: 15rpx 15rpx 0;
}
.image {
width: 120rpx;
height: 133.13rpx;
}
.group_6 {
margin-bottom: 3.75rpx;
}
.font_8 {
font-size: 33.75rpx;
font-family: FangZhengFonts;
line-height: 22.54rpx;
color: #e79ea1;
}
.section_4 {
margin: 0 12.5rpx;
padding: 22.5rpx 18.75rpx;
background-color: #f4f4f4;
border-radius: 9.38rpx;
}
.font_7 {
font-size: 26.25rpx;
font-family: FangZhengFonts;
line-height: 25.84rpx;
color: #000000;
}
.text_9 {
font-size: 28.13rpx;
line-height: 26.25rpx;
}
.text_8 {
font-size: 28.13rpx;
line-height: 27.36rpx;
}
.text_10 {
line-height: 25.33rpx;
}
.group_7 {
margin-top: 3.75rpx;
}
.text_11 {
line-height: 24.51rpx;
}
.image_2 {
// margin-right: 7.5rpx;
width: 45rpx;
height: 45rpx;
}
.font_9 {
font-size: 26.25rpx;
font-family: FangZhengFonts;
line-height: 23.79rpx;
color: #000000;
}
.font_10 {
font-size: 22.5rpx;
font-family: FangZhengFonts;
line-height: 21.09rpx;
color: #000000;
}
.text_12 {
margin-right: 3.75rpx;
}
.text_13 {
line-height: 24.21rpx;
}
.group_8 {
padding: 30rpx 22.5rpx 22.5rpx;
border-bottom: solid 1.88rpx #dbdbdb;
}
.text_14 {
font-size: 28.13rpx;
line-height: 26.7rpx;
}
.group_9 {
padding: 20.63rpx 0 0 180rpx;
}
.text_15 {
line-height: 25.54rpx;
}
.text-wrapper_2 {
padding: 15rpx 0;
background-color: #ffffff;
border-radius: 75rpx;
width: 153.75rpx;
height: 56.25rpx;
border: solid 1.88rpx #e79ea1;
}
.text-wrapper_3 {
padding: 15rpx 0;
background-color: #e79ea1;
border-radius: 75rpx;
width: 153.75rpx;
height: 56.25rpx;
}
.font_11 {
font-size: 26.25rpx;
font-family: FangZhengFonts;
line-height: 25.84rpx;
color: #ffffff;
}
.text_16 {
line-height: 24rpx;
}
/* 去掉滚动条样式 */
::-webkit-scrollbar {
display: none;
}
@import url(../../../common/css/global.css);
</style>