572 lines
16 KiB
JavaScript
572 lines
16 KiB
JavaScript
import Toast from 'tdesign-miniprogram/toast/index';
|
||
import { fetchSettleDetail } from '../../../services/order/orderConfirm';
|
||
import { commitPay, wechatPayOrder } from './pay';
|
||
import { getAddressPromise } from '../../usercenter/address/list/util';
|
||
|
||
const stripeImg = `https://cdn-we-retail.ym.tencent.com/miniapp/order/stripe.png`;
|
||
|
||
Page({
|
||
data: {
|
||
placeholder: '备注信息',
|
||
stripeImg,
|
||
loading: false,
|
||
settleDetailData: {
|
||
storeGoodsList: [], //正常下单商品列表
|
||
outOfStockGoodsList: [], //库存不足商品
|
||
abnormalDeliveryGoodsList: [], // 不能正常配送商品
|
||
inValidGoodsList: [], // 失效或者库存不足
|
||
limitGoodsList: [], //限购商品
|
||
couponList: [], //门店优惠券信息
|
||
}, // 获取结算页详情 data
|
||
orderCardList: [], // 仅用于商品卡片展示
|
||
couponsShow: false, // 显示优惠券的弹框
|
||
invoiceData: {
|
||
email: '', // 发票发送邮箱
|
||
buyerTaxNo: '', // 税号
|
||
invoiceType: null, // 开票类型 1:增值税专用发票; 2:增值税普通发票; 3:增值税电子发票;4:增值税卷式发票;5:区块链电子发票。
|
||
buyerPhone: '', //手机号
|
||
buyerName: '', //个人或公司名称
|
||
titleType: '', // 发票抬头 1-公司 2-个人
|
||
contentType: '', //发票内容 1-明细 2-类别
|
||
},
|
||
goodsRequestList: [],
|
||
userAddressReq: null,
|
||
popupShow: false, // 不在配送范围 失效 库存不足 商品展示弹框
|
||
notesPosition: 'center',
|
||
storeInfoList: [],
|
||
storeNoteIndex: 0, //当前填写备注门店index
|
||
promotionGoodsList: [], //当前门店商品列表(优惠券)
|
||
couponList: [], //当前门店所选优惠券
|
||
submitCouponList: [], //所有门店所选优惠券
|
||
currentStoreId: null, //当前优惠券storeId
|
||
userAddress: null,
|
||
},
|
||
|
||
payLock: false,
|
||
noteInfo: [],
|
||
tempNoteInfo: [],
|
||
onLoad(options) {
|
||
this.setData({
|
||
loading: true,
|
||
});
|
||
this.handleOptionsParams(options);
|
||
},
|
||
onShow() {
|
||
const invoiceData = wx.getStorageSync('invoiceData');
|
||
if (invoiceData) {
|
||
//处理发票
|
||
this.invoiceData = invoiceData;
|
||
this.setData({
|
||
invoiceData,
|
||
});
|
||
wx.removeStorageSync('invoiceData');
|
||
}
|
||
},
|
||
|
||
init() {
|
||
this.setData({
|
||
loading: true,
|
||
});
|
||
const { goodsRequestList } = this;
|
||
this.handleOptionsParams({ goodsRequestList });
|
||
},
|
||
// 处理不同情况下跳转到结算页时需要的参数
|
||
handleOptionsParams(options, couponList) {
|
||
let { goodsRequestList } = this; // 商品列表
|
||
let { userAddressReq } = this; // 收货地址
|
||
|
||
const storeInfoList = []; // 门店列表
|
||
// 如果是从地址选择页面返回,则使用地址显选择页面新选择的地址去获取结算数据
|
||
if (options.userAddressReq) {
|
||
userAddressReq = options.userAddressReq;
|
||
}
|
||
if (options.type === 'cart') {
|
||
// 从购物车跳转过来时,获取传入的商品列表数据
|
||
const goodsRequestListJson = wx.getStorageSync('order.goodsRequestList');
|
||
goodsRequestList = JSON.parse(goodsRequestListJson);
|
||
} else if (typeof options.goodsRequestList === 'string') {
|
||
goodsRequestList = JSON.parse(options.goodsRequestList);
|
||
}
|
||
//获取结算页请求数据列表
|
||
const storeMap = {};
|
||
goodsRequestList.forEach((goods) => {
|
||
if (!storeMap[goods.storeId]) {
|
||
storeInfoList.push({
|
||
storeId: goods.storeId,
|
||
storeName: goods.storeName,
|
||
});
|
||
storeMap[goods.storeId] = true;
|
||
}
|
||
});
|
||
this.goodsRequestList = goodsRequestList;
|
||
this.storeInfoList = storeInfoList;
|
||
const params = {
|
||
goodsRequestList,
|
||
storeInfoList,
|
||
userAddressReq,
|
||
couponList,
|
||
};
|
||
fetchSettleDetail(params).then(
|
||
(res) => {
|
||
this.setData({
|
||
loading: false,
|
||
});
|
||
this.initData(res.data);
|
||
},
|
||
() => {
|
||
//接口异常处理
|
||
this.handleError();
|
||
},
|
||
);
|
||
},
|
||
initData(resData) {
|
||
// 转换商品卡片显示数据
|
||
const data = this.handleResToGoodsCard(resData);
|
||
this.userAddressReq = resData.userAddress;
|
||
|
||
if (resData.userAddress) {
|
||
this.setData({ userAddress: resData.userAddress });
|
||
}
|
||
this.setData({ settleDetailData: data });
|
||
this.isInvalidOrder(data);
|
||
},
|
||
|
||
isInvalidOrder(data) {
|
||
// 失效 不在配送范围 限购的商品 提示弹窗
|
||
if (
|
||
(data.limitGoodsList && data.limitGoodsList.length > 0) ||
|
||
(data.abnormalDeliveryGoodsList &&
|
||
data.abnormalDeliveryGoodsList.length > 0) ||
|
||
(data.inValidGoodsList && data.inValidGoodsList.length > 0)
|
||
) {
|
||
this.setData({ popupShow: true });
|
||
return true;
|
||
}
|
||
this.setData({ popupShow: false });
|
||
if (data.settleType === 0) {
|
||
return true;
|
||
}
|
||
return false;
|
||
},
|
||
|
||
handleError() {
|
||
Toast({
|
||
context: this,
|
||
selector: '#t-toast',
|
||
message: '结算异常, 请稍后重试',
|
||
duration: 2000,
|
||
icon: '',
|
||
});
|
||
|
||
setTimeout(() => {
|
||
wx.navigateBack();
|
||
}, 1500);
|
||
this.setData({
|
||
loading: false,
|
||
});
|
||
},
|
||
getRequestGoodsList(storeGoodsList) {
|
||
const filterStoreGoodsList = [];
|
||
storeGoodsList &&
|
||
storeGoodsList.forEach((store) => {
|
||
const { storeName } = store;
|
||
store.skuDetailVos &&
|
||
store.skuDetailVos.forEach((goods) => {
|
||
const data = goods;
|
||
data.storeName = storeName;
|
||
filterStoreGoodsList.push(data);
|
||
});
|
||
});
|
||
return filterStoreGoodsList;
|
||
},
|
||
handleGoodsRequest(goods, isOutStock = false) {
|
||
const {
|
||
reminderStock,
|
||
quantity,
|
||
storeId,
|
||
uid,
|
||
saasId,
|
||
spuId,
|
||
goodsName,
|
||
skuId,
|
||
storeName,
|
||
roomId,
|
||
} = goods;
|
||
const resQuantity = isOutStock ? reminderStock : quantity;
|
||
return {
|
||
quantity: resQuantity,
|
||
storeId,
|
||
uid,
|
||
saasId,
|
||
spuId,
|
||
goodsName,
|
||
skuId,
|
||
storeName,
|
||
roomId,
|
||
};
|
||
},
|
||
handleResToGoodsCard(data) {
|
||
// 转换数据 符合 goods-card展示
|
||
const orderCardList = []; // 订单卡片列表
|
||
const storeInfoList = [];
|
||
const submitCouponList = []; //使用优惠券列表;
|
||
|
||
data.storeGoodsList &&
|
||
data.storeGoodsList.forEach((ele) => {
|
||
const orderCard = {
|
||
id: ele.storeId,
|
||
storeName: ele.storeName,
|
||
status: 0,
|
||
statusDesc: '',
|
||
amount: ele.storeTotalPayAmount,
|
||
goodsList: [],
|
||
}; // 订单卡片
|
||
ele.skuDetailVos.forEach((item, index) => {
|
||
orderCard.goodsList.push({
|
||
id: index,
|
||
thumb: item.image,
|
||
title: item.goodsName,
|
||
specs: item.skuSpecLst.map((s) => s.specValue), // 规格列表 string[]
|
||
price: item.tagPrice || item.settlePrice || '0', // 优先取限时活动价
|
||
settlePrice: item.settlePrice,
|
||
titlePrefixTags: item.tagText ? [{ text: item.tagText }] : [],
|
||
num: item.quantity,
|
||
skuId: item.skuId,
|
||
spuId: item.spuId,
|
||
storeId: item.storeId,
|
||
});
|
||
});
|
||
|
||
storeInfoList.push({
|
||
storeId: ele.storeId,
|
||
storeName: ele.storeName,
|
||
remark: '',
|
||
});
|
||
submitCouponList.push({
|
||
storeId: ele.storeId,
|
||
couponList: ele.couponList || [],
|
||
});
|
||
this.noteInfo.push('');
|
||
this.tempNoteInfo.push('');
|
||
orderCardList.push(orderCard);
|
||
});
|
||
|
||
this.setData({ orderCardList, storeInfoList, submitCouponList });
|
||
return data;
|
||
},
|
||
onGotoAddress() {
|
||
/** 获取一个Promise */
|
||
getAddressPromise()
|
||
.then((address) => {
|
||
this.handleOptionsParams({
|
||
userAddressReq: { ...address, checked: true },
|
||
});
|
||
})
|
||
.catch(() => {});
|
||
|
||
const { userAddressReq } = this; // 收货地址
|
||
|
||
let id = '';
|
||
|
||
if (userAddressReq?.id) {
|
||
id = `&id=${userAddressReq.id}`;
|
||
}
|
||
|
||
wx.navigateTo({
|
||
url: `/pages/usercenter/address/list/index?selectMode=1&isOrderSure=1${id}`,
|
||
});
|
||
},
|
||
onNotes(e) {
|
||
const { storenoteindex: storeNoteIndex } = e.currentTarget.dataset;
|
||
// 添加备注信息
|
||
this.setData({
|
||
dialogShow: true,
|
||
storeNoteIndex,
|
||
});
|
||
},
|
||
onInput(e) {
|
||
const { storeNoteIndex } = this.data;
|
||
this.noteInfo[storeNoteIndex] = e.detail.value;
|
||
},
|
||
onBlur() {
|
||
this.setData({
|
||
notesPosition: 'center',
|
||
});
|
||
},
|
||
onFocus() {
|
||
this.setData({
|
||
notesPosition: 'self',
|
||
});
|
||
},
|
||
onTap() {
|
||
this.setData({
|
||
placeholder: '',
|
||
});
|
||
},
|
||
onNoteConfirm() {
|
||
// 备注信息 确认按钮
|
||
const { storeInfoList, storeNoteIndex } = this.data;
|
||
this.tempNoteInfo[storeNoteIndex] = this.noteInfo[storeNoteIndex];
|
||
storeInfoList[storeNoteIndex].remark = this.noteInfo[storeNoteIndex];
|
||
|
||
this.setData({
|
||
dialogShow: false,
|
||
storeInfoList,
|
||
});
|
||
},
|
||
onNoteCancel() {
|
||
// 备注信息 取消按钮
|
||
const { storeNoteIndex } = this.data;
|
||
this.noteInfo[storeNoteIndex] = this.tempNoteInfo[storeNoteIndex];
|
||
this.setData({
|
||
dialogShow: false,
|
||
});
|
||
},
|
||
|
||
onSureCommit() {
|
||
// 商品库存不足继续结算
|
||
const { settleDetailData } = this.data;
|
||
const { outOfStockGoodsList, storeGoodsList, inValidGoodsList } =
|
||
settleDetailData;
|
||
if (
|
||
(outOfStockGoodsList && outOfStockGoodsList.length > 0) ||
|
||
(inValidGoodsList && storeGoodsList)
|
||
) {
|
||
// 合并正常商品 和 库存 不足商品继续支付
|
||
// 过滤不必要的参数
|
||
const filterOutGoodsList = [];
|
||
outOfStockGoodsList &&
|
||
outOfStockGoodsList.forEach((outOfStockGoods) => {
|
||
const { storeName } = outOfStockGoods;
|
||
outOfStockGoods.unSettlementGoods.forEach((ele) => {
|
||
const data = ele;
|
||
data.quantity = ele.reminderStock;
|
||
data.storeName = storeName;
|
||
filterOutGoodsList.push(data);
|
||
});
|
||
});
|
||
const filterStoreGoodsList = this.getRequestGoodsList(storeGoodsList);
|
||
const goodsRequestList = filterOutGoodsList.concat(filterStoreGoodsList);
|
||
this.handleOptionsParams({ goodsRequestList });
|
||
}
|
||
},
|
||
// 提交订单
|
||
submitOrder() {
|
||
const {
|
||
settleDetailData,
|
||
userAddressReq,
|
||
invoiceData,
|
||
storeInfoList,
|
||
submitCouponList,
|
||
} = this.data;
|
||
const { goodsRequestList } = this;
|
||
|
||
if (!userAddressReq && !settleDetailData.userAddress) {
|
||
Toast({
|
||
context: this,
|
||
selector: '#t-toast',
|
||
message: '请添加收货地址',
|
||
duration: 2000,
|
||
icon: 'help-circle',
|
||
});
|
||
|
||
return;
|
||
}
|
||
if (
|
||
this.payLock ||
|
||
!settleDetailData.settleType ||
|
||
!settleDetailData.totalAmount
|
||
) {
|
||
return;
|
||
}
|
||
this.payLock = true;
|
||
const resSubmitCouponList = this.handleCouponList(submitCouponList);
|
||
const params = {
|
||
userAddressReq: settleDetailData.userAddress || userAddressReq,
|
||
goodsRequestList: goodsRequestList,
|
||
userName: settleDetailData.userAddress.name || userAddressReq.name,
|
||
totalAmount: settleDetailData.totalPayAmount, //取优惠后的结算金额
|
||
invoiceRequest: null,
|
||
storeInfoList,
|
||
couponList: resSubmitCouponList,
|
||
};
|
||
if (invoiceData && invoiceData.email) {
|
||
params.invoiceRequest = invoiceData;
|
||
}
|
||
commitPay(params).then(
|
||
(res) => {
|
||
this.payLock = false;
|
||
const { data } = res;
|
||
// 提交出现 失效 不在配送范围 限购的商品 提示弹窗
|
||
if (this.isInvalidOrder(data)) {
|
||
return;
|
||
}
|
||
if (res.code === 'Success') {
|
||
this.handlePay(data, settleDetailData);
|
||
} else {
|
||
Toast({
|
||
context: this,
|
||
selector: '#t-toast',
|
||
message: res.msg || '提交订单超时,请稍后重试',
|
||
duration: 2000,
|
||
icon: '',
|
||
});
|
||
setTimeout(() => {
|
||
// 提交支付失败 返回购物车
|
||
wx.navigateBack();
|
||
}, 2000);
|
||
}
|
||
},
|
||
(err) => {
|
||
this.payLock = false;
|
||
if (
|
||
err.code === 'CONTAINS_INSUFFICIENT_GOODS' ||
|
||
err.code === 'TOTAL_AMOUNT_DIFFERENT'
|
||
) {
|
||
Toast({
|
||
context: this,
|
||
selector: '#t-toast',
|
||
message: err.msg || '支付异常',
|
||
duration: 2000,
|
||
icon: '',
|
||
});
|
||
this.init();
|
||
} else if (err.code === 'ORDER_PAY_FAIL') {
|
||
Toast({
|
||
context: this,
|
||
selector: '#t-toast',
|
||
message: '支付失败',
|
||
duration: 2000,
|
||
icon: 'close-circle',
|
||
});
|
||
setTimeout(() => {
|
||
wx.redirectTo({ url: '/order/list' });
|
||
});
|
||
} else if (err.code === 'ILLEGAL_CONFIG_PARAM') {
|
||
Toast({
|
||
context: this,
|
||
selector: '#t-toast',
|
||
message:
|
||
'支付失败,微信支付商户号设置有误,请商家重新检查支付设置。',
|
||
duration: 2000,
|
||
icon: 'close-circle',
|
||
});
|
||
setTimeout(() => {
|
||
wx.redirectTo({ url: '/order/list' });
|
||
});
|
||
} else {
|
||
Toast({
|
||
context: this,
|
||
selector: '#t-toast',
|
||
message: err.msg || '提交支付超时,请稍后重试',
|
||
duration: 2000,
|
||
icon: '',
|
||
});
|
||
setTimeout(() => {
|
||
// 提交支付失败 返回购物车
|
||
wx.navigateBack();
|
||
}, 2000);
|
||
}
|
||
},
|
||
);
|
||
},
|
||
|
||
// 处理支付
|
||
handlePay(data, settleDetailData) {
|
||
const { channel, payInfo, tradeNo, interactId, transactionId } = data;
|
||
const { totalAmount, totalPayAmount } = settleDetailData;
|
||
const payOrderInfo = {
|
||
payInfo: payInfo,
|
||
orderId: tradeNo,
|
||
orderAmt: totalAmount,
|
||
payAmt: totalPayAmount,
|
||
interactId: interactId,
|
||
tradeNo: tradeNo,
|
||
transactionId: transactionId,
|
||
};
|
||
|
||
if (channel === 'wechat') {
|
||
wechatPayOrder(payOrderInfo);
|
||
}
|
||
},
|
||
|
||
hide() {
|
||
// 隐藏 popup
|
||
this.setData({
|
||
'settleDetailData.abnormalDeliveryGoodsList': [],
|
||
});
|
||
},
|
||
onReceipt() {
|
||
// 跳转 开发票
|
||
const invoiceData = this.invoiceData || {};
|
||
wx.navigateTo({
|
||
url: `/pages/order/receipt/index?invoiceData=${JSON.stringify(
|
||
invoiceData,
|
||
)}`,
|
||
});
|
||
},
|
||
|
||
onCoupons(e) {
|
||
const { submitCouponList, currentStoreId } = this.data;
|
||
const { goodsRequestList } = this;
|
||
const { selectedList } = e.detail;
|
||
const tempSubmitCouponList = submitCouponList.map((storeCoupon) => {
|
||
return {
|
||
couponList:
|
||
storeCoupon.storeId === currentStoreId
|
||
? selectedList
|
||
: storeCoupon.couponList,
|
||
};
|
||
});
|
||
const resSubmitCouponList = this.handleCouponList(tempSubmitCouponList);
|
||
//确定选择优惠券
|
||
this.handleOptionsParams({ goodsRequestList }, resSubmitCouponList);
|
||
this.setData({ couponsShow: false });
|
||
},
|
||
onOpenCoupons(e) {
|
||
const { storeid } = e.currentTarget.dataset;
|
||
this.setData({
|
||
couponsShow: true,
|
||
currentStoreId: storeid,
|
||
});
|
||
},
|
||
|
||
handleCouponList(storeCouponList) {
|
||
//处理门店优惠券 转换成接口需要
|
||
if (!storeCouponList) return [];
|
||
const resSubmitCouponList = [];
|
||
storeCouponList.forEach((ele) => {
|
||
resSubmitCouponList.push(...ele.couponList);
|
||
});
|
||
return resSubmitCouponList;
|
||
},
|
||
|
||
onGoodsNumChange(e) {
|
||
const {
|
||
detail: { value },
|
||
currentTarget: {
|
||
dataset: { goods },
|
||
},
|
||
} = e;
|
||
const index = this.goodsRequestList.findIndex(
|
||
({ storeId, spuId, skuId }) =>
|
||
goods.storeId === storeId &&
|
||
goods.spuId === spuId &&
|
||
goods.skuId === skuId,
|
||
);
|
||
if (index >= 0) {
|
||
// eslint-disable-next-line no-confusing-arrow
|
||
const goodsRequestList = this.goodsRequestList.map((item, i) =>
|
||
i === index ? { ...item, quantity: value } : item,
|
||
);
|
||
this.handleOptionsParams({ goodsRequestList });
|
||
}
|
||
},
|
||
|
||
onPopupChange() {
|
||
this.setData({
|
||
popupShow: !this.data.popupShow,
|
||
});
|
||
},
|
||
});
|