296 lines
8.9 KiB
Vue
296 lines
8.9 KiB
Vue
|
<template>
|
|||
|
<view class="gg">
|
|||
|
<u-navbar :border-bottom="false" :is-back="false">
|
|||
|
<view class="u-flex u-m-l-20 u-m-r-20 gg-search-navbar">
|
|||
|
<view class="u-font-xl u-m-r-20">分类</view>
|
|||
|
<view class="gg-notice-search-bar">
|
|||
|
<u-icon class="gg-notice-search-bar-left-icon" name="search"></u-icon>
|
|||
|
<u-notice-bar
|
|||
|
:border-radius="30"
|
|||
|
:is-circular="false"
|
|||
|
:list="list"
|
|||
|
:more-icon="false"
|
|||
|
:volume-icon="false"
|
|||
|
class="gg-notice-search-bar-u-notice-bar"
|
|||
|
mode="vertical"
|
|||
|
type="none"
|
|||
|
></u-notice-bar>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</u-navbar>
|
|||
|
|
|||
|
<view class="gg-menu-wrap">
|
|||
|
<scroll-view :scroll-top="scrollTop" class="gg-tab-view menu-scroll-view" scroll-with-animation scroll-y>
|
|||
|
<view
|
|||
|
v-for="(item, index) in categories"
|
|||
|
:key="item.id"
|
|||
|
:class="[current === index ? 'gg-tab-item-active' : '']"
|
|||
|
:data-current="index"
|
|||
|
class="gg-tab-item"
|
|||
|
@tap.stop="swichCategory(item.id, index)"
|
|||
|
>
|
|||
|
<text class="u-line-1">{{ item.name }}</text>
|
|||
|
</view>
|
|||
|
</scroll-view>
|
|||
|
|
|||
|
<scroll-view class="gg-right-box" scroll-y @scrolltolower="loadMore">
|
|||
|
<view v-for="(item, index) in searchResult.content" :key="item.id" @click="gotoProductItem(item.id)">
|
|||
|
<view class="u-m-b-10 u-m-l-20 u-m-r-20 u-flex gg-product-item">
|
|||
|
<ListImgItem
|
|||
|
:showBottom="item.skuType === 0 && item.isNewPerson === 1"
|
|||
|
:showLeft="item.skuType === 1"
|
|||
|
:showRight="false"
|
|||
|
:src="item.imgUrl"
|
|||
|
height="200rpx"
|
|||
|
width="200rpx"
|
|||
|
>
|
|||
|
<template #left>秒杀商品</template>
|
|||
|
</ListImgItem>
|
|||
|
<view class="gg-product-item-msg u-border-bottom u-p-b-20 u-m-l-20">
|
|||
|
<view>
|
|||
|
<view class="u-font-lg">{{ item.title }}</view>
|
|||
|
<view class="u-type-info u-font-sm">已售{{ item.sale }}/剩余{{ item.stock }}</view>
|
|||
|
<block v-if="item.ruleList">
|
|||
|
<view v-for="(rule, ruleIndex) in item.ruleList" :key="ruleIndex" class="u-font-xs u-type-error-dark">
|
|||
|
{{ rule }}
|
|||
|
</view>
|
|||
|
</block>
|
|||
|
</view>
|
|||
|
<view class="u-flex u-row-between">
|
|||
|
<view class="u-type-error gg-product-item-msg-price-container">
|
|||
|
<text>¥</text>
|
|||
|
<text class="gg-product-item-msg-price-container-value">{{ item.price }}</text>
|
|||
|
</view>
|
|||
|
<AddToCart :shopDetail="item"></AddToCart>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
<u-gap height="20"></u-gap>
|
|||
|
</view>
|
|||
|
|
|||
|
<!-- 如果列表没有更多数据,则显示分隔线 -->
|
|||
|
<u-divider v-if="!(searchResult.first && searchResult.empty) && searchResult.last" :height="60"
|
|||
|
bg-color="transparent">我是有底线的
|
|||
|
</u-divider>
|
|||
|
<!-- 如果列表没有数据,则显示空内容 -->
|
|||
|
<u-empty :show="searchResult.first && searchResult.empty" mode="list"></u-empty>
|
|||
|
</scroll-view>
|
|||
|
</view>
|
|||
|
</view>
|
|||
|
</template>
|
|||
|
|
|||
|
<script>
|
|||
|
import {mapState, mapActions} from 'vuex';
|
|||
|
|
|||
|
export default {
|
|||
|
data() {
|
|||
|
return {
|
|||
|
list: ['最见搜索关键字', '暂时未处理搜索页', '可以考虑最见关键字'],
|
|||
|
current: 0, // 预设当前项的值
|
|||
|
categoryId: 0, // 当前选中的分类Id
|
|||
|
scrollTop: 0, //tab标题的滚动条位置
|
|||
|
menuHeight: 0, // 左边菜单的高度
|
|||
|
menuItemHeight: 0, // 左边菜单item的高度
|
|||
|
filter: {
|
|||
|
page: 1, // 当前页码
|
|||
|
limit: 5, // 每页记录数
|
|||
|
keyword: '', // 关键字
|
|||
|
wareId: ''
|
|||
|
},
|
|||
|
searchResult: {
|
|||
|
content: [],
|
|||
|
last: false
|
|||
|
} // 搜索商品结果对象
|
|||
|
};
|
|||
|
},
|
|||
|
computed: {
|
|||
|
...mapState('categoriesModule', ['categories'])
|
|||
|
},
|
|||
|
methods: {
|
|||
|
...mapActions('categoriesModule', ['getCategoriesAction']),
|
|||
|
...mapActions('cartModule', ['getCartListAction']),
|
|||
|
/*
|
|||
|
为什么不使用scroll-into-view而使用手动计算的方式,
|
|||
|
这是因为scroll-into-view不会进行居中菜单位置的定位处理,
|
|||
|
为了更好的用户操作体验,可以让当前选中菜单定位于整体滚动的居中位置
|
|||
|
*/
|
|||
|
// 点击左边的栏目切换
|
|||
|
async swichCategory(categoryId, index) {
|
|||
|
Object.assign(this.$data.searchResult, this.$options.data().searchResult); // 这里重置 searchResult 下的所有数据
|
|||
|
Object.assign(this.$data.filter, this.$options.data().filter); // 这里重置 filter 下的所有数据
|
|||
|
|
|||
|
this.categoryId = categoryId;
|
|||
|
if (index == this.current) return; // 防止选中分类的再次点击
|
|||
|
this.current = index;
|
|||
|
// 如果为0,意味着尚未初始化
|
|||
|
if (this.menuHeight == 0 || this.menuItemHeight == 0) {
|
|||
|
await this.getElRect('menu-scroll-view', 'menuHeight');
|
|||
|
await this.getElRect('gg-tab-item', 'menuItemHeight');
|
|||
|
}
|
|||
|
// 将菜单菜单活动item垂直居中
|
|||
|
this.scrollTop = index * this.menuItemHeight + this.menuItemHeight / 2 - this.menuHeight / 2;
|
|||
|
|
|||
|
// 获取右侧商品搜索结果数据
|
|||
|
this.getCategoryProductList();
|
|||
|
},
|
|||
|
// 获取一个目标元素的高度
|
|||
|
getElRect(elClass, dataVal) {
|
|||
|
new Promise((resolve, reject) => {
|
|||
|
const query = uni.createSelectorQuery().in(this);
|
|||
|
query
|
|||
|
.select('.' + elClass)
|
|||
|
.fields({size: true}, res => {
|
|||
|
// 如果节点尚未生成,res值为null,循环调用执行
|
|||
|
if (!res) {
|
|||
|
setTimeout(() => {
|
|||
|
this.getElRect(elClass);
|
|||
|
}, 10);
|
|||
|
return;
|
|||
|
}
|
|||
|
this[dataVal] = res.height;
|
|||
|
})
|
|||
|
.exec();
|
|||
|
});
|
|||
|
},
|
|||
|
// 获取分类商品列表
|
|||
|
async getCategoryProductList() {
|
|||
|
const o = {
|
|||
|
categoryId: this.categoryId,
|
|||
|
page: this.filter.page,
|
|||
|
keyword: this.filter.keyword,
|
|||
|
limit: this.filter.limit,
|
|||
|
wareId: this.filter.wareId
|
|||
|
};
|
|||
|
let result = await this.$u.api.getSearchSku(o);
|
|||
|
this.searchResult = {...result, content: [...this.searchResult.content, ...result.content]};
|
|||
|
},
|
|||
|
// 加载更多数据
|
|||
|
loadMore() {
|
|||
|
if (!this.searchResult.last) {
|
|||
|
this.filter.page = this.filter.page + 1;
|
|||
|
this.getCategoryProductList();
|
|||
|
}
|
|||
|
},
|
|||
|
// 跳转到商品详情页
|
|||
|
gotoProductItem(skuId) {
|
|||
|
this.$u.route('/pages/homeItem/homeItem', {
|
|||
|
skuId
|
|||
|
});
|
|||
|
}
|
|||
|
},
|
|||
|
async mounted() {
|
|||
|
await this.getCategoriesAction(); // 从仓库中获取分类列表
|
|||
|
this.categoryId = this.categories[0].id; // 获取第一个分类的id
|
|||
|
await this.getCategoryProductList(); // 商品数据搜索请求
|
|||
|
// 需要获取购物车数据列表,将最新获取的数据渲染到页面
|
|||
|
this.getCartListAction();
|
|||
|
}
|
|||
|
};
|
|||
|
</script>
|
|||
|
|
|||
|
<style lang="scss" scoped>
|
|||
|
.gg {
|
|||
|
height: calc(100vh);
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
|
|||
|
&-search-navbar {
|
|||
|
margin-top: -20rpx;
|
|||
|
width: 100%;
|
|||
|
}
|
|||
|
|
|||
|
/* 滚动信息搜索框 */
|
|||
|
&-notice-search-bar {
|
|||
|
flex: 1;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
background-color: #ededed;
|
|||
|
border-radius: 30rpx;
|
|||
|
|
|||
|
/* 滚动信息搜索框左侧图标 */
|
|||
|
&-left-icon {
|
|||
|
position: relative;
|
|||
|
left: 20rpx;
|
|||
|
color: $u-light-color;
|
|||
|
}
|
|||
|
|
|||
|
/* 滚动信息搜索框中的字体设置 */
|
|||
|
&-u-notice-bar {
|
|||
|
flex: 1;
|
|||
|
/* 深层穿透修改子组件字体颜色样式 */
|
|||
|
::v-deep .u-news-item {
|
|||
|
color: $u-light-color !important;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 菜单包装器 */
|
|||
|
&-menu-wrap {
|
|||
|
flex: 1;
|
|||
|
display: flex;
|
|||
|
overflow: hidden;
|
|||
|
}
|
|||
|
|
|||
|
/* 左侧sv选项卡模式菜单 */
|
|||
|
&-tab-view {
|
|||
|
width: 200rpx;
|
|||
|
height: 100%;
|
|||
|
}
|
|||
|
|
|||
|
/* 左侧菜单选项卡项 */
|
|||
|
&-tab-item {
|
|||
|
height: 110rpx;
|
|||
|
background: #f6f6f6;
|
|||
|
box-sizing: border-box;
|
|||
|
display: flex;
|
|||
|
align-items: center;
|
|||
|
justify-content: center;
|
|||
|
font-size: 26rpx;
|
|||
|
color: #444;
|
|||
|
font-weight: 400;
|
|||
|
line-height: 1;
|
|||
|
|
|||
|
/* 激活状态 */
|
|||
|
&-active {
|
|||
|
position: relative;
|
|||
|
color: $u-type-warning;
|
|||
|
font-size: 30rpx;
|
|||
|
font-weight: 600;
|
|||
|
background: #fff;
|
|||
|
/* 伪类处理 */
|
|||
|
&::before {
|
|||
|
content: '';
|
|||
|
position: absolute;
|
|||
|
border-left: 4px solid $u-type-warning;
|
|||
|
height: 32rpx;
|
|||
|
left: 0;
|
|||
|
top: 39rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
/* 产品列表项 */
|
|||
|
&-product-item {
|
|||
|
height: 210rpx;
|
|||
|
|
|||
|
&-msg {
|
|||
|
height: 100%;
|
|||
|
flex: 1;
|
|||
|
display: flex;
|
|||
|
flex-direction: column;
|
|||
|
justify-content: space-between;
|
|||
|
|
|||
|
&-price-container {
|
|||
|
&-value {
|
|||
|
font-size: 40rpx;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
&-right-box {
|
|||
|
background-color: rgb(250, 250, 250);
|
|||
|
}
|
|||
|
}
|
|||
|
</style>
|