master
lion 4 months ago
parent e60c9bcc4d
commit 81b078d9cd

@ -90,84 +90,134 @@
</view>
</view>
<!-- 支付二维码 -->
<!-- 支付区域 -->
<view class="payment-popup" v-if="orderInfo.pay_status === 0" id="pay-qrcode-section">
<view class="title">付款二维码</view>
<view class="amount">
<text class="symbol">¥</text>
<text class="number">{{orderInfo.price}}</text>
</view>
<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>
<!-- Tab 切换 -->
<view class="payment-tabs">
<view
class="tab-item"
:class="{ 'tab-active': activeTab === 'qrcode' }"
@click="switchTab('qrcode')"
>
付款二维码
</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 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>
<!-- Tab 内容 -->
<view class="tab-content">
<!-- 付款二维码 Tab -->
<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 v-if="myQrcode" style="border: 1px solid #ccc; padding: 10rpx;">
<!-- 显示图片可长按识别 -->
<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
ref="payQrcode"
id="pay-qrcode"
canvas-id="pay-qrcode"
:value="myQrcode"
:size="400"
:sizeUnit="'rpx'"
:hide="true"
:options="{
margin: 10,
}"
@complete="onQrcodeComplete"
></uqrcode>
</view>
<view v-else style="text-align: center; color: #999; padding: 40rpx;">
正在生成二维码...
</view>
</view>
<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 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>
</template>
@ -180,6 +230,7 @@
data() {
return {
myQrcode: '',
qrcodeImagePath: '', //
imgs: [],
orderId: '',
orderInfo: {},
@ -192,6 +243,7 @@
},
payTimer: null, //
isFromShare: false,
activeTab: 'qrcode', // tab: 'qrcode' 'pay'
}
},
onLoad(options) {
@ -212,10 +264,7 @@
},
onUnload() {
//
if (this.payTimer) {
clearInterval(this.payTimer)
this.payTimer = null
}
this.stopPayCheck()
//
this.clearShareCache()
@ -303,12 +352,22 @@
})
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)
}
},
async getCode(no) {
//
this.stopPayCheck()
try {
const res = await this.$u.api.accompanyPay({
no: no
@ -317,8 +376,12 @@
const result = res.result || res
if (result && result.code_url) {
this.myQrcode = result.code_url
//
this.startPayCheck()
//
this.qrcodeImagePath = ''
// tab
if (this.activeTab === 'qrcode') {
this.startPayCheck()
}
} else {
uni.showToast({
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() {
//
this.stopPayCheck()
// tab
if (this.orderInfo.pay_status !== 0 || this.activeTab !== 'qrcode') {
return
}
this.payTimer = setInterval(async () => {
// tab
if (this.activeTab !== 'qrcode' || this.orderInfo.pay_status !== 0) {
this.stopPayCheck()
return
}
try {
let res
res = await this.$u.api.accompanyOrderDetail({
const res = await this.$u.api.accompanyOrderDetail({
id: this.orderId
})
//
if (res.pay_status !== this.orderInfo.pay_status) {
this.orderInfo = res
}
if (res.pay_status === 1) {
clearInterval(this.payTimer)
this.payTimer = null
//
this.stopPayCheck()
//
this.myQrcode = ''
this.qrcodeImagePath = ''
//
await this.getOrderDetailStaff(this.orderId)
uni.showToast({
title: '支付成功',
icon: 'success'
@ -360,20 +473,18 @@
}
} catch (err) {
console.error('检查支付状态失败', err)
//
}
}, 3000) // 3
},
isPayCode() {
//
if (this.payTimer) {
clearInterval(this.payTimer)
this.payTimer = null
}
//
this.stopPayCheck()
this.myQrcode = ''
this.qrcodeImagePath = ''
//
this.getOrderDetailStaff(this.orderId)
},
showShareGuide() {
//
@ -445,9 +556,28 @@
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() {
// no
await this.getOrderDetailStaff(this.orderId)
try {
// 1. id
// 1. 使 no
const res = await this.$u.api.accompanyOrderPayParams({ no: this.orderInfo.no });
console.log("获取支付参数:",res)
@ -565,6 +695,53 @@
box-shadow: 0 4rpx 16rpx #e6eaf1;
padding: 30rpx;
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 {
font-size: 32rpx;
color: #333;

@ -215,28 +215,89 @@
</view>
</view>
<!-- 支付二维码 -->
<!-- 支付区域 -->
<view class="qrcode-section" v-if="showPayQrCode">
<view class="qrcode-title">微信支付</view>
<view class="qrcode-wrapper">
<uqrcode v-if="payQrCode" ref="payQrCode" canvas-id="pay-qrcode" :value="payQrCode" :size="400"
:sizeUnit="'rpx'" :start="true" :auto="true" :loading="false" @error="onQrCodeError"
@success="onQrCodeSuccess" :options="{
margin: 10,
colorDark: '#000000',
colorLight: '#ffffff'
}"></uqrcode>
<!-- Tab 切换 -->
<view class="payment-tabs">
<view
class="tab-item"
:class="{ 'tab-active': activeTab === 'qrcode' }"
@click="switchTab('qrcode')"
>
付款二维码
</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 class="qrcode-tip">请使用微信扫码支付</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">
@ -697,10 +758,12 @@
// pay popup
isShowPayPopup: false,
payQrCode: '', //
qrcodeImagePath: '', //
payTimer: null, //
showPriceEdit: false,
editPrice: '',
showPayQrCode: false
showPayQrCode: false,
activeTab: 'qrcode', // tab: 'qrcode' 'pay'
};
},
onReady() {
@ -730,6 +793,8 @@
//
this.showPayQrCode = false;
this.payQrCode = '';
this.qrcodeImagePath = '';
this.activeTab = 'qrcode'; // tab
},
onUnload() {
//
@ -744,7 +809,7 @@
const res = await this.$u.api.accompanyProduct({
type: type,
page: 1,
page_size: 999,
page_size: 999,
site_id:site_id
});
this.list_service = res.data;
@ -882,29 +947,29 @@
}
},
//
openMap(){
console.log("chooseLocation")
let that = this
uni.chooseLocation({
success(res){
console.log("chooseLocationres",res)
if (res.errMsg === 'chooseLocation:ok') {
that.form.city = res.address
console.log('位置名称:' + res.name);
console.log('详细地址:' + res.address);
console.log('纬度:' + res.latitude);
console.log('经度:' + res.longitude);
}
},
fail(err){
uni.showToast({
title:'打开地图失败',
icon:'none'
})
console.log("err",err)
}
});
//
openMap(){
console.log("chooseLocation")
let that = this
uni.chooseLocation({
success(res){
console.log("chooseLocationres",res)
if (res.errMsg === 'chooseLocation:ok') {
that.form.city = res.address
console.log('位置名称:' + res.name);
console.log('详细地址:' + res.address);
console.log('纬度:' + res.latitude);
console.log('经度:' + res.longitude);
}
},
fail(err){
uni.showToast({
title:'打开地图失败',
icon:'none'
})
console.log("err",err)
}
});
},
pay() {
if (!this.orderId) {
@ -1001,6 +1066,8 @@
//
this.payQrCode = result.code_url
//
this.qrcodeImagePath = ''
this.showPayQrCode = true
console.log('二维码URL:', this.payQrCode);
@ -1063,9 +1130,12 @@
})
if (res.pay_status === 1) {
clearInterval(this.payTimer)
this.payTimer = null
//
this.showPayQrCode = false
this.payQrCode = ''
this.qrcodeImagePath = ''
this.form.pay_status = 2
uni.showToast({
@ -1164,13 +1234,35 @@
this.isShowArchive = true;
},
//
//
onQrCodeSuccess() {
console.log('二维码生成成功');
uni.showToast({
title: '二维码生成成功',
icon: 'success'
});
},
// canvas
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;
},
// 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() {
// no
if (this.orderId) {
await this.getDetail(this.orderId)
}
if (!this.form.no) {
uni.showToast({
title: '订单号不存在',
icon: 'none'
})
return
}
try {
// 1.
// 1. 使 no
const res = await this.$u.api.accompanyOrderPayParams({
no: this.form.no
});
@ -1840,6 +2003,55 @@
margin-top: 30rpx;
text-align: center;
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 {
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;
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 {
font-size: 32rpx;
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;
text-align: center;
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 {
font-size: 28rpx;

Loading…
Cancel
Save