Merge branch 'home3.0' of https://git.nianxx.cn/zoujing/YGChatCS into aigc

This commit is contained in:
duanshuwen
2026-07-14 22:09:53 +08:00
13 changed files with 249 additions and 30 deletions

View File

@@ -21,7 +21,9 @@
</view>
<view v-show="tabIndex === 0" class="discovery-shell flex-full" @touchstart.capture="handleDiscoveryPanelTouchStart"
@touchstart="handleDiscoveryPanelTouchStart" @touchmove="handleDiscoveryPanelTouchMove">
@touchstart="handleDiscoveryPanelTouchStart" @touchmove.capture="handleDiscoveryPanelTouchMove"
@touchmove="handleDiscoveryPanelTouchMove"
@touchend="handleDiscoveryPanelTouchEnd" @touchcancel="handleDiscoveryPanelTouchEnd">
<view class="home-welcome-panel">
<HomeWelcome class="flex-shrink-0" :mainPageDataModel="mainPageDataModel" />
</view>
@@ -196,6 +198,10 @@ import {
recentConversation,
} from "@/request/api/ConversationApi";
import WebSocketManager from "@/utils/WebSocketManager";
import {
canExpandDiscoveryPanelFromScroll,
getDiscoveryPanelCollapseState,
} from "@/utils/discoveryPanelScroll";
import { IdUtils } from "@/utils";
import {
appendLongTextChunk,
@@ -228,8 +234,14 @@ const scrollTop = ref(99999);
const discoveryInnerScrollTop = ref(0);
const discoveryPanelTouchStartY = ref(0);
const isDiscoveryPanelCollapsed = ref(false);
let lastDiscoveryInnerScrollTop = 0;
let isDiscoveryPanelTouching = false;
let discoveryPanelTouchDirection = "";
let lastDiscoveryDownGestureAt = 0;
const DISCOVERY_PANEL_EXPAND_TOP = 4;
const DISCOVERY_PANEL_TOUCH_DELTA = 16;
const DISCOVERY_PANEL_DIRECTION_DELTA = 2;
const DISCOVERY_PANEL_GESTURE_RETAIN_MS = 800;
/// 会话列表
const chatMsgList = ref([]);
@@ -389,6 +401,10 @@ const handleScrollAreaTouchMove = () => {
const resetDiscoveryScrollState = () => {
discoveryInnerScrollTop.value = 0;
discoveryPanelTouchStartY.value = 0;
lastDiscoveryInnerScrollTop = 0;
isDiscoveryPanelTouching = false;
discoveryPanelTouchDirection = "";
lastDiscoveryDownGestureAt = 0;
isDiscoveryPanelCollapsed.value = false;
};
@@ -400,6 +416,8 @@ const getTouchPointY = (e) => {
const handleDiscoveryPanelTouchStart = (e) => {
handleScrollAreaTouchStart();
isDiscoveryPanelTouching = true;
discoveryPanelTouchDirection = "";
discoveryPanelTouchStartY.value = getTouchPointY(e);
};
@@ -410,6 +428,14 @@ const handleDiscoveryPanelTouchMove = (e) => {
if (!currentY || !discoveryPanelTouchStartY.value) return;
const touchDelta = currentY - discoveryPanelTouchStartY.value;
if (touchDelta < -DISCOVERY_PANEL_DIRECTION_DELTA) {
discoveryPanelTouchDirection = "up";
lastDiscoveryDownGestureAt = 0;
} else if (touchDelta > DISCOVERY_PANEL_DIRECTION_DELTA) {
discoveryPanelTouchDirection = "down";
lastDiscoveryDownGestureAt = Date.now();
}
if (touchDelta < -DISCOVERY_PANEL_TOUCH_DELTA) {
isDiscoveryPanelCollapsed.value = true;
} else if (
@@ -420,11 +446,27 @@ const handleDiscoveryPanelTouchMove = (e) => {
}
};
const handleDiscoveryPanelTouchEnd = () => {
isDiscoveryPanelTouching = false;
discoveryPanelTouchDirection = "";
};
const handleDiscoveryContentScroll = ({ scrollTop }) => {
discoveryInnerScrollTop.value = Number(scrollTop || 0);
if (discoveryInnerScrollTop.value > DISCOVERY_PANEL_TOUCH_DELTA) {
isDiscoveryPanelCollapsed.value = true;
}
const currentScrollTop = Number(scrollTop || 0);
isDiscoveryPanelCollapsed.value = getDiscoveryPanelCollapseState({
currentScrollTop,
lastScrollTop: lastDiscoveryInnerScrollTop,
isCollapsed: isDiscoveryPanelCollapsed.value,
threshold: DISCOVERY_PANEL_TOUCH_DELTA,
allowExpand: canExpandDiscoveryPanelFromScroll({
isTouching: isDiscoveryPanelTouching,
touchDirection: discoveryPanelTouchDirection,
lastDownGestureAt: lastDiscoveryDownGestureAt,
gestureRetainMs: DISCOVERY_PANEL_GESTURE_RETAIN_MS,
}),
});
discoveryInnerScrollTop.value = currentScrollTop;
lastDiscoveryInnerScrollTop = currentScrollTop;
};
const welcomeHeight = ref(0);

View File

@@ -43,12 +43,12 @@
}
.home-hero {
height: 136px;
height: 140px;
overflow: hidden;
}
.home-hero-bg {
height: 136px;
height: 140px;
}
.home-hero-sprite {

View File

@@ -36,10 +36,15 @@ const itemList = ref([
title: "快速预定",
type: Command.quickBooking,
},
// {
// icon: "",
// title: "旅行记录",
// type: Command.travelAIGC,
// },
{
icon: "",
title: "旅行记录",
type: Command.travelAIGC,
title: "我的订单",
type: Command.myOrder,
},
{
icon: "",

View File

@@ -1,7 +1,7 @@
<template>
<view v-if="hasBannerList">
<swiper @change="onSwiperChange" class="swiper" circular :autoplay="autoplay" :interval="interval"
:duration="duration" :indicator-dots="false">
:duration="duration" :indicator-dots="false" :vertical="true">
<swiper-item v-for="item in bannerList" :key="item.entityName">
<view class="swiper-item" @click="clickItem(item)">
<text class="text-color font-size-12 font-600">

View File

@@ -5,7 +5,7 @@
.swiper-stage {
position: relative;
width: 100%;
height: 270px;
height: 265px;
overflow: hidden;
}
@@ -33,7 +33,7 @@
overflow: hidden;
border-radius: 24px;
background: #ffffff;
box-shadow: 0 12px 20px rgba(15, 23, 42, 0.14);
box-shadow: 0 12px 16px rgba(15, 23, 42, 0.14);
}
.card-media {
@@ -93,7 +93,7 @@
}
.is-current .card-shell {
box-shadow: 0 12px 20px rgba(15, 23, 42, 0.18);
box-shadow: 0 12px 16px rgba(15, 23, 42, 0.18);
}
.is-single .swiper-stage {

View File

@@ -1,9 +1,9 @@
.discovery-audio-tool-card {
width: 100%;
height: 96px;
display: flex;
align-items: flex-start;
box-sizing: border-box;
padding: 0 12px;
}
.discovery-audio-tool-card.is-pressed {
@@ -28,7 +28,7 @@
height: 88px;
display: flex;
flex-direction: column;
padding: 18px 12px 14px;
padding: 12px;
border-radius: 28px;
background: #ffffff;
box-sizing: border-box;
@@ -94,7 +94,6 @@
.audio-progress-row {
display: flex;
align-items: center;
margin-top: 16px;
}
.audio-progress-track {
@@ -114,9 +113,9 @@
.audio-time {
flex: 0 0 90px;
max-width: 90px;
margin-left: 12px;
margin-left: 10px;
color: #94a0b2;
font-size: 15px;
font-size: 12px;
line-height: 20px;
font-weight: 600;
text-align: right;

View File

@@ -4,6 +4,7 @@
display: flex;
align-items: flex-start;
box-sizing: border-box;
padding: 0 12px;
}
.discovery-guide-map-tool-card.is-pressed {

View File

@@ -4,6 +4,7 @@
display: flex;
align-items: flex-start;
box-sizing: border-box;
padding: 0 12px;
}
.discovery-photo-tool-card.is-pressed {
@@ -28,7 +29,7 @@
height: 142px;
display: flex;
flex-direction: column;
padding: 16px 12px 12px;
padding: 12px;
border-radius: 28px;
background: #ffffff;
box-sizing: border-box;
@@ -197,7 +198,7 @@
display: flex;
align-items: flex-start;
gap: 8px;
margin-top: 10px;
margin-top: 6px;
}
.photo-option {
@@ -250,7 +251,7 @@
.photo-option-label {
display: block;
max-width: 76px;
margin: 5px auto 0;
margin: 2px auto 0;
color: $theme-color-500;
font-size: 14px;
line-height: 18px;

View File

@@ -1,7 +1,5 @@
<template>
<view class="container pl-12">
<ModuleTitle :title="themeName" />
<view class="container-scroll font-size-0 scroll-x whitespace-nowrap">
<view class="card-item bg-white inline-block rounded-20 mr-10"

View File

@@ -1,5 +1,5 @@
.container-scroll {
margin: 4px 0 6px;
}
.card-item {

View File

@@ -6,16 +6,15 @@
<scroll-view class="discovery-scroll" scroll-y @scroll="handleContentScroll">
<view class="discovery-body">
<ExploreCards v-if="discoveryCards.length > 0 && isPanoramaGuideTab" :list="discoveryCards"
@didSelectItem="handleCardClick" />
<CardSwiper v-else-if="discoveryCards.length > 0" :list="discoveryCards" @didSelectItem="handleCardClick" />
<CardSwiper v-if="discoveryCards.length > 0" :list="discoveryCards" @didSelectItem="handleCardClick" />
<ExploreCards v-if="exploreCards.length > 0" :list="exploreCards" @didSelectItem="handleCardClick" />
<QuickQuestions v-if="discoveryQuickQuestions.length > 0" :list="discoveryQuickQuestions"
@didSelectItem="handleQuickQuestionClick" />
<!-- <DiscoveryPhotoToolCard @didSelectItem="handleToolCardClick" @didSelectOption="handleToolOptionClick" />
<DiscoveryAudioToolCard @didSelectItem="handleToolCardClick" />
<DiscoveryGuideMapToolCard @didSelectItem="handleToolCardClick" /> -->
<DiscoveryAudioToolCard @didSelectItem="handleToolCardClick" />
<DiscoveryGuideMapToolCard @didSelectItem="handleToolCardClick" /> -->
</view>
</scroll-view>
</view>
@@ -47,6 +46,7 @@ const sceneId = appStore.sceneId || "";
const activeIndex = ref(0);
const discoveryTabs = ref([]);
const discoveryCards = ref([]);
const exploreCards = ref([]);
const discoveryQuickQuestions = ref([]);
const emit = defineEmits(["content-scroll"]);
@@ -106,12 +106,26 @@ const queryDiscoveryData = async (tabId) => {
/// 请求发现页卡片数据
const queryDiscoveryCards = async (tabId) => {
const res = await homeTabContentData({ tagId: 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 });
@@ -246,5 +260,8 @@ onMounted(() => {
.discovery-body {
width: 100%;
gap: 12px;
display: flex;
flex-direction: column;
}
</style>

View File

@@ -0,0 +1,42 @@
export const getDiscoveryPanelCollapseState = ({
currentScrollTop = 0,
lastScrollTop = 0,
isCollapsed = false,
threshold = 16,
directionThreshold = 2,
allowExpand = true,
}) => {
const current = Math.max(Number(currentScrollTop) || 0, 0);
const last = Math.max(Number(lastScrollTop) || 0, 0);
const delta = current - last;
if (delta > directionThreshold && current > threshold) {
return true;
}
if (allowExpand && delta < -directionThreshold) {
return false;
}
return isCollapsed;
};
export const canExpandDiscoveryPanelFromScroll = ({
isTouching = false,
touchDirection = "",
lastDownGestureAt = 0,
now = Date.now(),
gestureRetainMs = 800,
}) => {
if (isTouching) {
return touchDirection === "down";
}
const lastDownAt = Math.max(Number(lastDownGestureAt) || 0, 0);
if (!lastDownAt) {
return false;
}
const currentTime = Math.max(Number(now) || 0, 0);
return currentTime - lastDownAt <= gestureRetainMs;
};