feat: 优化活动列表和首页交互效果
This commit is contained in:
parent
12a5c6771a
commit
4dd491b61b
@ -6,51 +6,30 @@
|
|||||||
<view class="" >探索啤酒风味新边界</view>
|
<view class="" >探索啤酒风味新边界</view>
|
||||||
</view> -->
|
</view> -->
|
||||||
<view class="container">
|
<view class="container">
|
||||||
|
|
||||||
<scroll-view scroll-y style="height: 100%;width: 100%;">
|
<scroll-view scroll-y style="height: 100%;width: 100%;">
|
||||||
<view class="" style="margin: 20rpx 0;font-size: 32rpx;color: #030303;font-weight: 600;">
|
<!-- 活动标题和描述 -->
|
||||||
<view class="" >TasteRoom 风味屋 · 风味之旅系列</view>
|
<view class="activity-header">
|
||||||
|
<view class="activity-title">{{activityInfo.title || 'TasteRoom 风味屋 · 风味之旅系列'}}</view>
|
||||||
|
<view class="activity-desc">{{activityInfo.description || '探索啤酒风味新边界'}}</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="" style="margin: 20rpx 0;font-size: 24rpx;color: #606060;">
|
|
||||||
<view class="" >探索啤酒风味新边界</view>
|
|
||||||
</view>
|
|
||||||
<view style="width: 100%;" class="flex align-center flex-wrap justify-between">
|
|
||||||
<view class="" style="width: 32%;height: 100%;text-align: center;" v-for="it in currentMonth">
|
|
||||||
<image :src="it.cover" style="width: 100%;height: 300rpx;margin-right:20rpx;"></image>
|
|
||||||
<view class="" style="height: 80rpx;font-size: 28rpx;color: #030303;text-align: left;margin: 12rpx 0;">{{it.beerName}}</view>
|
|
||||||
<view class=""
|
|
||||||
style="font-size: 24rpx;color: rgba(30, 32, 25, 0.8);text-align: left;">西打酒
|
|
||||||
</view>
|
|
||||||
<view class=""
|
|
||||||
style="font-size: 24rpx;color: rgba(30, 32, 25, 0.8);text-align: left;margin: 12rpx 0;">
|
|
||||||
TasteRoom风味屋
|
|
||||||
</view>
|
|
||||||
<view class="flex align-center " style="color: #FFCC00;font-size: 28rpx;margin-bottom: 32rpx;">4.9
|
|
||||||
<image src="@/static/vector.png" style="width: 20rpx;height: 20rpx;margin-left: 10rpx;">
|
|
||||||
</image>
|
|
||||||
|
|
||||||
|
<!-- 酒款列表 -->
|
||||||
|
<view class="beer-list">
|
||||||
|
<view class="beer-item" v-for="(item, index) in beerList" :key="index" @click="toBeer(item)">
|
||||||
|
<image class="beer-image" :src="item.cover" mode="aspectFill"></image>
|
||||||
|
<view class="beer-info">
|
||||||
|
<view class="beer-name">{{item.beerName}}</view>
|
||||||
|
<view class="beer-style">{{item.beerStyles}}</view>
|
||||||
|
<view class="beer-brand">{{item.brandName}}</view>
|
||||||
|
<view class="beer-rating">
|
||||||
|
<text>{{item.avgOverallRating || '4.9'}}</text>
|
||||||
|
<image src="@/static/vector.png" class="rating-icon"></image>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- <view class="beerItem">
|
<view class="more-tip">更多新品发布信息,敬请关注更新~</view>
|
||||||
<view class="beerCard flex align-center" @click="toBeer(it)">
|
|
||||||
<image :src="it.cover" style="width: 144rpx;height: 204rpx;margin-right:20rpx;"></image>
|
|
||||||
<view class="flex-1">
|
|
||||||
|
|
||||||
<view class="word-all margin-bottom-sm" style="color:#1E2019">
|
|
||||||
{{it.beerName}}
|
|
||||||
</view>
|
|
||||||
<view class="word-all margin-bottom-sm"
|
|
||||||
style="font-size: 24rpx;color: rgba(30, 32, 25, 0.8);">{{ it.beerStyles}}
|
|
||||||
</view>
|
|
||||||
<view class="word-all margin-bottom-sm" style="color:#1E2019">{{ it.brandName}}</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<view style="width: 100%;color: #979797;margin-top: 60rpx;margin-bottom: 60rpx;text-align: center;">更多新品发布信息,敬请关注更新~</view>
|
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
<!-- <view class="flex align-center justify-between tip">
|
<!-- <view class="flex align-center justify-between tip">
|
||||||
@ -63,58 +42,69 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
getLastSixMonth,
|
getFeaturePage,
|
||||||
getNewBeerListByMonth,
|
getBeerList
|
||||||
popularStyle,
|
|
||||||
} from "@/api/platform.js"
|
} from "@/api/platform.js"
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dataList: [],
|
activityId: '',
|
||||||
currentMonth: [],
|
activityInfo: {},
|
||||||
currentMonthIndex: 0,
|
beerList: [],
|
||||||
popularStyleList: [],
|
|
||||||
queryForm: {
|
queryForm: {
|
||||||
num: null
|
search: ''
|
||||||
},
|
},
|
||||||
bgcolor:'#19367A',
|
bgcolor:'#19367A',
|
||||||
|
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
onLoad() {
|
onLoad(options) {
|
||||||
this.getPopularStyle()
|
if (options.id) {
|
||||||
this.getLastSixMonthFun()
|
this.activityId = options.id
|
||||||
this.$refs.successRef.open
|
this.getActivityDetail()
|
||||||
// uni.showTabBar()
|
}
|
||||||
},
|
},
|
||||||
onShow(){
|
onShow(){
|
||||||
// uni.showTabBar()
|
// uni.showTabBar()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 获取热门风格
|
// 获取活动详情
|
||||||
getPopularStyle() {
|
async getActivityDetail() {
|
||||||
popularStyle().then(res => {
|
try {
|
||||||
console.log(res)
|
const res = await getFeaturePage(this.activityId)
|
||||||
this.popularStyleList = res.data
|
if (res.code === 200 && res.data) {
|
||||||
|
this.activityInfo = res.data
|
||||||
|
// 获取活动相关的酒款列表
|
||||||
|
this.getBeerList()
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取活动详情失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '获取活动详情失败',
|
||||||
|
icon: 'none'
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
changeMonth(item, index) {
|
|
||||||
this.currentMonthIndex = index
|
// 获取酒款列表
|
||||||
this.currentMonth = item.beers
|
async getBeerList() {
|
||||||
this.queryForm.num = index
|
try {
|
||||||
this.getNewBeerListByMonthFun()
|
const res = await getBeerList(this.activityInfo.keyword || '')
|
||||||
},
|
if (res.code === 200 && res.data) {
|
||||||
getLastSixMonthFun() {
|
this.beerList = res.data
|
||||||
getLastSixMonth().then(res => {
|
}
|
||||||
console.log(res)
|
} catch (error) {
|
||||||
this.dataList = res.data
|
console.error('获取酒款列表失败:', error)
|
||||||
this.queryForm.num = 0
|
uni.showToast({
|
||||||
this.getNewBeerListByMonthFun()
|
title: '获取酒款列表失败',
|
||||||
|
icon: 'none'
|
||||||
})
|
})
|
||||||
|
}
|
||||||
},
|
},
|
||||||
// 跳转酒款详情
|
|
||||||
|
// 跳转到酒款详情
|
||||||
toBeer(item) {
|
toBeer(item) {
|
||||||
uni.navigateTo({
|
uni.navigateTo({
|
||||||
url: '/pages/index/review?beerId=' + item.id
|
url: '/pages/index/review?beerId=' + item.id
|
||||||
|
@ -1,75 +1,81 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="page flex flex-col">
|
<view class="page">
|
||||||
<!-- 固定搜索框 -->
|
<!-- 搜索框 -->
|
||||||
<view class="fixed-search-bar">
|
<view class="search-box">
|
||||||
<SearchBar :placeholders="'搜索酒款/品牌'" :bgcolor="'#19367A'" :borderRs="'0px 0px 24rpx 24rpx'"/>
|
<view class="search-input">
|
||||||
|
<image src="/static/icons/search.png" class="search-icon" />
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
v-model="searchKey"
|
||||||
|
placeholder="搜索品牌"
|
||||||
|
placeholder-class="placeholder"
|
||||||
|
@input="handleSearch"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 热门厂牌和我的关注 -->
|
<!-- 加载状态 -->
|
||||||
<view class="hot-header" v-if="hotflag">
|
<view v-if="loading" class="loading-state">
|
||||||
<view class="flex align-center hot-center">
|
<view class="loading-skeleton" v-for="i in 5" :key="i">
|
||||||
<view class="" style="margin-left: 24rpx;" @click="hotClick('1')" :class="hotActives=='1'?'hot-actives':''">
|
<view class="skeleton-logo"></view>
|
||||||
<view class="">热门厂牌</view>
|
<view class="skeleton-content">
|
||||||
</view>
|
<view class="skeleton-title"></view>
|
||||||
<view class="" style="color: #E0E0E0;margin-left: 20rpx;">|</view>
|
<view class="skeleton-subtitle"></view>
|
||||||
<view style="margin-left: 24rpx;" @click="hotClick('2')" :class="hotActives=='2'?'hot-actives':''">
|
|
||||||
<view class="">我的关注</view>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 热门厂牌列表 -->
|
<!-- 字母索引列表 -->
|
||||||
<!-- <view class="hot-bom flex align-center justify-between flex-wrap" v-if="hotflag">
|
<view v-else class="index-list">
|
||||||
<view class="" v-for="it in 8" style="width: 25%;text-align: center;">
|
<scroll-view
|
||||||
<view class="">
|
scroll-y
|
||||||
<image src="@/static/fengwei.png" mode="" style="width: 88rpx;height: 88rpx;"></image>
|
class="content"
|
||||||
</view>
|
:scroll-into-view="currentLetter ? 'letter-' + currentLetter : ''"
|
||||||
<view class="" style="font-size: 28rpx;margin: 16rpx 0 12rpx 0;">风味屋</view>
|
|
||||||
</view>
|
|
||||||
</view> -->
|
|
||||||
|
|
||||||
<!-- 联系人列表和索引栏 -->
|
|
||||||
<view class="container" :style="{ height: containerHeight + 'px',}" :class="hotflag?'':'hot-act'">
|
|
||||||
<scroll-view scroll-y :scroll-into-view="scrollIntoView" class="list" @scroll="handleScroll">
|
|
||||||
<view class="hot-bom flex align-center justify-between flex-wrap" v-if="hotflag">
|
|
||||||
<view class="" v-for="it in 8" style="width: 25%;text-align: center;">
|
|
||||||
<view class="">
|
|
||||||
<image src="@/static/bg/fengwei.png" mode="" style="width: 88rpx;height: 88rpx;"></image>
|
|
||||||
</view>
|
|
||||||
<view class="" style="font-size: 28rpx;margin: 16rpx 0 12rpx 0;">风味屋</view>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
<view v-for="(group, letter) in groupedData" :key="letter" :id="letter">
|
|
||||||
|
|
||||||
<view class="group-title">
|
|
||||||
{{ letter }}
|
|
||||||
<!-- 自定义 switch -->
|
|
||||||
<view class="flex align-center" v-if="currentVisibleLetter === letter">
|
|
||||||
<view class="" style="font-size: 24rpx;color: #606060;margin-right: 15rpx;">只看在售</view>
|
|
||||||
<!-- :class="{ 'switch-on': isOnSaleFilter[letter], 'switch-off': !isOnSaleFilter[letter] }"
|
|
||||||
@click="toggleFilter(letter)" -->
|
|
||||||
<view
|
|
||||||
class="custom-switch"
|
|
||||||
:class="{ 'switch-on': isOnSaleFilter, 'switch-off': !isOnSaleFilter }"
|
|
||||||
@click="toggleGlobalFilter"
|
|
||||||
>
|
>
|
||||||
<view class="switch-thumb"></view>
|
<block v-for="(group, letter) in groupedBreweries" :key="letter">
|
||||||
|
<view :id="'letter-' + letter" class="letter-section">
|
||||||
|
<view class="letter-title">{{letter}}</view>
|
||||||
|
<view
|
||||||
|
class="brewery-item hover-effect"
|
||||||
|
v-for="brewery in group"
|
||||||
|
:key="brewery.id"
|
||||||
|
@click="navigateToBrewery(brewery)"
|
||||||
|
>
|
||||||
|
<image
|
||||||
|
:src="brewery.logo || '/static/images/default-logo.png'"
|
||||||
|
class="brewery-logo"
|
||||||
|
mode="aspectFill"
|
||||||
|
:lazy-load="true"
|
||||||
|
/>
|
||||||
|
<view class="brewery-info">
|
||||||
|
<text class="brewery-name text-ellipsis">{{brewery.breweryName}}</text>
|
||||||
|
<text class="beer-count">{{brewery.beerCount || 0}}款在售</text>
|
||||||
|
</view>
|
||||||
|
<image
|
||||||
|
src="/static/icons/arrow-right.png"
|
||||||
|
class="arrow-icon"
|
||||||
|
/>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</block>
|
||||||
<view v-for="(item, index) in group" :key="index" class="contact-item">
|
|
||||||
<view class="">
|
<!-- 空状态 -->
|
||||||
<image src="@/static/logouts.png" style="width:88rpx;height: 88rpx;" mode=""></image>
|
<view v-if="Object.keys(groupedBreweries).length === 0" class="empty-state">
|
||||||
</view>
|
<image src="/static/images/empty.png" class="empty-image" />
|
||||||
<text style="margin-left: 52rpx;font-size: 28rpx;">{{ item.name }}</text>
|
<text class="empty-text">暂无相关品牌</text>
|
||||||
</view>
|
|
||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
<!-- 字母索引栏 -->
|
|
||||||
<view class="index-bar">
|
<!-- 右侧字母导航 -->
|
||||||
<view v-for="letter in indexLetters" :key="letter" @tap="scrollToGroup(letter)"
|
<view class="letter-nav">
|
||||||
:class="{ 'active-letter': activeLetter === letter }">
|
<view
|
||||||
{{ letter }}
|
v-for="letter in letters"
|
||||||
|
:key="letter"
|
||||||
|
class="letter-item"
|
||||||
|
:class="{ active: currentLetter === letter }"
|
||||||
|
@click="scrollToLetter(letter)"
|
||||||
|
>
|
||||||
|
{{letter}}
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -77,268 +83,410 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getLastSixMonth, getNewBeerListByMonth, popularStyle } from "@/api/platform.js";
|
import { getBreweries, getBeerList } from '@/api/bar.js'
|
||||||
import CustomNavBar from '@/components/CustomNavBar.vue';
|
|
||||||
import SearchBar from '@/components/SearchBar.vue';
|
export default {
|
||||||
export default {
|
name: 'HotLabel',
|
||||||
components: {
|
|
||||||
CustomNavBar,
|
|
||||||
SearchBar
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
dataList: [],
|
// 搜索相关
|
||||||
currentMonth: [],
|
searchKey: '',
|
||||||
currentMonthIndex: 0,
|
searchTimer: null,
|
||||||
popularStyleList: [],
|
|
||||||
queryForm: {
|
|
||||||
num: null,
|
|
||||||
},
|
|
||||||
bgcolor: '#19367A',
|
|
||||||
containerHeight: 0, // 动态计算的容器高度
|
|
||||||
rawGroupedData: [
|
|
||||||
{ name: "Alice", phone: "123456789", group: "A", isOnSale: true },
|
|
||||||
{ name: "Alice1", phone: "123456789", group: "A", isOnSale: false },
|
|
||||||
{ name: "Bob", phone: "987654321", group: "B", isOnSale: true },
|
|
||||||
{ name: "Bob1", phone: "987654321", group: "B", isOnSale: false },
|
|
||||||
{ name: "Charlie", phone: "555555555", group: "C", isOnSale: true },
|
|
||||||
{ name: "David", phone: "111111111", group: "D", isOnSale: true },
|
|
||||||
{ name: "Eve", phone: "222222222", group: "E", isOnSale: true },
|
|
||||||
{ name: "Frank", phone: "333333333", group: "F", isOnSale: true },
|
|
||||||
{ name: "Grace", phone: "444444444", group: "G", isOnSale: true },
|
|
||||||
{ name: "Hank", phone: "555555555", group: "H", isOnSale: true },
|
|
||||||
{ name: "Ivy", phone: "666666666", group: "I", isOnSale: true },
|
|
||||||
{ name: "Jack", phone: "777777777", group: "J", isOnSale: true },
|
|
||||||
],
|
|
||||||
scrollIntoView: "", // 当前滚动到的分组
|
|
||||||
isOnSaleFilter: {},
|
|
||||||
originalGroupedData: {},
|
|
||||||
activeLetter: "", // 当前选中的字母
|
|
||||||
hotActives: '1',
|
|
||||||
hotflag:true,
|
|
||||||
currentVisibleLetter: null,
|
|
||||||
isOnSaleFilter: false,
|
|
||||||
|
|
||||||
};
|
// 数据相关
|
||||||
},
|
breweries: [],
|
||||||
computed: {
|
groupedBreweries: {},
|
||||||
// 按字母分组
|
currentLetter: '',
|
||||||
groupedData() {
|
letters: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split(''),
|
||||||
const grouped = this.rawGroupedData.reduce((acc, item) => {
|
|
||||||
const group = item.group;
|
|
||||||
if (!acc[group]) acc[group] = [];
|
|
||||||
acc[group].push(item);
|
|
||||||
return acc;
|
|
||||||
}, {});
|
|
||||||
|
|
||||||
// // 应用过滤条件
|
// 加载状态
|
||||||
// Object.keys(grouped).forEach((letter) => {
|
loading: false
|
||||||
// if (this.isOnSaleFilter[letter]) {
|
|
||||||
// grouped[letter] = grouped[letter].filter((item) => item.isOnSale);
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// 如果全局过滤开关开启,过滤全部数据
|
|
||||||
if (this.isOnSaleFilter) {
|
|
||||||
Object.keys(grouped).forEach((letter) => {
|
|
||||||
grouped[letter] = grouped[letter].filter((item) => item.isOnSale);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return grouped;
|
|
||||||
},
|
|
||||||
// 字母索引
|
|
||||||
indexLetters() {
|
|
||||||
return Object.keys(this.groupedData).sort();
|
|
||||||
},
|
},
|
||||||
|
onShow() {
|
||||||
|
this.initData()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
hotClick(ind) {
|
// 初始化数据
|
||||||
this.hotActives = ind;
|
async initData() {
|
||||||
},
|
try {
|
||||||
toggleGlobalFilter() {
|
uni.showLoading({
|
||||||
this.isOnSaleFilter = !this.isOnSaleFilter;
|
title: '加载中...'
|
||||||
},
|
})
|
||||||
handleScroll(e) {
|
const res = await getBreweries()
|
||||||
const scrollTop = e.detail.scrollTop;
|
console.log('获取品牌列表响应:', res)
|
||||||
if (scrollTop < 2) {
|
|
||||||
this.hotflag = true; // 滚动到顶部时显示热门厂牌内容
|
if (res && res.data) {
|
||||||
|
this.breweries = res.data.map(item => ({
|
||||||
|
id: item.id,
|
||||||
|
breweryName: item.breweryName || '',
|
||||||
|
logo: item.logo || '',
|
||||||
|
beerCount: 0
|
||||||
|
}))
|
||||||
|
|
||||||
|
// 获取每个品牌的酒款数量
|
||||||
|
await this.getBeerCounts()
|
||||||
|
// 按首字母分组
|
||||||
|
this.groupBreweries()
|
||||||
|
} else {
|
||||||
|
throw new Error('获取品牌列表失败')
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('初始化数据失败:', error)
|
||||||
|
uni.showToast({
|
||||||
|
title: '加载失败,请重试',
|
||||||
|
icon: 'none'
|
||||||
|
})
|
||||||
|
} finally {
|
||||||
|
uni.hideLoading()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 获取热门风格
|
|
||||||
// getPopularStyle() {
|
// 获取每个品牌的酒款数量
|
||||||
// popularStyle().then((res) => {
|
async getBeerCounts() {
|
||||||
// console.log(res);
|
const promises = this.breweries.map(async (brewery) => {
|
||||||
// this.popularStyleList = res.data;
|
try {
|
||||||
// });
|
const res = await getBeerList({ breweryId: brewery.id })
|
||||||
// },
|
if (res && res.data) {
|
||||||
// getLastSixMonthFun() {
|
brewery.beerCount = res.data.total || 0
|
||||||
// getLastSixMonth().then((res) => {
|
}
|
||||||
// console.log(res);
|
} catch (error) {
|
||||||
// this.dataList = res.data;
|
console.error(`获取品牌 ${brewery.id} 的酒款数量失败:`, error)
|
||||||
// this.queryForm.num = 0;
|
brewery.beerCount = 0
|
||||||
// this.getNewBeerListByMonthFun();
|
}
|
||||||
// });
|
})
|
||||||
// },
|
|
||||||
// 点击字母滚动到对应分组
|
await Promise.all(promises)
|
||||||
scrollToGroup(letter) {
|
|
||||||
this.scrollIntoView = letter;
|
|
||||||
this.activeLetter = letter;
|
|
||||||
this.hotflag = false
|
|
||||||
this.currentVisibleLetter = letter; // 更新当前显示“只看在售”的字母
|
|
||||||
},
|
},
|
||||||
// 动态计算容器高度
|
|
||||||
calculateContainerHeight() {
|
// 按首字母分组品牌
|
||||||
const systemInfo = uni.getSystemInfoSync();
|
groupBreweries() {
|
||||||
const searchBarHeight = 120; // 搜索框高度
|
const grouped = {}
|
||||||
const hotHeaderHeight = 90; // 热门厂牌和我的关注高度
|
|
||||||
const hotBomHeight = 200; // 热门厂牌列表高度(根据实际内容调整)
|
this.breweries.forEach(brewery => {
|
||||||
this.containerHeight = systemInfo.windowHeight - searchBarHeight - hotHeaderHeight - hotBomHeight;
|
if (!brewery.breweryName) return
|
||||||
|
|
||||||
|
let firstLetter = brewery.breweryName.charAt(0).toUpperCase()
|
||||||
|
if (!/[A-Z]/.test(firstLetter)) {
|
||||||
|
firstLetter = '#'
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!grouped[firstLetter]) {
|
||||||
|
grouped[firstLetter] = []
|
||||||
|
}
|
||||||
|
grouped[firstLetter].push(brewery)
|
||||||
|
})
|
||||||
|
|
||||||
|
Object.keys(grouped).forEach(letter => {
|
||||||
|
grouped[letter].sort((a, b) =>
|
||||||
|
a.breweryName.localeCompare(b.breweryName, 'zh')
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.letters = [...'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('')]
|
||||||
|
if (grouped['#']) {
|
||||||
|
this.letters.push('#')
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('分组后的数据:', grouped)
|
||||||
|
this.groupedBreweries = grouped
|
||||||
},
|
},
|
||||||
// 切换开关状态
|
|
||||||
toggleFilter(letter) {
|
// 搜索处理
|
||||||
this.$set(this.isOnSaleFilter, letter, !this.isOnSaleFilter[letter]);
|
handleSearch() {
|
||||||
|
if (this.searchTimer) {
|
||||||
|
clearTimeout(this.searchTimer)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.searchTimer = setTimeout(() => {
|
||||||
|
const searchKey = this.searchKey.trim().toLowerCase()
|
||||||
|
|
||||||
|
if (!searchKey) {
|
||||||
|
this.groupBreweries()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const filteredBreweries = this.breweries.filter(brewery =>
|
||||||
|
brewery.breweryName.toLowerCase().includes(searchKey)
|
||||||
|
)
|
||||||
|
|
||||||
|
const grouped = {}
|
||||||
|
filteredBreweries.forEach(brewery => {
|
||||||
|
let firstLetter = brewery.breweryName.charAt(0).toUpperCase()
|
||||||
|
if (/[\u4e00-\u9fa5]/.test(firstLetter)) {
|
||||||
|
firstLetter = this.getFirstPinYinLetter(brewery.breweryName)
|
||||||
|
}
|
||||||
|
if (!/[A-Z]/.test(firstLetter)) {
|
||||||
|
firstLetter = '#'
|
||||||
|
}
|
||||||
|
if (!grouped[firstLetter]) {
|
||||||
|
grouped[firstLetter] = []
|
||||||
|
}
|
||||||
|
grouped[firstLetter].push(brewery)
|
||||||
|
})
|
||||||
|
|
||||||
|
this.groupedBreweries = grouped
|
||||||
|
}, 300)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// 滚动到指定字母
|
||||||
|
scrollToLetter(letter) {
|
||||||
|
this.currentLetter = letter
|
||||||
},
|
},
|
||||||
mounted() {
|
|
||||||
// 初始化原始数据副本
|
// 导航到品牌详情
|
||||||
this.originalGroupedData = JSON.parse(JSON.stringify(this.groupedData));
|
navigateToBrewery(brewery) {
|
||||||
this.calculateContainerHeight();
|
uni.navigateTo({
|
||||||
this.currentVisibleLetter = this.indexLetters[0];
|
url: `/pages/activityList/styleSelection?breweryId=${brewery.id}`
|
||||||
|
})
|
||||||
},
|
},
|
||||||
};
|
|
||||||
|
// 获取中文首字母
|
||||||
|
getFirstPinYinLetter(str) {
|
||||||
|
const pinyin = require('pinyin')
|
||||||
|
if (!str) return '#'
|
||||||
|
const firstChar = str.charAt(0)
|
||||||
|
if (!/[\u4e00-\u9fa5]/.test(firstChar)) return firstChar.toUpperCase()
|
||||||
|
const pinyinArr = pinyin(firstChar, {
|
||||||
|
style: pinyin.STYLE_FIRST_LETTER,
|
||||||
|
heteronym: false
|
||||||
|
})
|
||||||
|
return (pinyinArr[0] || ['#'])[0].toUpperCase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style lang="scss" scoped>
|
||||||
.page {
|
.page {
|
||||||
display: flex;
|
min-height: 100vh;
|
||||||
flex-direction: column;
|
background: #FFFFFF;
|
||||||
height: 100vh;
|
padding-top: 120rpx;
|
||||||
font-family: Roboto;
|
|
||||||
}
|
|
||||||
|
|
||||||
.fixed-search-bar {
|
// 搜索框
|
||||||
|
.search-box {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
z-index: 1000;
|
padding: 24rpx;
|
||||||
background-color: #fff; // 根据需要设置背景色
|
|
||||||
}
|
|
||||||
|
|
||||||
.hot-header {
|
|
||||||
margin-top: 120rpx; // 搜索框高度
|
|
||||||
}
|
|
||||||
|
|
||||||
.hot-center {
|
|
||||||
height: 90rpx;
|
|
||||||
color: #606060;
|
|
||||||
font-size: 24rpx;
|
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
}
|
z-index: 100;
|
||||||
|
box-shadow: 0 2rpx 10rpx rgba(0,0,0,0.05);
|
||||||
|
|
||||||
.hot-actives {
|
.search-input {
|
||||||
font-size: 28rpx;
|
|
||||||
font-weight: 600;
|
|
||||||
color: #030303;
|
|
||||||
}
|
|
||||||
|
|
||||||
.hot-bom {
|
|
||||||
padding: 0 24rpx;
|
|
||||||
background: #FFFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
.container {
|
|
||||||
flex: 1;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
|
height: 72rpx;
|
||||||
|
background: #F5F5F5;
|
||||||
|
border-radius: 36rpx;
|
||||||
|
padding: 0 24rpx;
|
||||||
|
|
||||||
.list {
|
.search-icon {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
}
|
||||||
|
|
||||||
.group-title {
|
.placeholder {
|
||||||
padding: 10px;
|
color: #999999;
|
||||||
background-color: #f9f9f9;
|
}
|
||||||
font-weight: bold;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 加载状态
|
||||||
|
.loading-state {
|
||||||
|
padding: 24rpx;
|
||||||
|
|
||||||
|
.loading-skeleton {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
padding: 24rpx;
|
||||||
}
|
margin-bottom: 24rpx;
|
||||||
|
|
||||||
.contact-item {
|
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
padding: 10px;
|
border-radius: 12rpx;
|
||||||
border-bottom: 1px solid #eee;
|
|
||||||
|
.skeleton-logo {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
background: #F5F5F5;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
animation: skeleton-loading 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-content {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.skeleton-title {
|
||||||
|
width: 60%;
|
||||||
|
height: 32rpx;
|
||||||
|
background: #F5F5F5;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
margin-bottom: 12rpx;
|
||||||
|
animation: skeleton-loading 1.5s infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skeleton-subtitle {
|
||||||
|
width: 40%;
|
||||||
|
height: 24rpx;
|
||||||
|
background: #F5F5F5;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
animation: skeleton-loading 1.5s infinite;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 字母索引列表
|
||||||
|
.index-list {
|
||||||
|
display: flex;
|
||||||
|
height: calc(100vh - 120rpx);
|
||||||
|
|
||||||
|
.content {
|
||||||
|
flex: 1;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
.letter-section {
|
||||||
|
.letter-title {
|
||||||
|
padding: 16rpx 24rpx;
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
background: #F9F9F9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.brewery-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
padding: 24rpx;
|
||||||
|
margin: 0 24rpx;
|
||||||
|
border-bottom: 2rpx solid #F5F5F5;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
.index-bar {
|
&:active {
|
||||||
width: 20px;
|
background: #F9F9F9;
|
||||||
|
transform: scale(0.98);
|
||||||
|
}
|
||||||
|
|
||||||
|
.brewery-logo {
|
||||||
|
width: 80rpx;
|
||||||
|
height: 80rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
|
margin-right: 24rpx;
|
||||||
|
background: #F5F5F5;
|
||||||
|
box-shadow: 0 4rpx 8rpx rgba(0,0,0,0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
.brewery-info {
|
||||||
|
flex: 1;
|
||||||
|
|
||||||
|
.brewery-name {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #333333;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beer-count {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.arrow-icon {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.empty-state {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
padding: 96rpx 0;
|
||||||
background-color: #f8f8f8;
|
|
||||||
}
|
|
||||||
|
|
||||||
.index-bar view {
|
.empty-image {
|
||||||
padding: 2px 0;
|
width: 240rpx;
|
||||||
font-size: 12px;
|
height: 240rpx;
|
||||||
cursor: pointer;
|
margin-bottom: 32rpx;
|
||||||
border-radius: 50%; /* 圆形背景 */
|
}
|
||||||
width: 20px;
|
|
||||||
height: 20px;
|
.empty-text {
|
||||||
|
font-size: 28rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 右侧字母导航
|
||||||
|
.letter-nav {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 24rpx 12rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
|
||||||
|
.letter-item {
|
||||||
|
width: 32rpx;
|
||||||
|
height: 32rpx;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
transition: background-color 0.3s;
|
font-size: 24rpx;
|
||||||
|
color: #666666;
|
||||||
|
margin: 4rpx 0;
|
||||||
|
border-radius: 50%;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
color: #FFFFFF;
|
||||||
|
background: #D42E78;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.index-bar view.active-letter {
|
@keyframes skeleton-loading {
|
||||||
background-color: #D42E78; /* 选中字母的背景色 */
|
0% {
|
||||||
color: white; /* 选中字母的文字颜色 */
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
50% {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 自定义 switch 样式 */
|
// 添加按键反馈效果
|
||||||
.custom-switch {
|
.hover-effect {
|
||||||
width: 50rpx;
|
transition: all 0.2s ease;
|
||||||
height: 28rpx;
|
|
||||||
border-radius: 14rpx;
|
&:active {
|
||||||
position: relative;
|
transform: scale(0.96);
|
||||||
cursor: pointer;
|
opacity: 0.8;
|
||||||
transition: background-color 0.3s;
|
}
|
||||||
-webkit-tap-highlight-color: transparent; /* 移除点击高亮 */
|
|
||||||
user-select: none; /* 禁止文本选择 */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.switch-on {
|
// 文本省略
|
||||||
background-color: #D42E78; /* 开启状态颜色(蓝色) */
|
.text-ellipsis {
|
||||||
}
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
.switch-off {
|
white-space: nowrap;
|
||||||
background-color: #e5e5e5; /* 关闭状态颜色 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-thumb {
|
|
||||||
width: 24rpx;
|
|
||||||
height: 24rpx;
|
|
||||||
background-color: white;
|
|
||||||
border-radius: 12rpx;
|
|
||||||
position: absolute;
|
|
||||||
top: 2rpx;
|
|
||||||
transition: left 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-on .switch-thumb {
|
|
||||||
left: 24rpx; /* 开启状态滑块位置 */
|
|
||||||
}
|
|
||||||
|
|
||||||
.switch-off .switch-thumb {
|
|
||||||
left: 2rpx; /* 关闭状态滑块位置 */
|
|
||||||
}
|
|
||||||
.hot-act{
|
|
||||||
padding-top: 120rpx;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -1,24 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<view class="page">
|
<view class="page">
|
||||||
<!-- 筛选导航 -->
|
<!-- 筛选导航 -->
|
||||||
<view class="filter-section">
|
|
||||||
<view class="filter-tabs">
|
|
||||||
<view
|
|
||||||
v-for="(tab, index) in dropdownMenuList"
|
|
||||||
:key="tab.prop"
|
|
||||||
class="tab-item"
|
|
||||||
:class="{ active: activeTab === tab.prop }"
|
|
||||||
@click="$refs.filterDropdown.toggleMenu(index)"
|
|
||||||
>
|
|
||||||
<text class="tab-text">{{ tab.title }}</text>
|
|
||||||
<image
|
|
||||||
class="tab-icon"
|
|
||||||
:class="{ up: activeTab === tab.prop }"
|
|
||||||
:src="activeTab === tab.prop ? '/static/icons/arrow-active.png' : '/static/icons/arrow.png'"
|
|
||||||
/>
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
|
|
||||||
<Sieving
|
<Sieving
|
||||||
ref="filterDropdown"
|
ref="filterDropdown"
|
||||||
:dropdownMenu="dropdownMenuList"
|
:dropdownMenu="dropdownMenuList"
|
||||||
@ -27,7 +9,6 @@
|
|||||||
@close="handleFilterClose"
|
@close="handleFilterClose"
|
||||||
@open="handleFilterOpen"
|
@open="handleFilterOpen"
|
||||||
/>
|
/>
|
||||||
</view>
|
|
||||||
|
|
||||||
<!-- 统计信息 -->
|
<!-- 统计信息 -->
|
||||||
<view class="stats-bar">
|
<view class="stats-bar">
|
||||||
@ -45,7 +26,7 @@
|
|||||||
@refresherrefresh="onRefresh"
|
@refresherrefresh="onRefresh"
|
||||||
>
|
>
|
||||||
<view
|
<view
|
||||||
class="beer-card"
|
class="beer-card hover-effect"
|
||||||
v-for="beer in beerList"
|
v-for="beer in beerList"
|
||||||
:key="beer.id"
|
:key="beer.id"
|
||||||
@click="navigateToBeerDetail(beer)"
|
@click="navigateToBeerDetail(beer)"
|
||||||
@ -54,7 +35,8 @@
|
|||||||
<image
|
<image
|
||||||
:src="beer.cover"
|
:src="beer.cover"
|
||||||
class="beer-image"
|
class="beer-image"
|
||||||
mode="aspectFit"
|
mode="aspectFill"
|
||||||
|
:lazy-load="true"
|
||||||
/>
|
/>
|
||||||
<view class="beer-details">
|
<view class="beer-details">
|
||||||
<text class="beer-name text-ellipsis">{{beer.beerName}}</text>
|
<text class="beer-name text-ellipsis">{{beer.beerName}}</text>
|
||||||
@ -85,36 +67,6 @@
|
|||||||
</view>
|
</view>
|
||||||
</scroll-view>
|
</scroll-view>
|
||||||
</view>
|
</view>
|
||||||
|
|
||||||
<!-- 风格筛选弹窗 -->
|
|
||||||
<uni-popup
|
|
||||||
ref="stylePopup"
|
|
||||||
type="right"
|
|
||||||
background-color="#fff"
|
|
||||||
>
|
|
||||||
<view class="style-popup">
|
|
||||||
<scroll-view
|
|
||||||
scroll-y
|
|
||||||
class="style-list"
|
|
||||||
>
|
|
||||||
<view
|
|
||||||
v-for="style in popularStyleList"
|
|
||||||
:key="style.id"
|
|
||||||
class="style-item"
|
|
||||||
:class="{'active': selectedStyle === style.beerStyles}"
|
|
||||||
@click="selectStyle(style)"
|
|
||||||
>
|
|
||||||
<text class="style-name">{{ style.beerStyles }}</text>
|
|
||||||
</view>
|
|
||||||
</scroll-view>
|
|
||||||
<view
|
|
||||||
class="clear-button"
|
|
||||||
@click="clearFilter"
|
|
||||||
>
|
|
||||||
清除筛选
|
|
||||||
</view>
|
|
||||||
</view>
|
|
||||||
</uni-popup>
|
|
||||||
</view>
|
</view>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -125,14 +77,13 @@
|
|||||||
popularStyle,
|
popularStyle,
|
||||||
getBrands,
|
getBrands,
|
||||||
getBeerStyles,
|
getBeerStyles,
|
||||||
|
getBeerByStyle
|
||||||
} from "@/api/platform.js"
|
} from "@/api/platform.js"
|
||||||
import CustomNavBar from '@/components/CustomNavBar.vue'
|
|
||||||
import Sieving from '@/components/sieving/index.vue'
|
import Sieving from '@/components/sieving/index.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'StyleSelection',
|
name: 'StyleSelection',
|
||||||
components: {
|
components: {
|
||||||
CustomNavBar,
|
|
||||||
Sieving
|
Sieving
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -145,15 +96,13 @@
|
|||||||
hasMore: true,
|
hasMore: true,
|
||||||
|
|
||||||
// 筛选相关
|
// 筛选相关
|
||||||
selectedStyle: '',
|
activeTab: '',
|
||||||
popularStyleList: [],
|
|
||||||
|
|
||||||
// 查询参数
|
// 查询参数
|
||||||
queryParams: {
|
queryParams: {
|
||||||
pageNum: 1,
|
pageNum: 1,
|
||||||
pageSize: 10,
|
pageSize: 10,
|
||||||
sortType: 'latest',
|
styleId: ''
|
||||||
style: ''
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 筛选配置
|
// 筛选配置
|
||||||
@ -212,9 +161,10 @@
|
|||||||
async initData() {
|
async initData() {
|
||||||
try {
|
try {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
this.getPopularStyles(),
|
this.getBrandOptions(),
|
||||||
this.getBeerList()
|
this.getStyleOptions()
|
||||||
])
|
])
|
||||||
|
await this.getBeerList()
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('初始化数据失败:', error)
|
console.error('初始化数据失败:', error)
|
||||||
uni.showToast({
|
uni.showToast({
|
||||||
@ -224,13 +174,31 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// 获取热门风格
|
// 获取品牌选项
|
||||||
async getPopularStyles() {
|
async getBrandOptions() {
|
||||||
try {
|
try {
|
||||||
const res = await popularStyle()
|
const res = await getBrands()
|
||||||
this.popularStyleList = res.data || []
|
const brands = res.data || []
|
||||||
|
this.dropdownMenuList[0].options = brands.map(brand => ({
|
||||||
|
label: brand.brandName,
|
||||||
|
value: brand.id
|
||||||
|
}))
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('获取热门风格失败:', error)
|
console.error('获取品牌列表失败:', error)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 获取风格选项
|
||||||
|
async getStyleOptions() {
|
||||||
|
try {
|
||||||
|
const res = await getBeerStyles()
|
||||||
|
const styles = res.data || []
|
||||||
|
this.dropdownMenuList[1].options = styles.map(style => ({
|
||||||
|
label: style.beerStyles,
|
||||||
|
value: style.id
|
||||||
|
}))
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取风格列表失败:', error)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -245,7 +213,7 @@
|
|||||||
this.beerList = []
|
this.beerList = []
|
||||||
}
|
}
|
||||||
|
|
||||||
const res = await getNewBeerListByMonth(this.queryParams)
|
const res = await getBeerByStyle(this.queryParams)
|
||||||
const newList = res.data || []
|
const newList = res.data || []
|
||||||
|
|
||||||
this.beerList = isRefresh ?
|
this.beerList = isRefresh ?
|
||||||
@ -278,39 +246,15 @@
|
|||||||
sortType: sort
|
sortType: sort
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sort === 'comprehensive') {
|
|
||||||
this.queryParams.weights = {
|
|
||||||
popular: 0.5,
|
|
||||||
rating: 0.3,
|
|
||||||
latest: 0.2
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
delete this.queryParams.weights
|
|
||||||
}
|
|
||||||
|
|
||||||
this.getBeerList(true)
|
this.getBeerList(true)
|
||||||
},
|
},
|
||||||
|
|
||||||
handleFilterOpen(tabName) {
|
handleFilterOpen(tabName) {
|
||||||
this.queryParams.style = tabName
|
this.activeTab = tabName
|
||||||
},
|
},
|
||||||
|
|
||||||
handleFilterClose() {
|
handleFilterClose() {
|
||||||
this.queryParams.style = ''
|
this.activeTab = ''
|
||||||
},
|
|
||||||
|
|
||||||
selectStyle(style) {
|
|
||||||
this.selectedStyle = style.beerStyles
|
|
||||||
this.queryParams.style = style.beerStyles
|
|
||||||
this.getBeerList(true)
|
|
||||||
this.$refs.stylePopup.close()
|
|
||||||
},
|
|
||||||
|
|
||||||
clearFilter() {
|
|
||||||
this.selectedStyle = ''
|
|
||||||
this.queryParams.style = ''
|
|
||||||
this.getBeerList(true)
|
|
||||||
this.$refs.stylePopup.close()
|
|
||||||
},
|
},
|
||||||
|
|
||||||
// 列表相关方法
|
// 列表相关方法
|
||||||
@ -336,73 +280,37 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.page {
|
.page {
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
background: #F2F2F2;
|
background: #F9F9F9;
|
||||||
|
|
||||||
.filter-section {
|
|
||||||
background: #FFFFFF;
|
|
||||||
border-bottom: 1rpx solid #F5F5F5;
|
|
||||||
|
|
||||||
.filter-tabs {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
height: 64rpx;
|
|
||||||
padding: 0 32rpx;
|
|
||||||
|
|
||||||
.tab-item {
|
|
||||||
width: 122rpx;
|
|
||||||
height: 64rpx;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
font-size: 28rpx;
|
|
||||||
color: #606060;
|
|
||||||
position: relative;
|
|
||||||
margin-right: 24rpx;
|
|
||||||
|
|
||||||
.tab-text {
|
|
||||||
margin-right: 8rpx;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tab-icon {
|
|
||||||
width: 24rpx;
|
|
||||||
height: 24rpx;
|
|
||||||
transition: transform 0.3s;
|
|
||||||
|
|
||||||
&.up {
|
|
||||||
transform: rotate(180deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: #D42E78;
|
|
||||||
|
|
||||||
.tab-icon {
|
|
||||||
filter: invert(36%) sepia(75%) saturate(1217%)
|
|
||||||
hue-rotate(308deg) brightness(87%) contrast(98%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 统计信息
|
||||||
.stats-bar {
|
.stats-bar {
|
||||||
padding: 20rpx 32rpx;
|
padding: 16rpx 24rpx;
|
||||||
|
background: #FFFFFF;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
.stats-text {
|
.stats-text {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #606060;
|
color: #999999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 内容区域
|
||||||
.content-container {
|
.content-container {
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
.beer-list {
|
.beer-list {
|
||||||
padding: 0 32rpx;
|
height: calc(100vh - 180rpx);
|
||||||
|
padding: 0 24rpx;
|
||||||
|
|
||||||
.beer-card {
|
.beer-card {
|
||||||
background: #FFFFFF;
|
background: #FFFFFF;
|
||||||
|
border-radius: 16rpx;
|
||||||
margin-bottom: 24rpx;
|
margin-bottom: 24rpx;
|
||||||
|
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||||
|
|
||||||
.beer-info {
|
.beer-info {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -410,10 +318,11 @@
|
|||||||
padding: 24rpx;
|
padding: 24rpx;
|
||||||
|
|
||||||
.beer-image {
|
.beer-image {
|
||||||
width: 144rpx;
|
width: 120rpx;
|
||||||
height: 204rpx;
|
height: 120rpx;
|
||||||
|
border-radius: 12rpx;
|
||||||
margin-right: 24rpx;
|
margin-right: 24rpx;
|
||||||
background: #F8F8F8;
|
object-fit: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beer-details {
|
.beer-details {
|
||||||
@ -421,67 +330,117 @@
|
|||||||
|
|
||||||
.beer-name {
|
.beer-name {
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #1E2019;
|
font-weight: 600;
|
||||||
margin-bottom: 16rpx;
|
color: #333333;
|
||||||
|
margin-bottom: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.beer-style {
|
.beer-style {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: rgba(30, 32, 25, 0.7);
|
color: #666666;
|
||||||
margin-bottom: 12rpx;
|
margin-bottom: 8rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
.brand-name {
|
.brand-name {
|
||||||
font-size: 24rpx;
|
font-size: 24rpx;
|
||||||
color: #606060;
|
color: #999999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.arrow-icon {
|
.arrow-icon {
|
||||||
width: 32rpx;
|
width: 32rpx;
|
||||||
height: 32rpx;
|
height: 32rpx;
|
||||||
opacity: 0.4;
|
margin-left: 16rpx;
|
||||||
}
|
opacity: 0.3;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.style-popup {
|
.empty-state {
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 96rpx 0;
|
||||||
|
|
||||||
.style-list {
|
.empty-image {
|
||||||
flex: 1;
|
width: 240rpx;
|
||||||
padding: 32rpx;
|
height: 240rpx;
|
||||||
|
margin-bottom: 32rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.style-item {
|
.empty-text {
|
||||||
padding: 24rpx 0;
|
|
||||||
font-size: 28rpx;
|
font-size: 28rpx;
|
||||||
color: #333333;
|
color: #999999;
|
||||||
|
|
||||||
&.active {
|
|
||||||
color: #19367A;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.clear-button {
|
.loading-status {
|
||||||
height: 88rpx;
|
padding: 32rpx 0;
|
||||||
line-height: 88rpx;
|
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 28rpx;
|
|
||||||
color: #606060;
|
.loading-wrapper {
|
||||||
border-top: 1rpx solid #F5F5F5;
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.loading-icon {
|
||||||
|
width: 40rpx;
|
||||||
|
height: 40rpx;
|
||||||
|
margin-right: 16rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-ellipsis {
|
.no-more {
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: #999999;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加按键反馈效果
|
||||||
|
.hover-effect {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.96);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加图片加载优化相关样式
|
||||||
|
.beer-image {
|
||||||
|
will-change: transform;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加骨架屏样式
|
||||||
|
.skeleton {
|
||||||
|
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 37%, #f2f2f2 63%);
|
||||||
|
background-size: 400% 100%;
|
||||||
|
animation: skeleton-loading 1.4s ease infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes skeleton-loading {
|
||||||
|
0% {
|
||||||
|
background-position: 100% 50%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 文本省略
|
||||||
|
.text-ellipsis {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
@ -6,12 +6,12 @@
|
|||||||
</view>
|
</view>
|
||||||
</view> -->
|
</view> -->
|
||||||
<view v-if="showJoinImg && bannerJoin" class="join-box" @click="toJoin">
|
<view v-if="showJoinImg && bannerJoin" class="join-box" @click="toJoin">
|
||||||
<image :src="bannerJoin.bannerUrl" class="img"></image>
|
<image :src="bannerJoin.bannerUrl" class="img" mode="aspectFill" :lazy-load="true"></image>
|
||||||
</view>
|
</view>
|
||||||
<!-- 轮播 -->
|
<!-- 轮播 -->
|
||||||
<swiper v-else class="join-box" circular :autoplay="true" :indicator-dots="true">
|
<swiper v-else class="join-box" circular :autoplay="true" :indicator-dots="true">
|
||||||
<swiper-item v-for="(item,index) in homeBanner" :key="index">
|
<swiper-item v-for="(item,index) in homeBanner" :key="index">
|
||||||
<image :src="item.bannerUrl" class="img"></image>
|
<image :src="item.bannerUrl" class="img" mode="aspectFill" :lazy-load="true"></image>
|
||||||
</swiper-item>
|
</swiper-item>
|
||||||
|
|
||||||
</swiper>
|
</swiper>
|
||||||
@ -19,7 +19,7 @@
|
|||||||
<!-- 快捷导航 -->
|
<!-- 快捷导航 -->
|
||||||
<view class="bg-white"
|
<view class="bg-white"
|
||||||
style="border-radius: 30rpx 30rpx 12rpx 12rpx;padding-top:8rpx;position: relative;margin-top:-20rpx">
|
style="border-radius: 30rpx 30rpx 12rpx 12rpx;padding-top:8rpx;position: relative;margin-top:-20rpx">
|
||||||
<view class="search-box" @click="toSearch">
|
<view class="search-box hover-effect" @click="toSearch">
|
||||||
<view class="search-input">
|
<view class="search-input">
|
||||||
<text class="cuIcon-search" style="font-size: 40rpx;color: #A2A2A2;margin-right: 24rpx;"></text>
|
<text class="cuIcon-search" style="font-size: 40rpx;color: #A2A2A2;margin-right: 24rpx;"></text>
|
||||||
<text style="color: #A2A2A2;">搜索酒款名称,品牌名称,啤酒风格</text>
|
<text style="color: #A2A2A2;">搜索酒款名称,品牌名称,啤酒风格</text>
|
||||||
@ -29,29 +29,11 @@
|
|||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex justify-between bg-white" style="padding: 20rpx 36rpx;">
|
<view class="flex justify-between bg-white" style="padding: 20rpx 36rpx;">
|
||||||
<view class="nav-item" @click="toGo(1)">
|
<view class="nav-item hover-effect" v-for="(item, index) in navItems" :key="index" @click="toGo(index + 1)">
|
||||||
<view class="flex justify-center align-center img-box">
|
<view class="flex justify-center align-center img-box">
|
||||||
<image src="/static/nav-1.png" style="width: 48rpx;height: 48rpx;"></image>
|
<image :src="'/static/nav-' + (index + 1) + '.png'" style="width: 48rpx;height: 48rpx;" :lazy-load="true"></image>
|
||||||
</view>
|
</view>
|
||||||
<text class="text-bold">新酒上市</text>
|
<text class="text-bold">{{item}}</text>
|
||||||
</view>
|
|
||||||
<view class="nav-item" @click="toGo(2)">
|
|
||||||
<view class="flex justify-center align-center img-box">
|
|
||||||
<image src="/static/nav-2.png" style="width: 48rpx;height: 48rpx;"></image>
|
|
||||||
</view>
|
|
||||||
<text class="text-bold">生成酒单</text>
|
|
||||||
</view>
|
|
||||||
<view class="nav-item" @click="toGo(3)">
|
|
||||||
<view class="flex justify-center align-center img-box">
|
|
||||||
<image src="/static/nav-3.png" style="width: 48rpx;height: 48rpx;"></image>
|
|
||||||
</view>
|
|
||||||
<text class="text-bold">酒币换购</text>
|
|
||||||
</view>
|
|
||||||
<view class="nav-item" @click="toGo(4)">
|
|
||||||
<view class="flex justify-center align-center img-box">
|
|
||||||
<image src="/static/nav-4.png" style="width: 48rpx;height: 48rpx;"></image>
|
|
||||||
</view>
|
|
||||||
<text class="text-bold">关注厂牌</text>
|
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
@ -143,6 +125,7 @@
|
|||||||
total: 0,
|
total: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
finished: false,
|
finished: false,
|
||||||
|
navItems: ['新酒上市', '生成酒单', '酒币换购', '关注厂牌'],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
@ -643,4 +626,70 @@
|
|||||||
.activity-item {
|
.activity-item {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.hover-effect {
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.96);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.search-box {
|
||||||
|
// ... existing code ...
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-item {
|
||||||
|
// ... existing code ...
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.95);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.more-btn-box {
|
||||||
|
// ... existing code ...
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.activity-item {
|
||||||
|
// ... existing code ...
|
||||||
|
&:active {
|
||||||
|
transform: scale(0.98);
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加图片加载优化相关样式
|
||||||
|
.img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
will-change: transform;
|
||||||
|
backface-visibility: hidden;
|
||||||
|
transform: translateZ(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 添加骨架屏样式
|
||||||
|
.skeleton {
|
||||||
|
background: linear-gradient(90deg, #f2f2f2 25%, #e6e6e6 37%, #f2f2f2 63%);
|
||||||
|
background-size: 400% 100%;
|
||||||
|
animation: skeleton-loading 1.4s ease infinite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes skeleton-loading {
|
||||||
|
0% {
|
||||||
|
background-position: 100% 50%;
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
background-position: 0 50%;
|
||||||
|
}
|
||||||
|
}
|
||||||
</style>
|
</style>
|
Loading…
x
Reference in New Issue
Block a user