You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1614 lines
37 KiB

<template>
<!-- 拼团页 -->
<view class="page1">
<view class="title">
<view class="title-sreach">
<view class="back-btn" @tap="back" :style="{'padding-top': menuButtonInfo.top +'px'}">
<uni-icons type="left" size="28"></uni-icons>
</view>
<view class="title-name" :style="{'padding-top': menuButtonInfo.top +'px'}">
饭团
<text>宿舍拼饭局</text>
</view>
<view class="title-search" :style="{'margin-top': menuButtonInfo.top +'px'}" @tap="goDetail('search')">
<uni-icons type="search" size="16" color="#08735d"></uni-icons>
<swiper class="search-word-swiper" vertical circular :autoplay="true" :interval="2200" :duration="500">
<swiper-item v-for="(word,index) in searchHotWords" :key="index">
<view class="search-hot-word">{{word}}</view>
</swiper-item>
</swiper>
<view class="search-trend">热搜↑</view>
</view>
</view>
<view class="title-tab">
<view class="campus-banner" @tap="goDetail('search')">
<view class="banner-glow"></view>
<view class="steam steam-one"></view>
<view class="steam steam-two"></view>
<view class="steam steam-three"></view>
<!-- <view class="food-float float-one">🍜</view>
<view class="food-float float-two">🥤</view>
<view class="food-float float-three">🍢</view>
<view class="food-float float-four">🥟</view> -->
<view class="banner-copy">
<view class="banner-sticker">宿舍正在拼</view>
<view class="banner-title">今天谁还没吃?</view>
<!-- <view class="banner-desc">楼下热乎的那口,凑个饭搭子就出发。</view> -->
<view class="banner-bubbles">
<text>拼团局开了</text>
<text>刚刚有人拼成功</text>
</view>
</view>
<view class="banner-food-card">
<img src="/static/images/img/loading.gif" alt="" />
<!-- <view class="food-card-tag">刚刚有人拼成功</view> -->
</view>
</view>
</view>
<view class="campus-live">
<!-- <view class="live-title">
<text v-for="(text,index) in liveSlogans" :key="index">{{text}}</text>
</view> -->
<scroll-view class="live-scroll" scroll-x enhanced :show-scrollbar="false">
<view class="live-bubble" v-for="(item,index) in liveFeeds" :key="index">
<view class="live-avatar">{{item.avatar}}</view>
<view class="live-copy">
<view class="live-main">{{item.name}} · {{item.dorm}}</view>
<view class="live-sub">{{item.food}}</view>
</view>
</view>
</scroll-view>
</view>
<view class="interest-card" :class="{'interest-card-expanded': categoryExpanded}">
<view class="section-head">
<text>校园美食兴趣入口</text>
<text @tap.stop="toggleCategory">{{categoryExpanded ? '收起' : '展开更多'}}</text>
</view>
<view class="menu-box">
<view class="menu-list" v-for="(item,index) in menuBtn" :key="index" @tap="goDetail('search',item)">
<view class="menu-icon-wrap">
<img :src="item.url" alt="" />
<text class="menu-sticker">{{item.sticker}}</text>
</view>
<view class="menu-name">{{item.displayName || item.name}}</view>
</view>
</view>
<view class="menu-box menu-box-second" v-if="categoryExpanded">
<view class="menu-list" v-for="(item,index) in menuBtn1" :key="index" @tap="goDetail('search',item)">
<view class="menu-icon-wrap">
<img :src="item.url" alt="" />
<text class="menu-sticker">{{item.sticker}}</text>
</view>
<view class="menu-name">{{item.displayName || item.name}}</view>
</view>
</view>
</view>
<view class="title-sort">
<view class="sort-member">
<view class="sort-text" @tap="searchShop('all','')">
综合排序 <text style="font-size: 20rpx;">▼</text>
</view>
</view>
<view class="sort-member">
<view class="sort-text" @tap="searchShop('sale','')">
拼单最多 <text style="font-size: 20rpx;">▼</text>
</view>
</view>
<view class="sort-member">
<view class="sort-text" @tap="searchShop('score','')">
同学最爱 <text style="font-size: 20rpx;">▼</text>
</view>
</view>
<view class="sort-member" style="position: relative;">
<view class="sort-text" @tap="checkArea">
宿舍附近 <text style="font-size: 20rpx;">▼</text>
</view>
<view class="sort-value" v-if="isArea">
<view class="sort-value1" v-for="(item,index) in shopArea" :key="index"
@tap="searchShop('area',item.id)">{{item.title}}</view>
</view>
</view>
</view>
</view>
<view class="shop-list">
<view class="shop-member" v-for="(item,index) in shopList" :key="index" @tap="goDetail('shop',item)">
<view @tap.stop="buyingye" v-if="item.status != 1"
style="width: 100%;height:100%;position: absolute;top: 0;background: rgba(0, 0, 0, 0.1);z-index: 999;border-radius: 20rpx;">
</view>
<view class="shop-card-bg"></view>
<view class="shop-top">
<view class="shop-img">
<img :src="item.shopIcon" lazy-load alt="">
<view class="shop-steam shop-steam-one"></view>
<view class="shop-steam shop-steam-two"></view>
<view class="shop-img-badge">拼团进行中</view>
</view>
<view class="shop-content">
<view class="shop-live-row">
<text>{{getDormStatus(index)}}</text>
<text>速速加入</text>
</view>
<view class="shop-name">
{{item.shopName}}
</view>
<view class="shop-content-center">
<view class="shop-rate">
<view class="avatar-stack">
<text>{{getLiveAvatar(index)}}</text>
<text>{{getLiveAvatar(index + 1)}}</text>
<text>{{getLiveAvatar(index + 2)}}</text>
</view>
<view class="shop-rate-text">附近同学正在拼</view>
</view>
<view class="shop-tag">
<text>
{{item.shopTypeTitle == undefined ? '美食' : item.shopTypeTitle}}
</text>
</view>
</view>
<view class="shop-content-bottom">
<view class="shop-deal">
<text v-if="item.subtitle != null">
{{item.subtitle}}
</text>
<text v-else>{{getGroupTip(index)}}</text>
</view>
<view class="shop-deal1">
<text>{{item.saleCount != null ? item.saleCount : 0}}</text>人跟拼
</view>
</view>
</view>
</view>
<view class="shop-bottom" v-if="item.products != null && item.products.length > 0">
<view class="menu-member" v-if='item1.isPush == 1 && item1.delFlag == 1'
v-for="(item1,index1) in item.products" :key="index1" @tap="goDetail('shop',item)">
<view class="menu-img">
<img :src="item1.productPicture" lazy-load alt="">
<view class="menu-img-gloss"></view>
</view>
<view class="menu-content">
<view class="shop-menu-name">
{{item1.productName}}
</view>
<view class="shop-menu-price">
¥{{item1.attributeListPrice | sliceMsg}}
</view>
<view class="shop-menu-purchase">
<text class="group-badge">拼</text>
<text class="group-price">¥{{item1.productGroupBuyPrices | slicePrice}}</text>
</view>
</view>
</view>
</view>
</view>
</view>
<view class="zaixian">
<image class="zaixian-gif" src="/static/images/img/loading.gif" mode="aspectFit"></image>
<view class="zaixian-divider"></view>
<swiper class="zaixian-swiper" vertical circular :autoplay="onlineWorkerAreaList.length > 1"
:interval="onlineWorkerInterval" :duration="onlineWorkerDuration">
<swiper-item v-if="onlineWorkerAreaList.length === 0">
<view class="zaixian-item">宿舍群正在等一个饭搭子</view>
</swiper-item>
<swiper-item v-for="(item,index) in onlineWorkerAreaList" :key="index">
<view class="zaixian-item">{{item.areaName}} 附近 {{item.onlineWorkerCount}} 位同学在线接单</view>
</swiper-item>
</swiper>
</view>
<view style="width: 100%;height: 120rpx;"></view>
<common-loading />
</view>
</template>
<script>
export default {
data() {
return {
loadStatus: 'more',
isArea: false,
indicatorDots: false,
autoplay: true,
interval: 4000,
duration: 1000,
searchScore: false,
searchSale: false,
categoryExpanded: false,
shopArea: [],
totalPages: 1,
searchForm: {
regionId: JSON.parse(uni.getStorageSync('area')).id,
merchantType: 1,
shopType: '',
shopArea: '',
pageNumber: 1,
keyWord: '',
pageSize: '10',
sort: "shoprank",
order: "desc",
sortOrder: 'shoprank',
orderOrder: 'desc',
sortScore: '',
orderScore: '',
sortSale: '',
orderSale: ''
},
shopList: [],
searchHotWords: ['🍜 今晚吃啥', '🥤 奶茶续命拼团', '🔥 还差1人', '🍱 宿舍套餐热拼'],
liveSlogans: ['谁在偷吃夜宵', '差个饭搭子', '隔壁宿舍已开拼'],
liveFeeds: [{
avatar: '🍜',
name: '晚八点定律',
dorm: '宿舍楼下',
food: '麻辣烫一出现就想下楼'
}, {
avatar: '🥤',
name: '奶茶续命',
dorm: '自习室门口',
food: '写作业前先喝一口甜的'
}, {
avatar: '🍢',
name: '宵夜雷达',
dorm: '操场边',
food: '风一吹就闻到烧烤味'
}, {
avatar: '🥟',
name: '热乎党',
dorm: '回寝路上',
food: '今晚适合来点汤汤水水'
}],
groupTags: ['附近宿舍正在拼', '刚刚有人拼成功', '夜宵爆单中', '饭搭子已上线'],
groupAvatars: ['🍜', '🥤', '🍢', '🍔', '🥟', '🍗'],
menuBtn: [{
name: '美食',
displayName: '今晚吃啥',
sticker: '热',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/d6b53eb217644e74bbf957ff7462c27b.png',
index: 1
}, {
name: '甜点饮品',
displayName: '奶茶续命',
sticker: '甜',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/b43aea98962b402f900eca84b2c171ae.png',
index: 2
}, {
name: '超市便利',
displayName: '宿舍囤货',
sticker: '囤',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/e082a4c10b9a47f0bdb588fb91bc9afb.png',
index: 3
}, {
name: '蔬菜水果',
displayName: '清爽一口',
sticker: '鲜',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/e6adc80518c24c488522ab19f036af27.png',
index: 4
}, {
name: '同学小店',
displayName: '同学店铺',
sticker: '校',
isStudentOnly: true,
value: '',
url: '/static/images/img/songshu.png',
index: 5
}],
menuBtn1: [{
name: '米粉面馆',
displayName: '嗦粉面馆',
sticker: '香',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/8d2f7ffb67a4477ebe663f562b3bd018.png',
index: 6
}, {
name: '早点',
displayName: '宿舍早餐',
sticker: '早',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/5e4fa14df92942eeb62254c8eb82f122.png',
index: 7
}, {
name: '快餐',
displayName: '干饭套餐',
sticker: '饱',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/05d2286ac1be4ae784858409889690d5.png',
index: 8
}, {
name: '麻辣烫冒菜',
displayName: '夜宵局',
sticker: '辣',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/0ac5e0095a5d4097b338ec450df8d3dd.png',
index: 9
}, {
name: '汉堡披萨',
displayName: '快乐碳水',
sticker: '炸',
value: '',
url: 'https://jewel-shop.oss-cn-beijing.aliyuncs.com/14b93d4bce134b3db4b42b13b6993e6c.png',
index: 10
}],
menuButtonInfo: {},
onlineWorkerTotal: 0,
onlineWorkerAreaList: [],
onlineWorkerInterval: 2500,
onlineWorkerDuration: 500
}
},
components: {
},
filters: {
sliceMsg(val) {
var name = ''
if (typeof(val) == 'string') {
let newObj = JSON.parse(val)
for (let as in newObj) {
name = newObj[as].specPrice
}
}
return name;
},
slicePrice(val) {
let begin = ''
if (val != null) {
begin = val[0].groupPrice
for (let i = 0; i < val.length; i++) {
if (val[i].groupPrice < begin) {
begin = val[i].groupPrice
}
}
}
return begin;
}
},
onReachBottom() {
if (this.searchForm.pageNumber >= this.totalPages) return;
// this.status = 'loading';
this.searchForm.pageNumber+=1;
console.log('1111')
this.getShopList();
},
onLoad() {
this.getShopList();
this.getEatType();
this.getShopArea();
this.getOnlineWorkerCountByCanteenArea();
},
onShow() {
this.menuButtonInfo = uni.getMenuButtonBoundingClientRect()
this.searchForm.regionId = JSON.parse(uni.getStorageSync('area')).id
// uni.showLoading({
// title: '加载中...',
// mask: true
// })
},
methods: {
searchShop(type, value) {
this.searchForm.pageNumber = 1
if (type == 'area') {
this.searchForm.shopArea = value
} else if (type == 'score') {
this.searchScore = !this.searchScore
this.searchSale = false
this.searchForm.sort = 'shopScore'
} else if (type == 'sale') {
this.searchSale = !this.searchSale
this.searchScore = false
this.searchForm.sort = 'saleCount'
} else if (type == 'all') {
this.searchForm.sortOrder = 'shoprank'
this.searchForm.orderOrder = 'desc'
this.searchForm.shopArea = ''
this.$delete(this.searchForm, 'isStudent')
this.searchForm.sort = 'shoprank'
this.searchScore = false
this.searchScore = false
this.searchSale = false
} else if (type == 'typeUp') {
//TODO跳转新页面
}
this.getShopList();
},
buyingye() {
uni.showToast({
title: '店铺不在营业时间!',
icon: 'none'
});
},
getDormStatus(index) {
return this.groupTags[index % this.groupTags.length]
},
getGroupTip(index) {
return ['还差1人就成团', '刚下课,大家都在拼', '这口热乎的很适合夜宵', '附近同学想一起点'][index % 4]
},
getLiveAvatar(index) {
return this.groupAvatars[index % this.groupAvatars.length]
},
toggleCategory() {
this.categoryExpanded = !this.categoryExpanded
},
getEatType() {
let that = this
that.tui.request("/dictData/getByCondition", "GET", {
sort: 'sortOrder',
order: 'asc',
dictId: '1712359407444168704'
}, false, true).then((res) => {
if (res.code == 200) {
for (let i = 0; i < res.result.content.length; i++) {
for (let m = 0; m < this.menuBtn.length; m++) {
if (this.menuBtn[m].name == res.result.content[i].title) {
this.menuBtn[m].value = res.result.content[i].value
}
}
for (let m = 0; m < this.menuBtn1.length; m++) {
if (this.menuBtn1[m].name == res.result.content[i].title) {
this.menuBtn1[m].value = res.result.content[i].value
}
}
}
} else {
that.tui.toast(res.message)
return
}
}).catch((res) => {})
},
getShopArea() {
let that = this
that.tui.request("/app/shopArea/getByParentId/" + JSON.parse(uni.getStorageSync('area')).id, "GET", {},
false, true).then((res) => {
if (res.code == 200) {
if (res.result != null) {
for (let m = 0; m < res.result.length; m++) {
if (res.result[m].isCanteen == 1) {
that.shopArea.push(res.result[m])
}
}
}
} else {
that.tui.toast(res.message)
return
}
}).catch((res) => {})
},
getOnlineWorkerCountByCanteenArea() {
let that = this
that.tui.request("/worker/getOnlineWorkerByArea", "GET", {
parentId: JSON.parse(uni.getStorageSync('area')).id
}, false, true).then((res) => {
if (res.code == 200) {
const list = Array.isArray(res.result) ? res.result : []
that.onlineWorkerAreaList = list
that.onlineWorkerTotal = list.reduce((sum, item) => {
const count = Number(item.onlineWorkerCount || 0)
return sum + (isNaN(count) ? 0 : count)
}, 0)
}
}).catch(() => {})
},
getShopList() {
console.log("3333")
this.loadStatus = 'loading'
if (this.searchSale) {
this.searchForm.sortSale = 'saleCount'
this.searchForm.orderSale = 'desc'
this.searchForm.sortOrder = ''
} else {
this.searchForm.sortSale = ''
}
if (this.searchScore) {
this.searchForm.sortScore = 'shopScore'
this.searchForm.orderScore = 'desc'
this.searchForm.sortOrder = ''
} else {
this.searchForm.sortScore = ''
}
console.log("2222")
let that = this
that.tui.request("/app/shop/getByCondition", "GET", this.searchForm, false, true).then((res) => {
that.loadStatus = 'nomore';
if (res.code == 200) {
if (that.searchForm.pageNumber == 1) {
that.shopList = res.result.content
} else {
that.shopList = [...that.shopList, ...res.result.content]
}
that.totalPages = res.result.totalPages
that.judgeBusinessStatus()
that.isArea = false
that.$forceUpdate()
} else {
that.tui.toast(res.message);
return
}
uni.hideLoading()
}).catch((res) => {})
},
judgeBusinessStatus() {
for (let i = 0; i < this.shopList.length; i++) {
if (this.shopList[i].shopTakeaway != '' && this.shopList[i].shopTakeaway != null) {
if (this.shopList[i].status == 1) {
let isEndTime = this.isWithinBusinessHours(this.shopList[i].shopTakeaway.businessHourBegin,this.shopList[i].shopTakeaway.businessHourEnd)
this.shopList[i].status = isEndTime ? 1 : 0
}
}
}
},
//判断是否在营业时间内
isWithinBusinessHours(begin, end) {
// 获取当前时间的时和分
const now = new Date();
const currentMinutes = now.getHours() * 60 + now.getMinutes();
// 解析开始和结束时间(格式 "HH:MM")
const parseTime = (timeStr) => {
const [hours, minutes] = timeStr.split(':').map(Number);
return hours * 60 + minutes;
};
const startMinutes = parseTime(begin);
const endMinutes = parseTime(end);
// 判断是否在区间内(包含端点)
return currentMinutes >= startMinutes && currentMinutes <= endMinutes;
},
goDetail(type, item) {
if (type == 'shop') {
uni.navigateTo({
url: '/package2/group/groupBuySingle?type=shop&item=' + JSON.stringify(item)
})
} else if (type == 'search') {
if (item) {
if (item.isStudentOnly) {
this.searchStudentShop()
return
}
uni.navigateTo({
url: '/package2/group/searchGroup?shopType=' + (item.value || '')
})
} else {
uni.navigateTo({
url: '/package2/group/searchGroup'
})
}
} else {
uni.navigateTo({
url: '/package2/group/groupBuySingle?type=product&item=' + JSON.stringify(item)
})
}
},
back() {
uni.navigateBack()
},
searchStudentShop() {
this.searchForm.pageNumber = 1
this.searchForm.shopArea = ''
this.searchForm.shopType = ''
this.searchForm.sort = 'shoprank'
this.searchForm.sortOrder = 'shoprank'
this.searchForm.orderOrder = 'desc'
this.searchScore = false
this.searchSale = false
this.$set(this.searchForm, 'isStudent', 1)
this.getShopList()
},
checkArea() {
this.isArea = !this.isArea
}
}
}
</script>
<style lang="scss">
page {
width: 100%;
min-height: 100%;
font-size: 24rpx;
background:
radial-gradient(circle at 12% 8%, rgba(197, 255, 153, 0.5), transparent 34%),
radial-gradient(circle at 90% 18%, rgba(175, 255, 231, 0.48), transparent 36%),
linear-gradient(180deg, #f6ffea 0%, #f7fff9 42%, #fff9ef 100%);
color: #00231C;
}
.page1 {
width: 100%;
min-height: 100vh;
font-size: 24rpx;
position: relative;
overflow-x: hidden;
}
.title {
width: 100%;
height: auto;
padding-bottom: 24rpx;
position: relative;
overflow: visible;
z-index: 10;
}
.title::before {
content: '';
position: absolute;
top: -140rpx;
right: -120rpx;
width: 420rpx;
height: 420rpx;
border-radius: 50%;
background: rgba(167, 255, 194, 0.42);
filter: blur(8rpx);
}
.title-sreach {
width: 75%;
display: flex;
align-items: flex-start;
height: 188rpx;
position: relative;
z-index: 2;
}
.back-btn {
padding-top: 110rpx;
width: 64rpx;
box-sizing: border-box;
}
.title-name {
padding-top: 110rpx;
font-size: 34rpx;
font-weight: 900;
line-height: 40rpx;
white-space: nowrap;
text {
display: block;
margin-top: 4rpx;
font-size: 18rpx;
line-height: 22rpx;
color: rgba(0, 35, 28, 0.56);
font-weight: 700;
}
}
.title-search {
margin-top: 110rpx;
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.72);
height: 58rpx;
margin-left: 18rpx;
border-radius: 58rpx;
flex: 1;
padding: 0 14rpx 0 18rpx;
box-sizing: border-box;
box-shadow: 0 14rpx 34rpx rgba(20, 115, 88, 0.12);
backdrop-filter: blur(16rpx);
border: 1rpx solid rgba(255, 255, 255, 0.86);
}
.search-word-swiper {
flex: 1;
height: 58rpx;
margin-left: 8rpx;
}
.search-hot-word {
height: 58rpx;
line-height: 58rpx;
font-size: 22rpx;
font-weight: 800;
color: #08735d;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.search-trend {
height: 34rpx;
line-height: 34rpx;
padding: 0 12rpx;
border-radius: 34rpx;
background: linear-gradient(90deg, #dcff9c, #baffec);
font-size: 18rpx;
font-weight: 900;
color: #08735d;
}
.title-tab {
width: 94%;
margin: 0 auto;
height: 256rpx;
position: relative;
z-index: 2;
}
.campus-banner {
width: 100%;
height: 100%;
border-radius: 38rpx;
position: relative;
overflow: hidden;
background:
linear-gradient(135deg, rgba(224, 255, 174, 0.98), rgba(179, 255, 225, 0.96) 52%, rgba(255, 246, 221, 0.96)),
linear-gradient(180deg, #f9fff1, #eaffd7);
box-shadow: 0 24rpx 54rpx rgba(22, 126, 93, 0.18);
border: 2rpx solid rgba(255, 255, 255, 0.8);
}
.banner-glow {
position: absolute;
right: -80rpx;
bottom: -100rpx;
width: 360rpx;
height: 360rpx;
border-radius: 50%;
background: rgba(255, 202, 116, 0.26);
}
.banner-copy {
position: relative;
z-index: 3;
padding: 10rpx 0 0 34rpx;
width: 58%;
box-sizing: border-box;
}
.banner-sticker {
display: inline-block;
height: 42rpx;
line-height: 42rpx;
padding: 0 18rpx;
border-radius: 42rpx 42rpx 42rpx 12rpx;
background: rgba(255, 255, 255, 0.72);
color: #08735d;
font-size: 22rpx;
font-weight: 900;
box-shadow: 0 8rpx 20rpx rgba(5, 96, 75, 0.1);
}
.banner-title {
margin-top: 18rpx;
font-size: 48rpx;
line-height: 56rpx;
font-weight: 900;
color: #083f34;
letter-spacing: 1rpx;
}
.banner-desc {
margin-top: 10rpx;
font-size: 23rpx;
line-height: 34rpx;
color: rgba(0, 35, 28, 0.68);
font-weight: 700;
}
.banner-bubbles {
margin-top: 60rpx;
white-space: nowrap;
text {
display: inline-block;
margin-right: 10rpx;
padding: 8rpx 14rpx;
border-radius: 24rpx;
background: rgba(255, 255, 255, 0.64);
font-size: 20rpx;
font-weight: 900;
color: #ff6b3d;
}
}
.banner-food-card {
position: absolute;
right: 18rpx;
bottom: 18rpx;
z-index: 2;
width: 216rpx;
height: 216rpx;
border-radius: 34rpx;
overflow: hidden;
box-shadow: 0 22rpx 42rpx rgba(66, 121, 81, 0.22);
transform: rotate(3deg);
animation: breathe 3.4s ease-in-out infinite;
img {
width: 100%;
height: 100%;
object-fit: cover;
transform: scale(1);
}
}
.food-card-tag {
position: absolute;
left: 16rpx;
bottom: 14rpx;
height: 38rpx;
line-height: 38rpx;
padding: 0 14rpx;
border-radius: 38rpx;
background: rgba(255, 255, 255, 0.82);
color: #ff5a35;
font-size: 20rpx;
font-weight: 900;
}
.food-float {
position: absolute;
z-index: 4;
width: 54rpx;
height: 54rpx;
line-height: 54rpx;
text-align: center;
border-radius: 50%;
background: rgba(255, 255, 255, 0.7);
box-shadow: 0 10rpx 24rpx rgba(10, 100, 70, 0.13);
animation: floatFood 3.2s ease-in-out infinite;
}
.float-one {
right: 248rpx;
top: 34rpx;
}
.float-two {
right: 38rpx;
top: 30rpx;
animation-delay: .5s;
}
.float-three {
right: 294rpx;
bottom: 38rpx;
animation-delay: .9s;
}
.float-four {
right: 162rpx;
top: 92rpx;
animation-delay: 1.3s;
}
.steam {
position: absolute;
z-index: 5;
width: 18rpx;
height: 70rpx;
border-radius: 50%;
border-left: 5rpx solid rgba(255, 255, 255, 0.72);
opacity: 0;
animation: steamUp 2.8s ease-in-out infinite;
}
.steam-one {
right: 148rpx;
bottom: 168rpx;
}
.steam-two {
right: 104rpx;
bottom: 150rpx;
animation-delay: .6s;
}
.steam-three {
right: 202rpx;
bottom: 144rpx;
animation-delay: 1.2s;
}
.campus-live {
width: 94%;
margin: 22rpx auto 0;
position: relative;
z-index: 2;
}
.live-title {
margin-bottom: 14rpx;
white-space: nowrap;
text {
display: inline-block;
margin-right: 12rpx;
padding: 8rpx 16rpx;
border-radius: 28rpx;
background: rgba(255, 255, 255, 0.62);
color: #083f34;
font-size: 23rpx;
font-weight: 900;
box-shadow: 0 8rpx 18rpx rgba(34, 128, 94, 0.08);
}
text:first-child {
background: linear-gradient(90deg, rgba(221, 255, 158, 0.88), rgba(186, 255, 236, 0.88));
color: #08735d;
}
}
.live-scroll {
width: 100%;
white-space: nowrap;
}
.live-bubble {
display: inline-flex;
align-items: center;
vertical-align: top;
margin-right: 18rpx;
min-width: 270rpx;
padding: 14rpx 18rpx 14rpx 14rpx;
box-sizing: border-box;
border-radius: 32rpx;
background: rgba(255, 255, 255, 0.56);
border: 1rpx solid rgba(255, 255, 255, 0.8);
box-shadow: 0 12rpx 28rpx rgba(34, 128, 94, 0.1);
animation: bubbleFloat 3.8s ease-in-out infinite;
}
.live-bubble:nth-child(2n) {
animation-delay: .7s;
}
.live-avatar {
width: 56rpx;
height: 56rpx;
line-height: 56rpx;
text-align: center;
border-radius: 50%;
background: linear-gradient(135deg, #e8ffb8, #b8ffe9);
margin-right: 12rpx;
box-shadow: inset 0 6rpx 10rpx rgba(255, 255, 255, 0.7);
}
.live-main {
font-size: 22rpx;
font-weight: 900;
color: #083f34;
}
.live-sub {
margin-top: 4rpx;
font-size: 20rpx;
font-weight: 700;
color: rgba(0, 35, 28, 0.55);
}
.interest-card {
width: 94%;
margin: 24rpx auto 0;
padding: 20rpx 12rpx 14rpx;
box-sizing: border-box;
border-radius: 36rpx;
background: rgba(255, 255, 255, 0.46);
border: 1rpx solid rgba(255, 255, 255, 0.72);
box-shadow: 0 18rpx 42rpx rgba(42, 134, 93, 0.1);
backdrop-filter: blur(16rpx);
position: relative;
z-index: 2;
}
.interest-card-expanded {
padding-bottom: 18rpx;
}
.section-head {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 14rpx 6rpx;
text:first-child {
font-size: 28rpx;
font-weight: 900;
color: #083f34;
}
text:last-child {
font-size: 20rpx;
font-weight: 900;
color: #08735d;
background: linear-gradient(90deg, rgba(218, 255, 159, 0.86), rgba(186, 255, 236, 0.86));
border-radius: 24rpx;
padding: 7rpx 16rpx;
box-shadow: 0 8rpx 18rpx rgba(20, 115, 88, 0.1);
}
}
.menu-box {
width: 100%;
display: flex;
margin-top: 14rpx;
}
.menu-box-second {
margin-top: 14rpx;
}
.menu-list {
flex: 1;
text-align: center;
transition: transform .18s ease;
}
.menu-list:active {
transform: scale(0.88);
}
.menu-icon-wrap {
width: 102rpx;
height: 102rpx;
margin: 0 auto;
position: relative;
border-radius: 32rpx;
background: linear-gradient(145deg, rgba(255, 255, 255, 0.86), rgba(217, 255, 172, 0.66));
box-shadow: 0 14rpx 28rpx rgba(23, 117, 83, 0.12), inset 0 8rpx 14rpx rgba(255, 255, 255, 0.85);
animation: iconFloat 4s ease-in-out infinite;
}
.menu-list:nth-child(2n) .menu-icon-wrap {
animation-delay: .6s;
}
.menu-icon-wrap img {
width: 80rpx;
height: 80rpx;
display: block;
margin: 0 auto;
padding-top: 12rpx;
filter: drop-shadow(0 8rpx 10rpx rgba(0, 70, 42, 0.14));
}
.menu-sticker {
position: absolute;
right: -8rpx;
top: -8rpx;
width: 36rpx;
height: 36rpx;
line-height: 36rpx;
text-align: center;
border-radius: 50%;
background: #ff774d;
color: #fff;
font-size: 18rpx;
font-weight: 900;
box-shadow: 0 8rpx 16rpx rgba(255, 83, 42, 0.22);
}
.menu-name {
text-align: center;
font-size: 22rpx;
font-weight: 900;
margin-top: 12rpx;
color: #083f34;
}
.title-sort {
height: 66rpx;
display: flex;
width: 94%;
margin: 22rpx auto 0;
position: relative;
z-index: 30;
}
.sort-member {
line-height: 66rpx;
text-align: center;
background: rgba(255, 255, 255, 0.68);
width: 23%;
margin-right: 2.66%;
border-radius: 22rpx;
box-shadow: 0 10rpx 24rpx rgba(44, 132, 93, 0.09);
font-weight: 900;
color: #245b4d;
}
.sort-member:last-child {
margin-right: 0;
}
.sort-text {
font-size: 22rpx;
}
.sort-value {
width: 180rpx;
height: auto;
max-height: 320rpx;
overflow: scroll;
background: rgba(1, 45, 36, 0.88);
position: absolute;
top: 82rpx;
right: 0;
border-radius: 24rpx;
color: #fff;
font-size: 22rpx;
box-shadow: 0 14rpx 32rpx rgba(0, 35, 28, 0.2);
z-index: 99;
}
.sort-value1 {
border-bottom: 1rpx solid rgba(255, 255, 255, 0.12);
}
.shop-list {
width: 94%;
height: auto;
margin: 10rpx auto 0;
}
.shop-member {
width: 100%;
height: auto;
border-radius: 34rpx;
background: rgba(255, 255, 255, 0.62);
margin-bottom: 24rpx;
position: relative;
overflow: hidden;
box-shadow: 0 18rpx 44rpx rgba(19, 91, 70, 0.12);
border: 1rpx solid rgba(255, 255, 255, 0.86);
animation: cardBreath 4.2s ease-in-out infinite;
}
.shop-card-bg {
position: absolute;
top: -120rpx;
right: -90rpx;
width: 300rpx;
height: 300rpx;
border-radius: 50%;
background: rgba(214, 255, 159, 0.36);
}
.shop-top {
padding: 22rpx;
display: flex;
position: relative;
z-index: 2;
}
.shop-img {
width: 188rpx;
height: 188rpx;
position: relative;
border-radius: 32rpx;
box-shadow: 0 16rpx 32rpx rgba(20, 75, 57, 0.16);
overflow: hidden;
img {
width: 100%;
background-size: 100%;
height: 100%;
border-radius: 32rpx;
object-fit: cover;
transform: scale(1.06);
}
}
.shop-img::after {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 55%;
background: linear-gradient(180deg, rgba(255, 255, 255, 0.2), transparent);
}
.shop-img-badge {
position: absolute;
left: 12rpx;
bottom: 12rpx;
height: 36rpx;
line-height: 36rpx;
padding: 0 12rpx;
border-radius: 36rpx;
background: rgba(255, 255, 255, 0.86);
color: #ff5b37;
font-size: 19rpx;
font-weight: 900;
}
.shop-steam {
position: absolute;
top: 14rpx;
width: 18rpx;
height: 56rpx;
border-left: 4rpx solid rgba(255, 255, 255, 0.82);
border-radius: 50%;
opacity: 0;
animation: steamUp 2.6s ease-in-out infinite;
}
.shop-steam-one {
left: 62rpx;
}
.shop-steam-two {
left: 108rpx;
animation-delay: .8s;
}
.shop-content {
flex: 1;
padding-left: 22rpx;
min-width: 0;
}
.shop-live-row {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10rpx;
text {
display: inline-block;
height: 34rpx;
line-height: 34rpx;
padding: 0 12rpx;
border-radius: 34rpx;
font-size: 18rpx;
font-weight: 900;
}
text:first-child {
background: rgba(219, 255, 157, 0.72);
color: #08735d;
}
text:last-child {
background: #ff744d;
color: #fff;
box-shadow: 0 8rpx 14rpx rgba(255, 93, 45, 0.2);
}
}
.shop-name {
font-size: 31rpx;
font-weight: 900;
line-height: 40rpx;
color: #062f28;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.shop-content-center {
display: flex;
align-items: center;
margin: 16rpx 0 14rpx;
}
.shop-rate {
background: rgba(255, 250, 237, 0.72);
min-height: 46rpx;
display: flex;
align-items: center;
border-radius: 46rpx;
padding: 0 14rpx 0 8rpx;
box-shadow: inset 0 0 0 1rpx rgba(255, 255, 255, 0.7);
}
.avatar-stack {
display: flex;
align-items: center;
text {
width: 34rpx;
height: 34rpx;
line-height: 34rpx;
text-align: center;
border-radius: 50%;
background: #fff;
margin-left: -8rpx;
font-size: 18rpx;
box-shadow: 0 4rpx 10rpx rgba(0, 45, 29, 0.12);
}
text:first-child {
margin-left: 0;
}
}
.shop-rate-text {
margin-left: 10rpx;
font-size: 20rpx;
font-weight: 900;
color: #7a5942;
}
.shop-tag {
flex: 1;
line-height: 40rpx;
text-align: right;
text {
padding: 6rpx 12rpx;
background: rgba(184, 255, 225, 0.62);
color: #08735d;
border-radius: 18rpx;
font-size: 20rpx;
font-weight: 900;
}
}
.shop-content-bottom {
display: flex;
align-items: center;
}
.shop-deal {
flex: 1;
min-width: 0;
text {
display: inline-block;
max-width: 100%;
padding: 7rpx 12rpx;
background: rgba(223, 255, 176, 0.62);
color: #487064;
border-radius: 16rpx;
font-size: 20rpx;
font-weight: 800;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.shop-deal1 {
font-size: 21rpx;
font-weight: 900;
color: #ff5a35;
text {
font-size: 28rpx;
padding-right: 4rpx;
}
}
.shop-bottom {
border-top: 1rpx solid rgba(20, 90, 70, 0.06);
width: 100%;
overflow-x: scroll;
display: flex;
height: auto;
overflow-y: hidden;
padding: 0rpx 0 22rpx;
position: relative;
z-index: 2;
background: rgba(255, 255, 255, 0.3);
}
.menu-member {
position: relative;
width: 148rpx;
height: 100%;
margin: 6rpx 0 0 18rpx;
flex-shrink: 0;
}
.menu-img {
height: 136rpx;
width: 136rpx;
margin: 0 auto;
border-radius: 24rpx;
box-shadow: 0 10rpx 22rpx rgba(0, 0, 0, 0.12);
overflow: hidden;
position: relative;
img {
width: 100%;
height: 100%;
background-size: 100%;
border-radius: 24rpx;
object-fit: cover;
transform: scale(1.08);
}
}
.menu-img-gloss {
position: absolute;
left: -30%;
top: -40%;
width: 80%;
height: 160%;
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.26), transparent);
transform: rotate(18deg);
animation: glossMove 3.8s ease-in-out infinite;
}
.menu-content {
width: 148rpx;
margin-top: 10rpx;
padding: 0 4rpx;
box-sizing: border-box;
font-size: 22rpx;
}
.shop-menu-name {
font-weight: 900;
overflow: hidden;
height: 32rpx;
line-height: 32rpx;
color: #15382f;
text-overflow: ellipsis;
white-space: nowrap;
}
.shop-menu-price {
margin-top: 4rpx;
color: #9b9588;
font-size: 21rpx;
font-weight: 700;
line-height: 28rpx;
text-decoration: line-through;
}
.shop-menu-purchase {
display: inline-flex;
align-items: center;
max-width: 100%;
background: linear-gradient(90deg, #fff1df, #ffe6e1);
min-height: 32rpx;
line-height: 32rpx;
padding: 0 8rpx 0 6rpx;
border-radius: 18rpx;
font-weight: 900;
margin-top: 6rpx;
color: #ff5a45;
font-size: 20rpx;
box-shadow: 0 6rpx 12rpx rgba(255, 57, 57, 0.09);
white-space: nowrap;
}
.group-badge {
width: 26rpx;
height: 26rpx;
line-height: 26rpx;
text-align: center;
border-radius: 50%;
background: #ff6d49;
color: #fff;
font-size: 18rpx;
font-weight: 900;
margin-right: 5rpx;
flex-shrink: 0;
}
.group-price {
margin-top: 2rpx;
color: #ff1f1f;
font-size: 24rpx;
padding-left: 0;
white-space: nowrap;
}
.zaixian {
position: fixed;
bottom: 40rpx;
left: 8%;
width: 84%;
height: 76rpx;
background: linear-gradient(90deg, rgba(227, 255, 150, 0.95), rgba(166, 255, 234, 0.95));
border-radius: 76rpx;
font-weight: 900;
display: flex;
align-items: center;
padding: 0 24rpx;
box-sizing: border-box;
text-align: center;
line-height: normal;
box-shadow: 0 12rpx 30rpx rgba(13, 114, 82, 0.18);
border: 1rpx solid rgba(255, 255, 255, 0.86);
z-index: 20;
}
.zaixian-gif {
width: 42rpx;
height: 42rpx;
flex-shrink: 0;
}
.zaixian-divider {
width: 2rpx;
height: 36rpx;
background: rgba(0, 35, 28, 0.2);
margin: 0 18rpx;
}
.zaixian-swiper {
flex: 1;
height: 76rpx;
}
.zaixian-item {
height: 76rpx;
line-height: 76rpx;
font-size: 24rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: #073d33;
}
@keyframes floatFood {
0%, 100% {
transform: translateY(0) rotate(0deg);
}
50% {
transform: translateY(-14rpx) rotate(8deg);
}
}
@keyframes steamUp {
0% {
opacity: 0;
transform: translateY(18rpx) scale(.75);
}
45% {
opacity: .8;
}
100% {
opacity: 0;
transform: translateY(-42rpx) scale(1.2);
}
}
@keyframes breathe {
0%, 100% {
transform: rotate(3deg) scale(1);
}
50% {
transform: rotate(1deg) scale(1.035);
}
}
@keyframes bubbleFloat {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-6rpx);
}
}
@keyframes iconFloat {
0%, 100% {
transform: translateY(0);
}
50% {
transform: translateY(-8rpx);
}
}
@keyframes cardBreath {
0%, 100% {
box-shadow: 0 18rpx 44rpx rgba(19, 91, 70, 0.12);
}
50% {
box-shadow: 0 22rpx 50rpx rgba(19, 91, 70, 0.17);
}
}
@keyframes glossMove {
0%, 45% {
transform: translateX(-40rpx) rotate(18deg);
}
100% {
transform: translateX(210rpx) rotate(18deg);
}
}
</style>