Files
YGChatCS/src/pages/Discovery/index.vue

314 lines
10 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<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>