2026-01-14 17:41:42 +08:00

269 lines
8.8 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>
<view class="address-page">
<navBar :title="'收货地址'" />
<!-- <uni-nav-bar left-icon="left" title="收货地址" fixed color="#8B2316" height="180rpx" :border="false" backgroundColor="#ffffff" @clickLeft="goBack" /> -->
<scroll-view scroll-y class="content">
<view class="form-item">
<view class="label">收件人</view>
<input class="input" v-model="receiver" placeholder="请输入收货人名字" />
</view>
<view class="divider-line"></view>
<view class="form-item">
<view class="label">手机号</view>
<input class="input" v-model="mobile" type="number" placeholder="收货人的电话,方便联系" />
</view>
<view class="divider-line"></view>
<!-- <view class="form-item">
<view class="label">邮箱</view>
<input class="input" v-model="email" type="text" placeholder="用于接收电子卡等信息(可选)" />
</view> -->
<view class="divider-line"></view>
<view class="form-item select-item" @click="openAreaPicker">
<view class="label">地址</view>
<view class="input placeholder" v-if="!regionText">请选择地址</view>
<view class="input" v-else>{{ regionText }}</view>
<text class="arrow"></text>
</view>
<view class="divider-line"></view>
<view class="form-item">
<view class="label">详细地址</view>
<input class="input" v-model="detail" placeholder="请输入街道、门牌等详细地址信息" />
</view>
</scroll-view>
<view class="footer-bar" @click="submit">
<view class="confirm-btn" >确定兑换</view>
</view>
<!-- 省市区选择器 -->
<view v-if="showAreaPicker" class="picker-mask" @click="closeAreaPicker"></view>
<view v-if="showAreaPicker" class="picker-panel">
<view class="picker-header">
<text class="picker-btn" @click="closeAreaPicker">取消</text>
<text class="picker-title">选择地区</text>
<text class="picker-btn ok" @click="confirmArea">确定</text>
</view>
<picker-view v-if="provinces.length && cities.length && areas.length" class="picker-view" :indicator-style="indicatorStyle" :value="pickerIndex" @change="onAreaChange">
<picker-view-column>
<view v-for="(p,pi) in provinces" :key="pi" class="picker-item">{{ p.name }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(c,ci) in cities" :key="ci" class="picker-item">{{ c.name }}</view>
</picker-view-column>
<picker-view-column>
<view v-for="(a,ai) in areas" :key="ai" class="picker-item">{{ a.name }}</view>
</picker-view-column>
</picker-view>
<view v-else class="picker-empty">地区数据加载中...</view>
</view>
</view>
<unidialog
:title="'确认收货信息'"
:visible="freeVisible"
:content="freeContent"
@close="freeClose"
@confirm="freeConfirm"
>
<template #content>
<view>
<view class="row">
<view class="left">收件人:</view>
<view class="right">{{ receiver }}</view>
</view>
<view class="row">
<view class="left">手机号:</view>
<view class="right">{{ mobile }}</view>
</view>
<view class="row">
<view class="left">地址:</view>
<view class="right">{{ regionText+detail }}</view>
</view>
<view class="row">
<view class="left">兑换积分:</view>
<view class="right"><text class="price">0积分</text>(包邮)</view>
</view>
<view class="row">请确认此次兑换物品不退不换</view>
</view>
</template>
</unidialog>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import areaList from '@/utils/areaList.js'
import api from '@/api/api.js'
import unidialog from '@/components/dialog/dialog.vue';
const freeVisible = ref(false)
const freeContent = ref('')
const goods_order_id = ref('')
const freeClose = () => {
freeVisible.value = false
}
const freeConfirm = () => {
freeVisible.value = false;
api.useWelfareNum({
other_uuid: goods_order_id.value,
type: 5
}).then(res => {
if(res.code == 1 || res.code == 200){
uni.sendNativeEvent('goTabbarPage', {
msg: 'mine'
},ret => {
console.log(ret);
})
}
})
}
const receiver = ref('')
const mobile = ref('')
const regionText = ref('')
const detail = ref('')
const email = ref('')
const editingId = ref(null)
const goodsUuid = ref('')
const goodsNum = ref(0)
const goBack = () => uni.navigateBack()
// 省市区数据(适配树形数组:[{code,label,value,children:[...] }...]
const provinces = ref([])
const cities = ref([])
const areas = ref([])
const pickerIndex = ref([0,0,0])
const showAreaPicker = ref(false)
const indicatorStyle = `height: 80rpx;`
const normalizeNode = (node) => ({
code: node?.code || '',
name: node?.label || node?.value || node?.name || '',
children: Array.isArray(node?.children) ? node.children : []
})
const getAreaTree = () => {
const raw = areaList && (areaList.default || areaList)
return Array.isArray(raw) ? raw.map(normalizeNode) : []
}
const buildData = () => {
const tree = getAreaTree()
provinces.value = tree.length ? tree : [{ code: '', name: '', children: [] }]
const pIdx = Math.min(pickerIndex.value[0], Math.max(provinces.value.length - 1, 0))
const pNode = provinces.value[pIdx]
cities.value = (pNode?.children || []).map(normalizeNode)
if (!cities.value.length) cities.value = [{ code: '', name: '', children: [] }]
const cIdx = Math.min(pickerIndex.value[1], Math.max(cities.value.length - 1, 0))
const cNode = cities.value[cIdx]
areas.value = (cNode?.children || []).map(normalizeNode)
if (!areas.value.length) areas.value = [{ code: '', name: '' }]
}
const openAreaPicker = () => {
showAreaPicker.value = true
pickerIndex.value = [0,0,0]
buildData()
}
const closeAreaPicker = () => { showAreaPicker.value = false }
const onAreaChange = (e) => {
const val = (e && e.detail && e.detail.value) ? e.detail.value : [0,0,0]
const [pi, ci, ai] = val
if (pi !== pickerIndex.value[0]) {
pickerIndex.value = [pi, 0, 0]
buildData()
return
}
if (ci !== pickerIndex.value[1]) {
pickerIndex.value = [pi, ci, 0]
buildData()
return
}
pickerIndex.value = [pi, ci, ai]
}
const confirmArea = () => {
const p = provinces.value[pickerIndex.value[0]]
const c = cities.value[pickerIndex.value[1]]
const a = areas.value[pickerIndex.value[2]]
regionText.value = [p?.name, c?.name, a?.name].filter(Boolean).join(' ')
closeAreaPicker()
}
onLoad((opts) => {
console.log(22);
console.log(opts);
goodsUuid.value = opts.goodsUuid
goodsNum.value = opts.goodsNum
})
const submit = () => {
if (!receiver.value) return uni.showToast({ title: '请输入收件人', icon: 'none' })
if (!/^1\d{10}$/.test(mobile.value)) return uni.showToast({ title: '请输入正确手机号', icon: 'none' })
if (!regionText.value) return uni.showToast({ title: '请选择地址', icon: 'none' })
if (!detail.value) return uni.showToast({ title: '请输入详细地址', icon: 'none' })
api.createGoodsOrder({
goodsUuid: goodsUuid.value,
goodsNum: goodsNum.value,
user_name: receiver.value,
mobile: mobile.value,
email:'',
address: regionText.value+detail.value
}).then(res => {
if(res.code == 1 || res.code == 200){
freeVisible.value = true
goods_order_id.value = res.data.goods_order_id
}
})
}
</script>
<style scoped lang="scss">
.address-page { min-height: 100vh; background: #fff; }
.content { position: absolute; top: calc(var(--status-bar-height) + 44px); bottom: 120rpx; left: 0; right: 0; background: #fff; }
.form-item { display: flex; align-items: center; padding: 24rpx; }
.label { width: 160rpx; color: #333; font-size: 30rpx; }
.input { flex: 1; color: #333; font-size: 30rpx; }
.placeholder { color: #bbb; }
.divider-line { height: 2rpx; background: #eee; margin: 0 24rpx; }
.select-item { position: relative; }
.arrow { position: absolute; right: 24rpx; color: #999; font-size: 48rpx; }
.footer-bar { position: fixed; left: 0; right: 0; bottom: 0; height: 120rpx; background: #27c5b8; display: flex; align-items: center; justify-content: center; }
.confirm-btn { color: #fff; font-size: 34rpx; font-weight: 700; }
/* 地区选择器 */
.picker-mask { position: fixed; left: 0; right: 0; top: 0; bottom: 0; background: rgba(0,0,0,0.4); }
.picker-panel { position: fixed; left: 0; right: 0; bottom: 0; background: #fff; }
.picker-header { display: flex; align-items: center; justify-content: space-between; padding: 20rpx 24rpx; border-bottom: 1rpx solid #eee; }
.picker-title { font-size: 30rpx; color: #333; }
.picker-btn { color: #666; font-size: 28rpx; }
.picker-btn.ok { color: #38c1b1; }
.picker-view { height: 480rpx; }
.picker-item { height: 80rpx; line-height: 80rpx; text-align: center; color: #333; }
.picker-empty { padding: 40rpx; text-align: center; color: #999; }
.row{
display: flex;
align-items: center;
font-size: 28rpx;
padding: 12rpx 0;
max-width: 800rpx;
margin-left: -100rpx;
.left{
text-align: left;
max-width: 125rpx;
}
.price{
color: #FF4D4F;
}
}
.left{
width: 160rpx;
}
</style>