feat: 自定义 tabbar 组件替代原生 tabbar,支持 CSS 控制图标大小
Made-with: Cursor
@@ -18,6 +18,7 @@ export default defineAppConfig({
|
||||
backgroundColor: '#F8FAFC'
|
||||
},
|
||||
tabBar: {
|
||||
custom: true,
|
||||
color: '#64748b',
|
||||
selectedColor: '#16a34a',
|
||||
backgroundColor: '#ffffff',
|
||||
@@ -25,19 +26,27 @@ export default defineAppConfig({
|
||||
list: [
|
||||
{
|
||||
pagePath: 'pages/home/index',
|
||||
text: '首页'
|
||||
text: '首页',
|
||||
iconPath: 'assets/tabbar/home.png',
|
||||
selectedIconPath: 'assets/tabbar/home-active.png'
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/menu/index',
|
||||
text: '点餐'
|
||||
text: '点餐',
|
||||
iconPath: 'assets/tabbar/menu.png',
|
||||
selectedIconPath: 'assets/tabbar/menu-active.png'
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/orders/index',
|
||||
text: '订单'
|
||||
text: '订单',
|
||||
iconPath: 'assets/tabbar/orders.png',
|
||||
selectedIconPath: 'assets/tabbar/orders-active.png'
|
||||
},
|
||||
{
|
||||
pagePath: 'pages/profile/index',
|
||||
text: '我的'
|
||||
text: '我的',
|
||||
iconPath: 'assets/tabbar/profile.png',
|
||||
selectedIconPath: 'assets/tabbar/profile-active.png'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
BIN
src/assets/tabbar/home-active.png
Normal file
|
After Width: | Height: | Size: 1.2 KiB |
BIN
src/assets/tabbar/home.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/tabbar/menu-active.png
Normal file
|
After Width: | Height: | Size: 875 B |
BIN
src/assets/tabbar/menu.png
Normal file
|
After Width: | Height: | Size: 987 B |
BIN
src/assets/tabbar/orders-active.png
Normal file
|
After Width: | Height: | Size: 776 B |
BIN
src/assets/tabbar/orders.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
src/assets/tabbar/profile-active.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
src/assets/tabbar/profile.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
101
src/components/tab-bar/index.vue
Normal file
@@ -0,0 +1,101 @@
|
||||
<template>
|
||||
<view class="tab-bar">
|
||||
<view
|
||||
v-for="(item, idx) in tabs"
|
||||
:key="item.pagePath"
|
||||
class="tab-bar__item"
|
||||
@tap="onSwitch(idx)"
|
||||
>
|
||||
<view class="tab-bar__icon">
|
||||
<image
|
||||
class="tab-bar__icon-img"
|
||||
:src="current === idx ? item.activeIcon : item.icon"
|
||||
mode="aspectFit"
|
||||
/>
|
||||
</view>
|
||||
<text
|
||||
class="tab-bar__label"
|
||||
:class="{ 'tab-bar__label--active': current === idx }"
|
||||
>
|
||||
{{ item.text }}
|
||||
</text>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import Taro from '@tarojs/taro'
|
||||
|
||||
import homeIcon from '@/assets/tabbar/home.png'
|
||||
import homeActiveIcon from '@/assets/tabbar/home-active.png'
|
||||
import menuIcon from '@/assets/tabbar/menu.png'
|
||||
import menuActiveIcon from '@/assets/tabbar/menu-active.png'
|
||||
import ordersIcon from '@/assets/tabbar/orders.png'
|
||||
import ordersActiveIcon from '@/assets/tabbar/orders-active.png'
|
||||
import profileIcon from '@/assets/tabbar/profile.png'
|
||||
import profileActiveIcon from '@/assets/tabbar/profile-active.png'
|
||||
|
||||
defineProps<{ current: number }>()
|
||||
|
||||
const tabs = [
|
||||
{ pagePath: '/pages/home/index', text: '首页', icon: homeIcon, activeIcon: homeActiveIcon },
|
||||
{ pagePath: '/pages/menu/index', text: '点餐', icon: menuIcon, activeIcon: menuActiveIcon },
|
||||
{ pagePath: '/pages/orders/index', text: '订单', icon: ordersIcon, activeIcon: ordersActiveIcon },
|
||||
{ pagePath: '/pages/profile/index', text: '我的', icon: profileIcon, activeIcon: profileActiveIcon }
|
||||
]
|
||||
|
||||
function onSwitch(idx: number) {
|
||||
Taro.switchTab({ url: tabs[idx].pagePath })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.tab-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100px;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
background-color: #fff;
|
||||
border-top: 1rpx solid #e5e7eb;
|
||||
z-index: 999;
|
||||
|
||||
&__item {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex: 1;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
&__icon-img {
|
||||
width: 44px;
|
||||
height: 44px;
|
||||
}
|
||||
|
||||
&__label {
|
||||
font-size: 20px;
|
||||
color: #64748b;
|
||||
margin-top: 2px;
|
||||
line-height: 1.2;
|
||||
|
||||
&--active {
|
||||
color: #16a34a;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -4,34 +4,55 @@ import { pinia, useAppStore, useCartStore } from '@/stores'
|
||||
import {
|
||||
FulfillmentScenes,
|
||||
demoHotProducts,
|
||||
type FulfillmentScene,
|
||||
type MiniProductCard
|
||||
} from '@/shared'
|
||||
import { openRoute } from '@/utils/router'
|
||||
|
||||
const categoryCards = [
|
||||
{ key: 'recommend', icon: '⭐', label: '推荐', toneClass: 'home-page__cat-icon--orange' },
|
||||
{ key: 'meal', icon: '🍚', label: '主食', toneClass: 'home-page__cat-icon--green-soft' },
|
||||
{ key: 'snack', icon: '🍜', label: '小吃', toneClass: 'home-page__cat-icon--yellow', badge: 'HOT' },
|
||||
{ key: 'drink', icon: '🧋', label: '饮品', toneClass: 'home-page__cat-icon--green-light' },
|
||||
{ key: 'set', icon: '📦', label: '套餐', toneClass: 'home-page__cat-icon--mint' },
|
||||
{ key: 'dessert', icon: '🍰', label: '甜品', toneClass: 'home-page__cat-icon--amber' }
|
||||
] as const
|
||||
export interface HomeCategoryItem {
|
||||
key: string
|
||||
char: string
|
||||
label: string
|
||||
tone: string
|
||||
badge?: string
|
||||
}
|
||||
|
||||
const trustItems = [
|
||||
{ key: 'fresh', icon: '⚡', label: '现炒现做' },
|
||||
{ key: 'fast', icon: '🕐', label: '30分钟送达' },
|
||||
{ key: 'pickup', icon: '🛍', label: '自提更快' },
|
||||
{ key: 'quality', icon: '🛡', label: '品质保证' }
|
||||
] as const
|
||||
export interface HomeTrustItem {
|
||||
key: string
|
||||
label: string
|
||||
}
|
||||
|
||||
const categoryCards: HomeCategoryItem[] = [
|
||||
{ key: 'recommend', char: '荐', label: '推荐', tone: 'warm' },
|
||||
{ key: 'staple', char: '饭', label: '主食', tone: 'green' },
|
||||
{ key: 'snack', char: '食', label: '小吃', tone: 'amber', badge: '热卖' },
|
||||
{ key: 'drink', char: '饮', label: '饮品', tone: 'teal' },
|
||||
{ key: 'combo', char: '套', label: '套餐', tone: 'blue' },
|
||||
{ key: 'dessert', char: '甜', label: '甜品', tone: 'rose' }
|
||||
]
|
||||
|
||||
const trustItems: HomeTrustItem[] = [
|
||||
{ key: 'fresh', label: '现炒现做' },
|
||||
{ key: 'fast', label: '30分钟送达' },
|
||||
{ key: 'pickup', label: '自提免等' },
|
||||
{ key: 'quality', label: '品质保障' }
|
||||
]
|
||||
|
||||
export function useHomePage () {
|
||||
const appStore = useAppStore(pinia)
|
||||
const cartStore = useCartStore(pinia)
|
||||
|
||||
const currentStore = computed(() => appStore.currentStore)
|
||||
const cartCount = computed(() => cartStore.itemCount)
|
||||
const currentScene = computed(() => appStore.scene)
|
||||
const sceneOptions = computed(() => appStore.sceneOptions)
|
||||
const isDineIn = computed(() => appStore.scene === FulfillmentScenes.DineIn)
|
||||
const recommendedProducts = ref<MiniProductCard[]>(demoHotProducts)
|
||||
|
||||
function switchScene (scene: string) {
|
||||
appStore.setScene(scene as FulfillmentScene)
|
||||
}
|
||||
|
||||
async function refreshPage () {
|
||||
await appStore.initBootstrap()
|
||||
await appStore.initStores()
|
||||
@@ -52,11 +73,14 @@ export function useHomePage () {
|
||||
return {
|
||||
cartCount,
|
||||
categoryCards,
|
||||
currentScene,
|
||||
currentStore,
|
||||
goMenu,
|
||||
goStoreSelect,
|
||||
isDineIn,
|
||||
recommendedProducts,
|
||||
sceneOptions,
|
||||
switchScene,
|
||||
trustItems
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,112 +1,151 @@
|
||||
<template>
|
||||
<view class="home-page">
|
||||
<view class="hp">
|
||||
<!-- Store Card -->
|
||||
<view class="home-page__store-card">
|
||||
<view class="home-page__store-icon-wrap">
|
||||
<text class="home-page__store-icon-emoji">📍</text>
|
||||
</view>
|
||||
<view class="home-page__store-text">
|
||||
<view class="home-page__store-name">
|
||||
<text class="home-page__store-name-text">{{ currentStore.name }}</text>
|
||||
<view class="home-page__store-status">
|
||||
<view class="home-page__store-status-dot" />
|
||||
<view class="hp__store" @click="goStoreSelect">
|
||||
<view class="hp__store-info">
|
||||
<view class="hp__store-row">
|
||||
<text class="hp__store-name">{{ currentStore.name }}</text>
|
||||
<view class="hp__store-status">
|
||||
<view class="hp__store-dot" />
|
||||
<text>营业中</text>
|
||||
</view>
|
||||
</view>
|
||||
<text class="home-page__store-addr">{{ currentStore.address }}</text>
|
||||
<text class="hp__store-addr">{{ currentStore.address }}</text>
|
||||
</view>
|
||||
<view class="home-page__store-switch" @click="goStoreSelect">
|
||||
<text>切换</text>
|
||||
<text class="home-page__chevron">›</text>
|
||||
<view class="hp__store-switch">
|
||||
<text>切换门店</text>
|
||||
<text class="hp__store-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Dine-in Scan Button -->
|
||||
<view v-if="isDineIn" class="home-page__scan-tab" @click="goMenu">
|
||||
<text>🔲</text>
|
||||
<text>堂食扫码点餐</text>
|
||||
<view class="hp__scan" @click="goMenu">
|
||||
<view class="hp__scan-ico">
|
||||
<IconScan size="18" color="#fff" />
|
||||
</view>
|
||||
<text class="hp__scan-text">堂食扫码点餐</text>
|
||||
</view>
|
||||
|
||||
<!-- Search Bar -->
|
||||
<view class="home-page__search" @click="goMenu">
|
||||
<text class="home-page__search-icon">🔍</text>
|
||||
<text class="home-page__search-placeholder">搜索菜品、套餐、饮品</text>
|
||||
<view class="hp__search" @click="goMenu">
|
||||
<view class="hp__search-ico">
|
||||
<IconSearch size="14" color="#9CA3AF" />
|
||||
</view>
|
||||
<text class="hp__search-ph">搜索菜品、套餐、饮品</text>
|
||||
</view>
|
||||
|
||||
<!-- Banner -->
|
||||
<view class="home-page__banner" @click="goMenu">
|
||||
<view class="home-page__banner-content">
|
||||
<view class="home-page__banner-tag">
|
||||
<text>✓ 新客专享</text>
|
||||
<view class="hp__banner" @click="goMenu">
|
||||
<view class="hp__banner-body">
|
||||
<view class="hp__banner-label">
|
||||
<text>新客专享</text>
|
||||
</view>
|
||||
<text class="home-page__banner-title">首单立减</text>
|
||||
<view class="home-page__banner-amount">
|
||||
<text class="home-page__banner-unit">¥</text>
|
||||
<text>12</text>
|
||||
<text class="hp__banner-title">首单立减</text>
|
||||
<view class="hp__banner-price">
|
||||
<text class="hp__banner-sym">¥</text>
|
||||
<text class="hp__banner-val">12</text>
|
||||
</view>
|
||||
<text class="home-page__banner-desc">全场满38再减8 · 限时三天</text>
|
||||
<view class="home-page__banner-cta">
|
||||
<text>立即领取 →</text>
|
||||
<text class="hp__banner-note">全场满 38 再减 8 · 限时三天</text>
|
||||
<view class="hp__banner-btn">
|
||||
<text>立即领取</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="home-page__banner-ring-outer" />
|
||||
<view class="home-page__banner-ring" />
|
||||
<image
|
||||
class="home-page__banner-food-img"
|
||||
src="https://images.unsplash.com/photo-1504674900247-0877df9cc836?w=240&h=240&fit=crop&auto=format&q=80"
|
||||
class="hp__banner-img"
|
||||
src="https://images.unsplash.com/photo-1504674900247-0877df9cc836?w=280&h=280&fit=crop&q=80"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="hp__banner-ring" />
|
||||
</view>
|
||||
|
||||
<!-- Categories -->
|
||||
<view class="home-page__categories">
|
||||
<view class="hp__cats">
|
||||
<view
|
||||
v-for="category in categoryCards"
|
||||
:key="category.key"
|
||||
class="home-page__cat-item"
|
||||
v-for="c in categoryCards"
|
||||
:key="c.key"
|
||||
class="hp__cat"
|
||||
@click="goMenu"
|
||||
>
|
||||
<view class="home-page__cat-icon" :class="category.toneClass">
|
||||
<text>{{ category.icon }}</text>
|
||||
<text v-if="category.badge" class="home-page__cat-badge">{{ category.badge }}</text>
|
||||
<view class="hp__cat-ico" :class="`hp__cat-ico--${c.tone}`">
|
||||
<text>{{ c.char }}</text>
|
||||
<text v-if="c.badge" class="hp__cat-badge">{{ c.badge }}</text>
|
||||
</view>
|
||||
<text class="home-page__cat-label">{{ category.label }}</text>
|
||||
<text class="hp__cat-name">{{ c.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Section Header -->
|
||||
<view class="home-page__section-head">
|
||||
<text class="home-page__section-title">热门推荐</text>
|
||||
<view class="home-page__section-more" @click="goMenu">
|
||||
<text>查看全部 ›</text>
|
||||
<!-- Promo Strip -->
|
||||
<view class="hp__promo" @click="goMenu">
|
||||
<view class="hp__promo-tag">
|
||||
<text>限时</text>
|
||||
</view>
|
||||
<text class="hp__promo-text">人气双人餐 超值特惠 ¥49 起</text>
|
||||
<text class="hp__promo-arrow">›</text>
|
||||
</view>
|
||||
|
||||
<!-- Section Header: Hot Products -->
|
||||
<view class="hp__hd">
|
||||
<text class="hp__hd-title">热门推荐</text>
|
||||
<view class="hp__hd-more" @click="goMenu">
|
||||
<text>查看全部</text>
|
||||
<text class="hp__hd-arrow">›</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Product List -->
|
||||
<view class="home-page__product-list">
|
||||
<ProductCard
|
||||
v-for="product in recommendedProducts"
|
||||
:key="product.id"
|
||||
:product="product"
|
||||
@select="goMenu"
|
||||
@action="goMenu"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- Trust Section -->
|
||||
<view class="home-page__trust">
|
||||
<view class="home-page__trust-grid">
|
||||
<view v-for="item in trustItems" :key="item.key" class="home-page__trust-item">
|
||||
<view class="home-page__trust-icon"><text>{{ item.icon }}</text></view>
|
||||
<text class="home-page__trust-label">{{ item.label }}</text>
|
||||
<!-- Product Grid -->
|
||||
<view class="hp__grid">
|
||||
<view
|
||||
v-for="p in recommendedProducts"
|
||||
:key="p.id"
|
||||
class="hp__card"
|
||||
@click="goMenu"
|
||||
>
|
||||
<view class="hp__card-cover">
|
||||
<image class="hp__card-img" :src="p.coverImageUrl" mode="aspectFill" />
|
||||
<text v-if="p.tagTexts?.length" class="hp__card-tag">{{ p.tagTexts[0] }}</text>
|
||||
</view>
|
||||
<view class="hp__card-body">
|
||||
<text class="hp__card-name">{{ p.name }}</text>
|
||||
<text class="hp__card-desc">{{ p.description }}</text>
|
||||
<text class="hp__card-sales">{{ p.salesText }}</text>
|
||||
<view class="hp__card-foot">
|
||||
<view class="hp__card-prices">
|
||||
<text class="hp__card-sym">¥</text>
|
||||
<text class="hp__card-num">{{ p.price }}</text>
|
||||
<text v-if="p.originalPriceText" class="hp__card-old">¥{{ p.originalPriceText }}</text>
|
||||
</view>
|
||||
<view
|
||||
class="hp__card-add"
|
||||
:class="{ 'hp__card-add--pill': p.hasOptions }"
|
||||
@click.stop="goMenu"
|
||||
>
|
||||
<text>{{ p.hasOptions ? '选规格' : '+' }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Trust Strip -->
|
||||
<view class="hp__trust">
|
||||
<view v-for="t in trustItems" :key="t.key" class="hp__trust-pill">
|
||||
<view class="hp__trust-dot" />
|
||||
<text>{{ t.label }}</text>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Bottom Spacer (TabBar safe area) -->
|
||||
<view class="hp__spacer" />
|
||||
|
||||
<!-- Custom TabBar -->
|
||||
<TabBar :current="0" />
|
||||
|
||||
<!-- Floating Cart FAB -->
|
||||
<view v-if="cartCount > 0" class="home-page__fab" @click="goMenu">
|
||||
<text class="home-page__fab-icon">🛒</text>
|
||||
<view class="home-page__fab-badge">
|
||||
<view v-if="cartCount > 0" class="hp__fab" @click="goMenu">
|
||||
<view class="hp__fab-ico">
|
||||
<IconCart size="20" color="#fff" />
|
||||
</view>
|
||||
<view class="hp__fab-badge">
|
||||
<text>{{ cartCount }}</text>
|
||||
</view>
|
||||
</view>
|
||||
@@ -114,7 +153,8 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import ProductCard from '@/components/product-card/index.vue'
|
||||
import { Search as IconSearch, Cart2 as IconCart, Scan2 as IconScan } from '@nutui/icons-vue-taro'
|
||||
import TabBar from '@/components/tab-bar/index.vue'
|
||||
import { useHomePage } from './composables/useHomePage'
|
||||
|
||||
const {
|
||||
@@ -123,7 +163,6 @@ const {
|
||||
currentStore,
|
||||
goMenu,
|
||||
goStoreSelect,
|
||||
isDineIn,
|
||||
recommendedProducts,
|
||||
trustItems
|
||||
} = useHomePage()
|
||||
|
||||
@@ -1,31 +1,30 @@
|
||||
.home-page__banner {
|
||||
border-radius: 24px;
|
||||
@use '../../../styles/variables' as *;
|
||||
|
||||
.hp__banner {
|
||||
border-radius: $r-xl;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
min-height: 160px;
|
||||
background: linear-gradient(135deg, #14532D 0%, #166534 35%, #15803D 70%, #1A7A42 100%);
|
||||
min-height: 156px;
|
||||
background: linear-gradient(135deg, #14532D 0%, #166534 40%, #15803D 100%);
|
||||
padding: 22px 20px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
box-shadow: 0 4px 16px rgba(22, 101, 52, 0.25), 0 8px 32px rgba(22, 101, 52, 0.12);
|
||||
}
|
||||
|
||||
.home-page__banner-content {
|
||||
.hp__banner-body {
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
max-width: 60%;
|
||||
z-index: 2;
|
||||
max-width: 58%;
|
||||
}
|
||||
|
||||
.home-page__banner-tag {
|
||||
.hp__banner-label {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
padding: 3px 10px;
|
||||
background: rgba(255, 255, 255, 0.12);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
border: 1px solid rgba(255, 255, 255, 0.08);
|
||||
border-radius: 999px;
|
||||
color: rgba(255, 255, 255, 0.9);
|
||||
color: rgba(255, 255, 255, 0.88);
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
width: fit-content;
|
||||
@@ -33,89 +32,79 @@
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.home-page__banner-title {
|
||||
.hp__banner-title {
|
||||
font-size: 15px;
|
||||
font-weight: 500;
|
||||
color: rgba(255, 255, 255, 0.85);
|
||||
color: rgba(255, 255, 255, 0.82);
|
||||
display: block;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.home-page__banner-amount {
|
||||
.hp__banner-price {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 2px;
|
||||
margin: 2px 0;
|
||||
}
|
||||
|
||||
.hp__banner-sym {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.hp__banner-val {
|
||||
font-size: 36px;
|
||||
font-weight: 800;
|
||||
color: #fff;
|
||||
line-height: 1.1;
|
||||
margin: 4px 0 2px;
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.home-page__banner-unit {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.home-page__banner-desc {
|
||||
.hp__banner-note {
|
||||
font-size: 12px;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
color: rgba(255, 255, 255, 0.55);
|
||||
margin-top: 6px;
|
||||
display: block;
|
||||
line-height: 1.5;
|
||||
letter-spacing: 0.2px;
|
||||
}
|
||||
|
||||
.home-page__banner-cta {
|
||||
.hp__banner-btn {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
height: 32px;
|
||||
padding: 0 18px;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
height: 30px;
|
||||
padding: 0 16px;
|
||||
background: rgba(255, 255, 255, 0.93);
|
||||
color: #14532D;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
border-radius: 999px;
|
||||
width: fit-content;
|
||||
margin-top: 14px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.home-page__banner-food-img {
|
||||
.hp__banner-img {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
right: 12px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
width: 116px;
|
||||
height: 116px;
|
||||
border-radius: 50%;
|
||||
border: 3px solid rgba(255, 255, 255, 0.15);
|
||||
box-shadow: 0 8px 24px rgba(0, 0, 0, 0.2);
|
||||
border: 3px solid rgba(255, 255, 255, 0.12);
|
||||
box-shadow: 0 6px 20px rgba(0, 0, 0, 0.18);
|
||||
z-index: 1;
|
||||
background: linear-gradient(135deg, rgba(34, 197, 94, 0.2), rgba(22, 163, 74, 0.2));
|
||||
}
|
||||
|
||||
.home-page__banner-ring {
|
||||
.hp__banner-ring {
|
||||
position: absolute;
|
||||
right: -2px;
|
||||
right: 2px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 144px;
|
||||
height: 144px;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
border-radius: 50%;
|
||||
border: 1.5px solid rgba(255, 255, 255, 0.08);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
.home-page__banner-ring-outer {
|
||||
position: absolute;
|
||||
right: -14px;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 168px;
|
||||
height: 168px;
|
||||
border-radius: 50%;
|
||||
border: 1px solid rgba(255, 255, 255, 0.04);
|
||||
border: 1px solid rgba(255, 255, 255, 0.06);
|
||||
z-index: 0;
|
||||
}
|
||||
|
||||
@@ -1,73 +1,57 @@
|
||||
@use '../../../styles/variables' as *;
|
||||
|
||||
.home-page {
|
||||
// ─── Page Shell ───
|
||||
.hp {
|
||||
min-height: 100vh;
|
||||
padding: 14px 16px 24px;
|
||||
padding: 12px 16px 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
gap: 16px;
|
||||
background: $bg;
|
||||
}
|
||||
|
||||
.home-page__store-card {
|
||||
// ─── Store Card ───
|
||||
.hp__store {
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
padding: 14px 16px;
|
||||
padding: 16px;
|
||||
box-shadow: $shadow-sm;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.home-page__store-icon-wrap {
|
||||
width: 42px;
|
||||
height: 42px;
|
||||
border-radius: $r-sm;
|
||||
background: $primary-light;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.home-page__store-icon-emoji {
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.home-page__store-text {
|
||||
.hp__store-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.home-page__store-name {
|
||||
font-size: 15px;
|
||||
font-weight: 600;
|
||||
color: $text-1;
|
||||
.hp__store-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.home-page__store-name-text {
|
||||
.hp__store-name {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: $text-1;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.home-page__store-status {
|
||||
.hp__store-status {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 3px;
|
||||
gap: 4px;
|
||||
font-size: 11px;
|
||||
color: $primary;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.home-page__store-status-dot {
|
||||
.hp__store-dot {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
@@ -75,87 +59,175 @@
|
||||
animation: pulse-dot 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
.home-page__store-addr {
|
||||
.hp__store-addr {
|
||||
font-size: 12px;
|
||||
color: $text-3;
|
||||
margin-top: 3px;
|
||||
white-space: nowrap;
|
||||
margin-top: 4px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.home-page__store-switch {
|
||||
font-size: 13px;
|
||||
color: $primary;
|
||||
font-weight: 500;
|
||||
.hp__store-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
font-size: 13px;
|
||||
color: $primary;
|
||||
font-weight: 500;
|
||||
padding: 8px 0;
|
||||
white-space: nowrap;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.home-page__chevron {
|
||||
font-size: 16px;
|
||||
.hp__store-arrow {
|
||||
font-size: 18px;
|
||||
line-height: 1;
|
||||
color: $primary;
|
||||
}
|
||||
|
||||
.home-page__scan-tab {
|
||||
// ─── Scene Tabs ───
|
||||
.hp__tabs {
|
||||
display: flex;
|
||||
gap: 0;
|
||||
background: #EEF2F6;
|
||||
border-radius: $r-full;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.hp__tab {
|
||||
flex: 1;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 5px;
|
||||
height: 44px;
|
||||
border-radius: $r-sm;
|
||||
background: $primary;
|
||||
color: #fff;
|
||||
border-radius: $r-full;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 2px 10px rgba(22, 163, 74, 0.35);
|
||||
font-weight: 500;
|
||||
color: $text-3;
|
||||
transition: all 0.25s ease;
|
||||
}
|
||||
|
||||
.home-page__search {
|
||||
.hp__tab--on {
|
||||
background: $primary;
|
||||
color: #fff;
|
||||
font-weight: 600;
|
||||
box-shadow: 0 2px 8px rgba(22, 163, 74, 0.3);
|
||||
}
|
||||
|
||||
// ─── Dine-in Scan Button ───
|
||||
.hp__scan {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 8px;
|
||||
height: 52px;
|
||||
border-radius: $r-md;
|
||||
background: $primary;
|
||||
box-shadow: 0 2px 12px rgba(22, 163, 74, 0.3);
|
||||
}
|
||||
|
||||
.hp__scan-ico {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.hp__scan-text {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
letter-spacing: 0.5px;
|
||||
}
|
||||
|
||||
// ─── Search Bar ───
|
||||
.hp__search {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: #F1F5F9;
|
||||
border-radius: $r-md;
|
||||
border-radius: $r-sm;
|
||||
padding: 0 14px;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.home-page__search-icon {
|
||||
font-size: 14px;
|
||||
.hp__search-ico {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.home-page__search-placeholder {
|
||||
.hp__search-ph {
|
||||
font-size: 14px;
|
||||
color: $text-4;
|
||||
}
|
||||
|
||||
.home-page__section-head {
|
||||
// ─── Section Header ───
|
||||
.hp__hd {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 2px 0;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.home-page__section-title {
|
||||
.hp__hd-title {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: $text-1;
|
||||
letter-spacing: 0.3px;
|
||||
}
|
||||
|
||||
.home-page__section-more {
|
||||
font-size: 13px;
|
||||
color: $text-4;
|
||||
.hp__hd-more {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 2px;
|
||||
font-size: 13px;
|
||||
color: $text-4;
|
||||
padding: 8px 0;
|
||||
}
|
||||
|
||||
.home-page__product-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
.hp__hd-arrow {
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
// ─── Promo Strip ───
|
||||
.hp__promo {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
background: #FFFBEB;
|
||||
border-radius: $r-sm;
|
||||
padding: 10px 14px;
|
||||
border: 1px solid #FEF3C7;
|
||||
}
|
||||
|
||||
.hp__promo-tag {
|
||||
background: $accent;
|
||||
color: #fff;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
padding: 2px 7px;
|
||||
border-radius: 4px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.hp__promo-text {
|
||||
flex: 1;
|
||||
font-size: 13px;
|
||||
color: #92400E;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.hp__promo-arrow {
|
||||
font-size: 18px;
|
||||
color: $accent;
|
||||
line-height: 1;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
// ─── Bottom Spacer ───
|
||||
.hp__spacer {
|
||||
height: 80px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
@use '../../../styles/variables' as *;
|
||||
|
||||
.home-page__categories {
|
||||
.hp__cats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
gap: 2px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.home-page__cat-item {
|
||||
.hp__cat {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 2px 8px;
|
||||
border-radius: $r-sm;
|
||||
padding: 4px 0 6px;
|
||||
}
|
||||
|
||||
.home-page__cat-icon {
|
||||
.hp__cat-ico {
|
||||
width: 48px;
|
||||
height: 48px;
|
||||
border-radius: 16px;
|
||||
border-radius: 14px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
font-size: 18px;
|
||||
font-size: 20px;
|
||||
font-weight: 700;
|
||||
|
||||
&--orange { background: #FFF4ED; }
|
||||
&--green-soft { background: #F0FDF4; }
|
||||
&--yellow { background: #FFFBEB; }
|
||||
&--green-light { background: #ECFDF5; }
|
||||
&--mint { background: #F0FDF4; }
|
||||
&--amber { background: #FFF7ED; }
|
||||
&--warm { background: #FFF4ED; color: #EA580C; }
|
||||
&--green { background: #F0FDF4; color: #16A34A; }
|
||||
&--amber { background: #FFFBEB; color: #D97706; }
|
||||
&--teal { background: #F0FDFA; color: #0D9488; }
|
||||
&--blue { background: #EFF6FF; color: #2563EB; }
|
||||
&--rose { background: #FFF1F2; color: #E11D48; }
|
||||
}
|
||||
|
||||
.home-page__cat-label {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: $text-2;
|
||||
}
|
||||
|
||||
.home-page__cat-badge {
|
||||
.hp__cat-badge {
|
||||
position: absolute;
|
||||
top: -3px;
|
||||
right: -6px;
|
||||
top: -4px;
|
||||
right: -8px;
|
||||
font-size: 9px;
|
||||
font-weight: 600;
|
||||
background: $red;
|
||||
color: #fff;
|
||||
padding: 1px 5px;
|
||||
border-radius: 999px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.hp__cat-name {
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
color: $text-2;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
@use '../../../styles/variables' as *;
|
||||
|
||||
.home-page__fab {
|
||||
.hp__fab {
|
||||
position: fixed;
|
||||
bottom: 92px;
|
||||
right: 16px;
|
||||
@@ -8,30 +8,33 @@
|
||||
width: 52px;
|
||||
height: 52px;
|
||||
border-radius: 50%;
|
||||
background: linear-gradient(135deg, $primary 0%, $primary-dark 100%);
|
||||
background: $primary;
|
||||
box-shadow: 0 4px 16px rgba(22, 163, 74, 0.35);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.home-page__fab-icon {
|
||||
font-size: 20px;
|
||||
.hp__fab-ico {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.home-page__fab-badge {
|
||||
.hp__fab-badge {
|
||||
position: absolute;
|
||||
top: -2px;
|
||||
right: -2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
border-radius: 9px;
|
||||
background: $red;
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
font-size: 10px;
|
||||
font-weight: 700;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 4px;
|
||||
border: 2px solid #fff;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
@forward './base.scss';
|
||||
@forward './banner.scss';
|
||||
@forward './category.scss';
|
||||
@forward './product.scss';
|
||||
@forward './trust.scss';
|
||||
@forward './fab.scss';
|
||||
|
||||
137
src/pages/home/styles/product.scss
Normal file
@@ -0,0 +1,137 @@
|
||||
@use '../../../styles/variables' as *;
|
||||
|
||||
.hp__grid {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.hp__card {
|
||||
width: calc(50% - 6px);
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
box-shadow: $shadow-sm;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.hp__card-cover {
|
||||
width: 100%;
|
||||
height: 136px;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hp__card-img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: $border;
|
||||
}
|
||||
|
||||
.hp__card-tag {
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
left: 8px;
|
||||
font-size: 10px;
|
||||
font-weight: 600;
|
||||
padding: 2px 8px;
|
||||
border-radius: 6px;
|
||||
color: #fff;
|
||||
background: rgba(22, 163, 74, 0.88);
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.hp__card-body {
|
||||
padding: 10px 12px 12px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.hp__card-name {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: $text-1;
|
||||
line-height: 1.4;
|
||||
display: block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.hp__card-desc {
|
||||
font-size: 11px;
|
||||
color: $text-3;
|
||||
margin-top: 3px;
|
||||
line-height: 1.5;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 1;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.hp__card-sales {
|
||||
font-size: 10px;
|
||||
color: $text-4;
|
||||
margin-top: 4px;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.hp__card-foot {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: space-between;
|
||||
margin-top: auto;
|
||||
padding-top: 8px;
|
||||
}
|
||||
|
||||
.hp__card-prices {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 1px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.hp__card-sym {
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
color: $primary-dark;
|
||||
}
|
||||
|
||||
.hp__card-num {
|
||||
font-size: 18px;
|
||||
font-weight: 700;
|
||||
color: $primary-dark;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.hp__card-old {
|
||||
font-size: 10px;
|
||||
color: $text-4;
|
||||
text-decoration: line-through;
|
||||
margin-left: 3px;
|
||||
}
|
||||
|
||||
.hp__card-add {
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 50%;
|
||||
background: $primary;
|
||||
color: #fff;
|
||||
font-size: 18px;
|
||||
font-weight: 500;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
|
||||
&--pill {
|
||||
width: auto;
|
||||
height: 28px;
|
||||
padding: 0 10px;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,28 @@
|
||||
@use '../../../styles/variables' as *;
|
||||
|
||||
.home-page__trust {
|
||||
background: $card;
|
||||
border-radius: $r-lg;
|
||||
padding: 16px 12px;
|
||||
box-shadow: $shadow-xs;
|
||||
}
|
||||
|
||||
.home-page__trust-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.home-page__trust-item {
|
||||
.hp__trust {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
padding: 4px 0;
|
||||
}
|
||||
|
||||
.hp__trust-pill {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
padding: 6px 4px;
|
||||
}
|
||||
|
||||
.home-page__trust-icon {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
border-radius: 11px;
|
||||
padding: 6px 12px;
|
||||
background: $primary-lighter;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 16px;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
color: $primary-dark;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.home-page__trust-label {
|
||||
font-size: 11px;
|
||||
color: $text-2;
|
||||
font-weight: 500;
|
||||
text-align: center;
|
||||
line-height: 1.4;
|
||||
.hp__trust-dot {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
border-radius: 50%;
|
||||
background: $primary;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
@@ -102,6 +102,9 @@
|
||||
@change-qty="(key, delta) => cartStore.changeQuantity(key, delta)"
|
||||
/>
|
||||
|
||||
<!-- Custom TabBar -->
|
||||
<TabBar :current="1" />
|
||||
|
||||
<!-- Spec Popup -->
|
||||
<SpecPopup
|
||||
v-if="detailVisible && activeDetail"
|
||||
@@ -126,6 +129,7 @@
|
||||
import ProductCard from '@/components/product-card/index.vue'
|
||||
import CartDrawer from '@/components/cart-drawer/index.vue'
|
||||
import SpecPopup from '@/components/spec-popup/index.vue'
|
||||
import TabBar from '@/components/tab-bar/index.vue'
|
||||
import { useMenuPage } from './composables/useMenuPage'
|
||||
|
||||
const {
|
||||
|
||||
@@ -61,12 +61,16 @@
|
||||
<NutButton type="primary" block @click="goMenu">去点餐</NutButton>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Custom TabBar -->
|
||||
<TabBar :current="2" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button as NutButton, Empty, Price, Tag } from '@nutui/nutui-taro'
|
||||
import PageHero from '@/components/page-hero/index.vue'
|
||||
import TabBar from '@/components/tab-bar/index.vue'
|
||||
import { useOrdersPage } from './composables/useOrdersPage'
|
||||
|
||||
const {
|
||||
|
||||
@@ -44,12 +44,16 @@
|
||||
<NutButton block plain @click="goDineIn">编辑桌号</NutButton>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Custom TabBar -->
|
||||
<TabBar :current="3" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { Button as NutButton } from '@nutui/nutui-taro'
|
||||
import PageHero from '@/components/page-hero/index.vue'
|
||||
import TabBar from '@/components/tab-bar/index.vue'
|
||||
import { useProfilePage } from './composables/useProfilePage'
|
||||
|
||||
const {
|
||||
|
||||
@@ -8,13 +8,13 @@ const productMap: Record<Id, MiniProductCard> = {
|
||||
id: '2000000000000000001',
|
||||
name: '招牌鸡腿饭',
|
||||
description: '招牌酱汁鸡腿搭配时蔬与米饭',
|
||||
coverImageUrl: 'https://dummyimage.com/160x160/f3f4f6/111827&text=Chicken',
|
||||
coverImageUrl: 'https://images.unsplash.com/photo-1546069901-ba9599a7e63c?w=400&h=400&fit=crop&q=80',
|
||||
price: 22,
|
||||
priceText: formatPrice(22),
|
||||
originalPrice: 26,
|
||||
originalPriceText: formatPrice(26),
|
||||
salesText: '月售 268',
|
||||
tagTexts: ['招牌', '热销'],
|
||||
tagTexts: ['招牌'],
|
||||
soldOut: false,
|
||||
hasOptions: false
|
||||
},
|
||||
@@ -22,13 +22,13 @@ const productMap: Record<Id, MiniProductCard> = {
|
||||
id: '2000000000000000002',
|
||||
name: '黑椒牛柳饭',
|
||||
description: '黑椒风味牛柳,适合工作日快餐',
|
||||
coverImageUrl: 'https://dummyimage.com/160x160/e5e7eb/111827&text=Beef',
|
||||
coverImageUrl: 'https://images.unsplash.com/photo-1544025162-d76694265947?w=400&h=400&fit=crop&q=80',
|
||||
price: 29,
|
||||
priceText: formatPrice(29),
|
||||
originalPrice: 33,
|
||||
originalPriceText: formatPrice(33),
|
||||
salesText: '月售 186',
|
||||
tagTexts: ['牛肉', '推荐'],
|
||||
tagTexts: ['推荐'],
|
||||
soldOut: false,
|
||||
hasOptions: false
|
||||
},
|
||||
@@ -36,7 +36,7 @@ const productMap: Record<Id, MiniProductCard> = {
|
||||
id: '2000000000000000003',
|
||||
name: '藤椒鸡丝沙拉',
|
||||
description: '轻食组合,适合晚餐与健身场景',
|
||||
coverImageUrl: 'https://dummyimage.com/160x160/dbeafe/111827&text=Salad',
|
||||
coverImageUrl: 'https://images.unsplash.com/photo-1512621776951-a57141f2eefd?w=400&h=400&fit=crop&q=80',
|
||||
price: 18,
|
||||
priceText: formatPrice(18),
|
||||
salesText: '月售 92',
|
||||
@@ -48,7 +48,7 @@ const productMap: Record<Id, MiniProductCard> = {
|
||||
id: '2000000000000000004',
|
||||
name: '芝士薯球',
|
||||
description: '外酥里糯的轻食小吃',
|
||||
coverImageUrl: 'https://dummyimage.com/160x160/fef3c7/111827&text=Snack',
|
||||
coverImageUrl: 'https://images.unsplash.com/photo-1555939594-58d7cb561ad1?w=400&h=400&fit=crop&q=80',
|
||||
price: 12,
|
||||
priceText: formatPrice(12),
|
||||
salesText: '月售 143',
|
||||
@@ -60,7 +60,7 @@ const productMap: Record<Id, MiniProductCard> = {
|
||||
id: '2000000000000000005',
|
||||
name: '茉莉轻乳茶',
|
||||
description: '清爽不腻,适合套餐搭配',
|
||||
coverImageUrl: 'https://dummyimage.com/160x160/ecfccb/111827&text=Tea',
|
||||
coverImageUrl: 'https://images.unsplash.com/photo-1558857563-b371033873b8?w=400&h=400&fit=crop&q=80',
|
||||
price: 10,
|
||||
priceText: formatPrice(10),
|
||||
salesText: '月售 310',
|
||||
@@ -72,11 +72,11 @@ const productMap: Record<Id, MiniProductCard> = {
|
||||
id: '2000000000000000006',
|
||||
name: '冰美式',
|
||||
description: '办公场景高频搭配饮品',
|
||||
coverImageUrl: 'https://dummyimage.com/160x160/e0f2fe/111827&text=Coffee',
|
||||
coverImageUrl: 'https://images.unsplash.com/photo-1509042239860-f550ce710b93?w=400&h=400&fit=crop&q=80',
|
||||
price: 14,
|
||||
priceText: formatPrice(14),
|
||||
salesText: '月售 201',
|
||||
tagTexts: ['办公必备'],
|
||||
tagTexts: ['热卖'],
|
||||
soldOut: false,
|
||||
hasOptions: false
|
||||
}
|
||||
@@ -150,6 +150,3 @@ export function buildMockPriceEstimate (payload: PriceEstimatePayload): PriceEst
|
||||
payableAmountText: formatPrice(payableAmount)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||