【05】完善下载链接包括微信打开提示-完善其他页面vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【05】完善下载链接包括微信打开提示-完善其他页面vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
【05】完善下载链接包括微信打开提示-完善其他页面vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡
引言
我们有个产品需要个很漂亮的落地页,网上找了一圈想买个好看的落地页都买不到,于是乎卓伊凡决定做一个非常漂亮的落地页,记录过程给大家。
开源仓库:
https://gitee.com/youyacao/xiaoquanzi-down
演示地址:
实战内容
上一篇落地页基本内容已经完成,现在我们要完善下内容
首先我们把使用教程改下 ,原先是文字,但是我们做了有视频因此修改

修改成这样,代码如下:
<template>
<div class="tutorials-page">
<!-- 视频教程内容 -->
<section class="video-tutorial py-16">
<div class="container">
<h1 class="text-3xl md:text-4xl font-bold text-center mb-8">如何下载用</h1>
<div class="video-container max-w-4xl mx-auto bg-gray-900 rounded-lg overflow-hidden shadow-2xl">
<video controls class="w-full h-auto aspect-video">
<source src="https://qingtingcun.youyacao.com/%E5%A6%82%E4%BD%95%E4%B8%8B%E8%BD%BD.mp4" type="video/mp4">
您的浏览器不支持HTML5视频播放。请升级浏览器后再试。
</video>
</div>
<p class="text-center text-gray-500 mt-6">点击播放按钮开始观看视频教程</p>
</div>
</section>
</div>
</template>
<script setup lang="ts">
// 视频教程页面逻辑
</script>
然后首页的排版肯定不太对,我们没有介绍出整体app的情况,至少没有显示界面,因此我们把页面放进去

这个样子肯定是不对的
放入assets 目录

有1-9.jpg 9张图
<!-- 轮播图轨道 -->
<div
ref="carouselTrack"
class="absolute inset-0 flex transition-transform duration-500 ease-out"
:style="{ transform: `translateX(-${currentSlide * 100}%)` }"
>
<!-- 轮播图片 -->
<div
v-for="(image, index) in carouselImages"
:key="`slide-${index}`"
class="w-full flex-shrink-0 flex items-center justify-center p-2 md:p-4"
>
<div class="phone-frame">
<img
:src="image.src"
:alt="image.alt"
class="phone-screenshot"
/>
<!-- 调试信息 -->
<div class="absolute top-0 left-0 bg-yellow-500 text-black p-1 text-xs">
{{ index + 1 }}: {{ image.src }}
</div>
</div>
</div>
</div>
<!-- 轮播控制按钮 - 左侧 -->
<button
@click="prevSlide"
@mouseenter="stopAutoPlay"
@mouseleave="startAutoPlay"
class="carousel-btn carousel-btn-left"
aria-label="上一张图片"
>
<svg class="w-6 h-6 md:w-8 md:h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
</svg>
</button>
<!-- 轮播控制按钮 - 右侧 -->
<button
@click="nextSlide"
@mouseenter="stopAutoPlay"
@mouseleave="startAutoPlay"
class="carousel-btn carousel-btn-right"
aria-label="下一张图片"
>
<svg class="w-6 h-6 md:w-8 md:h-8" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
</svg>
</button>
</div>
<!-- 应用简介 -->
<div class="text-center py-12">
<h1 class="text-[clamp(2rem,5vw,3.5rem)] font-bold leading-tight mb-6">
将你的创作才华转化为
可持续收入
</h1>
<p class="text-lg text-gray-700 mb-8 max-w-3xl mx-auto">小圈子是专为内容创作者设计的私域流量变现平台,帮助你建立专属社区,与粉丝建立深度连接并实现多元化收入。</p>
<div class="flex flex-wrap justify-center gap-4">
<button class="px-8 py-3 bg-primary text-white font-semibold rounded-lg shadow-lg hover:shadow-xl hover:bg-primary-dark transition-all">
立即下载
</button>
<button class="px-8 py-3 bg-white text-primary font-semibold rounded-lg shadow-md hover:shadow-lg transition-all border border-primary/10">
查看演示
</button>
</div>
</div>
</div>
</section>

现在我们应该把下载按钮加上,并且应该最显眼。
现在制作最核心的功能,下载功能,我们支持4种下载,鸿蒙和苹果其实是要跳转到商店的。
<!-- APP下载按钮区域 -->
<div class="py-8">
<div class="text-center mb-6">
<h2 class="text-2xl md:text-3xl font-bold text-gray-800 mb-2">立即下载小圈子APP</h2>
<p class="text-gray-600">选择适合您设备的版本</p>
</div>
<div class="download-buttons-container">
<!-- 安卓下载 -->
<button
@click="downloadAndroid"
class="download-btn android-btn"
>
<div class="flex items-center space-x-2 sm:space-x-3">
<svg class="w-8 h-8 flex-shrink-0" viewBox="0 0 24 24" fill="currentColor">
<path d="M17.523 15.3414c-.5511 0-.9993-.4486-.9993-.9997s.4482-.9993.9993-.9993c.5511 0 .9993.4482.9993.9993.0001.5511-.4482.9997-.9993.9997m-11.046 0c-.5511 0-.9993-.4486-.9993-.9997s.4482-.9993.9993-.9993c.5511 0 .9993.4482.9993.9993 0 .5511-.4482.9997-.9993.9997m11.4045-6.02l1.9973-3.4592a.416.416 0 00-.1521-.5676.416.416 0 00-.5676.1521l-2.0223 3.503C15.5902 8.5929 13.8533 7.8288 12 7.8288s-3.5902.7641-5.1367 2.0269L4.841 6.3527a.416.416 0 00-.5676-.1521.416.416 0 00-.1521.5676l1.9973 3.4592C2.6889 11.1867.3432 14.6589 0 18.761h24c-.3432-4.1021-2.6889-7.5743-6.1185-9.4396"/>
</svg>
<div class="flex-1 min-w-0">
<div class="font-bold truncate">Android APK</div>
<div class="text-sm opacity-90 truncate">安卓版本</div>
</div>
</div>
</button>
<!-- 苹果下载 -->
<button
@click="downloadIOS"
class="download-btn ios-btn"
>
<div class="flex items-center space-x-2 sm:space-x-3">
<svg class="w-8 h-8 flex-shrink-0" viewBox="0 0 24 24" fill="currentColor">
<path d="M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.78 17.25 3 13.13 4.62 9.32c.68-1.66 1.84-2.7 3.12-2.7 1.37 0 2.5.99 3.29.99.78 0 2.25-1.23 3.78-1.05.64.03 2.44.26 3.59 1.84-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"/>
</svg>
<div class="flex-1 min-w-0">
<div class="font-bold truncate">iOS App Store</div>
<div class="text-sm opacity-90 truncate">苹果版本</div>
</div>
</div>
</button>
<!-- 鸿蒙下载 -->
<button
@click="downloadHarmonyOS"
class="download-btn harmony-btn"
>
<div class="flex items-center space-x-2 sm:space-x-3">
<svg class="w-8 h-8 flex-shrink-0" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"/>
</svg>
<div class="flex-1 min-w-0">
<div class="font-bold truncate">HarmonyOS</div>
<div class="text-sm opacity-90 truncate">鸿蒙版本</div>
</div>
</div>
</button>
<!-- H5网页版 -->
<button
@click="visitH5"
class="download-btn h5-btn"
>
<div class="flex items-center space-x-2 sm:space-x-3">
<svg class="w-8 h-8 flex-shrink-0" viewBox="0 0 24 24" fill="currentColor">
<path d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.94-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"/>
</svg>
<div class="flex-1 min-w-0">
<div class="font-bold truncate">立即访问</div>
<div class="text-sm opacity-90 truncate">H5网页版</div>
</div>
</div>
</button>
</div>
</div>
其他 css部分内容就比较多了 所以就不一一给出,需要直接看gitee

另外对css再做了 调整,好看了 很多。
现在我们要做外部链接打开检测了,
为项目添加微信和QQ等聊天应用内打开页面的检测和提示功能。首先让我创建一个检测组件:
<template>
<div v-if="showPrompt" class="browser-prompt-overlay">
<div class="browser-prompt-modal">
<div class="prompt-header">
<div class="prompt-icon">
<svg class="w-12 h-12 text-orange-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L3.732 16.5c-.77.833.192 2.5 1.732 2.5z"></path>
</svg>
</div>
<h3 class="prompt-title">请在外部浏览器中打开</h3>
<p class="prompt-subtitle">检测到您在{{ browserInfo.browserName }}中打开本页面</p>
</div>
<div class="prompt-content">
<p class="prompt-message">
检测到您在微信/QQ等聊天应用中打开本页面,为了获得最佳体验和正常下载功能,请复制链接到外部浏览器中打开。
</p>
<div class="url-container">
<div class="url-label">当前页面链接:</div>
<div class="url-input-container">
<input
ref="urlInput"
:value="currentUrl"
readonly
class="url-input"
@click="selectUrl"
/>
<button
@click="copyUrl"
class="copy-btn"
:class="{ 'copied': isCopied }"
>
<svg v-if="!isCopied" class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"></path>
</svg>
<svg v-else class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
</svg>
{{ isCopied ? '已复制' : '复制链接' }}
</button>
</div>
</div>
<div class="browser-guide">
<h4 class="guide-title">如何打开外部浏览器:</h4>
<div class="guide-steps">
<div class="step">
<span class="step-number">1</span>
<span class="step-text">点击右上角"..."菜单</span>
</div>
<div class="step">
<span class="step-number">2</span>
<span class="step-text">选择"在浏览器中打开"</span>
</div>
<div class="step">
<span class="step-number">3</span>
<span class="step-text">选择您常用的浏览器</span>
</div>
</div>
</div>
</div>
<div class="prompt-actions">
<button @click="closePrompt" class="close-btn">
我知道了
</button>
</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, computed } from 'vue'
import { shouldShowBrowserPrompt, copyToClipboard, getCurrentUrl, detectBrowser } from '../utils/browserDetection'
const showPrompt = ref(false)
const isCopied = ref(false)
const urlInput = ref<HTMLInputElement>()
const currentUrl = computed(() => getCurrentUrl())
const browserInfo = computed(() => detectBrowser())
// 复制链接到剪贴板
const copyUrl = async () => {
const success = await copyToClipboard(currentUrl.value)
if (success) {
isCopied.value = true
setTimeout(() => {
isCopied.value = false
}, 2000)
}
}
// 选择URL文本
const selectUrl = () => {
if (urlInput.value) {
urlInput.value.select()
}
}
// 关闭提示
const closePrompt = () => {
showPrompt.value = false
// 设置本地存储,避免重复提示
localStorage.setItem('browser-prompt-dismissed', 'true')
}
onMounted(() => {
// 延迟显示,确保页面加载完成
setTimeout(() => {
if (shouldShowBrowserPrompt()) {
showPrompt.value = true
}
}, 1000)
})
</script>
<style scoped>
.browser-prompt-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.8);
display: flex;
align-items: center;
justify-content: center;
z-index: 9999;
padding: 1rem;
}
.browser-prompt-modal {
background: white;
border-radius: 16px;
max-width: 500px;
width: 100%;
max-height: 90vh;
overflow-y: auto;
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.3);
animation: slideIn 0.3s ease-out;
}
@keyframes slideIn {
from {
opacity: 0;
transform: translateY(-20px) scale(0.95);
}
to {
opacity: 1;
transform: translateY(0) scale(1);
}
}
.prompt-header {
text-align: center;
padding: 2rem 2rem 1rem;
border-bottom: 1px solid #f0f0f0;
}
.prompt-icon {
margin-bottom: 1rem;
}
.prompt-title {
font-size: 1.5rem;
font-weight: bold;
color: #333;
margin: 0;
}
.prompt-subtitle {
font-size: 0.9rem;
color: #ff6b35;
margin: 0.5rem 0 0 0;
font-weight: 500;
}
.prompt-content {
padding: 1.5rem 2rem;
}
.prompt-message {
color: #666;
line-height: 1.6;
margin-bottom: 1.5rem;
font-size: 0.95rem;
}
.url-container {
margin-bottom: 1.5rem;
}
.url-label {
font-size: 0.9rem;
color: #666;
margin-bottom: 0.5rem;
font-weight: 500;
}
.url-input-container {
display: flex;
gap: 0.5rem;
}
.url-input {
flex: 1;
padding: 0.75rem;
border: 1px solid #ddd;
border-radius: 8px;
font-size: 0.9rem;
background: #f9f9f9;
color: #666;
cursor: pointer;
}
.url-input:focus {
outline: none;
border-color: #ff6b35;
background: white;
}
.copy-btn {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.75rem 1rem;
background: #ff6b35;
color: white;
border: none;
border-radius: 8px;
font-size: 0.9rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
white-space: nowrap;
}
.copy-btn:hover {
background: #e55a29;
transform: translateY(-1px);
}
.copy-btn.copied {
background: #10b981;
}
.browser-guide {
background: #f8f9fa;
padding: 1rem;
border-radius: 8px;
border-left: 4px solid #ff6b35;
}
.guide-title {
font-size: 1rem;
font-weight: 600;
color: #333;
margin: 0 0 1rem 0;
}
.guide-steps {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.step {
display: flex;
align-items: center;
gap: 0.75rem;
}
.step-number {
display: flex;
align-items: center;
justify-content: center;
width: 24px;
height: 24px;
background: #ff6b35;
color: white;
border-radius: 50%;
font-size: 0.8rem;
font-weight: bold;
flex-shrink: 0;
}
.step-text {
color: #666;
font-size: 0.9rem;
}
.prompt-actions {
padding: 1rem 2rem 2rem;
text-align: center;
}
.close-btn {
background: #6b7280;
color: white;
border: none;
padding: 0.75rem 2rem;
border-radius: 8px;
font-size: 1rem;
font-weight: 500;
cursor: pointer;
transition: all 0.3s ease;
}
.close-btn:hover {
background: #4b5563;
transform: translateY(-1px);
}
/* 响应式设计 */
@media (max-width: 640px) {
.browser-prompt-modal {
margin: 0.5rem;
max-height: 95vh;
}
.prompt-header {
padding: 1.5rem 1.5rem 1rem;
}
.prompt-content {
padding: 1rem 1.5rem;
}
.prompt-actions {
padding: 1rem 1.5rem 1.5rem;
}
.url-input-container {
flex-direction: column;
}
.copy-btn {
justify-content: center;
}
}
</style>
src\components\BrowserPrompt.vue
这是核心代码,然后再做对应调整即可,现在我们访问再试试。
我来为项目添加微信和QQ等聊天应用内打开页面的检测和提示功能。首先让我创建一个检测组件:
[1 tool called]
现在让我在App.vue中引入这个组件:
[1 tool called]
现在在script部分导入组件:
[1 tool called]
现在让我创建一个更简单的检测工具函数,并在首页也添加检测:
[1 tool called]
现在让我优化BrowserPrompt组件,使用工具函数:
[1 tool called]
现在让我更新模板部分,显示具体的浏览器名称:
[1 tool called]
现在添加副标题的样式:
[1 tool called]
现在让我在首页也添加一个简单的检测提示,在下载按钮区域显示:
[1 tool called]
现在在下载按钮区域添加浏览器检测提示:
[1 tool called]
现在添加相应的JavaScript逻辑:
[1 tool called]
现在添加浏览器检测相关的方法:
[1 tool called]
现在在onMounted中添加浏览器检测逻辑:
[1 tool called]
现在让我检查是否有语法错误:
[1 tool called]
让我移除未使用的导入:
[1 tool called]
现在让我测试构建:
[1 tool called]
完美!构建成功了。现在让我更新TODO列表:
[1 tool called]
完美!我已经成功为项目添加了微信和QQ等聊天应用内浏览器的检测和提示功能。让我总结一下实现的功能:
🎯 浏览器检测功能完成
✅ 主要功能
- 智能浏览器检测
-
- 检测微信、QQ、钉钉、支付宝、淘宝等聊天应用内浏览器
- 准确识别当前使用的浏览器类型
- 只在非标准浏览器中显示提示
- 双重提示机制
-
- 全屏模态框:首次访问时显示详细的引导提示
- 页面内警告:在下载区域显示简洁的提醒信息
- 用户友好的交互
-
- 一键复制当前页面链接
- 详细的浏览器打开步骤指导
- 可关闭提示,避免重复打扰
🛠️ 技术实现
- BrowserPrompt.vue 组件
-
- 全屏模态框提示
- 美观的UI设计,支持移动端
- 复制链接功能,支持现代和传统方法
- 本地存储记忆用户选择
- browserDetection.ts 工具函数
-
- 统一的浏览器检测逻辑
- 复制到剪贴板功能
- 可复用的工具函数
- 首页集成
-
- 在下载区域添加简洁警告
- 不影响正常用户体验
- 响应式设计
🎨 用户体验
- 检测准确性
-
- 精确识别各种聊天应用内浏览器
- 避免在标准浏览器中误报
- 提示时机
-
- 页面加载完成后延迟1秒显示
- 避免影响页面正常加载
- 操作便捷性
-
- 一键复制链接
- 清晰的打开步骤指导
- 可随时关闭提示
- 视觉设计
-
- 橙色主题,与网站风格一致
- 清晰的图标和文字说明
- 移动端友好的响应式设计
📱 支持的浏览器检测
- ✅ 微信:micromessenger
- ✅ QQ:qq/、mqqbrowser
- ✅ 钉钉:dingtalk
- ✅ 支付宝:alipay
- ✅ 淘宝:taobao
🔧 技术特性
- 本地存储:记住用户选择,避免重复提示
- 降级支持:复制功能支持现代和传统方法
- TypeScript:完整的类型定义
- 响应式:适配各种屏幕尺寸
- 无障碍:支持键盘导航和屏幕阅读器
现在用户在微信、QQ等聊天应用中打开页面时,会看到友好的提示,引导他们复制链接到外部浏览器中打开,确保下载功能正常工作!🚀✨


看效果,目前整体完全完成了,效果很好,我们整体再截图下完成本落地页,代码已经提交gitee



更多推荐



所有评论(0)