Compare commits
3
Commits
040c56aad1
...
581734cedc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
581734cedc | ||
|
|
7cfdd27bbc | ||
|
|
329547891e |
No files matched your search
@@ -0,0 +1,28 @@
|
||||
# 呼叫热线弹窗布局调整设计
|
||||
|
||||
## 目标
|
||||
|
||||
调整呼叫热线弹窗的信息层级,使标题和关闭按钮稳定显示在弹窗顶部,并提高两个电话号码的可读性与可点击性。
|
||||
|
||||
## 设计
|
||||
|
||||
- 将标题和关闭按钮保留在独立头部区域,头部不参与正文内容排版,也不随正文压缩。
|
||||
- 正文继续展示原有提示文案,不改变文案含义。
|
||||
- 两个电话号码从行内文本中拆出,各自使用独立块级容器并各占一行。
|
||||
- 电话号码字号调整为 `20px`,保留现有蓝色样式和点击拨号行为。
|
||||
- 使用 Tailwind CSS 工具类完成布局调整,不新增 SCSS 布局样式。
|
||||
|
||||
## 数据与交互
|
||||
|
||||
电话号码常量、弹窗打开/关闭事件及 `uni.makePhoneCall` 调用保持不变。点击任一电话号码时,仍先关闭弹窗,再呼起对应号码的系统拨号界面。
|
||||
|
||||
## 验证
|
||||
|
||||
- 结构检查确认头部与正文是相邻且独立的区域。
|
||||
- 结构检查确认两个电话号码分别位于独立块级元素中。
|
||||
- 结构检查确认两个号码均使用更大的字号并保留独立点击事件。
|
||||
- 运行 `git diff --check` 检查格式问题。
|
||||
|
||||
## 范围
|
||||
|
||||
仅修改 `src/pages/ChatModule/CallMobile/index.vue` 的弹窗模板布局,不调整业务逻辑、文案内容或其他页面。
|
||||
@@ -1,17 +1,18 @@
|
||||
<template>
|
||||
<uni-popup ref="popup" type="center" :safe-area="false">
|
||||
<view class="popup-content bg-white mx-[24px] px-[12px] py-16 rounded-[12px]">
|
||||
<view class="header flex items-center pb-[12px]">
|
||||
<view class="popup-content mx-[40px] flex max-h-[80vh] flex-col overflow-hidden rounded-[12px] bg-white">
|
||||
<view class="header flex shrink-0 items-center bg-white px-[12px] pb-[12px] pt-[16px]">
|
||||
<view class="title flex-1 text-center text-[17px] text-[#000000] font-[500] ml-[24px]">呼叫热线</view>
|
||||
<uni-icons type="close" size="24" color="#CACFD8" @click="close" />
|
||||
</view>
|
||||
|
||||
<view class="border-box pl-[12px] pr-[12px]">
|
||||
<view class="border-box min-h-0 flex-1 overflow-y-auto px-[24px] pb-[32px]">
|
||||
<view class="text-[16px] text-[#a3a3a3] leading-[22px]">
|
||||
如有任何疑问,欢迎随时致电景区咨询热线:
|
||||
<text class="text-[#2563eb]" @click="handleClick(mobleNumber1)">{{ mobleNumber1 }}</text> / <text
|
||||
class="text-[#2563eb]" @click="handleClick(mobleNumber2)">{{ mobleNumber2 }}</text>,
|
||||
我们将全程为您提供细致解答与暖心服务。
|
||||
如有任何疑问,欢迎随时致电景区咨询热线,我们将全程为您提供细致解答与暖心服务。
|
||||
</view>
|
||||
<view class="mt-[12px] flex flex-col gap-[8px]">
|
||||
<view class="phone-row text-[16px] text-[#a3a3a3] leading-[28px]" @click="handleClick(mobleNumber1)">热线1: <text class="text-[18px] text-[#2563eb]">{{ mobleNumber1 }}</text></view>
|
||||
<view class="phone-row text-[16px] text-[#a3a3a3] leading-[28px]" @click="handleClick(mobleNumber2)">热线2: <text class="text-[18px] text-[#2563eb]">{{ mobleNumber2 }}</text></view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
@@ -1,18 +1,7 @@
|
||||
<template>
|
||||
<view class="discovery-photo-tool-card" hover-class="is-pressed" hover-stay-time="80" @tap="handleSelect">
|
||||
<view class="discovery-photo-tool-card" hover-class="is-pressed" hover-stay-time="80" @tap="handleJump">
|
||||
<view class="photo-visual w-[88px] min-w-0">
|
||||
<view class="camera-illustration">
|
||||
<view class="camera-top" />
|
||||
<view class="camera-flash" />
|
||||
<view class="camera-body">
|
||||
<view class="camera-lens">
|
||||
<view class="camera-lens-inner" />
|
||||
</view>
|
||||
<view class="camera-dot is-large" />
|
||||
<view class="camera-dot is-small" />
|
||||
</view>
|
||||
</view>
|
||||
<text class="photo-badge w-[calc(100%_-_18px)] truncate">{{ normalizedItem.badge }}</text>
|
||||
<image v-if="normalizedItem.coverUrl" class="block h-full w-full" :src="normalizedItem.coverUrl" mode="aspectFill" />
|
||||
</view>
|
||||
|
||||
<view class="photo-content min-w-0 flex-1">
|
||||
@@ -20,13 +9,12 @@
|
||||
<text class="photo-subtitle block w-full truncate">{{ normalizedItem.subTitle }}</text>
|
||||
|
||||
<view class="photo-options">
|
||||
<view v-for="(option, index) in normalizedItem.options" :key="getOptionKey(option, index)" class="photo-option min-w-0 flex-1"
|
||||
hover-class="is-option-pressed" hover-stay-time="80" @tap.stop="handleOptionSelect(option, index)">
|
||||
<view v-for="(photo, index) in normalizedItem.options" :key="getPhotoKey(photo, index)" class="photo-option min-w-0 flex-1"
|
||||
hover-class="is-option-pressed" hover-stay-time="80" @tap.stop="handleJump">
|
||||
<view class="photo-option-thumb">
|
||||
<image v-if="option.coverImage" class="photo-option-image" :src="option.coverImage" mode="aspectFill" />
|
||||
<view v-else class="photo-option-placeholder" :class="`is-${index}`" />
|
||||
<image v-if="photo?.photoUrl" class="photo-option-image" :src="photo.photoUrl" mode="aspectFill" />
|
||||
</view>
|
||||
<text class="photo-option-label block w-[76px] truncate">{{ option.label }}</text>
|
||||
<text class="photo-option-label block w-[76px] truncate">{{ photo?.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
@@ -35,20 +23,7 @@
|
||||
|
||||
<script setup>
|
||||
import { computed } from "vue";
|
||||
|
||||
const DEFAULT_OPTIONS = [
|
||||
{ id: "check-in", label: "景点打卡" },
|
||||
{ id: "companion", label: "小七陪伴" },
|
||||
{ id: "memory", label: "风格纪念" },
|
||||
];
|
||||
|
||||
const DEFAULT_ITEM = {
|
||||
id: "travel-photo",
|
||||
title: "在卧龙潭和小七合影",
|
||||
subTitle: "生成你在卧龙潭的专属纪念照",
|
||||
badge: "旅行纪念照",
|
||||
options: DEFAULT_OPTIONS,
|
||||
};
|
||||
import { navigateTo } from "@/router";
|
||||
|
||||
const props = defineProps({
|
||||
item: {
|
||||
@@ -57,37 +32,27 @@ const props = defineProps({
|
||||
},
|
||||
});
|
||||
|
||||
const emit = defineEmits(["didSelectItem", "didSelectOption"]);
|
||||
|
||||
const normalizeOption = (option, index) => ({
|
||||
raw: option,
|
||||
id: option.id ?? option.tabContentId ?? index,
|
||||
label: option.label || option.title || DEFAULT_OPTIONS[index]?.label || "",
|
||||
coverImage: option.coverImage || option.image || option.url || "",
|
||||
});
|
||||
|
||||
const normalizedItem = computed(() => {
|
||||
const source = Object.keys(props.item).length > 0 ? props.item : DEFAULT_ITEM;
|
||||
const options = source.options || source.children || source.items || DEFAULT_OPTIONS;
|
||||
const resource = props.item?.resource;
|
||||
const summary = resource?.summary;
|
||||
const componentParams = resource?.payload?.componentParams;
|
||||
|
||||
return {
|
||||
raw: source,
|
||||
id: source.id ?? source.tabContentId ?? DEFAULT_ITEM.id,
|
||||
title: source.title || DEFAULT_ITEM.title,
|
||||
subTitle: source.subTitle || source.desc || DEFAULT_ITEM.subTitle,
|
||||
badge: source.badge || source.tag || DEFAULT_ITEM.badge,
|
||||
options: options.slice(0, 3).map(normalizeOption),
|
||||
title: summary?.title,
|
||||
subTitle: summary?.subtitle,
|
||||
coverUrl: summary?.coverUrl,
|
||||
jumpUrl: componentParams?.jumpUrl,
|
||||
options: Array.isArray(componentParams?.photoList)
|
||||
? componentParams.photoList.slice(0, 3)
|
||||
: [],
|
||||
};
|
||||
});
|
||||
|
||||
const getOptionKey = (option, index) => option.id ?? option.label ?? index;
|
||||
const getPhotoKey = (photo, index) => photo?.photoUrl ?? photo?.title ?? index;
|
||||
|
||||
const handleSelect = () => {
|
||||
emit("didSelectItem", normalizedItem.value.raw);
|
||||
};
|
||||
|
||||
const handleOptionSelect = (option, index) => {
|
||||
emit("didSelectOption", option.raw, normalizedItem.value.raw, index);
|
||||
const handleJump = () => {
|
||||
if (!normalizedItem.value.jumpUrl) return;
|
||||
navigateTo(normalizedItem.value.jumpUrl);
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
<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" />
|
||||
<DiscoveryPhotoToolCard v-if="discoveryPhotoToolData" :item="discoveryPhotoToolData" />
|
||||
<DiscoveryAudioToolCard v-if="discoveryAudioToolData" :item="discoveryAudioToolData"
|
||||
:active="props.active" @didSelectItem="handleToolCardClick" />
|
||||
<DiscoveryGuideMapToolCard v-if="discoveryGuideMapToolData" :item="discoveryGuideMapToolData" />
|
||||
@@ -250,14 +249,6 @@ const handleToolCardClick = (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)}`);
|
||||
/// 商品
|
||||
|
||||
Reference in new issue
Block a user