<template>
|
<view class="edit-address-page">
|
<!-- 订单信息 -->
|
<view class="order-info">
|
<view class="order-title">订单信息</view>
|
<view class="order-sn">订单号:{{ orderDetail.order.sn || '' }}</view>
|
|
<!-- 商品列表 -->
|
<view class="goods-list">
|
<view class="goods-item" v-for="item in orderDetail.orderItems" :key="item.id">
|
<image class="goods-image" :src="item.image" mode="aspectFill"></image>
|
<view class="goods-info">
|
<view class="goods-name">{{ item.goodsName }}</view>
|
<view class="goods-price-qty">
|
<text class="price">¥{{ item.flowPrice }}</text>
|
<text class="qty">x{{ item.num }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</view>
|
|
<!-- 地址填写表单 -->
|
<view class="address-form">
|
<view class="form-title">配送地址</view>
|
|
<view class="form-item">
|
<text class="label">收货人</text>
|
<input class="input" v-model="addressForm.consigneeName" placeholder="请输入收货人姓名" />
|
</view>
|
|
<view class="form-item">
|
<text class="label">联系电话</text>
|
<input class="input" v-model="addressForm.consigneeMobile" placeholder="请输入联系电话" type="number" />
|
</view>
|
|
<view class="form-item">
|
<text class="label">所在地区</text>
|
<view class="picker-text" @click="showPicker">
|
{{ addressForm.___path || '请选择所在地区' }}
|
</view>
|
</view>
|
|
<view class="form-item">
|
<text class="label">详细地址</text>
|
<textarea class="textarea" v-model="addressForm.consigneeDetail"
|
placeholder="请输入详细地址(如街道、门牌号等)"></textarea>
|
</view>
|
</view>
|
|
<!-- 提交按钮(已适配安全区域) -->
|
<view class="submit-btn" @tap="submitAddress">保存地址</view>
|
|
<!-- 地址选择组件 -->
|
<m-city :provinceData="list" headTitle="区域选择" ref="cityPicker" @funcValue="getpickerParentValue" pickerSize="4">
|
</m-city>
|
</view>
|
</template>
|
|
<script>
|
import {
|
getOrderDetailEdit
|
} from '@/api/order.js'
|
import {
|
http
|
} from '@/utils/request.js'
|
import '@/components/uview-components/uview-ui';
|
import city from "../m-city/m-city.vue";
|
export default {
|
components: {
|
"m-city": city
|
},
|
data() {
|
return {
|
orderSn: '', // 订单编号
|
orderDetail: {
|
orderItems: []
|
}, // 订单详情
|
addressForm: {
|
consigneeName: '',
|
consigneeMobile: '',
|
consigneeAddressPath: '',
|
consigneeAddressIdPath: '',
|
consigneeDetail: '',
|
___path: '' // 显示用的地区文本
|
},
|
regionData: [
|
[],
|
[],
|
[]
|
], // 省市区数据
|
regionIndex: [0, 0, 0], // 选中的索引
|
regionText: '', // 显示的地区文本
|
regionCodes: [], // 地区编码
|
list: [{
|
id: "",
|
localName: "请选择",
|
children: [],
|
}, ]
|
}
|
},
|
onShow(){
|
console.log('触发onShow-------------------------->',this.orderSn)
|
this.loadOrderDetail()
|
},
|
onLoad(options) {
|
console.log('页面参数:', options)
|
if (options.q) {
|
// 双重解码:微信对URL进行了两次编码
|
const decodedUrl = decodeURIComponent(decodeURIComponent(options.q));
|
console.log('原始URL:', decodedUrl);
|
|
// 解析URL中的查询参数
|
const params = this.parseUrlParams(decodedUrl);
|
this.orderSn = params.orderSn;
|
this.loadOrderDetail()
|
}
|
},
|
methods: {
|
// 安全的toast方法,适配小程序环境
|
safeShowToast(options) {
|
// 确保loading和之前的toast已关闭
|
uni.hideLoading();
|
uni.hideToast();
|
// 使用nextTick确保在下一个事件循环中执行
|
this.$nextTick(() => {
|
uni.showToast({
|
...options,
|
duration: options.duration || 2000
|
});
|
});
|
},
|
|
// 解析URL参数
|
parseUrlParams(url) {
|
const params = {};
|
// 处理可能存在的hash(如果有的话)
|
const cleanUrl = url.split('#')[0];
|
const queryStr = cleanUrl.split('?')[1] || '';
|
|
queryStr.split('&').forEach(pair => {
|
const [key, value] = pair.split('=');
|
if (key) {
|
// 如果值存在,则解码,否则设为空字符串
|
params[key] = value ? decodeURIComponent(value) : '';
|
}
|
});
|
|
return params;
|
},
|
// 加载订单详情
|
async loadOrderDetail() {
|
if (!this.orderSn) {
|
console.log('订单号为空,无法加载订单详情');
|
this.safeShowToast({
|
title: '订单号不能为空',
|
icon: 'none'
|
});
|
return;
|
}
|
|
let loadingShown = false;
|
try {
|
uni.showLoading({
|
title: '加载中...'
|
});
|
loadingShown = true;
|
|
console.log('开始请求订单详情,订单号:', this.orderSn);
|
const res = await getOrderDetailEdit(this.orderSn);
|
console.log('----------获取订单返回结果------------->',res);
|
|
// 检查响应状态
|
if (res && res.data) {
|
if (res.data.success) {
|
this.orderDetail = res.data.result;
|
console.log('----------------------->订单数据', JSON.stringify(this.orderDetail));
|
} else {
|
console.log('API返回失败:', res.data.message);
|
// 先关闭loading再显示toast
|
uni.hideLoading();
|
loadingShown = false;
|
this.safeShowToast({
|
title: res.data.message || '获取订单信息失败',
|
icon: 'none'
|
});
|
}
|
} else {
|
console.log('服务器响应异常:', res);
|
uni.hideLoading();
|
loadingShown = false;
|
this.safeShowToast({
|
title: '服务器响应异常',
|
icon: 'none'
|
});
|
}
|
} catch (error) {
|
console.error('获取订单详情失败:', error);
|
// 网络异常或其他错误
|
if (loadingShown) {
|
uni.hideLoading();
|
loadingShown = false;
|
}
|
this.safeShowToast({
|
title: '网络异常,请稍后重试',
|
icon: 'none'
|
});
|
} finally {
|
// 确保loading被关闭
|
if (loadingShown) {
|
uni.hideLoading();
|
}
|
}
|
},
|
|
// 地区选择改变
|
async onColumnChange(e) {
|
const {
|
column,
|
value
|
} = e.detail
|
this.regionIndex[column] = value
|
|
if (column === 0) {
|
// 选择省份时,加载城市数据
|
const provinceId = this.regionData[0][value].id
|
try {
|
const cityRes = await http.request({
|
url: '/common/common/region/tree',
|
method: 'GET',
|
params: {
|
parentId: provinceId
|
}
|
})
|
if (cityRes.data.success) {
|
this.regionData[1] = cityRes.data.result.map(item => ({
|
name: item.name,
|
id: item.id
|
}))
|
this.regionData[2] = []
|
this.regionIndex[1] = 0
|
this.regionIndex[2] = 0
|
}
|
} catch (error) {
|
console.error('加载城市数据失败:', error)
|
}
|
} else if (column === 1) {
|
// 选择城市时,加载区县数据
|
const cityId = this.regionData[1][value].id
|
try {
|
const areaRes = await http.request({
|
url: '/common/common/region/tree',
|
method: 'GET',
|
params: {
|
parentId: cityId
|
}
|
})
|
if (areaRes.data.success) {
|
this.regionData[2] = areaRes.data.result.map(item => ({
|
name: item.name,
|
id: item.id
|
}))
|
this.regionIndex[2] = 0
|
}
|
} catch (error) {
|
console.error('加载区县数据失败:', error)
|
}
|
}
|
},
|
|
// 地区选择确认
|
onRegionChange(e) {
|
const {
|
value
|
} = e.detail
|
this.regionIndex = value
|
|
const province = this.regionData[0][value[0]]
|
const city = this.regionData[1][value[1]]
|
const area = this.regionData[2][value[2]]
|
|
if (province && city && area) {
|
this.regionText = `${province.name} ${city.name} ${area.name}`
|
this.addressForm.consigneeAddressIdPath = `${province.id},${city.id},${area.id}`
|
}
|
},
|
|
// 显示地址选择器
|
showPicker() {
|
this.$nextTick(() => {
|
if (this.$refs.cityPicker) {
|
this.$refs.cityPicker.show();
|
}
|
});
|
},
|
|
// 地址选择回调
|
getpickerParentValue(e) {
|
// 将需要绑定的地址设置为空,并赋值
|
this.addressForm.consigneeAddressIdPath = '';
|
let name = "";
|
let idPath = [];
|
let namePath = []
|
|
e.forEach((item, index) => {
|
if (item.id) {
|
// 遍历数据
|
idPath.push(item.id);
|
namePath.push(item.localName);
|
name += item.localName;
|
this.addressForm.___path = name;
|
}
|
});
|
|
// 设置地址路径
|
this.addressForm.consigneeAddressIdPath = idPath.join(',');
|
this.addressForm.consigneeAddressPath = namePath.join(',');
|
},
|
|
// 提交地址
|
async submitAddress() {
|
// 表单验证
|
if (!this.addressForm.consigneeName) {
|
uni.showToast({
|
title: '请输入收货人姓名',
|
icon: 'none'
|
})
|
return
|
}
|
if (!this.addressForm.consigneeMobile) {
|
uni.showToast({
|
title: '请输入联系电话',
|
icon: 'none'
|
})
|
return
|
}
|
if (!/^1[3-9]\d{9}$/.test(this.addressForm.consigneeMobile)) {
|
uni.showToast({
|
title: '请输入正确的手机号',
|
icon: 'none'
|
})
|
return
|
}
|
if (!this.addressForm.consigneeAddressIdPath || !this.addressForm.___path) {
|
uni.showToast({
|
title: '请选择所在地区',
|
icon: 'none'
|
})
|
return
|
}
|
if (!this.addressForm.consigneeDetail) {
|
uni.showToast({
|
title: '请输入详细地址',
|
icon: 'none'
|
})
|
return
|
}
|
|
try {
|
uni.showLoading({
|
title: '保存中...'
|
})
|
console.log('-------------------->', JSON.stringify(this.addressForm))
|
// 提交地址到订单(注释部分为实际接口调用逻辑)
|
const res = await http.request({
|
url: `/order/order/update/editAddress/${this.orderSn}/consignee`,
|
method: 'POST',
|
needToken: true,
|
data: this.addressForm
|
})
|
console.log("地址保存")
|
if (res.data.success) {
|
// uni.showToast({
|
// title: '地址保存成功',
|
// icon: 'success'
|
// })
|
uni.redirectTo({
|
url:'/pages/tabbar/index/home',
|
fail(e) {
|
console.log("跳转失败原因",e)
|
}
|
})
|
} else {
|
uni.showToast({
|
title: res.data.message || '保存失败',
|
icon: 'none'
|
})
|
}
|
} catch (error) {
|
console.error('提交地址失败:', error)
|
uni.showToast({
|
title: '保存失败,请重试',
|
icon: 'none'
|
})
|
} finally {
|
uni.hideLoading()
|
}
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
/* 根容器:底部内边距适配按钮+安全区域 */
|
.edit-address-page {
|
background-color: #f5f5f5;
|
min-height: 100vh;
|
/* 按钮高度(100rpx) + 安全区域高度 + 额外间距(20rpx),避免内容被按钮遮挡 */
|
padding-bottom: calc(100rpx + 20rpx + constant(safe-area-inset-bottom));
|
padding-bottom: calc(100rpx + 20rpx + env(safe-area-inset-bottom));
|
}
|
|
/* 订单信息区域 */
|
.order-info {
|
background: white;
|
margin: 20rpx;
|
padding: 30rpx;
|
border-radius: 16rpx;
|
}
|
|
.order-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
margin-bottom: 20rpx;
|
color: #333;
|
}
|
|
.order-sn {
|
font-size: 28rpx;
|
color: #666;
|
margin-bottom: 30rpx;
|
}
|
|
/* 商品列表 */
|
.goods-item {
|
display: flex;
|
align-items: center;
|
padding: 20rpx 0;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
.goods-item:last-child {
|
border-bottom: none;
|
}
|
|
.goods-image {
|
width: 120rpx;
|
height: 120rpx;
|
border-radius: 12rpx;
|
margin-right: 20rpx;
|
}
|
|
.goods-info {
|
flex: 1;
|
}
|
|
.goods-name {
|
font-size: 28rpx;
|
color: #333;
|
margin-bottom: 10rpx;
|
line-height: 1.4;
|
}
|
|
.goods-price-qty {
|
display: flex;
|
justify-content: space-between;
|
align-items: center;
|
}
|
|
.price {
|
font-size: 28rpx;
|
color: #ff6b35;
|
font-weight: bold;
|
}
|
|
.qty {
|
font-size: 24rpx;
|
color: #666;
|
}
|
|
/* 地址表单区域 */
|
.address-form {
|
background: white;
|
margin: 20rpx;
|
padding: 30rpx;
|
border-radius: 16rpx;
|
}
|
|
.form-title {
|
font-size: 32rpx;
|
font-weight: bold;
|
margin-bottom: 30rpx;
|
color: #333;
|
}
|
|
.form-item {
|
display: flex;
|
align-items: flex-start;
|
margin-bottom: 30rpx;
|
min-height: 80rpx;
|
}
|
|
.label {
|
width: 160rpx;
|
font-size: 28rpx;
|
color: #333;
|
line-height: 80rpx;
|
flex-shrink: 0;
|
}
|
|
.input {
|
flex: 1;
|
height: 80rpx;
|
line-height: 80rpx;
|
font-size: 28rpx;
|
color: #333;
|
padding: 0 20rpx;
|
border: 1rpx solid #e0e0e0;
|
border-radius: 8rpx;
|
}
|
|
.picker-text {
|
flex: 1;
|
height: 80rpx;
|
line-height: 80rpx;
|
font-size: 28rpx;
|
color: #333;
|
padding: 0 20rpx;
|
border: 1rpx solid #e0e0e0;
|
border-radius: 8rpx;
|
background: white;
|
}
|
|
.textarea {
|
flex: 1;
|
min-height: 120rpx;
|
font-size: 28rpx;
|
color: #333;
|
padding: 20rpx;
|
border: 1rpx solid #e0e0e0;
|
border-radius: 8rpx;
|
line-height: 1.4;
|
}
|
|
/* 底部提交按钮(核心:适配安全区域) */
|
.submit-btn {
|
position: fixed;
|
bottom: 0;
|
left: 0;
|
right: 0;
|
height: 100rpx;
|
line-height: 100rpx;
|
/* 保证文字垂直居中 */
|
background: #ff6b35;
|
color: white;
|
text-align: center;
|
font-size: 32rpx;
|
font-weight: bold;
|
/* 兼容新旧iOS和安卓的安全区域 */
|
padding-bottom: constant(safe-area-inset-bottom);
|
/* iOS 11.0-11.1 */
|
padding-bottom: env(safe-area-inset-bottom);
|
/* iOS 11.2+ 及安卓 */
|
}
|
</style>
|