750 lines
20 KiB
Vue
Raw Normal View History

2025-05-08 09:16:37 +08:00
<template>
<view class="whole">
<view class="addrbox">
<view class="item" v-if="loading">
<view class="icon ji"></view>
<view v-if="addressList.length != 0" class="addr addr1" @click="showAddr = true">
<view class="box">
<view class="tit">{{sender.name || ''}}&nbsp;&nbsp;{{sender.mobile || ''}}</view>
<text>{{sender.province && sender.province.name || ''}}{{sender.city && sender.city.name || ''}}{{sender.area && sender.area.name || ''}}{{sender.address || ''}}</text>
</view>
<up-icon name="arrow-right" />
</view>
<view v-else class="empty" @click="toAddress()">
<text>您还没有地址信息</text>
<view class="add">去添加地址</view>
</view>
</view>
<view class="item">
<view class="icon"></view>
<view class="addr">
<view class="box">
<view class="tit">{{refundInfo.refund_address_name}}&nbsp;&nbsp;{{refundInfo.refund_address_mobile || refundInfo.refund_address_tel}}</view>
<text>{{refundInfo.refund_address_province_name}}{{refundInfo.refund_address_city_name}}{{refundInfo.refund_address_area_name}}{{refundInfo.refund_address_detail}}</text>
</view>
</view>
</view>
</view>
<view class="timebox" @click="showSendType = true">
<view>寄件类型
<text v-if="sendType === ''">请选择寄件类型</text>
<text v-else>{{sendTypeObj[sendType]}}</text>
</view>
<up-icon name="arrow-right" />
</view>
<view class="timebox" @click="openTime()">
<view>上门时间
<text v-if="dateIndex === '' || timeIndex === ''">请选择上门取件时间</text>
<text v-else>{{dateList[dateIndex]}}&nbsp;&nbsp;{{timeList[timeIndex]}}</text>
</view>
<up-icon name="arrow-right" />
</view>
<view class="bottom">
<view class="btn" @click="toSendDetail()">立即提交</view>
</view>
<!-- 寄件类型 -->
<up-popup :show="showSendType" :round="10" mode="bottom" close-on-click-overlay closeable @close="showSendType = false">
<view class="reasonbox">
<view class="title">请选择寄件类型</view>
<view class="box">
<view class="row" v-for="(item, index) in sendTypeList" @click="selectSendType(item.id)">
<view class="tit">{{item.name}}</view>
<span v-if="sendType === item.id" class="iconfont icon-checked"></span>
<span v-else class="iconfont icon-circle"></span>
</view>
</view>
</view>
</up-popup>
<!-- 选择寄件地址 -->
<up-popup v-model:show="showAddr" :round="10" mode="bottom" close-on-click-overlay closeable @close="showAddr = false">
<view class="typebox">
<view class="title">选择寄件地址</view>
<view class="box">
<view class="row" v-for="item in addressList" @click="selectAddr(item)">
<view>
<view class="tit">{{item.name}}&nbsp;&nbsp;{{item.mobile}}</view>
<text>{{item.province.name}}{{item.city.name}}{{item.area.name}}{{item.address}}</text>
</view>
<span v-if="sender.id === item.id" class="iconfont icon-checked"></span>
<span v-else class="iconfont icon-circle"></span>
</view>
</view>
<view class="btn" @click="toAddress()">添加地址</view>
</view>
</up-popup>
<!-- 选择上门时间 -->
<up-popup v-model:show="showTime" :round="10" mode="bottom" close-on-click-overlay closeable @close="closeTime()">
<view class="timepopup">
<view class="title">选择上门时间</view>
<view class="box">
<view class="date">
<view class="row"
v-for="(it, index) in dateList" :key="index"
@click="selectDate(it, index)"
:class="index === dateIndex ? 'select': ''">{{it}}
</view>
</view>
<view class="time">
<view class="row"
v-for="(it, index) in timeList" :key="index"
@click="selectTime(it, index)"
:class="index === timeIndex ? 'select': ''"
>
<text>{{it}}</text>
<up-icon v-if="index === timeIndex" name="checkbox-mark" :color="Color" />
</view>
</view>
</view>
</view>
</up-popup>
<up-modal
:show="showTips"
title="您好,您有多个收件地址"
confirmText="确认"
cancelText="返回修改"
:confirmColor="Color"
:showCancelButton="true"
content="请确认取件地址是否正确"
@confirm="confirmBack()"
@cancel="showTips = false">
</up-modal>
</view>
</template>
<script>
import { ref, reactive, toRefs, watch } from 'vue'
import { get, post } from '@/api/request.js'
import { showToast, getShopInfo } from '@/components/common.js'
import { sendTypeObj, sendTypeList } from '@/utils/list.js'
export default {
setup() {
const data = reactive({
refund_id: '',
pickup_id: '',
sender: {
province: {},
city: {},
area: {}
},
refundInfo: {},
addressList: [],
showTime: false,
showAddr: false,
dateList: [],
timeObj: {},
timeList: [],
dateIndex: '',
timeIndex: '',
sendType: '',
showSendType: false,
tempData: [],
loading: false,
pickTimeObj: {
date: '',
start: '',
end: ''
},
Color: uni.getStorageSync('theme_color'),
showTips: false,
item_ids: [],
driver: '',
puInfo: {}
})
async function getAddressList() {
await get('/api/v1/address').then((res) => {
if(!data.pickup_id) {
data.sender = res.data && JSON.parse(JSON.stringify(res.data[0])) || {}
res.data.forEach((item) => {
if (item.is_default === 1) {
data.sender = JSON.parse(JSON.stringify(item))
}
})
}
data.addressList = res.data
data.loading = true
}).catch(() => {
data.loading = true
})
}
// 获取订单信息
async function getRefundInfo() {
await get(`/api/v1/orderRefundApply/${data.refund_id}`).then((res) => {
data.refundInfo = res.data
res.data.refunds.forEach((it) => {
data.item_ids.push({
order_item_id: it.order_item_id,
number: 1
})
})
})
}
// 获取寄货时间
async function getSendTime(type = '') {
data.dateList = []
data.timeList = []
data.timeObj = {}
data.dateIndex = ''
data.timeIndex = ''
if(data.driver == 'jd') {
let params = {
sender: {
name: data.sender.name,
mobile: data.sender.mobile,
province_name: data.sender.province.name,
province_id: data.sender.province_id,
city_name: data.sender.city.name,
city_id: data.sender.area_id,
area_name: data.sender.area.name,
area_id: data.sender.area_id,
address_detail: data.sender.address
},
receiver: {
name: data.refundInfo.refund_address_name,
mobile: data.refundInfo.refund_address_mobile,
province_name: data.refundInfo.refund_address_province_name,
province_id: data.refundInfo.refund_address_province_id,
city_name: data.refundInfo.refund_address_city_name,
city_id: data.refundInfo.refund_address_city_id,
area_name: data.refundInfo.refund_address_area_name,
area_id: data.refundInfo.refund_address_area_id,
address_detail: data.refundInfo.refund_address_detail
},
driver: data.driver,
consign_type: data.sendType || 1,
weight: 1,
order_item_ids: data.item_ids,
use_mode: 0
}
await post('/api/v1/pickup/check/price', params).then((res) => {
if(res.data.pickupSliceTimes && res.data.pickupSliceTimes.length) {
let List = JSON.parse(JSON.stringify(res.data.pickupSliceTimes))
List.reverse()
List.forEach((item) => {
data.dateList.push(item.dateKey)
data.timeObj[item.dateKey] = []
item.pickupSliceTimes.forEach((it) => {
data.timeObj[item.dateKey].push(it.startTime + '-' + it.endTime)
})
})
data.timeList = data.timeObj[data.dateList[0]] || []
if(data.pickup_id && type) {
data.dateIndex = data.dateList.indexOf(data.pickTimeObj.date)
data.timeList = data.timeObj[data.pickTimeObj.date] || []
data.timeIndex = data.timeList.indexOf(data.pickTimeObj.start + '-' + data.pickTimeObj.end)
if(data.dateIndex == -1 || data.timeIndex == -1) {
data.dateIndex = data.timeIndex = ''
data.timeList = data.timeObj[data.dateList[0]] || []
}
}
}
})
} else {
let params = {
sender: {
province_name: data.sender.province.name,
city_name: data.sender.city.name,
area_name: data.sender.area.name,
address_detail: data.sender.address
},
receiver: {
province_name: data.refundInfo.refund_address_province_name,
city_name: data.refundInfo.refund_address_city_name,
area_name: data.refundInfo.refund_address_area_name,
address_detail: data.refundInfo.refund_address_detail
}
}
await post('/api/v1/pickup/check/area', params).then((res) => {
res.data.forEach((item) => {
let date = item.start_time.split(' ')[0] // 2022-09-26
let start = item.start_time.split(' ')[1] // 15:00:00
let end = item.end_time.split(' ')[1] // 17:00:00
if (data.dateList.indexOf(date) === -1) {
data.dateList.push(date)
data.timeObj[date] = []
data.timeObj[date].push(start + '-' + end)
} else {
data.timeObj[date].push(start + '-' + end)
}
})
data.timeList = data.timeObj[data.dateList[0]] || []
if(data.pickup_id && type) {
data.dateIndex = data.dateList.indexOf(data.pickTimeObj.date)
data.timeList = data.timeObj[data.pickTimeObj.date] || []
data.timeIndex = data.timeList.indexOf(data.pickTimeObj.start + '-' + data.pickTimeObj.end)
if(data.dateIndex == -1 || data.timeIndex == -1) {
data.dateIndex = data.timeIndex = ''
data.timeList = data.timeObj[data.dateList[0]] || []
}
}
})
}
}
async function selectAddr(item) {
data.sender = item
await getSendTime()
data.showAddr = false
}
function openTime() {
if(Object.keys(data.sender).length === 0) {
showToast('请先添加寄件地址')
return false
}
data.showTime = true
}
function selectDate(it ,index) {
data.dateIndex = index
data.timeList = data.timeObj[data.dateList[data.dateIndex]]
}
function selectTime(it ,index) {
if(data.dateIndex === '') {
data.dateIndex = 0
}
data.timeIndex = index
data.showTime = false
}
function toAddress() {
data.showAddr = false
uni.navigateTo({
url: '/pages/address/info/index'
})
}
// 如果是修改寄件,获取寄件详情
function getPickupInfo() {
get(`/api/v1/pickup/${data.pickup_id}`).then((res) => {
data.puInfo = res.data
// 寄件人信息
data.sender.name = res.data.sender_name
data.sender.mobile = res.data.sender_mobile
data.sender.province.name = res.data.sender_province_name
data.sender.province_id = res.data.sender_province_id
data.sender.city.name = res.data.sender_city_name
data.sender.city_id = res.data.sender_city_id
data.sender.area.name = res.data.sender_area_name
data.sender.area_id = res.data.sender_area_id
data.sender.address = res.data.sender_address_detail
// 收件人信息
data.refundInfo.refund_address_province_id = res.data.receiver_province_id
data.refundInfo.refund_address_city_id = res.data.receiver_city_id
data.refundInfo.refund_address_name = res.data.receiver_name
data.refundInfo.refund_address_area_id = res.data.receiver_area_id
data.refundInfo.refund_address_mobile = res.data.receiver_mobile
data.refundInfo.refund_address_tel = res.data.receiver_tel
data.refundInfo.refund_address_province_name = res.data.receiver_province_name
data.refundInfo.refund_address_city_name = res.data.receiver_city_name
data.refundInfo.refund_address_area_name = res.data.receiver_area_name
data.refundInfo.refund_address_detail = res.data.receiver_address_detail
data.sendType = res.data.consign_type
data.pickTimeObj.date = res.data.start_date.split(' ')[0]
data.pickTimeObj.start = res.data.start_date.split(' ')[1]
data.pickTimeObj.end = res.data.end_date.split(' ')[1]
})
}
function toSendDetail() {
if(data.sendType === '') {
showToast('请选择寄件类型')
return false
}
if(data.dateIndex === '' || data.timeIndex === '') {
showToast('请选择上门取件时间')
return false
}
if(data.addressList.length > 1) {
data.showTips = true
} else {
confirmBack()
}
}
function confirmBack() {
uni.showLoading({
title: '正在提交...',
mask: true
})
let params = {
order_refund_apply_id: data.refund_id,
start_date: data.dateList[data.dateIndex] + ' ' + data.timeList[data.timeIndex].split('-')[0],
end_date: data.dateList[data.dateIndex] + ' ' + data.timeList[data.timeIndex].split('-')[1],
consign_type: data.sendType,
sender: {
address: '',
province_id: data.sender.province_id,
city_id: data.sender.city_id,
name: data.sender.name,
area_id: data.sender.area_id,
mobile: data.sender.mobile,
tel: '',
province_name: data.sender.province.name,
city_name: data.sender.city.name,
area_name: data.sender.area.name,
address_detail: data.sender.address
},
receiver: {
address: '',
province_id: data.refundInfo.refund_address_province_id,
city_id: data.refundInfo.refund_address_city_id,
name: data.refundInfo.refund_address_name,
area_id: data.refundInfo.refund_address_area_id,
mobile: data.refundInfo.refund_address_mobile,
tel: data.refundInfo.refund_address_tel,
province_name: data.refundInfo.refund_address_province_name,
city_name: data.refundInfo.refund_address_city_name,
area_name: data.refundInfo.refund_address_area_name,
address_detail: data.refundInfo.refund_address_detail
},
driver: data.driver
}
if(data.pickup_id) {
post('/api/v1/pickup/' + data.pickup_id, params, 'PUT').then((res) => {
uni.hideLoading()
wx.navigateBack({
delta: 1
})
})
} else {
post('/api/v1/pickup', params).then((res) => {
uni.hideLoading()
wx.navigateBack({
delta: 1
})
})
}
}
function selectSendType(id) {
data.sendType = id
data.showSendType = false
}
const address = ref(null)
watch(address, (newValue, oldValue) => {
get('/api/v1/address').then((res) => {
res.data.forEach((item) => {
if (item.id === newValue.id) {
data.sender = item
}
})
data.addressList = res.data
})
})
watch(() => data.showTime, (next) => {
if(next) {
data.tempData = [data.dateIndex, data.timeIndex]
}
}, { deep: true, })
function closeTime() {
data.dateIndex = data.tempData[0]
data.timeIndex = data.tempData[1]
data.showTime = false
}
async function getStoreInfo() {
let res = await getShopInfo()
data.driver = res.pickup_default_type
if(data.pickup_id) {
data.driver = data.puInfo.driver
}
getSendTime('init')
}
return {
sendTypeObj,
sendTypeList,
...toRefs(data),
selectDate,
selectTime,
selectAddr,
openTime,
toAddress,
toSendDetail,
getAddressList,
getRefundInfo,
getSendTime,
selectSendType,
address,
closeTime,
getPickupInfo,
getStoreInfo,
confirmBack
}
},
async onLoad(options) {
uni.showLoading({
title: '加载中...',
mask: true
})
this.refund_id = options.refund_id
await this.getAddressList()
await this.getRefundInfo()
if(options.pickup_id) {
this.pickup_id = options.pickup_id
await this.getPickupInfo()
}
uni.hideLoading()
setTimeout(() => {
this.getStoreInfo()
}, 1500)
}
}
</script>
<style lang="scss" scoped>
.whole {
.addrbox{
padding: 0 30rpx;
background: #fff;
.item{
display: flex;
align-items: center;
justify-content: space-between;
.addr{
width: calc(100% - 60rpx);
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx 0;
&.addr1{
border-bottom: 1rpx solid #e5e5e5;
}
.box{
.tit{
color: #000;
font-size: 30rpx;
}
text{
color: #7B7B7B;
font-size: 26rpx;
}
}
}
.icon{
color: #fff;
font-size: 24rpx;
width: 40rpx;
height: 40rpx;
display: flex;
align-items: center;
justify-content: center;
background: #7B7B7B;
border-radius: 50%;
&.ji{
background: #F14939;
position: relative;
&::after{
width: 0;
height: 100rpx;
content: '';
position: absolute;
border-left: 1rpx dashed #E5E5E5;
left: 20rpx;
top: 42rpx;
}
}
}
}
.empty{
width: calc(100% - 60rpx);
text-align: center;
padding: 10rpx 0;
text{
font-size: 24rpx;
color: #7B7B7B;
}
.add{
width: 60%;
margin: 20rpx auto 0;
height: 55rpx;
border: 1rpx dashed v-bind('Color');
font-size: 24rpx;
display: flex;
align-items: center;
justify-content: center;
color: v-bind('Color');
}
}
}
.timebox{
font-size: 30rpx;
color: #7B7B7B;
padding: 40rpx 30rpx;
background: #fff;
margin-top: 20rpx;
display: flex;
align-items: center;
justify-content: space-between;
text{
color: #000;
margin-left: 30rpx;
}
}
.bottom{
position: fixed;
left: 0;
bottom: 20rpx;
width: 100%;
padding: 0 30rpx;
z-index: 10;
box-sizing: border-box;
.btn{
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
width: 100%;
color: #fff;
border-radius: 80rpx;
background: v-bind('Color');
}
}
}
// 寄件地址弹窗
.typebox{
padding: 0 30rpx 20rpx;
.title{
font-size: 30rpx;
color: #303030;
font-weight: bold;
padding: 30rpx 0;
border-bottom: 1rpx solid #E5E5E5;
}
.box{
min-height: 40vh;
max-height: 66vh;
overflow: auto;
padding-bottom: 70rpx;
.row{
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1rpx solid #E5E5E5;
padding: 20rpx 0;
.tit{
font-size: 30rpx;
color: #303030;
margin-bottom: 6rpx;
}
text{
font-size: 26rpx;
color: #999;
}
}
}
.btn{
height: 80rpx;
display: flex;
align-items: center;
justify-content: center;
font-size: 30rpx;
width: 100%;
border-radius: 80rpx;
box-sizing: border-box;
border: 1rpx solid v-bind('Color');
color: v-bind('Color');
background: #fff;
}
}
.timepopup{
padding: 0 30rpx;
.title{
font-size: 30rpx;
color: #303030;
font-weight: bold;
padding: 30rpx 0;
border-bottom: 1rpx solid #E5E5E5;
}
.box{
overflow: hidden;
display: flex;
justify-content: space-between;
.date{
width: 200rpx;
height: 70vh;
overflow: auto;
.row{
padding: 30rpx 0;
font-size: 30rpx;
color: #303030;
&.select{
color: v-bind('Color');
}
}
}
.time{
width: calc(100% - 250rpx);
height: 70vh;
overflow: auto;
.row{
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx 0;
font-size: 30rpx;
color: #303030;
&.select{
color: v-bind('Color');
}
}
}
}
}
.reasonbox{
padding: 0 30rpx;
min-height: 50vh;
.title{
font-size: 30rpx;
color: #303030;
font-weight: bold;
padding: 30rpx 0;
border-bottom: 1rpx solid #E5E5E5;
}
.box{
padding-bottom: 100rpx;
.row{
display: flex;
align-items: center;
justify-content: space-between;
padding: 20rpx 0;
.tit{
font-size: 28rpx;
color: #707070;
}
}
}
}
.iconfont{
font-size: 20px;
}
.icon-checked{
color: v-bind('Color');
}
.icon-circle{
color: #999;
}
</style>