修改样式
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
<!-- 第一行:自动缓慢滚动 + 可手动滑动 -->
|
||||
<view class="scroll-row first-row">
|
||||
<scroll-view
|
||||
class="ab-scroll mb-22rpx"
|
||||
class="ab-scroll mb-10rpx"
|
||||
scroll-x
|
||||
show-scrollbar="false"
|
||||
:scroll-left="scrollLeft1"
|
||||
@@ -77,6 +77,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref, onMounted, onUnmounted, nextTick } from 'vue'
|
||||
import { useCategoryNavStore } from '@/store'
|
||||
|
||||
// 定义分类项接口(与模板字段一致)
|
||||
interface CategoryItem {
|
||||
@@ -97,6 +98,8 @@ const props = withDefaults(defineProps<Props>(), {
|
||||
categories: () => []
|
||||
})
|
||||
|
||||
const categoryNavStore = useCategoryNavStore()
|
||||
|
||||
// 定义事件
|
||||
const emit = defineEmits<{
|
||||
/** 点击分类项事件 */
|
||||
@@ -241,10 +244,11 @@ function onScroll2(e: any) {
|
||||
}
|
||||
}
|
||||
|
||||
// 点击处理
|
||||
// 点击处理(列表页菜谱 id 来自 store,不放在 URL query)
|
||||
const handleItemClick = (item: CategoryItem) => {
|
||||
emit('itemClick', item)
|
||||
navigateTo('/pages-store/pages/list/index?id=' + item.id)
|
||||
categoryNavStore.setPendingRecipeCategoryId(item.id)
|
||||
navigateTo('/pages-store/pages/list/index')
|
||||
}
|
||||
|
||||
function navigateTo(url: string) {
|
||||
@@ -301,14 +305,16 @@ onUnmounted(() => {
|
||||
min-width: 120rpx;
|
||||
height: 60rpx;
|
||||
padding: 0 20rpx;
|
||||
border: 1px solid #C8C8C8;
|
||||
background: #fff;
|
||||
border: none;
|
||||
border-radius: 30rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
cursor: pointer;
|
||||
transition: all 0.2s ease;
|
||||
flex-shrink: 0;
|
||||
|
||||
&:active {
|
||||
transform: translateY(0) scale(0.95);
|
||||
transform: translateY(0) scale(0.96);
|
||||
}
|
||||
|
||||
.category-icon {
|
||||
|
||||
@@ -1,40 +1,277 @@
|
||||
<script setup lang="ts">
|
||||
import {thumbnailImg} from "@/utils/utils";
|
||||
import { thumbnailImg } from '@/utils/utils'
|
||||
|
||||
const props = defineProps<{
|
||||
list: any[];
|
||||
}>();
|
||||
const { t } = useI18n();
|
||||
list: any[]
|
||||
}>()
|
||||
const { t } = useI18n()
|
||||
|
||||
function handleClickFood(item: any) {
|
||||
uni.navigateTo({
|
||||
url: '/pages-store/pages/store/index?id=' + item.id
|
||||
url: '/pages-store/pages/store/index?id=' + item.id,
|
||||
})
|
||||
}
|
||||
|
||||
function getCardImages(item: any): string[] {
|
||||
const raw = item?.shopImages
|
||||
let urls: string[] = []
|
||||
if (raw && typeof raw === 'string') {
|
||||
urls = raw
|
||||
.split(',')
|
||||
.map((s: string) => s.trim())
|
||||
.filter(Boolean)
|
||||
.map((u: string) => thumbnailImg(u) || u)
|
||||
}
|
||||
if (urls.length === 0 && item?.logo) {
|
||||
const logo = thumbnailImg(item.logo) || item.logo
|
||||
urls = logo ? [logo] : []
|
||||
}
|
||||
return urls
|
||||
}
|
||||
|
||||
function getTitleLines(item: any): { line1: string; line2: string } {
|
||||
const en = item?.merchantCategoryNamesEn?.[0]
|
||||
const zh = item?.merchantCategoryNamesZh?.[0]
|
||||
const name = String(item?.merchantName || '').trim()
|
||||
if (en && zh) return { line1: String(en), line2: String(zh) }
|
||||
if (en && !zh) return { line1: String(en), line2: name && name !== String(en) ? name : '' }
|
||||
if (zh && !en) return { line1: String(zh), line2: name && name !== String(zh) ? name : '' }
|
||||
const parts = name.split(/\n|\r|\||/).map((s) => s.trim()).filter(Boolean)
|
||||
if (parts.length >= 2) return { line1: parts[0], line2: parts[1] }
|
||||
return { line1: name, line2: '' }
|
||||
}
|
||||
|
||||
function formatMerchantRating(item: any): string {
|
||||
const r = Number(item?.rating)
|
||||
if (Number.isFinite(r) && r > 0) return r.toFixed(1)
|
||||
return '5.0'
|
||||
}
|
||||
|
||||
function subtitleLine(item: any): string {
|
||||
const comments = item?.commentCount ?? 0
|
||||
const dt = item?.deliveryTime
|
||||
if (dt === undefined || dt === null || dt === '') {
|
||||
return `(${comments})`
|
||||
}
|
||||
const n = Number(dt)
|
||||
if (Number.isFinite(n) && n > 0) {
|
||||
const unit = n === 1 ? t('common.day') : t('common.days')
|
||||
return `(${comments}) · ${n}${unit}`
|
||||
}
|
||||
return `(${comments}) · ${dt}`
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<scroll-view scroll-x="true">
|
||||
<view class="flex">
|
||||
<view class="w-30rpx shrink-0"></view>
|
||||
<template v-for="(item, index) in list" :key="item?.id ?? index">
|
||||
<view @click="handleClickFood(item)" :class="[index === 0 ? '' : 'ml-28rpx']">
|
||||
<image :src="thumbnailImg(item?.shopImages?.split(',')[0])" class="w-448rpx h-252rpx rounded-24rpx mb-20rpx bg-common" mode="aspectFill"></image>
|
||||
<text class="text-30rpx lh-30rpx text-#333 font-500 line-clamp-1">{{ item?.merchantName }}</text>
|
||||
<view v-if="+item.deliveryService === 1" class="text-#CE7138 text-24rpx lh-24rpx mt-12rpx">
|
||||
<scroll-view class="featured-scroll" scroll-x enable-flex :show-scrollbar="false">
|
||||
<view class="featured-track">
|
||||
<view class="featured-track__pad" />
|
||||
<view
|
||||
v-for="(item, index) in list"
|
||||
:key="item?.id ?? index"
|
||||
class="featured-card"
|
||||
:class="{ 'featured-card--first': index === 0 }"
|
||||
@click="handleClickFood(item)"
|
||||
>
|
||||
<!-- 左侧图:单图或与示例一致的双图上下分栏 -->
|
||||
<view class="featured-card__media">
|
||||
<template v-if="getCardImages(item).length >= 2">
|
||||
<image
|
||||
:src="getCardImages(item)[0]"
|
||||
class="featured-card__media-half featured-card__media-half--top"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<image
|
||||
:src="getCardImages(item)[1]"
|
||||
class="featured-card__media-half featured-card__media-half--bottom"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
</template>
|
||||
<image
|
||||
v-else-if="getCardImages(item).length >= 1"
|
||||
:src="getCardImages(item)[0]"
|
||||
class="featured-card__media-single"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view v-else class="featured-card__media-single featured-card__media-placeholder" />
|
||||
</view>
|
||||
|
||||
<view class="featured-card__body">
|
||||
<view class="featured-card__titles">
|
||||
<text v-if="getTitleLines(item).line1" class="featured-card__name featured-card__name--primary">{{
|
||||
getTitleLines(item).line1
|
||||
}}</text>
|
||||
<text v-if="getTitleLines(item).line2" class="featured-card__name featured-card__name--secondary">{{
|
||||
getTitleLines(item).line2
|
||||
}}</text>
|
||||
</view>
|
||||
|
||||
<view
|
||||
v-if="+item.deliveryService === 1"
|
||||
class="featured-card__fee"
|
||||
>
|
||||
{{ t('pages-store.store.tips5') }} ${{ item.deliveryFee }}{{ t('pages-store.store.start') }}
|
||||
</view>
|
||||
<view class="text-24rpx lh-24rpx flex items-center mt-12rpx">
|
||||
<text class="text-#333 font-500">{{ item.rating }}</text>
|
||||
<image src="@img/chef/124.png" class="w-24rpx h-24rpx mx-4rpx mt-2rpx"></image>
|
||||
<text class="text-#7D7D7D">({{ item.commentCount }}) • {{ item.deliveryTime }} {{ Number(item.deliveryTime) === 1 ? t('common.day') : t('common.days') }}</text>
|
||||
|
||||
<view class="featured-card__rating">
|
||||
<text class="featured-card__stars">★★★★★</text>
|
||||
<text class="featured-card__rate-num">{{ formatMerchantRating(item) }}</text>
|
||||
</view>
|
||||
|
||||
<text class="featured-card__sub">{{ subtitleLine(item) }}</text>
|
||||
|
||||
<view class="featured-card__arrow center">
|
||||
<view class="i-carbon:chevron-right text-32rpx text-white"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<view class="w-30rpx shrink-0 op-0">1</view>
|
||||
</view>
|
||||
<view class="featured-track__pad featured-track__pad--end" />
|
||||
</view>
|
||||
</scroll-view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.featured-scroll {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
.featured-track {
|
||||
display: flex;
|
||||
align-items: stretch;
|
||||
padding-bottom: 4rpx;
|
||||
}
|
||||
|
||||
.featured-track__pad {
|
||||
flex-shrink: 0;
|
||||
width: 6rpx;
|
||||
}
|
||||
.featured-track__pad--end {
|
||||
width: 24rpx;
|
||||
}
|
||||
|
||||
.featured-card {
|
||||
flex-shrink: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 620rpx;
|
||||
min-height: 256rpx;
|
||||
margin-left: 16rpx;
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.featured-card--first {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.featured-card__media {
|
||||
width: 232rpx;
|
||||
flex-shrink: 0;
|
||||
background: #f0f0f0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.featured-card__media-single {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-height: 256rpx;
|
||||
}
|
||||
|
||||
.featured-card__media-half {
|
||||
width: 100%;
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
.featured-card__media-half--top {
|
||||
border-bottom: 3rpx solid #fff;
|
||||
}
|
||||
|
||||
.featured-card__body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
padding: 20rpx 20rpx 18rpx 20rpx;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.featured-card__titles {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6rpx;
|
||||
}
|
||||
|
||||
.featured-card__name {
|
||||
font-size: 28rpx;
|
||||
line-height: 34rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
.featured-card__name--primary {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.featured-card__name--secondary {
|
||||
font-size: 28rpx;
|
||||
line-height: 34rpx;
|
||||
color: #1a1a1a;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.featured-card__media-placeholder {
|
||||
min-height: 256rpx;
|
||||
background: #e8e8e8;
|
||||
}
|
||||
|
||||
.featured-card__fee {
|
||||
margin-top: 10rpx;
|
||||
font-size: 24rpx;
|
||||
line-height: 30rpx;
|
||||
font-weight: 500;
|
||||
color: #d48806;
|
||||
}
|
||||
|
||||
.featured-card__rating {
|
||||
margin-top: 14rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.featured-card__stars {
|
||||
font-size: 22rpx;
|
||||
line-height: 1;
|
||||
color: #1a1a1a;
|
||||
letter-spacing: 2rpx;
|
||||
}
|
||||
|
||||
.featured-card__rate-num {
|
||||
font-size: 26rpx;
|
||||
line-height: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #1a1a1a;
|
||||
}
|
||||
|
||||
.featured-card__sub {
|
||||
margin-top: 8rpx;
|
||||
font-size: 22rpx;
|
||||
line-height: 28rpx;
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.featured-card__arrow {
|
||||
position: absolute;
|
||||
right: 16rpx;
|
||||
bottom: 16rpx;
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 50%;
|
||||
background: #14181b;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -61,11 +61,16 @@ function handleCollectionChange(value: boolean) {
|
||||
</script>
|
||||
<template>
|
||||
<view @click="handleClickFood" class="mb-52rpx">
|
||||
<image
|
||||
:src="item?.dishImage?.split(',')[0]||item?.logo"
|
||||
mode="aspectFill"
|
||||
class="w-100% h-400rpx rounded-24rpx bg-common"
|
||||
></image>
|
||||
<view class="food-box-img-wrap">
|
||||
<view v-if="item.isNew == 1" class="dish-new-ribbon">
|
||||
<text class="dish-new-ribbon__text">NEW</text>
|
||||
</view>
|
||||
<image
|
||||
:src="item?.dishImage?.split(',')[0]||item?.logo"
|
||||
mode="aspectFill"
|
||||
class="w-100% h-400rpx rounded-24rpx bg-common"
|
||||
></image>
|
||||
</view>
|
||||
<view class="flex justify-between items-start mt-14rpx">
|
||||
<view>
|
||||
<text class="text-30rpx lh-30rpx text-#333 font-500 line-clamp-1"
|
||||
@@ -86,3 +91,37 @@ function handleCollectionChange(value: boolean) {
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.food-box-img-wrap {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 24rpx;
|
||||
}
|
||||
|
||||
.dish-new-ribbon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 184rpx;
|
||||
height: 184rpx;
|
||||
overflow: hidden;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
|
||||
&__text {
|
||||
position: absolute;
|
||||
top: 26rpx;
|
||||
left: -66rpx;
|
||||
width: 240rpx;
|
||||
text-align: center;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
letter-spacing: 2rpx;
|
||||
line-height: 44rpx;
|
||||
background: #E23636;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<script setup lang="ts">
|
||||
import { useUserStore } from "@/store";
|
||||
const props = withDefaults(
|
||||
defineProps<{
|
||||
/** 首页顶栏紧凑模式:更小图标与间距 */
|
||||
compact?: boolean
|
||||
}>(),
|
||||
{ compact: false }
|
||||
)
|
||||
const emit = defineEmits(['toggleNotOpen']);
|
||||
const userStore = useUserStore();
|
||||
function navigateTo(url: string) {
|
||||
@@ -12,12 +19,25 @@ function navigateTo(url: string) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view class="flex items-center">
|
||||
<view @click="navigateTo('/pages-user/pages/message/index')" class="w-40rpx h-40rpx mr-42rpx relative">
|
||||
<view v-if="userStore.isLogin && userStore.unreadMessageCount > 0" class="w-32rpx h-32rpx bg-#E23636 absolute z-2 top--16rpx right--16rpx rounded-50% text-24rpx text-#fff text-center line-height-32rpx">{{ userStore.unreadMessageCount }}</view>
|
||||
<image src="@img/chef/114.png" class="w-40rpx h-40rpx"></image>
|
||||
<view class="flex items-center" :class="compact ? 'gap-20rpx' : ''">
|
||||
<view
|
||||
@click="navigateTo('/pages-user/pages/message/index')"
|
||||
:class="compact ? 'w-34rpx h-34rpx mr-0' : 'w-40rpx h-40rpx mr-42rpx'"
|
||||
class="relative shrink-0"
|
||||
>
|
||||
<view
|
||||
v-if="userStore.isLogin && userStore.unreadMessageCount > 0"
|
||||
:class="compact ? 'h-26rpx top--10rpx right--10rpx text-20rpx px-8rpx' : 'w-32rpx h-32rpx top--16rpx right--16rpx text-24rpx line-height-32rpx'"
|
||||
class="bg-#E23636 absolute z-2 rounded-50% text-#fff text-center font-500"
|
||||
>{{ userStore.unreadMessageCount }}</view>
|
||||
<image src="@img/chef/114.png" :class="compact ? 'w-34rpx h-34rpx' : 'w-40rpx h-40rpx'"></image>
|
||||
</view>
|
||||
<image @click="emit('toggleNotOpen')" src="@img/chef/115.png" class="w-40rpx h-40rpx"></image>
|
||||
<image
|
||||
@click="emit('toggleNotOpen')"
|
||||
src="@img/chef/115.png"
|
||||
:class="compact ? 'w-34rpx h-34rpx' : 'w-40rpx h-40rpx'"
|
||||
class="shrink-0"
|
||||
></image>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
|
||||
@@ -23,12 +23,22 @@ function handleClickSearch() {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<view @click="handleClickSearch" class="flex items-center h-88rpx bg-#F2F3F6 rounded-44rpx pl-36rpx">
|
||||
<image src="@img/chef/100222.png" class="w-28rpx h-28rpx"></image>
|
||||
<text class="text-30rpx text-#434343 ml-16rpx tracking-[.04em] font-500">{{ t('components.search.placeholder') }}</text>
|
||||
</view>
|
||||
<view
|
||||
@click="handleClickSearch"
|
||||
class="home-search-bar flex items-center h-88rpx rounded-44rpx pl-36rpx pr-28rpx bg-white"
|
||||
>
|
||||
<image src="@img/chef/100222.png" class="w-28rpx h-28rpx shrink-0"></image>
|
||||
<text class="home-search-placeholder text-28rpx ml-16rpx tracking-[.04em] font-500 truncate">{{
|
||||
t('components.search.placeholder')
|
||||
}}</text>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.home-search-bar {
|
||||
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
.home-search-placeholder {
|
||||
color: #9a9a9a;
|
||||
}
|
||||
</style>
|
||||
@@ -75,8 +75,11 @@ function selectTab(item: any) {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1), box-shadow 0.2s;
|
||||
width: 132rpx;
|
||||
height: 132rpx;
|
||||
width: 102rpx;
|
||||
height: 102rpx;
|
||||
border-radius: 50%;
|
||||
background: #fff;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.07);
|
||||
}
|
||||
.img-selected {
|
||||
border: 4rpx solid #ce7138;
|
||||
@@ -86,8 +89,8 @@ function selectTab(item: any) {
|
||||
}
|
||||
|
||||
.tab-img {
|
||||
width: 112rpx;
|
||||
height: 112rpx;
|
||||
width: 98rpx;
|
||||
height: 98rpx;
|
||||
border-radius: 50%;
|
||||
transition: transform 0.2s cubic-bezier(0.4, 0, 0.2, 1);
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
} from "@/service";
|
||||
import usePage from "@/hooks/usePage";
|
||||
import {getFeaturedDishList} from "@/pages-store/service";
|
||||
import { formatSalesCount } from "@/utils/utils";
|
||||
const configStore = useConfigStore();
|
||||
const userStore = useUserStore();
|
||||
const props = defineProps<{
|
||||
@@ -41,6 +42,12 @@ function isSoldOutStock(stockLike: unknown) {
|
||||
return !Number.isNaN(n) && n <= 0
|
||||
}
|
||||
|
||||
/** 底部营销条文案(接口若返回 marketingLabel / hotSaleTag 等则展示) */
|
||||
function getDishPromoLabel(item: Record<string, unknown>): string {
|
||||
const raw = item.marketingLabel ?? item.hotSaleTag ?? item.rankTag ?? item.promotionLabel
|
||||
return typeof raw === 'string' && raw.trim() ? raw.trim() : ''
|
||||
}
|
||||
|
||||
function navigateTo(url: string) {
|
||||
if(userStore.checkLogin()) {
|
||||
uni.navigateTo({
|
||||
@@ -209,6 +216,30 @@ const isShowMerchant = computed(()=> {
|
||||
}
|
||||
})
|
||||
|
||||
// 精选菜品瀑布流:按序均分到两列(0,2,4… / 1,3,5…),分页追加后仍交错排列
|
||||
const featuredDishColumns = computed(() => {
|
||||
const list = dataList.value
|
||||
return [
|
||||
list.filter((_, i) => i % 2 === 0),
|
||||
list.filter((_, i) => i % 2 === 1),
|
||||
]
|
||||
})
|
||||
|
||||
/** 顶栏购物车角标(多商家购物车汇总件数) */
|
||||
const cartBadgeTotal = computed(() => {
|
||||
const list = userStore.userCartAllData
|
||||
if (!Array.isArray(list) || list.length === 0) return 0
|
||||
let n = 0
|
||||
for (const m of list) {
|
||||
n += (m as { merchantCartVoList?: unknown[] })?.merchantCartVoList?.length || 0
|
||||
}
|
||||
return n
|
||||
})
|
||||
|
||||
function goCart() {
|
||||
navigateTo('/pages-user/pages/cart/index')
|
||||
}
|
||||
|
||||
// 手动触发下拉刷新了
|
||||
function onRefresh() {
|
||||
console.log('手动触发下拉刷新了')
|
||||
@@ -221,7 +252,7 @@ function handleClickSwiper(item: any) {
|
||||
console.log(item, '点击轮播图')
|
||||
switch (Number(item.activityType)) {
|
||||
case 1: // 商家列表
|
||||
navigateTo('/pages-store/pages/list/index?id=')
|
||||
navigateTo('/pages-store/pages/list/index')
|
||||
break
|
||||
case 2: // 活动菜品列表
|
||||
navigateTo('/pages-store/pages/dishes/index?id=' + item.id)
|
||||
@@ -261,7 +292,7 @@ const debouncedEmit = debounce(1300, (isCollected: boolean, id: string, type: Co
|
||||
|
||||
<template>
|
||||
<view
|
||||
class="bg-#fff"
|
||||
class="home-page-root"
|
||||
:style="[
|
||||
{
|
||||
height: configStore.windowHeight + 'px',
|
||||
@@ -271,20 +302,34 @@ const debouncedEmit = debounce(1300, (isCollected: boolean, id: string, type: Co
|
||||
<z-paging @onRefresh="onRefresh" ref="paging" v-model="dataList" :auto="false" @query="queryList" @scroll="onPageScroll" :refresher-enabled="true" :auto-show-back-to-top="false">
|
||||
<template #top>
|
||||
<status-bar />
|
||||
<view class="flex items-center pt-18rpx px-30rpx pb-20rpx">
|
||||
<!-- <text class="text-52rpx lh-52rpx text-#333 font-bold shrink-0">{{Config.appName}}</text>-->
|
||||
<image
|
||||
src="@img/logo.png"
|
||||
class="w-52rpx h-52rpx shrink-0"
|
||||
></image>
|
||||
<view class="bg-#D8D8D8 w-1rpx h-40rpx mx-14rpx"></view>
|
||||
<view @click="navigateTo('/pages/address/index')" class="text-#00A76D text-28rpx lh-28rpx flex items-center">
|
||||
<text v-if="userStore.appointmentTimeShow">{{ t('pages.address.appTime') }}:{{ userStore.appointmentTimeShow }}</text>
|
||||
<text v-else>{{ t('pages.address.reservation') }}</text>
|
||||
<image
|
||||
src="@img/chef/119.png"
|
||||
class="w-24rpx h-24rpx ml-6rpx mt-4rpx shrink-0"
|
||||
></image>
|
||||
<!-- 设计稿:品牌行 + 右侧地址胶囊、消息/客服、购物车 -->
|
||||
<view class="home-top-header px-24rpx pt-12rpx pb-8rpx">
|
||||
<view class="flex items-center justify-between gap-12rpx">
|
||||
<view class="flex items-center gap-14rpx min-w-0 flex-1">
|
||||
<image src="@img/logo.png" class="w-52rpx h-52rpx shrink-0" style="border-radius: 50%;"></image>
|
||||
<text class="text-32rpx lh-36rpx text-#1a1a1a font-bold tracking-tight shrink-0">{{ Config.appName }}</text>
|
||||
</view>
|
||||
<view class="flex items-center gap-10rpx shrink-0">
|
||||
<view class="home-loc-pill" @click="navigateTo('/pages-user/pages/search-address/index')">
|
||||
<!-- <image src="@img/chef/101.png" class="home-loc-pill__pin w-22rpx h-22rpx shrink-0"></image> -->
|
||||
<text class="home-loc-pill__text line-clamp-1">{{
|
||||
userStore.userLocation.location || t('pages.home.default-location')
|
||||
}}</text>
|
||||
<image src="@img/chef/119.png" class="home-loc-pill__arrow w-20rpx h-20rpx shrink-0 op-50 mt-2rpx"></image>
|
||||
</view>
|
||||
<view class="home-cart-btn" @click="goCart">
|
||||
<view class="i-carbon:shopping-cart text-36rpx text-#14181b"></view>
|
||||
<view v-if="userStore.isLogin && cartBadgeTotal > 0" class="home-cart-badge">{{ cartBadgeTotal > 99 ? '99+' : cartBadgeTotal }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="home-delivery-actions-row mt-14rpx flex items-center justify-between gap-16rpx">
|
||||
<view @click="navigateTo('/pages/address/index')" class="home-delivery-row flex items-center min-w-0 flex-1 text-26rpx lh-32rpx text-#00A76D">
|
||||
<text v-if="userStore.appointmentTimeShow">{{ t('pages.address.appTime') }}: {{ userStore.appointmentTimeShow }}</text>
|
||||
<text v-else>{{ t('pages.address.reservation') }}</text>
|
||||
<image src="@img/chef/119.png" class="w-22rpx h-22rpx ml-8rpx shrink-0"></image>
|
||||
</view>
|
||||
<msg-box compact class="shrink-0" @toggleNotOpen="toggleNotOpen" />
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
@@ -294,169 +339,415 @@ const debouncedEmit = debounce(1300, (isCollected: boolean, id: string, type: Co
|
||||
>
|
||||
<home-skeleton />
|
||||
</view>
|
||||
<view class="flex-center-sb px-30rpx pt-34rpx">
|
||||
<!--展示用户的定位城市,如果用户没有使用定位则展示选择的城市,用户选择城市后,需要更新定位城市-->
|
||||
<view @click="navigateTo('/pages-user/pages/search-address/index')" class="flex items-center text-30rpx text-#333 font-500">
|
||||
<text class="line-clamp-1">
|
||||
{{ userStore.userLocation.location || t('pages.home.default-location') }}
|
||||
</text>
|
||||
<image
|
||||
src="@img/chef/101.png"
|
||||
class="w-24rpx h-24rpx ml-10rpx mt-6rpx shrink-0"
|
||||
></image>
|
||||
</view>
|
||||
<view class="shrink-0 ml-40rpx">
|
||||
<msg-box @toggleNotOpen="toggleNotOpen" />
|
||||
</view>
|
||||
</view>
|
||||
<view class="px-30rpx mt-32rpx pb-22rpx">
|
||||
<view class="px-24rpx pt-12rpx pb-8rpx">
|
||||
<search />
|
||||
<!-- 分类滚动区域 -->
|
||||
<view class="mt-40rpx" v-if="appMerchantLabelList.length > 0">
|
||||
<!-- 分类标签(双行横滑) -->
|
||||
<view class="mt-28rpx" v-if="appMerchantLabelList.length > 0">
|
||||
<class-bullet :categories="appMerchantLabelList" @itemClick="handleItemClick" />
|
||||
</view>
|
||||
</view>
|
||||
<swiper
|
||||
class="card-swiper"
|
||||
class="home-promo-swiper card-swiper"
|
||||
:circular="true"
|
||||
:autoplay="true"
|
||||
previous-margin="60rpx"
|
||||
next-margin="60rpx"
|
||||
previous-margin="48rpx"
|
||||
next-margin="48rpx"
|
||||
>
|
||||
<template v-for="item in swiperList" :key="item.id">
|
||||
<swiper-item @click="handleClickSwiper(item)" class="">
|
||||
<image
|
||||
:src="item.activityImage"
|
||||
class="swiper-item-content w-full h-100% rounded-24rpx bg-common"
|
||||
></image>
|
||||
</swiper-item>
|
||||
</template>
|
||||
<swiper-item
|
||||
v-for="(item, sIdx) in swiperList"
|
||||
:key="item.id ?? sIdx"
|
||||
@click="handleClickSwiper(item)"
|
||||
>
|
||||
<image
|
||||
:src="item.activityImage"
|
||||
class="swiper-item-content w-full h-100% rounded-32rpx bg-common"
|
||||
></image>
|
||||
</swiper-item>
|
||||
</swiper>
|
||||
|
||||
<!-- 分类滚动区域 -->
|
||||
<tabs-type @changeType="tabsTypeChange" v-if="appMerchantCategoryList.length > 0" :list="appMerchantCategoryList" :currentId="currentCategory" class="mt-22rpx" />
|
||||
<!-- 快捷入口(圆形分类) -->
|
||||
<tabs-type @changeType="tabsTypeChange" v-if="appMerchantCategoryList.length > 0" :list="appMerchantCategoryList" :currentId="currentCategory" class="mt-28rpx home-tabs-quick" />
|
||||
|
||||
<!-- 筛选工具 -->
|
||||
<!-- <filtrate-tool class="mt-32rpx" @togglePickup="togglePickup" @toggleDiscount="toggleDiscount" @toggleScore="toggleScore" @togglePrice="togglePrice" />-->
|
||||
|
||||
<view class="animate-in fade-in animate-ease-in animate-duration-300" v-if="isShowMerchant">
|
||||
<!-- Featured on ChefLink 精选商家 -->
|
||||
<view v-if="featuredList.length > 0" class="mt-56rpx">
|
||||
<view
|
||||
class="mb-30rpx pl-30rpx text-36rpx lh-36rpx text-#333 font-bold"
|
||||
>{{ t('pages.home.featured-on') }}</view>
|
||||
<!-- Featured on ChefLink 精选商家(浅底 + 横向卡片,对齐设计稿) -->
|
||||
<view v-if="featuredList.length > 0" class="featured-merchants-section mt-36rpx px-24rpx pt-8rpx pb-16rpx">
|
||||
<view class="mb-24rpx px-6rpx text-32rpx lh-44rpx text-#1a1a1a">
|
||||
{{ t('pages.home.featured-on') }}
|
||||
</view>
|
||||
<featured-on :list="featuredList" />
|
||||
</view>
|
||||
|
||||
<!-- Nearby Merchants 附近商家 -->
|
||||
<view v-if="nearbyList.length > 0" class="mt-56rpx">
|
||||
<view
|
||||
class="mb-32rpx pl-30rpx text-36rpx lh-36rpx text-#333 font-bold"
|
||||
>{{ t('pages.home.nearby-merchants') }}</view>
|
||||
<view v-if="nearbyList.length > 0" class="nearby-merchants-block mt-36rpx px-24rpx pb-16rpx">
|
||||
<view class="mb-24rpx px-6rpx text-32rpx lh-44rpx text-#1a1a1a ">
|
||||
{{ t('pages.home.nearby-merchants') }}
|
||||
</view>
|
||||
<nearby-merchants :list="nearbyList" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- List -->
|
||||
<view class="mt-56rpx px-30rpx">
|
||||
<view class="mb-32rpx text-36rpx lh-36rpx text-#333 font-bold"
|
||||
<!-- List 精选菜品瀑布流(浅底 + 白卡片 + 阴影,结构对齐设计稿) -->
|
||||
<view class="featured-dishes-section mt-36rpx px-24rpx pb-40rpx">
|
||||
<view class="mb-24rpx px-6rpx text-32rpx lh-44rpx text-#1a1a1a "
|
||||
>{{ t('pages.home.featured-dishes') }}</view>
|
||||
<template v-for="(item, index) in dataList" :key="index">
|
||||
<view @click="navigateToDishes(item)" class="w-100% mb-30rpx">
|
||||
<view class="relative h-448rpx rounded-24rpx mb-28rpx">
|
||||
<view @click.stop="handleDishCollectionClick(item)" class="w-68rpx h-68rpx absolute z-2 top-0 right-0">
|
||||
<view class="waterfall-row flex gap-16rpx items-start">
|
||||
<view
|
||||
v-for="(col, colIndex) in featuredDishColumns"
|
||||
:key="colIndex"
|
||||
class="waterfall-col flex-1 min-w-0 flex flex-col gap-16rpx"
|
||||
>
|
||||
<view
|
||||
v-for="item in col"
|
||||
:key="item.id || String(item.merchantId) + '-' + item.dishName"
|
||||
@click="navigateToDishes(item)"
|
||||
class="featured-dish-card w-full"
|
||||
>
|
||||
<view class="featured-dish-image">
|
||||
<view v-if="item.isNew == 1" class="dish-new-ribbon">
|
||||
<text class="dish-new-ribbon__text">NEW</text>
|
||||
</view>
|
||||
<image
|
||||
v-if="!item.isCollect"
|
||||
src="@img-store/1334.png"
|
||||
:src="item?.dishImage?.split(',')[0]"
|
||||
mode="aspectFill"
|
||||
class="w-full h-full"
|
||||
class="featured-dish-img"
|
||||
/>
|
||||
<view
|
||||
v-if="isSoldOutStock(item?.stock)"
|
||||
class="featured-dish-sold-dim"
|
||||
/>
|
||||
<image
|
||||
v-else
|
||||
src="@img-store/1337.png"
|
||||
mode="aspectFill"
|
||||
class="w-full h-full"
|
||||
/>
|
||||
</view>
|
||||
<view
|
||||
v-if="isSoldOutStock(item?.stock)"
|
||||
class="absolute z-2 left-20rpx top-20rpx px-16rpx h-52rpx rounded-26rpx bg-#14181B/70 center text-26rpx text-#fff font-500"
|
||||
>
|
||||
已售完
|
||||
</view>
|
||||
<image
|
||||
:src="item?.dishImage?.split(',')[0]"
|
||||
v-if="isSoldOutStock(item?.stock)"
|
||||
src="/static/app/images/SoldOut.png"
|
||||
mode="aspectFill"
|
||||
class="w-full h-full rounded-24rpx bg-common"
|
||||
/>
|
||||
</view>
|
||||
<view class="line-clamp-1 text-30rpx text-#333 font-500">
|
||||
{{ item?.dishName }}
|
||||
</view>
|
||||
<view class="flex-center-sb mt-12rpx">
|
||||
<text class="text-32rpx lh-30rpx text-#333 font-500">US${{ item?.discountPrice }}</text>
|
||||
<view
|
||||
v-if="Number(item?.memberPrice) > 0"
|
||||
class="member-price-tag text-[#FBE3C3] font-500 text-30rpx lh-30rpx center pl-6rpx break-all"
|
||||
>
|
||||
<text>{{ t('pages-store.store.members') }}: </text>
|
||||
${{ item?.memberPrice }}
|
||||
class="featured-dish-sold-overlay"
|
||||
/>
|
||||
<view
|
||||
@click.stop="handleDishCollectionClick(item)"
|
||||
class="featured-dish-collect w-56rpx h-56rpx absolute z-4 top-12rpx right-12rpx center"
|
||||
>
|
||||
<image
|
||||
v-if="!item.isCollect"
|
||||
src="@img-store/1334.png"
|
||||
mode="aspectFill"
|
||||
class="w-44rpx h-44rpx featured-dish-collect-icon"
|
||||
/>
|
||||
<image
|
||||
v-else
|
||||
src="@img-store/1337.png"
|
||||
mode="aspectFill"
|
||||
class="w-44rpx h-44rpx featured-dish-collect-icon"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="flex-center-sb mt-12rpx">
|
||||
<view class="text-28rpx text-#999">
|
||||
<view class="line-through">US${{ item?.originalPrice }}</view>
|
||||
<view>{{ t('pages-store.store.sales') }}:{{ item?.salesCount }}</view>
|
||||
</view>
|
||||
|
||||
<view class="center w-64rpx h-64rpx rounded-50% bg-white shadow-lg">
|
||||
<image
|
||||
src="@img/chef/1285.png"
|
||||
class="w-30rpx h-30rpx shrink-0"
|
||||
></image>
|
||||
<view class="featured-dish-body">
|
||||
<view class="featured-dish-meta flex items-start justify-between gap-12rpx mb-14rpx">
|
||||
<view class="min-w-0 flex-1">
|
||||
<text class="featured-dish-price">US${{ item?.discountPrice }}</text>
|
||||
<text
|
||||
v-if="Number(item?.originalPrice) > Number(item?.discountPrice)"
|
||||
class="featured-dish-original"
|
||||
>US${{ item?.originalPrice }}</text>
|
||||
</view>
|
||||
<text class="featured-dish-sales shrink-0">{{ t('pages-store.store.sales') }}: {{ formatSalesCount(item?.salesCount) }}</text>
|
||||
</view>
|
||||
<view class="featured-dish-title line-clamp-2 mb-16rpx">
|
||||
{{ item?.dishName }}
|
||||
</view>
|
||||
<view class="flex items-center justify-between gap-12rpx">
|
||||
<view
|
||||
v-if="Number(item?.memberPrice) > 0"
|
||||
class="featured-dish-member shrink min-w-0"
|
||||
>
|
||||
<text class="featured-dish-member-inner">{{ t('pages-store.store.members') }}: US${{ item?.memberPrice }}</text>
|
||||
</view>
|
||||
<view v-else class="flex-1 min-w-0"></view>
|
||||
<view class="featured-dish-add center shrink-0">
|
||||
<image
|
||||
src="@img/chef/1285.png"
|
||||
class="w-28rpx h-28rpx"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-if="getDishPromoLabel(item as Record<string, unknown>)"
|
||||
class="featured-dish-promo mt-16rpx"
|
||||
>
|
||||
<text class="featured-dish-promo-text">{{ getDishPromoLabel(item as Record<string, unknown>) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
</view>
|
||||
</view>
|
||||
<template #bottom>
|
||||
<view class="h-50px"></view>
|
||||
<view :style="[configStore.iosSafeBottomPlaceholder]"></view>
|
||||
</template>
|
||||
</z-paging>
|
||||
<view v-if="userStore.isLogin && userStore.userCartAllData.length > 0" @click="navigateTo('/pages-user/pages/cart/index')" class="fixed bottom-138rpx left-50% translate-x--50% px-26rpx h-88rpx bg-#14181B rounded-44rpx center text-28rpx text-#fff font-500">
|
||||
<image src="@img/chef/125.png" class="w-28rpx h-28rpx shrink-0"></image>
|
||||
<view class="ml-10rpx whitespace-nowrap">{{ userStore.userCartAllData[0]?.merchantName }}</view>
|
||||
<view class="w-8rpx h-8rpx rounded-50% bg-white mx-8rpx"></view>
|
||||
<text>{{ userStore.userCartAllData[0]?.merchantCartVoList?.length || 0 }}</text>
|
||||
</view>
|
||||
|
||||
<!-- 回到顶部按钮 -->
|
||||
<view v-if="showBackToTop" @click="scrollToTop" class="fixed bottom-148rpx left-30rpx w-88rpx h-88rpx bg-#14181B rounded-50% center shadow-lg">
|
||||
<!-- 回到顶部(购物车已并入顶栏,不再使用底部浮条) -->
|
||||
<view v-if="showBackToTop" @click="scrollToTop" class="home-back-top fixed left-30rpx w-88rpx h-88rpx bg-#14181B rounded-50% center shadow-lg">
|
||||
<image src="@img/chef/119.png" class="w-40rpx h-40rpx shrink-0 rotate-180"></image>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.home-page-root {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.home-top-header {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.home-loc-pill {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
max-width: 200rpx;
|
||||
padding: 12rpx 18rpx;
|
||||
background: #fff;
|
||||
border-radius: 999rpx;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.home-loc-pill__text {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 22rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 500;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.home-cart-btn {
|
||||
position: relative;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 72rpx;
|
||||
height: 72rpx;
|
||||
flex-shrink: 0;
|
||||
background: #fff;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.07);
|
||||
}
|
||||
|
||||
.home-cart-badge {
|
||||
position: absolute;
|
||||
top: 4rpx;
|
||||
right: 4rpx;
|
||||
min-width: 28rpx;
|
||||
height: 28rpx;
|
||||
padding: 0 6rpx;
|
||||
font-size: 18rpx;
|
||||
line-height: 28rpx;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
background: #e23636;
|
||||
border-radius: 999rpx;
|
||||
}
|
||||
|
||||
.home-delivery-row {
|
||||
padding-left: 2rpx;
|
||||
}
|
||||
|
||||
.home-promo-swiper {
|
||||
margin-top: 8rpx;
|
||||
}
|
||||
|
||||
.home-tabs-quick {
|
||||
padding-left: 8rpx;
|
||||
padding-right: 8rpx;
|
||||
}
|
||||
|
||||
.nearby-merchants-block {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
/* 为底栏 Tab 预留空间,避免被遮挡 */
|
||||
.home-back-top {
|
||||
bottom: calc(100rpx + env(safe-area-inset-bottom, 0px));
|
||||
}
|
||||
|
||||
.card-swiper {
|
||||
height: 420rpx;
|
||||
height: 400rpx;
|
||||
}
|
||||
.swiper-item-content {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
transform: scale(0.95);
|
||||
border-radius: 20rpx;
|
||||
transition: transform 0.3s;
|
||||
transform: scale(0.94);
|
||||
border-radius: 32rpx;
|
||||
box-shadow: 0 8rpx 28rpx rgba(0, 0, 0, 0.08);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
.swiper-item-active .swiper-item-content {
|
||||
transform: scale(1);
|
||||
}
|
||||
.member-price-tag {
|
||||
min-width: 220rpx;
|
||||
height: 42rpx;
|
||||
background-image: url("/static/images/chef/1282.png");
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
/* 精选商家 / 精选菜品 区块(与页面背景统一) */
|
||||
.featured-merchants-section,
|
||||
.featured-dishes-section {
|
||||
background: #f2f2f2;
|
||||
}
|
||||
|
||||
.featured-dish-collect-icon {
|
||||
filter: drop-shadow(0 2rpx 6rpx rgba(0, 0, 0, 0.18));
|
||||
}
|
||||
|
||||
/* 瀑布流商品图:固定 1:1 区域,便于「已售完」等角标统一 */
|
||||
.featured-dish-image {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 0;
|
||||
padding-bottom: 100%;
|
||||
background: #f0f0f0;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.featured-dish-img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: block;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.featured-dish-sold-dim {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 2;
|
||||
background: rgba(20, 24, 27, 0.42);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.featured-dish-sold-overlay {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
z-index: 3;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.featured-dish-card {
|
||||
background: #fff;
|
||||
border-radius: 24rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.06);
|
||||
}
|
||||
|
||||
.featured-dish-body {
|
||||
padding: 20rpx 20rpx 22rpx;
|
||||
}
|
||||
|
||||
.featured-dish-price {
|
||||
color: #e02e24;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.featured-dish-original {
|
||||
margin-left: 10rpx;
|
||||
color: #b3b3b3;
|
||||
font-size: 22rpx;
|
||||
font-weight: 400;
|
||||
text-decoration: line-through;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
.featured-dish-sales {
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
line-height: 1.35;
|
||||
max-width: 48%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.featured-dish-title {
|
||||
color: #1a1a1a;
|
||||
font-size: 28rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.45;
|
||||
}
|
||||
|
||||
/* 会员价:暖色胶囊,替代长条形切图 */
|
||||
.featured-dish-member {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
max-width: calc(100% - 88rpx);
|
||||
}
|
||||
|
||||
.featured-dish-member-inner {
|
||||
display: inline-block;
|
||||
padding: 6rpx 18rpx;
|
||||
border-radius: 999rpx;
|
||||
background: linear-gradient(180deg, #fff5eb 0%, #ffe8d6 100%);
|
||||
color: #c45c1a;
|
||||
font-size: 24rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.35;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.featured-dish-add {
|
||||
width: 56rpx;
|
||||
height: 56rpx;
|
||||
border-radius: 50%;
|
||||
background: #14181b;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.12);
|
||||
}
|
||||
|
||||
/* 可选营销条(淡红底 + 文案) */
|
||||
.featured-dish-promo {
|
||||
padding: 12rpx 16rpx;
|
||||
border-radius: 12rpx;
|
||||
background: #fff0f0;
|
||||
}
|
||||
|
||||
.featured-dish-promo-text {
|
||||
color: #e02e24;
|
||||
font-size: 22rpx;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.dish-new-ribbon {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 184rpx;
|
||||
height: 184rpx;
|
||||
overflow: hidden;
|
||||
z-index: 5;
|
||||
pointer-events: none;
|
||||
|
||||
&__text {
|
||||
position: absolute;
|
||||
top: 26rpx;
|
||||
left: -66rpx;
|
||||
width: 240rpx;
|
||||
text-align: center;
|
||||
font-size: 22rpx;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
letter-spacing: 2rpx;
|
||||
line-height: 44rpx;
|
||||
background: #E23636;
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user