Task:点击购物车图标加入购物车

This commit is contained in:
modendeveloper
2025-01-14 23:42:33 +08:00
parent f8b6d72a59
commit 46b858b700
10 changed files with 485 additions and 24 deletions
+17 -1
View File
@@ -1,6 +1,6 @@
<template>
<view>
<view class="product-window" :class="attr.cartAttr === true ? 'on' : ''">
<view class="product-window" :class="attr.cartAttr === true ? 'on' : ''" :style="{paddingBottom: paddingBottom}">
<view class="textpic acea-row row-between-wrapper">
<view class="pictrue" @click="previewImg(attrObj.productSelect.image)">
<image :src="attrObj.productSelect.image" class="image" />
@@ -59,6 +59,14 @@
>+</view>
</view>
</view>
<view class="v12-px-2 v12-mt-3" v-if="showOk">
<u-button
shape="circle"
color="#C52733"
@click="$emit('ok')"
:disabled="(attr.productSelect.stock === 0 && attr.cartAttr)"
>加入购物车</u-button>
</view>
</view>
<view class="mask" @touchmove.prevent :hidden="attr.cartAttr === false" @click="closeAttr"></view>
</view>
@@ -67,6 +75,14 @@
export default {
name: "ProductWindow",
props: {
paddingBottom: {
type: String,
default: '140rpx'
},
showOk: {
type: Boolean,
default: false
},
attr: {
type: Object,
default: () => {
+1 -1
View File
@@ -36,7 +36,7 @@
<view class="price">
<text class="price-txt price-red">{{ item[priceKey] }}</text>
</view>
<view class="btn">
<view class="btn" @click.stop="$emit('add', item)">
<image
:src="webUrl + '/home/icon-cart.png'"
class="img"
+376
View File
@@ -0,0 +1,376 @@
import {
getCartCount,
getProductCode,
getProductDetail,
postCartAdd,
getProductSkuBySelected
} from '@/api/store'
export default {
data() {
return {
isWenwan: 0,
qualifications: [],
source: '',
isOpen: false,
attrTxt: '',
attrValue: '',
id: null,
productValueArr: [],
attr: {
cartAttr: false,
cart_num: 1,
defaultSku: [],
defaultSkuIndex: [],
productAttr: [],
productSelect: {
cart_num: 1,
earnPoints: 0,
image: '',
otPrice: 0,
price: 0,
stock: 0,
store_name: '',
unique: ''
}
},
cart_num: 1
}
},
methods: {
getSkuActiveStatus(selectedSku) {
getProductSkuBySelected({ id: this.id, selectedSku }).then(res => {
const { success, data } = res
if (success) {
for (const key in data) {
if (data[key]) {
this.attr.productAttr.map(item => {
if (item.attrName === key) {
item.attrValue.map(subItem => {
data[key].map(dataItem => {
if (dataItem.sku === subItem.attr) {
subItem.canUsed = dataItem.canUsed
}
})
})
}
})
}
}
console.log(this.$refs);
this.$refs.attrWindow.reRender(this.attr)
}
})
},
productCon() {
getProductDetail(this.id).then(res => {
const { data } = res
this.storeInfo = {...data.storeInfo}
if(data.storeInfo.stock === 0) {
uni.showToast({
title: "产品库存不足,请选择其他商品",
icon: "none",
duration: 5000
})
return
}
this.isWenwan = data.isWenwan
this.qualifications = data.qualifications || []
// 给 attr 赋值,将请求回来的规格赋值给 attr
if (this.source !== 'pre' && this.source !== 'day' && this.source !== 'kill' && this.source !== 'spe') {
// this.$set(this.attr, 'productAttr', data.productAttr)
this.attr.productAttr = data.productAttr || []
this.productValueArr = []
for (const key in data.productValue) {
this.productValueArr.push({
attrItemkey: key,
...data.productValue[key]
})
}
// 初始化认为所有的规格都是可以选的
this.attr.productAttr.map(item => {
item.attrValue.map(subItem => {
subItem.canUsed = true
})
})
}
this.attr.defaultSku = data.defaultSku
this.attr.defaultSkuIndex = data.defaultSkuIndex
this.DefaultSelect()
// 是否单一规格
const onlyOne = Object.keys(data.productValue).length === 1
if(onlyOne) {
this.handleOk()
return
}
this.attr.cartAttr = !this.isOpen ? true : false
})
},
getAttrItemData(attr) {
let result = {}
this.productValueArr.map(item => {
if (item.attrItemkey === attr) {
result = item
}
})
return result
},
// 默认选中属性
DefaultSelect() {
const productAttr = this.attr.productAttr
const productAttrLength = productAttr.length
this.attr.productAttr.map((item, index) => {
item.attrValue.map((subItem, subIndex) => {
if (this.attr.defaultSkuIndex[index] === subIndex) {
subItem.check = true
} else {
subItem.check = false
}
})
})
const skuKey = (this.attr.defaultSku || []).join(',')
if (!skuKey) {
return
}
const productSelect = this.getAttrItemData(skuKey)
this.attrValue = skuKey
this.attrTxt = '已选择'
if (productSelect && productAttrLength) {
// this.$set(
// this.attr.productSelect,
// 'store_name',
// this.storeInfo.storeName
// )
// this.$set(this.attr.productSelect, 'image', productSelect.image)
// this.$set(this.attr.productSelect, 'price', productSelect.price)
// this.$set(this.attr.productSelect, 'otPrice', productSelect.otPrice)
// this.$set(this.attr.productSelect, 'stock', productSelect.stock)
// this.$set(this.attr.productSelect, 'unique', productSelect.unique)
// this.$set(this.attr.productSelect, 'earnPoints', productSelect.earnPoints)
// this.$set(this.attr.productSelect, 'cart_num', 1)
// this.$set(this, 'attrValue', value.sort().join(',')) // 作废
// this.$set(this, 'attrValue', skuKey)
// this.$set(this, 'attrTxt', '已选择')
this.attr.productSelect = {
image: productSelect.image,
price: productSelect.price,
otPrice: productSelect.otPrice,
stock: productSelect.stock,
earnPoints: productSelect.earnPoints,
unique: productSelect.unique,
store_name: this.storeInfo.storeName,
cart_num: 1
}
this.getSkuActiveStatus(skuKey)
} else if (!productSelect && productAttrLength) {
// this.$set(
// this.attr.productSelect,
// 'store_name',
// this.storeInfo.storeName
// )
// this.$set(this.attr.productSelect, 'image', this.storeInfo.image)
// this.$set(this.attr.productSelect, 'price', this.storeInfo.price)
// this.$set(this.attr.productSelect, 'otPrice', this.storeInfo.otPrice)
// this.$set(this.attr.productSelect, 'stock', 0)
// this.$set(this.attr.productSelect, 'earnPoints', 0)
// this.$set(this.attr.productSelect, 'unique', '')
// this.$set(this.attr.productSelect, 'cart_num', 0)
// this.$set(this, 'attrValue', '')
// this.$set(this, 'attrTxt', '请选择')
this.attr.productSelect = {
image: this.storeInfo.image,
price: this.storeInfo.price,
otPrice: this.storeInfo.otPrice,
stock: 0,
earnPoints: 0,
unique: '',
store_name: this.storeInfo.storeName,
cart_num: 1
}
} else if (!productSelect && !productAttrLength) {
// this.$set(
// this.attr.productSelect,
// 'store_name',
// this.storeInfo.storeName
// )
// this.$set(this.attr.productSelect, 'image', this.storeInfo.image)
// this.$set(this.attr.productSelect, 'price', this.storeInfo.price)
// this.$set(this.attr.productSelect, 'otPrice', this.storeInfo.otPrice)
// this.$set(this.attr.productSelect, 'stock', this.storeInfo.stock)
// this.$set(this.attr.productSelect, 'earnPoints', 0)
// this.$set(
// this.attr.productSelect,
// 'unique',
// this.storeInfo.unique || ''
// )
// this.$set(this.attr.productSelect, 'cart_num', 1)
this.attr.productSelect = {
image: this.storeInfo.image,
price: this.storeInfo.price,
otPrice: this.storeInfo.otPrice,
stock: this.storeInfo.stock,
earnPoints: 0,
unique: this.storeInfo.unique || '',
store_name: this.storeInfo.storeName,
cart_num: 1
}
// this.$set(this, 'attrValue', '')
// this.$set(this, 'attrTxt', '请选择')
}
},
// 点击加入购物车按钮
addToCart(item, id = 'id') {
console.log(item, 'addToCart --------- item');
this.id = item[id]
this.$nextTick(() => {
this.productCon()
})// if(this.attr.cartAttr && !this.isOpen){
// return this.isOpen = true
// }
console.log(this.$refs.attrWindow, '--222--');
},
handleOk() {
const productSelect = this.getAttrItemData(this.attrValue)
// 如果有属性,没有选择,提示用户选择
const hasNo = (this.attr.productAttr.length && productSelect === undefined && this.isOpen) || productSelect.stock === 0
if (hasNo) {
uni.showToast({
title: "产品库存不足,请选择其他商品",
icon: "none",
duration: 5000
})
return
}
const q = {
productId: this.id,
cartNum: this.attr.productSelect.cart_num,
new: 0,
uniqueId: this.attr.productSelect !== undefined ? this.attr.productSelect.unique : ''
}
postCartAdd(q).then(res => {
this.isOpen = false
this.attr.cartAttr = false
uni.showToast({
title: "添加购物车成功",
icon: "none",
duration: 2000
})
})
},
ChangeCartNum(changeValue) {
// changeValue:是否 加|减
// 获取当前变动属性
const productSelect = this.getAttrItemData(this.attrValue)
// 如果没有属性,赋值给商品默认库存
if (productSelect === undefined && !this.attr.productAttr.length) {
productSelect = this.attr.productSelect
}
// 无属性值即库存为0;不存在加减
if (productSelect === undefined) return
let stock = productSelect.stock || 0
let num = this.attr.productSelect
if (changeValue) {
num.cart_num++
if (num.cart_num > stock) {
if(stock < 1) {
this.$set(this.attr.productSelect, 'cart_num', 1)
this.$set(this, 'cart_num', 1)
} else {
this.$set(this.attr.productSelect, 'cart_num', stock)
this.$set(this, 'cart_num', stock)
}
} else {
if (num.cart_num < 1) {
this.$set(this.attr.productSelect, 'cart_num', 1)
this.$set(this, 'cart_num', 1)
} else {
this.$set(this.attr.productSelect, 'cart_num', num.cart_num)
this.$set(this, 'cart_num', num.cart_num)
}
}
} else {
num.cart_num--
if (num.cart_num < 1) {
this.$set(this.attr.productSelect, 'cart_num', 1)
this.$set(this, 'cart_num', 1)
} else {
this.$set(this.attr.productSelect, 'cart_num', num.cart_num)
this.$set(this, 'cart_num', num.cart_num)
}
}
},
// 关闭属性
changeattr(msg) {
// 修改了规格
this.attr.cartAttr = msg
this.$set(this.attr.productSelect, 'cart_num', 1)
this.isOpen = false
},
// 打开属性插件
selecAttrTap() {
this.attr.cartAttr = true
this.isOpen = true
},
ChangeAttr(res) {
const { index, subIndex, value } = res
// 修改了规格
const productSelect = this.getAttrItemData(value)
if (productSelect) {
this.attr.productAttr[index].attrValue.map((subItem, subIdx) => {
subItem.check= false
if (subIndex === subIdx) {
subItem.check = true
}
})
this.$set(this.attr.productSelect, 'image', productSelect.image)
this.$set(this.attr.productSelect, 'price', productSelect.price)
this.$set(this.attr.productSelect, 'otPrice', productSelect.otPrice)
this.$set(this.attr.productSelect, 'stock', productSelect.stock)
this.$set(this.attr.productSelect, 'unique', productSelect.unique)
this.$set(this.attr.productSelect, 'earnPoints', productSelect.earnPoints)
this.$set(this.attr.productSelect, 'cart_num', 1)
this.$set(this, 'attrValue', value)
this.$set(this, 'attrTxt', '已选择')
this.getSkuActiveStatus(value)
} else {
this.$set(this.attr.productSelect, 'image', this.storeInfo.image)
this.$set(this.attr.productSelect, 'price', this.storeInfo.price)
this.$set(this.attr.productSelect, 'otPrice', this.storeInfo.otPrice)
this.$set(this.attr.productSelect, 'stock', 0)
this.$set(this.attr.productSelect, 'unique', '')
this.$set(this.attr.productSelect, 'earnPoints', 0)
this.$set(this.attr.productSelect, 'cart_num', 0)
this.$set(this, 'attrValue', '')
this.$set(this, 'attrTxt', '请选择')
}
},
changeFun(opt) {
if (typeof opt !== 'object') opt = {}
let action = opt.action || ''
let value = opt.value === undefined ? '' : opt.value
this.cart_num = 1
this[action] && this[action](value)
},
// queryCartCount (isAnima) {
// const isLogin = this.isLogin
// if (isLogin) {
// getCartCount({
// numType: 0
// }).then(res => {
// this.CartCount = res.data.count
// //加入购物车后重置属性
// if (isAnima) {
// this.animated = true
// setTimeout(function () {
// this.animated = false
// }, 500)
// }
// })
// }
// },
}
}
+1
View File
@@ -21,6 +21,7 @@
<view class="flex jc-between ai-center">
<text class="price">{{ item.price }}</text>
<image
@click.stop="$emit('add', item)"
:src="webUrl + '/home/icon-cart.png'"
class="btn"
/>
+16 -2
View File
@@ -248,6 +248,7 @@
v-else
:item="item"
@view="goGoodsCon(item)"
@add="addToCart(item)"
/>
</view>
</view>
@@ -284,6 +285,7 @@
v-else
:item="item"
@view="goGoodsCon(item)"
@add="addToCart(item)"
/>
</view>
</view>
@@ -323,6 +325,15 @@
@click="setTopHandle"
/>
</u-back-top>
<ProductWindow
ref="attrWindow"
:attr="attr"
:cartNum="cart_num"
:showOk="true"
@changeFun="changeFun"
@ok="handleOk"
paddingBottom="200rpx"
/>
<xdd-tabbar :curr-index="0" />
</view>
</template>
@@ -334,6 +345,8 @@ import { getCouponReceive } from '@/api/user'
import { getHomeData, getShareImage } from '@/api/public'
import { sharpBannar } from '@/api/goods'
import { pageListenMixins } from '@/mixins/pageListenMixins'
import ProductWindow from '@/components/ProductWindow'
import goCartMixin from '@/mixins/goCartMixins'
import {
getCurAddress,
getLocationPromise,
@@ -344,9 +357,10 @@ export default {
name: 'IndexPage',
components: {
XddTabbar,
XddProductItem
XddProductItem,
ProductWindow
},
mixins: [pageListenMixins],
mixins: [pageListenMixins, goCartMixin],
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
+14 -3
View File
@@ -56,7 +56,7 @@
<information :landmarkDataId="landmarkDataId"></information>
</view>
<view v-if="actived === 4">
<goods :goods="goods" v-if="goods.length > 0"></goods>
<goods :goods="goods" v-if="goods.length > 0" @add='addToCart($event, "productId")'></goods>
<!-- <image
v-if="isCompleteLoadGood"
:src="webUrl + '/home/no-data-bg.png'"
@@ -76,6 +76,14 @@
:show-avatar="false"
/>
<shareImg ref="shareImg"></shareImg>
<ProductWindow
ref="attrWindow"
:attr="attr"
:cartNum="cart_num"
:showOk="true"
@changeFun="changeFun"
@ok="handleOk"
/>
</view>
</template>
@@ -87,10 +95,12 @@ import {
} from "@/api/product"
import goods from "./components/goods.vue"
import { pageListenMixins } from '@/mixins/pageListenMixins'
import goCartMixin from '@/mixins/goCartMixins'
import projects from './components/projects.vue'
import culture from "./components/culture.vue"
import information from "./components/information.vue"
import shareImg from "./components/shareImg.vue"
import ProductWindow from '@/components/ProductWindow'
export default {
name: 'LandMarkPage',
components: {
@@ -98,9 +108,10 @@ export default {
projects,
culture,
information,
shareImg
shareImg,
ProductWindow
},
mixins: [pageListenMixins],
mixins: [pageListenMixins, goCartMixin],
data() {
return {
actived: 1,
+14 -9
View File
@@ -29,7 +29,7 @@
<image :src="webUrl+'/20210806121714655368.png'" mode="" style="width: 36rpx;height: 36rpx;"></image>
</view>
</view>
<view v-if="couponListLimit2ToShow.length > 0 || attr.productSelect.earnPoints" class="v12-mt-1 v12-mb-3">
<view v-if="couponListLimit2ToShow.length > 0 || attr.productSelect.earnPoints" class="v12-mt-1 v12-mb-1">
<view class="cell flex jc-between ai-center">
<view v-if="couponListLimit2ToShow.length > 0" class="v12-justify-start">
<view
@@ -43,13 +43,7 @@
</view>
</view>
</view>
<view
v-if="attr.productSelect.earnPoints"
:class="couponListLimit2ToShow.length > 0 ? 'earn-points' : ''"
class="value value2 v12-font-24 v12-primary-text"
>
预计获得{{ attr.productSelect.earnPoints }}积分
</view>
<view
v-if="couponListLimit2ToShow.length > 0"
class="value value2 v12-font-24 v12-primary-text"
@@ -60,6 +54,13 @@
</view>
</view>
</view>
<view
v-if="attr.productSelect.earnPoints"
:class="couponListLimit2ToShow.length > 0 ? 'earn-points' : ''"
class="value value2 v12-font-24 v12-primary-text"
>
预计获得{{ attr.productSelect.earnPoints }}积分
</view>
</view>
<view class="introduce bold">{{ storeInfo.storeName }}</view>
<rich-text class="subInfo" :nodes="storeInfo.storeInfo" v-if="storeInfo.storeInfo"/>
@@ -1009,6 +1010,7 @@ export default {
// 产品详情接口
productCon() {
const from = this.location
if (this.$deviceType == 'app') {
from.from = 'app'
}
@@ -1332,6 +1334,8 @@ export default {
goCat(news) {
const that = this
const productSelect = this.getAttrItemData(this.attrValue)
console.log(this.attr);
// 打开属性
if (that.attrValue) {
// 默认选中了属性,但是没有打开过属性弹窗还是自动打开让用户查看默认选中的属性
@@ -2070,7 +2074,8 @@ export default {
}
.earn-points {
flex: 1;
padding: 0 0 0 12rpx;
// padding: 0 0 0 12rpx;
margin-bottom: 10rpx;
box-sizing: border-box;
}
</style>
+17 -4
View File
@@ -76,7 +76,10 @@
</view>
<view class="vip-money">{{ force2Decimal(item.otPrice) }}</view>
</view>
<view class="sale">已售{{ item.sales }}</view>
<view class="" @click.stop="addToCart(item)">
<image class="logo" :src="webUrl+'/orderIcon/组 355.png'" mode="" style="margin-right:0; width: 34rpx; height:34rpx"/>
</view>
<!-- <view class="sale">已售{{ item.sales }}</view> -->
</view>
</view>
</view>
@@ -160,26 +163,36 @@
v-if="searchType === 'good' && loadend && list.length === 0"
/>
</view>
<ProductWindow
ref="attrWindow"
:attr="attr"
:cartNum="cart_num"
:showOk="true"
@changeFun="changeFun"
@ok="handleOk"
/>
</view>
</template>
<script>
import { getProducts, getHotels } from '@/api/store'
import ProductWindow from '@/components/ProductWindow'
import { mapGetters } from 'vuex'
import NP from 'number-precision'
import NoGoodData from '@/components/good/NoData'
import Recommend from '@/components/Recommend'
import goCartMixin from '@/mixins/goCartMixins'
export default {
name: 'GoodsList',
components: {
NoGoodData,
ProductWindow,
Recommend
},
data: function () {
mixins: [goCartMixin],
data () {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,
list: [],
query: {
page: 1,
+14 -3
View File
@@ -571,7 +571,7 @@
<text class="v12-font-bold v12-primary-text v12-font-24"></text>
<text class="v12-font-bold v12-primary-text v12-font-28">{{ item.productPrice }}</text>
</view>
<view class="btn">
<view class="btn" @click.stop="addToCart(item, 'productId')">
<image
:src="webUrl + '/home/icon-cart.png'"
class="img"
@@ -632,6 +632,14 @@
/>
</view>
</u-popup>
<ProductWindow
ref="attrWindow"
:attr="attr"
:cartNum="cart_num"
:showOk="true"
@changeFun="changeFun"
@ok="handleOk"
/>
</view>
</template>
@@ -653,6 +661,8 @@ import {
getShareImg,
getSaleList
} from '@/api/qianxian'
import ProductWindow from '@/components/ProductWindow'
import goCartMixin from '@/mixins/goCartMixins'
import {formatDateTime} from '@/utils'
import {getUrlParam} from '@/utils/common.js'
import imgBox from '@/components/imageTypeSet/imagebox.vue'
@@ -663,9 +673,10 @@ import { pageListenMixins } from '@/mixins/pageListenMixins'
export default {
components: {
imgBox,
XddProductItem
XddProductItem,
ProductWindow
},
mixins: [pageListenMixins],
mixins: [pageListenMixins, goCartMixin],
data() {
return {
saleActived: null,
+15 -1
View File
@@ -159,7 +159,7 @@
<text class="v12-font-32"></text>
<text class="v12-font-36">{{ item.price }}</text>
</view>
<view class="cart-img">
<view class="cart-img" @click.stop="addToCart(item, 'productId')">
<image
class="cart-img"
:src="webUrl + '/orderIcon/组 355.png'"
@@ -177,11 +177,25 @@
</view>
</view>
</view>
<ProductWindow
ref="attrWindow"
:attr="attr"
:cartNum="cart_num"
:showOk="true"
@changeFun="changeFun"
@ok="handleOk"
/>
</view>
</template>
<script>
import { getRank, getFoods, getRecipe } from "@/api/health";
import ProductWindow from '@/components/ProductWindow'
import goCartMixin from '@/mixins/goCartMixins'
export default {
components: {
ProductWindow
},
mixins: [goCartMixin],
data() {
return {
webUrl: this.$VUE_APP_RESOURCES_URL,