502 lines
17 KiB
HTML
502 lines
17 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="zh-CN">
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
|
|
<title>Airhub - WiFi配网</title>
|
|
<link rel="stylesheet" href="styles.css">
|
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
<link
|
|
href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Press+Start+2P&display=swap"
|
|
rel="stylesheet">
|
|
<style>
|
|
/* WiFi Config specific styles */
|
|
.wifi-steps {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 8px;
|
|
margin-bottom: 32px;
|
|
}
|
|
|
|
.step-dot {
|
|
width: 8px;
|
|
height: 8px;
|
|
border-radius: 50%;
|
|
background: rgba(167, 139, 250, 0.3);
|
|
transition: all 0.3s ease;
|
|
}
|
|
|
|
.step-dot.active {
|
|
background: #8B5CF6;
|
|
width: 24px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.step-dot.completed {
|
|
background: #22C55E;
|
|
}
|
|
|
|
.wifi-icon {
|
|
width: 80px;
|
|
height: 80px;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.wifi-list {
|
|
width: 100%;
|
|
max-width: 320px;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
}
|
|
|
|
.wifi-item {
|
|
display: flex;
|
|
align-items: center;
|
|
padding: 16px;
|
|
background: rgba(255, 255, 255, 0.8);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 16px;
|
|
border: 1px solid rgba(255, 255, 255, 0.5);
|
|
cursor: pointer;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.wifi-item:hover {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.wifi-item.selected {
|
|
border-color: #8B5CF6;
|
|
box-shadow: 0 0 0 2px rgba(139, 92, 246, 0.2);
|
|
}
|
|
|
|
.wifi-name {
|
|
flex: 1;
|
|
font-weight: 500;
|
|
color: #1F2937;
|
|
}
|
|
|
|
.wifi-signal {
|
|
color: #6B7280;
|
|
font-size: 20px;
|
|
}
|
|
|
|
.password-input {
|
|
width: 100%;
|
|
max-width: 320px;
|
|
padding: 16px 20px;
|
|
border: 1px solid rgba(255, 255, 255, 0.5);
|
|
background: rgba(255, 255, 255, 0.8);
|
|
backdrop-filter: blur(10px);
|
|
border-radius: 16px;
|
|
font-size: 16px;
|
|
font-family: inherit;
|
|
outline: none;
|
|
transition: all 0.2s ease;
|
|
}
|
|
|
|
.password-input:focus {
|
|
border-color: #8B5CF6;
|
|
box-shadow: 0 0 0 3px rgba(139, 92, 246, 0.15);
|
|
}
|
|
|
|
.progress-container {
|
|
width: 100%;
|
|
max-width: 280px;
|
|
text-align: center;
|
|
}
|
|
|
|
.progress-bar {
|
|
height: 6px;
|
|
background: rgba(139, 92, 246, 0.2);
|
|
border-radius: 3px;
|
|
overflow: hidden;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.progress-fill {
|
|
height: 100%;
|
|
background: linear-gradient(90deg, #22D3EE, #8B5CF6);
|
|
border-radius: 3px;
|
|
width: 0%;
|
|
transition: width 0.3s ease;
|
|
}
|
|
|
|
.progress-text {
|
|
color: #6B7280;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.result-icon {
|
|
font-size: 64px;
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.result-title {
|
|
font-size: 24px;
|
|
font-weight: 600;
|
|
color: #1F2937;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.result-desc {
|
|
color: #6B7280;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.step-content {
|
|
display: none;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
width: 100%;
|
|
}
|
|
|
|
.step-content.active {
|
|
display: flex;
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<!-- Animated Background -->
|
|
<div class="gradient-bg">
|
|
<div class="gradient-layer layer-1"></div>
|
|
<div class="gradient-layer layer-2"></div>
|
|
<div class="gradient-layer layer-3"></div>
|
|
</div>
|
|
|
|
<div class="page bluetooth-page active">
|
|
<header class="bt-header">
|
|
<button class="back-btn" onclick="goBack()">
|
|
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
<path d="M15 18L9 12L15 6" stroke="currentColor" stroke-width="2" stroke-linecap="round"
|
|
stroke-linejoin="round" />
|
|
</svg>
|
|
</button>
|
|
<h1 class="bt-title">WiFi配网</h1>
|
|
<div class="header-spacer"></div>
|
|
</header>
|
|
|
|
<main class="bt-content">
|
|
<!-- Step indicators -->
|
|
<div class="wifi-steps">
|
|
<div class="step-dot active" id="dot1"></div>
|
|
<div class="step-dot" id="dot2"></div>
|
|
<div class="step-dot" id="dot3"></div>
|
|
<div class="step-dot" id="dot4"></div>
|
|
</div>
|
|
|
|
<!-- Step 1: Select Network -->
|
|
<div class="step-content active" id="step1">
|
|
<svg class="wifi-icon" viewBox="0 0 24 24" fill="none">
|
|
<path d="M5 12.55a11 11 0 0 1 14.08 0" stroke="#8B5CF6" stroke-width="2" stroke-linecap="round" />
|
|
<path d="M1.42 9a16 16 0 0 1 21.16 0" stroke="#8B5CF6" stroke-width="2" stroke-linecap="round" />
|
|
<path d="M8.53 16.11a6 6 0 0 1 6.95 0" stroke="#8B5CF6" stroke-width="2" stroke-linecap="round" />
|
|
<circle cx="12" cy="20" r="1" fill="#8B5CF6" />
|
|
</svg>
|
|
<h2 style="margin-bottom: 8px; color: #1F2937;">选择WiFi网络</h2>
|
|
<p style="color: #6B7280; margin-bottom: 24px;">设备需要连接WiFi以使用AI功能</p>
|
|
|
|
<div class="wifi-list" id="wifiList">
|
|
<div class="wifi-item" onclick="selectWifi(this, 'Home_5G')">
|
|
<span class="wifi-name">Home_5G</span>
|
|
<img src="icons/wifi-4.svg" class="wifi-level-icon" alt="Strong">
|
|
</div>
|
|
<div class="wifi-item" onclick="selectWifi(this, 'Office_WiFi')">
|
|
<span class="wifi-name">Office_WiFi</span>
|
|
<img src="icons/wifi-3.svg" class="wifi-level-icon" alt="Good">
|
|
</div>
|
|
<div class="wifi-item" onclick="selectWifi(this, 'Guest_Network')">
|
|
<span class="wifi-name">Guest_Network</span>
|
|
<img src="icons/wifi-2.svg" class="wifi-level-icon" alt="Weak">
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 2: Enter Password -->
|
|
<div class="step-content" id="step2">
|
|
<svg class="wifi-icon" viewBox="0 0 24 24" fill="none">
|
|
<rect x="3" y="11" width="18" height="11" rx="2" stroke="#8B5CF6" stroke-width="2" />
|
|
<circle cx="12" cy="16" r="1" fill="#8B5CF6" />
|
|
<path d="M7 11V7a5 5 0 0110 0v4" stroke="#8B5CF6" stroke-width="2" />
|
|
</svg>
|
|
<h2 style="margin-bottom: 8px; color: #1F2937;" id="selectedWifiName">网络名称</h2>
|
|
<p style="color: #6B7280; margin-bottom: 24px;">请输入WiFi密码</p>
|
|
|
|
<input type="password" class="password-input" id="wifiPassword" placeholder="输入密码">
|
|
</div>
|
|
|
|
<!-- Step 3: Connecting -->
|
|
<div class="step-content" id="step3">
|
|
<svg class="wifi-icon connecting-anim" viewBox="0 0 24 24" fill="none">
|
|
<path class="wifi-wave wave-3" d="M5 12.55a11 11 0 0 1 14.08 0" stroke="#8B5CF6" stroke-width="2"
|
|
stroke-linecap="round" />
|
|
<path class="wifi-wave wave-2" d="M1.42 9a16 16 0 0 1 21.16 0" stroke="#8B5CF6" stroke-width="2"
|
|
stroke-linecap="round" />
|
|
<path class="wifi-wave wave-1" d="M8.53 16.11a6 6 0 0 1 6.95 0" stroke="#8B5CF6" stroke-width="2"
|
|
stroke-linecap="round" />
|
|
<circle class="wifi-dot" cx="12" cy="20" r="1" fill="#8B5CF6" />
|
|
</svg>
|
|
<h2 style="margin-bottom: 24px; color: #1F2937;">正在配网...</h2>
|
|
|
|
<div class="progress-container">
|
|
<div class="progress-bar">
|
|
<div class="progress-fill" id="progressFill"></div>
|
|
</div>
|
|
<p class="progress-text" id="progressText">正在连接WiFi...</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Step 4: Result -->
|
|
<div class="step-content" id="step4">
|
|
<!-- Dynamic Device Icon Container -->
|
|
<div class="success-icon-wrapper">
|
|
<img src="" alt="Device" id="successDeviceImg" class="success-device-img">
|
|
<div class="success-badge">✅</div>
|
|
</div>
|
|
<h2 class="result-title" id="resultTitle">配网成功!</h2>
|
|
<p class="result-desc" id="resultDesc">设备已成功连接到网络</p>
|
|
</div>
|
|
</main>
|
|
|
|
<footer class="bt-footer">
|
|
<button class="cancel-btn" id="cancelBtn" onclick="goBack()">取消</button>
|
|
<button class="connect-device-btn" id="nextBtn" onclick="nextStep()" style="display: none;">
|
|
<span class="btn-text" id="nextBtnText">下一步</span>
|
|
</button>
|
|
</footer>
|
|
</div>
|
|
|
|
<style>
|
|
.wifi-level-icon {
|
|
width: 24px;
|
|
height: 24px;
|
|
opacity: 0.8;
|
|
}
|
|
|
|
/* Connecting Animation */
|
|
.connecting-anim .wifi-wave {
|
|
stroke-opacity: 0.3;
|
|
animation: wifiPulse 1.5s infinite ease-in-out;
|
|
}
|
|
|
|
.connecting-anim .wave-1 {
|
|
animation-delay: 0.0s;
|
|
}
|
|
|
|
.connecting-anim .wave-2 {
|
|
animation-delay: 0.5s;
|
|
}
|
|
|
|
.connecting-anim .wave-3 {
|
|
animation-delay: 1.0s;
|
|
}
|
|
|
|
/* Outer wave */
|
|
|
|
@keyframes wifiPulse {
|
|
|
|
0%,
|
|
100% {
|
|
stroke-opacity: 0.3;
|
|
stroke: #8B5CF6;
|
|
}
|
|
|
|
50% {
|
|
stroke-opacity: 1;
|
|
stroke: #8B5CF6;
|
|
}
|
|
}
|
|
|
|
/* Success Icon Styles */
|
|
.success-icon-wrapper {
|
|
position: relative;
|
|
width: 120px;
|
|
height: 120px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin-bottom: 24px;
|
|
}
|
|
|
|
.success-device-img {
|
|
width: 120px;
|
|
height: 120px;
|
|
image-rendering: pixelated;
|
|
filter: drop-shadow(0 10px 20px rgba(139, 92, 246, 0.2));
|
|
animation: floatSuccess 3s ease-in-out infinite;
|
|
}
|
|
|
|
.success-badge {
|
|
position: absolute;
|
|
bottom: -5px;
|
|
right: -5px;
|
|
width: 32px;
|
|
height: 32px;
|
|
background: #22C55E;
|
|
color: white;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 18px;
|
|
border: 3px solid white;
|
|
box-shadow: 0 4px 10px rgba(34, 197, 94, 0.3);
|
|
animation: popIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
|
|
}
|
|
|
|
@keyframes floatSuccess {
|
|
|
|
0%,
|
|
100% {
|
|
transform: translateY(0);
|
|
}
|
|
|
|
50% {
|
|
transform: translateY(-10px);
|
|
}
|
|
}
|
|
|
|
@keyframes popIn {
|
|
from {
|
|
transform: scale(0);
|
|
}
|
|
|
|
to {
|
|
transform: scale(1);
|
|
}
|
|
}
|
|
</style>
|
|
|
|
<script>
|
|
let currentStep = 1;
|
|
let selectedWifi = '';
|
|
|
|
// Load device info immediately
|
|
let currentDevice = {};
|
|
try {
|
|
currentDevice = JSON.parse(localStorage.getItem('lastActiveDevice') || '{}');
|
|
console.log("Loaded device:", currentDevice);
|
|
} catch (e) { console.error(e); }
|
|
|
|
function getDeviceIcon(type) {
|
|
// Normalize type keys to match bluetooth.html
|
|
// Mappings: 'plush' -> capybara, 'badge_ai' -> badge-ai, 'badge' -> badge-basic
|
|
if (type === 'plush_core' || type === 'plush') return 'icons/pixel-capybara.svg';
|
|
if (type === 'badge_ai') return 'icons/pixel-badge-ai.svg';
|
|
if (type === 'badge_basic' || type === 'badge') return 'icons/pixel-badge-basic.svg';
|
|
|
|
return 'icons/pixel-badge-basic.svg'; // Fallback
|
|
}
|
|
|
|
function selectWifi(element, name) {
|
|
document.querySelectorAll('.wifi-item').forEach(el => el.classList.remove('selected'));
|
|
element.classList.add('selected');
|
|
selectedWifi = name;
|
|
document.getElementById('nextBtn').style.display = 'flex';
|
|
}
|
|
|
|
function nextStep() {
|
|
if (currentStep === 1 && !selectedWifi) return;
|
|
if (currentStep === 2 && !document.getElementById('wifiPassword').value) return;
|
|
|
|
currentStep++;
|
|
updateStepUI();
|
|
|
|
if (currentStep === 2) {
|
|
document.getElementById('selectedWifiName').textContent = selectedWifi;
|
|
}
|
|
if (currentStep === 3) {
|
|
startConnecting();
|
|
}
|
|
if (currentStep === 4) {
|
|
// Show device icon
|
|
const img = document.getElementById('successDeviceImg');
|
|
img.src = getDeviceIcon(currentDevice.type || 'badge_basic');
|
|
|
|
document.getElementById('nextBtnText').textContent = '进入设备';
|
|
document.getElementById('cancelBtn').style.display = 'none';
|
|
}
|
|
}
|
|
|
|
function updateStepUI() {
|
|
// Update step dots
|
|
for (let i = 1; i <= 4; i++) {
|
|
const dot = document.getElementById('dot' + i);
|
|
dot.classList.remove('active', 'completed');
|
|
if (i < currentStep) dot.classList.add('completed');
|
|
if (i === currentStep) dot.classList.add('active');
|
|
}
|
|
|
|
// Update step content
|
|
for (let i = 1; i <= 4; i++) {
|
|
const step = document.getElementById('step' + i);
|
|
step.classList.remove('active');
|
|
if (i === currentStep) step.classList.add('active');
|
|
}
|
|
|
|
// Update button text
|
|
if (currentStep === 2) {
|
|
document.getElementById('nextBtnText').textContent = '连接';
|
|
}
|
|
}
|
|
|
|
function startConnecting() {
|
|
document.getElementById('nextBtn').style.display = 'none';
|
|
const progressFill = document.getElementById('progressFill');
|
|
const progressText = document.getElementById('progressText');
|
|
|
|
const steps = [
|
|
{ progress: 30, text: '正在连接WiFi...' },
|
|
{ progress: 60, text: '正在验证密码...' },
|
|
{ progress: 90, text: '正在同步设备...' },
|
|
{ progress: 100, text: '完成!' }
|
|
];
|
|
|
|
let stepIndex = 0;
|
|
const interval = setInterval(() => {
|
|
if (stepIndex < steps.length) {
|
|
progressFill.style.width = steps[stepIndex].progress + '%';
|
|
progressText.textContent = steps[stepIndex].text;
|
|
stepIndex++;
|
|
} else {
|
|
clearInterval(interval);
|
|
setTimeout(() => {
|
|
currentStep = 4;
|
|
// Use button-triggered transition or auto
|
|
updateStepUI();
|
|
// Setup final state manually here as well to be safe
|
|
const img = document.getElementById('successDeviceImg');
|
|
if (img) img.src = getDeviceIcon(currentDevice.type || 'badge_basic');
|
|
|
|
document.getElementById('nextBtn').style.display = 'flex';
|
|
document.getElementById('nextBtnText').textContent = '进入设备';
|
|
document.getElementById('cancelBtn').style.display = 'none';
|
|
document.getElementById('nextBtn').onclick = () => {
|
|
window.location.href = 'device-control.html?t=' + new Date().getTime();
|
|
};
|
|
}, 500);
|
|
}
|
|
}, 800);
|
|
}
|
|
|
|
function goBack() {
|
|
if (currentStep > 1) {
|
|
currentStep--;
|
|
updateStepUI();
|
|
if (currentStep === 1) {
|
|
document.getElementById('nextBtn').style.display = selectedWifi ? 'flex' : 'none';
|
|
document.getElementById('nextBtnText').textContent = '下一步';
|
|
}
|
|
} else {
|
|
window.location.href = 'bluetooth.html';
|
|
}
|
|
}
|
|
</script>
|
|
</body>
|
|
|
|
</html> |