Files

383 lines
8.2 KiB
Vue
Raw Normal View History

2023-10-11 11:27:47 +08:00
<template>
2023-11-14 17:21:03 +08:00
<Popup
ref="popupRef"
:showCloseable="false"
@close="emit('close')"
2023-10-11 11:27:47 +08:00
>
<view
2023-11-14 17:21:03 +08:00
class="goodAttrSelect"
2023-10-11 11:27:47 +08:00
>
2023-11-14 17:21:03 +08:00
<view
class="goodAttrSelect-goods"
v-if="curAttr"
>
<uv-image
class="attr-image"
:src="curAttr.image || detailData.storeInfo.image"
width="150rpx"
height="150rpx"
></uv-image>
<view class="attr-info">
<view class="name">
{{ storeInfo.storeName }}
</view>
<view class="attr-info-bottom">
<view class="price">¥{{ curAttr.price }}</view>
<view class="stock">库存{{ curAttr.stock }}</view>
</view>
</view>
2023-10-11 11:27:47 +08:00
</view>
<div class="line"></div>
2023-11-14 17:21:03 +08:00
<view
class="goodAttrSelect-attr row"
v-if="curAttr"
>
2023-10-11 11:27:47 +08:00
<view class="goodAttrSelect-attr-title">
数量
</view>
<view class="goodAttrSelect-attr-content">
2023-11-14 17:21:03 +08:00
<!-- cart number -->
<view
class="cart-num flex flex-ai__center flex-jc__sb"
@click.stop=""
>
<view
class="button"
@click="handleCartNumberChange(curAttr,'minus')"
>
<uv-icon
name="minus"
color="#333"
size="12"
></uv-icon>
</view>
<view class="input">
<input
type="number"
inputmode="numeric"
v-model="storeNum"
@blur="(e)=>handleCartNumberInputChange(e,curAttr)"
>
</view>
<view
class="button"
@click="handleCartNumberChange(curAttr,'plus')"
>
<uv-icon
name="plus"
color="#333"
size="12"
></uv-icon>
</view>
</view>
<!-- <uv-number-box
v-model="storeNum"
min="1"
:max="curAttr.stock"
></uv-number-box>-->
2023-10-11 11:27:47 +08:00
</view>
</view>
<div class="line"></div>
<view
2023-11-14 17:21:03 +08:00
class="goodAttrSelect-attr"
v-for="(item, index) in productAttr"
:key="index"
2023-10-11 11:27:47 +08:00
>
<view class="goodAttrSelect-attr-title">
{{ item.attrName }}
</view>
<view class="goodAttrSelect-attr-content">
2023-11-14 17:21:03 +08:00
<space wrap="warp">
2023-10-11 11:27:47 +08:00
<view
2023-11-14 17:21:03 +08:00
:class="{ attr: true, check: selectedAttr[index] === attr }"
v-for="(attr, attrIndex) in item.attrValueArr"
:key="attrIndex"
@tap="handleSelectAttr(index, attr)"
>{{ attr }}
</view>
2023-10-11 11:27:47 +08:00
</space>
</view>
</view>
<view class="goodAttrSelect-action">
<uv-button
2023-11-14 17:21:03 +08:00
round
block
type="primary"
@tap="handleSubmit"
2023-10-11 11:27:47 +08:00
>
确定
</uv-button>
</view>
</view>
2023-11-14 17:21:03 +08:00
</Popup>
2023-10-11 11:27:47 +08:00
</template>
<script setup>
2023-11-14 17:21:03 +08:00
import { ref, unref } from 'vue';
import { getProductDetail } from '@/api/product'
import { useInterface } from "@/hooks/useInterface";
import Popup from '@/components/Popup/index.vue';
2023-10-11 11:27:47 +08:00
const props = defineProps(["id"])
2023-11-14 17:21:03 +08:00
const emit = defineEmits(['onSelect', 'submit', 'close'])
2023-10-11 11:27:47 +08:00
const popupRef = ref()
2023-11-14 17:21:03 +08:00
const selectedAttr = ref([])
2023-10-11 11:27:47 +08:00
const visible = ref(false)
const detailData = ref(null)
const storeInfo = ref(null)
const productAttr = ref(null)
const productValue = ref(null)
const storeNum = ref(1)
2023-11-14 17:21:03 +08:00
const curAttr = ref(null)
const defaultSelectAttrStr = ref(undefined)
2023-10-11 11:27:47 +08:00
const selectAttrPanel = ref(false)
const handleGetDetail = async (id) => {
const detail = await getProductDetail(id)
if (detail) {
detailData.value = detail
storeInfo.value = detail.storeInfo
productAttr.value = detail.productAttr
productValue.value = detail.productValue
2023-11-14 17:21:03 +08:00
if (!defaultSelectAttrStr.value) {
// 设置默认选中
let attr = []
detail.productAttr.forEach((item, i) => {
attr[i] = item.attrValueArr[0]
})
selectedAttr.value = attr
let selectedAttrStr = selectedAttr.value.join(',')
curAttr.value = productValue.value[selectedAttrStr]
} else {
selectedAttr.value = unref(defaultSelectAttrStr).split(',')
curAttr.value = productValue.value[defaultSelectAttrStr.value]
}
2023-10-11 11:27:47 +08:00
}
}
2023-11-14 17:21:03 +08:00
const handleSelectAttr = (index, attr) => {
selectedAttr.value[index] = attr
let selectedAttrStr = selectedAttr.value.join(',')
curAttr.value = productValue.value[selectedAttrStr]
2023-10-11 11:27:47 +08:00
}
const handleSubmit = () => {
2023-11-14 17:21:03 +08:00
// let value = []
// productAttr.value.map(item => {
// value.push(selectedAttr.value[item.attrName] || '')
// })
// if (value.includes('')) {
// uni.showToast({
// title: '请选择规格',
// icon: 'none',
// duration: 2000,
// })
// return
// }
let selectedAttrStr = selectedAttr.value.join(',')
emit('submit', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
2023-10-11 11:27:47 +08:00
})
emit('select', {
2023-11-14 17:21:03 +08:00
store: productValue.value[selectedAttrStr],
2023-10-11 11:27:47 +08:00
num: storeNum.value
})
2023-11-14 17:21:03 +08:00
emit('onSelect', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
2023-10-11 11:27:47 +08:00
}
2023-11-14 17:21:03 +08:00
const {toast} = useInterface()
/**
* 用户手动输入改变数量
* @param e
* @param item
* @returns {*}
*/
function handleCartNumberInputChange(e, item) {
const value = Number(e.detail.value)
if (value <= 0) {
storeNum.value = 1
toast({title: '至少选一件哦~'})
}
if (value > item.stock) {
storeNum.value = item.stock
toast({title: '超出库存啦~'})
}
storeNum.value = value
}
/**
* 用户点击购物车+-改变数量
* @param item
* @param type
* @returns {*}
*/
function handleCartNumberChange(item, type = 'plus') {
if (type === 'plus') {
// +
if (storeNum.value + 1 > item.stock) return toast({title: '超出库存啦~'})
storeNum.value += 1
} else {
// -
if (storeNum.value - 1 <= 0) return toast({title: '至少选一件哦~'})
storeNum.value -= 1
}
}
const open = (cartNum = 1, selectAttrStr = undefined) => {
defaultSelectAttrStr.value = selectAttrStr
storeNum.value = cartNum
2023-10-11 11:27:47 +08:00
handleGetDetail(props.id)
2023-11-14 17:21:03 +08:00
popupRef.value.show()
2023-10-11 11:27:47 +08:00
}
const close = () => {
popupRef.value.close()
2023-11-14 17:21:03 +08:00
emit('close')
2023-10-11 11:27:47 +08:00
}
defineExpose({
open,
close
})
</script>
2023-11-14 17:21:03 +08:00
<style lang="scss">
2023-10-11 11:27:47 +08:00
.goodAttrSelect {
height: 100%;
&-goods {
2023-11-14 17:21:03 +08:00
padding: 40rpx 30rpx;
display: flex;
.attr-image {
}
.attr-info {
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-between;
margin-left: 30rpx;
.name {
font-size: 28rpx;
line-height: 40rpx;
color: #333333;
}
&-bottom {
display: flex;
justify-content: space-between;
.price {
font-size: 30rpx;
line-height: 42rpx;
color: #333333;
}
.stock {
font-size: 24rpx;
line-height: 42rpx;
color: #666666;
}
}
}
2023-10-11 11:27:47 +08:00
}
&-action {
padding: 20rpx 20rpx;
}
&-attr {
padding: 40rpx 30rpx;
&.row {
display: flex;
align-items: center;
justify-content: space-between;
.goodAttrSelect-attr-title {
margin-bottom: 0;
}
}
&-title {
margin-bottom: 30rpx;
}
2023-11-14 17:21:03 +08:00
&-content {
}
2023-10-11 11:27:47 +08:00
}
}
.line {
height: 1rpx;
background: #E6E6E6;
}
.attr {
height: 68rpx;
border: 1rpx solid #333333;
padding: 0 20rpx;
font-size: 28rpx;
2023-11-14 17:21:03 +08:00
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
display: flex;
justify-content: center;
align-items: center;
2023-10-11 11:27:47 +08:00
&.check {
background: #333333;
color: #fff;
}
}
2023-11-14 17:21:03 +08:00
.cart-num {
font-size: 24rpx;
.input {
width: 120rpx;
input {
width: 100%;
text-align: center;
color: #333;
}
}
.button {
font-size: 32rpx;
width: 34rpx;
aspect-ratio: 1/1;
border-radius: 5rpx;
border: 2rpx solid #cccccc;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: center;
transition: all .3s;
&:active {
scale: 1.2;
}
}
}
2023-10-11 11:27:47 +08:00
</style>