feat: 新增确认送达弹框组件、添加安卓打包测试证书、骑手配送流程接口对接

This commit is contained in:
admin
2026-02-24 11:58:30 +08:00
parent b85833690f
commit bc1833ec89
25 changed files with 2982 additions and 1205 deletions

View File

@@ -0,0 +1,298 @@
<template>
<u-popup :show="show" mode="bottom" :closeable="true" @close="onClose" :safeAreaInsetBottom="false" border-radius="16">
<view class="delivery-popup">
<!-- 标题 -->
<view class="popup-header">
<text class="popup-title">确认送达</text>
</view>
<!-- 内容区域 -->
<view class="popup-content">
<view class="upload-label">
<text class="required">*</text>
<text>上传送达照片</text>
</view>
<!-- 照片列表 -->
<up-upload
:fileList="photoList"
@afterRead="afterRead"
@delete="deleteUpload"
:maxCount="1"
:maxSize="5 * 1024 * 1024"
uploadText="上传照片"
:previewFullImage="true"
></up-upload>
</view>
<!-- 底部按钮 -->
<view class="popup-footer">
<view class="btn submit" @click="onSubmit">提交</view>
</view>
</view>
</u-popup>
</template>
<script setup>
import { ref, watch } from 'vue';
import sheep from '@/sheep';
import { baseUrl, apiPath } from '@/sheep/config';
const props = defineProps({
// 控制显示隐藏
show: {
type: Boolean,
default: false
}
});
const emit = defineEmits(['update:show', 'submit', 'close']);
// 照片列表 (用于 up-upload 组件)
const photoList = ref([])
// 监听弹框显示,重置数据
watch(() => props.show, (newVal) => {
if (newVal) {
photoList.value = [];
}
});
// 关闭弹框
function onClose() {
emit('update:show', false);
emit('close');
}
// 删除上传的图片
function deleteUpload(event) {
photoList.value.splice(event.index, 1);
}
// 上传单个文件到 OSS
async function uploadFile(filePath) {
const token = uni.getStorageSync('token');
return new Promise((resolve, reject) => {
uni.uploadFile({
url: baseUrl + apiPath + '/app/file/uploadOss', // 上传接口地址
header: {
'Authorization': token
},
filePath: filePath,
name: 'file',
success: (res) => {
if (res.statusCode === 200) {
try {
const data = JSON.parse(res.data);
if (data.code === 0 && data.data) {
resolve(data.data);
} else {
console.error('上传失败:', data.msg);
resolve(null);
}
} catch (e) {
console.error('解析上传响应失败:', e);
resolve(null);
}
} else {
console.error('上传失败:', res.statusCode);
resolve(null);
}
},
fail: (err) => {
console.error('上传请求失败:', err);
reject(err);
}
});
});
}
// 上传图片后的回调
async function afterRead(event) {
// 当设置 mutiple 为 true 时, event.file.list 为数组
const { file } = event;
// 如果是单选,转换为数组处理
const fileList = Array.isArray(file) ? file : [file];
for (const item of fileList) {
// 标记为上传中
photoList.value.push({
...item,
status: 'uploading',
message: '上传中'
});
}
// 依次上传文件
for (let i = 0; i < fileList.length; i++) {
const item = fileList[i];
const index = photoList.value.findIndex(f => f.url === item.url);
try {
const url = await uploadFile(item.url);
if (url) {
// 上传成功,更新状态
photoList.value[index] = {
...photoList.value[index],
status: 'success',
message: ''
};
} else {
// 上传失败
photoList.value[index] = {
...photoList.value[index],
status: 'failed',
message: '上传失败'
};
}
} catch (error) {
console.error('上传图片异常:', error);
photoList.value[index] = {
...photoList.value[index],
status: 'failed',
message: '上传失败'
};
}
}
}
// 提交
async function onSubmit() {
if (photoList.value.length === 0) {
uni.showToast({
title: '请上传送达照片',
icon: 'none'
});
return;
}
// 查找上传成功的照片
const uploadedPhoto = photoList.value.find(p => p.status === 'success');
if (!uploadedPhoto) {
uni.showToast({
title: '照片上传中,请稍候',
icon: 'none'
});
return;
}
// 提交成功,返回上传后的 URL
emit('submit', uploadedPhoto.url);
onClose();
}
</script>
<style scoped lang="scss">
.delivery-popup {
padding: 30rpx;
padding-bottom: calc(30rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(30rpx + env(safe-area-inset-bottom));
}
.popup-header {
text-align: center;
padding-bottom: 30rpx;
border-bottom: 1rpx solid #f0f0f0;
}
.popup-title {
font-size: 34rpx;
font-weight: 600;
color: #333;
}
.popup-content {
padding: 30rpx 0;
}
.upload-label {
display: flex;
align-items: center;
font-size: 28rpx;
color: #333;
margin-bottom: 24rpx;
}
.required {
color: #f5222d;
margin-right: 4rpx;
}
.photo-list {
display: flex;
flex-wrap: wrap;
gap: 20rpx;
}
.photo-item {
position: relative;
width: 180rpx;
height: 180rpx;
border-radius: 12rpx;
overflow: hidden;
}
.photo-preview {
width: 100%;
height: 100%;
border-radius: 12rpx;
}
.photo-delete {
position: absolute;
top: 10rpx;
right: 10rpx;
width: 40rpx;
height: 40rpx;
background: rgba(0, 0, 0, 0.5);
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
}
.delete-icon {
color: #fff;
font-size: 32rpx;
line-height: 1;
}
.photo-add {
width: 180rpx;
height: 180rpx;
background: #f5f5f5;
border-radius: 12rpx;
display: flex;
align-items: center;
justify-content: center;
border: 2rpx dashed #ddd;
}
.add-icon {
font-size: 72rpx;
color: #999;
font-weight: 300;
}
.popup-footer {
margin-top: 40rpx;
}
.btn {
width: 100%;
height: 88rpx;
line-height: 88rpx;
text-align: center;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: 500;
}
.btn.submit {
background: #1e9fff;
color: #fff;
}
</style>

View File

@@ -10,7 +10,7 @@
<!-- 查询输入 -->
<view class="search-row">
<view style="width:620rpx;">
<input class="search-input" v-model="orderCode" placeholder="输入收人手机尾号4位+取单号如8927#11" />
<input class="search-input" v-model="orderCode" placeholder="输入收人手机尾号4位+取单号,如8927#11" />
</view>
<view style="margin-left:15rpx;">
<up-button type="primary" size="small" text="查询" @click="queryOrder"></up-button>
@@ -23,7 +23,7 @@
<text class="icon">🏬</text>
<text class="text">取货点店铺名称</text>
</view>
<text class="muted">{{ pickupName }}</text>
<text class="muted">取货店铺详细地址{{ pickupName }}</text>
</view>
<!-- 送餐地址 -->
@@ -45,20 +45,22 @@
<view class="form-row">
<text class="label">交接备注</text>
<picker :range="remarks" @change="onRemarkChange">
<view class="picker-display">{{ selectedRemarkText }}</view>
<view class="picker-display">{{ selectedRemarkText || '请选择交接备注' }}</view>
</picker>
</view>
<!-- 凭证 上传 -->
<view class="form-row proof-row">
<text class="label required">凭证</text>
<view class="proof-list">
<view v-for="(img, idx) in proofImages" :key="idx" class="proof-item">
<image :src="img" mode="aspectFill" class="proof-img" />
<view class="remove" @click="removeProofImage(idx)"></view>
</view>
<view class="proof-add" @click="addProofImage">+</view>
</view>
<up-upload
:fileList="uploadFileList"
@afterRead="afterRead"
@delete="deleteUpload"
:maxCount="1"
:maxSize="5 * 1024 * 1024"
uploadText="上传凭证"
:previewFullImage="true"
></up-upload>
</view>
<!-- 底部操作 -->
@@ -74,6 +76,10 @@
</template>
<script setup>
import DeliveryOrderApi from '@/sheep/api/member/deliveryOrder';
import sheep from '@/sheep';
import { baseUrl, apiPath } from '@/sheep/config';
import {
ref,
reactive,
@@ -90,26 +96,29 @@
const emit = defineEmits(['close', 'confirm'])
// 响应式数据
const orderIndex = ref(1)
const orderIndex = ref('')
const orderCode = ref('')
const pickupName = ref('取货店铺详细地址广东省广州市天河区学院站荷光路')
const address = ref('送餐详细地址广东省广州市天河区华景新城软件园区A栋303室')
const recipientTail = ref('1254')
const pickupName = ref('')
const address = ref('')
const recipientTail = ref('')
const customerNote = ref('依据餐量提供餐具')
const remarks = ['请选择 备注内容', '已核对身份证', '缺少配件', '地址异常']
const selectedRemark = ref(0)
const remarks = ['餐品破损', '餐品撒翻', '其他']
const selectedRemark = ref('')
const selectedRemarkText = computed(() => remarks[selectedRemark.value] || '')
const proofImages = ref([])
// 上传文件列表 (用于 up-upload 组件)
const uploadFileList = ref([])
// 已上传的凭证URL列表
const proofUrls = ref([])
// 方法
const onClose = () => {
emit('close')
}
const queryOrder = () => {
// 简单模拟查询:如果输入有内容则把 orderIndex 加 1 并回填部分数据
const queryOrder = async () => {
if (!orderCode.value) {
uni.showToast({
title: '请输入查询条件',
@@ -117,12 +126,56 @@
})
return
}
orderIndex.value += 1
// 这里可以调用接口查询并填充 pickupName/address 等
uni.showToast({
title: '查询成功',
icon: 'success'
})
try {
// 解析输入支持输入订单ID或手机尾号#取单号格式
let orderId = orderCode.value;
// 如果包含 # 符号尝试提取订单ID这里假设后缀是订单ID
if (orderCode.value.includes('#')) {
const parts = orderCode.value.split('#');
orderId = parts[parts.length - 1];
}
uni.showLoading({ title: '查询中...' });
const res = await DeliveryOrderApi.getDetail(orderId);
const data = res.data || res;
uni.hideLoading();
if (data && data.id) {
// 更新订单信息
orderIndex.value = data.id;
pickupName.value = data.shopName || '';
address.value = data.receiverAddress || '';
customerNote.value = data.orderRemark || '';
// 处理收货人信息
if (data.receiverPhone) {
recipientTail.value = (data.receiverPhone + '').slice(-4);
} else {
recipientTail.value = '';
}
uni.showToast({
title: '查询成功',
icon: 'success'
});
} else {
uni.showToast({
title: '未找到订单',
icon: 'none'
});
}
} catch (e) {
uni.hideLoading();
console.error('queryOrder error', e);
uni.showToast({
title: '查询失败',
icon: 'none'
});
}
}
// 拨打电话
@@ -140,37 +193,161 @@
selectedRemark.value = e.detail.value
}
const addProofImage = () => {
// 使用 uni.chooseImage 上传
uni.chooseImage({
count: 4,
success(res) {
const tempFiles = res.tempFilePaths || res.tempFiles.map(f => f.path)
proofImages.value = proofImages.value.concat(tempFiles)
// 删除上传的图片
const deleteUpload = (event) => {
uploadFileList.value.splice(event.index, 1)
proofUrls.value.splice(event.index, 1)
}
// 上传单个文件到 OSS
async function uploadFile(filePath) {
const token = uni.getStorageSync('token');
return new Promise((resolve, reject) => {
uni.uploadFile({
url: baseUrl + apiPath + '/app/file/uploadOss', // 上传接口地址
header: {
'Authorization': token
},
filePath: filePath,
name: 'file',
success: (res) => {
if (res.statusCode === 200) {
try {
const data = JSON.parse(res.data);
if (data.code === 0 && data.data) {
resolve(data.data);
} else {
console.error('上传失败:', data.msg);
resolve(null);
}
} catch (e) {
console.error('解析上传响应失败:', e);
resolve(null);
}
} else {
console.error('上传失败:', res.statusCode);
resolve(null);
}
},
fail: (err) => {
console.error('上传请求失败:', err);
reject(err);
}
});
});
}
// 上传图片后的回调
async function afterRead(event) {
// 当设置 mutiple 为 true 时, event.file.list 为数组
const { file } = event;
// 如果是单选,转换为数组处理
const fileList = Array.isArray(file) ? file : [file];
for (const item of fileList) {
// 标记为上传中
uploadFileList.value.push({
...item,
status: 'uploading',
message: '上传中'
});
}
// 依次上传文件
for (let i = 0; i < fileList.length; i++) {
const item = fileList[i];
const index = uploadFileList.value.findIndex(f => f.url === item.url);
try {
const url = await uploadFile(item.url);
if (url) {
// 上传成功,更新状态
uploadFileList.value[index] = {
...uploadFileList.value[index],
status: 'success',
message: ''
};
proofUrls.value.push(url);
} else {
// 上传失败
uploadFileList.value[index] = {
...uploadFileList.value[index],
status: 'failed',
message: '上传失败'
};
}
} catch (error) {
console.error('上传图片异常:', error);
uploadFileList.value[index] = {
...uploadFileList.value[index],
status: 'failed',
message: '上传失败'
};
}
})
}
}
const removeProofImage = (idx) => {
proofImages.value.splice(idx, 1)
}
const onConfirm = () => {
const onConfirm = async () => {
// 校验配送单信息
if (!orderIndex.value) {
uni.showToast({
title: '没有配送单信息',
icon: 'none'
})
return
}
// 校验凭证
if (proofImages.value.length === 0) {
if (proofUrls.value.length === 0) {
uni.showToast({
title: '请上传凭证',
icon: 'none'
})
return
}
const payload = {
orderIndex: orderIndex.value,
orderCode: orderCode.value,
remark: selectedRemarkText.value,
proofImages: proofImages.value
try {
uni.showLoading({ title: '提交中...' });
// 调用确认交接接口
const res = await DeliveryOrderApi.riderConfirmHandover({
deliveryOrderId: Number(orderIndex.value),
// 注意:这里假设 remarks 的 index 就是 handoverRemarkId如果后端需要实际ID可能需要调整
handoverRemarkId: selectedRemark.value === 0 ? undefined : selectedRemark.value,
imageUrlList: proofUrls.value
});
uni.hideLoading();
if (res.code === 0 && res.data === true) {
uni.showToast({
title: '交接成功',
icon: 'success'
});
// 关闭弹框并通知父组件
emit('confirm', {
orderIndex: orderIndex.value,
orderCode: orderCode.value,
remark: selectedRemarkText.value,
proofImages: proofUrls.value
});
} else {
uni.showToast({
title: res.msg || '交接失败',
icon: 'none'
});
}
} catch (error) {
uni.hideLoading();
console.error('确认交接异常:', error);
uni.showToast({
title: '交接失败,请重试',
icon: 'none'
});
}
emit('confirm', payload)
}
</script>
@@ -212,6 +389,7 @@
border: 1rpx solid #ddd;
padding: 0 20rpx;
border-radius: 6rpx;
font-size: 22rpx;
}
.search-btn {

View File

@@ -5,14 +5,16 @@
<view class="top-area" :style="headerStyle">
<view class="top-bg"></view>
<view class="top-inner">
<view class="user-info">
<image class="user-avatar" @tap="sheep.$router.go('/pages/index/user')"
:src="driverInfo.avatar || defaultAvatar" mode="cover" />
<view class="user-info" @tap="sheep.$router.go('/pages/index/user')">
<image class="user-avatar" :src="driverInfo.avatar || defaultAvatar" mode="cover" />
<view class="user-meta">
<!-- <text class="user-status" @click="toggleOnline">{{ driverInfo.isOnline ? '在线中' : '离线' }}</text> -->
<text class="user-status">
<text class="user-status" v-if="driverInfo.nickname">
{{ driverInfo.onlineStatus == 0 ? '离线' : (driverInfo.onlineStatus == 1 ? '在线' : '待审核') }}
</text>
<text class="user-status" v-else>
请登录
</text>
</view>
</view>
<view class="tabs">
@@ -53,7 +55,7 @@
<text class="address-title">{{ order.shopAddress }}</text>
<text class="address-sub">商家 · {{ order.shopPhone || '' }}</text>
</view>
<view class="nav-icon" @click="openMap(order.shopLat, order.shopLng, order.shopAddress)">导航</view>
<view class="nav-icon" @click.stop="openMap(order.shopLat, order.shopLng, order.shopAddress)">导航</view>
</view>
<view class="address-row">
<view class="icon deliver"></view>
@@ -61,14 +63,14 @@
<text class="address-title">{{ order.deliveryAddress }}</text>
<text class="address-sub">收货人{{ order.receiverName }} {{ order.receiverPhone ? ('尾号' + (order.receiverPhone + '').slice(-4)) : ''}}</text>
</view>
<view class="nav-icon" @click="openMap(order.deliveryLat, order.deliveryLng, order.deliveryAddress)">导航</view>
<view class="nav-icon" @click.stop="openMap(order.deliveryLat, order.deliveryLng, order.deliveryAddress)">导航</view>
</view>
</view>
</view>
<!-- 操作区 -->
<view class="order-actions">
<view class="contact" @click="callPhone(order.receiverPhone)">
<view class="contact" @click="openRemindPopupWithOrder(order)">
<text>联系</text>
</view>
<view class="confirm" @click="confirmArrive(order.id)" v-if="order.deliveryStatus == 2">
@@ -77,15 +79,55 @@
<view class="confirm" @click="confirmPickup(order.id)" v-if="order.deliveryStatus == 3">
<text>确认取餐</text>
</view>
<view class="confirm" style="background: #ffaa00;" v-if="order.deliveryStatus == 4">
<text>送达交接点</text>
</view>
<view class="confirm" v-if="order.deliveryStatus == 5" @click="openDeliveryPopup(order)">
<text>确认送达顾客</text>
</view>
</view>
</view>
</scroll-view>
<!-- 催单弹框 -->
<up-popup v-model:show="showRemind" mode="bottom" :closeable="false" border-radius="12">
<view class="remind-popup">
<view class="remind-row">
<text class="remind-title">联系商家</text>
<view class="remind-btn" @click.stop="callShopPhone">拨打电话</view>
</view>
<view class="remind-row">
<text class="remind-title">联系顾客</text>
<view class="remind-btn" @click.stop="callCustomerPhone">拨打电话</view>
</view>
</view>
</up-popup>
<!-- 底部批量操作栏 -->
<view class="bottom-bar">
<view v-if="activeTab == 'delivering'" class="batch-operation" @click="openBatchOperation">批量操作</view>
<view class="batch-item" @click="scanQr">扫一扫取单</view>
<view class="batch-item" @click="openManualInput">输入用户单编码</view>
</view>
<!-- 批量操作模态弹框 -->
<u-modal :show="batchModalShow" :title="batchModalTitle" :content="batchModalContent" confirmText="确认送达" cancelText="取消"
:showCancelButton="hasDeliveryOrders" @confirm="onBatchConfirm" @cancel="batchModalShow = false" @close="batchModalShow = false"
:closeOnClickOverlay="false" :zoom="true" confirmColor="#1e9fff" />
<!-- 批量送达交接点异步操作弹框 -->
<u-modal :show="batchLoadingModalShow" :title="batchLoadingModalTitle" :content="batchLoadingModalContent" confirmText="确认送达"
:showCancelButton="false" :asyncClose="true" @confirm="onBatchLoadingConfirm" ref="batchLoadingModalRef"
confirmColor="#1e9fff" />
<!-- 确认送达顾客弹框 -->
<DeliveryPopup
:show="showDeliveryPopup"
:receiverPhone="currentOrderForDelivery?.receiverPhone || ''"
@update:show="showDeliveryPopup = $event"
@submit="handleDeliveryConfirm"
@close="showDeliveryPopup = false"
/>
</view>
</template>
@@ -95,13 +137,10 @@ import sheep from '@/sheep';
import { onShow } from '@dcloudio/uni-app';
import OrderCodePopup from './components/order-code-popup.vue';
import DeliveryOrderApi from '@/sheep/api/member/deliveryOrder';
import DeliveryPopup from './components/delivery-popup.vue';
// 驿站/骑手信息(从 store 获取或 mock
const driverInfo = ref({
isOnline: true,
nickName: '骑手张三',
avatar: ''
});
//骑手信息
const driverInfo = computed(() => sheep.$store('user').userInfo);
const defaultAvatar = 'https://huichibao.oss-cn-guangzhou.aliyuncs.com/1/material/348b8223-8d03-46aa-8836-6757e8beebd2.png';
@@ -148,7 +187,7 @@ const filteredOrders = computed(() => orders.value);
// 加载订单列表数据
async function loadOrders(isLoadMore = false) {
if (loading.value) return;
if (driverInfo.value.auditStatus != 2) return;
loading.value = true;
// 根据当前 tab 确定接口参数 status
@@ -199,6 +238,10 @@ async function loadOrders(isLoadMore = false) {
// 判断是否还有更多数据
noMore.value = orders.value.length >= pagination.value.total;
} else {
// 清空列表,防止旧数据残留
if (!isLoadMore) {
orders.value = [];
}
sheep.$helper.toast(res.msg || '加载失败');
}
} catch (error) {
@@ -275,10 +318,66 @@ async function confirmPickup(orderId) {
}
}
// 催单弹框控制
const showRemind = ref(false);
const currentOrder = ref(null);
// 批量操作模态弹框控制
const batchModalShow = ref(false);
const batchModalTitle = ref('当前送达交接点订单数');
const batchModalContent = ref('');
const hasDeliveryOrders = ref(false);
// 批量送达异步操作弹框控制
const batchLoadingModalShow = ref(false);
const batchLoadingModalTitle = ref('当前送达交接点订单数');
const batchLoadingModalContent = ref('');
const batchOrderCount = ref(0);
// 确认送达顾客弹框控制
const showDeliveryPopup = ref(false);
const currentOrderForDelivery = ref(null);
function openRemindPopupWithOrder(order) {
currentOrder.value = order;
showRemind.value = true;
}
function openRemindPopup() {
showRemind.value = true;
}
function closeRemindPopup() {
showRemind.value = false;
}
function callShopPhone(phone) {
//订单获取商家电话
const orderPhone = currentOrder.value?.shopPhone || '';
if (!orderPhone) {
sheep.$helper.toast('未找到商家电话');
return;
}
callPhone(orderPhone);
closeRemindPopup();
}
function callCustomerPhone(phone) {
//从订单获取顾客电话
const orderPhone = currentOrder.value?.receiverPhone || '';
if (!orderPhone) {
sheep.$helper.toast('未找到顾客电话');
return;
}
callPhone(orderPhone);
closeRemindPopup();
}
// 拨打电话
function callPhone(phone) {
console.log("电话:", phone)
if (!phone) {
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('未找到联系电话');
sheep.$helper.toast('未找到联系电话');
return;
}
uni.makePhoneCall({
@@ -296,7 +395,13 @@ function openMap(lat, lng, name) {
latitude: Number(lat),
longitude: Number(lng),
name: name || '',
scale: 18
scale: 18,
success: function () {
console.log('success');
},
error: function (err) {
console.log("错误信息:", err);
}
});
}
@@ -321,6 +426,76 @@ function openManualInput() {
orderPopupShow.value = true;
}
// 打开批量操作弹框
function openBatchOperation() {
// 筛选出配送中状态为待送达交接点(ddeliveryStatus=4)的订单
const deliveryOrders = orders.value.filter(o => o.type === 'delivering' && o.deliveryStatus === 4);
hasDeliveryOrders.value = deliveryOrders.length > 0;
if (hasDeliveryOrders.value) {
// 有待送达交接点的订单
batchModalTitle.value = '当前送达交接点订单数';
batchModalContent.value = `${deliveryOrders.length}`;
batchModalShow.value = true;
} else {
// 没有待送达交接点的订单
batchModalTitle.value = '';
batchModalContent.value = '暂无待送达交接点的订单';
batchModalShow.value = true;
}
}
// 批量送达交接点确认
function onBatchConfirm() {
// 筛选出配送中状态为待送达交接点的订单
const deliveryOrders = orders.value.filter(o => o.type === 'delivering' && o.deliveryStatus === 4);
batchOrderCount.value = deliveryOrders.length;
if (deliveryOrders.length > 0) {
// 关闭第一个弹框,打开异步操作弹框
batchModalShow.value = false;
batchLoadingModalTitle.value = '当前送达交接点订单数';
batchLoadingModalContent.value = `${deliveryOrders.length}`;
batchLoadingModalShow.value = true;
} else {
// 没有订单,直接关闭
batchModalShow.value = false;
}
}
// 批量送达交接点异步确认(真正执行批量操作)
async function onBatchLoadingConfirm() {
// 筛选出配送中状态为待送达交接点的订单ID
const deliveryOrderIds = orders.value
.filter(o => o.type === 'delivering' && o.deliveryStatus === 4)
.map(o => o.id);
if (deliveryOrderIds.length === 0) {
batchLoadingModalShow.value = false;
return;
}
try {
// 调用批量送达交接点接口ids 为逗号分隔的订单ID字符串
const res = await DeliveryOrderApi.riderDeliveryHandoverBatch(deliveryOrderIds.join(','));
if (res.code === 0 && res.data === true) {
// 关闭异步弹框
batchLoadingModalShow.value = false;
sheep.$helper.toast('批量送达交接点操作成功');
// 刷新订单列表
refreshOrders();
} else {
batchLoadingModalShow.value = false;
sheep.$helper.toast(res.msg || '批量送达交接点失败');
}
} catch (error) {
console.error('批量送达交接点异常:', error);
batchLoadingModalShow.value = false;
sheep.$helper.toast('批量送达交接点失败,请重试');
}
}
function onConfirmCode(payload) {
// payload 包含 code, result, remark, images
// 这里简单展示提示,实际应调用后端或触发下一步逻辑
@@ -328,6 +503,41 @@ function onConfirmCode(payload) {
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('交接已确认');
}
// 确认送达顾客
async function handleDeliveryConfirm(imageUrl) {
console.log('送达照片URL:', imageUrl);
if (!currentOrderForDelivery.value?.id) {
sheep.$helper.toast('订单信息异常');
return;
}
try {
const res = await DeliveryOrderApi.riderConfirmDelivery({
deliveryOrderId: currentOrderForDelivery.value.id,
imageUrl: imageUrl
});
if (res.code === 0 && res.data === true) {
sheep.$helper.toast('已提交送达照片');
showDeliveryPopup.value = false;
// 刷新订单列表
refreshOrders();
} else {
sheep.$helper.toast(res.msg || '提交失败');
}
} catch (error) {
console.error('确认送达异常:', error);
sheep.$helper.toast('提交失败,请重试');
}
}
// 打开确认送达顾客弹框
function openDeliveryPopup(order) {
currentOrderForDelivery.value = order;
showDeliveryPopup.value = true;
}
const headerStyle = ref({});
function setHeaderSafeArea() {
@@ -577,4 +787,45 @@ onShow(() => {
border-radius: 40rpx;
border: 1rpx solid #ddd;
}
.batch-operation {
background: #1e9fff;
color: #fff;
padding: 14rpx 20rpx;
border-radius: 40rpx;
font-weight: 500;
}
/* 催单弹框样式 */
.remind-popup {
padding: 20rpx 0;
}
.remind-row {
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx;
background: #f6f6f6;
margin: 10rpx 16rpx;
border-radius: 8rpx;
}
.remind-title {
font-size: 28rpx;
font-weight: 700;
color: #333;
}
.remind-btn {
background: #1e9fff;
color: #fff;
padding: 10rpx 18rpx;
border-radius: 8rpx;
font-weight: 700;
}
.remind-cancel {
text-align: center;
padding: 18rpx 0 70rpx;
color: #666;
font-size: 26rpx;
background: #fff;
margin-top: 10rpx;
}
</style>

View File

@@ -33,7 +33,7 @@
</view>
<view class="stats-item">
<text class="stats-title">今日完成单量</text>
<text class="stats-value"> {{ todayOrders }} </text>
<text class="stats-value"> {{ formatMoney(todayOrders) }} </text>
<view class="stats-link" @tap="sheep.$router.go('/pages/user/order/orderRecord')">
订单统计 <uni-icons type="right" size="13"></uni-icons>
</view>