6 changed files with 888 additions and 9 deletions
@ -0,0 +1,471 @@ |
|||
<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> |
|||
Loading…
Reference in new issue