665 lines
17 KiB
Vue
665 lines
17 KiB
Vue
<template>
|
|
<view class="wrap">
|
|
<up-navbar placeholder style="z-index: 100800;" @leftClick="navBack">
|
|
<template #center>
|
|
<view>订单</view>
|
|
</template>
|
|
</up-navbar>
|
|
<up-sticky bgColor="#fff">
|
|
<view style="padding: 10rpx 20rpx 0 20rpx;">
|
|
<up-search shape="round" v-model="keyword" @custom="searchOn" @search="searchOn" @clear="searchOn"
|
|
:actionStyle="{color: '#20b128'}"></up-search>
|
|
</view>
|
|
<up-tabs :current="tabsActive" :list="tablist" lineColor="#20b128" :scrollable="false"
|
|
:activeStyle=" { color: '#20b128', fontWeight: 'bold' }" @change="changeTab"></up-tabs>
|
|
</up-sticky>
|
|
|
|
<swiper class="swiper-box" :current="swiperCurrent" @animationfinish="animationfinish">
|
|
<swiper-item class="swiper-item" v-for="(list, k) in orderList" :key="k">
|
|
<scroll-view scroll-y style="height: 100%;width: 100%;" @scrolltolower="loadMoreGood"
|
|
@refresherrefresh="refresherrefresh(1)" :refresher-triggered="triggered" refresher-enabled
|
|
refresher-background="#F6F6F6">
|
|
<view class="page-box">
|
|
<view v-if="list.length>0" class="list">
|
|
<good v-for="(item, index) in list" :datas="item" :key="index" :type="k" :status="status"
|
|
:order_id='item.order_id' @cancleOrder="cancleOrder" @takeOrder="takeOrder"
|
|
@rePay="rePay" @purchaseAgain="purchaseAgain" @applyAfterSales="applyAfterSales"
|
|
@showVerifyFn='showVerifyFn'></good>
|
|
</view>
|
|
<view v-if="!where[k].loading&&list.length==0" style="padding-top: 100rpx;">
|
|
<up-empty text="订单空空如也"
|
|
icon="https://lihai001.oss-cn-chengdu.aliyuncs.com/def/29955202404260944367594.png">
|
|
</up-empty>
|
|
</view>
|
|
<view v-else-if="where[k].loadend" style="padding-top: 100rpx;">
|
|
<view style="text-align: center;color: #999;">没有更多了</view>
|
|
</view>
|
|
<view v-if="where[k].loading"
|
|
style="padding-top: 100rpx;display: flex;flex-direction: column;align-items: center;">
|
|
<up-loading-icon mode="circle"></up-loading-icon>
|
|
<view style="margin-top: 20rpx;color: #999;">加载中</view>
|
|
</view>
|
|
<view style="width: 100%;height: 300rpx;"></view>
|
|
</view>
|
|
</scroll-view>
|
|
</swiper-item>
|
|
</swiper>
|
|
</view>
|
|
<orderCanclePopup :show="showCancel" @close="showCancel=false" @change="submitCancel" />
|
|
<modal :show="showTake" title="确认收货" content="请确认您已收到货" @close="showTake=false" @change="confirmReceipt" />
|
|
|
|
<!-- 退款原因 -->
|
|
<up-popup :show="refundShow" closeable round="10" @close="refundShow = false">
|
|
<view class="address-popup">
|
|
<view class="head-title">选择商品</view>
|
|
|
|
<view class="afterSales-type">
|
|
<view class="afterSales-type-title">售后类型</view>
|
|
<view class="afterSales-type-con">
|
|
<view class="afterSales-type-item" :class="{'fuck-active':afterSalesType===0}"
|
|
@click="afterSalesType=0">仅退款</view>
|
|
<view class="afterSales-type-item" :class="{'fuck-active':afterSalesType==1}"
|
|
@click="afterSalesType=1">退款退货</view>
|
|
<view class="afterSales-type-item" :class="{'fuck-active':afterSalesType==2}"
|
|
@click="afterSalesType=2">换货</view>
|
|
</view>
|
|
<view class="afterSales-type-tip" v-if="afterSalesType===0">当前售后类型仅支持未备货商品</view>
|
|
<view class="afterSales-type-tip" v-if="afterSalesType==1">当前售后类型仅支持非生鲜类商品</view>
|
|
<view class="afterSales-type-tip" v-if="afterSalesType==2">当前售后类型仅支持选择单个商品</view>
|
|
</view>
|
|
|
|
<view class="scroll-wrap">
|
|
<scroll-view style="max-height: 50vh;padding-bottom: 20rpx;" scroll-y>
|
|
<block v-for="(item,index) in goodsList" :key="index">
|
|
<view class="goods">
|
|
<view class="goods-item">
|
|
<view class="goods-item-left">
|
|
<view class="goods-item-left-img">
|
|
<up-image width="164rpx" height="164rpx" :src="item.image" radius="8rpx" />
|
|
</view>
|
|
<view class="goods-item-left-info">
|
|
<view class="goods_name">{{item.store_name}}</view>
|
|
<view class="goods_detail">
|
|
<view class="goods-detail_num">数量{{item.cart_num}}</view>
|
|
<view class="goods_detail_price">
|
|
<text class="symbol">¥</text>
|
|
<text class="numbers">{{item.price}}</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<view class="goods-item-right" @click="onChooseGoods(item)">
|
|
<image v-if="item.isSelected" src="@/static/icon/check.png"></image>
|
|
<image v-else src="@/static/icon/n-check.png"></image>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</block>
|
|
</scroll-view>
|
|
</view>
|
|
<view style="height: 120rpx;display: flex;justify-content: center;padding: 0 30rpx;align-items: center;"
|
|
@click="onPageToAfterSales">
|
|
<up-button color="#20B128" shape="circle" @click="onSubmitReason">提交</up-button>
|
|
</view>
|
|
</view>
|
|
</up-popup>
|
|
|
|
<view class="mask" v-if='showVerifyPop' @click="showVerifyPop=false">
|
|
<view
|
|
style="position: absolute;top: 50%;left: 50%;transform: translate(-50%,-50%);background-color: white;padding: 20rpx;">
|
|
<up-image :src="orderData.verify_img" width="404rpx" height="60rpx"></up-image>
|
|
<view style="font-weight: bold;color: #333;font-size: 26;text-align: center;margin-top: 20rpx;">
|
|
核销码 {{orderData.verify_code}}
|
|
</view>
|
|
</view>
|
|
</view>
|
|
<ZyPasswordboard v-if='passwordBoardVisible' v-model:visible="passwordBoardVisible" v-bind="passwordBoardProps"
|
|
@close='closeKeyBord' />
|
|
</template>
|
|
|
|
<script setup>
|
|
import {
|
|
onLoad,
|
|
onUnload,
|
|
onPullDownRefresh
|
|
} from "@dcloudio/uni-app"
|
|
import {
|
|
ref
|
|
} from 'vue';
|
|
import good from "./component/good.vue";
|
|
import orderCanclePopup from "@/components/orderCanclePopup.vue"
|
|
import modal from "@/components/modal.vue"
|
|
import ZyPasswordboard from '@/uni_modules/zy-passwordboard/components/zy-passwordboard/zy-passwordboard.vue';
|
|
import {
|
|
cancelOrderApi,
|
|
rePaymentApi,
|
|
confirmReceiptApi,
|
|
orderListApi,
|
|
purchaseAgainApi
|
|
} from "@/api/order.js"
|
|
import {
|
|
userInfoApi
|
|
} from "@/api/user.js"
|
|
|
|
|
|
|
|
const tabsActive = ref(0)
|
|
const changeTab = ({
|
|
index
|
|
}) => {
|
|
tabsActive.value = index;
|
|
swiperCurrent.value = index;
|
|
}
|
|
const tablist = ref([{
|
|
name: '全部'
|
|
}, {
|
|
name: '待付款'
|
|
}, {
|
|
name: '待核销'
|
|
}, {
|
|
name: '已核销'
|
|
}, {
|
|
name: '退款/售后'
|
|
}]);
|
|
|
|
const swiperCurrent = ref(0);
|
|
const animationfinish = ({
|
|
detail: {
|
|
current
|
|
}
|
|
}) => {
|
|
swiperCurrent.value = current;
|
|
tabsActive.value = current;
|
|
|
|
if (swiperCurrent.value == 0 && orderList.value[0].length == 0) getOrderList(0, '', ''); //全部
|
|
if (swiperCurrent.value == 1 && orderList.value[1].length == 0) getOrderList(1, '', 0); //代付款
|
|
if (swiperCurrent.value == 2 && orderList.value[2].length == 0) getOrderList(2, 1, 1); //待核销
|
|
if (swiperCurrent.value == 3 && orderList.value[3].length == 0) getOrderList(3, 2, 1); //已核销
|
|
if (swiperCurrent.value == 4 && orderList.value[4].length == 0) getOrderList(4, -1, 1); //退款
|
|
}
|
|
|
|
const showVerifyPop = ref(false)
|
|
const orderData = ref({})
|
|
const showVerifyFn = (e) => {
|
|
showVerifyPop.value = true
|
|
orderData.value = e
|
|
}
|
|
|
|
|
|
// 取消订单
|
|
const showCancel = ref(false);
|
|
let cancelId = '';
|
|
const submitCancel = (e) => {
|
|
showCancel.value = false;
|
|
cancelOrderApi({
|
|
order_id: cancelId,
|
|
value: e.name
|
|
}).then(res => {
|
|
uni.showToast({
|
|
title: '取消成功',
|
|
icon: 'none'
|
|
})
|
|
orderList.value[1] = orderList.value[1].filter(item => item.id !== cancelId)
|
|
})
|
|
}
|
|
|
|
// 取消订单
|
|
const cancleOrder = (e) => {
|
|
cancelId = e.id;
|
|
showCancel.value = true;
|
|
}
|
|
|
|
// 确认收货
|
|
const showTake = ref(false);
|
|
let takeId = "";
|
|
const takeOrder = (e) => {
|
|
takeId = e.id;
|
|
showTake.value = true;
|
|
}
|
|
|
|
// 确认收货
|
|
const confirmReceipt = () => {
|
|
confirmReceiptApi({
|
|
order_id: takeId
|
|
}).then(res => {
|
|
showTake.value = false;
|
|
uni.$u.toast('确认收货成功');
|
|
reloadAll();
|
|
})
|
|
}
|
|
|
|
// 再次购买
|
|
const purchaseAgain = (e) => {
|
|
purchaseAgainApi({
|
|
order_id: e.id
|
|
}).then(res => {
|
|
uni.$u.toast('已加入购物车');
|
|
uni.navigateTo({
|
|
url: '/pages/cart/cart'
|
|
})
|
|
})
|
|
}
|
|
|
|
// 申请售后<!--sb项目-->
|
|
const refundShow = ref(false);
|
|
const goodsList = ref([]); // 申请售后商品
|
|
const afterSalesType = ref(''); //申请售后类型 0 1 2
|
|
const orderId = ref('');
|
|
|
|
// 申请售后
|
|
const applyAfterSales = (item) => {
|
|
refundShow.value = true;
|
|
goodsList.value = item.goods_list;
|
|
orderId.value = item.id;
|
|
}
|
|
|
|
// 跳转到申请售后
|
|
const onPageToAfterSales = () => {
|
|
if (afterSalesType.value === '') return uni.$u.toast('请选择售后类型');
|
|
if (!goodsList.value || goodsList.value.length == 0) return uni.$u.toast('暂无可申请售后的商品');
|
|
let goods = goodsList.value.find(i => i.isSelected);
|
|
if (goods == undefined) return uni.$u.toast('请选择需要申请售后的商品');
|
|
|
|
let ids = [];
|
|
let goodsListSel = [];
|
|
goodsList.value.map(i => {
|
|
if (i.isSelected) {
|
|
ids.push(i.old_cart_id);
|
|
goodsListSel.push(i);
|
|
}
|
|
});
|
|
|
|
uni.navigateTo({
|
|
url: "/pages/afterSales/afterSales",
|
|
success(res) {
|
|
refundShow.value = false; // close modal
|
|
res.eventChannel.emit('orderDetail', {
|
|
id: orderId.value, //订单id
|
|
old_cart_id: ids,
|
|
refund_type: afterSalesType.value,
|
|
goodsList: goodsListSel
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
// 选择物品
|
|
const onChooseGoods = (item) => {
|
|
if (item.hasOwnProperty('isSelected')) {
|
|
item.isSelected = !item.isSelected;
|
|
} else {
|
|
item.isSelected = true;
|
|
}
|
|
}
|
|
|
|
const pay_type = ref('3')
|
|
|
|
const rePay = async (e) => {
|
|
payFn(e)
|
|
return
|
|
if (!pay_type.value) return uni.$u.toast('请选择支付方式');
|
|
if (pay_type.value == 3 || pay_type.value == 18) {
|
|
let res = await userInfoApi()
|
|
return res.data.pay_password ? passwordBoardVisible.value = true : showModal.value = true
|
|
}
|
|
}
|
|
// 支付密码
|
|
const password = ref(''); // 支付密码
|
|
const passwordBoardVisible = ref(false);
|
|
const passwordBoardProps = {
|
|
title: '输入支付密码',
|
|
onComplete(value) {
|
|
password.value = value
|
|
passwordBoardVisible.value = false
|
|
console.log(password.value)
|
|
// payFn()
|
|
}
|
|
};
|
|
const closeKeyBord = () => {
|
|
password.value = ''
|
|
}
|
|
|
|
|
|
const payFn = (e) => {
|
|
rePaymentApi({
|
|
order_id: e.id,
|
|
address_id: e.address_id,
|
|
mer_id: e.merchant,
|
|
pay_type: e.pay_type
|
|
}).then(res => {
|
|
if (!res.data?.nonceStr) return uni.$u.toast('支付失败!');
|
|
uni.requestPayment({
|
|
provider: 'wxpay',
|
|
timeStamp: res.data.timeStamp,
|
|
nonceStr: res.data.nonceStr,
|
|
package: res.data.package,
|
|
signType: res.data.signType,
|
|
paySign: res.data.paySign,
|
|
success: (e) => {
|
|
if (e.errMsg == 'requestPayment:ok') {
|
|
uni.showToast({
|
|
title: '订单支付成功',
|
|
icon: 'success'
|
|
})
|
|
reloadAll();
|
|
} else uni.$u.toast('支付失败')
|
|
},
|
|
fail: (e) => {
|
|
uni.$u.toast('用户取消支付')
|
|
}
|
|
})
|
|
}).catch(err => {
|
|
uni.$u.toast(err.msg || '网络错误')
|
|
})
|
|
}
|
|
|
|
const notWxPay = () => {
|
|
alert("不是微信支付")
|
|
}
|
|
|
|
|
|
// 订单
|
|
const where = ref([{
|
|
page_no: 1,
|
|
page_size: 25,
|
|
loading: false,
|
|
loadend: false
|
|
}, {
|
|
page_no: 1,
|
|
page_size: 25,
|
|
loading: false,
|
|
loadend: false
|
|
},
|
|
{
|
|
page_no: 1,
|
|
page_size: 25,
|
|
loading: false,
|
|
loadend: false
|
|
},
|
|
{
|
|
page_no: 1,
|
|
page_size: 25,
|
|
loading: false,
|
|
loadend: false
|
|
},
|
|
{
|
|
page_no: 1,
|
|
page_size: 25,
|
|
loading: false,
|
|
loadend: false
|
|
}
|
|
])
|
|
const keyword = ref('')
|
|
const orderList = ref([
|
|
[],
|
|
[],
|
|
[],
|
|
[],
|
|
[]
|
|
])
|
|
const getOrderList = (type = 0, status = '', paid = 1, ifPullReFresh = false) => {
|
|
if (where.value[type].loadend) return;
|
|
where.value[type].loading = true;
|
|
orderListApi({
|
|
page_no: where.value[type].page_no,
|
|
page_size: where.value[type].page_size,
|
|
order_id: keyword.value,
|
|
status: status,
|
|
paid: paid
|
|
}).then(res => {
|
|
if (where.value[type].page_no == 1) orderList.value[type] = [];
|
|
orderList.value[type] = [...orderList.value[type], ...res.data.lists];
|
|
if (res.data.lists.length < where.value[type].page_size) where.value[type].loadend = true;
|
|
where.value[type].page_no++;
|
|
where.value[type].loading = false;
|
|
if (ifPullReFresh) uni.stopPullDownRefresh();
|
|
|
|
}).catch(err => {
|
|
where.value[type].loading = false;
|
|
})
|
|
}
|
|
|
|
const loadMoreGood = () => {
|
|
if (swiperCurrent.value == 0) getOrderList(0, '', ''); //全部
|
|
if (swiperCurrent.value == 1) getOrderList(1, '', 0); //代付款
|
|
if (swiperCurrent.value == 2) getOrderList(2, 1, 1); //待核销
|
|
if (swiperCurrent.value == 3) getOrderList(3, 2, 1); //已核销
|
|
if (swiperCurrent.value == 4) getOrderList(4, -1, 1); //退款
|
|
}
|
|
|
|
// 搜索
|
|
const searchOn = (ifPullReFresh = false) => {
|
|
orderList.value[+swiperCurrent.value] = [];
|
|
console.log(swiperCurrent.value)
|
|
where.value[+swiperCurrent.value].page_no = 1;
|
|
where.value[+swiperCurrent.value].loadend = false;
|
|
if (swiperCurrent.value == 0) getOrderList(0, '', '', ifPullReFresh); //全部
|
|
if (swiperCurrent.value == 1) getOrderList(1, '', 0, ifPullReFresh); //代付款
|
|
if (swiperCurrent.value == 2) getOrderList(2, 1, 1, ifPullReFresh); //待核销
|
|
if (swiperCurrent.value == 3) getOrderList(3, 2, 1, ifPullReFresh); //已核销
|
|
if (swiperCurrent.value == 4) getOrderList(4, -1, 1, ifPullReFresh); //退款
|
|
}
|
|
|
|
let back = 0;
|
|
const navBack = () => {
|
|
uni.navigateBack({
|
|
delta: back ? +back : 0
|
|
})
|
|
}
|
|
|
|
const reloadAll = () => { //对订单进行操作时刷新页面
|
|
where.value.forEach(item => {
|
|
item.page_no = 1;
|
|
item.loadend = false;
|
|
});
|
|
|
|
getOrderList(0, '', ''); //全部
|
|
getOrderList(1, '', 0); //代付款
|
|
getOrderList(2, 1, 1); //待核销
|
|
getOrderList(3, 2, 1); //已核销
|
|
getOrderList(4, -1, 1); //退款
|
|
}
|
|
|
|
onLoad((options) => {
|
|
if (options.type) {
|
|
tabsActive.value = +options.type;
|
|
swiperCurrent.value = +options.type;
|
|
searchOn();
|
|
}
|
|
if (options.back) back = options.back;
|
|
|
|
uni.$on('reLoadOrderList', reloadAll);
|
|
})
|
|
|
|
onUnload(() => {
|
|
uni.$off('reLoadOrderList', reloadAll)
|
|
})
|
|
|
|
const triggered = ref(false);
|
|
let flag = false
|
|
const refresherrefresh = (type = 1) => {
|
|
if (flag) return
|
|
flag = true
|
|
triggered.value = true;
|
|
searchOn()
|
|
console.log("别恶心我了")
|
|
setTimeout(() => {
|
|
triggered.value = false;
|
|
flag = false
|
|
}, 500)
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss">
|
|
.wrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: calc(100vh - var(--window-top));
|
|
width: 100%;
|
|
}
|
|
|
|
.swiper-box {
|
|
flex: 1;
|
|
}
|
|
|
|
.swiper-item {
|
|
height: 100%;
|
|
}
|
|
|
|
.page-box {
|
|
margin: 20rpx;
|
|
}
|
|
|
|
.address-popup {
|
|
// padding: 30rpx;
|
|
background-color: #F6F6F6;
|
|
|
|
.head-title {
|
|
font-weight: bold;
|
|
text-align: center;
|
|
margin-bottom: 20rpx;
|
|
padding: 20rpx;
|
|
}
|
|
|
|
.afterSales-type {
|
|
margin: 0 20rpx 20rpx;
|
|
background: #FFFFFF;
|
|
border-radius: 16rpx;
|
|
padding: 20rpx;
|
|
box-sizing: border-box;
|
|
|
|
.afterSales-type-title {
|
|
font-size: 32rpx;
|
|
color: #444444;
|
|
margin-bottom: 28rpx;
|
|
}
|
|
|
|
.afterSales-type-con {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-bottom: 20rpx;
|
|
|
|
.afterSales-type-item {
|
|
width: 200rpx;
|
|
height: 70rpx;
|
|
line-height: 70rpx;
|
|
border-radius: 12rpx;
|
|
color: #777777;
|
|
border: 2rpx solid #D3D3D3;
|
|
font-size: 28rpx;
|
|
text-align: center;
|
|
|
|
&:not(:nth-last-child(1)) {
|
|
margin-right: 24rpx;
|
|
}
|
|
}
|
|
|
|
.fuck-active {
|
|
color: #FC452F;
|
|
border: 2rpx solid #FC452F;
|
|
font-weight: 600;
|
|
}
|
|
}
|
|
|
|
.afterSales-type-tip {
|
|
font-size: 20rpx;
|
|
color: #FC452F;
|
|
}
|
|
}
|
|
|
|
.scroll-wrap {
|
|
margin: 0 20rpx;
|
|
background: #FFFFFF;
|
|
border-radius: 16rpx;
|
|
padding: 20rpx 20rpx 1rpx;
|
|
box-sizing: border-box;
|
|
|
|
.goods {
|
|
.goods-item {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
margin-bottom: 30rpx;
|
|
|
|
.goods-item-left {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.goods-item-left-img {
|
|
margin-right: 20rpx;
|
|
}
|
|
|
|
.goods-item-left-info {
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: space-between;
|
|
height: 164rpx;
|
|
|
|
.goods_name {
|
|
font-size: 28rpx;
|
|
color: #060606;
|
|
max-width: 400rpx;
|
|
overflow: hidden;
|
|
white-space: nowrap;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.goods_detail {
|
|
display: flex;
|
|
align-items: center;
|
|
|
|
.goods-detail_num {
|
|
margin-right: 30rpx;
|
|
font-size: 28rpx;
|
|
color: #333333;
|
|
}
|
|
|
|
.goods_detail_price {
|
|
display: flex;
|
|
|
|
.symbol {
|
|
align-self: flex-end;
|
|
font-size: 22rpx;
|
|
color: #333333;
|
|
}
|
|
|
|
.numbers {
|
|
font-size: 32rpx;
|
|
color: #333333;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.goods-item-right {
|
|
image {
|
|
width: 48rpx;
|
|
height: 48rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@keyframes disappear {
|
|
to {
|
|
opacity: 0;
|
|
/* 渐隐 */
|
|
transform: scale(0);
|
|
/* 缩小 */
|
|
}
|
|
}
|
|
|
|
|
|
.mask {
|
|
position: fixed;
|
|
width: 100vw;
|
|
height: 100vh;
|
|
background-color: rgba(0, 0, 0, .5);
|
|
top: 0;
|
|
left: 0;
|
|
z-index: 99999 !important;
|
|
}
|
|
</style> |