|
|
<!DOCTYPE html>
|
|
|
<html lang="zh-CN">
|
|
|
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>📱 权限设置指南</title>
|
|
|
<style>
|
|
|
body {
|
|
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
|
color: white;
|
|
|
margin: 0;
|
|
|
padding: 20px;
|
|
|
min-height: 100vh;
|
|
|
}
|
|
|
|
|
|
.container {
|
|
|
max-width: 600px;
|
|
|
margin: 0 auto;
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
border-radius: 15px;
|
|
|
padding: 30px;
|
|
|
backdrop-filter: blur(10px);
|
|
|
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.37);
|
|
|
}
|
|
|
|
|
|
h1 {
|
|
|
text-align: center;
|
|
|
margin-bottom: 30px;
|
|
|
font-size: 28px;
|
|
|
}
|
|
|
|
|
|
.step {
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
border-radius: 10px;
|
|
|
padding: 20px;
|
|
|
margin-bottom: 20px;
|
|
|
border-left: 4px solid #4CAF50;
|
|
|
}
|
|
|
|
|
|
.step h3 {
|
|
|
margin: 0 0 15px 0;
|
|
|
color: #4CAF50;
|
|
|
font-size: 18px;
|
|
|
}
|
|
|
|
|
|
.step p {
|
|
|
margin: 10px 0;
|
|
|
line-height: 1.6;
|
|
|
}
|
|
|
|
|
|
.button-group {
|
|
|
text-align: center;
|
|
|
margin: 30px 0;
|
|
|
}
|
|
|
|
|
|
.btn {
|
|
|
background: #4CAF50;
|
|
|
color: white;
|
|
|
border: none;
|
|
|
padding: 15px 30px;
|
|
|
border-radius: 25px;
|
|
|
font-size: 16px;
|
|
|
font-weight: bold;
|
|
|
cursor: pointer;
|
|
|
margin: 10px;
|
|
|
transition: all 0.3s ease;
|
|
|
text-decoration: none;
|
|
|
display: inline-block;
|
|
|
}
|
|
|
|
|
|
.btn:hover {
|
|
|
background: #45a049;
|
|
|
transform: translateY(-2px);
|
|
|
box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
|
|
|
}
|
|
|
|
|
|
.btn-secondary {
|
|
|
background: #2196F3;
|
|
|
}
|
|
|
|
|
|
.btn-secondary:hover {
|
|
|
background: #1976D2;
|
|
|
}
|
|
|
|
|
|
.warning {
|
|
|
background: rgba(255, 193, 7, 0.2);
|
|
|
border: 2px solid #ffc107;
|
|
|
border-radius: 10px;
|
|
|
padding: 15px;
|
|
|
margin: 20px 0;
|
|
|
}
|
|
|
|
|
|
.success {
|
|
|
background: rgba(76, 175, 80, 0.2);
|
|
|
border: 2px solid #4CAF50;
|
|
|
border-radius: 10px;
|
|
|
padding: 15px;
|
|
|
margin: 20px 0;
|
|
|
}
|
|
|
|
|
|
.status {
|
|
|
background: rgba(0, 0, 0, 0.3);
|
|
|
border-radius: 10px;
|
|
|
padding: 15px;
|
|
|
margin: 20px 0;
|
|
|
text-align: center;
|
|
|
}
|
|
|
|
|
|
.status-item {
|
|
|
display: flex;
|
|
|
justify-content: space-between;
|
|
|
align-items: center;
|
|
|
margin: 10px 0;
|
|
|
padding: 10px;
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
border-radius: 5px;
|
|
|
}
|
|
|
|
|
|
.status-indicator {
|
|
|
width: 12px;
|
|
|
height: 12px;
|
|
|
border-radius: 50%;
|
|
|
background: #f44336;
|
|
|
animation: pulse 2s infinite;
|
|
|
}
|
|
|
|
|
|
.status-indicator.granted {
|
|
|
background: #4CAF50;
|
|
|
animation: none;
|
|
|
}
|
|
|
|
|
|
@keyframes pulse {
|
|
|
0% {
|
|
|
opacity: 1;
|
|
|
}
|
|
|
|
|
|
50% {
|
|
|
opacity: 0.5;
|
|
|
}
|
|
|
|
|
|
100% {
|
|
|
opacity: 1;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
.browser-guide {
|
|
|
background: rgba(0, 0, 0, 0.2);
|
|
|
border-radius: 10px;
|
|
|
padding: 15px;
|
|
|
margin: 20px 0;
|
|
|
}
|
|
|
|
|
|
.browser-guide h4 {
|
|
|
margin: 0 0 10px 0;
|
|
|
color: #81C784;
|
|
|
}
|
|
|
|
|
|
.browser-guide ul {
|
|
|
margin: 10px 0;
|
|
|
padding-left: 20px;
|
|
|
}
|
|
|
|
|
|
.browser-guide li {
|
|
|
margin: 5px 0;
|
|
|
line-height: 1.5;
|
|
|
}
|
|
|
</style>
|
|
|
</head>
|
|
|
|
|
|
<body>
|
|
|
<div class="container">
|
|
|
<h1>📱 权限设置指南</h1>
|
|
|
|
|
|
<div class="status">
|
|
|
<h3>📊 当前权限状态</h3>
|
|
|
<div class="status-item">
|
|
|
<span>📍 GPS定位权限</span>
|
|
|
<div class="status-indicator" id="gpsIndicator"></div>
|
|
|
</div>
|
|
|
<div class="status-item">
|
|
|
<span>📷 摄像头权限</span>
|
|
|
<div class="status-indicator" id="cameraIndicator"></div>
|
|
|
</div>
|
|
|
<div id="statusText">正在检查权限状态...</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="step">
|
|
|
<h3>🎯 第1步:GPS定位权限</h3>
|
|
|
<p>为了在地图上显示您的位置,需要获取GPS定位权限:</p>
|
|
|
<ul>
|
|
|
<li>当浏览器弹出权限请求时,点击<strong>"允许"</strong></li>
|
|
|
<li>如果已经拒绝,点击地址栏的🔒图标重新设置</li>
|
|
|
<li>确保设备的定位服务已开启</li>
|
|
|
</ul>
|
|
|
<div class="button-group">
|
|
|
<button class="btn" onclick="requestGPSPermission()">📍 请求GPS权限</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="step">
|
|
|
<h3>📷 第2步:摄像头权限</h3>
|
|
|
<p>为了拍摄和传输视频,需要获取摄像头访问权限:</p>
|
|
|
<ul>
|
|
|
<li>当浏览器询问摄像头权限时,点击<strong>"允许"</strong></li>
|
|
|
<li>如果失败,检查其他应用是否占用摄像头</li>
|
|
|
<li>建议使用后置摄像头以获得更好效果</li>
|
|
|
</ul>
|
|
|
<div class="button-group">
|
|
|
<button class="btn" onclick="requestCameraPermission()">📷 请求摄像头权限</button>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="browser-guide">
|
|
|
<h4>🔧 不同浏览器的权限设置方法:</h4>
|
|
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
|
<strong>📱 Safari (iOS):</strong>
|
|
|
<ul>
|
|
|
<li>设置 → Safari → 摄像头/麦克风 → 允许</li>
|
|
|
<li>设置 → 隐私与安全性 → 定位服务 → Safari → 使用App期间</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
|
|
|
<div style="margin-bottom: 15px;">
|
|
|
<strong>🤖 Chrome (Android):</strong>
|
|
|
<ul>
|
|
|
<li>点击地址栏左侧的🔒或ℹ️图标</li>
|
|
|
<li>设置权限为"允许"</li>
|
|
|
<li>或在设置 → 网站设置中调整</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
<strong>🖥️ 桌面浏览器:</strong>
|
|
|
<ul>
|
|
|
<li>点击地址栏的🔒图标</li>
|
|
|
<li>将摄像头和位置权限设为"允许"</li>
|
|
|
<li>刷新页面使设置生效</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<div class="warning">
|
|
|
<h4>⚠️ 常见问题解决:</h4>
|
|
|
<p><strong>GPS获取失败:</strong></p>
|
|
|
<ul>
|
|
|
<li>移动到窗边或室外获得更好信号</li>
|
|
|
<li>检查设备的定位服务是否开启</li>
|
|
|
<li>在浏览器设置中清除网站数据后重试</li>
|
|
|
</ul>
|
|
|
<p><strong>摄像头无法访问:</strong></p>
|
|
|
<ul>
|
|
|
<li>关闭其他正在使用摄像头的应用</li>
|
|
|
<li>重启浏览器或设备</li>
|
|
|
<li>使用Chrome或Safari等现代浏览器</li>
|
|
|
</ul>
|
|
|
</div>
|
|
|
|
|
|
<div class="button-group">
|
|
|
<a href="gps_test.html" class="btn btn-secondary">🧪 权限测试页面</a>
|
|
|
<a href="mobile_client.html" class="btn" id="continueBtn" style="display: none;">✅ 继续使用系统</a>
|
|
|
</div>
|
|
|
|
|
|
<div class="success" id="successMessage" style="display: none;">
|
|
|
<h4>🎉 权限设置成功!</h4>
|
|
|
<p>所有权限已获取,您现在可以正常使用移动侦察系统了。</p>
|
|
|
</div>
|
|
|
</div>
|
|
|
|
|
|
<script>
|
|
|
let gpsPermission = false;
|
|
|
let cameraPermission = false;
|
|
|
|
|
|
// 页面加载时检查权限状态
|
|
|
window.onload = function () {
|
|
|
checkPermissions();
|
|
|
};
|
|
|
|
|
|
async function checkPermissions() {
|
|
|
// 检查GPS权限
|
|
|
if ('geolocation' in navigator) {
|
|
|
try {
|
|
|
await new Promise((resolve, reject) => {
|
|
|
navigator.geolocation.getCurrentPosition(resolve, reject, { timeout: 5000 });
|
|
|
});
|
|
|
updateGPSStatus(true);
|
|
|
} catch (e) {
|
|
|
updateGPSStatus(false);
|
|
|
}
|
|
|
} else {
|
|
|
updateGPSStatus(false);
|
|
|
}
|
|
|
|
|
|
// 检查摄像头权限
|
|
|
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
|
|
|
try {
|
|
|
const stream = await navigator.mediaDevices.getUserMedia({ video: true });
|
|
|
stream.getTracks().forEach(track => track.stop()); // 停止预览
|
|
|
updateCameraStatus(true);
|
|
|
} catch (e) {
|
|
|
updateCameraStatus(false);
|
|
|
}
|
|
|
} else {
|
|
|
updateCameraStatus(false);
|
|
|
}
|
|
|
|
|
|
updateOverallStatus();
|
|
|
}
|
|
|
|
|
|
function updateGPSStatus(granted) {
|
|
|
gpsPermission = granted;
|
|
|
const indicator = document.getElementById('gpsIndicator');
|
|
|
if (granted) {
|
|
|
indicator.classList.add('granted');
|
|
|
} else {
|
|
|
indicator.classList.remove('granted');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function updateCameraStatus(granted) {
|
|
|
cameraPermission = granted;
|
|
|
const indicator = document.getElementById('cameraIndicator');
|
|
|
if (granted) {
|
|
|
indicator.classList.add('granted');
|
|
|
} else {
|
|
|
indicator.classList.remove('granted');
|
|
|
}
|
|
|
}
|
|
|
|
|
|
function updateOverallStatus() {
|
|
|
const statusText = document.getElementById('statusText');
|
|
|
const continueBtn = document.getElementById('continueBtn');
|
|
|
const successMessage = document.getElementById('successMessage');
|
|
|
|
|
|
if (gpsPermission && cameraPermission) {
|
|
|
statusText.textContent = '✅ 所有权限已获取!';
|
|
|
statusText.style.color = '#4CAF50';
|
|
|
continueBtn.style.display = 'inline-block';
|
|
|
successMessage.style.display = 'block';
|
|
|
} else {
|
|
|
let missing = [];
|
|
|
if (!gpsPermission) missing.push('GPS定位');
|
|
|
if (!cameraPermission) missing.push('摄像头');
|
|
|
statusText.textContent = `❌ 缺少权限: ${missing.join('、')}`;
|
|
|
statusText.style.color = '#f44336';
|
|
|
continueBtn.style.display = 'none';
|
|
|
successMessage.style.display = 'none';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
async function requestGPSPermission() {
|
|
|
if (!('geolocation' in navigator)) {
|
|
|
alert('❌ 您的设备不支持GPS定位功能');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
await new Promise((resolve, reject) => {
|
|
|
navigator.geolocation.getCurrentPosition(
|
|
|
(position) => {
|
|
|
alert(`✅ GPS权限获取成功!\n位置: ${position.coords.latitude.toFixed(6)}, ${position.coords.longitude.toFixed(6)}`);
|
|
|
resolve(position);
|
|
|
},
|
|
|
(error) => {
|
|
|
let message = '';
|
|
|
switch (error.code) {
|
|
|
case error.PERMISSION_DENIED:
|
|
|
message = '❌ GPS权限被拒绝\n请在浏览器设置中允许位置访问';
|
|
|
break;
|
|
|
case error.POSITION_UNAVAILABLE:
|
|
|
message = '❌ 位置信息不可用\n请移动到室外或窗边';
|
|
|
break;
|
|
|
case error.TIMEOUT:
|
|
|
message = '❌ 位置获取超时\n请检查GPS信号';
|
|
|
break;
|
|
|
default:
|
|
|
message = '❌ GPS获取失败: ' + error.message;
|
|
|
}
|
|
|
alert(message);
|
|
|
reject(error);
|
|
|
},
|
|
|
{ enableHighAccuracy: true, timeout: 15000, maximumAge: 10000 }
|
|
|
);
|
|
|
});
|
|
|
updateGPSStatus(true);
|
|
|
} catch (e) {
|
|
|
updateGPSStatus(false);
|
|
|
}
|
|
|
updateOverallStatus();
|
|
|
}
|
|
|
|
|
|
async function requestCameraPermission() {
|
|
|
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
|
|
|
alert('❌ 您的浏览器不支持摄像头功能\n请使用Chrome、Firefox或Safari等现代浏览器');
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
const stream = await navigator.mediaDevices.getUserMedia({
|
|
|
video: { facingMode: 'environment' },
|
|
|
audio: false
|
|
|
});
|
|
|
|
|
|
// 立即停止流,只是为了测试权限
|
|
|
stream.getTracks().forEach(track => track.stop());
|
|
|
|
|
|
alert('✅ 摄像头权限获取成功!');
|
|
|
updateCameraStatus(true);
|
|
|
} catch (error) {
|
|
|
let message = '';
|
|
|
if (error.name === 'NotAllowedError') {
|
|
|
message = '❌ 摄像头权限被拒绝\n请在浏览器设置中允许摄像头访问';
|
|
|
} else if (error.name === 'NotFoundError') {
|
|
|
message = '❌ 未找到可用的摄像头设备';
|
|
|
} else if (error.name === 'NotReadableError') {
|
|
|
message = '❌ 摄像头被其他应用占用\n请关闭其他使用摄像头的应用';
|
|
|
} else {
|
|
|
message = '❌ 摄像头访问失败: ' + error.message;
|
|
|
}
|
|
|
alert(message);
|
|
|
updateCameraStatus(false);
|
|
|
}
|
|
|
updateOverallStatus();
|
|
|
}
|
|
|
</script>
|
|
|
</body>
|
|
|
|
|
|
</html> |