Files
2023-11-14 17:21:03 +08:00

383 lines
8.2 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>
<Popup
ref="popupRef"
:showCloseable="false"
@close="emit('close')"
>
<view
class="goodAttrSelect"
>
<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>
</view>
<div class="line"></div>
<view
class="goodAttrSelect-attr row"
v-if="curAttr"
>
<view class="goodAttrSelect-attr-title">
数量
</view>
<view class="goodAttrSelect-attr-content">
<!-- 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>-->
</view>
</view>
<div class="line"></div>
<view
class="goodAttrSelect-attr"
v-for="(item, index) in productAttr"
:key="index"
>
<view class="goodAttrSelect-attr-title">
{{ item.attrName }}
</view>
<view class="goodAttrSelect-attr-content">
<space wrap="warp">
<view
:class="{ attr: true, check: selectedAttr[index] === attr }"
v-for="(attr, attrIndex) in item.attrValueArr"
:key="attrIndex"
@tap="handleSelectAttr(index, attr)"
>{{ attr }}
</view>
</space>
</view>
</view>
<view class="goodAttrSelect-action">
<uv-button
round
block
type="primary"
@tap="handleSubmit"
>
确定
</uv-button>
</view>
</view>
</Popup>
</template>
<script setup>
import { ref, unref } from 'vue';
import { getProductDetail } from '@/api/product'
import { useInterface } from "@/hooks/useInterface";
import Popup from '@/components/Popup/index.vue';
const props = defineProps(["id"])
const emit = defineEmits(['onSelect', 'submit', 'close'])
const popupRef = ref()
const selectedAttr = ref([])
const visible = ref(false)
const detailData = ref(null)
const storeInfo = ref(null)
const productAttr = ref(null)
const productValue = ref(null)
const storeNum = ref(1)
const curAttr = ref(null)
const defaultSelectAttrStr = ref(undefined)
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
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]
}
}
}
const handleSelectAttr = (index, attr) => {
selectedAttr.value[index] = attr
let selectedAttrStr = selectedAttr.value.join(',')
curAttr.value = productValue.value[selectedAttrStr]
}
const handleSubmit = () => {
// 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
})
emit('select', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
emit('onSelect', {
store: productValue.value[selectedAttrStr],
num: storeNum.value
})
}
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
handleGetDetail(props.id)
popupRef.value.show()
}
const close = () => {
popupRef.value.close()
emit('close')
}
defineExpose({
open,
close
})
</script>
<style lang="scss">
.goodAttrSelect {
height: 100%;
&-goods {
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;
}
}
}
}
&-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;
}
&-content {
}
}
}
.line {
height: 1rpx;
background: #E6E6E6;
}
.attr {
height: 68rpx;
border: 1rpx solid #333333;
padding: 0 20rpx;
font-size: 28rpx;
text-overflow: ellipsis;
overflow: hidden;
white-space: nowrap;
display: flex;
justify-content: center;
align-items: center;
&.check {
background: #333333;
color: #fff;
}
}
.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;
}
}
}
</style>