修改样式

This commit is contained in:
2026-04-11 11:55:03 +08:00
parent ef9210a567
commit ec9282a64f
59 changed files with 8708 additions and 2558 deletions
@@ -1,23 +1,17 @@
<script setup lang="ts">
import useEventEmit from "@/hooks/useEventEmit";
import {CollectionType, EventEnum} from "@/constant/enums";
import { debounce } from 'throttle-debounce'
import Search from "../tabbar-home/components/search.vue";
import { useConfigStore, useUserStore } from "@/store";
import MsgBox from "../tabbar-home/components/msg-box.vue";
import Collection from "@/components/collection/index.vue";
import BrowseSkeleton from "./components/browse-skeleton.vue";
import {
appMerchantDishNearbyListPost,
appSearchSearchRecipePost,
appCollectCollectPost,
} from "@/service";
import {thumbnailImg} from "@/utils/utils";
const configStore = useConfigStore();
const userStore = useUserStore();
const emit = defineEmits(["toggleNotOpen"]);
const loading = ref(false);
const recipePreviewLimit = 4;
const { t } = useI18n();
@@ -29,10 +23,6 @@ function navigateTo(url: string) {
}
}
function toggleNotOpen() {
emit("toggleNotOpen");
}
async function initData() {
if(!recipeData.value) {
loading.value = true;
@@ -43,13 +33,14 @@ async function initData() {
}
// 获取菜谱数据
const recipeData = ref([]);
const recipeData = ref<any[]>([]);
function getRecipeData() {
appSearchSearchRecipePost({
body: {
params: {
pageNum: 1,
pageSize: 10,
}
},
body: {}
}).then(res=> {
console.log('菜谱数据', res)
recipeData.value = res.rows;
@@ -57,30 +48,16 @@ function getRecipeData() {
loading.value = false;
})
}
// 收藏菜品
function handleSubmitCollectRecipe(item: any) {
collectRecipe(item)
}
// 防抖处理函数
const collectRecipe = debounce(1000, (item: any) => {
appCollectCollectPost({
body: {
targetId: item.id,
targetType: CollectionType.RECIPE
}
}).then(res=> {
item.isCollect = !item.isCollect;
})
}, {
atBegin: true, // 立即触发
});
function navigateToRecipeDetail(id: string | number) {
navigateTo(`/pages-user/pages/recipe/index?id=${id}`)
}
function navigateToRecipeList() {
navigateTo('/pages-user/pages/recipe/list')
}
// 获取附近的菜品
const dishData = ref([]);
const dishData = ref<any[]>([]);
function appMerchantDishNearbyList() {
appMerchantDishNearbyListPost({
params: {
@@ -88,8 +65,8 @@ function appMerchantDishNearbyList() {
pageSize: 10,
},
body: {
lat: userStore.userLocation.latitude,
lng: userStore.userLocation.longitude,
lat: String(userStore.userLocation.latitude ?? ''),
lng: String(userStore.userLocation.longitude ?? ''),
}
}).then(res=> {
console.log('菜品数据', res)
@@ -100,6 +77,27 @@ function handleClickDish(item: any) {
navigateTo(`/pages-store/pages/store/index?id=${item.merchantId}`)
}
function getMerchantName(item: any) {
return item?.merchantVo?.merchantName || item?.merchantName||item?.dishName || '--'
}
function getMerchantLogo(item: any) {
return item?.merchantVo?.logo || item?.logo || item?.dishImage?.split?.(',')?.[0] || item?.dishImage || ''
}
function getMerchantRate(item: any) {
const rating = Number(item?.merchantVo?.rating ?? item?.rating ?? 0)
return Number.isFinite(rating) && rating > 0 ? rating.toFixed(1) : '5.0'
}
function getPreviewRecipeList() {
return recipeData.value.slice(0, recipePreviewLimit)
}
function showRecipeMore() {
return recipeData.value.length > recipePreviewLimit
}
async function getPlatformDefaultStoreInfo() {}
defineExpose({
@@ -131,65 +129,57 @@ defineExpose({
v-show="!loading"
class="animate-in fade-in animate-ease-in animate-duration-300"
>
<view class="flex-center-sb px-30rpx pt-16rpx">
<view class="text-56rpx text-#333 lh-56rpx font-bold">{{
t("tabBar.browse")
}}</view>
<msg-box @toggleNotOpen="toggleNotOpen" />
</view>
<view class="px-30rpx mt-44rpx">
<view class="px-24rpx pt-16rpx">
<search />
</view>
<view class="mt-50rpx px-30rpx">
<view @click="navigateTo('/pages-user/pages/recipe/list')" class="flex-center-sb">
<text class="text-36rpx lh-36rpx text-#333 font-bold">{{
t("pages.browse.titleRecipes")
}}</text>
<image src="@img/chef/116.png" class="w-64rpx h-64rpx"></image>
</view>
<scroll-view scroll-x="true" class="mt-16rpx">
<view class="flex gap-30rpx">
<template v-for="item in recipeData">
<view @click="navigateToRecipeDetail(item.id)" class="w-312rpx">
<view class="browse-wrap px-24rpx">
<view class="section-title mt-36rpx">{{ t("pages.browse.titleRecipes") }}</view>
<view class="mt-28rpx">
<scroll-view scroll-x class="recipe-scroll" :show-scrollbar="false" :enable-flex="true">
<view class="recipe-track">
<view
v-for="item in getPreviewRecipeList()"
:key="item.id"
class="recipe-item"
@click="navigateToRecipeDetail(item.id)"
>
<image
:src="thumbnailImg(item?.recipeImage?.split(',')[0])"
class="w-310rpx h-296rpx rounded-24rpx mb-26rpx bg-common"
class="recipe-avatar"
mode="aspectFill"
></image>
<view class="flex-center-sb">
<text class="text-30rpx lh-30rpx text-#333 line-clamp-1 tracking-[.04em] font-500"
>{{ item.recipeName }}</text
>
<view class="w-40rpx h-40rpx ml-14rpx shrink-0">
<collection
:is-collected="item.isCollect"
@collectionChange="handleSubmitCollectRecipe(item)"
/>
</view>
/>
<text class="recipe-name line-clamp-1">{{ item.recipeName }}</text>
</view>
<view v-if="showRecipeMore()" class="recipe-more" @click="navigateToRecipeList">
<view class="recipe-more__text-wrap">
<text class="recipe-more__text">{{ t("pages.browse.moreRecipes") }}</text>
</view>
<i class="i-carbon:chevron-right recipe-more__icon"></i>
</view>
</view>
</scroll-view>
</view>
<view class="section-title mt-54rpx">{{ t("pages.browse.titleCuisine") }}</view>
<scroll-view scroll-x class="store-scroll mt-28rpx pb-40rpx" :show-scrollbar="false" :enable-flex="true">
<view class="store-track">
<view v-for="item in dishData" :key="item.id" @click="handleClickDish(item)" class="store-card">
<image
:src="thumbnailImg(getMerchantLogo(item))"
class="store-card__cover"
mode="aspectFill"
/>
<view class="store-card__right">
<view class="store-card__name line-clamp-2">{{ getMerchantName(item) }}</view>
<view class="store-card__rating"> {{ getMerchantRate(item) }}</view>
<view class="store-card__brand">{{ t("pages.browse.brandTag") }}</view>
<view class="store-card__arrow center">
<i class="i-carbon:chevron-right text-30rpx text-white"></i>
</view>
</view>
</template>
</view>
</view>
</scroll-view>
<view
class="mt-50rpx mb-28rpx text-36rpx lh-36rpx text-#333 font-bold"
>{{ t("pages.browse.titleCuisine") }}</view
>
<view class="grid grid-cols-2 gap-x-30rpx gap-y-46rpx pb-40rpx">
<template v-for="item in dishData">
<view @click="handleClickDish(item)" class="w-330rpx overflow-hidden">
<image
:src="thumbnailImg(item?.dishImage?.split(',')[0])"
class="w-full h-186rpx rounded-24rpx mb-16rpx bg-common"
mode="aspectFill"
></image>
<text class="text-30rpx lh-30rpx text-#333 line-clamp-1 tracking-[.04em] font-500"
>{{ item.dishName }}</text
>
</view>
</template>
</view>
</view>
</view>
@@ -201,4 +191,148 @@ defineExpose({
</view>
</template>
<style scoped lang="scss"></style>
<style scoped lang="scss">
.browse-wrap {
background: #fff;
}
.section-title {
font-size: 32rpx;
line-height: 48rpx;
// font-weight: 700;
color: #1c1c1c;
}
.recipe-scroll,
.store-scroll {
width: 100%;
}
.recipe-track {
display: flex;
align-items: flex-start;
gap: 22rpx;
padding-right: 24rpx;
}
.recipe-item {
flex-shrink: 0;
display: flex;
flex-direction: column;
align-items: center;
}
.recipe-avatar {
width: 112rpx;
height: 112rpx;
border-radius: 56rpx;
background: #f1f1f1;
}
.recipe-name {
max-width: 140rpx;
margin-top: 14rpx;
text-align: center;
font-size: 26rpx;
line-height: 32rpx;
color: #222;
font-weight: 500;
}
.recipe-more {
flex-shrink: 0;
height: 112rpx;
display: flex;
align-items: center;
justify-content: space-between;
gap: 4rpx;
padding: 4rpx 8rpx;
}
.recipe-more__text-wrap {
display: flex;
flex-direction: column;
justify-content: center;
gap: 6rpx;
}
.recipe-more__text {
font-size: 24rpx;
line-height: 28rpx;
color: #8a8a8a;
font-weight: 500;
writing-mode: vertical-rl;
text-orientation: upright;
letter-spacing: 2rpx;
white-space: nowrap;
}
.recipe-more__icon {
font-size: 20rpx;
color: #8a8a8a;
}
.store-track {
display: flex;
align-items: stretch;
gap: 22rpx;
padding-right: 24rpx;
}
.store-card {
width: 404rpx;
height: 220rpx;
border-radius: 20rpx;
overflow: hidden;
background: #fff;
flex-shrink: 0;
display: flex;
box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.06);
}
.store-card__cover {
width: 184rpx;
height: 220rpx;
background: #f2f2f2;
flex-shrink: 0;
}
.store-card__right {
flex: 1;
padding: 16rpx 14rpx 14rpx 16rpx;
position: relative;
}
.store-card__name {
font-size: 28rpx;
line-height: 34rpx;
color: #191919;
font-weight: 600;
}
.store-card__rating {
margin-top: 8rpx;
color: #111;
font-size: 26rpx;
line-height: 30rpx;
font-weight: 500;
}
.store-card__brand {
margin-top: 12rpx;
color: #d39a48;
font-size: 24rpx;
line-height: 28rpx;
font-weight: 500;
}
.store-card__arrow {
position: absolute;
right: 10rpx;
bottom: 12rpx;
width: 52rpx;
height: 52rpx;
border-radius: 50%;
background: #111;
}
</style>