Files
delivery-uniapp/pages/index/components/order-code-popup.vue
2026-01-24 17:45:54 +08:00

354 lines
7.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<up-popup :show="show" mode="center" :round="5" safeAreaInsetBottom @close="onClose" :closeable="true">
<view class="popup-wrap" style="width:680rpx;">
<!-- 标题 -->
<view class="popup-header">
<text class="title">催单</text>
<text class="order-no">#{{ orderIndex }}</text>
</view>
<!-- 查询输入 -->
<view class="search-row">
<view style="width:620rpx;">
<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>
</view>
</view>
<!-- 取货点 -->
<view class="section">
<view class="section-title">
<text class="icon">🏬</text>
<text class="text">取货点店铺名称</text>
</view>
<text class="muted">{{ pickupName }}</text>
</view>
<!-- 送餐地址 -->
<view class="section">
<view class="section-title">
<text class="icon">🚩</text>
<text class="text">送餐详细地址</text>
</view>
<text class="muted">{{ address }}</text>
<view class="recipient">收货人名称先生 尾号{{ recipientTail }}</view>
</view>
<!-- 客户备注 -->
<view class="customer-note">
<text>顾客{{ customerNote }}</text>
</view>
<!-- 交接备注 下拉 -->
<view class="form-row">
<text class="label">交接备注</text>
<picker :range="remarks" @change="onRemarkChange">
<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>
</view>
<!-- 底部操作 -->
<view class="footer-row">
<up-button type="success" text="联系上一个骑手" icon="phone" @click="callPhone('13131008612')"></up-button>
<view style="margin-left:15rpx;width:600rpx;">
<up-button type="primary" text="确认交接" @click="onConfirm"></up-button>
</view>
</view>
</view>
</up-popup>
</template>
<script setup>
import {
ref,
reactive,
computed
} from 'vue'
const props = defineProps({
show: {
type: Boolean,
default: false
}
})
const emit = defineEmits(['close', 'confirm'])
// 响应式数据
const orderIndex = ref(1)
const orderCode = ref('')
const pickupName = ref('取货店铺详细地址广东省广州市天河区学院站荷光路')
const address = ref('送餐详细地址广东省广州市天河区华景新城软件园区A栋303室')
const recipientTail = ref('1254')
const customerNote = ref('依据餐量提供餐具')
const remarks = ['请选择 备注内容', '已核对身份证', '缺少配件', '地址异常']
const selectedRemark = ref(0)
const selectedRemarkText = computed(() => remarks[selectedRemark.value] || '')
const proofImages = ref([])
// 方法
const onClose = () => {
emit('close')
}
const queryOrder = () => {
// 简单模拟查询:如果输入有内容则把 orderIndex 加 1 并回填部分数据
if (!orderCode.value) {
uni.showToast({
title: '请输入查询条件',
icon: 'none'
})
return
}
orderIndex.value += 1
// 这里可以调用接口查询并填充 pickupName/address 等
uni.showToast({
title: '查询成功',
icon: 'success'
})
}
// 拨打电话
const callPhone = (phone) => {
if (!phone) {
sheep.$helper && sheep.$helper.toast && sheep.$helper.toast('未找到联系电话');
return;
}
uni.makePhoneCall({
phoneNumber: phone
});
}
const onRemarkChange = (e) => {
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 removeProofImage = (idx) => {
proofImages.value.splice(idx, 1)
}
const onConfirm = () => {
// 校验凭证
if (proofImages.value.length === 0) {
uni.showToast({
title: '请上传凭证',
icon: 'none'
})
return
}
const payload = {
orderIndex: orderIndex.value,
orderCode: orderCode.value,
remark: selectedRemarkText.value,
proofImages: proofImages.value
}
emit('confirm', payload)
}
</script>
<style scoped>
.popup-wrap {
padding: 24rpx;
background: #fff;
border-radius: 12rpx;
}
.popup-header {
display: flex;
justify-content: center;
align-items: center;
margin-bottom: 18rpx;
}
.title {
color: #00a0df;
font-size: 30rpx;
font-weight: 700;
margin-right: 8rpx;
}
.order-no {
color: #666;
font-size: 24rpx;
}
.search-row {
display: flex;
align-items: center;
margin-bottom: 16rpx;
}
.search-input {
flex: 1;
height: 64rpx;
border: 1rpx solid #ddd;
padding: 0 20rpx;
border-radius: 6rpx;
}
.search-btn {
width: 120rpx;
height: 64rpx;
font-size: 22rpx;
background: #fff;
border-left: 1rpx solid #ddd;
}
.section {
padding: 12rpx 0;
border-top: 1rpx solid #f0f0f0;
}
.section-title {
display: flex;
align-items: center;
margin-bottom: 8rpx;
}
.section-title .icon {
margin-right: 12rpx;
font-size: 26rpx;
}
.section-title .text {
font-weight: 700;
font-size: 26rpx;
}
.muted {
color: #666;
font-size: 22rpx;
}
.recipient {
color: #999;
font-size: 20rpx;
margin-top: 6rpx;
}
.customer-note {
background: #f7f7f7;
padding: 12rpx;
border-radius: 6rpx;
margin: 12rpx 0;
color: #666;
}
.form-row {
display: flex;
align-items: center;
margin: 12rpx 0;
}
.label {
width: 180rpx;
color: #333;
}
.required {
color: #e53935;
}
.picker-display {
flex: 1;
height: 64rpx;
line-height: 64rpx;
border: 1rpx solid #e6e6e6;
padding: 0 12rpx;
border-radius: 6rpx;
}
.proof-row .proof-list {
display: flex;
align-items: center;
}
.proof-item {
position: relative;
width: 140rpx;
height: 140rpx;
margin-right: 14rpx;
}
.proof-img {
width: 100%;
height: 100%;
border-radius: 6rpx;
}
.remove {
position: absolute;
right: 4rpx;
top: 4rpx;
background: rgba(0, 0, 0, 0.5);
color: #fff;
padding: 2rpx 6rpx;
border-radius: 10rpx;
font-size: 20rpx;
}
.proof-add {
width: 140rpx;
height: 140rpx;
border: 1rpx dashed #ddd;
display: flex;
justify-content: center;
align-items: center;
font-size: 48rpx;
color: #999;
border-radius: 6rpx;
}
.footer-row {
display: flex;
justify-content: space-between;
align-items: center;
margin-top: 18rpx;
}
.phone-area {
display: flex;
align-items: center;
color: #333;
}
.phone-icon {
font-size: 30rpx;
margin-right: 8rpx;
}
.confirm-btn {
background: #0a99e6;
color: #fff;
padding: 14rpx 32rpx;
border-radius: 8rpx;
}
</style>