feat(uniapp): 按设计稿重构首页并修复点餐分类高亮
重构米糖风格首页与纵向渐变背景;点击分类时锁定 scroll 回写,避免左侧高亮回跳到上一项。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
1 parent
4d925fb6ff
commit
f7b825ff7b
3 files changed
+531
-226
No files matched your search
@@ -3,7 +3,9 @@
|
|||||||
{
|
{
|
||||||
"path": "pages/index/index",
|
"path": "pages/index/index",
|
||||||
"style": {
|
"style": {
|
||||||
"navigationBarTitleText": "首页"
|
"navigationBarTitleText": "首页",
|
||||||
|
"navigationBarBackgroundColor": "#fff3e6",
|
||||||
|
"backgroundColor": "#fff3e6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<layout>
|
<layout>
|
||||||
<uv-sticky
|
<view class="index-page">
|
||||||
bg-color="#F5F5F5"
|
|
||||||
offset-top="0"
|
|
||||||
customNavHeight="0"
|
|
||||||
>
|
|
||||||
<uv-navbar
|
<uv-navbar
|
||||||
:fixed="false"
|
:fixed="false"
|
||||||
:safeAreaInsetTop="true"
|
:safeAreaInsetTop="true"
|
||||||
@@ -12,279 +8,570 @@
|
|||||||
bgColor="transparent"
|
bgColor="transparent"
|
||||||
leftIcon=""
|
leftIcon=""
|
||||||
/>
|
/>
|
||||||
<!-- #ifndef MP -->
|
|
||||||
<blank size="10"></blank>
|
|
||||||
<!-- #endif -->
|
|
||||||
|
|
||||||
<blank size="5"></blank>
|
<!-- 顶部问候 -->
|
||||||
</uv-sticky>
|
<view class="index-header">
|
||||||
|
<view class="index-header__greet">
|
||||||
|
你好,{{ isLogin && member.nickname ? member.nickname : '游客' }}
|
||||||
|
</view>
|
||||||
|
<view class="index-header__sub">欢迎来到米糖烘焙点单</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
<blank size="10"></blank>
|
<!-- 品牌 Banner / 广告轮播 -->
|
||||||
<view class="container index-page">
|
<view class="index-banner">
|
||||||
<view class="index-banner">
|
<view v-if="listAds.length" class="index-banner__swiper-wrap">
|
||||||
<uv-swiper class="index-banner__swiper" height="300" imgMode="aspectFill" keyName="image" :list="listAds" indicatorMode="dot" indicatorStyle="bottom"></uv-swiper>
|
<uv-swiper
|
||||||
<view class="index-banner__intro">
|
class="index-banner__swiper"
|
||||||
<view class="index-banner__greet">您好,{{ isLogin ? member.nickname : '游客' }}</view>
|
height="320"
|
||||||
<view class="index-banner__note">意向点餐外卖系统</view>
|
radius="24"
|
||||||
</view>
|
imgMode="aspectFill"
|
||||||
</view>
|
keyName="image"
|
||||||
<view class="index-content">
|
:list="listAds"
|
||||||
<view class="flex justify-between index-menu">
|
indicator
|
||||||
<view class="flex flex-column align-center index-menu__item" @tap="takein">
|
indicatorMode="dot"
|
||||||
<view><image src="/static/images/index002.png" mode="aspectFit" class="index-menu__icon"></image></view>
|
indicatorActiveColor="#F28C38"
|
||||||
<view>自取</view>
|
indicatorInactiveColor="rgba(255,255,255,.75)"
|
||||||
<view class="font-small text-light-black">下单免排队</view>
|
/>
|
||||||
</view>
|
</view>
|
||||||
<view class="flex flex-column align-center index-menu__item" @tap="takeout">
|
<view v-else class="index-banner__brand">
|
||||||
<view><image src="/static/images/index003.png" mode="aspectFit" class="index-menu__icon"></image></view>
|
<view class="index-banner__brand-left">
|
||||||
<view>外卖</view>
|
<view class="index-banner__logo">
|
||||||
<view class="font-small text-light-black">美食送到家</view>
|
<text class="index-banner__logo-en">Maitre</text>
|
||||||
</view>
|
<text class="index-banner__logo-zh">米糖</text>
|
||||||
</view>
|
</view>
|
||||||
<view class="index-card">
|
<view class="index-banner__divider"></view>
|
||||||
<view class="index-card__main">
|
<view class="index-banner__slogan">你的烘焙材料管家</view>
|
||||||
<view class="index-card__header">
|
<view class="index-banner__features">
|
||||||
<text class="index-card__title">我的卡券</text>
|
<view
|
||||||
<text class="index-card__value">{{member.couponCount}}</text>
|
v-for="item in brandFeatures"
|
||||||
</view>
|
:key="item.label"
|
||||||
<view class="index-card__desc">
|
class="index-banner__feature"
|
||||||
可抵扣商品价格哦
|
>
|
||||||
</view>
|
<view class="index-banner__feature-icon">
|
||||||
</view>
|
<uv-icon :name="item.icon" size="14" color="#8B5A2B" />
|
||||||
<view class="index-card__action" @tap="coupons">
|
</view>
|
||||||
去领个券
|
<text class="index-banner__feature-label">{{ item.label }}</text>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="index-card">
|
</view>
|
||||||
<view class="index-card__main" @tap="goScore">
|
<view class="index-banner__brand-right">
|
||||||
<view class="index-card__header">
|
<view class="index-banner__cupcake">
|
||||||
<text class="index-card__title">积分商城</text>
|
<view class="index-banner__cupcake-cherry"></view>
|
||||||
</view>
|
<view class="index-banner__cupcake-frost"></view>
|
||||||
<view class="index-card__desc">
|
<view class="index-banner__cupcake-body"></view>
|
||||||
进入积分商城兑换优惠券
|
<view class="index-banner__cupcake-wrap"></view>
|
||||||
</view>
|
</view>
|
||||||
</view>
|
</view>
|
||||||
<view class="index-card__action" @tap="goScore">
|
<view class="index-banner__dots">
|
||||||
逛一逛
|
<view class="index-banner__dot index-banner__dot--active"></view>
|
||||||
</view>
|
<view class="index-banner__dot"></view>
|
||||||
<!-- <view class="index-card__action index-card__action--with-icon" @tap="goScore">
|
<view class="index-banner__dot"></view>
|
||||||
<image src="/static/images/jifen.png" class="index-card__action-icon"></image>
|
</view>
|
||||||
<text>逛一逛</text>
|
</view>
|
||||||
</view> -->
|
</view>
|
||||||
</view>
|
|
||||||
</view>
|
<!-- 自取 / 外卖 -->
|
||||||
</view>
|
<view class="index-services">
|
||||||
|
<view class="index-service" @tap="takein">
|
||||||
|
<view class="index-service__info">
|
||||||
|
<view class="index-service__title">自取</view>
|
||||||
|
<view class="index-service__desc">下单免排队</view>
|
||||||
|
<view class="index-service__btn index-service__btn--orange">
|
||||||
|
去下单 >
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<image
|
||||||
|
class="index-service__img"
|
||||||
|
src="/static/images/index002.png"
|
||||||
|
mode="aspectFit"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
<view class="index-service" @tap="takeout">
|
||||||
|
<view class="index-service__info">
|
||||||
|
<view class="index-service__title">外卖</view>
|
||||||
|
<view class="index-service__desc">美食送到家</view>
|
||||||
|
<view class="index-service__btn index-service__btn--gold">
|
||||||
|
去下单 >
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
<image
|
||||||
|
class="index-service__img"
|
||||||
|
src="/static/images/index003.png"
|
||||||
|
mode="aspectFit"
|
||||||
|
/>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
|
||||||
|
<!-- 卡券 / 积分 -->
|
||||||
|
<view class="index-extras">
|
||||||
|
<view class="index-extra" @tap="coupons">
|
||||||
|
<view class="index-extra__icon index-extra__icon--coupon">
|
||||||
|
<uv-icon name="coupon-fill" size="22" color="#ffffff" />
|
||||||
|
</view>
|
||||||
|
<view class="index-extra__main">
|
||||||
|
<view class="index-extra__title-row">
|
||||||
|
<text class="index-extra__title">我的卡券</text>
|
||||||
|
<text class="index-extra__value">{{ member.couponCount || 0 }}</text>
|
||||||
|
</view>
|
||||||
|
<view class="index-extra__desc">可抵扣商品价格哦</view>
|
||||||
|
</view>
|
||||||
|
<view class="index-extra__link">去领个券 ></view>
|
||||||
|
</view>
|
||||||
|
<view class="index-extra index-extra--last" @tap="goScore">
|
||||||
|
<view class="index-extra__icon index-extra__icon--score">
|
||||||
|
<uv-icon name="bag" size="22" color="#ffffff" />
|
||||||
|
</view>
|
||||||
|
<view class="index-extra__main">
|
||||||
|
<view class="index-extra__title-row">
|
||||||
|
<text class="index-extra__title">积分商城</text>
|
||||||
|
</view>
|
||||||
|
<view class="index-extra__desc">进入积分商城兑换优惠券</view>
|
||||||
|
</view>
|
||||||
|
<view class="index-extra__link">逛一逛 ></view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
</layout>
|
</layout>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import { ref } from 'vue'
|
||||||
ref
|
|
||||||
} from 'vue'
|
|
||||||
import { onLoad } from '@dcloudio/uni-app'
|
import { onLoad } from '@dcloudio/uni-app'
|
||||||
import {
|
import { menuAds } from '@/api/market'
|
||||||
menuAds
|
|
||||||
} from '@/api/market'
|
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { useMainStore } from '@/store/store'
|
import { useMainStore } from '@/store/store'
|
||||||
//
|
|
||||||
const main = useMainStore()
|
const main = useMainStore()
|
||||||
const { member,store, isLogin} = storeToRefs(main)
|
const { member, store, isLogin } = storeToRefs(main)
|
||||||
//const store = ref(main.store)
|
|
||||||
const listAds = ref([])
|
const listAds = ref([])
|
||||||
// const isLogin = ref(main.isLogin)
|
|
||||||
|
const brandFeatures = [
|
||||||
|
{ icon: 'thumb-up', label: '优质原料' },
|
||||||
|
{ icon: 'grid', label: '品类丰富' },
|
||||||
|
{ icon: 'gift', label: '新鲜烘焙' },
|
||||||
|
{ icon: 'heart', label: '贴心服务' }
|
||||||
|
]
|
||||||
|
|
||||||
const handGetListAds = async () => {
|
const handGetListAds = async () => {
|
||||||
let shop_id = store.id ? store.id : 0;
|
const shop_id = store.value?.id ? store.value.id : 0
|
||||||
let data = await menuAds({
|
const data = await menuAds({ shop_id })
|
||||||
shop_id: shop_id
|
if (data) {
|
||||||
});
|
listAds.value = data.list || []
|
||||||
if (data) {
|
uni.setStorage({
|
||||||
listAds.value = data.list;
|
key: 'isActive',
|
||||||
console.log('listAds:',listAds.value)
|
data: data.isActive
|
||||||
uni.setStorage({
|
})
|
||||||
key: 'isActive',
|
if (data.list && data.list.length > 0) {
|
||||||
data: data.isActive
|
uni.setStorage({
|
||||||
});
|
key: 'shopAd',
|
||||||
if(data.list.length > 0){
|
data: data.list[0].image
|
||||||
uni.setStorage({
|
})
|
||||||
key: 'shopAd',
|
}
|
||||||
data: data.list[0].image
|
}
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const takein = () => {
|
const takein = () => {
|
||||||
main.SET_ORDER_TYPE('takein')
|
main.SET_ORDER_TYPE('takein')
|
||||||
uni.switchTab({
|
uni.switchTab({ url: '/pages/menu/menu' })
|
||||||
url: '/pages/menu/menu'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const takeout = () => {
|
const takeout = () => {
|
||||||
main.SET_ORDER_TYPE('takeout')
|
main.SET_ORDER_TYPE('takeout')
|
||||||
uni.switchTab({
|
uni.switchTab({ url: '/pages/menu/menu' })
|
||||||
url: '/pages/menu/menu'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const coupons = () => {
|
const coupons = () => {
|
||||||
console.log("--> % orderType:\n", main.orderType)
|
if (!main.isLogin) {
|
||||||
console.log("--> % isLogin:\n", main.isLogin)
|
uni.navigateTo({ url: '/pages/components/pages/login/login' })
|
||||||
if(!main.isLogin) {
|
return
|
||||||
uni.navigateTo({url: '/pages/components/pages/login/login'})
|
}
|
||||||
return
|
uni.navigateTo({ url: '/pages/components/pages/coupons/coupons' })
|
||||||
}
|
|
||||||
uni.navigateTo({
|
|
||||||
url: '/pages/components/pages/coupons/coupons'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const goScore = () => {
|
const goScore = () => {
|
||||||
uni.navigateTo({
|
uni.navigateTo({ url: '/pages/components/pages/scoreproduct/list' })
|
||||||
url: '/pages/components/pages/scoreproduct/list'
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
onLoad(() => {
|
onLoad(() => {
|
||||||
// main.init()
|
|
||||||
handGetListAds()
|
handGetListAds()
|
||||||
})
|
})
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
// 首页局部尺寸 token(与 uni.scss 全局变量配合)
|
$page-bg-top: #fff3e6;
|
||||||
$index-banner-height: 300rpx;
|
$page-bg-mid: #fff8f0;
|
||||||
$index-menu-item-width: 355rpx;
|
$page-bg-bottom: #ffffff;
|
||||||
$index-card-radius: 10rpx;
|
$card-radius: 28rpx;
|
||||||
$index-content-padding-x: 15rpx;
|
$accent-orange: #f28c38;
|
||||||
$index-intro-offset-x: 40rpx;
|
$accent-gold: #f5ba42;
|
||||||
$index-intro-offset-y: 50rpx;
|
$text-main: #2b2b2b;
|
||||||
$index-value-font-size: 44rpx;
|
$text-sub: #9a9590;
|
||||||
$index-gap-sm: 10rpx;
|
|
||||||
|
|
||||||
/* #ifdef H5 */
|
/* #ifdef H5 */
|
||||||
page {
|
page {
|
||||||
height: auto;
|
height: auto;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
}
|
}
|
||||||
/* #endif */
|
/* #endif */
|
||||||
|
|
||||||
.index-page {
|
.index-page {
|
||||||
--index-banner-height: #{$index-banner-height};
|
min-height: 100vh;
|
||||||
--index-menu-item-width: #{$index-menu-item-width};
|
padding: 8rpx 28rpx 40rpx;
|
||||||
|
box-sizing: border-box;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
$page-bg-top 0%,
|
||||||
|
$page-bg-mid 42%,
|
||||||
|
$page-bg-bottom 100%
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
.index-banner {
|
.index-header {
|
||||||
position: relative;
|
padding: 8rpx 8rpx 28rpx;
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
&__swiper {
|
&__greet {
|
||||||
width: 100%;
|
font-size: 40rpx;
|
||||||
height: var(--index-banner-height);
|
font-weight: 700;
|
||||||
}
|
color: $text-main;
|
||||||
|
line-height: 1.3;
|
||||||
|
}
|
||||||
|
|
||||||
&__intro {
|
&__sub {
|
||||||
position: absolute;
|
margin-top: 10rpx;
|
||||||
top: calc(#{$index-intro-offset-y} + var(--status-bar-height));
|
font-size: 26rpx;
|
||||||
left: $index-intro-offset-x;
|
color: $text-sub;
|
||||||
color: $text-color-white;
|
}
|
||||||
display: flex;
|
}
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__greet {
|
.index-banner {
|
||||||
font-size: $font-size-lg;
|
margin-bottom: 24rpx;
|
||||||
margin-bottom: $index-gap-sm;
|
|
||||||
}
|
|
||||||
|
|
||||||
&__note {
|
&__swiper-wrap {
|
||||||
font-size: $font-size-sm;
|
overflow: hidden;
|
||||||
}
|
border-radius: $card-radius;
|
||||||
}
|
box-shadow: 0 12rpx 28rpx rgba(180, 120, 60, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
.index-content {
|
&__brand {
|
||||||
padding: 0 $index-content-padding-x;
|
position: relative;
|
||||||
}
|
display: flex;
|
||||||
|
align-items: stretch;
|
||||||
|
min-height: 320rpx;
|
||||||
|
padding: 36rpx 28rpx 48rpx;
|
||||||
|
border-radius: $card-radius;
|
||||||
|
overflow: hidden;
|
||||||
|
background:
|
||||||
|
radial-gradient(ellipse at 85% 40%, rgba(255, 255, 255, 0.55) 0%, transparent 55%),
|
||||||
|
linear-gradient(135deg, #f7e8d4 0%, #f0d7b8 45%, #e8c9a0 100%);
|
||||||
|
box-shadow: 0 12rpx 28rpx rgba(180, 120, 60, 0.12);
|
||||||
|
}
|
||||||
|
|
||||||
.index-menu {
|
&__brand-left {
|
||||||
margin-top: $spacing-row-base;
|
flex: 1;
|
||||||
|
z-index: 2;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
&__item {
|
&__logo {
|
||||||
width: var(--index-menu-item-width);
|
display: flex;
|
||||||
padding-bottom: $spacing-row-lg;
|
align-items: baseline;
|
||||||
background-color: $text-color-white;
|
gap: 12rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__icon {
|
&__logo-en {
|
||||||
width: 100rpx;
|
font-size: 48rpx;
|
||||||
height: 100rpx;
|
font-weight: 600;
|
||||||
margin-top: $spacing-row-lg;
|
font-style: italic;
|
||||||
}
|
color: #6b3f1f;
|
||||||
}
|
font-family: 'Times New Roman', Georgia, serif;
|
||||||
|
letter-spacing: 1rpx;
|
||||||
|
}
|
||||||
|
|
||||||
.index-card {
|
&__logo-zh {
|
||||||
position: relative;
|
font-size: 40rpx;
|
||||||
display: flex;
|
font-weight: 700;
|
||||||
align-items: center;
|
color: #5a3418;
|
||||||
justify-content: center;
|
}
|
||||||
margin: $index-gap-sm 0;
|
|
||||||
padding: 25rpx;
|
|
||||||
border-radius: $index-card-radius;
|
|
||||||
background-color: $text-color-white;
|
|
||||||
box-shadow: $box-shadow;
|
|
||||||
|
|
||||||
&__main {
|
&__divider {
|
||||||
flex: 1;
|
width: 72rpx;
|
||||||
display: flex;
|
height: 4rpx;
|
||||||
flex-direction: column;
|
margin: 16rpx 0 12rpx;
|
||||||
justify-content: center;
|
border-radius: 4rpx;
|
||||||
}
|
background: linear-gradient(90deg, #d4a45a, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
&__header {
|
&__slogan {
|
||||||
display: flex;
|
font-size: 24rpx;
|
||||||
align-items: center;
|
color: #8a6a4a;
|
||||||
}
|
margin-bottom: 28rpx;
|
||||||
|
}
|
||||||
|
|
||||||
&__title {
|
&__features {
|
||||||
margin-right: $index-gap-sm;
|
display: flex;
|
||||||
font-size: $font-size-base;
|
flex-wrap: wrap;
|
||||||
color: $text-color-base;
|
gap: 16rpx 20rpx;
|
||||||
}
|
}
|
||||||
|
|
||||||
&__value {
|
&__feature {
|
||||||
font-size: $index-value-font-size;
|
display: flex;
|
||||||
font-weight: bold;
|
align-items: center;
|
||||||
}
|
gap: 6rpx;
|
||||||
|
}
|
||||||
|
|
||||||
&__desc {
|
&__feature-icon {
|
||||||
display: flex;
|
width: 32rpx;
|
||||||
align-items: center;
|
height: 32rpx;
|
||||||
font-size: $font-size-sm;
|
border-radius: 50%;
|
||||||
color: $text-color-assist;
|
background: rgba(255, 255, 255, 0.55);
|
||||||
}
|
color: #8b5a2b;
|
||||||
|
font-size: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
&__action {
|
&__feature-label {
|
||||||
display: flex;
|
font-size: 20rpx;
|
||||||
align-items: center;
|
color: #7a5a3a;
|
||||||
justify-content: center;
|
}
|
||||||
font-size: $font-size-sm;
|
|
||||||
color: $color-primary;
|
|
||||||
|
|
||||||
&--with-icon {
|
&__brand-right {
|
||||||
flex-direction: column;
|
width: 220rpx;
|
||||||
}
|
display: flex;
|
||||||
}
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
&__action-icon {
|
&__cupcake {
|
||||||
width: $img-size-sm;
|
position: relative;
|
||||||
height: $img-size-sm;
|
width: 140rpx;
|
||||||
margin-bottom: $index-gap-sm;
|
height: 180rpx;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
&__cupcake-cherry {
|
||||||
|
position: absolute;
|
||||||
|
top: 8rpx;
|
||||||
|
left: 58rpx;
|
||||||
|
width: 28rpx;
|
||||||
|
height: 28rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: #e4572e;
|
||||||
|
box-shadow: 0 4rpx 8rpx rgba(180, 40, 20, 0.25);
|
||||||
|
z-index: 4;
|
||||||
|
|
||||||
|
&::after {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: -10rpx;
|
||||||
|
left: 10rpx;
|
||||||
|
width: 4rpx;
|
||||||
|
height: 14rpx;
|
||||||
|
border-radius: 4rpx;
|
||||||
|
background: #3d6b3d;
|
||||||
|
transform: rotate(-20deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__cupcake-frost {
|
||||||
|
position: absolute;
|
||||||
|
top: 28rpx;
|
||||||
|
left: 18rpx;
|
||||||
|
width: 104rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 52rpx 52rpx 40rpx 40rpx;
|
||||||
|
background: linear-gradient(180deg, #fff 0%, #f5f0ea 100%);
|
||||||
|
box-shadow: inset 0 -8rpx 12rpx rgba(200, 180, 160, 0.35);
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__cupcake-body {
|
||||||
|
position: absolute;
|
||||||
|
top: 84rpx;
|
||||||
|
left: 28rpx;
|
||||||
|
width: 84rpx;
|
||||||
|
height: 52rpx;
|
||||||
|
border-radius: 8rpx 8rpx 4rpx 4rpx;
|
||||||
|
background: linear-gradient(180deg, #6b3a22 0%, #4a2414 100%);
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__cupcake-wrap {
|
||||||
|
position: absolute;
|
||||||
|
top: 128rpx;
|
||||||
|
left: 24rpx;
|
||||||
|
width: 92rpx;
|
||||||
|
height: 44rpx;
|
||||||
|
background: repeating-linear-gradient(
|
||||||
|
90deg,
|
||||||
|
#f4e6d4 0 10rpx,
|
||||||
|
#e8d2b8 10rpx 20rpx
|
||||||
|
);
|
||||||
|
clip-path: polygon(8% 0, 92% 0, 100% 100%, 0 100%);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__dots {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 16rpx;
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10rpx;
|
||||||
|
z-index: 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__dot {
|
||||||
|
width: 10rpx;
|
||||||
|
height: 10rpx;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: rgba(255, 255, 255, 0.7);
|
||||||
|
|
||||||
|
&--active {
|
||||||
|
background: $accent-orange;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.index-services {
|
||||||
|
display: flex;
|
||||||
|
gap: 20rpx;
|
||||||
|
margin-bottom: 24rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
.index-service {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 260rpx;
|
||||||
|
padding: 28rpx 24rpx;
|
||||||
|
border-radius: $card-radius;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 8rpx 24rpx rgba(180, 120, 60, 0.08);
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
&__info {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 40rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $text-main;
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__desc {
|
||||||
|
margin-top: 8rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: $text-sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
align-self: flex-start;
|
||||||
|
margin-top: 20rpx;
|
||||||
|
padding: 10rpx 22rpx;
|
||||||
|
border-radius: 999rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: #fff;
|
||||||
|
|
||||||
|
&--orange {
|
||||||
|
background: $accent-orange;
|
||||||
|
}
|
||||||
|
|
||||||
|
&--gold {
|
||||||
|
background: $accent-gold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__img {
|
||||||
|
position: absolute;
|
||||||
|
right: -8rpx;
|
||||||
|
bottom: -8rpx;
|
||||||
|
width: 150rpx;
|
||||||
|
height: 150rpx;
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.index-extras {
|
||||||
|
padding: 8rpx 8rpx 8rpx 4rpx;
|
||||||
|
border-radius: $card-radius;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: 0 8rpx 24rpx rgba(180, 120, 60, 0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.index-extra {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 28rpx 24rpx;
|
||||||
|
border-bottom: 1rpx solid #f3ebe3;
|
||||||
|
|
||||||
|
&--last {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__icon {
|
||||||
|
width: 72rpx;
|
||||||
|
height: 72rpx;
|
||||||
|
border-radius: 18rpx;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-right: 20rpx;
|
||||||
|
|
||||||
|
&--coupon {
|
||||||
|
background: linear-gradient(145deg, #ffb347, #f28c38);
|
||||||
|
}
|
||||||
|
|
||||||
|
&--score {
|
||||||
|
background: linear-gradient(145deg, #ff9a4d, #ff7417);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&__main {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title-row {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 10rpx;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
font-size: 30rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $text-main;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__value {
|
||||||
|
font-size: 34rpx;
|
||||||
|
font-weight: 700;
|
||||||
|
color: $text-main;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__desc {
|
||||||
|
margin-top: 6rpx;
|
||||||
|
font-size: 22rpx;
|
||||||
|
color: $text-sub;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__link {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 12rpx;
|
||||||
|
font-size: 24rpx;
|
||||||
|
color: $accent-orange;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -286,6 +286,9 @@ const newValue = ref([])
|
|||||||
const shopAd = ref('')
|
const shopAd = ref('')
|
||||||
const isCartShow = ref(true)
|
const isCartShow = ref(true)
|
||||||
const popup = ref()
|
const popup = ref()
|
||||||
|
// 点击左侧分类主动滚动时,暂时忽略右侧 scroll 回写,避免高亮回跳到上一项
|
||||||
|
const menuClickLock = ref(false)
|
||||||
|
let menuClickLockTimer = null
|
||||||
|
|
||||||
const measureMenuLayout = () => {
|
const measureMenuLayout = () => {
|
||||||
}
|
}
|
||||||
@@ -529,19 +532,32 @@ const handleMenuTap = (id) => { //点击菜单项事件
|
|||||||
calcSize()
|
calcSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
menuClickLock.value = true
|
||||||
|
if (menuClickLockTimer) clearTimeout(menuClickLockTimer)
|
||||||
currentCateId.value = id
|
currentCateId.value = id
|
||||||
nextTick(() => cateScrollTop.value = filteredGoods.value.find(item => item.id == id)?.top || 0)
|
menuScrollIntoView.value = `menu-${id}`
|
||||||
|
const targetTop = filteredGoods.value.find(item => item.id == id)?.top || 0
|
||||||
|
nextTick(() => {
|
||||||
|
// 同一 scroll-top 重复赋值不会触发滚动,做微小偏移确保生效
|
||||||
|
cateScrollTop.value = cateScrollTop.value === targetTop ? targetTop + 0.01 : targetTop
|
||||||
|
})
|
||||||
|
// scroll-with-animation 期间屏蔽 scroll 回写,动画结束后再放开
|
||||||
|
menuClickLockTimer = setTimeout(() => {
|
||||||
|
menuClickLock.value = false
|
||||||
|
menuClickLockTimer = null
|
||||||
|
}, 400)
|
||||||
}
|
}
|
||||||
const handleGoodsScroll = ({ detail }) => { //商品列表滚动事件
|
const handleGoodsScroll = ({ detail }) => { //商品列表滚动事件
|
||||||
|
if (menuClickLock.value) return
|
||||||
if (!sizeCalcState.value) {
|
if (!sizeCalcState.value) {
|
||||||
calcSize()
|
calcSize()
|
||||||
}
|
}
|
||||||
console.log('scrollTop:',detail)
|
|
||||||
const {
|
const {
|
||||||
scrollTop
|
scrollTop
|
||||||
} = detail
|
} = detail
|
||||||
let tabs = filteredGoods.value.filter(item => item.top <= scrollTop).reverse()
|
// 加一点容差,避免刚好停在分类顶部时因浮点误差高亮到上一项
|
||||||
if (tabs.length > 0) {
|
const tabs = filteredGoods.value.filter(item => item.top <= scrollTop + 2).reverse()
|
||||||
|
if (tabs.length > 0 && tabs[0].id !== currentCateId.value) {
|
||||||
currentCateId.value = tabs[0].id
|
currentCateId.value = tabs[0].id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in new issue
Block a user