gy-app-shop/pages/order/detail.vue

556 lines
16 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="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>