You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
472 lines
12 KiB
472 lines
12 KiB
|
1 day ago
|
<template>
|
||
|
|
<view class="page">
|
||
|
|
<view class="fixed-head">
|
||
|
|
<view class="nav" :style="{'height': navHeight + 'px'}">
|
||
|
|
<view class="back-btn" :style="{'top': backTop + 'px'}" @tap="back">
|
||
|
|
<uni-icons type="left" size="26"></uni-icons>
|
||
|
|
</view>
|
||
|
|
<view class="nav-title">自配送订单</view>
|
||
|
|
</view>
|
||
|
|
<view class="tabs">
|
||
|
|
<view class="tab" :class="{active: tab === 'pickup'}" @tap="switchTab('pickup')">待取货</view>
|
||
|
|
<view class="tab" :class="{active: tab === 'complete'}" @tap="switchTab('complete')">待送达</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<scroll-view class="list" :style="{'top': listTop + 'px'}" scroll-y @scrolltolower="loadMore">
|
||
|
|
<view class="card" v-for="(item,index) in list" :key="item.id">
|
||
|
|
<view class="card-head">
|
||
|
|
<view class="tag">商家自配送</view>
|
||
|
|
<view class="time">{{item.mustFinishTime | formatTime}}前送达</view>
|
||
|
|
</view>
|
||
|
|
<view class="order-code" v-if="item.numberCode">#{{item.numberCode}}</view>
|
||
|
|
<view class="address">
|
||
|
|
<view class="dot get">取</view>
|
||
|
|
<view>
|
||
|
|
<view class="name">{{item.shopName}}</view>
|
||
|
|
<view class="desc">{{item.shopAddress}}</view>
|
||
|
|
<view class="phone-row" v-if="item.shopPhone" @tap.stop="makeCall(item.shopPhone)">
|
||
|
|
商家电话:{{item.shopPhone}}
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<view class="address">
|
||
|
|
<view class="dot send">送</view>
|
||
|
|
<view>
|
||
|
|
<view class="name">{{item.receiverName}} {{item.receiverPhone}}</view>
|
||
|
|
<view class="desc">{{item.receiverAddress}}</view>
|
||
|
|
<view class="phone-row" v-if="item.receiverPhone" @tap.stop="makeCall(item.receiverPhone)">
|
||
|
|
用户电话:{{item.receiverPhone}}
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<view class="goods-row" v-if="item.goodsList && item.goodsList.length > 0" @tap="productDetail(item)">
|
||
|
|
<view class="goods-title">商品详情</view>
|
||
|
|
<view class="goods-desc">共{{goodsCount(item)}}件,点击查看规格和数量</view>
|
||
|
|
<uni-icons type="right" size="14" color="#7a8582"></uni-icons>
|
||
|
|
</view>
|
||
|
|
<view class="remark" v-if="item.remark">备注:{{item.remark}}</view>
|
||
|
|
<view class="fee">配送费 ¥{{item.deliveryFee || 0}}</view>
|
||
|
|
<view class="btn" @tap="handleOrder(index,item)">
|
||
|
|
{{buttonText(item)}}
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<view class="empty" v-if="list.length === 0 && loadStatus === 'nomore'">暂无订单</view>
|
||
|
|
</scroll-view>
|
||
|
|
<uni-popup ref="productPopup" background-color="transparent">
|
||
|
|
<view class="product-popup-content">
|
||
|
|
<view class="product-popup-header">
|
||
|
|
<view class="product-popup-title">商品详情</view>
|
||
|
|
<view class="product-popup-subtitle">请核对商品规格和数量</view>
|
||
|
|
</view>
|
||
|
|
<view class="product-popup-list" v-if="productData && productData.length > 0">
|
||
|
|
<view class="product-popup-card" v-for="(item1,index1) in productData" :key="index1">
|
||
|
|
<view class="product-popup-img">
|
||
|
|
<img :src="item1.productPicture" alt="">
|
||
|
|
</view>
|
||
|
|
<view class="product-popup-info">
|
||
|
|
<view class="product-popup-name">{{item1.productName}}</view>
|
||
|
|
<view class="product-popup-spec">
|
||
|
|
<text class="product-popup-label">规格</text>
|
||
|
|
<text class="product-popup-spec-text">{{formatSpecs(item1.specs)}}</text>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<view class="product-popup-quantity">
|
||
|
|
<view class="product-popup-quantity-num">x{{item1.quantity}}</view>
|
||
|
|
<view class="product-popup-quantity-label">数量</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
</view>
|
||
|
|
<view class="product-popup-empty" v-else>暂无商品详情</view>
|
||
|
|
</view>
|
||
|
|
</uni-popup>
|
||
|
|
</view>
|
||
|
|
</template>
|
||
|
|
|
||
|
|
<script>
|
||
|
|
export default {
|
||
|
|
data() {
|
||
|
|
return {
|
||
|
|
tab: 'pickup',
|
||
|
|
list: [],
|
||
|
|
loadStatus: 'more',
|
||
|
|
totalPages: 1,
|
||
|
|
searchForm: {
|
||
|
|
pageNum: 1,
|
||
|
|
pageSize: 10,
|
||
|
|
status: 1,
|
||
|
|
deliveryType: 1,
|
||
|
|
shopDelivery: 1,
|
||
|
|
shopId: '',
|
||
|
|
workerId: '',
|
||
|
|
regionId: ''
|
||
|
|
},
|
||
|
|
menuButtonInfo: {},
|
||
|
|
navHeight: 120,
|
||
|
|
backTop: 88,
|
||
|
|
listTop: 210,
|
||
|
|
productData: []
|
||
|
|
}
|
||
|
|
},
|
||
|
|
filters: {
|
||
|
|
formatTime(value) {
|
||
|
|
if (!value) return '';
|
||
|
|
const date = new Date(value);
|
||
|
|
return `${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}`;
|
||
|
|
}
|
||
|
|
},
|
||
|
|
onShow() {
|
||
|
|
this.initNavMetrics();
|
||
|
|
this.initWorkerFromShop();
|
||
|
|
this.resetList();
|
||
|
|
},
|
||
|
|
methods: {
|
||
|
|
initNavMetrics() {
|
||
|
|
const rect = uni.getMenuButtonBoundingClientRect();
|
||
|
|
this.menuButtonInfo = rect || {};
|
||
|
|
const top = rect && rect.top ? rect.top : 32;
|
||
|
|
const height = rect && rect.height ? rect.height : 32;
|
||
|
|
this.backTop = top + 6;
|
||
|
|
this.navHeight = top + height + 52;
|
||
|
|
this.listTop = this.navHeight + 76;
|
||
|
|
},
|
||
|
|
back() {
|
||
|
|
uni.navigateBack();
|
||
|
|
},
|
||
|
|
initWorkerFromShop() {
|
||
|
|
const shop = this.getCurrentShop();
|
||
|
|
this.searchForm.shopId = uni.getStorageSync('shopId');
|
||
|
|
this.searchForm.regionId = JSON.parse(uni.getStorageSync('area')).id;
|
||
|
|
this.searchForm.workerId = shop.workerId || '';
|
||
|
|
this.worker = {
|
||
|
|
workerId: shop.workerId || '',
|
||
|
|
workerName: shop.workerName || '',
|
||
|
|
workerPhone: shop.workerPhone || ''
|
||
|
|
};
|
||
|
|
},
|
||
|
|
getCurrentShop() {
|
||
|
|
const shopList = uni.getStorageSync('schoolShop') || [];
|
||
|
|
const shopId = uni.getStorageSync('shopId');
|
||
|
|
if (Array.isArray(shopList)) {
|
||
|
|
return shopList.find(item => item.id == shopId) || {};
|
||
|
|
}
|
||
|
|
return {};
|
||
|
|
},
|
||
|
|
switchTab(tab) {
|
||
|
|
this.tab = tab;
|
||
|
|
this.resetList();
|
||
|
|
},
|
||
|
|
resetList() {
|
||
|
|
this.list = [];
|
||
|
|
this.searchForm.pageNum = 1;
|
||
|
|
this.totalPages = 1;
|
||
|
|
this.loadStatus = 'more';
|
||
|
|
this.searchForm.status = this.tab === 'pickup' ? 1 : 2;
|
||
|
|
this.getList();
|
||
|
|
},
|
||
|
|
loadMore() {
|
||
|
|
if (this.searchForm.pageNum >= this.totalPages) return;
|
||
|
|
this.searchForm.pageNum++;
|
||
|
|
this.getList();
|
||
|
|
},
|
||
|
|
getList() {
|
||
|
|
if (!this.searchForm.workerId) {
|
||
|
|
this.loadStatus = 'nomore';
|
||
|
|
this.tui.toast('店铺未绑定自配送配送员');
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.tui.request('/mall/delivery/pageShopDelivery', 'POST', this.searchForm, false, false).then((res) => {
|
||
|
|
if (res.code == 200) {
|
||
|
|
const records = res.result.records || [];
|
||
|
|
this.list = this.searchForm.pageNum == 1 ? records : this.list.concat(records);
|
||
|
|
this.totalPages = res.result.pages || 1;
|
||
|
|
this.loadStatus = this.searchForm.pageNum >= this.totalPages ? 'nomore' : 'more';
|
||
|
|
} else {
|
||
|
|
this.tui.toast(res.message);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
},
|
||
|
|
handleOrder(index, item) {
|
||
|
|
if (this.tab === 'pickup' && !item.arriveTime) {
|
||
|
|
this.changeStatus(index, item, 1);
|
||
|
|
return;
|
||
|
|
}
|
||
|
|
this.changeStatus(index, item, this.tab === 'pickup' ? 2 : 3);
|
||
|
|
},
|
||
|
|
buttonText(item) {
|
||
|
|
if (this.tab === 'pickup') {
|
||
|
|
return item.arriveTime ? '确认取货' : '已到店';
|
||
|
|
}
|
||
|
|
return '确认送达';
|
||
|
|
},
|
||
|
|
changeStatus(index, item, status) {
|
||
|
|
const url = status === 1 ? '/mall/delivery/arriveShop' : (status === 2 ? '/mall/delivery/pickup' : '/mall/delivery/complete');
|
||
|
|
this.tui.request(url, 'POST', {
|
||
|
|
regionId: this.searchForm.regionId,
|
||
|
|
deliveryId: item.id,
|
||
|
|
workerId: this.worker.workerId
|
||
|
|
}, false, true).then((res) => {
|
||
|
|
if (res.code == 200) {
|
||
|
|
if (status === 1) {
|
||
|
|
this.$set(this.list[index], 'arriveTime', new Date());
|
||
|
|
} else {
|
||
|
|
this.list.splice(index, 1);
|
||
|
|
}
|
||
|
|
this.tui.toast(res.message || '操作成功');
|
||
|
|
} else {
|
||
|
|
this.tui.toast(res.message);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
},
|
||
|
|
productDetail(item) {
|
||
|
|
this.productData = item.goodsList || [];
|
||
|
|
this.$refs.productPopup.open();
|
||
|
|
},
|
||
|
|
goodsCount(item) {
|
||
|
|
return (item.goodsList || []).reduce((sum, goods) => sum + Number(goods.quantity || 0), 0);
|
||
|
|
},
|
||
|
|
formatSpecs(data) {
|
||
|
|
let str;
|
||
|
|
if (typeof data === 'object' && data !== null) {
|
||
|
|
str = JSON.stringify(data);
|
||
|
|
} else if (typeof data === 'string') {
|
||
|
|
str = data;
|
||
|
|
} else {
|
||
|
|
str = String(data || '');
|
||
|
|
}
|
||
|
|
return str.replace(/[{}"]/g, '');
|
||
|
|
},
|
||
|
|
makeCall(phone) {
|
||
|
|
if (!phone) return;
|
||
|
|
uni.makePhoneCall({
|
||
|
|
phoneNumber: phone
|
||
|
|
});
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
</script>
|
||
|
|
|
||
|
|
<style>
|
||
|
|
.page{
|
||
|
|
height: 100vh;
|
||
|
|
background: #F5F8F5;
|
||
|
|
padding: 0 24rpx;
|
||
|
|
box-sizing: border-box;
|
||
|
|
position: relative;
|
||
|
|
overflow: hidden;
|
||
|
|
}
|
||
|
|
.fixed-head{
|
||
|
|
position: absolute;
|
||
|
|
top: -40rpx;
|
||
|
|
left: 24rpx;
|
||
|
|
right: 24rpx;
|
||
|
|
z-index: 10;
|
||
|
|
background: #F5F8F5;
|
||
|
|
}
|
||
|
|
.nav{
|
||
|
|
position: relative;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
}
|
||
|
|
.back-btn{
|
||
|
|
position: absolute;
|
||
|
|
left: 0;
|
||
|
|
width: 68rpx;
|
||
|
|
height: 68rpx;
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: center;
|
||
|
|
border-radius: 50%;
|
||
|
|
background: rgba(255, 255, 255, 0.9);
|
||
|
|
box-shadow: 0 8rpx 20rpx rgba(0, 35, 28, 0.08);
|
||
|
|
}
|
||
|
|
.nav-title{
|
||
|
|
position: absolute;
|
||
|
|
bottom: 18rpx;
|
||
|
|
font-size: 32rpx;
|
||
|
|
font-weight: 800;
|
||
|
|
}
|
||
|
|
.tabs{
|
||
|
|
display: flex;
|
||
|
|
background: #fff;
|
||
|
|
border-radius: 24rpx;
|
||
|
|
padding: 10rpx;
|
||
|
|
margin-bottom: 0;
|
||
|
|
}
|
||
|
|
.tab{
|
||
|
|
flex: 1;
|
||
|
|
text-align: center;
|
||
|
|
height: 70rpx;
|
||
|
|
line-height: 70rpx;
|
||
|
|
border-radius: 20rpx;
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
.tab.active{
|
||
|
|
background: linear-gradient(90deg, #e3ff96, #a6ffea);
|
||
|
|
}
|
||
|
|
.list{
|
||
|
|
position: absolute;
|
||
|
|
left: 24rpx;
|
||
|
|
right: 24rpx;
|
||
|
|
bottom: 0;
|
||
|
|
box-sizing: border-box;
|
||
|
|
padding-top: 20rpx;
|
||
|
|
padding-bottom: 36rpx;
|
||
|
|
}
|
||
|
|
.card{
|
||
|
|
background: #fff;
|
||
|
|
border-radius: 24rpx;
|
||
|
|
padding: 24rpx;
|
||
|
|
margin-bottom: 20rpx;
|
||
|
|
box-shadow: 0 12rpx 30rpx rgba(0, 35, 28, 0.08);
|
||
|
|
}
|
||
|
|
.card-head{
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
justify-content: space-between;
|
||
|
|
}
|
||
|
|
.tag{
|
||
|
|
background: rgba(255, 111, 44, 0.1);
|
||
|
|
color: #ff6f2c;
|
||
|
|
padding: 8rpx 16rpx;
|
||
|
|
border-radius: 18rpx;
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
.time{
|
||
|
|
color: #666;
|
||
|
|
}
|
||
|
|
.order-code{
|
||
|
|
margin-top: 18rpx;
|
||
|
|
font-size: 32rpx;
|
||
|
|
font-weight: 800;
|
||
|
|
}
|
||
|
|
.address{
|
||
|
|
display: flex;
|
||
|
|
margin-top: 18rpx;
|
||
|
|
}
|
||
|
|
.dot{
|
||
|
|
width: 44rpx;
|
||
|
|
height: 44rpx;
|
||
|
|
line-height: 44rpx;
|
||
|
|
text-align: center;
|
||
|
|
border-radius: 50%;
|
||
|
|
color: #fff;
|
||
|
|
margin-right: 16rpx;
|
||
|
|
}
|
||
|
|
.get{
|
||
|
|
background: #0b9b73;
|
||
|
|
}
|
||
|
|
.send{
|
||
|
|
background: #ff6f2c;
|
||
|
|
}
|
||
|
|
.name{
|
||
|
|
font-weight: 700;
|
||
|
|
}
|
||
|
|
.desc,.remark,.fee{
|
||
|
|
margin-top: 8rpx;
|
||
|
|
color: #666;
|
||
|
|
line-height: 38rpx;
|
||
|
|
}
|
||
|
|
.phone-row{
|
||
|
|
display: inline-block;
|
||
|
|
margin-top: 8rpx;
|
||
|
|
color: #0b9b73;
|
||
|
|
font-weight: 700;
|
||
|
|
line-height: 34rpx;
|
||
|
|
}
|
||
|
|
.goods-row{
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
margin-top: 20rpx;
|
||
|
|
padding: 18rpx 20rpx;
|
||
|
|
border-radius: 18rpx;
|
||
|
|
background: rgba(247, 248, 248, 0.8);
|
||
|
|
}
|
||
|
|
.goods-title{
|
||
|
|
font-weight: 800;
|
||
|
|
margin-right: 16rpx;
|
||
|
|
}
|
||
|
|
.goods-desc{
|
||
|
|
flex: 1;
|
||
|
|
color: #666;
|
||
|
|
font-size: 24rpx;
|
||
|
|
}
|
||
|
|
.btn{
|
||
|
|
margin-top: 24rpx;
|
||
|
|
height: 76rpx;
|
||
|
|
line-height: 76rpx;
|
||
|
|
text-align: center;
|
||
|
|
border-radius: 38rpx;
|
||
|
|
background: linear-gradient(90deg, #e3ff96, #a6ffea);
|
||
|
|
font-weight: 800;
|
||
|
|
}
|
||
|
|
.empty{
|
||
|
|
text-align: center;
|
||
|
|
color: #888;
|
||
|
|
padding: 80rpx 0;
|
||
|
|
}
|
||
|
|
.product-popup-content{
|
||
|
|
width: 650rpx;
|
||
|
|
max-height: 850rpx;
|
||
|
|
padding: 30rpx;
|
||
|
|
border-radius: 28rpx;
|
||
|
|
background: #fff;
|
||
|
|
box-sizing: border-box;
|
||
|
|
}
|
||
|
|
.product-popup-title{
|
||
|
|
font-size: 32rpx;
|
||
|
|
font-weight: 800;
|
||
|
|
}
|
||
|
|
.product-popup-subtitle{
|
||
|
|
margin-top: 8rpx;
|
||
|
|
color: #888;
|
||
|
|
font-size: 24rpx;
|
||
|
|
}
|
||
|
|
.product-popup-list{
|
||
|
|
margin-top: 24rpx;
|
||
|
|
max-height: 680rpx;
|
||
|
|
overflow-y: auto;
|
||
|
|
}
|
||
|
|
.product-popup-card{
|
||
|
|
display: flex;
|
||
|
|
align-items: center;
|
||
|
|
padding: 18rpx 0;
|
||
|
|
border-bottom: 1rpx solid #f0f0f0;
|
||
|
|
}
|
||
|
|
.product-popup-img img{
|
||
|
|
width: 90rpx;
|
||
|
|
height: 90rpx;
|
||
|
|
border-radius: 16rpx;
|
||
|
|
margin-right: 18rpx;
|
||
|
|
}
|
||
|
|
.product-popup-info{
|
||
|
|
flex: 1;
|
||
|
|
min-width: 0;
|
||
|
|
}
|
||
|
|
.product-popup-name{
|
||
|
|
font-weight: 800;
|
||
|
|
line-height: 38rpx;
|
||
|
|
}
|
||
|
|
.product-popup-spec{
|
||
|
|
margin-top: 8rpx;
|
||
|
|
color: #777;
|
||
|
|
font-size: 24rpx;
|
||
|
|
}
|
||
|
|
.product-popup-label{
|
||
|
|
margin-right: 10rpx;
|
||
|
|
color: #999;
|
||
|
|
}
|
||
|
|
.product-popup-quantity{
|
||
|
|
width: 80rpx;
|
||
|
|
text-align: right;
|
||
|
|
}
|
||
|
|
.product-popup-quantity-num{
|
||
|
|
font-weight: 800;
|
||
|
|
}
|
||
|
|
.product-popup-quantity-label,
|
||
|
|
.product-popup-empty{
|
||
|
|
color: #888;
|
||
|
|
font-size: 22rpx;
|
||
|
|
}
|
||
|
|
</style>
|