增加相关商品推荐功能
This commit is contained in:
@@ -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 秒
|
||||
|
||||
@@ -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>
|
||||
@@ -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) => {
|
||||
|
||||
Reference in New Issue
Block a user