556 lines
16 KiB
Vue
556 lines
16 KiB
Vue
<template>
|
||
<view class="container">
|
||
<!-- 订单信息 -->
|
||
<view class="info-card">
|
||
<view class="info-item">
|
||
<text class="label">订单编号</text>
|
||
<text class="value">{{ orderInfo.orderSn }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">创建时间</text>
|
||
<text class="value">{{ orderInfo.createTime }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">客户姓名</text>
|
||
<text class="value">{{ orderInfo.memberName }}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">客户手机</text>
|
||
<text class="value">{{ orderInfo.memberPhone }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 商品信息 -->
|
||
<view class="info-card">
|
||
<view class="card-title">商品信息</view>
|
||
<view class="">
|
||
<view v-for="(item, index) in orderInfo.orderItems" :key="index" class="product-item">
|
||
<image :src="item.productPic" mode="aspectFill" class="product-image" @click="lookPic(item.productPic)">
|
||
</image>
|
||
<view class="product-info">
|
||
<text class="product-name">{{ item.productName }}</text>
|
||
<view class="product-bottom">
|
||
<text class="product-quantity">x{{ item.productQuantity }}</text>
|
||
<text class="product-price">¥{{ (item.productPrice / 100).toFixed(2) }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
|
||
<!-- 订单金额信息 -->
|
||
<view class="amount-info">
|
||
<view class="amount-item">
|
||
<text>总金额</text>
|
||
<text class="price">¥{{ (orderInfo.totalAmount / 100).toFixed(2) }}</text>
|
||
</view>
|
||
<view class="amount-item">
|
||
<text>已付额</text>
|
||
<text class="price paid">¥{{ orderInfo.payAmount ? (orderInfo.payAmount / 100).toFixed(2) : '0.00' }}</text>
|
||
</view>
|
||
<view class="amount-item">
|
||
<text>支付方式</text>
|
||
<view class="payment-method">
|
||
<!-- <u-icon name="weixin-fill" color="#07c160" size="28"></u-icon> -->
|
||
<text>{{getDictName('mall_pay_type',orderInfo.payType,'dictLabel')}}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 订单其他信息 -->
|
||
<view class="info-card">
|
||
<view class="info-item">
|
||
<text class="label">订单来源</text>
|
||
<view class="value source">
|
||
<u-icon name="shopping-mall" size="24"></u-icon>
|
||
<text>{{getDictName('mall_source_type',orderInfo.sourceType,'dictLabel')}}</text>
|
||
</view>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">订单状态</text>
|
||
<text class="value status"
|
||
:class="['dict-item',getDictName('mall_order_status',orderInfo.orderStatus,'listClass')]">{{getDictName('mall_order_status',orderInfo.orderStatus,'dictLabel')}}</text>
|
||
</view>
|
||
<view class="info-item">
|
||
<text class="label">订单备注</text>
|
||
<text class="value">{{ orderInfo.orderNote || '无' }}</text>
|
||
</view>
|
||
</view>
|
||
<!-- 底部购买按钮 -->
|
||
<view class="btn-box">
|
||
<u-button type="primary" style="width: 680rpx;" :loading="buttonLoading" @click="handlePay">去支付</u-button>
|
||
</view>
|
||
<u-toast ref="uToast" />
|
||
</view>
|
||
</template>
|
||
|
||
<script>
|
||
// import jweixin from '../../utils/jweixin-1.6.0.js';
|
||
var jweixin = require('jweixin-module');
|
||
export default {
|
||
data() {
|
||
return {
|
||
orderId: '',
|
||
orderInfo: {
|
||
"billContent": null,
|
||
"billHeader": null,
|
||
"billReceiverEmail": null,
|
||
"billReceiverPhone": null,
|
||
"billType": 0,
|
||
"confirmStatus": 0,
|
||
"createBy": "",
|
||
"createTime": "",
|
||
"deliveryTime": null,
|
||
"finishTime": null,
|
||
"freightAmount": null,
|
||
"id": "",
|
||
"memberName": "",
|
||
"memberPhone": "",
|
||
"memberUsername": "",
|
||
"orderItems": [],
|
||
"orderNote": null,
|
||
"orderSn": "",
|
||
"orderStatus": 0,
|
||
"orderType": 0,
|
||
"payAmount": null,
|
||
"payTime": null,
|
||
"payType": 0,
|
||
"receiverCity": null,
|
||
"receiverDetailAddress": null,
|
||
"receiverName": null,
|
||
"receiverPhone": null,
|
||
"receiverPostCode": null,
|
||
"receiverProvince": null,
|
||
"receiverRegion": null,
|
||
"sourceType": 0,
|
||
"totalAmount": 0,
|
||
"updateBy": "",
|
||
"updateTime": ""
|
||
},
|
||
mall_order_status: [],
|
||
mall_source_type: [],
|
||
mall_pay_type: [],
|
||
buttonLoading: false,
|
||
officialAccount: {
|
||
appid: '',
|
||
appsecret: 'ca307cfb6c94e8ac015e26cfd717a91c',
|
||
},
|
||
code: '',
|
||
openId: '',
|
||
}
|
||
},
|
||
onLoad(option) {
|
||
let appIdPublic = uni.getStorageSync('appIdPublic');
|
||
console.log("this.$store.state.app.appConfig.appIdPublic",this.$store.state.app.appConfig.appIdPublic)
|
||
this.officialAccount.appid = appIdPublic || '';
|
||
this.getDictDataList('mall_order_status');
|
||
this.getDictDataList('mall_source_type');
|
||
this.getDictDataList('mall_pay_type');
|
||
console.log("option", option)
|
||
this.orderId = option.id;
|
||
this.getOrderDetail(option.id);
|
||
let res = uni.getStorageSync('openId');
|
||
if (res) {
|
||
this.openId = res;
|
||
} else {
|
||
// #ifdef H5
|
||
let code = this.getUrlCode('code')
|
||
if (code || this.code) {
|
||
this.code = code;
|
||
this.getOpenidAndUserinfo(code)
|
||
// // 清除URL中的code参数
|
||
// const url = window.location.href;
|
||
// const newUrl = url.split('?')[0]; // 去掉参数部分
|
||
// history.replaceState({}, '', newUrl+'');
|
||
} else {
|
||
console.log("当前网址", window.location.href)
|
||
this.getH5Code()
|
||
}
|
||
// #endif
|
||
}
|
||
},
|
||
methods: {
|
||
// 获取订单详情
|
||
getOrderDetail(id) {
|
||
this.$api.orderApi.getOrderDetail(id).then((res) => {
|
||
console.log("获取订单详情", res)
|
||
if (res.code == 200) {
|
||
this.orderInfo = res.data;
|
||
}
|
||
}).catch(() => {})
|
||
},
|
||
getDictDataList(type) {
|
||
this.$api.getDictList(type).then((res) => {
|
||
if (res.code === 200) {
|
||
this[type] = res.data || [];
|
||
}
|
||
})
|
||
},
|
||
getDictName(list, value, key) {
|
||
let name = ''
|
||
if (this[list]) {
|
||
this[list].forEach((item) => {
|
||
if (item.dictValue == value) {
|
||
name = item[key];
|
||
}
|
||
})
|
||
return name;
|
||
}
|
||
},
|
||
lookPic(url) {
|
||
uni.previewImage({
|
||
current: '', // 当前显示图片的 http 链接
|
||
urls: [url] // 需要预览的图片 http 链接列表
|
||
});
|
||
},
|
||
handlePay() {
|
||
// 处理购买逻辑
|
||
// uni.showToast({
|
||
// title: '正在开发中...',
|
||
// icon: 'none'
|
||
// })
|
||
// openid获取支付参数、调用支付
|
||
console.log("支付")
|
||
if(this.openId){
|
||
this.$api.orderApi.addPayOrder({
|
||
orderId: this.orderInfo.id,
|
||
//拉卡拉这个参数无用,后面换类型在添加其他参数如:openid
|
||
channelExtra: JSON.stringify({'openid': this.openId}),
|
||
wayCode: 'LKL_WX_JSAPI'
|
||
}).then((res) => {
|
||
console.log("获取支付详情", res)
|
||
if (res.code == 200) {
|
||
// this.orderInfo = res.data;
|
||
}
|
||
}).catch(() => {})
|
||
// this.wxpay({
|
||
// "appId": this.officialAccount.appid, //公众号
|
||
// "timeStamp": 'a1sd12as1d23sa1d231as2d1asd', //时间戳
|
||
// "nonceStr": 'a1sd12as1d23sa1d231as2d1asd', //随机串
|
||
// "package": 'a1sd12as1d23sa1d231as2d1asd', //prepay_id
|
||
// "signType": 'a1sd12as1d23sa1d231as2d1asd', //微信签名方式RSA
|
||
// "paySign": 'a1sd12as1d23sa1d231as2d1asd', //微信签名
|
||
// "signature": 'a1sd12as1d23sa1d231as2d1asd' //微信签名
|
||
// })
|
||
}else{
|
||
this.clearUrlCode()
|
||
this.getH5Code()
|
||
this.$refs.uToast.show({
|
||
title: '获取支付信息失败,请重试',
|
||
type: 'error',
|
||
})
|
||
}
|
||
|
||
},
|
||
clearUrlCode(){
|
||
// 清除URL中的code参数
|
||
const url = window.location.href;
|
||
const newUrl = url.split('?')[0]; // 去掉参数部分
|
||
history.replaceState({}, '', newUrl+'/pages/order/detail?id='+this.orderId);
|
||
},
|
||
getH5Code() {
|
||
if (this.isWechat()) {
|
||
// 截取地址中的code,如果没有code就去微信授权,如果已经获取到code了就直接把code传给后台获取openId
|
||
window.location.href = 'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + this.officialAccount
|
||
.appid + '&redirect_uri=' + encodeURIComponent(window.location.href) +
|
||
'&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect'
|
||
console.log("跳转授权页面",'https://open.weixin.qq.com/connect/oauth2/authorize?appid=' + this.officialAccount
|
||
.appid + '&redirect_uri=' + encodeURIComponent(window.location.href) +
|
||
'&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect')
|
||
// redirect_uri是授权成功后,跳转的url地址,微信会帮我们跳转到该链接,并且通过?的形式拼接code,这里需要用encodeURIComponent对链接进行处理。
|
||
// 如果配置参数一一对应,那么此时已经通过回调地址刷新页面后,你就会再地址栏中看到code了。
|
||
// http://127.0.0.1/pages/views/profile/login/login?code=001BWV4J1lRzz00H4J1J1vRE4J1BWV4q&state=1
|
||
}
|
||
},
|
||
getUrlCode(name) {
|
||
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.href) || [,
|
||
''])[1].replace(/\+/g, '%20')) || null
|
||
},
|
||
isWechat() {
|
||
return String(navigator.userAgent.toLowerCase().match(/MicroMessenger/i)) === "micromessenger";
|
||
},
|
||
getOpenidAndUserinfo(code) {
|
||
console.log("code换openid")
|
||
this.$api.orderApi.getWxOpenid({
|
||
code: code
|
||
}).then((res) => {
|
||
console.log("获取openid", res)
|
||
if (res.code == 200) {
|
||
if(res.data.openid){
|
||
this.openId = res.data.openid;
|
||
uni.setStorageSync('openId', res.data.openid)
|
||
this.clearUrlCode();
|
||
}else{
|
||
this.clearUrlCode();
|
||
this.getUrlCode();
|
||
}
|
||
// 1、调用后端获取支付参数
|
||
// 2、调起支付
|
||
}else{
|
||
|
||
}
|
||
}).catch(() => {
|
||
|
||
})
|
||
// uni.request({
|
||
// url: 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='+this.officialAccount.appid+'&secret='+this.officialAccount.secret +'&grant_type=authorization_code&code='+code,
|
||
// success: (res) => {
|
||
// console.log('通过code获取openid和accessToken', res)
|
||
// // if(res.data.code === 200) {
|
||
// // // 登录成功,可以将用户信息和token保存到缓存中
|
||
// // uni.setStorageSync('userInfo', res.data.result.userInfo)
|
||
// // uni.setStorageSync('token', res.data.result.token)
|
||
// // }
|
||
// }
|
||
// })
|
||
},
|
||
wxpay(data) {
|
||
// if (typeof WeixinJSBridge == "undefined") {
|
||
// if (document.addEventListener) {
|
||
// document.addEventListener('WeixinJSBridgeReady', this.onBridgeReady(data), false);
|
||
// } else if (document.attachEvent) {
|
||
// document.attachEvent('WeixinJSBridgeReady', this.onBridgeReady(data));
|
||
// document.attachEvent('onWeixinJSBridgeReady', this.onBridgeReady(data));
|
||
// }
|
||
// } else {
|
||
// this.onBridgeReady(data);
|
||
// }
|
||
jweixin.config({
|
||
debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。(测试记得关掉)
|
||
appId: data.appId, // 公众号的唯一标识
|
||
timestamp: data.timestamp, // 生成签名的时间戳
|
||
nonceStr: data.nonceStr, // 生成签名的随机串
|
||
signature: data.signature, // 签名
|
||
jsApiList: ['chooseWXPay'], // JS接口列表
|
||
})
|
||
this.onBridgeReady(data);
|
||
},
|
||
|
||
onBridgeReady(data) {
|
||
// jweixin.ready(()=>{
|
||
// // config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
|
||
// jweixin.chooseWXPay({
|
||
// timestamp: data.timeStamp,
|
||
// package: data.package,
|
||
// nonceStr: data.nonceStr,
|
||
// signType: data.signType,
|
||
// paySign: data.paySign,
|
||
// success: (res) => {
|
||
// if (res.errMsg == "chooseWXPay:ok") {
|
||
// console.log('支付成功')
|
||
// } else {
|
||
// console.log('支付失败')}
|
||
// },
|
||
// fail: (res) => {
|
||
// console.log('支付失败')
|
||
// }
|
||
// });
|
||
// });
|
||
|
||
jweixin.invoke(
|
||
'getBrandWCPayRequest', {
|
||
// 传入第一步后端接口返回的核心参数
|
||
"appId": data.appId, //公众号
|
||
"timeStamp": data.timeStamp, //时间戳
|
||
"nonceStr": data.nonceStr, //随机串
|
||
"package": data.package, //prepay_id
|
||
"signType": data.signType, //微信签名方式RSA
|
||
"paySign": data.paySign //微信签名
|
||
},
|
||
(res)=>{
|
||
// 支付成功
|
||
if (res.err_msg == "get_brand_wcpay_request:ok") {
|
||
// 使用以上方式判断前端返回,微信团队郑重提示:
|
||
//res.err_msg将在用户支付成功后返回ok,但并不保证它绝对可靠。
|
||
this.$refs.uToast.show({
|
||
title: '支付成功',
|
||
type: 'success',
|
||
})
|
||
}
|
||
// 支付过程中用户取消
|
||
if (res.err_msg == "get_brand_wcpay_request:cancel") {
|
||
this.$refs.uToast.show({
|
||
title: '用户取消',
|
||
type: 'error',
|
||
})
|
||
}
|
||
// 支付失败
|
||
if (res.err_msg == "get_brand_wcpay_request:fail") {
|
||
this.$refs.uToast.show({
|
||
title: '支付失败',
|
||
type: 'error',
|
||
})
|
||
}
|
||
/**
|
||
* 其它
|
||
* 1、请检查预支付会话标识prepay_id是否已失效
|
||
* 2、请求的appid与下单接口的appid是否一致
|
||
* */
|
||
if (res.err_msg == "调用支付JSAPI缺少参数:total_fee") {
|
||
this.$refs.uToast.show({
|
||
title: '缺少参数',
|
||
type: 'error',
|
||
})
|
||
}
|
||
});
|
||
}
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="scss" scoped>
|
||
.container {
|
||
min-height: 100vh;
|
||
background-color: #f5f5f5;
|
||
padding: 20rpx;
|
||
padding-bottom: 120rpx;
|
||
}
|
||
|
||
.info-card {
|
||
background-color: #fff;
|
||
border-radius: 12rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.info-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
|
||
.label {
|
||
color: #666;
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.value {
|
||
color: #333;
|
||
font-size: 28rpx;
|
||
}
|
||
}
|
||
|
||
.card-title {
|
||
font-size: 30rpx;
|
||
font-weight: 500;
|
||
margin-bottom: 20rpx;
|
||
}
|
||
|
||
.product-item {
|
||
display: flex;
|
||
padding: 20rpx 0;
|
||
border-bottom: 1rpx solid #eee;
|
||
|
||
&:last-child {
|
||
border-bottom: none;
|
||
}
|
||
}
|
||
|
||
|
||
.product-image {
|
||
width: 160rpx;
|
||
height: 160rpx;
|
||
border-radius: 8rpx;
|
||
margin-right: 20rpx;
|
||
}
|
||
|
||
.product-info {
|
||
flex: 1;
|
||
display: flex;
|
||
flex-direction: column;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.product-name {
|
||
font-size: 28rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.product-bottom {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.product-quantity {
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
}
|
||
|
||
.product-price {
|
||
font-size: 32rpx;
|
||
color: #333;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.amount-info {
|
||
margin-top: 30rpx;
|
||
padding-top: 30rpx;
|
||
border-top: 1rpx solid #eee;
|
||
}
|
||
|
||
.amount-item {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
margin-bottom: 20rpx;
|
||
font-size: 28rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.price {
|
||
font-weight: 500;
|
||
|
||
&.paid {
|
||
color: #19be6b;
|
||
}
|
||
}
|
||
}
|
||
|
||
.payment-method {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
color: #333;
|
||
}
|
||
|
||
.source {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 10rpx;
|
||
}
|
||
|
||
.status {
|
||
color: #19be6b;
|
||
}
|
||
|
||
.btn-box {
|
||
display: flex;
|
||
justify-content: space-around;
|
||
align-items: center;
|
||
height: 120rpx;
|
||
position: fixed;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background: #fff;
|
||
z-index: 999;
|
||
|
||
button {
|
||
width: 680rpx;
|
||
height: 85rpx;
|
||
border-radius: 10rpx;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
}
|
||
</style> |