205 lines
5.8 KiB
Vue
205 lines
5.8 KiB
Vue
<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 { t } = useI18n();
|
|
|
|
function navigateTo(url: string) {
|
|
if(userStore.checkLogin()) {
|
|
uni.navigateTo({
|
|
url,
|
|
});
|
|
}
|
|
}
|
|
|
|
function toggleNotOpen() {
|
|
emit("toggleNotOpen");
|
|
}
|
|
|
|
async function initData() {
|
|
if(!recipeData.value) {
|
|
loading.value = true;
|
|
}
|
|
getRecipeData()
|
|
// 获取菜品数据
|
|
appMerchantDishNearbyList()
|
|
}
|
|
|
|
// 获取菜谱数据
|
|
const recipeData = ref([]);
|
|
function getRecipeData() {
|
|
appSearchSearchRecipePost({
|
|
body: {
|
|
pageNum: 1,
|
|
pageSize: 10,
|
|
}
|
|
}).then(res=> {
|
|
console.log('菜谱数据', res)
|
|
recipeData.value = res.rows;
|
|
}).finally(()=> {
|
|
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}`)
|
|
}
|
|
|
|
// 获取附近的菜品
|
|
const dishData = ref([]);
|
|
function appMerchantDishNearbyList() {
|
|
appMerchantDishNearbyListPost({
|
|
params: {
|
|
pageNum: 1,
|
|
pageSize: 10,
|
|
},
|
|
body: {
|
|
lat: userStore.userLocation.latitude,
|
|
lng: userStore.userLocation.longitude,
|
|
}
|
|
}).then(res=> {
|
|
console.log('菜品数据', res)
|
|
dishData.value = res.rows;
|
|
})
|
|
}
|
|
function handleClickDish(item: any) {
|
|
navigateTo(`/pages-store/pages/store/index?id=${item.merchantId}`)
|
|
}
|
|
|
|
async function getPlatformDefaultStoreInfo() {}
|
|
|
|
defineExpose({
|
|
initData,
|
|
init: getPlatformDefaultStoreInfo,
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<view
|
|
class="bg-#fff"
|
|
:style="[
|
|
{
|
|
height: configStore.windowHeight + 'px',
|
|
},
|
|
]"
|
|
>
|
|
<z-paging ref="paging">
|
|
<template #top>
|
|
<status-bar />
|
|
</template>
|
|
<view
|
|
v-show="loading"
|
|
class="animate-in fade-in animate-ease-out animate-duration-300"
|
|
>
|
|
<browse-skeleton />
|
|
</view>
|
|
<view
|
|
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">
|
|
<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">
|
|
<image
|
|
:src="thumbnailImg(item?.recipeImage?.split(',')[0])"
|
|
class="w-310rpx h-296rpx rounded-24rpx mb-26rpx bg-common"
|
|
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>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
</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>
|
|
|
|
<template #bottom>
|
|
<view class="h-50px"></view>
|
|
<view :style="[configStore.iosSafeBottomPlaceholder]"></view>
|
|
</template>
|
|
</z-paging>
|
|
</view>
|
|
</template>
|
|
|
|
<style scoped lang="scss"></style>
|