361 lines
11 KiB
HTML
361 lines
11 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="zh-CN">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<title>ESP32 萤火虫设备配置</title>
|
||
<style>
|
||
* {
|
||
margin: 0;
|
||
padding: 0;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
body {
|
||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
min-height: 100vh;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
padding: 20px;
|
||
}
|
||
|
||
.container {
|
||
background: white;
|
||
border-radius: 20px;
|
||
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
||
padding: 40px;
|
||
max-width: 500px;
|
||
width: 100%;
|
||
}
|
||
|
||
.header {
|
||
text-align: center;
|
||
margin-bottom: 30px;
|
||
}
|
||
|
||
.logo {
|
||
font-size: 48px;
|
||
margin-bottom: 10px;
|
||
}
|
||
|
||
.title {
|
||
font-size: 24px;
|
||
font-weight: bold;
|
||
color: #333;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.subtitle {
|
||
color: #666;
|
||
font-size: 14px;
|
||
}
|
||
|
||
.form-group {
|
||
margin-bottom: 20px;
|
||
}
|
||
|
||
.form-label {
|
||
display: block;
|
||
font-weight: 500;
|
||
color: #333;
|
||
margin-bottom: 8px;
|
||
}
|
||
|
||
.form-input {
|
||
width: 100%;
|
||
padding: 12px 16px;
|
||
border: 2px solid #e1e5e9;
|
||
border-radius: 10px;
|
||
font-size: 16px;
|
||
transition: border-color 0.3s;
|
||
}
|
||
|
||
.form-input:focus {
|
||
outline: none;
|
||
border-color: #667eea;
|
||
}
|
||
|
||
.btn-primary {
|
||
width: 100%;
|
||
padding: 14px;
|
||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||
color: white;
|
||
border: none;
|
||
border-radius: 10px;
|
||
font-size: 16px;
|
||
font-weight: 500;
|
||
cursor: pointer;
|
||
transition: transform 0.2s;
|
||
}
|
||
|
||
.btn-primary:hover {
|
||
transform: translateY(-2px);
|
||
}
|
||
|
||
.btn-primary:disabled {
|
||
opacity: 0.6;
|
||
cursor: not-allowed;
|
||
transform: none;
|
||
}
|
||
|
||
.status {
|
||
margin-top: 20px;
|
||
padding: 12px;
|
||
border-radius: 8px;
|
||
text-align: center;
|
||
font-weight: 500;
|
||
}
|
||
|
||
.status.success {
|
||
background: #d4edda;
|
||
color: #155724;
|
||
border: 1px solid #c3e6cb;
|
||
}
|
||
|
||
.status.error {
|
||
background: #f8d7da;
|
||
color: #721c24;
|
||
border: 1px solid #f5c6cb;
|
||
}
|
||
|
||
.status.loading {
|
||
background: #d1ecf1;
|
||
color: #0c5460;
|
||
border: 1px solid #bee5eb;
|
||
}
|
||
|
||
.wifi-list {
|
||
max-height: 200px;
|
||
overflow-y: auto;
|
||
border: 1px solid #e1e5e9;
|
||
border-radius: 8px;
|
||
margin-bottom: 15px;
|
||
}
|
||
|
||
.wifi-item {
|
||
padding: 12px 16px;
|
||
border-bottom: 1px solid #f0f0f0;
|
||
cursor: pointer;
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
}
|
||
|
||
.wifi-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.wifi-item:hover {
|
||
background: #f8f9fa;
|
||
}
|
||
|
||
.wifi-item.selected {
|
||
background: #e3f2fd;
|
||
color: #1976d2;
|
||
}
|
||
|
||
.wifi-signal {
|
||
font-size: 12px;
|
||
color: #666;
|
||
}
|
||
|
||
.scan-btn {
|
||
width: 100%;
|
||
padding: 10px;
|
||
background: #f8f9fa;
|
||
border: 1px solid #e1e5e9;
|
||
border-radius: 8px;
|
||
cursor: pointer;
|
||
margin-bottom: 15px;
|
||
}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
<div class="header">
|
||
<div class="logo">🔥</div>
|
||
<div class="title">萤火虫设备配置</div>
|
||
<div class="subtitle">请配置您的WiFi网络连接</div>
|
||
</div>
|
||
|
||
<form id="configForm">
|
||
<div class="form-group">
|
||
<label class="form-label">扫描WiFi网络</label>
|
||
<button type="button" class="scan-btn" onclick="scanWifi()">🔍 扫描附近的WiFi网络</button>
|
||
<div id="wifiList" class="wifi-list" style="display: none;"></div>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="ssid">WiFi名称 (SSID)</label>
|
||
<input type="text" id="ssid" class="form-input" placeholder="请输入WiFi名称" required>
|
||
</div>
|
||
|
||
<div class="form-group">
|
||
<label class="form-label" for="password">WiFi密码</label>
|
||
<input type="password" id="password" class="form-input" placeholder="请输入WiFi密码" required>
|
||
</div>
|
||
|
||
<button type="submit" class="btn-primary" id="submitBtn">
|
||
📡 配置设备
|
||
</button>
|
||
</form>
|
||
|
||
<div id="status" class="status" style="display: none;"></div>
|
||
</div>
|
||
|
||
<script>
|
||
let selectedWifi = '';
|
||
|
||
// 扫描WiFi网络
|
||
async function scanWifi() {
|
||
const wifiList = document.getElementById('wifiList');
|
||
const scanBtn = document.querySelector('.scan-btn');
|
||
|
||
scanBtn.textContent = '🔄 扫描中...';
|
||
scanBtn.disabled = true;
|
||
|
||
try {
|
||
// 模拟WiFi扫描结果
|
||
const mockWifiList = [
|
||
{ ssid: 'MyHome_WiFi', rssi: -45, security: 'WPA2' },
|
||
{ ssid: 'Office_Network', rssi: -60, security: 'WPA2' },
|
||
{ ssid: 'Guest_WiFi', rssi: -75, security: 'Open' },
|
||
{ ssid: 'Neighbor_5G', rssi: -80, security: 'WPA3' }
|
||
];
|
||
|
||
// 实际应该调用ESP32的WiFi扫描API
|
||
// const response = await fetch('/api/wifi/scan');
|
||
// const wifiList = await response.json();
|
||
|
||
displayWifiList(mockWifiList);
|
||
|
||
} catch (error) {
|
||
showStatus('WiFi扫描失败: ' + error.message, 'error');
|
||
}
|
||
|
||
scanBtn.textContent = '🔍 重新扫描';
|
||
scanBtn.disabled = false;
|
||
}
|
||
|
||
// 显示WiFi列表
|
||
function displayWifiList(networks) {
|
||
const wifiList = document.getElementById('wifiList');
|
||
wifiList.innerHTML = '';
|
||
|
||
networks.forEach(network => {
|
||
const item = document.createElement('div');
|
||
item.className = 'wifi-item';
|
||
item.onclick = () => selectWifi(network.ssid, item);
|
||
|
||
const signalStrength = getSignalStrength(network.rssi);
|
||
|
||
item.innerHTML = `
|
||
<div>
|
||
<strong>${network.ssid}</strong>
|
||
<div class="wifi-signal">${network.security} • ${signalStrength}</div>
|
||
</div>
|
||
<div>${getSignalIcon(network.rssi)}</div>
|
||
`;
|
||
|
||
wifiList.appendChild(item);
|
||
});
|
||
|
||
wifiList.style.display = 'block';
|
||
}
|
||
|
||
// 选择WiFi
|
||
function selectWifi(ssid, element) {
|
||
selectedWifi = ssid;
|
||
document.getElementById('ssid').value = ssid;
|
||
|
||
// 移除其他选中状态
|
||
document.querySelectorAll('.wifi-item').forEach(item => {
|
||
item.classList.remove('selected');
|
||
});
|
||
|
||
// 添加选中状态
|
||
element.classList.add('selected');
|
||
}
|
||
|
||
// 获取信号强度描述
|
||
function getSignalStrength(rssi) {
|
||
if (rssi > -50) return '信号强';
|
||
if (rssi > -70) return '信号中等';
|
||
return '信号弱';
|
||
}
|
||
|
||
// 获取信号图标
|
||
function getSignalIcon(rssi) {
|
||
if (rssi > -50) return '📶';
|
||
if (rssi > -70) return '📶';
|
||
return '📶';
|
||
}
|
||
|
||
// 显示状态消息
|
||
function showStatus(message, type) {
|
||
const status = document.getElementById('status');
|
||
status.textContent = message;
|
||
status.className = `status ${type}`;
|
||
status.style.display = 'block';
|
||
}
|
||
|
||
// 表单提交
|
||
document.getElementById('configForm').addEventListener('submit', async function(e) {
|
||
e.preventDefault();
|
||
|
||
const ssid = document.getElementById('ssid').value;
|
||
const password = document.getElementById('password').value;
|
||
const submitBtn = document.getElementById('submitBtn');
|
||
|
||
if (!ssid || !password) {
|
||
showStatus('请填写完整的WiFi信息', 'error');
|
||
return;
|
||
}
|
||
|
||
submitBtn.disabled = true;
|
||
submitBtn.textContent = '⏳ 配置中...';
|
||
showStatus('正在配置WiFi连接,请稍候...', 'loading');
|
||
|
||
try {
|
||
const response = await fetch('/api/wifi', {
|
||
method: 'POST',
|
||
headers: {
|
||
'Content-Type': 'application/json',
|
||
},
|
||
body: JSON.stringify({
|
||
ssid: ssid,
|
||
password: password
|
||
})
|
||
});
|
||
|
||
const result = await response.json();
|
||
|
||
if (result.success) {
|
||
showStatus('✅ 配置成功!设备将重新连接到您的WiFi网络。请在手机上连接到相同的WiFi,然后打开萤火虫APP继续使用。', 'success');
|
||
|
||
// 3秒后自动关闭页面
|
||
setTimeout(() => {
|
||
window.close();
|
||
}, 3000);
|
||
} else {
|
||
showStatus('❌ 配置失败: ' + (result.message || '未知错误'), 'error');
|
||
}
|
||
|
||
} catch (error) {
|
||
showStatus('❌ 配置失败: ' + error.message, 'error');
|
||
}
|
||
|
||
submitBtn.disabled = false;
|
||
submitBtn.textContent = '📡 配置设备';
|
||
});
|
||
|
||
// 页面加载完成后自动扫描WiFi
|
||
window.addEventListener('load', function() {
|
||
setTimeout(scanWifi, 1000);
|
||
});
|
||
</script>
|
||
</body>
|
||
</html>
|