feat: 添加 PWA 下载页面和路由配置;更新 PWA 图标设置

This commit is contained in:
2026-01-06 17:11:49 +07:00
parent d2782e1087
commit 10cdf2797c
3 changed files with 259 additions and 13 deletions

View File

@@ -204,6 +204,10 @@ const routes: Array<RouteRecordRaw> = [
path: "/global-menu",
component: () => import("@/views/global-menu/index.vue"),
},
{
path: "/pwa_download",
component: () => import("@/views/pwa/download.vue"),
},
];
const router = createRouter({

253
src/views/pwa/download.vue Normal file
View File

@@ -0,0 +1,253 @@
<script lang='ts' setup>
import { alertController } from "@ionic/vue";
import IconParkOutlineApplication from "~icons/icon-park-outline/application";
import IconParkOutlineCheckOne from "~icons/icon-park-outline/check-one";
import IconParkOutlineDownload from "~icons/icon-park-outline/download";
import IconParkOutlinePhone from "~icons/icon-park-outline/phone";
import IconParkOutlineShare from "~icons/icon-park-outline/share";
const { showInstallButton, isInstalled, promptInstall, isIOS, isIOSSafari } = usePWAInstall();
const platform = usePlatform();
const appName = "Riwa";
const isLoading = ref(false);
const showIOSGuide = ref(false);
// 检测用户是否卸载过应用
const wasUninstalled = computed(() => {
// 如果localStorage中有标记表示曾经安装过但当前未安装
const wasInstalled = localStorage.getItem("pwa-was-installed");
return wasInstalled === "true" && !isInstalled.value;
});
// 显示下载按钮的条件:
// 1. 浏览器环境
// 2. 未安装或曾经卸载过
// 3. Android 或有安装提示事件
const shouldShowDownloadButton = computed(() => {
return platform === "browser" && (!isInstalled.value || wasUninstalled.value) && (showInstallButton.value || wasUninstalled.value);
});
// iOS 安装指引
async function showIOSInstallGuide() {
showIOSGuide.value = true;
}
// 处理安装
async function handleInstall() {
if (isIOSSafari) {
await showIOSInstallGuide();
return;
}
isLoading.value = true;
try {
const result = await promptInstall();
if (result.outcome === "accepted") {
// 记录已安装状态
localStorage.setItem("pwa-was-installed", "true");
const alert = await alertController.create({
header: "安装成功",
message: "应用已成功安装到您的设备",
buttons: ["确定"],
});
await alert.present();
}
else if (result.outcome === "ios-instruction") {
await showIOSInstallGuide();
}
}
catch (error) {
console.error("Installation error:", error);
}
finally {
isLoading.value = false;
}
}
// 监听安装状态变化
watch(isInstalled, (installed) => {
if (installed) {
localStorage.setItem("pwa-was-installed", "true");
}
});
</script>
<template>
<ion-page>
<ion-header class="ion-no-border">
<ion-toolbar class="ion-toolbar">
<ion-title>下载应用</ion-title>
</ion-toolbar>
</ion-header>
<ion-content :fullscreen="true">
<div class="flex flex-col items-center min-h-full px-6 py-12">
<!-- App Logo & Name -->
<div class="flex flex-col items-center mb-8">
<img alt="RWA平台" src="/favicon.svg" class="w-16 h-16">
<h1 class="text-3xl font-bold mb-2">
{{ appName }}
</h1>
<p class="text-text-500 text-center text-sm">
随时随地管理您的数字资产
</p>
</div>
<!-- 已安装状态 -->
<div v-if="isInstalled && !wasUninstalled" class="w-full max-w-md">
<div class="bg-success/10 border border-success/20 rounded-2xl p-6 text-center">
<IconParkOutlineCheckOne class="text-5xl text-success mx-auto mb-4" />
<h2 class="text-lg font-semibold text-success mb-2">
应用已安装
</h2>
<p class="text-sm text-text-500">
您可以在主屏幕找到应用图标
</p>
</div>
</div>
<!-- iOS 安装指引 -->
<div v-else-if="isIOSSafari || (platform === 'browser' && isIOS)" class="w-full max-w-md">
<div class="bg-background-secondary rounded-2xl p-6 mb-6">
<div class="flex items-center mb-4">
<IconParkOutlinePhone class="text-2xl text-primary mr-3" />
<h2 class="text-lg font-semibold">
iOS 安装步骤
</h2>
</div>
<div class="space-y-4">
<!-- Step 1 -->
<div class="flex-center">
<div class="w-8 h-8 rounded-full bg-text-900 text-text-300 flex items-center justify-center font-bold text-sm mr-3 shrink-0">
1
</div>
<div class="flex-1">
<p class="text-sm">
点击 Safari 底部的
<IconParkOutlineShare class="inline-block text-primary mx-1" />
<strong>分享</strong> 按钮
</p>
</div>
</div>
<!-- Step 2 -->
<div class="flex-center">
<div class="w-8 h-8 rounded-full bg-text-900 text-text-300 flex items-center justify-center font-bold text-sm mr-3 shrink-0">
2
</div>
<div class="flex-1">
<p class="text-sm">
在弹出的菜单中向下滚动找到
<strong>"添加到主屏幕"</strong>
</p>
</div>
</div>
<!-- Step 3 -->
<div class="flex-center">
<div class="w-8 h-8 rounded-full bg-text-900 text-text-300 flex items-center justify-center font-bold text-sm mr-3 shrink-0">
3
</div>
<div class="flex-1">
<p class="text-sm">
点击 <strong>"添加"</strong> 完成安装
</p>
</div>
</div>
</div>
</div>
<!-- 提示卡片 -->
<div class="bg-warning/10 border border-warning/20 rounded-xl p-4 text-sm text-text-600">
<p class="flex-center">
<span class="mr-2">💡</span>
<span>请使用 Safari 浏览器进行安装</span>
</p>
</div>
</div>
<!-- Android/Chrome 下载按钮 -->
<div v-else-if="shouldShowDownloadButton" class="w-full max-w-md">
<div class="bg-background-secondary rounded-2xl p-6 mb-6 text-center">
<IconParkOutlineDownload class="text-5xl text-primary mx-auto mb-4" />
<h2 class="text-xl font-semibold mb-2">
{{ wasUninstalled ? '重新安装应用' : '安装到设备' }}
</h2>
<p class="text-sm text-text-500 mb-6">
{{ wasUninstalled ? '快速重新安装应用到您的设备' : '一键安装,无需下载,即刻使用' }}
</p>
<ion-button
expand="block"
size="large"
class="font-semibold"
:disabled="isLoading"
@click="handleInstall"
>
<IconParkOutlineDownload v-if="!isLoading" class="mr-2" />
<ion-spinner v-if="isLoading" name="crescent" class="mr-2" />
{{ isLoading ? '安装中...' : wasUninstalled ? '重新安装' : '立即安装' }}
</ion-button>
</div>
<!-- 优势列表 -->
<div class="space-y-3">
<div class="flex items-center text-sm">
<div class="w-8 h-8 rounded-full bg-success/10 flex items-center justify-center mr-3">
<IconParkOutlineCheckOne class="text-success" />
</div>
<span class="text-text-600">无需应用商店快速安装</span>
</div>
<div class="flex items-center text-sm">
<div class="w-8 h-8 rounded-full bg-success/10 flex items-center justify-center mr-3">
<IconParkOutlineCheckOne class="text-success" />
</div>
<span class="text-text-600">占用空间小运行流畅</span>
</div>
<div class="flex items-center text-sm">
<div class="w-8 h-8 rounded-full bg-success/10 flex items-center justify-center mr-3">
<IconParkOutlineCheckOne class="text-success" />
</div>
<span class="text-text-600">自动更新始终最新版本</span>
</div>
</div>
</div>
<!-- 原生应用提示 -->
<div v-else-if="platform !== 'browser'" class="w-full max-w-md">
<div class="bg-background-secondary rounded-2xl p-6 text-center">
<IconParkOutlineCheckOne class="text-5xl text-success mx-auto mb-4" />
<h2 class="text-lg font-semibold mb-2">
您正在使用原生应用
</h2>
<p class="text-sm text-text-500">
已经是最新版本无需下载
</p>
</div>
</div>
<!-- 浏览器不支持提示 -->
<div v-else class="w-full max-w-md">
<div class="bg-warning/10 border border-warning/20 rounded-2xl p-6 text-center">
<p class="text-sm text-text-600">
当前浏览器暂不支持应用安装
</p>
<p class="text-xs text-text-500 mt-2">
建议使用 ChromeSafari Edge 浏览器
</p>
</div>
</div>
</div>
</ion-content>
</ion-page>
</template>
<style lang='css' scoped>
ion-content {
--background: var(--ion-background-color);
}
</style>

View File

@@ -57,20 +57,9 @@ export default defineConfig({
prefer_related_applications: false,
icons: [
{
src: "/pwa-192x192.png",
src: "/favicon.svg",
sizes: "192x192",
type: "image/png",
},
{
src: "/pwa-512x512.png",
sizes: "512x512",
type: "image/png",
},
{
src: "/pwa-512x512.png",
sizes: "512x512",
type: "image/png",
purpose: "any maskable",
type: "image/svg",
},
],
},