Browse Source

颜选商城sku版本修改调整

yuwenjun1997 2 years ago
parent
commit
946079cc7d

+ 0 - 1
common/auth.js

@@ -6,7 +6,6 @@ export function wxLogin() {
         uni.login({
         uni.login({
             provider: 'weixin',
             provider: 'weixin',
             success(res) {
             success(res) {
-                console.log(res.code)
                 resolve(res.code)
                 resolve(res.code)
             },
             },
             fail() {
             fail() {

+ 106 - 0
common/goods.helper.js

@@ -0,0 +1,106 @@
+// 获取产品活动类型 (拼团 活动价 限时特价)
+export function generateActivityType(productData) {
+    const { collageStatus = 0, activeStatus = 0, discountStatus = 0 } = productData
+    // 拼团价
+    if (collageStatus > 0) {
+        return 'group' // 拼团价
+    }
+    // 限时活动
+    else if (discountStatus > 0) {
+        return 'time-limit'
+    }
+    // 普通活动价
+    else if (activeStatus > 0) {
+        return 'activity'
+    }
+    // 普通商品
+    return 'normal' // 普通价
+}
+
+// 获取产品价格类型
+export function generatePriceType(productData) {
+    const { couponStatus = 0, collageStatus = 0, activeStatus = 0, discountStatus = 0, couponId } = productData
+    // 拼团价
+    if (collageStatus > 0) {
+        if (couponStatus === 1 && couponId) {
+            return 'groupWithCoupon' // 拼团券后价
+        } else {
+            return 'group' // 拼团价
+        }
+    }
+    // 限时活动
+    else if (discountStatus > 0 || activeStatus > 0) {
+        if (couponStatus === 1 && couponId) {
+            return 'activityWithCoupon' // 券后价
+        } else {
+            return 'normal' // 限时活动价格
+        }
+    }
+    // 无活动价
+    else {
+        if (couponStatus === 1 && couponId) {
+            return 'normalWithCoupon' // 普通券后价
+        } else {
+            return 'normal' // 普通价
+        }
+    }
+}
+
+// 导航栏按钮类别
+const navbarButtonGroup = {
+    // 仅拼团
+    group: {
+        left: ['单独购买', '¥1000.00'],
+        right: ['拼团购买', '¥1000.00']
+    },
+
+    // 拼团 + 优惠券
+    groupWithCoupon: {
+        left: ['领券单独购买', '¥1000.00'],
+        right: ['领券拼团购买', '¥1000.00']
+    },
+
+    // 限时活动 / 活动价 + 优惠券
+    activityWithCoupon: {
+        left: ['加入购物车'],
+        right: ['领券购买', '¥1000.00']
+    },
+
+    // 限时活动 / 活动价 + 优惠券
+    normalWithCoupon: {
+        left: ['加入购物车'],
+        right: ['领券购买', '¥1000.00']
+    },
+
+    // 普通方式 不使用优惠券
+    normal: {
+        left: ['加入购物车'],
+        right: ['立即购买']
+    }
+}
+
+export function generateNavbarButtonText(productData) {
+    const { priceType } = productData
+    const navbarButton = navbarButtonGroup[priceType]
+    // 拼团券后价购买
+    if (priceType === 'groupWithCoupon') {
+        navbarButton.left[1] = `¥${productData.normalCouponPrice.toFixed(2)}`
+        navbarButton.right[1] = `¥${productData.couponPrice.toFixed(2)}`
+    }
+    // 拼团价购买
+    else if (priceType === 'group') {
+        navbarButton.left[1] = `¥${productData.normalPrice.toFixed(2)}`
+        navbarButton.right[1] = `¥${productData.price.toFixed(2)}`
+    }
+    // 活动价券后价购买(限时特价|普通活动)
+    else if (priceType === 'activityWithCoupon') {
+        navbarButton.right[1] = `¥${productData.couponPrice.toFixed(2)}`
+    }
+    // 普通价券后价购买
+    else if (priceType === 'normalWithCoupon') {
+        navbarButton.right[1] = `¥${productData.couponPrice.toFixed(2)}`
+    } else {
+        navbarButton.right[1] = ''
+    }
+    return navbarButton
+}

+ 50 - 18
components/views/cm-cart-product/cm-cart-product.vue

@@ -6,26 +6,34 @@
             <template v-if="isExpired">
             <template v-if="isExpired">
                 <view class="tip">商品已下架</view>
                 <view class="tip">商品已下架</view>
             </template>
             </template>
+
             <template v-else>
             <template v-else>
                 <view class="unit">规格:{{ productInfo.productUnit }}</view>
                 <view class="unit">规格:{{ productInfo.productUnit }}</view>
-                <view class="tags">
-                    <!-- 拼团价  活动价  限时特价  券后价   -->
-                    <view class="tag cx" v-if="userId === productInfo.heUserId">促销</view>
-                    <view class="tag cx" v-else>自营</view>
-                    <view class="tag pt" v-if="productInfo.collageStatus > 0">拼团价</view>
-                    <view class="tag hd" v-else-if="productInfo.activeStatus > 0">活动价</view>
-                    <view class="tag other" v-else-if="productInfo.discountStatus > 0">限时特价</view>
-                    <!-- <view class="tag other" v-else-if="productInfo.couponStatus > 1">{{ productInfo.couponInfo }}</view> -->
-                    <!-- <view class="tag other" v-else-if="productInfo.couponStatus > 0">券后价</view> -->
-                </view>
-                <view class="price">
-                    <text>¥{{ productInfo.price | priceFormat }}</text>
-                    <text class="delete" v-if="productInfo.normalPrice">
-                        ¥{{ productInfo.normalPrice | priceFormat }}
-                    </text>
-                </view>
-                <cm-number-box class="numberbox" v-model="productInfo.num" @change="change"></cm-number-box>
-                <!-- <uni-number-box class="numberbox" v-model="productInfo.num" @change="change" :min="1"></uni-number-box> -->
+                <template>
+                    <view class="tags">
+                        <!-- 拼团价  活动价  限时特价  券后价   -->
+                        <view class="tag cx" v-if="userId === productInfo.heUserId">促销</view>
+                        <view class="tag cx" v-else>自营</view>
+                        <view class="tag pt" v-if="productInfo.collageStatus > 0">拼团价</view>
+                        <view class="tag hd" v-else-if="productInfo.activeStatus > 0">活动价</view>
+                        <view class="tag other" v-else-if="productInfo.discountStatus > 0">限时特价</view>
+                    </view>
+                    <template v-if="emptyStock">
+                        <view class="empty-stock">
+                            <view class="tip">重新选择商品规格</view>
+                            <view class="btn" @click="$emit('unitChange', productInfo)">重选</view>
+                        </view>
+                    </template>
+                    <template v-else>
+                        <view class="price">
+                            <text>¥{{ productInfo.price | priceFormat }}</text>
+                            <text class="delete" v-if="productInfo.normalPrice">
+                                ¥{{ productInfo.normalPrice | priceFormat }}
+                            </text>
+                        </view>
+                        <cm-number-box class="numberbox" v-model="productInfo.num" @change="change"></cm-number-box>
+                    </template>
+                </template>
             </template>
             </template>
         </view>
         </view>
     </view>
     </view>
@@ -39,6 +47,10 @@ export default {
             type: Boolean,
             type: Boolean,
             default: false
             default: false
         },
         },
+        emptyStock: {
+            type: Boolean,
+            default: false
+        },
         productInfo: {
         productInfo: {
             type: Object,
             type: Object,
             default: () => {}
             default: () => {}
@@ -105,6 +117,26 @@ export default {
         color: #f83c6c;
         color: #f83c6c;
     }
     }
 
 
+    .empty-stock {
+        display: flex;
+        align-items: center;
+        .tip {
+            margin-top: 0;
+            font-size: 28rpx;
+            color: #666666;
+        }
+        .btn {
+            font-size: 24rpx;
+            color: #ff457b;
+            border: 1rpx solid #ff457b;
+            margin-left: 16rpx;
+            box-sizing: border-box;
+            line-height: 30rpx;
+            padding: 0 12rpx;
+            border-radius: 15rpx;
+        }
+    }
+
     .unit {
     .unit {
         min-height: 28rpx;
         min-height: 28rpx;
         font-size: 20rpx;
         font-size: 20rpx;

+ 32 - 5
components/views/cm-cart-supplier-area/cm-cart-supplier-area.vue

@@ -13,14 +13,26 @@
             <view class="section" v-for="(item, index) in productList" :key="item.productId">
             <view class="section" v-for="(item, index) in productList" :key="item.productId">
                 <tui-divider height="60" v-if="index !== 0"></tui-divider>
                 <tui-divider height="60" v-if="index !== 0"></tui-divider>
                 <view class="checkbox">
                 <view class="checkbox">
-                    <label class="icon iconfont " :class="isChecked(item.productId) ? 'icon-xuanze' : 'icon-weixuanze'">
-                        <checkbox :value="item.productId" :checked="item.checked" v-show="false" />
+                    <label
+                        class="icon iconfont "
+                        :class="isChecked(item.productId) ? 'icon-xuanze' : 'icon-weixuanze'"
+                        :style="{ color: item.stock === 0 && !isDeleted ? '#ddd' : '' }"
+                        @click="onLabelClick(item)"
+                    >
+                        <checkbox
+                            :value="item.productId"
+                            :checked="item.checked"
+                            v-show="false"
+                            :disabled="item.stock === 0 && !isDeleted"
+                        />
                     </label>
                     </label>
                     <cm-cart-product
                     <cm-cart-product
                         class="product"
                         class="product"
                         :isExpired="false"
                         :isExpired="false"
+                        :emptyStock="item.stock === 0"
                         :productInfo="item"
                         :productInfo="item"
                         @countChange="onCountChange"
                         @countChange="onCountChange"
+                        @unitChange="onUnitChange"
                     ></cm-cart-product>
                     ></cm-cart-product>
                 </view>
                 </view>
             </view>
             </view>
@@ -35,6 +47,10 @@ export default {
         shopInfo: {
         shopInfo: {
             type: Object,
             type: Object,
             default: () => {}
             default: () => {}
+        },
+        isDeleted: {
+            type: Boolean,
+            default: false
         }
         }
     },
     },
     data() {
     data() {
@@ -54,8 +70,11 @@ export default {
         productList() {
         productList() {
             return this.shopInfo.productList || []
             return this.shopInfo.productList || []
         },
         },
+        selectProductList() {
+            return this.shopInfo.productList.filter(item => item.stock !== 0 || this.isDeleted)
+        },
         isCheckedAll() {
         isCheckedAll() {
-            return this.checkedList.length === this.productList.length
+            return this.checkedList.length === this.selectProductList.length
         }
         }
     },
     },
     methods: {
     methods: {
@@ -64,12 +83,12 @@ export default {
             if (this.isCheckedAll) {
             if (this.isCheckedAll) {
                 this.checkedList = []
                 this.checkedList = []
             } else {
             } else {
-                this.checkedList = this.productList.map(item => item.productId.toString())
+                this.checkedList = this.selectProductList.map(item => item.productId.toString())
             }
             }
         },
         },
         // 选中全部
         // 选中全部
         selectAll() {
         selectAll() {
-            this.checkedList = this.productList.map(item => item.productId.toString())
+            this.checkedList = this.selectProductList.map(item => item.productId.toString())
         },
         },
         // 取消全选
         // 取消全选
         unSelectAll() {
         unSelectAll() {
@@ -86,6 +105,14 @@ export default {
         // 商品数量改变
         // 商品数量改变
         onCountChange(e) {
         onCountChange(e) {
             this.$emit('countChange', e)
             this.$emit('countChange', e)
+        },
+        // 商品规格修改
+        onUnitChange(e) {
+            this.$emit('unitChange', e)
+        },
+        onLabelClick(item) {
+            if (item.stock !== 0) return
+            this.$toast.error('请重新选择商品规格')
         }
         }
     }
     }
 }
 }

+ 563 - 0
components/views/cm-goods-buy-popup/cm-goods-buy-popup.vue

@@ -0,0 +1,563 @@
+<template>
+    <uni-popup type="bottom" class="uni-popup" ref="popup" @change="handleChange">
+        <view class="close iconfont icon-iconfontguanbi" @click="handleClose"></view>
+        <view class="popup-content" v-if="currentSku">
+            <view class="goods-info">
+                <image class="cover" :src="product.mainImage"></image>
+                <!-- 普通价格,阶梯价格,拼团价格,限时特价 -->
+                <view class="info">
+                    <view class="price row">
+                        <text class="label">单价:</text>
+                        <text class="amount" v-text="price"></text>
+                    </view>
+                    <view class="row tags">
+                        <!-- 券后价 -->
+                        <template v-if="couponPriceFlag">
+                            <view class="tag-qh">券后价¥{{ couponPrice }}</view>
+                        </template>
+                        <template v-if="activityType === 'group'">
+                            <view class="tag-pt">{{ collageInfo.memberNum }}人拼团</view>
+                        </template>
+                        <template v-if="activityType === 'activity'">
+                            <view class="tag-hd">活动价</view>
+                            <view class="tag-text">查看活动价</view>
+                        </template>
+                        <template v-if="activityType === 'time-limit'">
+                            <view class="tag-xs">限时特价</view>
+                        </template>
+                    </view>
+                </view>
+            </view>
+            <!-- 产品规格 -->
+            <view class="buy-unit">
+                <view class="label">规格:</view>
+                <scroll-view scroll-y="true" class="unit-wrapper">
+                    <view class="unit-list">
+                        <template v-for="item in skusList">
+                            <view
+                                class="unit"
+                                :class="{
+                                    disabled: item.stock === 0,
+                                    active: item.skuId === currentSkuId && item.stock !== 0
+                                }"
+                                :key="item.skuId"
+                                v-text="item.unit"
+                                @click="handleChooseUtil(item)"
+                            ></view>
+                        </template>
+                    </view>
+                </scroll-view>
+            </view>
+            <!-- 购买数量 -->
+            <view class="buy-number">
+                <view class="label">购买数量:</view>
+                <cm-number-box v-model.lazy="count" :max="limitedNum"></cm-number-box>
+            </view>
+            <!-- 优惠券 -->
+            <view class="coupon-tip">
+                <template v-if="couponTipFlag">
+                    <text>当前商品可使用</text>
+                    <text class="active" v-text="couponTip">满300减200元</text>
+                    <text>优惠券</text>
+                </template>
+            </view>
+            <!-- 操作 -->
+            <view class="control" :class="{ disabled: disabled }">
+                <!-- 加入购物车 -->
+                <template v-if="useType === 'cart'">
+                    <view class="btn btn-confirm" @click="handleClick('cart')">确定</view>
+                </template>
+                <!-- 加入购物车 / 立即购买区域 -->
+                <template v-if="useType === 'buy'">
+                    <template v-if="groupPriceFlag">
+                        <template v-if="couponPriceFlag">
+                            <view class="btn btn-confirm" @click="handleClick('buy')">领券购买</view>
+                        </template>
+                        <template v-else>
+                            <view class="btn btn-confirm" @click="handleClick('buy')">立即购买</view>
+                        </template>
+                    </template>
+                    <template v-else>
+                        <template v-if="buttonType === 'left'">
+                            <view class="btn btn-confirm" @click="handleClick('cart')">确定</view>
+                        </template>
+                        <template v-else>
+                            <template v-if="couponPriceFlag">
+                                <view class="btn btn-confirm" @click="handleClick('buy')">领券购买</view>
+                            </template>
+                            <template v-else>
+                                <view class="btn btn-confirm" @click="handleClick('buy')">确定</view>
+                            </template>
+                        </template>
+                    </template>
+                </template>
+                <!-- 点击规格区域 -->
+                <template v-if="useType === 'unit'">
+                    <template v-if="groupPriceFlag">
+                        <view class="btn btn-cart" @click="handleClick('buy')">
+                            <text class="tip">{{ leftButton[0] }}</text>
+                            <text class="amount">{{ leftButton[1] }}</text>
+                        </view>
+                        <view class="btn btn-buy" @click="handleClick('buy')">
+                            <text class="tip">{{ rightButton[0] }}</text>
+                            <text class="amount">{{ rightButton[1] }}</text>
+                        </view>
+                    </template>
+                    <template v-else>
+                        <view class="btn btn-cart" @click="handleClick('cart')">{{ leftButton[0] }}</view>
+                        <view class="btn btn-buy" @click="handleClick('buy')">
+                            <template v-if="rightButton[1]">
+                                <text class="tip">{{ rightButton[0] }}</text>
+                                <text class="amount">{{ rightButton[1] }}</text>
+                            </template>
+                            <template v-else>
+                                {{ rightButton[0] }}
+                            </template>
+                        </view>
+                    </template>
+                </template>
+            </view>
+        </view>
+    </uni-popup>
+</template>
+
+<script>
+import { generateNavbarButtonText } from '@/common/goods.helper.js'
+import { mapGetters } from 'vuex'
+export default {
+    name: 'cm-goods-buy-popup',
+    props: {
+        value: {
+            type: Boolean,
+            default: false
+        },
+        product: {
+            type: Object,
+            default: () => {}
+        },
+        couponList: {
+            type: Array,
+            default: () => []
+        },
+        // 组件使用位置
+        useType: {
+            type: String,
+            default: 'buy'
+        },
+        // 按钮类型 left 左侧按钮点击 right 右侧按钮点击
+        buttonType: {
+            type: String,
+            default: 'left'
+        }
+    },
+    computed: {
+        // sku列表
+        skusList() {
+            return this.product.skus || []
+        },
+        // 选中的sku
+        currentSku() {
+            return this.skusList.find(sku => sku.skuId === this.currentSkuId) || {}
+        },
+        // 展示价格
+        price() {
+            return this.generatePrice()
+        },
+        // 活动类型
+        activityType() {
+            return this.currentSku.activityType
+        },
+        // 价格类型
+        priceType() {
+            return this.currentSku.priceType
+        },
+        // 券后价标识
+        couponPriceFlag() {
+            return ['groupWithCoupon', 'activityWithCoupon', 'normalWithCoupon'].includes(this.currentSku.priceType)
+        },
+        // 拼团价标识
+        groupPriceFlag() {
+            return ['groupWithCoupon', 'group'].includes(this.currentSku.priceType)
+        },
+        // 券后价
+        couponPrice() {
+            return this.buttonType === 'left' ? this.currentSku.normalCouponPrice : this.currentSku.couponPrice
+        },
+        // 优惠券提示标识
+        couponTipFlag() {
+            return this.currentSku.couponStatus > 0 && this.currentSku.couponId
+        },
+        // 优惠券提示
+        couponTip() {
+            if (this.currentSku.couponId) {
+                const currentCoupon = this.couponList.find(coupon => this.currentSku.couponId === coupon.couponId)
+                return currentCoupon.couponTitle
+            }
+            if (this.currentSku.couponInfo) {
+                return this.currentSku.couponInfo.split('|')[1]
+            }
+            return ''
+        },
+        // 商品拼团信息
+        collageInfo() {
+            return this.currentSku.collageProduct
+        },
+        limitedNum() {
+            return this.currentSku.stock === null ? 100 : this.currentSku.stock
+        },
+        disabled() {
+            return this.currentSku.stock === 0
+        }
+    },
+    data() {
+        return {
+            count: 1,
+            currentSkuId: 0,
+            leftButton: {},
+            rightButton: {}
+        }
+    },
+    watch: {
+        value: {
+            handler: function(val) {
+                if (val) {
+                    this.currentSkuId = this.product.skuId
+                    this.initNavbarButton()
+                    this.handleOpen()
+                } else {
+                    this.handleClose()
+                }
+            },
+            immediate: true
+        }
+    },
+    mounted() {
+        console.log('product', this.product)
+    },
+    methods: {
+        // 导航按钮点击事件
+        handleClick(type) {
+            if (this.disabled) {
+                return
+            }
+            this.$emit('confirm', {
+                type: type,
+                sku: this.currentSku,
+                count: this.count
+            })
+        },
+        // 初始化导航按钮文案
+        initNavbarButton() {
+            const navbarButton = generateNavbarButtonText(this.currentSku)
+            this.leftButton = navbarButton.left
+            this.rightButton = navbarButton.right
+        },
+        // 设置价格
+        generatePrice() {
+            // 拼团价
+            if (this.groupPriceFlag) {
+                // 单独购买价格
+                if (this.buttonType === 'left') {
+                    return this.currentSku.normalPrice
+                }
+            }
+
+            // 非阶梯价
+            if (this.currentSku.activeStatus <= 0) {
+                return this.currentSku.price
+            }
+            // 阶梯价列表为空
+            if (!this.currentSku.ladderList) {
+                return this.currentSku.price
+            }
+            // 阶梯价
+            const lastItem = this.currentSku.ladderList
+                .sort((a, b) => b.buyNum - a.buyNum)
+                .find(item => this.count >= item.buyNum)
+            return lastItem ? lastItem.buyPrice : this.currentSku.price
+        },
+        // 关闭
+        handleClose() {
+            this.$nextTick(() => {
+                this.$refs.popup.close()
+            })
+        },
+        // 关闭/打开
+        handleChange(e) {
+            this.$emit('input', e.show)
+        },
+        // 打开
+        handleOpen() {
+            this.$nextTick(() => {
+                this.$refs.popup.open()
+            })
+        },
+        handleChooseUtil(item) {
+            this.currentSkuId = item.skuId
+            this.$emit('utilChange', item)
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.uni-popup {
+    position: relative;
+    z-index: 99999;
+    .close {
+        position: absolute;
+        right: 24rpx;
+        top: 24rpx;
+        color: #999;
+        font-size: 32rpx;
+    }
+}
+
+.popup-content {
+    padding: 40rpx 32rpx;
+    background-color: #fff;
+    border-radius: 16rpx 16rpx 0 0;
+
+    &::after {
+        position: absolute;
+        content: '';
+        width: 100%;
+        height: 80rpx;
+        bottom: -80rpx;
+        left: 0;
+        background-color: #fff;
+    }
+
+    .goods-info {
+        display: flex;
+        .cover {
+            flex-shrink: 0;
+            width: 180rpx;
+            height: 180rpx;
+            border: 1px solid #e1e1e1;
+        }
+
+        .info {
+            margin-left: 24rpx;
+            margin-top: 24rpx;
+
+            .price {
+                display: flex;
+                align-items: center;
+
+                .label {
+                    font-size: 26rpx;
+                    color: #666666;
+                }
+
+                .amount {
+                    font-size: 26rpx;
+                    color: #ff457b;
+                    font-weight: bold;
+
+                    &::before {
+                        content: '¥';
+                    }
+                }
+            }
+
+            .tags {
+                display: flex;
+                align-items: center;
+                flex-wrap: wrap;
+                margin-top: 24rpx;
+                gap: 16rpx 24rpx;
+
+                .tag-text {
+                    font-size: 22rpx;
+                    color: #ff457b;
+                }
+
+                .tag-qh {
+                    line-height: 40rpx;
+                    height: 40rpx;
+                    background: #ff457b;
+                    border-radius: 25rpx;
+                    padding: 0 15rpx;
+                    font-size: 24rpx;
+                    font-weight: bold;
+                    color: #ffffff;
+                }
+
+                .tag-pt {
+                    height: 32rpx;
+                    line-height: 32rpx;
+                    padding: 0 8rpx;
+                    background: linear-gradient(90deg, #6431f2 0%, #b03bb8 49%, #ff457b 100%);
+                    border-radius: 4rpx;
+                    font-size: 22rpx;
+                    color: #fff;
+                }
+
+                .tag-hd,
+                .tag-xs {
+                    height: 30rpx;
+                    padding: 0 8rpx;
+                    line-height: 28rpx;
+                    background: #fff3f7;
+                    border: 1rpx solid #ff457b;
+                    border-radius: 4rpx;
+                    font-size: 22rpx;
+                    color: #ff457b;
+                }
+            }
+        }
+    }
+
+    .buy-unit {
+        margin-top: 32rpx;
+
+        .label {
+            margin-bottom: 24rpx;
+        }
+
+        .unit-wrapper {
+            max-height: 300rpx;
+            .unit-list {
+                display: flex;
+                flex-wrap: wrap;
+                gap: 24rpx 16rpx;
+                padding-top: 24rpx;
+
+                .unit {
+                    position: relative;
+                    height: 48rpx;
+                    line-height: 46rpx;
+                    padding: 0 28rpx;
+                    background: #f5f5f5;
+                    color: #666666;
+                    font-size: 24rpx;
+                    box-sizing: border-box;
+                    border: 1rpx solid #f5f5f5;
+                    border-radius: 24rpx;
+
+                    &.active {
+                        color: #ff457b;
+                        border-color: #ff457b;
+                        background: #fff8fd;
+                    }
+
+                    &.disabled::after {
+                        content: '缺货';
+                        position: absolute;
+                        height: 32rpx;
+                        line-height: 32rpx;
+                        background: #cccccc;
+                        color: #fff;
+                        padding: 0 10rpx;
+                        right: 0;
+                        top: 0;
+                        transform: translate(30%, -50%);
+                        font-size: 22rpx;
+                        border-radius: 17rpx;
+                        border: 2rpx solid #fff;
+                    }
+                }
+            }
+        }
+    }
+
+    .buy-number,
+    .buy-unit {
+        .label {
+            font-weight: bold;
+            color: #333333;
+            font-size: 28rpx;
+        }
+    }
+
+    .buy-number {
+        display: flex;
+        justify-content: space-between;
+        align-items: center;
+        margin-top: 60rpx;
+    }
+
+    .coupon-tip {
+        margin: 70rpx 0 24rpx;
+        font-size: 0;
+        text-align: center;
+
+        text {
+            font-size: 24rpx;
+            color: #666;
+        }
+
+        .active {
+            color: #ff457b;
+        }
+    }
+
+    .control {
+        display: flex;
+        align-items: center;
+        justify-content: space-evenly;
+
+        &.disabled {
+            .btn {
+                background: #ddd !important;
+                color: #fff !important;
+            }
+        }
+
+        .btn {
+            height: 90rpx;
+            font-size: 30rpx;
+            border-radius: 45rpx;
+            display: flex;
+            justify-content: center;
+            align-items: center;
+            flex-direction: column;
+            position: relative;
+            overflow: hidden;
+
+            &:active::after {
+                content: '';
+                position: absolute;
+                width: 100%;
+                height: 100%;
+                left: 0;
+                top: 0;
+                background: #999;
+                opacity: 0.1;
+            }
+
+            &.btn-confirm {
+                width: 100%;
+            }
+
+            &.btn-confirm,
+            &.btn-buy {
+                color: #fff;
+                background: linear-gradient(90deg, #fc32b4 0%, #f83c6c 100%);
+            }
+
+            &.btn-cart {
+                color: #ff457b;
+                background: #ffeff4;
+            }
+
+            &.btn-buy,
+            &.btn-cart {
+                width: 280rpx;
+            }
+
+            .tip {
+                font-size: 22rpx;
+                margin-bottom: 4rpx;
+                line-height: 24rpx;
+            }
+            .amount {
+                font-size: 30rpx;
+                font-weight: 600;
+                line-height: 36rpx;
+            }
+        }
+    }
+}
+</style>

+ 1 - 1
components/views/cm-product/cm-product.vue

@@ -65,7 +65,7 @@ export default {
         },
         },
         // 加入购物车
         // 加入购物车
         addCart() {
         addCart() {
-            this.$store.dispatch('cart/addToCart', { productId: this.data.productId })
+            this.$store.dispatch('cart/addToCart', { skuId: this.data.skuId })
         }
         }
     }
     }
 }
 }

+ 65 - 0
mixins/goodsDetail.js

@@ -0,0 +1,65 @@
+import { generateActivityType, generatePriceType } from '@/common/goods.helper.js'
+import { fetchProductDetail } from '@/services/api/goods.js'
+import { fetchCouponListByProductId } from '@/services/api/coupon.js'
+
+const goodsDetail = {
+    methods: {
+        // 获取商品详情
+        async fetchProductDetail(productId) {
+            try {
+                const userId = this.$store.getters.userId
+                const res = await fetchProductDetail({ productId, userId })
+                return this.generateProductInfo(res.data)
+            } catch (e) {
+                return e
+            }
+        },
+
+        // 处理商品信息
+        generateProductInfo(product) {
+            if (!product) return product
+            // 商品活动类型
+            product.activityType = generateActivityType(product)
+            product.priceType = generatePriceType(product)
+            product.skus = product.skus.map(sku => {
+                sku.activityType = generateActivityType(sku)
+                sku.priceType = generatePriceType(sku)
+                return sku
+            })
+            return product
+        },
+
+        // 获取商品可用优惠券
+        async fetchCouponListByProduct(productId) {
+            try {
+                const userId = this.$store.getters.userId
+                const res = await fetchCouponListByProductId({ productId, userId })
+                return res.data.map(coupon => this.generateCoupon(coupon))
+            } catch (e) {
+                return e
+            }
+        },
+
+        // 创建优惠券
+        generateCoupon(coupon) {
+            const obj = Object.assign({}, coupon)
+            // 添加标题
+            if (coupon.noThresholdFlag > 0) {
+                obj.couponTitle = `减¥${coupon.couponAmount}元`
+            } else {
+                obj.couponTitle = `满¥${coupon.touchPrice}元减¥${coupon.couponAmount}元`
+            }
+            // 添加优惠券状态
+            if (obj.useStatus === 0) {
+                obj.controlType = 'receive'
+            } else if (obj.useStatus === 1) {
+                obj.couponStatus = 'received'
+                obj.controlType = 'search'
+            }
+            return obj
+        },
+    }
+}
+
+
+export default goodsDetail

+ 1 - 1
pages/index/index.vue

@@ -1,5 +1,5 @@
 <template>
 <template>
-    <view class=""><tui-skeleton v-if="true" :loadingType="3" :isLoading="true"></tui-skeleton></view>
+    <view><tui-skeleton v-if="true" :loadingType="3" :isLoading="true"></tui-skeleton></view>
 </template>
 </template>
 
 
 <script>
 <script>

+ 63 - 4
pages/tabBar/cart/cart.vue

@@ -46,8 +46,10 @@
                 <view class="supplier-area" v-for="item in shopList" :key="item.shopId">
                 <view class="supplier-area" v-for="item in shopList" :key="item.shopId">
                     <cm-cart-supplier-area
                     <cm-cart-supplier-area
                         :shopInfo="item"
                         :shopInfo="item"
+                        :isDeleted="isDeleted"
                         @change="checkedProductChange"
                         @change="checkedProductChange"
                         @countChange="onCountChange"
                         @countChange="onCountChange"
+                        @unitChange="onUnitChange"
                         ref="supplierArea"
                         ref="supplierArea"
                     ></cm-cart-supplier-area>
                     ></cm-cart-supplier-area>
                 </view>
                 </view>
@@ -87,6 +89,17 @@
         <tui-modal :show="removeModal" content="确认删除选中的商品吗?" @click="onConfirmRemove"></tui-modal>
         <tui-modal :show="removeModal" content="确认删除选中的商品吗?" @click="onConfirmRemove"></tui-modal>
         <!-- 清空失效商品确认 -->
         <!-- 清空失效商品确认 -->
         <tui-modal :show="removeExpModal" content="确认清空失效商品?" @click="onConfirmRemoveExp"></tui-modal>
         <tui-modal :show="removeExpModal" content="确认清空失效商品?" @click="onConfirmRemoveExp"></tui-modal>
+
+        <!-- 重新选择商品规格 -->
+        <cm-goods-buy-popup
+            v-model="goodsBuyPopup"
+            :product="productInfo"
+            :couponList="goodsCouponList"
+            :useType="useType"
+            :buttonType="buttonType"
+            @confirm="onSaveNewUnit"
+            v-if="productInfo"
+        ></cm-goods-buy-popup>
     </view>
     </view>
 </template>
 </template>
 
 
@@ -96,6 +109,7 @@ import { fetchCouponListByProductIds } from '@/services/api/coupon.js'
 import { arrayUnique } from '@/common/utils.js'
 import { arrayUnique } from '@/common/utils.js'
 import { mapGetters, mapActions } from 'vuex'
 import { mapGetters, mapActions } from 'vuex'
 import CouponUtils from '@/common/couponUtils.js'
 import CouponUtils from '@/common/couponUtils.js'
+import goodsDetailMixin from '@/mixins/goodsDetail.js'
 // 业务帮助函数
 // 业务帮助函数
 import {
 import {
     totalAllCheckedProduct,
     totalAllCheckedProduct,
@@ -103,6 +117,7 @@ import {
     initFormatCouponList,
     initFormatCouponList,
     makeCouponUseTip
     makeCouponUseTip
 } from '@/common/business.helper.js'
 } from '@/common/business.helper.js'
+import { setTimeout } from 'timers'
 
 
 const resetData = () => ({
 const resetData = () => ({
     isRequest: true,
     isRequest: true,
@@ -130,10 +145,19 @@ const resetData = () => ({
     couponTipText: '', // 可用优惠券提示
     couponTipText: '', // 可用优惠券提示
 
 
     // 保存变动
     // 保存变动
-    changeRef: null
+    changeRef: null,
+
+    // 选择商品规格
+    cartId: 0,
+    goodsBuyPopup: false,
+    useType: 'cart',
+    buttonType: 'left',
+    goodsCouponList: [],
+    productInfo: null
 })
 })
 
 
 export default {
 export default {
+    mixins: [goodsDetailMixin],
     data() {
     data() {
         return resetData()
         return resetData()
     },
     },
@@ -167,7 +191,7 @@ export default {
         this.resetData()
         this.resetData()
         this.fetchCartInfo()
         this.fetchCartInfo()
     },
     },
-    
+
     onShow() {
     onShow() {
         this.resetData()
         this.resetData()
         this.fetchCartInfo()
         this.fetchCartInfo()
@@ -175,7 +199,7 @@ export default {
     },
     },
     methods: {
     methods: {
         ...mapActions('cart', ['removeFromCart', 'fetchCartKindCount']),
         ...mapActions('cart', ['removeFromCart', 'fetchCartKindCount']),
-        
+
         // 初始化数据
         // 初始化数据
         resetData() {
         resetData() {
             const data = resetData()
             const data = resetData()
@@ -356,11 +380,46 @@ export default {
             this.handleCartManager()
             this.handleCartManager()
         },
         },
 
 
+        // 商品规格修改
+        async onUnitChange(e) {
+            try {
+                this.cartId = e.cartId
+                uni.showLoading({ title: '加载中...' })
+                this.productInfo = await this.fetchProductDetail(e.productId)
+                this.goodsCouponList = await this.fetchCouponListByProduct(e.productId)
+                setTimeout(() => {
+                    this.goodsBuyPopup = true
+                    uni.hideLoading()
+                }, 1000)
+            } catch (e) {
+                console.log(e)
+            }
+        },
+
+        // 保存商品规格
+        async onSaveNewUnit(e) {
+            try {
+                console.log(e)
+                await this.$store.dispatch('cart/updateProductUnit', {
+                    newSkuId: e.sku.skuId,
+                    cartId: this.cartId,
+                    productCount: e.count
+                })
+                this.$toast.success('规格修改成功')
+                this.resetData()
+                this.fetchCartInfo()
+                this.fetchCartKindCount()
+            } catch (e) {
+                console.log(e)
+                this.$toast.error('修改规格失败')
+            }
+        },
+
         // 验证是否全选
         // 验证是否全选
         validateIsChekedAll() {
         validateIsChekedAll() {
             return this.shopList.every(item => {
             return this.shopList.every(item => {
                 const checkedList = this.checkedShopMap[item.shopId] || []
                 const checkedList = this.checkedShopMap[item.shopId] || []
-                return item.productList.length === checkedList.length
+                return item.productList.filter(item => item.stock !== 0 || this.isDeleted).length === checkedList.length
             })
             })
         }
         }
     }
     }

+ 0 - 1
pages/tabBar/home/home.vue

@@ -67,7 +67,6 @@
 <script>
 <script>
 import { fetchHomeCarousel, fetchHomeNavbar, fetchHomeFloorData, fetchHomeCouponList } from '@/services/api/home.js'
 import { fetchHomeCarousel, fetchHomeNavbar, fetchHomeFloorData, fetchHomeCouponList } from '@/services/api/home.js'
 import { fetchCouponDisplay } from '@/services/api/coupon.js'
 import { fetchCouponDisplay } from '@/services/api/coupon.js'
-import { fetchProductFloorList } from '@/services/api/goods.js'
 import { shareDataResult } from '@/common/share.helper.js'
 import { shareDataResult } from '@/common/share.helper.js'
 import { mapActions, mapGetters } from 'vuex'
 import { mapActions, mapGetters } from 'vuex'
 import { queryStringify } from '@/common/utils.js'
 import { queryStringify } from '@/common/utils.js'

+ 1 - 1
pages/views/activity/activity-detail.vue

@@ -156,7 +156,7 @@ export default {
 
 
         // 加入购物车
         // 加入购物车
         handAddCarts(pro) {
         handAddCarts(pro) {
-            this.addToCart({ productId: pro.productId, heUserId: this.userId })
+            this.addToCart({ skuId: pro.skuId, heUserId: this.userId })
         },
         },
 
 
         // 跳转购物车
         // 跳转购物车

+ 60 - 2
pages/views/cart/cart.vue

@@ -54,8 +54,10 @@
                 <view class="supplier-area" v-for="item in shopList" :key="item.shopId">
                 <view class="supplier-area" v-for="item in shopList" :key="item.shopId">
                     <cm-cart-supplier-area
                     <cm-cart-supplier-area
                         :shopInfo="item"
                         :shopInfo="item"
+                        :isDeleted="isDeleted"
                         @change="checkedProductChange"
                         @change="checkedProductChange"
                         @countChange="onCountChange"
                         @countChange="onCountChange"
+                        @unitChange="onUnitChange"
                         ref="supplierArea"
                         ref="supplierArea"
                     ></cm-cart-supplier-area>
                     ></cm-cart-supplier-area>
                 </view>
                 </view>
@@ -94,6 +96,17 @@
         <tui-modal :show="removeModal" content="确认删除选中的商品吗?" @click="onConfirmRemove"></tui-modal>
         <tui-modal :show="removeModal" content="确认删除选中的商品吗?" @click="onConfirmRemove"></tui-modal>
         <!-- 清空失效商品确认 -->
         <!-- 清空失效商品确认 -->
         <tui-modal :show="removeExpModal" content="确认清空失效商品?" @click="onConfirmRemoveExp"></tui-modal>
         <tui-modal :show="removeExpModal" content="确认清空失效商品?" @click="onConfirmRemoveExp"></tui-modal>
+
+        <!-- 重新选择商品规格 -->
+        <cm-goods-buy-popup
+            v-model="goodsBuyPopup"
+            :product="productInfo"
+            :couponList="goodsCouponList"
+            :useType="useType"
+            :buttonType="buttonType"
+            @confirm="onSaveNewUnit"
+            v-if="productInfo"
+        ></cm-goods-buy-popup>
     </view>
     </view>
 </template>
 </template>
 
 
@@ -103,6 +116,7 @@ import { fetchCouponListByProductIds } from '@/services/api/coupon.js'
 import { arrayUnique } from '@/common/utils.js'
 import { arrayUnique } from '@/common/utils.js'
 import { mapGetters, mapActions } from 'vuex'
 import { mapGetters, mapActions } from 'vuex'
 import CouponUtils from '@/common/couponUtils.js'
 import CouponUtils from '@/common/couponUtils.js'
+import goodsDetailMixin from '@/mixins/goodsDetail.js'
 // 业务帮助函数
 // 业务帮助函数
 import {
 import {
     totalAllCheckedProduct,
     totalAllCheckedProduct,
@@ -147,10 +161,19 @@ const resetData = () => ({
     couponTipText: '', // 可用优惠券提示
     couponTipText: '', // 可用优惠券提示
 
 
     // 保存变动
     // 保存变动
-    changeRef: null
+    changeRef: null,
+
+    // 选择商品规格
+    cartId: 0,
+    goodsBuyPopup: false,
+    useType: 'cart',
+    buttonType: 'left',
+    goodsCouponList: [],
+    productInfo: null
 })
 })
 
 
 export default {
 export default {
+    mixins: [goodsDetailMixin],
     data() {
     data() {
         return resetData()
         return resetData()
     },
     },
@@ -387,11 +410,46 @@ export default {
             this.handleCartManager()
             this.handleCartManager()
         },
         },
 
 
+        // 商品规格修改
+        async onUnitChange(e) {
+            try {
+                this.cartId = e.cartId
+                uni.showLoading({ title: '加载中...' })
+                this.productInfo = await this.fetchProductDetail(e.productId)
+                this.goodsCouponList = await this.fetchCouponListByProduct(e.productId)
+                setTimeout(() => {
+                    this.goodsBuyPopup = true
+                    uni.hideLoading()
+                }, 1000)
+            } catch (e) {
+                console.log(e)
+            }
+        },
+
+        // 保存商品规格
+        async onSaveNewUnit(e) {
+            try {
+                console.log(e)
+                await this.$store.dispatch('cart/updateProductUnit', {
+                    newSkuId: e.sku.skuId,
+                    cartId: this.cartId,
+                    productCount: e.count
+                })
+                this.$toast.success('规格修改成功')
+                this.resetData()
+                this.fetchCartInfo()
+                this.fetchCartKindCount()
+            } catch (e) {
+                console.log(e)
+                this.$toast.error('修改规格失败')
+            }
+        },
+
         // 验证是否全选
         // 验证是否全选
         validateIsChekedAll() {
         validateIsChekedAll() {
             return this.shopList.every(item => {
             return this.shopList.every(item => {
                 const checkedList = this.checkedShopMap[item.shopId] || []
                 const checkedList = this.checkedShopMap[item.shopId] || []
-                return item.productList.length === checkedList.length
+                return item.productList.filter(item => item.stock !== 0 || this.isDeleted).length === checkedList.length
             })
             })
         },
         },
 
 

+ 1 - 48
pages/views/goods/commons/helper.js

@@ -1,53 +1,6 @@
 import { navbarButtonGroup } from '../config/config.js'
 import { navbarButtonGroup } from '../config/config.js'
 
 
-// 获取产品活动类型 (拼团 活动价 限时特价)
-export function generateActivityType(productData) {
-    const { collageStatus = 0, activeStatus = 0, discountStatus = 0 } = productData
-    // 拼团价
-    if (collageStatus > 0) {
-        return 'group' // 拼团价
-    }
-    // 限时活动
-    else if (discountStatus > 0) {
-        return 'time-limit'
-    }
-    // 普通活动价
-    else if (activeStatus > 0) {
-        return 'activity'
-    }
-    // 普通商品
-    return 'normal' // 普通价
-}
-
-// 获取产品价格类型
-export function generatePriceType(productData) {
-    const { couponStatus = 0, collageStatus = 0, activeStatus = 0, discountStatus = 0, couponId } = productData
-    // 拼团价
-    if (collageStatus > 0) {
-        if (couponStatus === 1 && couponId) {
-            return 'groupWithCoupon' // 拼团券后价
-        } else {
-            return 'group' // 拼团价
-        }
-    }
-    // 限时活动
-    else if (discountStatus > 0 || activeStatus > 0) {
-        if (couponStatus === 1 && couponId) {
-            return 'activityWithCoupon' // 券后价
-        } else {
-            return 'normal' // 限时活动价格
-        }
-    }
-    // 无活动价
-    else {
-        if (couponStatus === 1 && couponId) {
-            return 'normalWithCoupon' // 普通券后价
-        } else {
-            return 'normal' // 普通价
-        }
-    }
-}
-
+// 导航按钮类型
 export function generateNavbarButtonText(productData) {
 export function generateNavbarButtonText(productData) {
     const { priceType } = productData
     const { priceType } = productData
     const navbarButton = navbarButtonGroup[priceType]
     const navbarButton = navbarButtonGroup[priceType]

+ 2 - 2
pages/views/goods/components/goods-coupon-section/goods-coupon-section.vue

@@ -33,10 +33,10 @@ export default {
     background-color: #fff;
     background-color: #fff;
     .section {
     .section {
         @extend .cm-flex-between;
         @extend .cm-flex-between;
-        font-size: 24rpx;
+        font-size: 28rpx;
 
 
         .label {
         .label {
-            color: #666;
+            color: #FF457B;
         }
         }
 
 
         .coupon-tags {
         .coupon-tags {

+ 3 - 3
pages/views/goods/components/goods-navbar/goods-navbar.vue

@@ -3,15 +3,15 @@
         <simple-safe-view>
         <simple-safe-view>
             <view class="navbar">
             <view class="navbar">
                 <view class="navbar-left">
                 <view class="navbar-left">
-                		  <view class="item" @click="$emit('leftClick', 0)">
+                    <view class="item" @click="$emit('leftClick', 0)">
                         <!-- 首页 -->
                         <!-- 首页 -->
                         <view class="iconfont icon-fanhuishouye"></view>
                         <view class="iconfont icon-fanhuishouye"></view>
-                			     <view class="label">首页</view>
+                        <view class="label">首页</view>
                     </view>
                     </view>
                     <button class="item contact" @click="$emit('leftClick', 1)" open-type="contact">
                     <button class="item contact" @click="$emit('leftClick', 1)" open-type="contact">
                         <!-- 客服 -->
                         <!-- 客服 -->
                         <view class="iconfont icon-kefu"></view>
                         <view class="iconfont icon-kefu"></view>
-                 			    <view class="label">客服</view>
+                        <view class="label">客服</view>
                     </button>
                     </button>
                     <view class="item cart" @click="$emit('leftClick', 2)">
                     <view class="item cart" @click="$emit('leftClick', 2)">
                         <!-- 购物车 -->
                         <!-- 购物车 -->

+ 195 - 85
pages/views/goods/components/goods-receive-buy-popup/goods-receive-buy-popup.vue

@@ -4,46 +4,62 @@
             <view class="close iconfont icon-iconfontguanbi" @click="close"></view>
             <view class="close iconfont icon-iconfontguanbi" @click="close"></view>
             <view class="popup-content" :style="{ paddingBottom: safeArea ? 0 : '40rpx' }">
             <view class="popup-content" :style="{ paddingBottom: safeArea ? 0 : '40rpx' }">
                 <view class="content">
                 <view class="content">
-                    <!-- 商品图片 -->
-                    <image :src="productData.mainImage" class="cover"></image>
+                    <!-- 商品信息 -->
                     <view class="info">
                     <view class="info">
-                        <!-- 数量 -->
-                        <view class="row">
-                            <view class="count">
-                                <view class="label">数量</view>
-                                <cm-number-box
-                                    class="number-box"
-                                    v-model.lazy="count"
-                                    :max="limitedNum"
-                                ></cm-number-box>
+                        <image :src="productData.mainImage" class="cover"></image>
+                        <view class="price">
+                            <!-- 单价 -->
+                            <view class="row">
+                                <view class="label">单价:</view>
+                                <!-- 拼团价 -->
+                                <template v-if="productData.activityType === 'group'">
+                                    <view class="amount" v-if="groupBuyFlag">{{ productPrice | priceFormat }}</view>
+                                    <view class="amount" v-else>{{ productData.normalPrice | priceFormat }}</view>
+                                </template>
+                                <!-- 其它价格 -->
+                                <template v-else>
+                                    <view class="amount">{{ productPrice | priceFormat }}</view>
+                                </template>
                             </view>
                             </view>
-                            <view
-                                class="clickable"
-                                @click="$emit('detail')"
-                                v-if="productData.activeStatus > 0 && productData.ladderList.length > 0"
-                            >
-                                查看活动价
+                            <view class="row tags">
+                                <!-- 券后价 -->
+                                <template v-if="hasCouponPrice && priceType === 'normal'">
+                                    <view class="tag-qh">券后价¥{{ productData.couponPrice | priceFormat }}</view>
+                                </template>
+                                <!-- 价格标签 -->
+                                <template v-if="priceType !== 'normal'">
+                                    <view class="tag-pt" v-if="priceType === 'group'">
+                                        <text v-if="collageInfo">{{ collageInfo.memberNum }}人拼团</text>
+                                    </view>
+                                    <template v-else-if="priceType === 'activity'">
+                                        <view class="tag-hd">活动价</view>
+                                        <view class="clickable" @click="$emit('detail')">查看活动价</view>
+                                    </template>
+                                    <view class="tag-xs" v-else>限时特价</view>
+                                </template>
                             </view>
                             </view>
                         </view>
                         </view>
-                        <!-- 单价 -->
-                        <view class="row">
-                            <view class="label">单价</view>
-                            <!-- 拼团价 -->
-                            <template v-if="productData.activityType === 'group'">
-                                <view class="amount" v-if="groupBuyFlag">{{ productPrice | priceFormat }}</view>
-                                <view class="amount" v-else>{{ productData.normalPrice | priceFormat }}</view>
-                            </template>
-                            <!-- 其它价格 -->
-                            <template v-else>
-                                <view class="amount">{{ productPrice | priceFormat }}</view>
-                            </template>
-                        </view>
-                        <!-- 券后价 -->
-                        <view class="row" v-if="productData.couponStatus === 1 && productData.couponId">
-                            <view class="tag-qh">券后价¥{{ productData.couponPrice | priceFormat }}</view>
+                    </view>
+                    <!-- 规格 -->
+                    <view class="unit">
+                        <view class="label">规格:</view>
+                        <view class="list">
+                            <view class="item">3ml</view>
+                            <view class="item">135ml + 小样20ml</view>
+                            <view class="item">3ml 2瓶</view>
+                            <view class="item">10ml 2瓶</view>
+                            <view class="item disabled">10ml 2瓶</view>
+                            <view class="item">135ml + 精华20ml</view>
+                            <view class="item active">5ml 2瓶</view>
                         </view>
                         </view>
                     </view>
                     </view>
+                    <!-- 购买数量 -->
+                    <view class="count">
+                        <view class="label">购买数量:</view>
+                        <cm-number-box v-model.lazy="count" :max="limitedNum"></cm-number-box>
+                    </view>
                 </view>
                 </view>
+                <!-- 优惠券使用提示 -->
                 <view class="tip">
                 <view class="tip">
                     <template v-if="productData.couponStatus > 0 && productData.couponId">
                     <template v-if="productData.couponStatus > 0 && productData.couponId">
                         当前商品可使用
                         当前商品可使用
@@ -56,9 +72,7 @@
                         <text v-if="productData.couponStatus === 1 && productData.couponId">领券购买</text>
                         <text v-if="productData.couponStatus === 1 && productData.couponId">领券购买</text>
                         <text v-else>立即购买</text>
                         <text v-else>立即购买</text>
                     </template>
                     </template>
-                    <template v-else>
-                        确认
-                    </template>
+                    <text v-else>确认</text>
                 </tui-button>
                 </tui-button>
             </view>
             </view>
         </uni-popup>
         </uni-popup>
@@ -74,10 +88,6 @@ export default {
             type: Object,
             type: Object,
             default: () => null
             default: () => null
         },
         },
-        currentCoupon: {
-            type: Object,
-            default: () => null
-        },
         couponTip: {
         couponTip: {
             type: String,
             type: String,
             default: ''
             default: ''
@@ -106,6 +116,18 @@ export default {
                 return this.productData.collageProduct.limitedNum || this.productData.stock
                 return this.productData.collageProduct.limitedNum || this.productData.stock
             }
             }
             return this.productData.stock
             return this.productData.stock
+        },
+        /* 商品价格类型 normal: 普通价 | group: 拼团价 | activity: 活动价 | time-limit: 限时特价 | coupon: 券后价 */
+        priceType() {
+            return this.productData?.activityType
+        },
+        // 有可使用优惠券
+        hasCouponPrice() {
+            return this.productData.couponStatus === 1
+        },
+        // 商品拼团信息
+        collageInfo() {
+            return this.productData?.collageProduct
         }
         }
     },
     },
     methods: {
     methods: {
@@ -179,69 +201,157 @@ export default {
 
 
         .content {
         .content {
             width: 100%;
             width: 100%;
-            @extend .cm-flex-between;
-            justify-content: flex-start;
-            .cover {
-                width: 180rpx;
-                height: 180rpx;
+
+            .unit,
+            .count {
+                .label {
+                    font-weight: bold;
+                    color: #333333;
+                    font-size: 28rpx;
+                }
             }
             }
 
 
-            .info {
-                margin-left: 24rpx;
+            .count {
+                @extend .cm-flex-between;
+                align-items: center;
+                margin-top: 68rpx;
+            }
+
+            .unit {
+                margin-top: 32rpx;
+                .list {
+                    display: flex;
+                    flex-wrap: wrap;
+
+                    .item {
+                        position: relative;
+                        height: 48rpx;
+                        line-height: 46rpx;
+                        padding: 0 28rpx;
+                        background: #f5f5f5;
+                        color: #666666;
+                        font-size: 24rpx;
+                        box-sizing: border-box;
+                        border: 1rpx solid #f5f5f5;
+                        margin-right: 16rpx;
+                        margin-top: 24rpx;
+                        border-radius: 24rpx;
 
 
-                .row {
-                    @extend .cm-flex-center;
-                    justify-content: flex-start;
+                        &.active {
+                            color: #ff457b;
+                            border-color: #ff457b;
+                            background: #fff8fd;
+                        }
 
 
-                    &:first-child {
-                        margin-bottom: 40rpx;
+                        &.disabled {
+                            // border: 1rpx solid #f9f9f9;
+                            // background: #f9f9f9;
+                            // color: #ddd;
+                            &::after {
+                                content: '缺货';
+                                position: absolute;
+                                height: 32rpx;
+                                line-height: 32rpx;
+                                background: #cccccc;
+                                color: #fff;
+                                padding: 0 10rpx;
+                                right: 0;
+                                top: 0;
+                                transform: translate(30%, -50%);
+                                font-size: 22rpx;
+                                border-radius: 17rpx;
+                                border: 2rpx solid #fff;
+                            }
+                        }
                     }
                     }
                 }
                 }
+            }
 
 
-                .count {
-                    @extend .cm-flex-center;
-                    justify-content: flex-start;
+            .info {
+                display: flex;
+                .cover {
+                    width: 180rpx;
+                    height: 180rpx;
+                    border: 1px solid #e1e1e1;
+                }
 
 
-                    .number-box {
-                        margin: 0 24rpx;
+                .price {
+                    margin-left: 24rpx;
+                    margin-top: 24rpx;
+
+                    .label {
+                        font-size: 24rpx;
+                        color: #666666;
                     }
                     }
-                }
 
 
-                .label {
-                    font-size: 24rpx;
-                    color: #666666;
+                    .amount {
+                        font-size: 26rpx;
+                        color: #ff457b;
+                        font-weight: bold;
 
 
-                    &::after {
-                        content: ':';
+                        &::before {
+                            content: '¥';
+                        }
                     }
                     }
-                }
 
 
-                .clickable {
-                    font-size: 26rpx;
-                    color: #ff457b;
+                    .row {
+                        display: flex;
+                        align-items: center;
+
+                        &:nth-child(2) {
+                            margin-top: 24rpx;
+                        }
+                    }
                 }
                 }
 
 
-                .amount {
-                    font-size: 26rpx;
-                    color: #ff457b;
-                    font-weight: bold;
+                .tags {
+                    & > view {
+                        margin-right: 24rpx;
+                        &:last-child {
+                            margin-right: 0;
+                        }
+                    }
 
 
-                    &::before {
-                        content: '¥';
+                    .clickable {
+                        font-size: 22rpx;
+                        color: #ff457b;
                     }
                     }
-                }
 
 
-                .tag-qh {
-                    display: inline-block;
-                    line-height: 40rpx;
-                    height: 40rpx;
-                    margin-top: 14rpx;
-                    background: #ff457b;
-                    border-radius: 25rpx;
-                    padding: 0 15rpx;
-                    font-size: 24rpx;
-                    font-weight: bold;
-                    color: #ffffff;
+                    .tag-qh {
+                        display: inline-block;
+                        line-height: 40rpx;
+                        height: 40rpx;
+                        margin-top: 14rpx;
+                        background: #ff457b;
+                        border-radius: 25rpx;
+                        padding: 0 15rpx;
+                        font-size: 24rpx;
+                        font-weight: bold;
+                        color: #ffffff;
+                    }
+
+                    .tag-pt {
+                        @extend .cm-flex-center;
+                        height: 32rpx;
+                        padding: 0 8rpx;
+                        background: linear-gradient(90deg, #6431f2 0%, #b03bb8 49%, #ff457b 100%);
+                        border-radius: 4rpx;
+                        font-size: 22rpx;
+                        color: #fff;
+                    }
+
+                    .tag-hd,
+                    .tag-xs {
+                        @extend .cm-flex-center;
+                        display: block;
+                        height: 30rpx;
+                        padding: 0 8rpx;
+                        background: #fff3f7;
+                        border: 1rpx solid #ff457b;
+                        border-radius: 4rpx;
+                        font-size: 22rpx;
+                        color: #ff457b;
+                    }
                 }
                 }
             }
             }
         }
         }

+ 55 - 0
pages/views/goods/components/goods-unit-section/goods-unit-section.vue

@@ -0,0 +1,55 @@
+<template>
+    <view class="goods-unit-section">
+        <view class="section" @click="$emit('click')">
+            <view class="label">规格:</view>
+            <view class="list"><text v-text="text"></text></view>
+            <view class="iconfont icon-chakangengduo"></view>
+        </view>
+    </view>
+</template>
+
+<script>
+export default {
+    props: {
+        skuList: {
+            type: Array,
+            default: () => []
+        }
+    },
+    computed: {
+        text() {
+            const len = this.skuList.length
+            return `共${len}种规格可选`
+        }
+    }
+}
+</script>
+
+<style lang="scss" scoped>
+.goods-unit-section {
+    padding: 24rpx;
+    background-color: #fff;
+    .section {
+        @extend .cm-flex-between;
+        font-size: 28rpx;
+
+        .label {
+            color: #666;
+        }
+
+        .list {
+            flex: 1;
+            margin: 0 24rpx;
+            color: #333;
+
+            text {
+                margin-right: 24rpx;
+            }
+        }
+        .iconfont {
+            font-size: 28rpx;
+            color: #666;
+        }
+    }
+}
+</style>

+ 53 - 58
pages/views/goods/goods-detail.vue

@@ -30,6 +30,10 @@
             <!-- 商品基本信息:商品名称 && 分享 && 标签 && 备注 && 服务-->
             <!-- 商品基本信息:商品名称 && 分享 && 标签 && 备注 && 服务-->
             <goods-info @share="onShare" :productData="productInfo"></goods-info>
             <goods-info @share="onShare" :productData="productInfo"></goods-info>
 
 
+            <view class="section" v-if="productInfo.skus.length > 0">
+                <goods-unit-section :skuList="productInfo.skus" @click="onUnitClick"></goods-unit-section>
+            </view>
+
             <!-- 参数 -->
             <!-- 参数 -->
             <view class="section" v-if="productInfo.parametersList.length > 0">
             <view class="section" v-if="productInfo.parametersList.length > 0">
                 <goods-params-section :paramList="productInfo.parametersList"></goods-params-section>
                 <goods-params-section :paramList="productInfo.parametersList"></goods-params-section>
@@ -46,13 +50,7 @@
             <!-- 商品详情 -->
             <!-- 商品详情 -->
             <view class="section detail">
             <view class="section detail">
                 <view class="title">商品详情</view>
                 <view class="title">商品详情</view>
-                <!-- <view
-                    v-if="productDetail.detailInfo"
-                    v-html="productDetail.detailInfo"
-                    style="overflow-x: hidden;"
-                ></view> -->
                 <template v-if="productDetail && productDetail.detailInfo">
                 <template v-if="productDetail && productDetail.detailInfo">
-                    <!-- <parser :html="productDetail.detailInfo" :img-mode="widthFix"></parser> -->
                     <uParse :content="productDetail.detailInfo" />
                     <uParse :content="productDetail.detailInfo" />
                 </template>
                 </template>
                 <!-- 空 -->
                 <!-- 空 -->
@@ -96,17 +94,7 @@
             @open="$refs.receiveBuyPopup.close()"
             @open="$refs.receiveBuyPopup.close()"
             @close="$refs.receiveBuyPopup.open()"
             @close="$refs.receiveBuyPopup.open()"
         ></goods-activity-popup>
         ></goods-activity-popup>
-
-        <!-- 领券购买 -->
-        <goods-receive-buy-popup
-            ref="receiveBuyPopup"
-            :productData="productInfo"
-            :couponTip="couponTip"
-            :groupBuyFlag="groupBuyFlag"
-            :navbarType="navbarTypeFlag"
-            @detail="$refs.activitypPopup.open()"
-            @submit="onSubmit"
-        ></goods-receive-buy-popup>
+       
         <!-- 分享弹窗 -->
         <!-- 分享弹窗 -->
         <cm-share-popup ref="sharePopup" :data="posterData" type="product"></cm-share-popup>
         <cm-share-popup ref="sharePopup" :data="posterData" type="product"></cm-share-popup>
 
 
@@ -121,14 +109,24 @@
 
 
         <!-- 返回顶部 -->
         <!-- 返回顶部 -->
         <tui-scroll-top :scrollTop="scrollTop" :bottom="80"></tui-scroll-top>
         <tui-scroll-top :scrollTop="scrollTop" :bottom="80"></tui-scroll-top>
+
+        <!-- 购买弹窗 -->
+        <cm-goods-buy-popup
+            v-model="goodsBuyPopup"
+            :product="productInfo"
+            :couponList="couponList"
+            :useType="useType"
+            :buttonType="buttonType"
+            @confirm="onSubmit"
+            v-if="productInfo"
+        ></cm-goods-buy-popup>
     </view>
     </view>
 </template>
 </template>
 
 
 <script>
 <script>
 // 配置
 // 配置
-import { generateActivityType, generatePriceType, generateNavbarButtonText } from './commons/helper.js'
-// import Parser from '@/pages/views/goods/components/jyf-Parser/index.vue'//富文本处理
-// import marked from '@/components/uni/marked'
+import { generateNavbarButtonText } from './commons/helper.js'
+import { generateActivityType, generatePriceType } from '@/common/goods.helper.js'
 import uParse from '@/components/uni/uParse/src/wxParse'
 import uParse from '@/components/uni/uParse/src/wxParse'
 import { debounce } from '@/common/utils.js'
 import { debounce } from '@/common/utils.js'
 import { shareDataResult } from '@/common/share.helper.js'
 import { shareDataResult } from '@/common/share.helper.js'
@@ -161,7 +159,11 @@ export default {
             posterData: {},
             posterData: {},
             collageId: '',
             collageId: '',
             groupBuyFlag: false, // 用户是否拼团购买
             groupBuyFlag: false, // 用户是否拼团购买
-            autoplay: true
+            autoplay: true,
+            // 购买商品弹窗
+            goodsBuyPopup: false,
+            useType: 'buy',
+            buttonType: 'left'
         }
         }
     },
     },
     computed: {
     computed: {
@@ -208,7 +210,6 @@ export default {
     onLoad(options) {
     onLoad(options) {
         this.productId = parseInt(options.productId)
         this.productId = parseInt(options.productId)
         this.jumpState = parseInt(options.jumpState)
         this.jumpState = parseInt(options.jumpState)
-        // this.fetchProductDetail()
     },
     },
     onShow() {
     onShow() {
         this.autoplay = true
         this.autoplay = true
@@ -220,19 +221,21 @@ export default {
     methods: {
     methods: {
         ...mapActions('cart', ['addToCart']),
         ...mapActions('cart', ['addToCart']),
 
 
+        // 选择规格
+        onUnitClick() {
+            this.useType = 'unit'
+            this.goodsBuyPopup = true
+        },
+
         // 商品提交
         // 商品提交
-        onSubmit(count) {
-            // 加入购物车
-            if (this.navbarTypeFlag === 'cart') {
+        onSubmit(detail) {
+            if (detail.type === 'cart') {
                 this.addToCart({
                 this.addToCart({
-                    productId: this.productInfo.productId,
-                    productCount: count,
+                    skuId: detail.sku.skuId,
+                    productCount: detail.count,
                     heUserId: this.productInfo.heUserId
                     heUserId: this.productInfo.heUserId
                 })
                 })
-            }
-
-            // 立即购买(提交商品信息)
-            if (this.navbarTypeFlag === 'buy') {
+            } else if (detail.type === 'buy') {
                 if (!this.userId) {
                 if (!this.userId) {
                     const pages = getCurrentPages()
                     const pages = getCurrentPages()
                     const page = pages[pages.length - 1]
                     const page = pages[pages.length - 1]
@@ -240,39 +243,26 @@ export default {
                     uni.redirectTo({ url: '/pages/authorize/login-custom' })
                     uni.redirectTo({ url: '/pages/authorize/login-custom' })
                     return
                     return
                 }
                 }
-
                 const submitData = {
                 const submitData = {
-                    productId: this.productInfo.productId, // 产品id
-                    productCount: count, // 产品购买数量
+                    productId: detail.sku.productId, // 产品id
+                    skuId: detail.sku.skuId, // sku id
+                    productCount: detail.count, // 产品购买数量
                     heUserId: this.productInfo.heUserId, // 协销用户id
                     heUserId: this.productInfo.heUserId, // 协销用户id
                     collageFlag: this.groupBuyFlag ? 1 : 0, // 是否拼团购买
                     collageFlag: this.groupBuyFlag ? 1 : 0, // 是否拼团购买
                     collageId: this.collageId, // 拼团id
                     collageId: this.collageId, // 拼团id
-                    couponId: this.productInfo.couponId, // 默认使用优惠券id
-                    allCount: count // 商品总数
+                    couponId: detail.sku.couponId, // 默认使用优惠券id
+                    allCount: detail.count // 商品总数
                 }
                 }
                 uni.setStorageSync('COMMIT_PRODUCT_INFO', submitData)
                 uni.setStorageSync('COMMIT_PRODUCT_INFO', submitData)
                 this.$router.navigateTo('order/order-create?type=product')
                 this.$router.navigateTo('order/order-create?type=product')
             }
             }
-
-            this.$refs.receiveBuyPopup.close()
+            this.goodsBuyPopup = false
         },
         },
 
 
         // 优惠券点击事件
         // 优惠券点击事件
         onCouponClick(couponData) {
         onCouponClick(couponData) {
             if (couponData.controlType === 'receive') {
             if (couponData.controlType === 'receive') {
-                // const index = this.couponList.findIndex(item => item.couponId === coupon.couponId)
-                // this.couponList.splice(index, 1)
-                // coupon.controlType = 'buy'
-                // coupon.couponStatus = 'received'
-                // this.$set(this.couponList, index, coupon)
                 this.fetchCouponList()
                 this.fetchCouponList()
-                // this.couponList = this.couponList.map(coupon => {
-                //     if (coupon.couponId === couponData.couponId) {
-                //         coupon.controlType = 'search'
-                //         coupon.couponStatus = 'received'
-                //     }
-                //     return coupon
-                // })
             }
             }
         },
         },
 
 
@@ -319,12 +309,12 @@ export default {
         // 导航菜单右侧按钮点击
         // 导航菜单右侧按钮点击
         navbarRightClick(index) {
         navbarRightClick(index) {
             this.navbarTypeFlag = index > 0 || this.productInfo.collageStatus > 0 ? 'buy' : 'cart'
             this.navbarTypeFlag = index > 0 || this.productInfo.collageStatus > 0 ? 'buy' : 'cart'
-
             if (this.productInfo.activityType === 'group') {
             if (this.productInfo.activityType === 'group') {
                 this.groupBuyFlag = index > 0
                 this.groupBuyFlag = index > 0
             }
             }
-
-            this.$refs.receiveBuyPopup.open()
+            this.useType = 'buy'
+            this.buttonType = index === 0 ? 'left' : 'right'
+            this.goodsBuyPopup = true
         },
         },
 
 
         // 导航栏菜单左侧按钮点击
         // 导航栏菜单左侧按钮点击
@@ -346,7 +336,6 @@ export default {
 
 
         // 顶部tab切换
         // 顶部tab切换
         onTabChange(index) {
         onTabChange(index) {
-            // const selector = `.product-detail #anchor-${index}`
             const offset = this.anchorList[index].top
             const offset = this.anchorList[index].top
             uni.pageScrollTo({
             uni.pageScrollTo({
                 scrollTop: this.scrollTop + offset - 40 - 10,
                 scrollTop: this.scrollTop + offset - 40 - 10,
@@ -383,9 +372,9 @@ export default {
         async fetchProductDetail() {
         async fetchProductDetail() {
             try {
             try {
                 const res = await fetchProductDetail({ productId: this.productId, userId: this.userId })
                 const res = await fetchProductDetail({ productId: this.productId, userId: this.userId })
-                this.productInfo = this.generateProductInfo(res.data)
                 this.isRequest = false
                 this.isRequest = false
                 this.productInfo.heUserId = this.jumpState === 1 ? 0 : this.userId
                 this.productInfo.heUserId = this.jumpState === 1 ? 0 : this.userId
+                this.productInfo = this.generateProductInfo(res.data)
                 this.initNavbarButton()
                 this.initNavbarButton()
                 this.fetchCouponList()
                 this.fetchCouponList()
             } catch (e) {
             } catch (e) {
@@ -429,9 +418,9 @@ export default {
             const obj = Object.assign({}, coupon)
             const obj = Object.assign({}, coupon)
             // 添加标题
             // 添加标题
             if (coupon.noThresholdFlag > 0) {
             if (coupon.noThresholdFlag > 0) {
-                obj.couponTitle = `减¥${coupon.couponAmount}`
+                obj.couponTitle = `减¥${coupon.couponAmount}`
             } else {
             } else {
-                obj.couponTitle = `满¥${coupon.touchPrice}减¥${coupon.couponAmount}`
+                obj.couponTitle = `满¥${coupon.touchPrice}减¥${coupon.couponAmount}`
             }
             }
             // 添加优惠券状态
             // 添加优惠券状态
             if (obj.useStatus === 0) {
             if (obj.useStatus === 0) {
@@ -456,10 +445,16 @@ export default {
         },
         },
 
 
         // 处理商品信息
         // 处理商品信息
-        generateProductInfo(product = {}) {
+        generateProductInfo(product) {
+            if (!product) return product
             // 商品活动类型
             // 商品活动类型
             product.activityType = generateActivityType(product)
             product.activityType = generateActivityType(product)
             product.priceType = generatePriceType(product)
             product.priceType = generatePriceType(product)
+            product.skus = product.skus.map(sku => {
+                sku.activityType = generateActivityType(sku)
+                sku.priceType = generatePriceType(sku)
+                return sku
+            })
             return product
             return product
         }
         }
     }
     }

+ 1 - 1
pages/views/goods/goods-search.vue

@@ -138,7 +138,7 @@ export default {
         },
         },
         // 加入购物车
         // 加入购物车
         addCart(row) {
         addCart(row) {
-            this.$store.dispatch('cart/addToCart', { productId: row.productId })
+            this.$store.dispatch('cart/addToCart', { skuId: row.skuId })
         },
         },
         handleSearch() {
         handleSearch() {
             this.list = []
             this.list = []

+ 3 - 1
pages/views/order/order-create.vue

@@ -249,6 +249,7 @@ export default {
                 this.submitParams.cartType = 2 // 从商品详情 / 拼单入口提交(标识)
                 this.submitParams.cartType = 2 // 从商品详情 / 拼单入口提交(标识)
                 this.confirmParams.productCount = productInfo.productCount
                 this.confirmParams.productCount = productInfo.productCount
                 this.confirmParams.productId = productInfo.productId
                 this.confirmParams.productId = productInfo.productId
+                this.confirmParams.skuId = productInfo.skuId
                 this.confirmParams.heUserId = productInfo.heUserId || 0
                 this.confirmParams.heUserId = productInfo.heUserId || 0
                 this.confirmParams.collageFlag = this.collageFlag = productInfo.collageFlag // 是否是拼团商品
                 this.confirmParams.collageFlag = this.collageFlag = productInfo.collageFlag // 是否是拼团商品
                 this.confirmParams.couponId = productInfo.couponId
                 this.confirmParams.couponId = productInfo.couponId
@@ -288,7 +289,8 @@ export default {
                 const productInfo = shop.productList.map(product => ({
                 const productInfo = shop.productList.map(product => ({
                     productId: product.productId,
                     productId: product.productId,
                     productNum: product.num,
                     productNum: product.num,
-                    heUserId: product.heUserId
+                    heUserId: product.heUserId,
+                    skuId: product.skuId
                 }))
                 }))
                 return { shopId: shop.shopId, note: shop.note, productInfo, splitCode: shop.splitCode }
                 return { shopId: shop.shopId, note: shop.note, productInfo, splitCode: shop.splitCode }
             })
             })

+ 3 - 1
pages/views/order/order-pay.vue

@@ -27,7 +27,9 @@
                                 </view>
                                 </view>
                                 <view class="price">
                                 <view class="price">
                                     <text class="active">¥{{ product.price | priceFormat }}</text>
                                     <text class="active">¥{{ product.price | priceFormat }}</text>
-                                    <text class="deleted">¥{{ product.normalPrice | priceFormat }}</text>
+                                    <text class="deleted" v-if="product.price < product.normalPrice">
+                                        ¥{{ product.normalPrice | priceFormat }}
+                                    </text>
                                 </view>
                                 </view>
                             </view>
                             </view>
                         </view>
                         </view>

+ 9 - 0
services/api/cart.js

@@ -53,3 +53,12 @@ export function removeProductFromCart(data) {
         data
         data
     })
     })
 }
 }
+
+/* 更新购物车商品规格 */
+export function updateProductUnit(data) {
+    return request({
+        url: '/shopping/check/sku',
+        method: 'POST',
+        data
+    })
+}

+ 0 - 9
services/api/coupon.js

@@ -27,15 +27,6 @@ export function checkCouponAlert(params) {
     })
     })
 }
 }
 
 
-/* 获取优惠券可用商品列表 */
-export function fetchProductByCoupon(params) {
-    return request({
-        url: '/coupon/product/page',
-        method: 'GET',
-        params
-    })
-}
-
 /* 统计已领取优惠券数量 */
 /* 统计已领取优惠券数量 */
 export function fetchReceivedCouponCount(params) {
 export function fetchReceivedCouponCount(params) {
     return request({
     return request({

+ 0 - 27
services/api/goods.js

@@ -1,23 +1,5 @@
 import request from '@/services/http.request.js'
 import request from '@/services/http.request.js'
 
 
-/* 获取商品楼层数据 */
-export function fetchProductFloorList(params) {
-    return request({
-        url: '/product/floor',
-        method: 'GET',
-        params
-    })
-}
-
-/* 获取商品楼层详情 */
-export function fetchProductFloorDetail(params) {
-    return request({
-        url: '/product/floor/detail',
-        method: 'GET',
-        params
-    })
-}
-
 /* 获取商品列表 */
 /* 获取商品列表 */
 export function fetchProductList(params) {
 export function fetchProductList(params) {
     return request({
     return request({
@@ -54,15 +36,6 @@ export function clearProductSearchHistory(params) {
     })
     })
 }
 }
 
 
-/* 搜索商品列表 */
-export function searchProductList(params) {
-    return request({
-        url: '/search/query/product',
-        method: 'GET',
-        params
-    })
-}
-
 /* 活动专区(分销者) */
 /* 活动专区(分销者) */
 export function fetchProductActivityAreaList(params) {
 export function fetchProductActivityAreaList(params) {
     return request({
     return request({

+ 2 - 2
services/config.env.js

@@ -1,8 +1,8 @@
 export let APP_API_URI = ''
 export let APP_API_URI = ''
 if (process.env.NODE_ENV === 'development') {
 if (process.env.NODE_ENV === 'development') {
     // 开发环境
     // 开发环境
-    // APP_API_URI = 'http://192.168.2.68:8011'	 //本地联调地址
-    APP_API_URI = 'https://mall2c-b.caimei365.com'
+    APP_API_URI = 'http://192.168.2.67:8011'	 //本地联调地址
+    // APP_API_URI = 'https://mall2c-b.caimei365.com'
     // APP_API_URI = 'https://mall2c.caimei365.com'
     // APP_API_URI = 'https://mall2c.caimei365.com'
 } else {
 } else {
     // 生产环境
     // 生产环境

+ 13 - 3
store/modules/cart.js

@@ -2,7 +2,8 @@ import {
     removeProductFromCart,
     removeProductFromCart,
     fetchCartProductCount,
     fetchCartProductCount,
     shoppingAddCart,
     shoppingAddCart,
-    updateProductCount
+    updateProductCount,
+    updateProductUnit
 } from '@/services/api/cart.js'
 } from '@/services/api/cart.js'
 
 
 const state = {
 const state = {
@@ -28,7 +29,7 @@ const mutations = {
 
 
 const actions = {
 const actions = {
     // 加入购物车
     // 加入购物车
-    async addToCart({ dispatch, rootGetters }, { productId, productCount = 1, heUserId = 0 }) {
+    async addToCart({ dispatch, rootGetters }, { skuId, productCount = 1, heUserId = 0 }) {
 
 
         if (!rootGetters.userId) {
         if (!rootGetters.userId) {
             const pages = getCurrentPages()
             const pages = getCurrentPages()
@@ -39,7 +40,7 @@ const actions = {
         }
         }
 
 
         try {
         try {
-            const res = await shoppingAddCart({ productId, userId: rootGetters.userId, productCount, heUserId })
+            const res = await shoppingAddCart({ skuId, userId: rootGetters.userId, productCount, heUserId })
             dispatch('fetchCartKindCount')
             dispatch('fetchCartKindCount')
             setTimeout(() => {
             setTimeout(() => {
                 uni.showToast({
                 uni.showToast({
@@ -83,6 +84,15 @@ const actions = {
         } catch (e) {
         } catch (e) {
             return Promise.reject(e)
             return Promise.reject(e)
         }
         }
+    },
+
+    // 购物车商品规格更新
+    async updateProductUnit({ dispatch }, { cartId, newSkuId, productCount }) {
+        try {
+            return updateProductUnit({ newSkuId, cartId, count: productCount })
+        } catch (e) {
+            return Promise.reject(e)
+        }
     }
     }
 }
 }
 
 

+ 30 - 18
store/modules/user.js

@@ -1,20 +1,35 @@
 import { wechatAuthLogin, mobileLogin, getAccessToken } from '@/services/api/auth.js'
 import { wechatAuthLogin, mobileLogin, getAccessToken } from '@/services/api/auth.js'
 import { wxLogin } from '@/common/auth.js'
 import { wxLogin } from '@/common/auth.js'
-import { setStorage } from '@/common/storage.js'
+import { setStorage, getStorage } from '@/common/storage.js'
 import { objAssign } from '@/common/utils.js'
 import { objAssign } from '@/common/utils.js'
 
 
-const state = {
-    // 用户信息
-    headImgUrl: '',
-    mobile: '',
-    nickName: '',
-    openId: '',
-    userId: 0,
-    userIdentity: -1, // 用户类型
-    inviteUserId: '', // 分享者用户ID
-    accessToken: '', // token
+function initUserState() {
+    const state = {
+        // 用户信息
+        headImgUrl: '',
+        mobile: '',
+        nickName: '',
+        openId: '',
+        userId: 0,
+        userIdentity: -1, // 用户类型
+        inviteUserId: '', // 分享者用户ID
+        accessToken: '', // token
+    }
+    const userInfo = getStorage('USER_INFO')
+    if (userInfo) {
+        Object.assign(state, userInfo)
+    }
+    const accessToken = getStorage('ACCESS_TOKEN')
+    if (accessToken) {
+        state.accessToken = accessToken
+    }
+    return state
 }
 }
 
 
+const state = initUserState()
+
+console.log(state)
+
 const mutations = {
 const mutations = {
     SET_USER_INFO: (state, userInfo) => {
     SET_USER_INFO: (state, userInfo) => {
         objAssign(state, userInfo)
         objAssign(state, userInfo)
@@ -37,10 +52,8 @@ const actions = {
             commit('SET_USER_INFO', data)
             commit('SET_USER_INFO', data)
             setStorage('USER_INFO', data)
             setStorage('USER_INFO', data)
             dispatch('getAccessToken') // 获取token
             dispatch('getAccessToken') // 获取token
-            return res
         } catch (e) {
         } catch (e) {
-            commit('SET_LOGIN_FLAG', false)
-            return Promise.reject(e)
+            console.log(e)
         }
         }
     },
     },
     // 手机号注册登录
     // 手机号注册登录
@@ -50,9 +63,8 @@ const actions = {
             const data = JSON.parse(res.data)
             const data = JSON.parse(res.data)
             commit('SET_USER_INFO', data)
             commit('SET_USER_INFO', data)
             setStorage('USER_INFO', data)
             setStorage('USER_INFO', data)
-            return res
         } catch (e) {
         } catch (e) {
-            return Promise.reject(e)
+            console.log(e)
         }
         }
     },
     },
     // 获取accessToken
     // 获取accessToken
@@ -60,9 +72,9 @@ const actions = {
         try {
         try {
             const res = await getAccessToken()
             const res = await getAccessToken()
             commit('SET_ACCESS_TOKEN', res.data)
             commit('SET_ACCESS_TOKEN', res.data)
-            return res
+            setStorage('ACCESS_TOKEN', res.data)
         } catch (e) {
         } catch (e) {
-            return Promise.reject(e)
+            console.log(e)
         }
         }
     }
     }
 }
 }