feat: 预览的组件
This commit is contained in:
@@ -73,11 +73,17 @@
|
||||
(item.componentName && isLongTextCard(item.componentName))
|
||||
"
|
||||
>
|
||||
<AnswerComponent
|
||||
<!-- <AnswerComponent
|
||||
v-if="isLongTextCard(item.componentName)"
|
||||
:longTextData="item.longTextData"
|
||||
:finish="item.finish"
|
||||
/> -->
|
||||
|
||||
<LongTextGuideCardPreview
|
||||
v-if="item.componentName && isLongTextCard(item.componentName)"
|
||||
:componentName="item.componentName"
|
||||
/>
|
||||
|
||||
<QuickBookingComponent
|
||||
v-if="
|
||||
item.toolCall &&
|
||||
@@ -103,27 +109,21 @@
|
||||
item.toolCall.componentName === CompName.mapCard
|
||||
"
|
||||
/>
|
||||
<!-- <GeneratorPhotoComponent
|
||||
<GeneratorPhotoComponent
|
||||
v-else-if="
|
||||
item.toolCall &&
|
||||
item.toolCall.componentName ===
|
||||
CompName.aigcPhotoGeneratorCard
|
||||
"
|
||||
:toolCall="item.toolCall"
|
||||
/> -->
|
||||
/>
|
||||
<!-- <ZModuleC01
|
||||
v-else-if="
|
||||
item.toolCall &&
|
||||
item.toolCall.componentName === CompName.aigcPhotoGeneratorCard
|
||||
"
|
||||
/> -->
|
||||
<LongTextGuideCardPreview
|
||||
v-else-if="
|
||||
item.toolCall &&
|
||||
item.toolCall.componentName === CompName.aigcPhotoGeneratorCard
|
||||
" :componentName="item.toolCall.componentName" />
|
||||
|
||||
|
||||
<Feedback
|
||||
v-else-if="
|
||||
item.toolCall &&
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
export const DETAIL_ROUTE_BY_TYPE = {
|
||||
longTextCard: "/pages/ChatModule/LongTextGuideCardPreview/guide",
|
||||
longTextCardSnap: "/pages/ChatModule/LongTextGuideCardPreview/poi",
|
||||
longTextCardRoute: "/pages/ChatModule/LongTextGuideCardPreview/route",
|
||||
longTextCardScenicSpot: "/pages/ChatModule/LongTextGuideCardPreview/photo",
|
||||
};
|
||||
|
||||
export const getLongTextGuideDetailRoute = (type) => {
|
||||
return DETAIL_ROUTE_BY_TYPE[type] || "";
|
||||
};
|
||||
|
||||
129
src/pages/ChatModule/LongTextGuideCardPreview/guide.vue
Normal file
129
src/pages/ChatModule/LongTextGuideCardPreview/guide.vue
Normal file
@@ -0,0 +1,129 @@
|
||||
<template>
|
||||
<view class="long-text-detail-page flex flex-col">
|
||||
<TopNavBar title="漂流攻略" background="#E5EFE9" />
|
||||
|
||||
<scroll-view class="long-text-detail-scroll" scroll-y>
|
||||
<view class="long-text-detail-content">
|
||||
<view class="long-text-detail-card">
|
||||
<view class="long-text-detail-header">
|
||||
<view class="long-text-detail-title">下水之前,先听小七唠两句</view>
|
||||
<view class="long-text-detail-badge is-amber">漂流攻略</view>
|
||||
</view>
|
||||
|
||||
<view class="long-text-detail-body">
|
||||
<view class="detail-paragraph">
|
||||
卧龙潭的水,是那种一眼就让人想跳进去的绿。
|
||||
<text class="detail-highlight">皮筏艇漂流</text>
|
||||
全程约两公里,三段激流接连而下,水花会结结实实拍在脸上。这趟值得冲,但晕水的朋友得先掂量掂量。
|
||||
</view>
|
||||
|
||||
<image
|
||||
class="detail-main-image"
|
||||
:src="comp1"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
|
||||
<view class="detail-section-title">下水前,这几样别落下</view>
|
||||
<view class="detail-tip-block">
|
||||
① 换洗衣服塞进防水袋,手机一定要封好<br />
|
||||
② 穿凉鞋或防滑鞋,拖鞋是真的不让下<br />
|
||||
③ 贵重东西先存好寄存柜,别揣身上
|
||||
</view>
|
||||
|
||||
<view class="detail-paragraph">
|
||||
小七的私心建议:挑
|
||||
<text class="detail-highlight">上午九点到十一点</text>
|
||||
这一场。水量足、太阳还没毒,漂下来浑身舒坦,不会被晒得发昏。
|
||||
</view>
|
||||
|
||||
<view class="detail-section-title">这些坑,提前绕开</view>
|
||||
<view class="detail-tip-block is-warn">
|
||||
雨后水量猛涨可能临时停漂,出发前先问一句开放状态;现场拖鞋不补租,光脚更危险。
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-zone">
|
||||
<view class="detail-action-label">相关票务</view>
|
||||
<scroll-view class="detail-product-scroll" scroll-x>
|
||||
<view class="detail-product-row">
|
||||
<view
|
||||
v-for="product in products"
|
||||
:key="product.name"
|
||||
class="detail-product-card"
|
||||
>
|
||||
<image class="detail-product-image" :src="product.img" mode="aspectFill" />
|
||||
<view class="detail-product-body">
|
||||
<view v-if="product.saleTag" class="detail-product-tag">
|
||||
{{ product.saleTag }}
|
||||
</view>
|
||||
<view class="detail-product-name">{{ product.name }}</view>
|
||||
<view class="detail-product-price">
|
||||
<text class="detail-product-currency">¥</text>{{ product.price }}
|
||||
<text v-if="product.original" class="detail-product-original">
|
||||
¥{{ product.original }}
|
||||
</text>
|
||||
</view>
|
||||
<button
|
||||
class="detail-buy-button"
|
||||
@click="showToast(`跳转商品详情页:${product.name}`)"
|
||||
>
|
||||
立即购买
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
|
||||
<view class="detail-action-label">继续追问</view>
|
||||
<view class="detail-faq-wrap">
|
||||
<view
|
||||
v-for="question in faq"
|
||||
:key="question"
|
||||
class="detail-faq-chip"
|
||||
@click="showToast(`追问:${question}`)"
|
||||
>
|
||||
{{ question }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||
import comp1 from "./images/comp1.jpg";
|
||||
import comp11 from "./images/comp11.jpg";
|
||||
import comp12 from "./images/comp12.jpg";
|
||||
|
||||
|
||||
const products = [
|
||||
{
|
||||
name: "卧龙潭皮筏艇漂流",
|
||||
img: comp11,
|
||||
price: "50",
|
||||
},
|
||||
{
|
||||
name: "鸳鸯湖玻璃船",
|
||||
img: comp12,
|
||||
price: "50",
|
||||
saleTag: "漂完顺路",
|
||||
},
|
||||
];
|
||||
|
||||
const faq = ["几岁的孩子能玩", "会不会全身湿透", "漂完去哪儿歇脚"];
|
||||
|
||||
const showToast = (title) => {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/detail.scss";
|
||||
</style>
|
||||
|
||||
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp1.jpg
Normal file
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp1.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 572 KiB |
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp11.jpg
Normal file
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp11.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.4 MiB |
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp12.jpg
Normal file
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp12.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 637 KiB |
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp2.jpg
Normal file
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp2.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 349 KiB |
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp4.jpg
Normal file
BIN
src/pages/ChatModule/LongTextGuideCardPreview/images/comp4.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 484 KiB |
@@ -25,11 +25,12 @@
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { defineProps,computed } from "vue";
|
||||
import { defineProps, computed } from "vue";
|
||||
import { getLongTextGuideDetailRoute } from "./detailRoutes.mjs";
|
||||
const props = defineProps({
|
||||
componentName: {
|
||||
type: String,
|
||||
default: 'longTextCard',
|
||||
default: 'longTextCardSnap',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -45,7 +46,7 @@ const longTextCard = {
|
||||
const longTextCardSnap = {
|
||||
type: 'longTextCardSnap',
|
||||
badge: "景点故事",
|
||||
badgeTone: "blue",
|
||||
badgeTone: "green",
|
||||
title: "小七孔古桥 · 走了三百年的石拱",
|
||||
summary: "小七孔古桥是一座三百岁的七孔石桥,小七孔的名字就从这儿来…",
|
||||
footer: "点击查看完整介绍",
|
||||
@@ -54,7 +55,7 @@ const longTextCardSnap = {
|
||||
const longTextCardRoute = {
|
||||
type: 'longTextCardRoute',
|
||||
badge: "路线指引",
|
||||
badgeTone: "green",
|
||||
badgeTone: "violet",
|
||||
title: "漂完卧龙潭,顺道去鸳鸯湖",
|
||||
summary: "卧龙潭到鸳鸯湖坐观光车约二十分钟。要紧的是鸳鸯湖分上下湖…",
|
||||
footer: "点击查看完整路线",
|
||||
@@ -63,7 +64,7 @@ const longTextCardRoute = {
|
||||
const longTextCardScenicSpot = {
|
||||
type: 'longTextCardScenicSpot',
|
||||
badge: "拍照攻略",
|
||||
badgeTone: "indigo",
|
||||
badgeTone: "blue",
|
||||
title: "鸳鸯湖玻璃船,这样拍才不亏",
|
||||
summary: "玻璃船拍照,关键是拍水下那抹通透的绿,顺光时段最出片…",
|
||||
footer: "点击查看完整攻略",
|
||||
@@ -80,12 +81,21 @@ const item = computed(() => {
|
||||
case 'longTextCardScenicSpot':
|
||||
return longTextCardScenicSpot;
|
||||
default:
|
||||
return longTextCard;
|
||||
return longTextCardSnap;
|
||||
}
|
||||
});
|
||||
|
||||
const openDetail = (item) => {
|
||||
/// 这里可以根据 item.type 来区分打开不同的详情页,目前先统一处理
|
||||
const url = getLongTextGuideDetailRoute(item.type);
|
||||
if (!url) {
|
||||
uni.showToast({
|
||||
title: "暂未配置详情页",
|
||||
icon: "none",
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
uni.navigateTo({ url });
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
119
src/pages/ChatModule/LongTextGuideCardPreview/photo.vue
Normal file
119
src/pages/ChatModule/LongTextGuideCardPreview/photo.vue
Normal file
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<view class="long-text-detail-page flex flex-col">
|
||||
<TopNavBar title="拍照攻略" background="#E5EFE9" />
|
||||
|
||||
<scroll-view class="long-text-detail-scroll" scroll-y>
|
||||
<view class="long-text-detail-content">
|
||||
<view class="long-text-detail-card">
|
||||
<view class="long-text-detail-header">
|
||||
<view class="long-text-detail-title">鸳鸯湖玻璃船,这样拍才不亏</view>
|
||||
<view class="long-text-detail-badge is-blue">拍照攻略</view>
|
||||
</view>
|
||||
|
||||
<view class="long-text-detail-body">
|
||||
<view class="detail-paragraph">
|
||||
鸳鸯湖的玻璃船,船底是透明的,水下世界看得清清楚楚。拍照的关键就一句话:
|
||||
<text class="detail-highlight">别只顾着拍人,把水下那抹通透的绿一起收进来。</text>
|
||||
</view>
|
||||
|
||||
<view class="detail-section-title">三个不会错的机位</view>
|
||||
<view class="detail-tip-block">
|
||||
① 蹲低,贴着透明船底拍,水草和光斑会铺满整个画面<br />
|
||||
② 船头回拍人物,背景是大片湖光,人物站三分之一处<br />
|
||||
③ 把手伸进光里,拍水面波纹和指尖,是很灵的细节
|
||||
</view>
|
||||
|
||||
<view class="detail-paragraph">
|
||||
时间上,挑
|
||||
<text class="detail-highlight">上午十点到下午两点</text>
|
||||
的顺光时段。阳光直直照进水里,那种绿才透得出来,阴天和傍晚,水色会闷,差很多。
|
||||
</view>
|
||||
|
||||
<view class="detail-section-title">手机党看这里</view>
|
||||
<view class="detail-tip-block">
|
||||
手机开 0.5x 广角,水面和船一起进画;隔着玻璃拍记得擦干净船底;逆光时手动点一下水面降曝光。
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-zone">
|
||||
<view class="detail-action-label">查看机位图</view>
|
||||
<view class="photo-card" @click="previewPhoto">
|
||||
<image class="photo-card-image" :src="photo.thumb" mode="aspectFill" />
|
||||
<view class="photo-card-caption">
|
||||
<view class="photo-card-title">{{ photo.title }}</view>
|
||||
<view class="photo-card-subtitle">{{ photo.sub }}</view>
|
||||
</view>
|
||||
<view class="photo-card-expand">↗</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-label">AIGC 合影</view>
|
||||
<view class="detail-action-card">
|
||||
<view class="aigc-cover">
|
||||
<image class="aigc-image" :src="aigc.img" mode="aspectFill" />
|
||||
<view class="aigc-badge">AI 生成</view>
|
||||
</view>
|
||||
<view class="aigc-body">
|
||||
<view class="aigc-title">{{ aigc.name }}</view>
|
||||
<view class="aigc-desc">{{ aigc.desc }}</view>
|
||||
<button class="detail-solid-button aigc-button" @click="showToast('跳转 AIGC 合影功能页')">
|
||||
生成我的合影
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-label">继续追问</view>
|
||||
<view class="detail-faq-wrap">
|
||||
<view
|
||||
v-for="question in faq"
|
||||
:key="question"
|
||||
class="detail-faq-chip"
|
||||
@click="showToast(`追问:${question}`)"
|
||||
>
|
||||
{{ question }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||
import comp4 from "./images/comp4.jpg";
|
||||
|
||||
const photo = {
|
||||
thumb: comp4,
|
||||
full: comp4,
|
||||
title: "玻璃船底机位",
|
||||
sub: "蹲低贴船底 · 上午顺光",
|
||||
};
|
||||
|
||||
const aigc = {
|
||||
name: "鸳鸯湖玻璃船 AIGC 合影",
|
||||
img: comp4,
|
||||
desc: "上船拍一张,小七帮你一键生成专属合影,不用求人也不用自拍杆。",
|
||||
};
|
||||
|
||||
const faq = ["几点光线最好", "船上能站起来拍吗", "穿什么颜色上镜"];
|
||||
|
||||
const previewPhoto = () => {
|
||||
uni.previewImage({
|
||||
current: photo.full,
|
||||
urls: [photo.full],
|
||||
});
|
||||
};
|
||||
|
||||
const showToast = (title) => {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/detail.scss";
|
||||
</style>
|
||||
|
||||
95
src/pages/ChatModule/LongTextGuideCardPreview/poi.vue
Normal file
95
src/pages/ChatModule/LongTextGuideCardPreview/poi.vue
Normal file
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<view class="long-text-detail-page flex flex-col">
|
||||
<TopNavBar title="景点故事" background="#E5EFE9" />
|
||||
|
||||
<scroll-view class="long-text-detail-scroll" scroll-y>
|
||||
<view class="long-text-detail-content">
|
||||
<view class="long-text-detail-card">
|
||||
<view class="long-text-detail-header">
|
||||
<view class="long-text-detail-title">小七孔古桥 · 走了三百年的石拱</view>
|
||||
<view class="long-text-detail-badge is-emerald">景点故事</view>
|
||||
</view>
|
||||
|
||||
<view class="long-text-detail-body">
|
||||
<view class="detail-paragraph">
|
||||
小七孔古桥静静卧在响水河上,七个石拱挨着排开,桥身爬满青苔藤蔓。它建于清道光年间,
|
||||
<text class="detail-highlight">三百多岁</text>
|
||||
了。整个景区的名字,就是从这座桥来的。
|
||||
</view>
|
||||
|
||||
<image
|
||||
class="detail-main-image"
|
||||
:src="comp2"
|
||||
mode="aspectFill"
|
||||
/>
|
||||
|
||||
<view class="detail-section-title">站在这儿,看什么</view>
|
||||
<view class="detail-tip-block">
|
||||
① 桥拱与水面倒影合成完整的圆,这是古桥最经典的一眼<br />
|
||||
② 桥身的青苔和藤蔓,是三百年时间慢慢长出来的<br />
|
||||
③ 桥下水浅处清澈见底,能看见鹅卵石和游鱼
|
||||
</view>
|
||||
|
||||
<view class="detail-paragraph">
|
||||
小七的建议:别急着走过去。先在桥侧站一会儿,古桥不是用来打卡的,是用来
|
||||
<text class="detail-highlight">慢慢看</text>
|
||||
的。光线斜下来的时候,石桥、绿水、倒影会一起把你框进画里。
|
||||
</view>
|
||||
|
||||
<view class="detail-section-title">顺带一提</view>
|
||||
<view class="detail-tip-block is-warn">
|
||||
桥面是三百年的老石头,雨后偏滑,慢点走;别翻护栏到桥下浅滩,既危险也伤桥。
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-zone">
|
||||
<view class="detail-action-label">查看景点详情</view>
|
||||
<view class="detail-action-card is-raised" @click="showToast('跳转 H5 景点详情页:小七孔古桥')">
|
||||
<view class="poi-mini-tag">核心地标</view>
|
||||
<view class="poi-mini-body">
|
||||
<view class="poi-mini-title">小七孔古桥</view>
|
||||
<view class="poi-mini-desc">
|
||||
清道光年间建的七孔石桥,响水河上的镇景之宝,小七孔之名由此而来,桥畔可观涵碧潭。
|
||||
</view>
|
||||
<button class="detail-solid-button" @click.stop="showToast('带我去:小七孔古桥')">
|
||||
带我去
|
||||
</button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-label">继续追问</view>
|
||||
<view class="detail-faq-wrap">
|
||||
<view
|
||||
v-for="question in faq"
|
||||
:key="question"
|
||||
class="detail-faq-chip"
|
||||
@click="showToast(`追问:${question}`)"
|
||||
>
|
||||
{{ question }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||
import comp2 from "./images/comp2.jpg";
|
||||
|
||||
const faq = ["古桥有什么传说", "最佳观赏时间", "旁边还有什么景点"];
|
||||
|
||||
const showToast = (title) => {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/detail.scss";
|
||||
</style>
|
||||
|
||||
150
src/pages/ChatModule/LongTextGuideCardPreview/route.vue
Normal file
150
src/pages/ChatModule/LongTextGuideCardPreview/route.vue
Normal file
@@ -0,0 +1,150 @@
|
||||
<template>
|
||||
<view class="long-text-detail-page flex flex-col">
|
||||
<TopNavBar title="路线指引" background="#E5EFE9" />
|
||||
|
||||
<scroll-view class="long-text-detail-scroll" scroll-y>
|
||||
<view class="long-text-detail-content">
|
||||
<view class="long-text-detail-card">
|
||||
<view class="long-text-detail-header">
|
||||
<view class="long-text-detail-title">漂完卧龙潭,顺道去鸳鸯湖</view>
|
||||
<view class="long-text-detail-badge is-violet">路线指引</view>
|
||||
</view>
|
||||
|
||||
<view class="long-text-detail-body">
|
||||
<view class="detail-paragraph">
|
||||
漂完卧龙潭,人多半是湿着、累着的。这时候去鸳鸯湖刚刚好。坐观光车顺路不绕,二十分钟左右就到。
|
||||
</view>
|
||||
|
||||
<view class="detail-section-title">鸳鸯湖分上下湖,先选好玩哪个</view>
|
||||
<view class="detail-paragraph">
|
||||
鸳鸯湖不是一个码头,它分成上下两个湖,玩的船不一样,
|
||||
<text class="detail-highlight">下车站点也不同</text>
|
||||
,上车前先选好。
|
||||
</view>
|
||||
|
||||
<view class="route-vs-wrap">
|
||||
<view class="route-vs-col">
|
||||
<view class="route-vs-head">上湖 · 鸳湖</view>
|
||||
<view class="route-vs-boat" style="color: #2563eb">玻璃船 ¥50</view>
|
||||
<view class="route-vs-row">
|
||||
透明船底,<text class="route-vs-bold">适合拍照</text>
|
||||
</view>
|
||||
<view class="route-vs-row">带老人孩子图轻松</view>
|
||||
<view class="route-vs-row">
|
||||
在 <text class="route-vs-bold">鸳鸯湖上湖站</text> 下车
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="route-vs-col">
|
||||
<view class="route-vs-head">下湖 · 鸯湖</view>
|
||||
<view class="route-vs-boat" style="color: #059669">铁皮船 ¥30</view>
|
||||
<view class="route-vs-row">自己划,1-6 人一船</view>
|
||||
<view class="route-vs-row">
|
||||
<text class="route-vs-bold">水上迷宫</text>穿林,更有乐趣
|
||||
</view>
|
||||
<view class="route-vs-row">
|
||||
在 <text class="route-vs-bold">鸳鸯湖站</text> 下车,再走 4 分钟
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-paragraph">时间够的话两个湖都能玩,中间有观光车接驳。</view>
|
||||
|
||||
<view class="detail-section-title">路上留个心</view>
|
||||
<view class="detail-tip-block is-warn">
|
||||
① 旺季观光车要排队,上午人最多<br />
|
||||
② 下湖枯水期水位低,水上迷宫游线可能关闭,购票前先问一句<br />
|
||||
③ 雨天石板路偏滑,带孩子老人慢一点
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-zone">
|
||||
<view class="detail-action-label">完整路线</view>
|
||||
<view class="route-step-card">
|
||||
<view class="route-step-title">卧龙潭 → 鸳鸯湖 · 看准上下湖</view>
|
||||
<view
|
||||
v-for="(step, index) in steps"
|
||||
:key="step.act"
|
||||
class="route-step"
|
||||
>
|
||||
<view class="route-step-index">{{ index + 1 }}</view>
|
||||
<view class="route-step-main">
|
||||
<view class="route-step-act">{{ step.act }}</view>
|
||||
<view class="route-step-meta">{{ step.meta }}</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="route-step-card">
|
||||
<view class="route-step-title">沿途设施</view>
|
||||
<view
|
||||
v-for="facility in facilities"
|
||||
:key="facility.label"
|
||||
class="facility-row"
|
||||
>
|
||||
<view class="facility-label">{{ facility.label }}</view>
|
||||
<view>{{ facility.text }}</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="detail-action-label">继续追问</view>
|
||||
<view class="detail-faq-wrap">
|
||||
<view
|
||||
v-for="question in faq"
|
||||
:key="question"
|
||||
class="detail-faq-chip"
|
||||
@click="showToast(`追问:${question}`)"
|
||||
>
|
||||
{{ question }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import TopNavBar from "@/components/TopNavBar/index.vue";
|
||||
|
||||
const steps = [
|
||||
{
|
||||
act: "卧龙潭码头 → 卧龙潭站",
|
||||
meta: "步行约 5 分钟 · 认准观光车乘车点",
|
||||
},
|
||||
{
|
||||
act: "上车前先认准方向:去上湖 or 下湖",
|
||||
meta: "两个湖站点不同,排队通道也不同,别走错",
|
||||
},
|
||||
{
|
||||
act: "A·去上湖玩玻璃船 → 鸳鸯湖上湖站下车",
|
||||
meta: "车程约 6 分钟 · 玻璃船 ¥50/人",
|
||||
},
|
||||
{
|
||||
act: "B·去下湖玩铁皮船 → 鸳鸯湖站下车",
|
||||
meta: "车程约 12 分钟 · 下车再步行 4 分钟 · 铁皮船 ¥30/人",
|
||||
},
|
||||
];
|
||||
|
||||
const facilities = [
|
||||
{ label: "换洗", text: "卧龙潭站 · 洗手间 + 换洗寄存点" },
|
||||
{ label: "休息", text: "鸳鸯湖上湖 · 美食驿站 + 休息亭" },
|
||||
{ label: "补给", text: "鸳鸯湖站 · 美食驿站 + 充电宝租赁" },
|
||||
{ label: "卫生间", text: "下湖卫生间在景点处,上湖卫生间在售票处前 150m" },
|
||||
];
|
||||
|
||||
const faq = ["上湖下湖哪个好玩", "玻璃船和铁皮船怎么选", "两个湖都玩来得及吗"];
|
||||
|
||||
const showToast = (title) => {
|
||||
uni.showToast({
|
||||
title,
|
||||
icon: "none",
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "./styles/detail.scss";
|
||||
</style>
|
||||
|
||||
530
src/pages/ChatModule/LongTextGuideCardPreview/styles/detail.scss
Normal file
530
src/pages/ChatModule/LongTextGuideCardPreview/styles/detail.scss
Normal file
@@ -0,0 +1,530 @@
|
||||
.long-text-detail-page {
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
background: #e5efe9;
|
||||
}
|
||||
|
||||
.long-text-detail-scroll {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.long-text-detail-content {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.long-text-detail-card {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.long-text-detail-header {
|
||||
padding: 16px 18px 14px;
|
||||
border-bottom: 1px solid rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.long-text-detail-title {
|
||||
color: #1e293b;
|
||||
font-size: 18px;
|
||||
font-weight: 900;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.long-text-detail-badge {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
min-height: 24px;
|
||||
margin-top: 10px;
|
||||
padding: 0 10px;
|
||||
align-items: center;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 999px;
|
||||
font-size: 11px;
|
||||
font-weight: 900;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.long-text-detail-badge.is-amber {
|
||||
color: #d97706;
|
||||
background: #fffbeb;
|
||||
border-color: #fde68a;
|
||||
}
|
||||
|
||||
.long-text-detail-badge.is-emerald {
|
||||
color: #047857;
|
||||
background: #ecfdf5;
|
||||
border-color: #a7f3d0;
|
||||
}
|
||||
|
||||
.long-text-detail-badge.is-violet {
|
||||
color: #7c3aed;
|
||||
background: #f5f3ff;
|
||||
border-color: #ddd6fe;
|
||||
}
|
||||
|
||||
.long-text-detail-badge.is-blue {
|
||||
color: #2563eb;
|
||||
background: #eff6ff;
|
||||
border-color: #bfdbfe;
|
||||
}
|
||||
|
||||
.long-text-detail-body {
|
||||
padding: 18px 18px 4px;
|
||||
}
|
||||
|
||||
.detail-paragraph {
|
||||
margin-bottom: 14px;
|
||||
color: #475569;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 24px;
|
||||
}
|
||||
|
||||
.detail-highlight {
|
||||
padding: 1px 5px;
|
||||
border-radius: 4px;
|
||||
color: #065f46;
|
||||
background: #ecfdf5;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.detail-section-title {
|
||||
margin: 18px 0 8px;
|
||||
color: #1e293b;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.detail-main-image {
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
margin: 4px 0 16px;
|
||||
border-radius: 14px;
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.detail-tip-block {
|
||||
margin: 4px 0 16px;
|
||||
padding: 10px 14px;
|
||||
border-left: 3px solid #34d399;
|
||||
border-radius: 12px;
|
||||
color: #065f46;
|
||||
background: #f0fdf4;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.detail-tip-block.is-warn {
|
||||
color: #92400e;
|
||||
background: #fffbeb;
|
||||
border-left-color: #fbbf24;
|
||||
}
|
||||
|
||||
.detail-action-zone {
|
||||
margin-top: 4px;
|
||||
padding-bottom: 20px;
|
||||
border-top: 1px solid rgba(15, 23, 42, 0.06);
|
||||
}
|
||||
|
||||
.detail-action-label {
|
||||
padding: 12px 18px 8px;
|
||||
color: #94a3b8;
|
||||
font-size: 10px;
|
||||
font-weight: 900;
|
||||
letter-spacing: 0.6px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.detail-action-card {
|
||||
margin: 0 16px 12px;
|
||||
overflow: hidden;
|
||||
border: 1px solid #f1f5f9;
|
||||
border-radius: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.detail-action-card.is-raised {
|
||||
border-radius: 24px;
|
||||
box-shadow: 0 4px 20px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.poi-mini-tag {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
margin: 14px 0 0 14px;
|
||||
padding: 4px 10px;
|
||||
align-items: center;
|
||||
border-radius: 8px;
|
||||
color: #059669;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
box-shadow: 0 1px 4px rgba(15, 23, 42, 0.08);
|
||||
font-size: 10px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.poi-mini-body {
|
||||
padding: 10px 20px 16px;
|
||||
}
|
||||
|
||||
.poi-mini-title {
|
||||
margin-bottom: 10px;
|
||||
color: #1e293b;
|
||||
font-size: 19px;
|
||||
font-weight: 900;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.poi-mini-desc {
|
||||
margin-bottom: 12px;
|
||||
padding: 10px 12px;
|
||||
border: 1px solid rgba(167, 243, 208, 0.5);
|
||||
border-radius: 12px;
|
||||
color: #065f46;
|
||||
background: linear-gradient(to right, #ecfdf5, rgba(240, 253, 250, 0.5));
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.detail-solid-button {
|
||||
width: 100%;
|
||||
height: 42px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 14px;
|
||||
color: #fff;
|
||||
background: #0f172a;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
line-height: 42px;
|
||||
}
|
||||
|
||||
.detail-solid-button::after {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.detail-product-scroll {
|
||||
width: 100%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.detail-product-row {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
padding: 0 16px 2px;
|
||||
}
|
||||
|
||||
.detail-product-card {
|
||||
width: 220px;
|
||||
flex-shrink: 0;
|
||||
overflow: hidden;
|
||||
border: 1px solid #f1f5f9;
|
||||
border-radius: 20px;
|
||||
background: #fff;
|
||||
box-shadow: 0 2px 12px rgba(15, 23, 42, 0.04);
|
||||
}
|
||||
|
||||
.detail-product-image {
|
||||
width: 100%;
|
||||
height: 110px;
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.detail-product-body {
|
||||
padding: 10px 12px 12px;
|
||||
}
|
||||
|
||||
.detail-product-tag {
|
||||
display: inline-flex;
|
||||
width: fit-content;
|
||||
margin-bottom: 4px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 6px;
|
||||
color: #f43f5e;
|
||||
background: #fef2f2;
|
||||
font-size: 9px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.detail-product-name {
|
||||
overflow: hidden;
|
||||
color: #1e293b;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
line-height: 20px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.detail-product-price {
|
||||
margin: 4px 0 8px;
|
||||
color: #f43f5e;
|
||||
font-size: 20px;
|
||||
font-weight: 900;
|
||||
line-height: 26px;
|
||||
}
|
||||
|
||||
.detail-product-currency {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.detail-product-original {
|
||||
margin-left: 4px;
|
||||
color: #cbd5e1;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
|
||||
.detail-buy-button {
|
||||
width: 100%;
|
||||
height: 34px;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
border-radius: 12px;
|
||||
color: #451a03;
|
||||
background: #fbbf24;
|
||||
font-size: 12px;
|
||||
font-weight: 900;
|
||||
line-height: 34px;
|
||||
}
|
||||
|
||||
.detail-buy-button::after {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.detail-faq-wrap {
|
||||
margin: 0 16px;
|
||||
}
|
||||
|
||||
.detail-faq-chip {
|
||||
display: inline-flex;
|
||||
margin: 0 6px 8px 0;
|
||||
padding: 8px 13px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 20px;
|
||||
color: #475569;
|
||||
background: #fff;
|
||||
font-size: 11.5px;
|
||||
font-weight: 800;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.route-vs-wrap {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin: 6px 0 16px;
|
||||
}
|
||||
|
||||
.route-vs-col {
|
||||
flex: 1;
|
||||
padding: 11px 12px;
|
||||
border: 1px solid #e8edf2;
|
||||
border-radius: 12px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.route-vs-head {
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 7px;
|
||||
border-bottom: 1px dashed #d8e0e8;
|
||||
color: #1e293b;
|
||||
font-size: 12px;
|
||||
font-weight: 900;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.route-vs-boat {
|
||||
margin-bottom: 7px;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.route-vs-row {
|
||||
margin-bottom: 5px;
|
||||
color: #64748b;
|
||||
font-size: 11px;
|
||||
font-weight: 600;
|
||||
line-height: 17px;
|
||||
}
|
||||
|
||||
.route-vs-bold {
|
||||
color: #334155;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.route-step-card {
|
||||
margin: 0 16px 12px;
|
||||
padding: 14px 16px;
|
||||
border: 1px solid rgba(15, 23, 42, 0.07);
|
||||
border-radius: 16px;
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.route-step-title {
|
||||
margin-bottom: 12px;
|
||||
color: #1e293b;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.route-step {
|
||||
display: flex;
|
||||
gap: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.route-step:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.route-step-index {
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
flex-shrink: 0;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
background: #8b5cf6;
|
||||
font-size: 10px;
|
||||
font-weight: 900;
|
||||
line-height: 18px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.route-step-main {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.route-step-act {
|
||||
color: #334155;
|
||||
font-size: 12px;
|
||||
font-weight: 800;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.route-step-meta {
|
||||
margin-top: 1px;
|
||||
color: #94a3b8;
|
||||
font-size: 10.5px;
|
||||
font-weight: 700;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.facility-row {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
padding: 5px 0;
|
||||
color: #475569;
|
||||
font-size: 11.5px;
|
||||
font-weight: 700;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.facility-label {
|
||||
width: 52px;
|
||||
flex-shrink: 0;
|
||||
color: #7c3aed;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.photo-card {
|
||||
position: relative;
|
||||
margin: 0 16px 12px;
|
||||
overflow: hidden;
|
||||
border-radius: 16px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.photo-card-image {
|
||||
width: 100%;
|
||||
height: 200px;
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.photo-card-caption {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
padding: 28px 14px 12px;
|
||||
background: linear-gradient(to top, rgba(15, 23, 42, 0.58), rgba(15, 23, 42, 0));
|
||||
}
|
||||
|
||||
.photo-card-title {
|
||||
color: #fff;
|
||||
font-size: 13px;
|
||||
font-weight: 900;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.photo-card-subtitle {
|
||||
margin-top: 2px;
|
||||
color: rgba(255, 255, 255, 0.78);
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.photo-card-expand {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
background: rgba(15, 23, 42, 0.38);
|
||||
font-size: 18px;
|
||||
font-weight: 800;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.aigc-image {
|
||||
width: 100%;
|
||||
height: 160px;
|
||||
background: #f1f5f9;
|
||||
}
|
||||
|
||||
.aigc-cover {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.aigc-badge {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 10px;
|
||||
padding: 4px 10px;
|
||||
border-radius: 10px;
|
||||
color: #fff;
|
||||
background: linear-gradient(135deg, #8b5cf6, #6366f1);
|
||||
box-shadow: 0 2px 8px rgba(99, 102, 241, 0.35);
|
||||
font-size: 10px;
|
||||
font-weight: 900;
|
||||
}
|
||||
|
||||
.aigc-body {
|
||||
padding: 12px 14px 14px;
|
||||
}
|
||||
|
||||
.aigc-title {
|
||||
color: #1e293b;
|
||||
font-size: 15px;
|
||||
font-weight: 900;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
.aigc-desc {
|
||||
margin: 5px 0 12px;
|
||||
color: #64748b;
|
||||
font-size: 11.5px;
|
||||
font-weight: 700;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
.aigc-button {
|
||||
background: linear-gradient(135deg, #8b5cf6, #6366f1);
|
||||
}
|
||||
@@ -39,6 +39,12 @@
|
||||
border-color: #a7f3d0;
|
||||
}
|
||||
|
||||
.long-text-guide-card__badge.is-violet {
|
||||
color: #7c3aed;
|
||||
background: #f5f3ff;
|
||||
border-color: #ddd6fe;
|
||||
}
|
||||
|
||||
.long-text-guide-card__badge.is-blue {
|
||||
color: #2563eb;
|
||||
background: #eff6ff;
|
||||
|
||||
651
src/pages/ChatModule/LongTextGuideCardPreview/长文本收纳组件_4类演示.html
Normal file
651
src/pages/ChatModule/LongTextGuideCardPreview/长文本收纳组件_4类演示.html
Normal file
@@ -0,0 +1,651 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>长文本收纳组件 · 4 类演示</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<style>
|
||||
body { background: #E5EFE9; font-family: -apple-system, BlinkMacSystemFont, 'PingFang SC', sans-serif; padding: 24px 16px; }
|
||||
@keyframes fade-in-up { from { opacity:0; transform:translateY(12px); } to { opacity:1; transform:translateY(0); } }
|
||||
.animate-fade-in-up { animation: fade-in-up 0.4s ease both; }
|
||||
|
||||
/* ── page slide ── */
|
||||
.c0-screen { position: relative; overflow: hidden; }
|
||||
.c0-page { position: absolute; top:0; left:0; width:100%; transition: transform 0.32s cubic-bezier(0.4,0,0.2,1); }
|
||||
.c0-page.p1 { transform: translateX(0); }
|
||||
.c0-page.p2 { transform: translateX(100%); }
|
||||
.c0-page.p1.out { transform: translateX(-100%); }
|
||||
.c0-page.p2.in { transform: translateX(0); }
|
||||
|
||||
/* ── p1 summary card ── */
|
||||
.p1-card { background:#fff; border-radius:24px; border:1px solid rgba(0,0,0,0.06); overflow:hidden; cursor:pointer; transition:transform 0.15s; -webkit-tap-highlight-color:transparent; }
|
||||
.p1-card:active { transform:scale(0.98); }
|
||||
|
||||
/* ── p2 wrap ── */
|
||||
.p2-wrap { background:#fff; border-radius:24px; border:1px solid rgba(0,0,0,0.06); overflow:hidden; }
|
||||
.p2-header { display:flex; align-items:center; gap:10px; padding:14px 16px 12px; border-bottom:0.5px solid rgba(0,0,0,0.06); }
|
||||
.back-btn { width:28px; height:28px; border-radius:50%; background:#f2f2f2; display:flex; align-items:center; justify-content:center; cursor:pointer; font-size:18px; line-height:1; color:#555; transition:background 0.15s; flex-shrink:0; -webkit-tap-highlight-color:transparent; }
|
||||
.back-btn:active { background:#ddd; }
|
||||
|
||||
/* ── rich body ── */
|
||||
.rich-body { padding:18px 18px 4px; }
|
||||
.rich-body p { font-size:13px; color:#475569; line-height:1.85; font-weight:500; margin-bottom:14px; }
|
||||
.rich-body strong { color:#065f46; background:#ecfdf5; padding:1px 5px; border-radius:4px; font-weight:800; }
|
||||
.rich-body h5 { font-size:13px; font-weight:800; color:#1e293b; margin:18px 0 8px; }
|
||||
.rich-img { width:100%; border-radius:14px; object-fit:cover; margin:4px 0 16px; display:block; height:160px; }
|
||||
.tip-block { background:#f0fdf4; border-radius:12px; border-left:3px solid #34d399; padding:10px 14px; margin:4px 0 16px; font-size:12px; color:#065f46; font-weight:700; line-height:1.7; }
|
||||
.tip-block.warn { background:#fffbeb; border-left-color:#fbbf24; color:#92400e; }
|
||||
|
||||
/* ── 双栏对照卡(上下湖对比专用)── */
|
||||
.vs-wrap { display:flex; gap:8px; margin:6px 0 16px; }
|
||||
.vs-col { flex:1; background:#f8fafc; border:1px solid #e8edf2; border-radius:12px; padding:11px 12px; }
|
||||
.vs-col .vs-head { display:flex; align-items:center; gap:5px; font-size:12px; font-weight:900; color:#1e293b; margin-bottom:8px; padding-bottom:7px; border-bottom:1px dashed #d8e0e8; }
|
||||
.vs-col .vs-dot { width:7px; height:7px; border-radius:50%; flex-shrink:0; }
|
||||
.vs-col .vs-row { font-size:11px; font-weight:600; color:#64748b; line-height:1.5; margin-bottom:5px; }
|
||||
.vs-col .vs-row:last-child { margin-bottom:0; }
|
||||
.vs-col .vs-row b { color:#334155; font-weight:800; }
|
||||
.vs-col .vs-boat { font-size:13px; font-weight:900; margin-bottom:7px; }
|
||||
|
||||
/* ── action zone shell ── */
|
||||
.action-zone { border-top:0.5px solid rgba(0,0,0,0.06); margin-top:4px; }
|
||||
.action-zone-label { font-size:10px; font-weight:800; color:#94a3b8; letter-spacing:0.6px; text-transform:uppercase; padding:12px 18px 8px; }
|
||||
.action-zone-bottom { height:20px; }
|
||||
|
||||
/* ── C1 景点详情 mini ── */
|
||||
.c1-mini { margin:0 16px; background:#fff; border-radius:24px; overflow:hidden; box-shadow:0 4px 20px rgba(0,0,0,0.04); border:1px solid #f1f5f9; cursor:pointer; -webkit-tap-highlight-color:transparent; transition:transform 0.15s; }
|
||||
.c1-mini:active { transform:scale(0.98); }
|
||||
.c1-mini .c1-tag { display:inline-flex; align-items:center; gap:4px; background:rgba(255,255,255,0.9); color:#059669; font-size:10px; font-weight:900; padding:4px 10px; border-radius:8px; box-shadow:0 1px 4px rgba(0,0,0,0.08); margin:14px 0 0 14px; width:fit-content; }
|
||||
.c1-mini .c1-body { padding:10px 20px 16px; }
|
||||
.c1-mini .c1-title { font-size:19px; font-weight:900; color:#1e293b; margin-bottom:10px; letter-spacing:-0.3px; }
|
||||
.c1-mini .c1-desc { background:linear-gradient(to right, #ecfdf5, rgba(240,253,250,0.5)); border-radius:12px; padding:10px 12px; margin-bottom:12px; border:1px solid rgba(167,243,208,0.5); display:flex; align-items:flex-start; gap:8px; }
|
||||
.c1-mini .c1-desc p { font-size:12px; font-weight:700; color:#065f46; line-height:1.55; margin:0; }
|
||||
.c1-mini .c1-btn { width:100%; background:#0f172a; color:#fff; border:none; border-radius:14px; padding:12px; font-size:13px; font-weight:900; display:flex; align-items:center; justify-content:center; gap:6px; cursor:pointer; -webkit-tap-highlight-color:transparent; transition:transform 0.15s; }
|
||||
.c1-mini .c1-btn:active { transform:scale(0.97); }
|
||||
|
||||
/* ── C8 地图点位 mini ── */
|
||||
.c8-mini { margin:0 16px; border-radius:16px; overflow:hidden; border:0.5px solid rgba(0,0,0,0.07); }
|
||||
.c8-mini .c8-img-wrap { position:relative; }
|
||||
.c8-mini .c8-img { width:100%; height:160px; object-fit:cover; display:block; }
|
||||
.c8-mini .c8-dest-tag { position:absolute; bottom:10px; left:10px; background:rgba(0,0,0,0.4); border-radius:10px; padding:4px 10px 4px 8px; display:flex; align-items:center; gap:5px; font-size:11px; font-weight:900; color:#fff; }
|
||||
.c8-mini .c8-bar { background:#fff; padding:12px 14px; display:flex; align-items:center; gap:10px; }
|
||||
.c8-mini .c8-info { flex:1; min-width:0; }
|
||||
.c8-mini .c8-name { font-size:15px; font-weight:900; color:#1e293b; }
|
||||
.c8-mini .c8-dist { font-size:11px; color:#94a3b8; font-weight:700; margin-top:2px; }
|
||||
.c8-mini .c8-btn { background:#0f172a; color:#fff; border:none; border-radius:14px; padding:10px 20px; font-size:13px; font-weight:900; display:flex; align-items:center; gap:6px; cursor:pointer; flex-shrink:0; -webkit-tap-highlight-color:transparent; transition:transform 0.15s; }
|
||||
.c8-mini .c8-btn:active { transform:scale(0.96); }
|
||||
|
||||
/* ── C9 商品卡轮播 ── */
|
||||
.c9-scroll { display:flex; gap:10px; overflow-x:auto; padding:0 16px; -webkit-overflow-scrolling:touch; scroll-snap-type:x mandatory; }
|
||||
.c9-scroll::-webkit-scrollbar { display:none; }
|
||||
.c9-card { background:#fff; border-radius:20px; border:1px solid #f1f5f9; overflow:hidden; flex-shrink:0; width:220px; scroll-snap-align:start; box-shadow:0 2px 12px rgba(0,0,0,0.04); }
|
||||
.c9-card .c9-thumb { width:100%; height:110px; object-fit:cover; display:block; }
|
||||
.c9-card .c9-body { padding:10px 12px 12px; }
|
||||
.c9-card .c9-name { font-size:13px; font-weight:900; color:#1e293b; margin-bottom:6px; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
|
||||
.c9-card .c9-price-row { display:flex; align-items:baseline; gap:4px; margin-bottom:8px; }
|
||||
.c9-card .c9-price { font-size:20px; font-weight:900; color:#f43f5e; letter-spacing:-0.5px; }
|
||||
.c9-card .c9-currency { font-size:12px; font-weight:900; color:#f43f5e; }
|
||||
.c9-card .c9-original { font-size:11px; font-weight:700; color:#cbd5e1; text-decoration:line-through; }
|
||||
.c9-card .c9-btn { width:100%; background:#fbbf24; color:#451a03; border:none; border-radius:12px; padding:8px; font-size:12px; font-weight:900; cursor:pointer; -webkit-tap-highlight-color:transparent; transition:transform 0.15s; }
|
||||
.c9-card .c9-btn:active { transform:scale(0.97); }
|
||||
.c9-card .c9-sale-tag { display:inline-block; background:#fef2f2; color:#f43f5e; font-size:9px; font-weight:900; padding:2px 6px; border-radius:6px; margin-bottom:4px; }
|
||||
|
||||
/* ── AIGC 合影 mini ── */
|
||||
.aigc-mini { margin:0 16px; border-radius:16px; overflow:hidden; border:0.5px solid rgba(0,0,0,0.07); background:#fff; }
|
||||
.aigc-mini .aigc-img-wrap { position:relative; }
|
||||
.aigc-mini .aigc-img { width:100%; height:160px; object-fit:cover; display:block; }
|
||||
.aigc-mini .aigc-badge { position:absolute; top:10px; left:10px; background:linear-gradient(135deg,#8b5cf6,#6366f1); border-radius:10px; padding:4px 10px 4px 8px; display:flex; align-items:center; gap:5px; font-size:10px; font-weight:900; color:#fff; box-shadow:0 2px 8px rgba(99,102,241,0.4); }
|
||||
.aigc-mini .aigc-body { padding:12px 14px 14px; }
|
||||
.aigc-mini .aigc-name { font-size:15px; font-weight:900; color:#1e293b; margin-bottom:5px; }
|
||||
.aigc-mini .aigc-desc { font-size:11.5px; font-weight:700; color:#64748b; line-height:1.6; margin-bottom:12px; }
|
||||
.aigc-mini .aigc-btn { width:100%; background:linear-gradient(135deg,#8b5cf6,#6366f1); color:#fff; border:none; border-radius:14px; padding:11px; font-size:13px; font-weight:900; display:flex; align-items:center; justify-content:center; gap:6px; cursor:pointer; -webkit-tap-highlight-color:transparent; transition:transform 0.15s; }
|
||||
.aigc-mini .aigc-btn:active { transform:scale(0.97); }
|
||||
|
||||
/* ── C4 路线步骤 mini ── */
|
||||
.c4-mini { margin:0 16px; background:#fff; border-radius:16px; border:0.5px solid rgba(0,0,0,0.07); padding:14px 16px; }
|
||||
.c4-mini .c4-head { display:flex; align-items:center; gap:6px; font-size:13px; font-weight:900; color:#1e293b; margin-bottom:12px; }
|
||||
.c4-step { display:flex; gap:10px; margin-bottom:10px; }
|
||||
.c4-step:last-child { margin-bottom:0; }
|
||||
.c4-step .c4-dot { width:18px; height:18px; border-radius:50%; background:#8b5cf6; color:#fff; font-size:10px; font-weight:900; display:flex; align-items:center; justify-content:center; flex-shrink:0; }
|
||||
.c4-step .c4-line { flex:1; }
|
||||
.c4-step .c4-act { font-size:12px; font-weight:800; color:#334155; line-height:1.5; }
|
||||
.c4-step .c4-meta { font-size:10.5px; color:#94a3b8; font-weight:700; margin-top:1px; }
|
||||
|
||||
/* ── C5 设施位置 mini ── */
|
||||
.c5-mini { margin:10px 16px 0; background:#fff; border-radius:16px; border:0.5px solid rgba(0,0,0,0.07); padding:12px 16px; }
|
||||
.c5-mini .c5-head { display:flex; align-items:center; gap:6px; font-size:12px; font-weight:900; color:#1e293b; margin-bottom:8px; }
|
||||
.c5-row { display:flex; align-items:center; gap:8px; padding:5px 0; font-size:11.5px; font-weight:700; color:#475569; }
|
||||
.c5-row .c5-ic { width:16px; text-align:center; }
|
||||
|
||||
/* ── C12 FAQ mini ── */
|
||||
.c12-mini { margin:10px 16px 0; }
|
||||
.c12-chip { display:inline-flex; align-items:center; gap:5px; background:#fff; border:1px solid #e2e8f0; border-radius:20px; padding:8px 13px; font-size:11.5px; font-weight:800; color:#475569; margin:0 6px 8px 0; cursor:pointer; -webkit-tap-highlight-color:transparent; transition:all 0.15s; }
|
||||
.c12-chip:active { transform:scale(0.96); background:#f1f5f9; }
|
||||
.c12-chip svg { color:#10b981; }
|
||||
|
||||
/* lightbox */
|
||||
.lightbox { position:fixed; inset:0; z-index:999; background:rgba(0,0,0,0.92); display:flex; align-items:center; justify-content:center; opacity:0; pointer-events:none; transition:opacity 0.25s ease; }
|
||||
.lightbox.open { opacity:1; pointer-events:all; }
|
||||
.lightbox img { max-width:100%; max-height:100%; border-radius:4px; transform:scale(0.94); transition:transform 0.28s cubic-bezier(0.4,0,0.2,1); }
|
||||
.lightbox.open img { transform:scale(1); }
|
||||
.lb-close { position:absolute; top:20px; right:20px; width:34px; height:34px; border-radius:50%; background:rgba(255,255,255,0.15); display:flex; align-items:center; justify-content:center; cursor:pointer; }
|
||||
|
||||
/* 跳转链路浮层 */
|
||||
.flow-toast { position:fixed; left:50%; bottom:32px; transform:translateX(-50%) translateY(20px); background:#0f172a; color:#fff; font-size:12px; font-weight:700; padding:11px 18px; border-radius:14px; box-shadow:0 8px 30px rgba(0,0,0,0.25); opacity:0; pointer-events:none; transition:all 0.3s cubic-bezier(0.4,0,0.2,1); max-width:340px; line-height:1.6; z-index:888; }
|
||||
.flow-toast.show { opacity:1; transform:translateX(-50%) translateY(0); }
|
||||
.flow-toast .ft-label { color:#fbbf24; font-weight:900; margin-right:4px; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="max-w-[390px] mx-auto">
|
||||
|
||||
<!-- ════ 标题区 ════ -->
|
||||
<div class="flex flex-col items-start gap-3 w-full mb-6 animate-fade-in-up">
|
||||
<div class="flex items-center gap-2 px-1">
|
||||
<div class="w-8 h-8 rounded-full border-[1.5px] border-emerald-100 shadow-sm overflow-hidden shrink-0 bg-emerald-50 flex items-center justify-center text-[15px]">🐯</div>
|
||||
<span class="text-[12px] font-black text-slate-800">小七 · 荔波小七孔 AI 伴游</span>
|
||||
</div>
|
||||
<div class="ml-1">
|
||||
<span class="bg-slate-900 text-white text-[9px] font-black px-2 py-1 rounded-md tracking-widest uppercase mr-2">演示</span>
|
||||
<span class="text-[12px] font-black text-slate-800">长文本收纳组件 · 4 类</span>
|
||||
</div>
|
||||
<p class="ml-1 text-[11px] font-bold text-slate-400 leading-relaxed">
|
||||
点击卡片 = 折叠态展开为完整内容。<br>
|
||||
展开后下半部分是「行动条」,挂载真实可点击的组件。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- ════ 屏幕 ════ -->
|
||||
<div class="c0-screen w-full animate-fade-in-up" id="screen">
|
||||
|
||||
<!-- ─── p1 折叠态卡片列表 ─── -->
|
||||
<div class="c0-page p1 w-full" id="p1">
|
||||
|
||||
<!-- 攻略型 -->
|
||||
<div class="p1-card mb-3" onclick="goDetail('guide')">
|
||||
<div class="p-5">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="text-[10px] font-black text-amber-600 bg-amber-50 px-2 py-0.5 rounded-full border border-amber-100">漂流攻略</span>
|
||||
<span class="text-[9px] font-bold text-slate-300">长文本-攻略组件</span>
|
||||
</div>
|
||||
<h4 class="text-[14px] font-black text-slate-800 mb-1.5">下水之前,先听小七唠两句</h4>
|
||||
<p class="text-[12px] text-slate-400 font-medium leading-relaxed line-clamp-2" id="sum-guide"></p>
|
||||
</div>
|
||||
<div class="px-5 pb-4 flex items-center justify-between">
|
||||
<span class="text-[11px] text-slate-300 font-bold">点击查看完整攻略</span>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 3l4 4-4 4" stroke="#cbd5e1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 景点型 -->
|
||||
<div class="p1-card mb-3" onclick="goDetail('poi')">
|
||||
<div class="p-5">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="text-[10px] font-black text-emerald-700 bg-emerald-50 px-2 py-0.5 rounded-full border border-emerald-100">景点故事</span>
|
||||
<span class="text-[9px] font-bold text-slate-300">长文本-景点组件</span>
|
||||
</div>
|
||||
<h4 class="text-[14px] font-black text-slate-800 mb-1.5">小七孔古桥 · 走了三百年的石拱</h4>
|
||||
<p class="text-[12px] text-slate-400 font-medium leading-relaxed line-clamp-2" id="sum-poi"></p>
|
||||
</div>
|
||||
<div class="px-5 pb-4 flex items-center justify-between">
|
||||
<span class="text-[11px] text-slate-300 font-bold">点击查看完整介绍</span>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 3l4 4-4 4" stroke="#cbd5e1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 路线型 -->
|
||||
<div class="p1-card mb-3" onclick="goDetail('nav')">
|
||||
<div class="p-5">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="text-[10px] font-black text-violet-600 bg-violet-50 px-2 py-0.5 rounded-full border border-violet-100">路线指引</span>
|
||||
<span class="text-[9px] font-bold text-slate-300">长文本-路线组件</span>
|
||||
</div>
|
||||
<h4 class="text-[14px] font-black text-slate-800 mb-1.5">漂完卧龙潭,顺道去鸳鸯湖</h4>
|
||||
<p class="text-[12px] text-slate-400 font-medium leading-relaxed line-clamp-2" id="sum-nav"></p>
|
||||
</div>
|
||||
<div class="px-5 pb-4 flex items-center justify-between">
|
||||
<span class="text-[11px] text-slate-300 font-bold">点击查看完整路线</span>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 3l4 4-4 4" stroke="#cbd5e1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 拍照型 -->
|
||||
<div class="p1-card" onclick="goDetail('photo')">
|
||||
<div class="p-5">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span class="text-[10px] font-black text-blue-600 bg-blue-50 px-2 py-0.5 rounded-full border border-blue-100">拍照攻略</span>
|
||||
<span class="text-[9px] font-bold text-slate-300">长文本-拍照组件</span>
|
||||
</div>
|
||||
<h4 class="text-[14px] font-black text-slate-800 mb-1.5">鸳鸯湖玻璃船,这样拍才不亏</h4>
|
||||
<p class="text-[12px] text-slate-400 font-medium leading-relaxed line-clamp-2" id="sum-photo"></p>
|
||||
</div>
|
||||
<div class="px-5 pb-4 flex items-center justify-between">
|
||||
<span class="text-[11px] text-slate-300 font-bold">点击查看完整攻略</span>
|
||||
<svg width="14" height="14" viewBox="0 0 14 14" fill="none"><path d="M5 3l4 4-4 4" stroke="#cbd5e1" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- ─── p2 展开态 ─── -->
|
||||
<div class="c0-page p2 w-full" id="p2">
|
||||
<div class="p2-wrap">
|
||||
<div class="p2-header">
|
||||
<div class="back-btn" onclick="goBack()">‹</div>
|
||||
<span class="text-[14px] font-black text-slate-800" id="p2-title"></span>
|
||||
<span class="text-[10px] font-bold px-2 py-0.5 rounded-full ml-auto border" id="p2-badge"></span>
|
||||
</div>
|
||||
<div class="rich-body" id="rich-body"></div>
|
||||
<div class="action-zone" id="action-zone"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- lightbox -->
|
||||
<div class="lightbox" id="lightbox" onclick="closeLB()">
|
||||
<div class="lb-close" onclick="closeLB()">
|
||||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||||
</div>
|
||||
<img id="lb-img" src="" alt="大图" onclick="event.stopPropagation()">
|
||||
</div>
|
||||
|
||||
<!-- 跳转链路提示 -->
|
||||
<div class="flow-toast" id="flowToast"></div>
|
||||
|
||||
<script>
|
||||
/* ════════════════════════════════
|
||||
ACTION ZONE BUILDERS
|
||||
════════════════════════════════ */
|
||||
|
||||
/* 景点详情组件 */
|
||||
function buildC1(poi) {
|
||||
return `
|
||||
<div class="action-zone-label">查看景点详情</div>
|
||||
<div class="c1-mini" onclick="flow('景点详情组件','跳转 H5 景点详情页 ${poi.url}')">
|
||||
<div class="c1-tag">
|
||||
<svg width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></svg>
|
||||
${poi.tag}
|
||||
</div>
|
||||
<div class="c1-body">
|
||||
<div class="c1-title">${poi.name}</div>
|
||||
<div class="c1-desc"><p>${poi.desc}</p></div>
|
||||
<button class="c1-btn">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="3 11 22 2 13 21 11 13 3 11"/></svg>
|
||||
带我去
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/* 地图点位组件 */
|
||||
function buildC8(dest) {
|
||||
return `
|
||||
<div class="action-zone-label">带我去这里</div>
|
||||
<div class="c8-mini">
|
||||
<div class="c8-img-wrap">
|
||||
<img class="c8-img" src="${dest.img}" alt="${dest.name}">
|
||||
<div class="c8-dest-tag">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></svg>
|
||||
目的地
|
||||
</div>
|
||||
</div>
|
||||
<div class="c8-bar">
|
||||
<div class="c8-info">
|
||||
<div class="c8-name">前往${dest.name}</div>
|
||||
<div class="c8-dist">${dest.dist}</div>
|
||||
</div>
|
||||
<button class="c8-btn" onclick="flow('地图点位组件','调起地图 App 导航 · ${dest.coord}')">
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polygon points="3 11 22 2 13 21 11 13 3 11"/></svg>
|
||||
导航
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/* 商品组件 */
|
||||
function buildC9(products) {
|
||||
const cards = products.map(p => `
|
||||
<div class="c9-card">
|
||||
<img class="c9-thumb" src="${p.img}" alt="${p.name}">
|
||||
<div class="c9-body">
|
||||
${p.saleTag ? `<div class="c9-sale-tag">${p.saleTag}</div>` : ''}
|
||||
<div class="c9-name">${p.name}</div>
|
||||
<div class="c9-price-row">
|
||||
<span class="c9-currency">¥</span>
|
||||
<span class="c9-price">${p.price}</span>
|
||||
${p.original ? `<span class="c9-original">¥${p.original}</span>` : ''}
|
||||
</div>
|
||||
<button class="c9-btn" onclick="flow('商品组件','跳转商品详情页 · 下单 ${p.name}')">立即购买</button>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
return `<div class="action-zone-label">相关票务</div><div class="c9-scroll">${cards}</div>`;
|
||||
}
|
||||
|
||||
/* 路线组件 */
|
||||
function buildC4(route) {
|
||||
const steps = route.steps.map((s,i) => `
|
||||
<div class="c4-step">
|
||||
<div class="c4-dot">${i+1}</div>
|
||||
<div class="c4-line">
|
||||
<div class="c4-act">${s.act}</div>
|
||||
<div class="c4-meta">${s.meta}</div>
|
||||
</div>
|
||||
</div>
|
||||
`).join('');
|
||||
return `
|
||||
<div class="action-zone-label">完整路线</div>
|
||||
<div class="c4-mini">
|
||||
<div class="c4-head">
|
||||
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><polyline points="12 6 12 12 16 14"/></svg>
|
||||
${route.title}
|
||||
</div>
|
||||
${steps}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/* 设施位置组件 */
|
||||
function buildC5(facility) {
|
||||
const rows = facility.items.map(f => `
|
||||
<div class="c5-row"><span class="c5-ic">${f.ic}</span><span>${f.txt}</span></div>
|
||||
`).join('');
|
||||
return `
|
||||
<div class="c5-mini">
|
||||
<div class="c5-head">
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="#8b5cf6" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M20 10c0 4.993-5.539 10.193-7.399 11.799a1 1 0 0 1-1.202 0C9.539 20.193 4 14.993 4 10a8 8 0 0 1 16 0"/><circle cx="12" cy="10" r="3"/></svg>
|
||||
沿途设施
|
||||
</div>
|
||||
${rows}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/* FAQ组件 */
|
||||
function buildC12(faq) {
|
||||
const chips = faq.map(q => `
|
||||
<div class="c12-chip" onclick="flow('FAQ组件','把追问发回 AI 伴游区 · 「${q}」')">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
|
||||
${q}
|
||||
</div>
|
||||
`).join('');
|
||||
return `<div class="action-zone-label">继续追问</div><div class="c12-mini">${chips}</div>`;
|
||||
}
|
||||
|
||||
/* AIGC 合影组件 */
|
||||
function buildAIGC(a) {
|
||||
return `
|
||||
<div class="action-zone-label">AIGC 合影</div>
|
||||
<div class="aigc-mini">
|
||||
<div class="aigc-img-wrap">
|
||||
<img class="aigc-img" src="${a.img}" alt="${a.name}">
|
||||
<div class="aigc-badge">
|
||||
<svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round"><path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/></svg>
|
||||
AI 生成
|
||||
</div>
|
||||
</div>
|
||||
<div class="aigc-body">
|
||||
<div class="aigc-name">${a.name}</div>
|
||||
<div class="aigc-desc">${a.desc}</div>
|
||||
<button class="aigc-btn" onclick="flow('AIGC 合影','跳转 AIGC 合影功能页 · 生成专属合影')">
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><path d="M14.5 4h-5L7 7H4a2 2 0 0 0-2 2v9a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V9a2 2 0 0 0-2-2h-3l-2.5-3z"/><circle cx="12" cy="13" r="3"/></svg>
|
||||
生成我的合影
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/* ════════════════════════════════
|
||||
CONTENT DATA — 4 类组件演示数据
|
||||
════════════════════════════════ */
|
||||
const contents = {
|
||||
|
||||
/* ── 攻略型 · 卧龙潭漂流 ── */
|
||||
guide: {
|
||||
title: '下水之前,先听小七唠两句',
|
||||
badge: '漂流攻略',
|
||||
badgeColor: 'text-amber-600 bg-amber-50 border-amber-100',
|
||||
/* content_summary = guide_conclusion 前 30 字 */
|
||||
summary: '卧龙潭漂流值得冲,全程四十分钟、三段激流,但晕水的人要掂量…',
|
||||
body: `
|
||||
<p>卧龙潭的水,是那种一眼就让人想跳进去的绿。<strong>皮筏艇漂流</strong>全程约两公里,三段激流接连而下,水花会结结实实拍在脸上——这趟值得冲,但晕水的朋友得先掂量掂量。</p>
|
||||
<img class="rich-img" src="https://images.unsplash.com/photo-1530866495561-507c9faab2ed?w=600&q=75" alt="卧龙潭漂流">
|
||||
<h5>下水前,这几样别落下</h5>
|
||||
<div class="tip-block">
|
||||
① 换洗衣服塞进防水袋,手机一定要封好<br>
|
||||
② 穿凉鞋或防滑鞋,拖鞋是真的不让下<br>
|
||||
③ 贵重东西先存好寄存柜,别揣身上
|
||||
</div>
|
||||
<p>小七的私心建议:挑 <strong>上午九点到十一点</strong> 这一场。水量足、太阳还没毒,漂下来浑身舒坦,不会被晒得发昏。</p>
|
||||
<h5>这些坑,提前绕开</h5>
|
||||
<div class="tip-block warn">
|
||||
雨后水量猛涨可能临时停漂,出发前先问一句开放状态;现场拖鞋不补租,光脚更危险。
|
||||
</div>
|
||||
`,
|
||||
products: [
|
||||
{ name:'卧龙潭皮筏艇漂流', img:'https://images.unsplash.com/photo-1530866495561-507c9faab2ed?w=400&q=75', price:'50', original:null, saleTag:null },
|
||||
{ name:'鸳鸯湖玻璃船', img:'https://images.unsplash.com/photo-1544551763-46a013bb70d5?w=400&q=75', price:'50', original:null, saleTag:'漂完顺路' }
|
||||
],
|
||||
faq: ['几岁的孩子能玩','会不会全身湿透','漂完去哪儿歇脚']
|
||||
},
|
||||
|
||||
/* ── 景点型 · 小七孔古桥 ── */
|
||||
poi: {
|
||||
title: '小七孔古桥 · 走了三百年的石拱',
|
||||
badge: '景点故事',
|
||||
badgeColor: 'text-emerald-700 bg-emerald-50 border-emerald-100',
|
||||
/* content_summary = poi_definition 前 30 字 */
|
||||
summary: '小七孔古桥是一座三百岁的七孔石桥,小七孔的名字就从这儿来…',
|
||||
body: `
|
||||
<p>小七孔古桥静静卧在响水河上,七个石拱挨着排开,桥身爬满青苔藤蔓。它建于清道光年间,<strong>三百多岁</strong>了——整个景区的名字,就是从这座桥来的。</p>
|
||||
<img class="rich-img" src="https://images.unsplash.com/photo-1682687982501-1e5898cb8f4b?w=600&q=75" alt="小七孔古桥">
|
||||
<h5>站在这儿,看什么</h5>
|
||||
<div class="tip-block">
|
||||
① 桥拱与水面倒影合成完整的圆,这是古桥最经典的一眼<br>
|
||||
② 桥身的青苔和藤蔓,是三百年时间慢慢长出来的<br>
|
||||
③ 桥下水浅处清澈见底,能看见鹅卵石和游鱼
|
||||
</div>
|
||||
<p>小七的建议:别急着走过去。先在桥侧站一会儿——古桥不是用来"打卡"的,是用来 <strong>慢慢看</strong> 的。光线斜下来的时候,石桥、绿水、倒影会一起把你框进画里。</p>
|
||||
<h5>顺带一提</h5>
|
||||
<div class="tip-block warn">
|
||||
桥面是三百年的老石头,雨后偏滑,慢点走;别翻护栏到桥下浅滩,既危险也伤桥。
|
||||
</div>
|
||||
`,
|
||||
poi: {
|
||||
tag:'核心地标', name:'小七孔古桥',
|
||||
desc:'清道光年间建的七孔石桥,响水河上的镇景之宝,小七孔之名由此而来,桥畔可观涵碧潭~',
|
||||
url:'poi_xiaoqikong_bridge.html'
|
||||
},
|
||||
faq: ['古桥有什么传说','最佳观赏时间','旁边还有什么景点']
|
||||
},
|
||||
|
||||
/* ── 路线型 · 卧龙潭 → 鸳鸯湖 ── */
|
||||
nav: {
|
||||
title: '漂完卧龙潭,顺道去鸳鸯湖',
|
||||
badge: '路线指引',
|
||||
badgeColor: 'text-violet-600 bg-violet-50 border-violet-100',
|
||||
/* content_summary = route_summary 前 30 字 */
|
||||
summary: '卧龙潭到鸳鸯湖,坐观光车约二十分钟。要紧的是鸳鸯湖分上下湖…',
|
||||
body: `
|
||||
<p>漂完卧龙潭,人多半是湿着、累着的——这时候去鸳鸯湖刚刚好。坐观光车顺路不绕,二十分钟左右就到。</p>
|
||||
<h5>鸳鸯湖分上下湖,先选好玩哪个</h5>
|
||||
<p style="margin-bottom:8px;">鸳鸯湖不是一个码头,它分成上下两个湖,玩的船不一样,<strong>下车站点也不同</strong>——上车前先选好。</p>
|
||||
<div class="vs-wrap">
|
||||
<div class="vs-col">
|
||||
<div class="vs-head"><span class="vs-dot" style="background:#3b82f6"></span>上湖 · 鸳湖</div>
|
||||
<div class="vs-boat" style="color:#2563eb">玻璃船 ¥50</div>
|
||||
<div class="vs-row">透明船底,<b>适合拍照</b></div>
|
||||
<div class="vs-row">带老人孩子图轻松</div>
|
||||
<div class="vs-row">在 <b>鸳鸯湖上湖站</b> 下车</div>
|
||||
</div>
|
||||
<div class="vs-col">
|
||||
<div class="vs-head"><span class="vs-dot" style="background:#10b981"></span>下湖 · 鸯湖</div>
|
||||
<div class="vs-boat" style="color:#059669">铁皮船 ¥30</div>
|
||||
<div class="vs-row">自己划,1-6 人一船</div>
|
||||
<div class="vs-row"><b>水上迷宫</b>穿林,更有乐趣</div>
|
||||
<div class="vs-row">在 <b>鸳鸯湖站</b> 下车,再走 4 分钟</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>时间够的话两个湖都能玩,中间有观光车接驳。</p>
|
||||
<h5>路上留个心</h5>
|
||||
<div class="tip-block warn">
|
||||
① 旺季观光车要排队,上午人最多<br>
|
||||
② 下湖枯水期水位低,水上迷宫游线可能关闭,购票前先问一句<br>
|
||||
③ 雨天石板路偏滑,带孩子老人慢一点
|
||||
</div>
|
||||
`,
|
||||
route: {
|
||||
title: '卧龙潭 → 鸳鸯湖 · 看准上下湖',
|
||||
steps: [
|
||||
{ act:'卧龙潭码头 → 卧龙潭站', meta:'步行约 5 分钟 · 认准观光车乘车点' },
|
||||
{ act:'上车前先认准方向:去上湖 or 下湖', meta:'两个湖站点不同,排队通道也不同,别走错' },
|
||||
{ act:'A·去上湖玩玻璃船 → 鸳鸯湖上湖站下车', meta:'车程约 6 分钟 · 玻璃船 ¥50/人' },
|
||||
{ act:'B·去下湖玩铁皮船 → 鸳鸯湖站下车', meta:'车程约 12 分钟 · 下车再步行 4 分钟 · 铁皮船 ¥30/人' }
|
||||
]
|
||||
},
|
||||
facility: {
|
||||
items: [
|
||||
{ ic:'🚻', txt:'卧龙潭站 · 洗手间 + 换洗寄存点' },
|
||||
{ ic:'🍦', txt:'鸳鸯湖上湖 · 美食驿站(文创雪糕)+ 休息亭' },
|
||||
{ ic:'🍜', txt:'鸳鸯湖站 · 美食驿站 + 充电宝租赁' },
|
||||
{ ic:'🚻', txt:'下湖卫生间在景点处,上湖卫生间在售票处前 150m' }
|
||||
]
|
||||
},
|
||||
faq: ['上湖下湖哪个好玩','玻璃船和铁皮船怎么选','两个湖都玩来得及吗']
|
||||
},
|
||||
|
||||
/* ── 拍照型 · 鸳鸯湖玻璃船 ── */
|
||||
photo: {
|
||||
title: '鸳鸯湖玻璃船,这样拍才不亏',
|
||||
badge: '拍照攻略',
|
||||
badgeColor: 'text-blue-600 bg-blue-50 border-blue-100',
|
||||
/* content_summary = photo_conclusion 前 30 字 */
|
||||
summary: '玻璃船拍照,关键是拍水下那抹通透的绿,顺光时段最出片…',
|
||||
body: `
|
||||
<p>鸳鸯湖的玻璃船,船底是透明的,水下世界看得清清楚楚。拍照的关键就一句话:<strong>别只顾着拍人,把水下那抹通透的绿一起收进来。</strong></p>
|
||||
<h5>三个不会错的机位</h5>
|
||||
<div class="tip-block">
|
||||
① 蹲低,贴着透明船底拍,水草和光斑会铺满整个画面<br>
|
||||
② 船头回拍人物,背景是大片湖光,人物站三分之一处<br>
|
||||
③ 把手伸进光里,拍水面波纹和指尖,是很灵的细节
|
||||
</div>
|
||||
<p>时间上,挑 <strong>上午十点到下午两点</strong> 的顺光时段。阳光直直照进水里,那种绿才透得出来——阴天和傍晚,水色会闷,差很多。</p>
|
||||
<h5>手机党看这里</h5>
|
||||
<div class="tip-block">
|
||||
手机开 0.5x 广角,水面和船一起进画;隔着玻璃拍记得擦干净船底;逆光时手动点一下水面降曝光。
|
||||
</div>
|
||||
`,
|
||||
img: {
|
||||
thumb:'https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=600&q=75',
|
||||
full:'https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=1200&q=90',
|
||||
title:'玻璃船底机位', sub:'蹲低贴船底 · 上午顺光'
|
||||
},
|
||||
aigc: {
|
||||
name:'鸳鸯湖玻璃船 AIGC 合影',
|
||||
img:'https://images.unsplash.com/photo-1559827260-dc66d52bef19?w=400&q=75',
|
||||
desc:'上船拍一张,小七帮你一键生成专属合影,不用求人也不用自拍杆'
|
||||
},
|
||||
faq: ['几点光线最好','船上能站起来拍吗','穿什么颜色上镜']
|
||||
}
|
||||
};
|
||||
|
||||
/* ════════════════════════════════
|
||||
RENDER
|
||||
════════════════════════════════ */
|
||||
/* 折叠态摘要回填 */
|
||||
document.getElementById('sum-guide').textContent = contents.guide.summary;
|
||||
document.getElementById('sum-poi').textContent = contents.poi.summary;
|
||||
document.getElementById('sum-nav').textContent = contents.nav.summary;
|
||||
document.getElementById('sum-photo').textContent = contents.photo.summary;
|
||||
|
||||
/* action_zone 按组件类型拼装 */
|
||||
function buildActionZone(d) {
|
||||
let html = '';
|
||||
if (d.poi) html += buildC1(d.poi); // 景点详情组件
|
||||
if (d.route) html += buildC4(d.route); // 路线组件
|
||||
if (d.facility) html += buildC5(d.facility); // 设施位置组件
|
||||
if (d.img) html += buildC7(d.img); // 图片组件
|
||||
if (d.dest) html += buildC8(d.dest); // 地图点位组件
|
||||
if (d.products) html += buildC9(d.products); // 商品组件
|
||||
if (d.aigc) html += buildAIGC(d.aigc); // AIGC 合影
|
||||
if (d.faq) html += buildC12(d.faq); // FAQ组件
|
||||
html += '<div class="action-zone-bottom"></div>';
|
||||
return html;
|
||||
}
|
||||
|
||||
/* 图片组件(拍照型用) */
|
||||
function buildC7(img) {
|
||||
const caption = img.title ? `
|
||||
<div style="position:absolute;bottom:0;left:0;right:0;padding:28px 14px 12px;background:linear-gradient(to top,rgba(0,0,0,0.55),rgba(0,0,0,0));border-radius:0 0 16px 16px;">
|
||||
<div style="color:#fff;font-size:13px;font-weight:900;margin-bottom:2px;">${img.title}</div>
|
||||
${img.sub ? `<div style="color:rgba(255,255,255,0.75);font-size:11px;font-weight:700;">${img.sub}</div>` : ''}
|
||||
</div>` : '';
|
||||
return `
|
||||
<div class="action-zone-label">查看机位图</div>
|
||||
<div style="margin:0 16px;border-radius:16px;overflow:hidden;cursor:pointer;position:relative;" onclick="openLB('${img.full}')">
|
||||
<img src="${img.thumb}" alt="${img.title||'大图'}" style="width:100%;height:200px;object-fit:cover;display:block;">
|
||||
${caption}
|
||||
<div style="position:absolute;top:10px;right:10px;width:30px;height:30px;border-radius:50%;background:rgba(0,0,0,0.35);display:flex;align-items:center;justify-content:center;">
|
||||
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="white" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"><polyline points="15 3 21 3 21 9"/><polyline points="9 21 3 21 3 15"/><line x1="21" y1="3" x2="14" y2="10"/><line x1="3" y1="21" x2="10" y2="14"/></svg>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
/* ── transitions ── */
|
||||
const p1 = document.getElementById('p1');
|
||||
const p2 = document.getElementById('p2');
|
||||
const screen = document.getElementById('screen');
|
||||
function syncH(el) { screen.style.minHeight = el.scrollHeight + 'px'; }
|
||||
|
||||
function goDetail(type) {
|
||||
const d = contents[type];
|
||||
document.getElementById('p2-title').textContent = d.title;
|
||||
const badge = document.getElementById('p2-badge');
|
||||
badge.textContent = d.badge;
|
||||
badge.className = `text-[10px] font-bold px-2 py-0.5 rounded-full ml-auto border ${d.badgeColor}`;
|
||||
document.getElementById('rich-body').innerHTML = d.body;
|
||||
document.getElementById('action-zone').innerHTML = buildActionZone(d);
|
||||
p1.classList.add('out');
|
||||
p2.classList.add('in');
|
||||
setTimeout(() => syncH(p2), 60);
|
||||
flow('展开', '折叠态 → 展开态 · content_summary 换成完整 content_body');
|
||||
}
|
||||
|
||||
function goBack() {
|
||||
p1.classList.remove('out');
|
||||
p2.classList.remove('in');
|
||||
setTimeout(() => syncH(p1), 60);
|
||||
}
|
||||
|
||||
/* ── lightbox ── */
|
||||
function openLB(src) {
|
||||
document.getElementById('lb-img').src = src;
|
||||
document.getElementById('lightbox').classList.add('open');
|
||||
document.body.style.overflow = 'hidden';
|
||||
flow('图片组件', '点开机位样张大图');
|
||||
}
|
||||
function closeLB() {
|
||||
document.getElementById('lightbox').classList.remove('open');
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
|
||||
/* ── 跳转链路提示 ── */
|
||||
let flowTimer = null;
|
||||
function flow(label, text) {
|
||||
const t = document.getElementById('flowToast');
|
||||
t.innerHTML = `<span class="ft-label">${label} ›</span>${text}`;
|
||||
t.classList.add('show');
|
||||
clearTimeout(flowTimer);
|
||||
flowTimer = setTimeout(() => t.classList.remove('show'), 2600);
|
||||
}
|
||||
|
||||
window.addEventListener('load', () => syncH(p1));
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user