H5 添加到手机桌面快捷方式 注意一定要https 协议才可以添加
index,html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>添加到桌面</title>
<!-- iOS 支持 -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="我的应用">
<link rel="apple-touch-icon" href="icon.svg">
<!-- Android Chrome 支持 -->
<link rel="manifest" href="manifest.json">
<meta name="theme-color" content="#4285f4">
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
padding: 20px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
.container {
background: white;
border-radius: 16px;
padding: 30px;
box-shadow: 0 10px 40px rgba(0,0,0,0.2);
max-width: 400px;
width: 100%;
}
h1 {
font-size: 24px;
color: #333;
margin-bottom: 20px;
text-align: center;
}
.btn {
width: 100%;
padding: 16px;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
border: none;
border-radius: 8px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
transition: transform 0.2s;
margin-bottom: 15px;
}
.btn:active {
transform: scale(0.98);
}
.guide {
display: none;
background: #f8f9fa;
border-radius: 8px;
padding: 20px;
margin-top: 20px;
}
.guide.show {
display: block;
}
.guide h3 {
font-size: 18px;
color: #333;
margin-bottom: 15px;
}
.guide ol {
padding-left: 20px;
color: #666;
line-height: 1.8;
}
.guide li {
margin-bottom: 8px;
}
.icon {
font-size: 48px;
text-align: center;
margin-bottom: 20px;
}
.tip {
font-size: 14px;
color: #666;
text-align: center;
margin-top: 15px;
line-height: 1.6;
}
</style>
</head>
<body>
<div class="container">
<div class="icon">📱</div>
<h1>添加到桌面</h1>
<button class="btn" onclick="addToHomeScreen()">添加快捷方式</button>
<div id="iosGuide" class="guide">
<h3>iOS 添加步骤:</h3>
<ol>
<li>点击底部的 <strong>分享</strong> 按钮 📤</li>
<li>向下滚动找到 <strong>"添加到主屏幕"</strong></li>
<li>点击 <strong>"添加"</strong> 完成</li>
</ol>
</div>
<div id="androidGuide" class="guide">
<h3>Android 添加步骤:</h3>
<ol>
<li>点击浏览器右上角 <strong>菜单</strong> ⋮</li>
<li>选择 <strong>"添加到主屏幕"</strong></li>
<li>确认添加即可</li>
</ol>
</div>
<p class="tip" id="tipText">点击按钮将本页面添加到手机桌面</p>
<!-- 调试信息 -->
<div style="margin-top: 20px; padding: 15px; background: #f0f0f0; border-radius: 8px; font-size: 12px; color: #666;">
<div><strong>调试信息:</strong></div>
<div id="debugInfo"></div>
</div>
</div>
<script>
let deferredPrompt;
let isIOS = false;
let isAndroid = false;
// 检测设备类型
function detectDevice() {
const ua = navigator.userAgent.toLowerCase();
isIOS = /iphone|ipad|ipod/.test(ua);
isAndroid = /android/.test(ua);
console.log('设备检测:', { isIOS, isAndroid, ua });
}
// 监听 PWA 安装提示事件(Android Chrome)
window.addEventListener('beforeinstallprompt', (e) => {
console.log('beforeinstallprompt 事件触发');
e.preventDefault();
deferredPrompt = e;
document.getElementById('tipText').textContent = '点击按钮即可添加到桌面';
});
// 监听安装成功事件
window.addEventListener('appinstalled', () => {
console.log('PWA 安装成功');
deferredPrompt = null;
alert('添加成功!请在桌面查看');
});
// 添加到主屏幕
async function addToHomeScreen() {
detectDevice();
// Android Chrome - PWA 方式
if (deferredPrompt) {
console.log('使用 PWA 安装提示');
try {
deferredPrompt.prompt();
const { outcome } = await deferredPrompt.userChoice;
console.log('用户选择:', outcome);
if (outcome === 'accepted') {
alert('添加成功!');
} else {
showAndroidGuide();
}
deferredPrompt = null;
} catch (err) {
console.error('PWA 安装失败:', err);
showAndroidGuide();
}
}
// iOS Safari
else if (isIOS) {
console.log('iOS 设备,显示引导');
showIOSGuide();
}
// Android 其他浏览器
else if (isAndroid) {
console.log('Android 设备,显示引导');
showAndroidGuide();
}
// 其他情况
else {
alert('请在手机浏览器中打开此页面');
}
}
// 显示 iOS 引导
function showIOSGuide() {
const guide = document.getElementById('iosGuide');
guide.classList.add('show');
document.getElementById('androidGuide').classList.remove('show');
document.getElementById('tipText').textContent = '请按照以下步骤操作';
}
// 显示 Android 引导
function showAndroidGuide() {
const guide = document.getElementById('androidGuide');
guide.classList.add('show');
document.getElementById('iosGuide').classList.remove('show');
document.getElementById('tipText').textContent = '请按照以下步骤操作';
}
// 注册 Service Worker
if ('serviceWorker' in navigator) {
window.addEventListener('load', () => {
navigator.serviceWorker.register('./sw.js')
.then((registration) => {
console.log('Service Worker 注册成功:', registration.scope);
})
.catch((error) => {
console.log('Service Worker 注册失败:', error);
});
});
}
// 显示调试信息
function showDebugInfo() {
const debugInfo = document.getElementById('debugInfo');
const isHTTPS = location.protocol === 'https:';
const hasSW = 'serviceWorker' in navigator;
const isStandalone = window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches;
debugInfo.innerHTML = `
<div>协议: ${location.protocol} ${isHTTPS ? '✅' : '❌ 需要 HTTPS'}</div>
<div>支持 Service Worker: ${hasSW ? '✅' : '❌'}</div>
<div>已安装: ${isStandalone ? '是' : '否'}</div>
<div>PWA 提示: ${deferredPrompt ? '✅ 已捕获' : '❌ 未触发'}</div>
<div>浏览器: ${navigator.userAgent}</div>
`;
}
// 页面加载时检测
window.addEventListener('load', () => {
detectDevice();
// 延迟显示调试信息,等待 beforeinstallprompt 事件
setTimeout(showDebugInfo, 1000);
// 检测是否已经在独立模式运行(已添加到桌面)
if (window.navigator.standalone || window.matchMedia('(display-mode: standalone)').matches) {
document.getElementById('tipText').textContent = '已添加到桌面,正在独立模式运行';
document.querySelector('.btn').disabled = true;
document.querySelector('.btn').textContent = '已添加到桌面';
document.querySelector('.btn').style.opacity = '0.6';
}
});
</script>
</body>
</html>
sw.js
// Service Worker for PWA
const CACHE_NAME = 'app-cache-v1';
const urlsToCache = [
'./Untitled-3.html',
'./manifest.json',
'./icon.svg'
];
// 安装 Service Worker
self.addEventListener('install', (event) => {
event.waitUntil(
caches.open(CACHE_NAME)
.then((cache) => cache.addAll(urlsToCache))
);
});
// 激活 Service Worker
self.addEventListener('activate', (event) => {
event.waitUntil(
caches.keys().then((cacheNames) => {
return Promise.all(
cacheNames.map((cacheName) => {
if (cacheName !== CACHE_NAME) {
return caches.delete(cacheName);
}
})
);
})
);
});
// 拦截请求
self.addEventListener('fetch', (event) => {
event.respondWith(
caches.match(event.request)
.then((response) => response || fetch(event.request))
);
});
manifest.json
{
"name": "我的应用",
"short_name": "应用",
"description": "添加到桌面的快捷方式",
"start_url": "./Untitled-3.html",
"display": "standalone",
"background_color": "#ffffff",
"theme_color": "#4285f4",
"orientation": "portrait",
"icons": [
{
"src": "icon.svg",
"sizes": "any",
"type": "image/svg+xml",
"purpose": "any maskable"
},
{
"src": "icon.svg",
"sizes": "192x192",
"type": "image/svg+xml"
},
{
"src": "icon.svg",
"sizes": "512x512",
"type": "image/svg+xml"
}
]
}
部署nginx 测试
# nginx 配置示例
server {
listen 80;
server_name your-domain.com;
# 强制跳转到 HTTPS(重要!)
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name your-domain.com;
# SSL 证书配置
ssl_certificate /path/to/your/cert.pem;
ssl_certificate_key /path/to/your/key.pem;
root /path/to/your/files;
index index.html;
# 重要:设置正确的 MIME 类型
location ~ \.json$ {
add_header Content-Type application/json;
add_header Cache-Control "public, max-age=0";
}
location ~ \.js$ {
add_header Content-Type application/javascript;
add_header Cache-Control "public, max-age=0";
}
location ~ \.svg$ {
add_header Content-Type image/svg+xml;
add_header Cache-Control "public, max-age=31536000";
}
# Service Worker 不能被缓存
location = /sw.js {
add_header Content-Type application/javascript;
add_header Cache-Control "no-cache, no-store, must-revalidate";
add_header Service-Worker-Allowed "/";
}
# manifest.json
location = /manifest.json {
add_header Content-Type application/manifest+json;
add_header Cache-Control "public, max-age=0";
}
}

浙公网安备 33010602011771号