master
lion 7 months ago
parent e60c9bcc4d
commit 81b078d9cd

@ -90,84 +90,134 @@
</view> </view>
</view> </view>
<!-- 支付二维码 --> <!-- 支付区域 -->
<view class="payment-popup" v-if="orderInfo.pay_status === 0" id="pay-qrcode-section"> <view class="payment-popup" v-if="orderInfo.pay_status === 0" id="pay-qrcode-section">
<view class="title">付款二维码</view> <!-- Tab 切换 -->
<view class="amount"> <view class="payment-tabs">
<text class="symbol">¥</text> <view
<text class="number">{{orderInfo.price}}</text> class="tab-item"
</view> :class="{ 'tab-active': activeTab === 'qrcode' }"
@click="switchTab('qrcode')"
<view class="qr-code"> >
<!-- 支付二维码 --> 付款二维码
<view v-if="myQrcode" style="border: 1px solid #ccc; padding: 10rpx;">
<uqrcode
v-if="myQrcode"
canvas-id="pay-qrcode"
:value="myQrcode"
:size="400"
:sizeUnit="'rpx'"
:options="{
margin: 10,
}"
></uqrcode>
</view> </view>
<view v-else style="text-align: center; color: #999; padding: 40rpx;"> <view
正在生成二维码... class="tab-item"
:class="{ 'tab-active': activeTab === 'pay' }"
@click="switchTab('pay')"
>
立即支付
</view> </view>
</view> </view>
<view class="tips"> <!-- Tab 内容 -->
<text>请扫码支付订单金额</text> <view class="tab-content">
<text class="sub-tips">支付完成后订单将自动完成</text> <!-- 付款二维码 Tab -->
</view> <view v-if="activeTab === 'qrcode'" class="tab-panel">
<view class="amount">
<text class="symbol">¥</text>
<text class="number">{{orderInfo.price}}</text>
</view>
<!-- 分享按钮 --> <view class="qr-code">
<view class="share-section"> <!-- 支付二维码 -->
<u-button <view v-if="myQrcode" style="border: 1px solid #ccc; padding: 10rpx;">
type="primary" <!-- 显示图片可长按识别 -->
size="medium" <image
@click="showShareGuide" v-if="qrcodeImagePath"
:custom-style="{ :src="qrcodeImagePath"
background: 'linear-gradient(to right, #1479ff, #4a90e2)', mode="aspectFit"
color: '#fff', show-menu-by-longpress
borderRadius: '40rpx', style="width: 400rpx; height: 400rpx; display: block; margin: 0 auto;"
fontSize: '28rpx' ></image>
}" <!-- Canvas 绘制使用 hide 属性隐藏但保持可渲染 -->
> <uqrcode
<u-icon name="share" color="#fff" size="16" style="margin-right: 8rpx;"></u-icon> v-else
转发给微信好友 ref="payQrcode"
</u-button> id="pay-qrcode"
canvas-id="pay-qrcode"
<!-- 返回首页按钮仅分享进入时显示 --> :value="myQrcode"
<u-button :size="400"
v-if="isFromShare" :sizeUnit="'rpx'"
type="default" :hide="true"
size="medium" :options="{
@click="goToHome" margin: 10,
:custom-style="{ }"
marginTop: '20rpx', @complete="onQrcodeComplete"
borderRadius: '40rpx', ></uqrcode>
fontSize: '28rpx' </view>
}" <view v-else style="text-align: center; color: #999; padding: 40rpx;">
> 正在生成二维码...
<u-icon name="home" color="#1479ff" size="16" style="margin-right: 8rpx;"></u-icon> </view>
返回首页 </view>
</u-button>
<view class="tips">
<text>请扫码支付订单金额</text>
<text class="sub-tips">支付完成后订单将自动完成</text>
</view>
<!-- 分享按钮 -->
<view class="share-section">
<u-button
type="primary"
size="medium"
@click="showShareGuide"
:custom-style="{
background: 'linear-gradient(to right, #1479ff, #4a90e2)',
color: '#fff',
borderRadius: '40rpx',
fontSize: '28rpx'
}"
>
<u-icon name="share" color="#fff" size="16" style="margin-right: 8rpx;"></u-icon>
转发给微信好友
</u-button>
<!-- 返回首页按钮仅分享进入时显示 -->
<u-button
v-if="isFromShare"
type="default"
size="medium"
@click="goToHome"
:custom-style="{
marginTop: '20rpx',
borderRadius: '40rpx',
fontSize: '28rpx'
}"
>
<u-icon name="home" color="#1479ff" size="16" style="margin-right: 8rpx;"></u-icon>
返回首页
</u-button>
</view>
</view>
<!-- 立即支付 Tab -->
<view v-if="activeTab === 'pay'" class="tab-panel">
<view class="amount">
<text class="symbol">¥</text>
<text class="number">{{orderInfo.price}}</text>
</view>
<view class="pay-button-section">
<u-button
type="primary"
shape="circle"
@click="scrollToPayQr"
class="pay-btn-large"
:custom-style="{
width: '100%',
height: '88rpx',
fontSize: '32rpx',
fontWeight: '500'
}"
>
立即支付
</u-button>
</view>
</view>
</view> </view>
</view> </view>
</view> </view>
<!-- 底部立即支付按钮 -->
<view v-if="orderInfo.pay_status === 0 && loginRole !== 'operator'" class="bottom-pay-btn">
<u-button
type="primary"
shape="circle"
@click="scrollToPayQr"
class="pay-btn"
>
立即支付
</u-button>
</view>
</view> </view>
</template> </template>
@ -180,6 +230,7 @@
data() { data() {
return { return {
myQrcode: '', myQrcode: '',
qrcodeImagePath: '', //
imgs: [], imgs: [],
orderId: '', orderId: '',
orderInfo: {}, orderInfo: {},
@ -192,6 +243,7 @@
}, },
payTimer: null, // payTimer: null, //
isFromShare: false, isFromShare: false,
activeTab: 'qrcode', // tab: 'qrcode' 'pay'
} }
}, },
onLoad(options) { onLoad(options) {
@ -212,10 +264,7 @@
}, },
onUnload() { onUnload() {
// //
if (this.payTimer) { this.stopPayCheck()
clearInterval(this.payTimer)
this.payTimer = null
}
// //
this.clearShareCache() this.clearShareCache()
@ -303,12 +352,22 @@
}) })
this.imgs = _arr this.imgs = _arr
} }
// pay_status //
if (res.pay_status === 0) { if (res.pay_status !== 0) {
this.stopPayCheck()
this.myQrcode = ''
this.qrcodeImagePath = ''
return
}
// tab
if (res.pay_status === 0 && this.activeTab === 'qrcode') {
await this.getCode(res.no) await this.getCode(res.no)
} }
}, },
async getCode(no) { async getCode(no) {
//
this.stopPayCheck()
try { try {
const res = await this.$u.api.accompanyPay({ const res = await this.$u.api.accompanyPay({
no: no no: no
@ -317,8 +376,12 @@
const result = res.result || res const result = res.result || res
if (result && result.code_url) { if (result && result.code_url) {
this.myQrcode = result.code_url this.myQrcode = result.code_url
// //
this.startPayCheck() this.qrcodeImagePath = ''
// tab
if (this.activeTab === 'qrcode') {
this.startPayCheck()
}
} else { } else {
uni.showToast({ uni.showToast({
icon: 'none', icon: 'none',
@ -332,27 +395,77 @@
}) })
} }
}, },
//
onQrcodeComplete(e) {
//
if (e && e.success && this.$refs.payQrcode) {
// canvas
setTimeout(() => {
if (this.$refs.payQrcode) {
this.$refs.payQrcode.toTempFilePath({
success: (res) => {
//
this.qrcodeImagePath = res.tempFilePath
console.log('二维码图片生成成功:', this.qrcodeImagePath)
},
fail: (err) => {
console.error('二维码转图片失败:', err)
// canvas
uni.showToast({
icon: 'none',
title: '二维码图片生成失败'
})
}
})
}
}, 500) // 500ms canvas
}
},
//
stopPayCheck() {
if (this.payTimer) {
clearInterval(this.payTimer)
this.payTimer = null
}
},
// //
startPayCheck() { startPayCheck() {
//
this.stopPayCheck()
// tab
if (this.orderInfo.pay_status !== 0 || this.activeTab !== 'qrcode') {
return
}
this.payTimer = setInterval(async () => { this.payTimer = setInterval(async () => {
// tab
if (this.activeTab !== 'qrcode' || this.orderInfo.pay_status !== 0) {
this.stopPayCheck()
return
}
try { try {
let res const res = await this.$u.api.accompanyOrderDetail({
res = await this.$u.api.accompanyOrderDetail({
id: this.orderId id: this.orderId
}) })
//
if (res.pay_status !== this.orderInfo.pay_status) {
this.orderInfo = res
}
if (res.pay_status === 1) { if (res.pay_status === 1) {
clearInterval(this.payTimer) //
this.payTimer = null this.stopPayCheck()
// //
this.myQrcode = '' this.myQrcode = ''
this.qrcodeImagePath = ''
//
await this.getOrderDetailStaff(this.orderId) await this.getOrderDetailStaff(this.orderId)
uni.showToast({ uni.showToast({
title: '支付成功', title: '支付成功',
icon: 'success' icon: 'success'
@ -360,20 +473,18 @@
} }
} catch (err) { } catch (err) {
console.error('检查支付状态失败', err) console.error('检查支付状态失败', err)
//
} }
}, 3000) // 3 }, 3000) // 3
}, },
isPayCode() { isPayCode() {
// //
if (this.payTimer) { this.stopPayCheck()
clearInterval(this.payTimer)
this.payTimer = null
}
this.myQrcode = '' this.myQrcode = ''
this.qrcodeImagePath = ''
// //
this.getOrderDetailStaff(this.orderId) this.getOrderDetailStaff(this.orderId)
}, },
showShareGuide() { showShareGuide() {
// //
@ -445,9 +556,28 @@
console.log('分享缓存数据已清除下次进入将重新进行token校验') console.log('分享缓存数据已清除下次进入将重新进行token校验')
}, },
// Tab
async switchTab(tab) {
const previousTab = this.activeTab
this.activeTab = tab
// tab
if (tab !== 'qrcode') {
this.stopPayCheck()
}
// tab no
await this.getOrderDetailStaff(this.orderId)
// getOrderDetailStaff activeTab pay_status getCode
// qrcode tab
},
scrollToPayQr: async function() { scrollToPayQr: async function() {
// no
await this.getOrderDetailStaff(this.orderId)
try { try {
// 1. id // 1. 使 no
const res = await this.$u.api.accompanyOrderPayParams({ no: this.orderInfo.no }); const res = await this.$u.api.accompanyOrderPayParams({ no: this.orderInfo.no });
console.log("获取支付参数:",res) console.log("获取支付参数:",res)
@ -565,6 +695,53 @@
box-shadow: 0 4rpx 16rpx #e6eaf1; box-shadow: 0 4rpx 16rpx #e6eaf1;
padding: 30rpx; padding: 30rpx;
z-index: 1; z-index: 1;
.payment-tabs {
display: flex;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 30rpx;
.tab-item {
flex: 1;
text-align: center;
padding: 20rpx 0;
font-size: 30rpx;
color: #666;
position: relative;
transition: all 0.3s;
&.tab-active {
color: #1479ff;
font-weight: 500;
&::after {
content: '';
position: absolute;
bottom: -2rpx;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background: #1479ff;
border-radius: 2rpx;
}
}
}
}
.tab-content {
.tab-panel {
min-height: 400rpx;
}
.pay-button-section {
padding: 60rpx 0;
display: flex;
justify-content: center;
align-items: center;
}
}
.title { .title {
font-size: 32rpx; font-size: 32rpx;
color: #333; color: #333;

@ -215,28 +215,89 @@
</view> </view>
</view> </view>
<!-- 支付二维码 --> <!-- 支付区域 -->
<view class="qrcode-section" v-if="showPayQrCode"> <view class="qrcode-section" v-if="showPayQrCode">
<view class="qrcode-title">微信支付</view> <!-- Tab 切换 -->
<view class="qrcode-wrapper"> <view class="payment-tabs">
<uqrcode v-if="payQrCode" ref="payQrCode" canvas-id="pay-qrcode" :value="payQrCode" :size="400" <view
:sizeUnit="'rpx'" :start="true" :auto="true" :loading="false" @error="onQrCodeError" class="tab-item"
@success="onQrCodeSuccess" :options="{ :class="{ 'tab-active': activeTab === 'qrcode' }"
margin: 10, @click="switchTab('qrcode')"
colorDark: '#000000', >
colorLight: '#ffffff' 付款二维码
}"></uqrcode> </view>
<view
class="tab-item"
:class="{ 'tab-active': activeTab === 'pay' }"
@click="switchTab('pay')"
>
立即支付
</view>
</view>
<!-- Tab 内容 -->
<view class="tab-content">
<!-- 付款二维码 Tab -->
<view v-if="activeTab === 'qrcode'" class="tab-panel">
<view class="qrcode-wrapper">
<!-- 显示图片可长按识别 -->
<image
v-if="qrcodeImagePath"
:src="qrcodeImagePath"
mode="aspectFit"
show-menu-by-longpress
style="width: 400rpx; height: 400rpx; display: block; margin: 0 auto;"
></image>
<!-- Canvas 绘制使用 hide 属性隐藏但保持可渲染 -->
<uqrcode
v-else-if="payQrCode"
ref="payQrCode"
canvas-id="pay-qrcode"
:value="payQrCode"
:size="400"
:sizeUnit="'rpx'"
:start="true"
:auto="true"
:loading="false"
:hide="true"
@error="onQrCodeError"
@complete="onQrCodeComplete"
:options="{
margin: 10,
colorDark: '#000000',
colorLight: '#ffffff'
}"
></uqrcode>
<view v-else style="text-align: center; color: #999; padding: 40rpx;">
正在生成二维码...
</view>
</view>
<view class="qrcode-tip">请使用微信扫码支付</view>
</view>
<!-- 立即支付 Tab -->
<view v-if="activeTab === 'pay'" class="tab-panel">
<view class="pay-button-section">
<u-button
type="primary"
shape="circle"
@click="scrollToPayQr"
class="pay-btn-large"
:custom-style="{
width: '100%',
height: '88rpx',
fontSize: '32rpx',
fontWeight: '500'
}"
>
立即支付
</u-button>
</view>
</view>
</view> </view>
<view class="qrcode-tip">请使用微信扫码支付</view>
</view> </view>
</view> </view>
<!-- 底部立即支付按钮 -->
<view v-if="showPayQrCode" class="bottom-pay-btn">
<u-button type="primary" shape="circle" @click="scrollToPayQr" class="pay-btn">
立即支付
</u-button>
</view>
<!-- 服务完成 --> <!-- 服务完成 -->
<view v-if="form.pay_status === 2"> <view v-if="form.pay_status === 2">
@ -697,10 +758,12 @@
// pay popup // pay popup
isShowPayPopup: false, isShowPayPopup: false,
payQrCode: '', // payQrCode: '', //
qrcodeImagePath: '', //
payTimer: null, // payTimer: null, //
showPriceEdit: false, showPriceEdit: false,
editPrice: '', editPrice: '',
showPayQrCode: false showPayQrCode: false,
activeTab: 'qrcode', // tab: 'qrcode' 'pay'
}; };
}, },
onReady() { onReady() {
@ -730,6 +793,8 @@
// //
this.showPayQrCode = false; this.showPayQrCode = false;
this.payQrCode = ''; this.payQrCode = '';
this.qrcodeImagePath = '';
this.activeTab = 'qrcode'; // tab
}, },
onUnload() { onUnload() {
// //
@ -1001,6 +1066,8 @@
// //
this.payQrCode = result.code_url this.payQrCode = result.code_url
//
this.qrcodeImagePath = ''
this.showPayQrCode = true this.showPayQrCode = true
console.log('二维码URL:', this.payQrCode); console.log('二维码URL:', this.payQrCode);
@ -1063,9 +1130,12 @@
}) })
if (res.pay_status === 1) { if (res.pay_status === 1) {
clearInterval(this.payTimer) clearInterval(this.payTimer)
this.payTimer = null
// //
this.showPayQrCode = false this.showPayQrCode = false
this.payQrCode = ''
this.qrcodeImagePath = ''
this.form.pay_status = 2 this.form.pay_status = 2
uni.showToast({ uni.showToast({
@ -1164,13 +1234,35 @@
this.isShowArchive = true; this.isShowArchive = true;
}, },
// //
onQrCodeSuccess() { onQrCodeSuccess() {
console.log('二维码生成成功'); console.log('二维码生成成功');
uni.showToast({ },
title: '二维码生成成功', // canvas
icon: 'success' onQrCodeComplete(e) {
}); //
if (e && e.success && this.$refs.payQrCode) {
// canvas
setTimeout(() => {
if (this.$refs.payQrCode) {
this.$refs.payQrCode.toTempFilePath({
success: (res) => {
//
this.qrcodeImagePath = res.tempFilePath
console.log('二维码图片生成成功:', this.qrcodeImagePath)
},
fail: (err) => {
console.error('二维码转图片失败:', err)
// canvas
uni.showToast({
icon: 'none',
title: '二维码图片生成失败'
})
}
})
}
}, 500) // 500ms canvas
}
}, },
// //
@ -1189,10 +1281,81 @@
this.showPriceEdit = true; this.showPriceEdit = true;
}, },
// Tab
async switchTab(tab) {
// tab
if (this.activeTab === tab) {
return
}
// tab
this.activeTab = tab
// tab
if (tab === 'qrcode') {
// URL
if (this.qrcodeImagePath || this.payQrCode) {
// 使 setTimeout UI
if (this.orderId) {
setTimeout(() => {
this.getDetail(this.orderId).catch(err => {
console.error('获取订单详情失败:', err)
})
}, 100)
}
return
}
//
if (this.orderId) {
// 使 $nextTick DOM
this.$nextTick(async () => {
//
await this.getDetail(this.orderId)
//
if (this.form.pay_status === 0 && this.form.no) {
try {
const payRes = await this.$u.api.accompanyPay({
no: this.form.no
})
const result = payRes.result || payRes
if (result && result.code_url) {
this.payQrCode = result.code_url
//
this.qrcodeImagePath = ''
}
} catch (error) {
console.error('获取二维码失败:', error)
uni.showToast({
icon: 'none',
title: '获取二维码失败'
})
}
}
})
}
}
// tab
// form.no
},
// //
scrollToPayQr: async function() { scrollToPayQr: async function() {
// no
if (this.orderId) {
await this.getDetail(this.orderId)
}
if (!this.form.no) {
uni.showToast({
title: '订单号不存在',
icon: 'none'
})
return
}
try { try {
// 1. // 1. 使 no
const res = await this.$u.api.accompanyOrderPayParams({ const res = await this.$u.api.accompanyOrderPayParams({
no: this.form.no no: this.form.no
}); });
@ -1840,6 +2003,55 @@
margin-top: 30rpx; margin-top: 30rpx;
text-align: center; text-align: center;
padding: 20rpx; padding: 20rpx;
background: #fff;
border-radius: 20rpx;
box-shadow: 0 4rpx 16rpx #e6eaf1;
.payment-tabs {
display: flex;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 30rpx;
.tab-item {
flex: 1;
text-align: center;
padding: 20rpx 0;
font-size: 30rpx;
color: #666;
position: relative;
transition: all 0.3s;
&.tab-active {
color: #1479ff;
font-weight: 500;
&::after {
content: '';
position: absolute;
bottom: -2rpx;
left: 50%;
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background: #1479ff;
border-radius: 2rpx;
}
}
}
}
.tab-content {
.tab-panel {
min-height: 400rpx;
}
.pay-button-section {
padding: 60rpx 0;
display: flex;
justify-content: center;
align-items: center;
}
}
.qrcode-title { .qrcode-title {
font-size: 28rpx; font-size: 28rpx;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -74,6 +74,45 @@
padding: 30rpx; padding: 30rpx;
z-index: 1; z-index: 1;
} }
.detail-page .payment-popup .payment-tabs.data-v-75de4fcc {
display: flex;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 30rpx;
}
.detail-page .payment-popup .payment-tabs .tab-item.data-v-75de4fcc {
flex: 1;
text-align: center;
padding: 20rpx 0;
font-size: 30rpx;
color: #666;
position: relative;
transition: all 0.3s;
}
.detail-page .payment-popup .payment-tabs .tab-item.tab-active.data-v-75de4fcc {
color: #1479ff;
font-weight: 500;
}
.detail-page .payment-popup .payment-tabs .tab-item.tab-active.data-v-75de4fcc::after {
content: "";
position: absolute;
bottom: -2rpx;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background: #1479ff;
border-radius: 2rpx;
}
.detail-page .payment-popup .tab-content .tab-panel.data-v-75de4fcc {
min-height: 400rpx;
}
.detail-page .payment-popup .tab-content .pay-button-section.data-v-75de4fcc {
padding: 60rpx 0;
display: flex;
justify-content: center;
align-items: center;
}
.detail-page .payment-popup .title.data-v-75de4fcc { .detail-page .payment-popup .title.data-v-75de4fcc {
font-size: 32rpx; font-size: 32rpx;
color: #333; color: #333;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -451,6 +451,48 @@
margin-top: 30rpx; margin-top: 30rpx;
text-align: center; text-align: center;
padding: 20rpx; padding: 20rpx;
background: #fff;
border-radius: 20rpx;
box-shadow: 0 4rpx 16rpx #e6eaf1;
}
.qrcode-section .payment-tabs.data-v-6614d6de {
display: flex;
border-bottom: 2rpx solid #e5e5e5;
margin-bottom: 30rpx;
}
.qrcode-section .payment-tabs .tab-item.data-v-6614d6de {
flex: 1;
text-align: center;
padding: 20rpx 0;
font-size: 30rpx;
color: #666;
position: relative;
transition: all 0.3s;
}
.qrcode-section .payment-tabs .tab-item.tab-active.data-v-6614d6de {
color: #1479ff;
font-weight: 500;
}
.qrcode-section .payment-tabs .tab-item.tab-active.data-v-6614d6de::after {
content: "";
position: absolute;
bottom: -2rpx;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
width: 60rpx;
height: 4rpx;
background: #1479ff;
border-radius: 2rpx;
}
.qrcode-section .tab-content .tab-panel.data-v-6614d6de {
min-height: 400rpx;
}
.qrcode-section .tab-content .pay-button-section.data-v-6614d6de {
padding: 60rpx 0;
display: flex;
justify-content: center;
align-items: center;
} }
.qrcode-section .qrcode-title.data-v-6614d6de { .qrcode-section .qrcode-title.data-v-6614d6de {
font-size: 28rpx; font-size: 28rpx;

Loading…
Cancel
Save