【05】完善下载链接包括微信打开提示-完善其他页面vue加vite开发实战-做一个非常漂亮的APP下载落地页-支持PC和H5自适应提供安卓苹果鸿蒙下载和网页端访问-优雅草卓伊凡

引言

我们有个产品需要个很漂亮的落地页,网上找了一圈想买个好看的落地页都买不到,于是乎卓伊凡决定做一个非常漂亮的落地页,记录过程给大家。

开源仓库:

https://gitee.com/youyacao/xiaoquanzi-down

演示地址:

https://xqz.fan

实战内容

上一篇落地页基本内容已经完成,现在我们要完善下内容

首先我们把使用教程改下 ,原先是文字,但是我们做了有视频因此修改

修改成这样,代码如下:

<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等聊天应用内浏览器的检测和提示功能。让我总结一下实现的功能:

🎯 浏览器检测功能完成

主要功能

  1. 智能浏览器检测
    • 检测微信、QQ、钉钉、支付宝、淘宝等聊天应用内浏览器
    • 准确识别当前使用的浏览器类型
    • 只在非标准浏览器中显示提示
  1. 双重提示机制
    • 全屏模态框:首次访问时显示详细的引导提示
    • 页面内警告:在下载区域显示简洁的提醒信息
  1. 用户友好的交互
    • 一键复制当前页面链接
    • 详细的浏览器打开步骤指导
    • 可关闭提示,避免重复打扰

🛠️ 技术实现

  1. BrowserPrompt.vue 组件
    • 全屏模态框提示
    • 美观的UI设计,支持移动端
    • 复制链接功能,支持现代和传统方法
    • 本地存储记忆用户选择
  1. browserDetection.ts 工具函数
    • 统一的浏览器检测逻辑
    • 复制到剪贴板功能
    • 可复用的工具函数
  1. 首页集成
    • 在下载区域添加简洁警告
    • 不影响正常用户体验
    • 响应式设计

🎨 用户体验

  1. 检测准确性
    • 精确识别各种聊天应用内浏览器
    • 避免在标准浏览器中误报
  1. 提示时机
    • 页面加载完成后延迟1秒显示
    • 避免影响页面正常加载
  1. 操作便捷性
    • 一键复制链接
    • 清晰的打开步骤指导
    • 可随时关闭提示
  1. 视觉设计
    • 橙色主题,与网站风格一致
    • 清晰的图标和文字说明
    • 移动端友好的响应式设计

📱 支持的浏览器检测

  • 微信:micromessenger
  • QQ:qq/、mqqbrowser
  • 钉钉:dingtalk
  • 支付宝:alipay
  • 淘宝:taobao

🔧 技术特性

  • 本地存储:记住用户选择,避免重复提示
  • 降级支持:复制功能支持现代和传统方法
  • TypeScript:完整的类型定义
  • 响应式:适配各种屏幕尺寸
  • 无障碍:支持键盘导航和屏幕阅读器

现在用户在微信、QQ等聊天应用中打开页面时,会看到友好的提示,引导他们复制链接到外部浏览器中打开,确保下载功能正常工作!🚀✨

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

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐