193 lines
6.0 KiB
Vue
193 lines
6.0 KiB
Vue
<template>
|
|
<view class="exchange-page">
|
|
<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="addr-card" @click="changeAddress">
|
|
<view class="addr-header">
|
|
<text class="addr-title">收货信息</text>
|
|
<text class="addr-change">{{ selectedAddress ? '更换' : '添加' }}</text>
|
|
</view>
|
|
<view v-if="selectedAddress" class="addr-info">
|
|
<text class="addr-row">{{ selectedAddress.receiver }} {{ selectedAddress.mobile }}</text>
|
|
<text class="addr-row small">{{ selectedAddress.fullAddress || (selectedAddress.region + ' ' + selectedAddress.detail) }}</text>
|
|
</view>
|
|
<view v-else class="addr-empty">请添加收货地址</view>
|
|
</view>
|
|
|
|
<view class="goods-title">{{ title }}</view>
|
|
<view class="price">{{ price }}积分</view>
|
|
|
|
<view class="divider"></view>
|
|
|
|
<view class="section">
|
|
<view class="section-label">兑换数量</view>
|
|
<view class="qty-row">
|
|
<view class="qty-btn" :class="{ active: qty === 1 }" @click="setQty(1)">1</view>
|
|
<view class="qty-btn" :class="{ active: qty === 2 }" @click="setQty(2)">2</view>
|
|
<view class="qty-btn" :class="{ active: qty === 3 }" @click="setQty(3)">3</view>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="section">
|
|
<view class="section-label">所需积分</view>
|
|
<view class="need-points">{{ needPoints }}积分</view>
|
|
</view>
|
|
</scroll-view>
|
|
|
|
<view class="footer-bar">
|
|
<view class="confirm-btn" @click="goAddress">我要兑换</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref } from 'vue'
|
|
import { onLoad, onShow } from '@dcloudio/uni-app'
|
|
import goods_api from '@/api/goods_api'
|
|
const title = ref('')
|
|
const price = ref(0)
|
|
const qty = ref(1)
|
|
const needPoints = ref(0)
|
|
const totalPoints = ref(0)
|
|
const selectedAddress = ref(null)
|
|
const id = ref('')
|
|
|
|
const goBack = () => uni.navigateBack()
|
|
|
|
const setQty = (n) => {
|
|
qty.value = n
|
|
needPoints.value = n * Number(price.value || 0)
|
|
}
|
|
|
|
onLoad((opts) => {
|
|
if (opts) {
|
|
title.value = decodeURIComponent(opts.title || '')
|
|
price.value = Number(opts.price || 0)
|
|
id.value = opts.id || ''
|
|
setQty(1)
|
|
getTotalPoints()
|
|
}
|
|
})
|
|
|
|
onShow(() => {
|
|
loadAddress()
|
|
})
|
|
|
|
const STORAGE_KEY = 'goods_addresses'
|
|
const SELECTED_KEY = 'goods_selected_address'
|
|
const loadAddress = () => {
|
|
try {
|
|
const sel = uni.getStorageSync(SELECTED_KEY)
|
|
if (sel && sel.id) {
|
|
selectedAddress.value = sel
|
|
return
|
|
}
|
|
const list = uni.getStorageSync(STORAGE_KEY)
|
|
if (Array.isArray(list) && list.length) {
|
|
selectedAddress.value = list[0]
|
|
} else {
|
|
selectedAddress.value = null
|
|
}
|
|
} catch (e) {
|
|
selectedAddress.value = null
|
|
}
|
|
}
|
|
|
|
const changeAddress = () => {
|
|
let list = []
|
|
try {
|
|
const cached = uni.getStorageSync(STORAGE_KEY)
|
|
list = Array.isArray(cached) ? cached : []
|
|
} catch (e) { list = [] }
|
|
if (!list.length) {
|
|
uni.navigateTo({ url: '/pages_goods/exchange/address' })
|
|
return
|
|
}
|
|
uni.navigateTo({ url: '/pages_goods/exchange/address_list' })
|
|
}
|
|
|
|
const goAddress = () => {
|
|
if (needPoints.value > totalPoints.value) {
|
|
uni.showToast({ title: '积分不足', icon: 'none' })
|
|
return
|
|
}
|
|
if (!selectedAddress.value) {
|
|
changeAddress()
|
|
return
|
|
}
|
|
|
|
const data = {
|
|
goodsUuid: id.value,
|
|
address: selectedAddress.value.fullAddress,
|
|
user_name: selectedAddress.value.receiver,
|
|
mobile: selectedAddress.value.mobile,
|
|
goodsNum: qty.value,
|
|
email: selectedAddress.value.email
|
|
}
|
|
console.log(data)
|
|
|
|
|
|
//{"goodsUuid":"e6ca84edc8e64242a379dd0b895ea812",
|
|
// "address":"北京市东城区你一下",
|
|
// "user_name":"噢噢",
|
|
// "mobile":"13825244552",
|
|
// "goodsNum":"1",
|
|
// "email":""}
|
|
// 模拟下单:此处可调用后端接口完成兑换
|
|
uni.showModal({
|
|
title: '确认兑换',
|
|
content: `兑换“${title.value}”x${qty.value},共需 ${needPoints.value} 积分`,
|
|
success: (r) => {
|
|
if (r.confirm) {
|
|
// 扣减本地积分(演示)
|
|
totalPoints.value = Math.max(0, totalPoints.value - needPoints.value)
|
|
uni.removeStorageSync(SELECTED_KEY)
|
|
goods_api.createGoodsOrder(data).then(res => {
|
|
console.log(res)
|
|
if (res.code == 200) {
|
|
uni.showToast({ title: '兑换成功', icon: 'none' })
|
|
uni.navigateBack()
|
|
} else {
|
|
uni.showToast({ title: res.msg, icon: 'none' })
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
const getTotalPoints = () => {
|
|
goods_api.getTotalPoints && goods_api.getTotalPoints().then(res => {
|
|
if (res.code == 200) {
|
|
totalPoints.value = res.data || 0
|
|
}
|
|
}).catch(() => {})
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.exchange-page { min-height: 100vh; background: #fff; }
|
|
.content { position: absolute; top: 180rpx; bottom: 120rpx; left: 0; right: 0; background: #fff; }
|
|
.addr-card { background: #fff; padding: 24rpx; border-bottom: 1rpx solid #f0f0f0; }
|
|
.addr-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 12rpx; }
|
|
.addr-title { color: #333; font-size: 30rpx; }
|
|
.addr-change { color: #38c1b1; font-size: 28rpx; }
|
|
.addr-info { display: flex; flex-direction: column; gap: 8rpx; }
|
|
.addr-row { color: #333; font-size: 28rpx; }
|
|
.addr-row.small { color: #666; font-size: 26rpx; }
|
|
.addr-empty { color: #bbb; font-size: 28rpx; }
|
|
.goods-title { padding: 24rpx; font-size: 32rpx; color: #333; line-height: 1.6; }
|
|
.price { padding: 0 24rpx 24rpx; color: #e74c3c; font-size: 30rpx; font-weight: 700; }
|
|
.divider { height: 16rpx; background: #f5f5f5; }
|
|
.section { padding: 24rpx; }
|
|
.section-label { color: #333; font-size: 30rpx; margin-bottom: 20rpx; }
|
|
.qty-row { display: flex; gap: 24rpx; }
|
|
.qty-btn { flex: 1; text-align: center; height: 96rpx; line-height: 96rpx; border: 2rpx solid #38c1b1; color: #38c1b1; border-radius: 12rpx; font-size: 36rpx; }
|
|
.qty-btn.active { background: #38c1b1; color: #fff; }
|
|
.need-points { color: #333; font-size: 30rpx; text-align: right; }
|
|
.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; }
|
|
</style>
|
|
|