562 lines
21 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<view class="container">
<!-- 顶部展开后的阴影 -->
<view class="boxshadow" v-if="topShow"></view>
<view class="header">
<view class="searchBox" :style="{ height: localHeight + 'px', paddingTop: top + 'px' }">
<view class="searchBox_left" @click="back">
<u-icon name="arrow-left" size="20px" color="#000"></u-icon>
</view>
<view class="searchBox_ipt" @click="searchPage">
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/com_communitySearchIcon.png"
mode="aspectFill"></image>
<input disabled type="text" placeholder="输入商品名称" />
</view>
</view>
<view class="slide">
<view class="slide_con">
<view v-for="(item, index) in CateList" :key="index" class="slide_conBox" @click="changeCate(item.id)">
<view class="slide_item" :class="item.id === currentCategoryId ? 'slide_item_active' : ''">
<image :src="picUrl + item.category_pic" mode="aspectFill"></image>
<text>{{ item.category_name }}</text>
</view>
</view>
</view>
<view class="open" @click="topOpen" v-if="!topShow">
展 开
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_openIcon.png"
mode="aspectFill"></image>
</view>
</view>
</view>
<!-- 整体展开的顶部 -->
<view class="header header2" v-if="topShow">
<view class="slide">
<view class="slide_con">
<view v-for="(item, index) in CateList" :key="index" class="slide_conBox" @click="changeCate(item.id)">
<view class="slide_item" :class="item.id === currentCategoryId ? 'slide_item_active' : ''">
<image :src="picUrl + item.category_pic" mode="aspectFill"></image>
<text>{{ item.category_name }}</text>
</view>
</view>
</view>
</view>
<view class="hides" @click="topOpen">
收起 <u-icon name="arrow-up"></u-icon>
</view>
</view>
<view class="Con">
<view class="Con_left">
<view class="CateItem" :class="item.id === currentLeftCateId ? 'CateItem_active' : ''"
v-for="item in leftCateList" :key="item.id" @click="changeLeftCate(item.id)">
<!-- <image v-if="false" class="hot"
src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_hot.png"
mode="aspectFill">
</image> -->
<!-- <image class="bao"
src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_bao.png"
mode="aspectFill"></image> -->
{{ item.category_name }}
</view>
</view>
<view class="Con_right" v-if="tagList1.length > 0">
<view class="CateList_Box" :class="cateListShow ? 'bgf' : ''">
<view class="CateList" ref="cateListRef">
<view class="CateList_Item" v-for="(item, index) in tagList" :key="item.id"
:class="index == rightTopActive ? 'CateList_Item_active' : ''" @click="checkItem(index)">
{{ item.tag_name }}
</view>
</view>
<view class="more" @click="changeCateListShow">
<u-icon v-if="!cateListShow" name="arrow-down"></u-icon>
<u-icon v-if="cateListShow" name="arrow-up"></u-icon>
</view>
</view>
<!-- 右下展开的内容 -->
<view class="activeCateList" v-if="cateListShow">
<view class="CateList_Item" v-for="(item, index) in tagList" :key="index"
:class="index == rightTopActive ? 'CateList_Item_active' : ''" @click="checkItem(index)">
{{ item.tag_name }}
</view>
</view>
<!-- 右下阴影 -->
<view class="boxshadow2" v-if="cateListShow" @click="changeCateListShow"></view>
<view class="CateIte">
<view class="CateInfo"
v-for="item in (selectedTagId === 'all' ? tagList.slice(1) : [tagList.find(t => t.id === selectedTagId) || {}])"
:key="item.id">
<view class="CateInfo_tit">
{{ item.tag_name }}
</view>
<view class="CateInfo_Item" v-for="items in item.commodity_info_list" :key="items.id">
<view class="CateInfo_Item_Box">
<view class="CateInfo_Item_left" @click="goods(items)">
<view class="tag tag-img" v-if="
!items.commodity_goods_info_list[1] &&
items.commodity_goods_info_list[0].is_same_day
">当日达</view>
<image :src="picUrl + items.commodity_pic" mode="aspectFill"></image>
</view>
<view class="CateInfo_Item_right" :class="GGshow ? 'noneBor' : ''">
<view class="CateInfo_Item_right_Tit" @click="goods(items)">
<view class="tag tag-text" v-if="
!items.commodity_goods_info_list[1] &&
items.commodity_goods_info_list[0].is_same_day
">当日达</view>
{{ items.commodity_name }}
</view>
<view class="CateInfo_Item_right_subtit" @click="goods(items)">
{{ items.commodity_intro }}
</view>
<view class="CateInfo_Item_Money">
<view class="CateInfo_Item_Money_left">
{{ getPriceRange(items.commodity_goods_info_list) }}
</view>
<view class="CateInfo_Item_Money_right" v-if="!(items.commodity_goods_info_list.length > 1)">
<u-number-box :min="0" v-model="items.commodity_goods_info_list[0].quantity"
@change="(value) => handleQuantityChange(value, items)">
<view slot="minus" class="minus">
<u-icon name="minus" size="20"></u-icon>
</view>
<text slot="input" style="width: 50px; text-align: center" class="input">{{
items.commodity_goods_info_list[0].quantity
? items.commodity_goods_info_list[0].quantity
: 0
}}</text>
<view slot="plus" class="plus">
<u-icon name="plus" color="#FFFFFF" size="20"></u-icon>
</view>
</u-number-box>
</view>
</view>
<view class="gg" @click="chooseGG(item,items)" v-if="
items.commodity_goods_info_list.length > 1 && !items.isShow
">
选择规格
<u-icon name="arrow-down" size="26rpx" color="#FF370B"></u-icon>
</view>
<view class="gg" @click="chooseGG(item,items)" v-if="
items.commodity_goods_info_list.length > 1 && items.isShow
">
收起
<u-icon name="arrow-up" size="26rpx" color="#FF370B"></u-icon>
</view>
</view>
</view>
<view class="GGList" v-if="items.isShow">
<view class="GGItem" v-for="ite in items.commodity_goods_info_list" :key="ite.id" @click="goods(items)">
<view class="GGItem_Image">
<view class="tag tag-img" v-if="ite.is_same_day">当日达</view>
<image :src="picUrl + ite.commodity_pic" mode="aspectFill"></image>
</view>
<view class="GGItem_Con">
<view class="GGItem_Con_Tit">
<view class="tag tag-text" v-if="ite.is_same_day">当日达</view>
{{ ite.goods_name }}
</view>
<view class="GGItem_Con_Msg">
<view class="GGItem_Con_Msg_left">
<span>¥</span>{{ ite.sales_price }}
</view>
<view class="GGItem_Con_Msg_right">
<u-number-box v-model="ite.quantity" :min="0"
@change="(value) => handleQuantityChange(value, ite)">
<view slot="minus" class="minus">
<u-icon name="minus" size="20"></u-icon>
</view>
<text slot="input" style="width: 50px; text-align: center" class="input">{{ ite.quantity ?
ite.quantity : 0 }}</text>
<view slot="plus" class="plus">
<u-icon name="plus" color="#FFFFFF" size="20"></u-icon>
</view>
</u-number-box>
</view>
</view>
</view>
</view>
</view>
</view>
<!-- 按钮 -->
<!-- <view class="btn">
查看全部商品
<view class="cir">
<u-icon name="arrow-right" color="#fff" size="12px"></u-icon>
</view>
</view> -->
</view>
</view>
</view>
<view class="Con_right" v-else>
<view class="empty">
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/com_nearbyList_empty.png"
mode="aspectFill"></image>
暂无数据
</view>
</view>
</view>
<!-- <nav-footer :current="3" /> -->
<view class="shop_car" @click="shopCar">
<u-badge numberType="limit" type="error" max="99" :value="carNum"></u-badge>
<image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_car_num.png"></image>
<!-- <image src="https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_car_empty.png"></image> -->
</view>
</view>
</template>
<script>
import { apiArr } from "../../../api/shop";
import { picUrl, menuButtonInfo, request, NavgateTo } from "../../../utils";
export default {
data() {
return {
picUrl,
flag: false,
top: "",
localHeight: "",
search: "",
value: "1",
cateListShow: false,
conRightElement: null,
iconList: [
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon1.png",
name: "休闲零食",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon2.png",
name: "肉蛋果蔬",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon3.png",
name: "酒水饮料",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon4.png",
name: "家具电器",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png",
name: "电脑手机",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon1.png",
name: "休闲零食",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon2.png",
name: "肉蛋果蔬",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon3.png",
name: "酒水饮料",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon4.png",
name: "家具电器",
},
{
icon: "https://wechat-img-file.oss-cn-beijing.aliyuncs.com/property-img-file/shop_icon5.png",
name: "电脑手机",
},
],
rightTopActive: 0,
currentLeftCateId: null,
topShow: false,
currentCategoryId: null,
GGshow: false,
originalTagList: [], // 存储原始的tagList数据
selectedTagId: null, // 当前选中的标签ID
CateList: [], //分类列表
currentFirstId: "",
leftCateList: [], //底部左侧分类
currentSecondId: "",
rightCateList: [], //底部右侧分类
currentThirdId: "",
tagList: [],
tagList1: [],
carNum: "",
goodsDetail: [],
showTag: false, //当日达标签
};
},
methods: {
back() {
NavgateTo('1')
},
changeCate(id) {
this.checkItem(0)
// 更新当前选中的顶级分类ID
this.currentCategoryId = id;
// 根据id查找对应的分类
const category = this.CateList.find((item) => item.id === id);
if (category) {
// 将leftCateList设置为该分类的二级分类若为null则设为空数组
this.leftCateList = category.level_two_category || [];
this.tagList1 = category.level_three_category || [];
if (this.leftCateList.length > 0) {
this.currentLeftCateId = this.leftCateList[0].id;
this.secondId = this.leftCateList[0].id;
} else {
this.currentLeftCateId = null;
this.secondId = null;
}
this.getGoodsList();
}
this.topShow = false;
},
//顶部分类点击
changeCateListShow() {
this.cateListShow = !this.cateListShow;
},
//选择右下角分类
checkItem(index) {
this.cateListShow = false
this.rightTopActive = index;
// 获取选中的标签ID
this.selectedTagId = this.tagList[index]?.id;
},
//右下角点击更多
topOpen() {
this.topShow = !this.topShow;
},
// 选择商品规格
chooseGG(item,targetItems) {
// 根据两个参数的id判断点击的数据
if (item && targetItems && item.id) {
for (let i = 1; i < this.tagList.length; i++) {
const tagItem = this.tagList[i];
// 先根据item.id找到对应的tagItem
if (tagItem.id === item.id) {
const infoIndex = tagItem.commodity_info_list.findIndex(infoItem => infoItem.id === targetItems.id);
if (infoIndex > -1) {
// 直接修改数据源中的对象,确保响应式
const currentItem = tagItem.commodity_info_list[infoIndex];
this.$set(currentItem, 'isShow', !currentItem.isShow);
console.log("修改后数据源中的isShow:", currentItem.isShow);
break;
}
}
}
}
},
//搜索页
searchPage() {
NavgateTo("../search/index");
},
//商品详情页
goods(e) {
NavgateTo(`../goods/index?item=${JSON.stringify(e)}`);
// NavgateTo("../goods/index");
},
// 购物车
shopCar() {
NavgateTo("../shopCar/index");
},
//分类列表
getCateList() {
request(apiArr.goodsCateList, "POST", {}).then((res) => {
console.log(res);
this.CateList = res.commodity_category_list;
this.firstId = res.commodity_category_list[0].id;
// 设置默认选中第一个分类
this.currentCategoryId = this.firstId;
this.leftCateList =
res.commodity_category_list[0].level_two_category || [];
if (this.leftCateList.length > 0) {
this.currentLeftCateId = this.leftCateList[0].id;
this.secondId = this.leftCateList[0].id;
} else {
this.currentLeftCateId = null;
this.secondId = null;
}
this.getGoodsList();
});
},
getGoodsList() {
if (!this.secondId) {
this.tagList = [];
this.originalTagList = [];
return;
}
request(apiArr.getGoodsList, "POST", {
user_id: uni.getStorageSync("userId"),
id: this.secondId,
}).then((res) => {
// 深拷贝接口数据,避免引用问题
const commodityList = JSON.parse(JSON.stringify(res.commodity_list));
commodityList.forEach((tagItem) => { // 重命名外层变量,避免嵌套冲突
tagItem.commodity_info_list.forEach((infoItem) => { // 内层变量重命名
// 初始化isShow为响应式属性
this.$set(infoItem, 'isShow', false);
infoItem.commodity_goods_info_list.forEach((param) => {
this.goodsDetail.forEach((goods) => {
if (goods.goods_id === param.id) {
this.$set(param, 'quantity', goods.count); // 同步数量也要用$set
}
});
});
});
});
this.originalTagList = commodityList;
this.tagList1 = commodityList;
// 重新构建tagList确保使用拷贝后的响应式数据
this.tagList = [{ id: 'all', tag_name: '全部' }, ...commodityList];
this.rightTopActive = 0;
this.selectedTagId = 'all';
});
},
getShopCarList() {
request(apiArr.getCar, "POST").then((res) => {
this.carNum = res.total;
// 合并当日达和普通商品数据
this.goodsDetail = [].concat(res.same_day_cart_list, res.normal_cart_list)
.flatMap(supplier => supplier.commodity_cart_and_goods_model);
});
},
changeLeftCate(e) {
this.currentLeftCateId = e;
this.secondId = e;
this.getGoodsList();
},
//商品数量变化
handleQuantityChange(val, item) {
const quantity = typeof val === 'object' && val !== null && 'value' in val ? val.value : val;
// 检查库存数量
let currentQuantity = 0;
let stockQuantity = 0;
let goodsToUpdate = null;
// 对于有规格的主商品绑定到items.commodity_goods_info_list[0].quantity
if (
item.commodity_goods_info_list &&
item.commodity_goods_info_list.length
) {
this.goodsId = item.commodity_goods_info_list[0].id;
currentQuantity = item.commodity_goods_info_list[0].quantity || 0;
stockQuantity = item.commodity_goods_info_list[0].stock_quantity || 0;
goodsToUpdate = item.commodity_goods_info_list[0];
}
// 对于规格列表中的商品绑定到ite.quantity
else {
this.goodsId = item.id;
currentQuantity = item.quantity || 0;
stockQuantity = item.stock_quantity || 0;
goodsToUpdate = item;
}
// 判断是否增加数量且库存不足
if (quantity > currentQuantity && currentQuantity >= stockQuantity) {
uni.showToast({
title: "库存不足",
icon: 'none'
});
return;
}
// 使用$set确保响应式更新
this.$set(goodsToUpdate, 'quantity', quantity);
const params = {
user_id: uni.getStorageSync("userId"),
goods_id_and_count: [
{
goods_id: this.goodsId,
count: quantity,
},
],
};
// 发送请求更新后端数据
request(apiArr.updateCar, "POST", params).then((res) => {
console.log(res);
// 先更新购物车数据
this.getShopCarList();
// 延迟一小段时间确保goodsDetail已经更新
setTimeout(() => {
// 重新同步商品列表中的数量
this.syncGoodsQuantities();
}, 100);
uni.showToast({
title: "操作成功!",
success() { },
});
});
},
// 同步商品列表中的数量
syncGoodsQuantities() {
// 遍历所有商品,同步数量
this.tagList.forEach((tagItem) => {
if (tagItem.commodity_info_list) {
tagItem.commodity_info_list.forEach((infoItem) => {
infoItem.commodity_goods_info_list.forEach((param) => {
const goods = this.goodsDetail.find(g => g.goods_id === param.id);
if (goods) {
this.$set(param, 'quantity', goods.count);
}
});
});
}
});
},
getPriceRange(goodsList) {
if (!goodsList || goodsList.length === 0) return '¥0';
const prices = goodsList.map(item => Number(item.sales_price));
const minPrice = Math.min(...prices);
const maxPrice = Math.max(...prices);
return minPrice === maxPrice ? `${minPrice}` : `${minPrice} ~ ¥${maxPrice}`;
},
},
onLoad(options) {
const meun = menuButtonInfo();
this.top = meun.top;
this.localHeight = meun.height;
this.getCateList();
// this.getShopCarList();
},
onShow() {
this.getShopCarList();
this.getGoodsList();
},
onHide() {
// 移除滚动事件监听
if (this.conRightElement) {
this.conRightElement = null;
}
},
onReachBottom() {
if (this.flag) {
}
},
};
</script>
<style>
@import url("./index.css");
</style>