393 lines
7.5 KiB
Vue
393 lines
7.5 KiB
Vue
<template>
|
||
<z-paging-swiper>
|
||
<template #top>
|
||
<view class="" style="width: 100%; height: 225.19rpx; background-color: white; position: relative;">
|
||
<view class="title">
|
||
商城
|
||
</view>
|
||
</view>
|
||
|
||
</template>
|
||
<z-paging ref="paging" show-refresher-update-time loading-more-no-more-text="我也是有底线的!" v-model="dataList"
|
||
@query="queryList" :fixed="false" :show-loading-more-when-reload="true">
|
||
<!-- 搜索 -->
|
||
<text-search v-model="searchKeyword" placeholder="搜索商品" @search="handleSearch" @clear="clearSearch" />
|
||
<!-- 顶部三个商品 -->
|
||
<swiper v-if="!isSearch && topDataList.length > 0" :display-multiple-items="3" class="top" :duration="500">
|
||
<swiper-item v-for="(item, i) in topDataList" :key="i" @click="goToDetail(item)">
|
||
<view class="item">
|
||
<view class="img">
|
||
<image v-if="item.image" :src="item.image" mode="aspectFill" class="product-image">
|
||
</image>
|
||
</view>
|
||
|
||
<view class="item-info">
|
||
<view class="item-name">
|
||
{{ item.title }}
|
||
</view>
|
||
<view class="item-bottom">
|
||
<view class="item-price">
|
||
<text class="price-symbol-small">¥</text>
|
||
<text class="price-value-small">{{ item.price }}</text>
|
||
</view>
|
||
|
||
<view class="item-count">
|
||
<text class="count-text-small">{{ item.sales }}/{{ item.stock }}</text>
|
||
<image src="/static/ic_box.png" class="box-icon-small" mode="aspectFit"></image>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</swiper-item>
|
||
</swiper>
|
||
<view class="view-list">
|
||
<view class="product-item" v-for="(item, i) in dataList" :key="i" @click="goToDetail(item)">
|
||
|
||
<view class="product-image-container">
|
||
<image v-if="item.image" :src="item.image" mode="aspectFill" class="product-image">
|
||
</image>
|
||
</view>
|
||
|
||
<view class="product-name">
|
||
{{ item.title }}
|
||
</view>
|
||
|
||
<view class="product-count">
|
||
<text class="count-text">{{ item.sales }}/{{ item.stock }}</text>
|
||
<image src="/static/ic_box.png" class="box-icon" mode="aspectFit"></image>
|
||
</view>
|
||
|
||
<view class="product-price">
|
||
<text class="price-symbol">¥</text>
|
||
<text class="price-value">{{ item.price }}</text>
|
||
</view>
|
||
|
||
<view class="buy-button" @click.stop="buyProduct(item)">
|
||
<text class="buy-text">购买</text>
|
||
</view>
|
||
|
||
|
||
</view>
|
||
|
||
</view>
|
||
|
||
<template #empty>
|
||
<no-data />
|
||
</template>
|
||
<template #loading>
|
||
<loading-data />
|
||
</template>
|
||
</z-paging>
|
||
</z-paging-swiper>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue';
|
||
const paging = ref(null);
|
||
import { getProductList, getBannerList } from '@/common/server/product';
|
||
import TextSearch from '@/components/youdas-container/text-search.vue';
|
||
|
||
// 响应式数据
|
||
const topDataList = ref([
|
||
]);
|
||
let isSearch = ref(false);
|
||
const dataList = ref([]);
|
||
const searchKeyword = ref(''); // 搜索关键词
|
||
|
||
// 跳转到商品详情页
|
||
const goToDetail = (item) => {
|
||
uni.navigateTo({
|
||
url: `/pages/mall/product-detail?id=${item.id}`
|
||
});
|
||
};
|
||
|
||
// 购买商品
|
||
const buyProduct = (item, event) => {
|
||
// 阻止事件冒泡
|
||
event.stopPropagation();
|
||
|
||
// 检查库存
|
||
if (item.stock <= 0) {
|
||
uni.showToast({
|
||
title: '商品已售罄',
|
||
icon: 'none'
|
||
});
|
||
return;
|
||
}
|
||
|
||
// 添加到购物车或直接购买的逻辑
|
||
uni.showToast({
|
||
title: '已添加到购物车',
|
||
icon: 'success'
|
||
});
|
||
};
|
||
|
||
// 处理搜索
|
||
const handleSearch = () => {
|
||
if (searchKeyword.value == '') {
|
||
isSearch.value = false;
|
||
} else {
|
||
isSearch.value = true;
|
||
}
|
||
|
||
paging.value.reload();
|
||
};
|
||
|
||
// 清空搜索
|
||
const clearSearch = () => {
|
||
searchKeyword.value = '';
|
||
isSearch.value = false;
|
||
paging.value.reload();
|
||
};
|
||
|
||
const queryList = (pageNo, pageSize) => {
|
||
getProductList(pageNo, pageSize, searchKeyword.value).then(res => {
|
||
dataList.value.concat(res || []);
|
||
paging.value.complete(res || false);
|
||
});
|
||
};
|
||
|
||
onLoad(async () => {
|
||
const bannerList = await getBannerList();
|
||
topDataList.value = bannerList;
|
||
});
|
||
</script>
|
||
|
||
<style lang="scss">
|
||
.content {
|
||
width: 100%;
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background-color: #F7F7F7;
|
||
}
|
||
|
||
.title {
|
||
width: 100%;
|
||
display: flex;
|
||
justify-content: center;
|
||
align-items: center;
|
||
font-size: 32.44rpx;
|
||
font-weight: 600;
|
||
position: absolute;
|
||
bottom: 30rpx;
|
||
}
|
||
|
||
.top {
|
||
width: 688.94rpx;
|
||
height: 325.38rpx;
|
||
margin: 34rpx auto;
|
||
display: flex;
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
|
||
.item {
|
||
width: 216.31rpx;
|
||
height: 100%;
|
||
background-color: #FFFFFF;
|
||
border-radius: 15.27rpx;
|
||
display: flex;
|
||
flex-direction: column;
|
||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||
transition: transform 0.3s;
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
}
|
||
}
|
||
|
||
.img {
|
||
width: 100%;
|
||
height: 216.31rpx;
|
||
background-color: #F2F2F2;
|
||
border-radius: 15.27rpx 15.27rpx 0rpx 0rpx;
|
||
overflow: hidden;
|
||
|
||
.product-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.item-info {
|
||
width: 100%;
|
||
height: 109.07rpx;
|
||
position: relative;
|
||
padding: 8rpx;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.item-name {
|
||
width: 100%;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
font-size: 19.08rpx;
|
||
color: #333333;
|
||
text-align: center;
|
||
margin-top: 6rpx;
|
||
}
|
||
|
||
.item-bottom {
|
||
position: absolute;
|
||
width: 100%;
|
||
bottom: 12rpx;
|
||
left: 0;
|
||
padding: 0 13rpx;
|
||
box-sizing: border-box;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
}
|
||
|
||
.item-price {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
}
|
||
|
||
.price-symbol-small {
|
||
font-size: 15.27rpx;
|
||
margin-top: 6rpx;
|
||
color: #FF6A6A;
|
||
}
|
||
|
||
.price-value-small {
|
||
font-size: 22.9rpx;
|
||
font-weight: bold;
|
||
color: #FF6A6A;
|
||
}
|
||
|
||
.item-count {
|
||
display: flex;
|
||
flex-direction: row;
|
||
align-items: center;
|
||
}
|
||
|
||
.count-text-small {
|
||
font-size: 15.27rpx;
|
||
color: #6C6C6C;
|
||
}
|
||
|
||
.box-icon-small {
|
||
width: 17.39rpx;
|
||
height: 17.39rpx;
|
||
margin-left: 7rpx;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
.product-item {
|
||
width: 100%;
|
||
height: 261.45rpx;
|
||
background-color: #FFFFFF;
|
||
margin-bottom: 21rpx;
|
||
border-radius: 15.27rpx;
|
||
position: relative;
|
||
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
||
transition: transform 0.3s;
|
||
|
||
&:active {
|
||
transform: scale(0.98);
|
||
}
|
||
}
|
||
|
||
.product-image-container {
|
||
width: 216.31rpx;
|
||
height: 216.31rpx;
|
||
background-color: #F2F2F2;
|
||
border-radius: 15.27rpx;
|
||
position: absolute;
|
||
left: 22rpx;
|
||
top: 22rpx;
|
||
overflow: hidden;
|
||
|
||
.product-image {
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
}
|
||
|
||
.product-name {
|
||
width: 350rpx;
|
||
overflow: hidden;
|
||
text-overflow: ellipsis;
|
||
white-space: nowrap;
|
||
position: absolute;
|
||
left: 269rpx;
|
||
top: 44rpx;
|
||
font-size: 26.72rpx;
|
||
font-weight: 600;
|
||
color: #333333;
|
||
}
|
||
|
||
.product-count {
|
||
position: absolute;
|
||
display: flex;
|
||
flex-direction: row;
|
||
left: 269rpx;
|
||
top: 95rpx;
|
||
align-items: center;
|
||
|
||
.count-text {
|
||
font-size: 15.27rpx;
|
||
color: #6C6C6C;
|
||
}
|
||
|
||
.box-icon {
|
||
width: 17.39rpx;
|
||
height: 17.39rpx;
|
||
margin-left: 7rpx;
|
||
}
|
||
}
|
||
|
||
.product-price {
|
||
position: absolute;
|
||
display: flex;
|
||
flex-direction: row;
|
||
left: 269rpx;
|
||
bottom: 44rpx;
|
||
align-items: center;
|
||
|
||
.price-symbol {
|
||
font-size: 19.08rpx;
|
||
margin-top: 15rpx;
|
||
color: #FF6A6A;
|
||
}
|
||
|
||
.price-value {
|
||
font-size: 34.35rpx;
|
||
font-weight: bold;
|
||
color: #FF6A6A;
|
||
}
|
||
}
|
||
|
||
.buy-button {
|
||
width: 89.22rpx;
|
||
height: 42rpx;
|
||
border-radius: 20.99rpx;
|
||
border: 1rpx solid #FF6A6A;
|
||
background-color: white;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
position: absolute;
|
||
right: 38rpx;
|
||
bottom: 38rpx;
|
||
transition: all 0.3s;
|
||
|
||
&:active {
|
||
background-color: #FF6A6A;
|
||
|
||
.buy-text {
|
||
color: white;
|
||
}
|
||
}
|
||
|
||
.buy-text {
|
||
font-size: 19.08rpx;
|
||
color: #FF6A6A;
|
||
font-weight: 500;
|
||
}
|
||
}
|
||
</style> |