增加相关商品推荐功能

This commit is contained in:
2025-12-25 19:03:17 +08:00
parent b5ecab0a03
commit 75ed724fbb
3 changed files with 452 additions and 211 deletions

View File

@@ -36,30 +36,7 @@ export default async (params) => {
}
// #ifdef H5
uni.cache.set('token', 'b61c8b0f1c9d47ad924e33c48b496ce6')
uni.cache.set('userInfo', {
"acQrcodeValidTime": "2025-11-17 17:57:16",
"alipayOpenId": "",
"birthDay": "2025-10-17",
"createTime": "2024-07-06 11:30:16",
"distributionAmount": 0,
"headImg": "https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132",
"id": "36434",
"idCard": "612401199810058031",
"isAc": 0,
"lastLoginTime": "2025-12-25 09:19:20",
"nickName": "微信用户",
"password": "",
"payPwd": "e10adc3949ba59abbe56e057f20f883e",
"phone": "18049104914",
"realName": "叶明飞",
"sex": 1,
"status": 1,
"updateTime": "2025-12-25 09:17:59",
"usePayPwd": 0,
"wechatAcOpenId": "1111",
"wechatAcQrcode": "",
"wechatOpenId": "or1l86yipGvwyfPhrKIAcQuSfAV8"
})
uni.cache.set('userInfo',{"acQrcodeValidTime":"2025-11-17 17:57:16","alipayOpenId":"","birthDay":"2025-10-17","createTime":"2024-07-06 11:30:16","distributionAmount":0,"headImg":"https://thirdwx.qlogo.cn/mmopen/vi_32/POgEwh4mIHO4nibH0KlMECNjjGxQUq24ZEaGT4poC6icRiccVGKSyXwibcPq4BWmiaIGuG1icwxaQX6grC9VemZoJ8rg/132","id":"36434","idCard":"612401199810058031","isAc":0,"lastLoginTime":"2025-12-25 11:41:15","nickName":"微信用户","password":"","payPwd":"e10adc3949ba59abbe56e057f20f883e","phone":"18049104914","realName":"叶明飞","sex":1,"status":1,"updateTime":"2025-12-25 09:41:58","usePayPwd":0,"wechatAcOpenId":"1111","wechatAcQrcode":"","wechatOpenId":"or1l86yipGvwyfPhrKIAcQuSfAV8"})
// #endif
return new Promise((resolve, reject) => {
const timeoutDuration = params.timeout || 10000; // 可以通过 params 传入超时时间,默认 10 秒

View File

@@ -1,191 +1,233 @@
<template>
<up-popup :show="visible" :round="20" mode="bottom" @close="close" :close-on-click-overlay="true">
<view class="shop_sku">
<view class="" style="height: calc(100vh - 70px);">
<view class="shop_sku" >
<scroll-view scroll-y style="max-height: 60vh; width: 100%">
<view class="positionabsolute">
<up-icon name="arrow-down" @click="close" color="#333" size="22"></up-icon>
</view>
<up-swiper :list="goods.images" @change="swiperChange" :current="swiperCurrent" radius="6px"
height="250" @click="prveImgs(goods.images, goods.images[swiperCurrent])">
</up-swiper>
<view class="shop_sku_name">{{ goods.name }}</view>
<view class="shop_sku_description" v-if="isSkuGoods">
{{ goods.shortTitle ? goods.shortTitle : '' }}
</view>
<view v-if="goods.type != 'package'">
<view class="shop_sku_box" v-for="(specOptions, specType) in goods.selectSpecInfo" :key="specType">
<view class="shop_sku_box_name">
{{ specType }}
</view>
<view class="flex-start">
<view class="shop_sku_box_item" v-for="option in specOptions" :key="option"
@click="selectSpec(specType, option)" :class="{
shop_sku_box_item_selected: isSkuSelected(specType, option)
}">
{{ option }}
<view class="shop_sku_box_item_tip"
v-if="goods.result && goods.result.isSoldStock == 1 && selectedSpecs[specType] === option">
<view>售罄</view>
</view>
<view class="shop_sku_box_item_tip"
v-if="goods.result == 'kong' && canSubmit == false && selectedSpecs[specType] === option">
<view>已下架</view>
</view>
</view>
</view>
<scroll-view scroll-y style="height: calc(100vh - 240px); width: 100%">
<!-- <view class="positionabsolute">
<up-icon name="arrow-down" @click="close" color="#333" size="22"></up-icon>
</view> -->
<view class="positionabsolute">
<up-icon name="close-circle" @click="close" color="#000" size="25"></up-icon>
</view>
</view>
<!-- 套餐 -->
<view v-else>
<view class="shop_sku_box">
<view v-for="(setmenu, setmenuindex) in goods.groupSnap" :key="setmenuindex">
<view class="shop_sku_box_name">{{ setmenu.title }} {{ setmenu.count }}
{{ setmenu.number }}</view>
<up-swiper :list="goods.images" @change="swiperChange" :current="swiperCurrent" radius="6px"
height="250" @click="prveImgs(goods.images, goods.images[swiperCurrent])">
</up-swiper>
<view class="shop_sku_name">{{ goods.name }}</view>
<view class="shop_sku_description" v-if="isSkuGoods">
{{ goods.shortTitle ? goods.shortTitle : '' }}
</view>
<view v-if="goods.type != 'package'">
<view class="shop_sku_box" v-for="(specOptions, specType) in goods.selectSpecInfo" :key="specType">
<view class="shop_sku_box_name">
{{ specType }}
</view>
<view class="flex-start">
<view class="shop_sku_box_item" v-for="(option, goodsid) in setmenu.goods"
:key="goodsid" @click="goodsidClick(setmenuindex, option, goodsid)" :class="{
shop_sku_box_item_selected: isOptionSelected(setmenuindex, option)
}" :disabled="isMaxSelected(setmenuindex) && !isOptionSelected(setmenuindex, option)">
{{ option.proName }}
<text v-if="option.unitName">/{{ option.unitName }}</text>
<view class="shop_sku_box_item_tip" v-if="goods.isSoldStock == 1">
<view class="shop_sku_box_item" v-for="option in specOptions" :key="option"
@click="selectSpec(specType, option)" :class="{
shop_sku_box_item_selected: isSkuSelected(specType, option)
}">
{{ option }}
<view class="shop_sku_box_item_tip"
v-if="goods.result && goods.result.isSoldStock == 1 && selectedSpecs[specType] === option">
<view>售罄</view>
</view>
<view class="shop_sku_box_item_tip"
v-if="goods.result == 'kong' && canSubmit == false && selectedSpecs[specType] === option">
<view>已下架</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 推荐搭配 -->
<view class="u-m-t-48 u-p-30">
<view class="font-bold u-font-32 ">推荐搭配</view>
<view class="u-flex recommand-goods">
<view class=" item" v-for="(product,index) in goods.relatedRecommendJson" :key="index">
<up-image width="210rpx" height="210rpx" radius="12rpx" :src="product.coverImg"></up-image>
<view class="info">
<view class="u-line-2 name u-m-t-10 u-font-32 font-500">
{{product.name}}
</view>
<view class="u-flex u-row-between">
<view class="font-bold">
<text class="u-font-24"></text>
<text class="u-font-32">
<GoodsPrice :limitDiscount="cartStore.limitTimeDiscount"
:cart="returnFirstSku(product)" :shopUserInfo="shopUserInfo"
:shopInfo="shopInfo"></GoodsPrice>
</text>
</view>
<view class="btn">
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
<!-- 套餐 -->
<view v-else>
<view class="shop_sku_box">
<view v-for="(setmenu, setmenuindex) in goods.groupSnap" :key="setmenuindex">
<view class="shop_sku_box_name">{{ setmenu.title }} {{ setmenu.count }}
{{ setmenu.number }}</view>
<view class="flex-start">
<view class="shop_sku_box_item" v-for="(option, goodsid) in setmenu.goods"
:key="goodsid" @click="goodsidClick(setmenuindex, option, goodsid)" :class="{
shop_sku_box_item_selected: isOptionSelected(setmenuindex, option)
}" :disabled="isMaxSelected(setmenuindex) && !isOptionSelected(setmenuindex, option)">
{{ option.proName }}
<text v-if="option.unitName">/{{ option.unitName }}</text>
<view class="shop_sku_box_item_tip" v-if="goods.isSoldStock == 1">
<view>售罄</view>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 推荐搭配 -->
<view class="u-m-t-48 u-p-30" v-if="goods.relatedRecommendJson.length">
<view class="font-bold u-font-32 ">推荐搭配</view>
<view class="u-flex recommand-goods">
<view class=" item" v-for="(product,index) in goods.relatedRecommendJson" :key="index"
@click="modalAdd(product)">
<view class="relative">
<up-image width="210rpx" height="210rpx" radius="12rpx"
:src="product.coverImg"></up-image>
<view class="vifgoodsImg flex-center"
v-if="product.isSale == 0 || (product.isSaleTime == 0 && !product.isSaleTimeshow) || product.isSoldStock == 1 || (product.isStock == 1 && product.stockNumber <= 0)">
<image v-if="product.isSale == 0" src="@/static/ztt/icon_goods_yxj.svg"
style="width: 200rpx; height: 100%" mode=""></image>
<image v-else-if="product.isSaleTime == 0 && !product.isSaleTimeshow"
src="@/static/ztt/icon_goods_wks.svg" style="width: 200rpx; height: 100%"
mode="">
</image>
<image v-else-if="product.isSoldStock == 1" src="@/static/ztt/icon_goods_sq.svg"
style="width: 200rpx; height: 100%" mode=""></image>
<image v-else-if="product.isStock == 1 && product.stockNumber <= 0"
src="@/static/ztt/icon_goods_kcbz.svg" style="width: 200rpx; height: 100%"
mode="">
</image>
</view>
</view>
<view class="info">
<view class="u-line-2 name u-m-t-10 u-font-32 font-500">
{{product.name}}
</view>
<view class="u-flex u-row-between">
<view class="font-bold u-flex u-col-baseline">
<text class="u-font-24"></text>
<view class="u-font-32">
<GoodsPrice :limitDiscount="cartStore.limitTimeDiscount"
:cart="returnFirstSku(product)" :shopUserInfo="shopUserInfo"
:shopInfo="shopInfo"></GoodsPrice>
</view>
</view>
<view class="btn relative" @click.stop="addGoods(product)">
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
<view class="dot" v-if="returnGoodsImCartNum(product)>0">
{{returnGoodsImCartNum(product)}}
</view>
</view>
</view>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="shop_bottom">
<view class="flex-between">
<view class="price price-sku" v-if="goods.type != 'package' && goods.result">
<text class="i"></text>
<view class="num">
<GoodsPrice :limitDiscount="cartStore.limitTimeDiscount" :cart="selSku"
:shopUserInfo="shopUserInfo" :shopInfo="shopInfo"></GoodsPrice>
</view>
<text class="num" v-if="false">
{{
shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1
? goods.result.memberPrice || goods.result.salePrice
: goods.result.salePrice
}}
</text>
<text class="i" v-if="goods.unitName">/{{ goods.unitName }}</text>
<text
v-if="goods.result.suitNum > 1">{{ goods.result.suitNum }}{{ goods.result.unitName }}起点</text>
</view>
<view class="price price-package" v-else>
<text class="i"></text>
<view class="num">
<GoodsPrice :limitDiscount="cartStore.limitTimeDiscount" :cart="goods"
:shopUserInfo="shopUserInfo" :shopInfo="shopInfo"></GoodsPrice>
</view>
<text class="num" v-if="false">
{{
shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1
? goods.memberPrice || goods.salePrice
: goods.salePrice
}}
</text>
<text class="i" v-if="goods.unitName">/{{ goods.unitName }}</text>
<text v-if="goods.suitNum > 1">{{ goods.suitNum }}{{ goods.unitName }}起点</text>
</view>
<view class="operation-wrap" v-if="goods.type != 'package'&&stockNumberIsFull(goods)">
<view class="btn">
<up-icon name="minus-circle-fill" color="#E9AB7A" size="25"
v-if="shopCartNumber > 0"></up-icon>
<view class="btnClick" @click="shopCart('-')"></view>
</view>
<text class="num">{{ shopCartNumber }}</text>
<view class="btn">
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
<view class="btnClick" @click="shopCart('+')"></view>
</view>
</view>
</view>
</view>
</scroll-view>
<view class="shop_bottom">
<view class="flex-between">
<view class="price price-sku" v-if="goods.type != 'package' && goods.result">
<text class="i"></text>
<view class="num">
<GoodsPrice :limitDiscount="cartStore.limitTimeDiscount" :cart="selSku"
:shopUserInfo="shopUserInfo" :shopInfo="shopInfo"></GoodsPrice>
</view>
<text class="num" v-if="false">
{{
shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1
? goods.result.memberPrice || goods.result.salePrice
: goods.result.salePrice
}}
</text>
<text class="i" v-if="goods.unitName">/{{ goods.unitName }}</text>
<text
v-if="goods.result.suitNum > 1">{{ goods.result.suitNum }}{{ goods.result.unitName }}起点</text>
<view class="shop_skuselect flex-start" v-if="selectedSpecsStr">
<view class="shop_skuselectname">{{ selectedSpecsStr }}</view>
</view>
<view class="price price-package" v-else>
<text class="i"></text>
<view class="num">
<GoodsPrice :limitDiscount="cartStore.limitTimeDiscount" :cart="goods"
:shopUserInfo="shopUserInfo" :shopInfo="shopInfo"></GoodsPrice>
</view>
<text class="num" v-if="false">
{{
shopInfo.isVip == 1 && shopInfo.isMemberPrice == 1
? goods.memberPrice || goods.salePrice
: goods.salePrice
}}
</text>
<text class="i" v-if="goods.unitName">/{{ goods.unitName }}</text>
<text v-if="goods.suitNum > 1">{{ goods.suitNum }}{{ goods.unitName }}起点</text>
</view>
<view class="operation-wrap" v-if="goods.type != 'package'&&stockNumberIsFull(goods)">
<view class="btn">
<up-icon name="minus-circle-fill" color="#E9AB7A" size="25"
v-if="shopCartNumber > 0"></up-icon>
<view class="btnClick" @click="shopCart('-')"></view>
</view>
<text class="num">{{ shopCartNumber }}</text>
<view class="btn">
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
<view class="btnClick" @click="shopCart('+')"></view>
</view>
</view>
</view>
<view class="shop_skuselect flex-start" v-if="selectedSpecsStr">
<view class="shop_skuselectname">{{ selectedSpecsStr }}</view>
</view>
<template v-if="!stockNumberIsFull(goods)">
<view class="addShopping">
库存不足
</view>
</template>
<template v-else>
<template v-if="isSkuGoods">
<view v-if="goods.type == 'package'" class="addShopping"
:class="shopCartNumber > 0 && allConditionsSatisfied ? 'active' : ''"
@click="submitSelection(goods)">
添加到购物车
</view>
<view v-else class="addShopping" :class="shopCartNumber > 0 && canSubmit ? 'active' : ''"
@click="submitSelection(goods)">
添加到购物车
<template v-if="!stockNumberIsFull(goods)">
<view class="addShopping">
库存不足
</view>
</template>
<template v-else>
<view class="addShopping" :class="shopCartNumber > 0 ? 'active' : ''"
@click="submitSelection(goods)">
添加到购物车
</view>
<template v-if="isSkuGoods">
<view v-if="goods.type == 'package'" class="addShopping package"
:class=" allConditionsSatisfied ? 'active' : ''" @click="submitSelection(goods)">
添加到购物车
</view>
<view v-else class="sku addShopping" :class="shopCartNumber > 0 && canSubmit ? 'active' : ''"
@click="submitSelection(goods)">
添加到购物车
</view>
</template>
<template v-else>
<view class="addShopping single" :class="shopCartNumber > 0 ? 'active' : ''"
@click="submitSelection(goods)">
添加到购物车
</view>
</template>
</template>
</template>
</view>
</view>
</view>
</up-popup>
</template>
<script setup>
import {
useNavbarStore
} from '@/stores/navbarStore';
const store = useNavbarStore();
const {
showBack,
rightText,
showSearch,
title,
isTransparent,
height,
hasPlaceholder,
scrollTop
} = toRefs(store);
import {
APIminiAppinfo,
APIminiAppskuinfo,
productRelated
} from '@/common/api/product/product.js';
import dayjs from 'dayjs';
//价格计算辅助函数
import {
limitUtils
@@ -213,9 +255,46 @@
}
},
},
GoodsIDInCartNumMap: {
type: Object,
default: () => {
return {
}
},
}
});
// / 选择规格的方法
const goodsidClick = (setmenuindex, option, goodsid) => {
if (!selectedOptions.value[setmenuindex]) {
// 如果 selectedOptions.value[setmenuindex] 不存在,初始化一个空数组
selectedOptions.value[setmenuindex] = [];
}
if (isOptionSelected(setmenuindex, option)) {
// 如果已经选中,取消选中
selectedOptions.value[setmenuindex] = selectedOptions.value[setmenuindex].filter((item) => item.proId !==
option.proId);
} else if (!isMaxSelected(setmenuindex)) {
// 如果未达到最大选择数量,添加到选中列表
selectedOptions.value[setmenuindex].push(option);
}
};
// 计算所有选中条件是否都符合
const allConditionsSatisfied = computed(() => {
// 检查 specifications.item.groupSnap 是否存在
if (!props.goods?.groupSnap) {
return false;
}
return props.goods.groupSnap.every((optionGroup, index) => {
// 获取当前索引对应的已选选项,如果不存在则默认为空数组
const selected = selectedOptions.value[index] || [];
// 检查是否达到最大选择数量
const hasEnoughSelection = selected.length === optionGroup.number;
return hasEnoughSelection;
});
});
// 存储用户当前选择的规格,初始为空对象
const selectedSpecs = ref({});
@@ -253,7 +332,24 @@
} else {}
} else {}
};
// 判断是否达到最大选择数量
const isMaxSelected = (setmenuindex) => {
// 确保 selectedOptions.value[setmenuindex] 存在
if (selectedOptions.value[setmenuindex]) {
return selectedOptions.value[setmenuindex].length >= props.goods.groupSnap[setmenuindex].number;
}
return false;
};
// 存储选中的选项,二维数组
const selectedOptions = ref(props.goods.groupSnap.map(() => []));
// 判断选项是否已选中
const isOptionSelected = (setmenuindex, option) => {
// 确保 selectedOptions.value[setmenuindex] 存在
if (selectedOptions.value[setmenuindex]) {
return selectedOptions.value[setmenuindex].some((item) => item.proId === option.proId);
}
return false;
};
const canSubmit = computed(() => {
if (shopCartNumber.value <= 0) {
return false
@@ -296,12 +392,16 @@
swiperCurrent.value = e.current;
}
const emits = defineEmits(['prveImgs', 'websocketsendMessage'])
const emits = defineEmits(['prveImgs', 'websocketsendMessage', 'close', 'modalAdd'])
function prveImgs(images, currentUrl) {
emits('prveImgs', images, currentUrl)
}
function modalAdd(item) {
emits('modalAdd', item)
}
const visible = defineModel({
default: false,
});
@@ -316,11 +416,24 @@
function close() {
visible.value = false;
shopCartNumber.value = 0;
selectedOptions.value = props.goods.groupSnap.map(() => [])
emits('close')
}
function isSelected(option) {
return selectedSpecs.value[specType] === option;
}
const calculateValue = (cartNumber, i, step = 1) => {
if (i == '+') {
const result = parseFloat(cartNumber) + parseFloat(step);
return result.toFixed(2);
} else {
// 当减到0返回del
const result = parseFloat(cartNumber) - parseFloat(step);
return result == 0 ? 'del' : result.toFixed(2);
}
};
// 判断商品是否在可售时间内
const isProductAvailable = async (sellDaysStr, startTimeStr, endTimeStr) => {
// 将后端返回的字符串转换为数组
@@ -355,6 +468,67 @@
return isInRange;
};
async function addGoods(goods) {
if (!isProductAvailable(goods.days, goods.startTime,
goods.endTime)) {
uni.showToast({
title: '不在可售时间内'
});
return false;
}
if (goods.isSoldStock == 1 || (goods.isSaleTime == 0 && !goods.isSaleTimeshow)) {
return uni.showToast({
title: '商品已下架或不在可售时间内',
icon: 'none'
});
}
const sku = goods.skuList[0]
const findCart = cartStore.carts.find(cart => cart.product_id == goods.id && sku.id)
emits('websocketsendMessage', {
id: findCart ? findCart.id : '',
type: 'shopping',
suitNum: sku.suitNum,
table_code: uni.cache.get('tableCode'),
shop_id: uni.cache.get('shopId'),
operate_type: findCart ? 'edit' : 'add',
product_id: goods.id,
sku_id: sku.id,
number: findCart ? await calculateValue(findCart.number * 1, '+', 1) : 1,
pro_group_info: '',
goods_type: goods.type == 'package' ? 'package' : '',
memberPrice: goods.memberPrice,
is_print: 1,
product_type: goods.type,
is_time_discount: showLimitDiscount(goods)
})
}
/**
* 返回购物车对应的商品数量
*/
function returnGoodsImCartNum(goods) {
console.log('props.GoodsIDInCartNumMap', props.GoodsIDInCartNumMap)
if (props.GoodsIDInCartNumMap.hasOwnProperty(goods.id)) {
return props.GoodsIDInCartNumMap[goods.id]
}
return 0
}
function returnSelectedGroupSnap() {
if (!props.goods?.groupSnap) {
return '';
}
return props.goods.groupSnap.map((v, index) => {
return {
...v,
goods: selectedOptions.value[index]
}
});
}
// 提交选择并执行下一步操作的方法
const submitSelection = async (goods) => {
if (!isProductAvailable(goods.days, goods.startTime,
@@ -365,48 +539,53 @@
return false;
}
// 判断购物车是否有该选中商品
// 数量不能少于0
if (shopCartNumber.value <= 0) {
if (goods.type != 'package' && shopCartNumber.value <= 0) {
return;
}
if (goods.type == 'package' && !allConditionsSatisfied.value) {
return
}
if ((goods.type == 'package' && allConditionsSatisfied.value) || (goods.type ==
'sku' && canSubmit.value)) {
let res = cartStore.carts.find(cart => cart.product_id == goods.id && cart.sku_id == selSku.value.id)
let suitNum = 1;
let sku_id = ''
// 是否是套餐 有就传
if (goods.type == 'package') {
// 需求更改:所所有商品套餐都是add,没有修改
shopCartNumber.value = props.goods.suitNum;
suitNum = props.goods.suitNum;
sku_id = props.goods.sku_id;
res = null;
} else {
selectedGroupSnap.value = [];
suitNum = selSku.value.suitNum
sku_id = selSku.value.id
}
console.log('goods', goods);
emits('websocketsendMessage', {
id: res ? res.cartListId : '',
id: res ? res.id : '',
type: 'shopping',
suitNum: selSku.value.suitNum,
suitNum,
table_code: uni.cache.get('tableCode'),
shop_id: uni.cache.get('shopId'),
operate_type: res ? 'edit' : 'add',
product_id: goods.id,
sku_id: selSku.value.id,
sku_id,
number: res ? await calculateValue(res.cartNumber, '+', shopCartNumber.value) :
shopCartNumber.value,
pro_group_info: selectedGroupSnap.value,
pro_group_info: returnSelectedGroupSnap(),
goods_type: goods.type == 'package' ? 'package' : '',
memberPrice: goods.memberPrice,
is_print: 1,
product_type: goods.type,
is_time_discount: showLimitDiscount(goods)
})
// 清空套餐选中
selectedGroupSnap.value = [];
showShopsku.value = false;
} else {
let res = cartStore.carts.find(cart => cart.product_id == goods.id && goods.skuList[0].id)
emits('websocketsendMessage', {
id: res ? res.cartListId : '',
id: res ? res.id : '',
type: 'shopping',
suitNum: goods.suitNum,
table_code: uni.cache.get('tableCode'),
@@ -422,9 +601,10 @@
is_time_discount: showLimitDiscount(goods)
})
return;
}
close()
};
function showLimitDiscount(item) {
@@ -442,10 +622,7 @@
return false;
}
let res = null
if (props.goods.result === 'kong') {
//没有满足可添加或者编辑的规格
return;
}
if (i == '-') {
if (!res && shopCartNumber.value == props.goods.suitNum) {
uni.showToast({
@@ -457,8 +634,12 @@
shopCartNumber.value--;
}
} else {
if (!res && shopCartNumber.value < 1) {
if (props.goods.type == 'sku') {
if (!selSku.value) {
return
}
shopCartNumber.value = parseFloat(selSku.value.suitNum);
} else {
shopCartNumber.value = parseFloat(props.goods.suitNum);
@@ -470,28 +651,45 @@
};
</script>
<style lang="scss" scoped>
.box {
height: 100vh;
display: flex;
flex-direction: column;
.top {
width: 750rpx;
}
}
.shop_sku {
width: 100%;
// height: 100vh;
flex: 1;
position: relative;
border-radius: 20rpx;
background: #fff;
box-sizing: border-box;
overflow: hidden;
.positionabsolute {
position: absolute;
top: 30rpx;
z-index: 999;
left: 30rpx;
width: 60rpx;
height: 60rpx;
display: flex;
align-items: center;
justify-content: center;
background-color: #eee;
border-radius: 50%;
right: 30rpx;
}
// .positionabsolute {
// position: absolute;
// top: 30rpx;
// z-index: 999;
// left: 30rpx;
// width: 60rpx;
// height: 60rpx;
// display: flex;
// align-items: center;
// justify-content: center;
// background-color: #eee;
// border-radius: 50%;
// }
.shop_sku_name {
padding: 0 28rpx;
margin-top: 20rpx;
@@ -695,4 +893,38 @@
}
}
}
.relative {
position: relative;
}
.dot {
position: absolute;
right: -10rpx;
top: -10rpx;
background-color: #FF534B;
border-radius: 32rpx;
width: 30rpx;
font-size: 20rpx;
color: #fff;
height: 30rpx;
text-align: center;
overflow: hidden;
}
.vifgoodsImg {
width: 100%;
height: 204rpx;
position: absolute;
top: 0;
left: 0;
z-index: 20;
background-color: rgb(0, 0, 0, 0.5);
image {
padding: 30rpx;
width: 100%;
height: 100%;
}
}
</style>

View File

@@ -160,7 +160,10 @@
<!-- <view class="btnClick"
@tap.stop="$u.throttle(() => singleclick(item, '-'), 500)"></view> -->
</view>
<text class="num">{{ ifcartNumber(item) }}</text>
<!-- <text class="num">{{ ifcartNumber(item) }}</text> -->
<text class="dot num"
v-if="returnGoodsImCartNum(item1)">{{ returnGoodsImCartNum(item1) < 99 ? returnGoodsImCartNum(item1) : '99+' }}</text>
<view class="btn">
<up-icon name="plus-circle-fill" color="#E9AB7A" size="25"></up-icon>
<!-- <view class="btnClick"
@@ -571,7 +574,17 @@
<Loading :isLoading="!useSocket.isConnected" />
<ModalList></ModalList>
<recommendGoodsModal v-if="isDataLoaded" @onBuyClick="onBuyClick"></recommendGoodsModal>
<goodsModal v-model="showGoodsModal" :goods="specifications.item" @prveImgs="prveImgs" @websocketsendMessage="websocketsendMessage"></goodsModal>
<view
v-for="(item,index) in goodsModalList" :key="index"
>
<goodsModal :key="index" v-model="item.show" :goods="item.goods" @prveImgs="prveImgs" @close="goodsModalClose(index)"
@websocketsendMessage="websocketsendMessage"
@modalAdd="modalAdd"
:GoodsIDInCartNumMap="GoodsIDInCartNumMap"
></goodsModal>
</view>
<xbSwiperPreview :visable="showPrveImg" :imgs="prveImgsList" @update:visable="updateShowPrveImg">
</xbSwiperPreview>
<!-- 显示选择人数popup -->
@@ -849,7 +862,7 @@
// 购物车对应的商品数
const GoodsIDInCartNumMap = computed(() => {
const map = {}
for (let cart in cartStore.carts) {
for (let cart of cartStore.carts) {
if (map[cart.product_id]) {
map[cart.product_id] += cart.number * 1
} else {
@@ -864,7 +877,10 @@
* 返回购物车对应的商品数量
*/
function returnGoodsImCartNum(goods) {
if (GoodsIDInCartNumMap.value.hasOwnProperty([goods.id])) {
if(!goods){
return 0
}
if (GoodsIDInCartNumMap.value.hasOwnProperty(goods.id)) {
GoodsIDInCartNumMap.value[goods.id]
}
return 0
@@ -1357,6 +1373,15 @@
prveImgs(res.images);
}
const goodsModalList=ref([])
function goodsModalClose(index){
goodsModalList.value.splice(index,1)
}
function modalAdd(item){
clickspecifications(item)
}
//获取多规格数据
const clickspecifications = async (item, index, indexs, type) => {
console.log('clickspecifications', item);
@@ -1372,7 +1397,10 @@
// }
if (item.isSoldStock == 1 || (item.isSaleTime == 0 && !item.isSaleTimeshow)) {
return false;
return uni.showToast({
title:'商品已下架或不在可售时间内',
icon:'none'
});
}
shopCartNumber.value = 0;
@@ -1418,7 +1446,11 @@
// 给默认数量
specifications.item.amountcartNumber = 0;
// showShopsku.value = true;
showGoodsModal.value=true
goodsModalList.value.push({
show:true,
goods:specifications.item
})
// showGoodsModal.value=true
};
// 判断商品是否在可售时间内
const isProductAvailable = async (sellDaysStr, startTimeStr, endTimeStr) => {