255 lines
5.1 KiB
Vue
255 lines
5.1 KiB
Vue
<script setup>
|
|
/**
|
|
* 下单组件
|
|
*/
|
|
import {
|
|
ref,
|
|
reactive,
|
|
getCurrentInstance,
|
|
computed,
|
|
defineEmits,
|
|
onMounted,
|
|
defineProps,
|
|
defineExpose,
|
|
watch,
|
|
} from 'vue'
|
|
//
|
|
import util from '@/common/js/util.js'
|
|
//
|
|
import api from '@/api/index.js'
|
|
// 地址
|
|
import JyCommodityAddress from '@/components/public/jy-commodity-address'
|
|
|
|
const {
|
|
proxy
|
|
} = getCurrentInstance()
|
|
//
|
|
const props = defineProps({
|
|
// 商品信息
|
|
detail: {
|
|
type: Object,
|
|
default: () => ({})
|
|
},
|
|
// 模式 detail详情 collect收藏列表
|
|
mode: {
|
|
type: String,
|
|
default: 'detail'
|
|
},
|
|
})
|
|
// 提交
|
|
const emit = defineEmits(['confirm'])
|
|
// 地址
|
|
const address = ref({})
|
|
// 已选择的规格下标
|
|
const spaceIndex = ref(0)
|
|
// 上次选择的规格下标
|
|
const spaceIndexLast = ref(0)
|
|
// 数量
|
|
const payNum = ref(1)
|
|
// 上次数量
|
|
const payNumLast = ref(1)
|
|
// 当前选择的规格
|
|
const currentSpec = computed(() => {
|
|
let spec = props.detail.specs || []
|
|
return spec[spaceIndex.value] || {}
|
|
})
|
|
// 应付总价
|
|
const total = computed(() => {
|
|
let price = parseFloat(props.detail.price) * 100
|
|
let result = parseInt(price * payNum.value) / 100
|
|
return result
|
|
})
|
|
|
|
watch(() => address.value, (nValue) => {
|
|
console.log('address', nValue)
|
|
})
|
|
|
|
onMounted(() => {
|
|
// 获取默认收货地址
|
|
if (props.mode === 'detail') getDefaultAddress()
|
|
})
|
|
|
|
// 获取默认收货地址
|
|
function getDefaultAddress() {
|
|
util.isLogin().then(res => {
|
|
api.shop.getDefaultAddress({}).then(res => {
|
|
if (res.code === 200) {
|
|
if (res.data) Object.assign(address.value, {}, res.data)
|
|
return
|
|
}
|
|
util.alert({
|
|
content: res.msg,
|
|
showCancel: false,
|
|
})
|
|
})
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 跳转
|
|
* @param {Object} url 跳转路径
|
|
*/
|
|
function link(url) {
|
|
uni.navigateTo({
|
|
url,
|
|
})
|
|
}
|
|
|
|
/**
|
|
* 选择规格
|
|
* @param {Object} index 选择规格下标
|
|
*/
|
|
function handleSpec(index) {
|
|
if (spaceIndex.value !== index) spaceIndex.value = index
|
|
}
|
|
|
|
/**
|
|
* 打开弹窗
|
|
* @param {Object} event 携带参数
|
|
*/
|
|
function open(event) {
|
|
// 同步选择值
|
|
if (event) {
|
|
spaceIndex.value = event.spaceIndex || 0
|
|
payNum.value = event.payNum || 1
|
|
}
|
|
// 打开弹窗
|
|
proxy.$refs.payment.open()
|
|
}
|
|
|
|
// 关闭弹窗
|
|
function close() {
|
|
proxy.$refs.payment.close()
|
|
}
|
|
|
|
// 确认
|
|
function handleConfirm() {
|
|
// 验证必填项
|
|
if (props.mode == 'detail' && !address.value.id) {
|
|
util.alert('请选择收货地址')
|
|
return
|
|
}
|
|
//
|
|
let param = {
|
|
spec: currentSpec.value,
|
|
spaceIndex: spaceIndex.value,
|
|
payNum: payNum.value,
|
|
}
|
|
|
|
// 如果有地址信息
|
|
if (address.value.id) param.address = address.value
|
|
|
|
emit('confirm', param)
|
|
// 同步选择值
|
|
spaceIndexLast.value = spaceIndex.value
|
|
payNumLast.value = payNum.value
|
|
|
|
//
|
|
close()
|
|
}
|
|
|
|
/**
|
|
* 弹窗状态改变
|
|
* @param {Object} ev
|
|
*/
|
|
function handlePopChange(ev) {
|
|
// 关闭弹窗时 同步选择值
|
|
if (!ev.show) {
|
|
spaceIndex.value = spaceIndexLast.value
|
|
payNum.value = payNumLast.value
|
|
}
|
|
}
|
|
|
|
defineExpose({
|
|
open,
|
|
close,
|
|
})
|
|
</script>
|
|
|
|
<template>
|
|
<!-- 规格 -->
|
|
<uni-popup type="bottom" ref="payment" @change="handlePopChange">
|
|
<view class="buy popBot plr20 bfff">
|
|
<view class="address mtb40" v-if="mode === 'detail'">
|
|
<JyCommodityAddress v-model:address="address" />
|
|
</view>
|
|
|
|
<!-- 商品图 价格 明细 数量 -->
|
|
<view class="jy-card-commodity-content df fdr mtb40">
|
|
<!-- 商品图 -->
|
|
<image class="wh200 br10" :src="currentSpec.image" mode="aspectFill" />
|
|
|
|
<!-- 价格 明细 数量 -->
|
|
<view class="info f1 df fdc jcsb ml30">
|
|
<!-- 价格 -->
|
|
<view class="price df fdr aic">
|
|
<text class="cFF9B27 f28">单价</text>
|
|
<text class="cFF9B27 f24">¥</text>
|
|
<text class="cFF9B27 f50">{{detail.price}}</text>
|
|
</view>
|
|
<!-- 已选 -->
|
|
<view class="content-info-num">
|
|
<text class="f26 c333">已选: {{currentSpec.sku}}</text>
|
|
</view>
|
|
<!-- 计数器 -->
|
|
<view class="w200">
|
|
<uni-number-box v-model="payNum" :step="1" />
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 规格 -->
|
|
<view class="spec">
|
|
<view class="selection df fdr fww">
|
|
<!-- disabled 销量为零不能选 -->
|
|
<text class="option mtb20 mr20 f26" :class="{'active': spaceIndex === index}"
|
|
v-for="(item,index) in detail.specs" :key="item.id"
|
|
@click="handleSpec(index)">{{item.sku}}</text>
|
|
</view>
|
|
</view>
|
|
|
|
<view class="btn lg primary mtb30" @click="handleConfirm">
|
|
<text class="tac cfff" v-if="mode == 'detail'">立即下单 ¥{{total}}</text>
|
|
<text class="tac cfff" v-if="mode == 'collect'">确定</text>
|
|
</view>
|
|
</view>
|
|
</uni-popup>
|
|
</template>
|
|
|
|
<style lang="scss" scoped>
|
|
// 规格
|
|
.spec {
|
|
|
|
// 选项
|
|
.option {
|
|
padding: 5rpx 15rpx;
|
|
color: #333;
|
|
background-color: #F7F7F7;
|
|
border-radius: 10rpx;
|
|
transition: .3s;
|
|
border: 2rpx solid #F7F7F7;
|
|
|
|
.text {}
|
|
|
|
// .text {
|
|
// color: #FF9B27;
|
|
// }
|
|
|
|
// 被选中
|
|
&.active {
|
|
color: #FF9B27;
|
|
background-color: #FFFBF8;
|
|
border-color: #FF9B27;
|
|
}
|
|
|
|
// 不能选
|
|
&.disabled {
|
|
background-color: F7F7F7;
|
|
|
|
.txt {
|
|
color: #999;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style> |