314 lines
10 KiB
Vue
314 lines
10 KiB
Vue
<template>
|
||
<view class="flex h-full min-h-0 w-full flex-col bg-[#F0F8F3]">
|
||
<view
|
||
v-if="!isMainPanoramaGuide"
|
||
class="z-[12] flex w-full shrink-0 flex-row items-center bg-[#F0F8F3]"
|
||
>
|
||
<view
|
||
class="ml-[12px] mr-[8px] p-[4px] flex h-[36px] w-[36px] shrink-0 items-center justify-center rounded-full border border-white/70"
|
||
@click="handleMainPanoramaClick"
|
||
>
|
||
<image
|
||
class="h-full w-full"
|
||
src="https://one-feel-config-images-bucket.oss-cn-chengdu.aliyuncs.com/xiaoqi/back_home.png"
|
||
mode="aspectFit"
|
||
/>
|
||
</view>
|
||
<view v-if="discoveryTabs.length > 0" class="min-w-0 flex-1 overflow-hidden">
|
||
<FindTabs v-model="activeIndex" :tabs="discoveryTabs" @change="handleTabChange" />
|
||
</view>
|
||
</view>
|
||
|
||
<scroll-view class="h-0 min-h-0 w-full flex-1 overflow-hidden" scroll-y @scroll="handleContentScroll">
|
||
<view v-show="isMainPanoramaGuide" class="flex w-full flex-col gap-[12px]">
|
||
<PanoramicHome @select="handlePanoramicHomeSelect" />
|
||
</view>
|
||
<view v-if="!isMainPanoramaGuide" class="flex w-full flex-col gap-[12px]">
|
||
<CardSwiper v-if="discoveryCards.length > 0" :list="discoveryCards" @didSelectItem="handleCardClick" />
|
||
<ExploreCards v-if="exploreCards.length > 0" :list="exploreCards" @didSelectItem="handleCardClick" />
|
||
|
||
<DiscoveryPhotoToolCard v-if="discoveryPhotoToolData" :item="discoveryPhotoToolData"
|
||
@didSelectItem="handleToolCardClick" @didSelectOption="handleToolOptionClick" />
|
||
<DiscoveryAudioToolCard v-if="discoveryAudioToolData" :item="discoveryAudioToolData"
|
||
:active="props.active" @didSelectItem="handleToolCardClick" />
|
||
<DiscoveryGuideMapToolCard v-if="discoveryGuideMapToolData" :item="discoveryGuideMapToolData" />
|
||
<DiscoveryGoodsCard v-if="discoveryGoodsData.length > 0" :list="discoveryGoodsData" />
|
||
|
||
<QuickQuestions v-if="discoveryQuickQuestions.length > 0" :list="discoveryQuickQuestions"
|
||
@didSelectItem="handleQuickQuestionClick" />
|
||
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, ref } from "vue";
|
||
import { SEND_MESSAGE_CONTENT_TEXT, SEND_MESSAGE_COMMAND_TYPE } from "@/constant/constant";
|
||
import { navigateTo } from "@/router";
|
||
import { getAccessToken } from "@/constant/token";
|
||
|
||
import FindTabs from "./components/FindTabs/index.vue";
|
||
import CardSwiper from "./components/CardSwiper/index.vue";
|
||
import ExploreCards from "./components/ExploreCards/index.vue";
|
||
import QuickQuestions from "./components/QuickQuestions/index.vue";
|
||
import DiscoveryPhotoToolCard from "./components/DiscoveryPhotoToolCard/index.vue";
|
||
import DiscoveryAudioToolCard from "./components/DiscoveryAudioToolCard/index.vue";
|
||
import DiscoveryGuideMapToolCard from "./components/DiscoveryGuideMapToolCard/index.vue";
|
||
import DiscoveryGoodsCard from "./components/DiscoveryGoodsCard/index.vue";
|
||
import PanoramicHome from "./components/PanoramicHome/index.vue";
|
||
import { homeTabsData, getNearbyTags, homeTabContentData, homeQuickQuestionData, resourceCenterData } from "../../request/api/MainPageDataApi";
|
||
import { useAppStore, useLocationStore } from "@/store";
|
||
import { JumpType } from "../../model/ChatModel";
|
||
|
||
const props = defineProps({
|
||
active: {
|
||
type: Boolean,
|
||
default: true,
|
||
},
|
||
});
|
||
|
||
const appStore = useAppStore();
|
||
const locationStore = useLocationStore();
|
||
/// 从个渠道获取如二维码
|
||
const sceneId = appStore.sceneId || "";
|
||
const currentTabsId = ref("");
|
||
|
||
const activeIndex = ref(0);
|
||
const discoveryTabs = ref([]);
|
||
const discoveryCards = ref([]);
|
||
const exploreCards = ref([]);
|
||
const discoveryQuickQuestions = ref([]);
|
||
const discoveryPhotoToolData = ref(null);
|
||
const discoveryAudioToolData = ref(null);
|
||
const discoveryGuideMapToolData = ref(null);
|
||
const discoveryGoodsData = ref([]);
|
||
const emit = defineEmits(["content-scroll"]);
|
||
|
||
/// 是否是主景区引导页 默认是 true,点击主景区后为 false
|
||
const isMainPanoramaGuide = ref(true);
|
||
|
||
/// 监听页面滚动事件
|
||
const handleContentScroll = (e) => {
|
||
emit("content-scroll", {
|
||
scrollTop: Number(e.detail?.scrollTop || 0),
|
||
});
|
||
};
|
||
|
||
/// 点击主景区
|
||
const handleMainPanoramaClick = () => {
|
||
isMainPanoramaGuide.value = true;
|
||
currentTabsId.value = "";
|
||
discoveryTabs.value = [];
|
||
discoveryCards.value = [];
|
||
exploreCards.value = [];
|
||
discoveryQuickQuestions.value = [];
|
||
discoveryPhotoToolData.value = null;
|
||
discoveryAudioToolData.value = null;
|
||
discoveryGuideMapToolData.value = null;
|
||
discoveryGoodsData.value = [];
|
||
};
|
||
|
||
|
||
/// tabs 切换事件
|
||
const handleTabChange = ({ tab, idx }) => {
|
||
activeIndex.value = idx;
|
||
queryDiscoveryData(tab);
|
||
}
|
||
|
||
/// 请求发现页tab数据
|
||
const queryTabsList = async (homePageId) => {
|
||
const res = await homeTabsData({ homePageId });
|
||
if (res.code === 0 && Array.isArray(res.data)) {
|
||
const tabList = res.data;
|
||
if (tabList.length === 0) {
|
||
uni.showToast({
|
||
title: "暂无数据~",
|
||
icon: "none"
|
||
});
|
||
return;
|
||
};
|
||
isMainPanoramaGuide.value = false;
|
||
discoveryTabs.value.push(...tabList);
|
||
/// 根据sceneId查询对应tab数据
|
||
findTabByIdWithActiveTabIndex(sceneId);
|
||
/// 如果没有sceneId,则获取位置信息,获取附近标签数据
|
||
getLocation();
|
||
}
|
||
}
|
||
|
||
/// 点击主景区后,选择景区后,查询对应tab数据
|
||
const handlePanoramicHomeSelect = (item) => {
|
||
const homePageId = item?.homePageId;
|
||
if (!homePageId) return;
|
||
queryTabsList(homePageId);
|
||
};
|
||
|
||
/// 根据id查询tab并设置activeIndex
|
||
const findTabByIdWithActiveTabIndex = (tabsId) => {
|
||
const resolvedTab = resolveDiscoveryTab(discoveryTabs.value, tabsId);
|
||
if (!resolvedTab.tab?.id) return;
|
||
|
||
if (currentTabsId.value === resolvedTab.tab.id) return;
|
||
currentTabsId.value = resolvedTab.tab.id;
|
||
activeIndex.value = resolvedTab.activeIndex;
|
||
queryDiscoveryData(resolvedTab.tab);
|
||
}
|
||
|
||
/// 找到对应的tab后,查询发现页数据
|
||
const resolveDiscoveryTab = (tabs, tabId) => {
|
||
if (!Array.isArray(tabs) || tabs.length === 0) {
|
||
return { activeIndex: -1, tab: null };
|
||
}
|
||
|
||
const matchedIndex = tabs.findIndex((tab) => tab.id === tabId);
|
||
const activeIndex = matchedIndex > -1 ? matchedIndex : 0;
|
||
return { activeIndex, tab: tabs[activeIndex] };
|
||
};
|
||
|
||
/// 统一请求发现页数据
|
||
const queryDiscoveryData = async (tab) => {
|
||
if (!tab?.id) return;
|
||
|
||
queryDiscoveryCards(tab.id);
|
||
queryQuickQuestionData(tab.id);
|
||
loadResourceCenterDataList(tab.resourceSetCode);
|
||
};
|
||
|
||
/// 请求发现页卡片数据
|
||
const queryDiscoveryCards = async (tabId) => {
|
||
loadDiscoveryCards(tabId);
|
||
loadExploreCards(tabId);
|
||
}
|
||
|
||
/// 请求发现页卡片数据 轮播
|
||
const loadDiscoveryCards = async (tabId) => {
|
||
const res = await homeTabContentData({ tagId: tabId, resourceType: 0 });
|
||
if (res.code === 0) {
|
||
discoveryCards.value = configDataList(res.data);
|
||
}
|
||
}
|
||
|
||
/// 请求发现页探索卡片数据 大卡片
|
||
const loadExploreCards = async (tabId) => {
|
||
const res = await homeTabContentData({ tagId: tabId, resourceType: 1 });
|
||
if (res.code === 0) {
|
||
exploreCards.value = configDataList(res.data);
|
||
}
|
||
}
|
||
|
||
/// 请求快速问题列表数据
|
||
const queryQuickQuestionData = async (tabId) => {
|
||
const res = await homeQuickQuestionData({ tagId: tabId });
|
||
if (res.code === 0) {
|
||
discoveryQuickQuestions.value = configDataList(res.data);
|
||
}
|
||
}
|
||
|
||
/// 按资源集编码读取当前生效快照
|
||
const loadResourceCenterDataList = async (setCode) => {
|
||
if (!setCode) return;
|
||
const res = await resourceCenterData({ setCode });
|
||
if (res.code === 0) {
|
||
const discoveryResourceItems = res.data.items || [];
|
||
// AUDIO POI COMMODITY COMPONENT
|
||
discoveryPhotoToolData.value = discoveryResourceItems.find(item => item.resource?.type === 'COMPONENT') || null;
|
||
discoveryAudioToolData.value = discoveryResourceItems.find(item => item.resource?.type === 'AUDIO') || null;
|
||
discoveryGuideMapToolData.value = discoveryResourceItems.find(item => item.resource?.type === 'POI') || null;
|
||
discoveryGoodsData.value = discoveryResourceItems.filter(item => item.resource?.type === 'COMMODITY') || [];
|
||
}
|
||
}
|
||
|
||
/// 统一处理接口返回数据结构
|
||
const configDataList = (data) => {
|
||
return data.map((item) => ({
|
||
id: item.id,
|
||
title: item.tabContent.mainTitle,
|
||
subTitle: item.tabContent.subTitle,
|
||
tag: item.tabContent.tag,
|
||
coverImage: item.tabContent.coverImage,
|
||
tabContentId: item.tabContent.id,
|
||
jumpContent: item.tabContent.jumpContent,
|
||
jumpDesc: item.tabContent.jumpDesc,
|
||
jumpType: item.tabContent.jumpType,/// 跳转类型: 0商品 1提示词 2链接 3组件指令
|
||
}));
|
||
}
|
||
|
||
/// 卡片点击事件
|
||
const handleCardClick = (item) => {
|
||
handleClick(item);
|
||
};
|
||
|
||
/// 快速问题点击事件
|
||
const handleQuickQuestionClick = (item) => {
|
||
handleClick(item);
|
||
};
|
||
|
||
const handleToolCardClick = (item) => {
|
||
if (item?.jumpType !== undefined) {
|
||
handleClick(item);
|
||
}
|
||
};
|
||
|
||
const handleToolOptionClick = (option, parentItem) => {
|
||
if (option?.jumpType !== undefined) {
|
||
handleClick(option);
|
||
} else {
|
||
handleToolCardClick(parentItem);
|
||
}
|
||
};
|
||
|
||
const handleClick = async (item) => {
|
||
console.log(`执行点击事件: ${item.jumpType},参数:${JSON.stringify(item.jumpContent)}`);
|
||
/// 商品
|
||
if (item.jumpType === JumpType.commodity) {
|
||
uni.navigateTo({
|
||
url: `/pages/goods/index?commodityId=${item.jumpContent}`,
|
||
});
|
||
}
|
||
/// 提示词
|
||
else if (item.jumpType === JumpType.prompt) {
|
||
uni.$emit(SEND_MESSAGE_CONTENT_TEXT, item.jumpContent);
|
||
}
|
||
/// 链接
|
||
else if (item.jumpType === JumpType.link) {
|
||
if (item.jumpContent) {
|
||
const token = getAccessToken();
|
||
navigateTo(item.jumpContent, { token: token });
|
||
}
|
||
}
|
||
/// 组件指令
|
||
else if (item.jumpType === JumpType.command) {
|
||
uni.$emit(SEND_MESSAGE_COMMAND_TYPE, { type: item.jumpContent, title: item.jumpDesc });
|
||
}
|
||
}
|
||
|
||
/// 获取位置信息
|
||
const getLocation = () => {
|
||
/// 已经有sceneId了,说明之前已经获取过位置信息了,就不需要再获取一次了
|
||
if (sceneId) return;
|
||
uni.getLocation({
|
||
type: 'wgs84',
|
||
success: function (res) {
|
||
// 将位置信息存储到 Pinia 中
|
||
locationStore.setLocationData({
|
||
latitude: res.latitude,
|
||
longitude: res.longitude,
|
||
});
|
||
console.log('当前位置:' + JSON.stringify(res));
|
||
getNearbyTagsData();
|
||
}
|
||
});
|
||
}
|
||
|
||
/// 获取附近标签数据
|
||
const getNearbyTagsData = async () => {
|
||
const res = await getNearbyTags();
|
||
if (res.code === 0) {
|
||
const nearbyTagId = res.data;
|
||
findTabByIdWithActiveTabIndex(nearbyTagId);
|
||
}
|
||
}
|
||
|
||
</script>
|