修复配网时城市输入乱码的问题

This commit is contained in:
2026-02-02 08:14:35 +08:00
parent e0177bc005
commit 21c7f3f990
4 changed files with 294 additions and 319 deletions

View File

@@ -139,6 +139,7 @@ async def lcd_set(request):
elif k == "ui_type": elif k == "ui_type":
display.ui_type = v display.ui_type = v
config.set(k, v) config.set(k, v)
config.write()
except Exception as e: except Exception as e:
ack["status"] = "error" ack["status"] = "error"
ack["message"] = str(e) ack["message"] = str(e)
@@ -212,7 +213,7 @@ async def fetch_weather_data(city=None):
# 从配置文件获取城市,如果没有提供则使用配置中的值 # 从配置文件获取城市,如果没有提供则使用配置中的值
if not city: if not city:
city = config.get("city") or "北京" city = config.get("cityid") or "北京"
print(f"正在获取{city}天气数据...") print(f"正在获取{city}天气数据...")
# 从配置获取API基础URL默认使用官方API # 从配置获取API基础URL默认使用官方API

View File

@@ -119,11 +119,13 @@ class HTTPServer(BaseServer):
ssid = unquote(params.get(b"ssid", None)) ssid = unquote(params.get(b"ssid", None))
password = unquote(params.get(b"password", "")) password = unquote(params.get(b"password", ""))
city = unquote(params.get(b"city", None)) city = unquote(params.get(b"city", None))
cityid = params.get(b"city", None)
# 使用全局Config实例保存配置 # 使用全局Config实例保存配置
config.set("ssid", ssid) config.set("ssid", ssid)
config.set("password", password) config.set("password", password)
config.set("city", city) config.set("city", city)
config.set("cityid", cityid)
if config.write(): if config.write():
print("Configuration saved successfully") print("Configuration saved successfully")
else: else:

View File

@@ -79,6 +79,7 @@ placeholder="例如:北京"
可输入城市名称或城市ID<a 可输入城市名称或城市ID<a
href="https://mapopen-website-wiki.cdn.bcebos.com/cityList/weather_district_id.csv" href="https://mapopen-website-wiki.cdn.bcebos.com/cityList/weather_district_id.csv"
target="_blank" target="_blank"
download
>查看城市ID列表</a >查看城市ID列表</a
> >
</small></div><div class="form-group"><label class="form-label">自动熄屏时间</label </small></div><div class="form-group"><label class="form-label">自动熄屏时间</label
@@ -348,6 +349,7 @@ showMessage("城市名称不能为空", "error");
return; return;
}const configData = { }const configData = {
city: city, city: city,
cityid: encodeURIComponent(city),
};// 只有当输入了熄屏时间时才添加到配置中 };// 只有当输入了熄屏时间时才添加到配置中
if (standbyTime !== "") { if (standbyTime !== "") {
configData.standby_time = standbyTime; configData.standby_time = standbyTime;

View File

@@ -1,318 +1,288 @@
<html> <html><head><meta charset="utf-8" /><meta name="viewport" content="width=device-width, initial-scale=1" /><title>WiFi认证</title><style>
<head> body {
<meta charset="utf-8" /> font-family: sans-serif;
<meta name="viewport" content="width=device-width, initial-scale=1" /> background: #3498db;
<title>WiFi认证</title> width: 100%;
<style> text-align: center;
body { margin: 20px 0;
font-family: sans-serif; position: relative;
background: #3498db; }
width: 100%; p {
text-align: center; font-size: 12px;
margin: 20px 0; text-decoration: none;
position: relative; color: #fff;
} }
p { h1 {
font-size: 12px; font-size: 1.5em;
text-decoration: none; color: #525252;
color: #fff; }
} .box {
h1 { background: white;
font-size: 1.5em; width: 40ch;
color: #525252; border-radius: 6px;
} margin: 0 auto;
.box { padding: 10px 0;
background: white; position: relative;
width: 40ch; }
border-radius: 6px; input[type="text"],
margin: 0 auto; input[type="password"] {
padding: 10px 0; background: #ecf0f1;
position: relative; border: #ccc 1px solid;
} border-bottom: #ccc 2px solid;
input[type="text"], padding: 8px;
input[type="password"] { width: 80%;
background: #ecf0f1; color: #000;
border: #ccc 1px solid; margin-top: 10px;
border-bottom: #ccc 2px solid; font-size: 1em;
padding: 8px; border-radius: 4px;
width: 80%; }
color: #000; .btn {
margin-top: 10px; background: #2ecc71;
font-size: 1em; width: 80%;
border-radius: 4px; padding: 8px 0;
} color: white;
.btn { border-radius: 4px;
background: #2ecc71; border: #27ae60 1px solid;
width: 80%; margin: 20 auto;
padding: 8px 0; font-weight: 800;
color: white; font-size: 0.9em;
border-radius: 4px; cursor: pointer;
border: #27ae60 1px solid; }
margin: 20 auto; .btn:hover {
font-weight: 800; background: #27ae60;
font-size: 0.9em; }
cursor: pointer; .config-title {
} font-size: 1em;
.btn:hover { color: #525252;
background: #27ae60; margin-top: 15px;
} }
.config-title { .wifi-list {
font-size: 1em; width: 80%;
color: #525252; max-height: 200px;
margin-top: 15px; overflow-y: auto;
} margin: 10px auto;
.wifi-list { text-align: left;
width: 80%; border: 1px solid #eee;
max-height: 200px; background: #f8f8f8;
overflow-y: auto; border-radius: 4px;
margin: 10px auto; padding: 5px;
text-align: left; }
border: 1px solid #eee; .wifi-item {
background: #f8f8f8; padding: 5px;
border-radius: 4px; cursor: pointer;
padding: 5px; border-bottom: 1px solid #eee;
} display: flex;
.wifi-item { align-items: center;
padding: 5px; justify-content: space-between;
cursor: pointer; }
border-bottom: 1px solid #eee; .wifi-item:hover {
display: flex; background: #e0e0e0;
align-items: center; }
justify-content: space-between; .wifi-name {
} flex-grow: 1;
.wifi-item:hover { }
background: #e0e0e0; .wifi-signal {
} font-size: 12px;
.wifi-name { color: #888;
flex-grow: 1; }
} .refresh-btn {
.wifi-signal { position: absolute;
font-size: 12px; top: 10px;
color: #888; right: 10px;
} background: none;
.refresh-btn { border: none;
position: absolute; cursor: pointer;
top: 10px; font-size: 20px;
right: 10px; color: #7f8c8d;
background: none; width: 30px;
border: none; height: 30px;
cursor: pointer; display: flex;
font-size: 20px; align-items: center;
color: #7f8c8d; justify-content: center;
width: 30px; border-radius: 50%;
height: 30px; }
display: flex; .refresh-btn:hover {
align-items: center; background: #ecf0f1;
justify-content: center; }
border-radius: 50%; .refresh-btn:disabled {
} color: #bdc3c7;
.refresh-btn:hover { cursor: not-allowed;
background: #ecf0f1; }
} .wifi-icon {
.refresh-btn:disabled { position: relative;
color: #bdc3c7; display: inline-block;
cursor: not-allowed; width: 18px;
} height: 12px;
.wifi-icon { margin-right: 5px;
position: relative; }
display: inline-block; .wifi-icon-bar {
width: 18px; position: absolute;
height: 12px; bottom: 0;
margin-right: 5px; background: #7f8c8d;
} border-radius: 1px;
.wifi-icon-bar { }
position: absolute; .wifi-icon-bar:nth-child(1) {
bottom: 0; left: 0;
background: #7f8c8d; width: 3px;
border-radius: 1px; height: 3px;
} }
.wifi-icon-bar:nth-child(1) { .wifi-icon-bar:nth-child(2) {
left: 0; left: 5px;
width: 3px; width: 3px;
height: 3px; height: 6px;
} }
.wifi-icon-bar:nth-child(2) { .wifi-icon-bar:nth-child(3) {
left: 5px; left: 10px;
width: 3px; width: 3px;
height: 6px; height: 9px;
} }
.wifi-icon-bar:nth-child(3) { .wifi-icon-bar:nth-child(4) {
left: 10px; left: 15px;
width: 3px; width: 3px;
height: 9px; height: 12px;
} }
.wifi-icon-bar:nth-child(4) { .wifi-signal-4 .wifi-icon-bar {
left: 15px; background: #2ecc71;
width: 3px; }
height: 12px; .wifi-signal-3 .wifi-icon-bar:nth-child(1),
} .wifi-signal-3 .wifi-icon-bar:nth-child(2),
.wifi-signal-4 .wifi-icon-bar { .wifi-signal-3 .wifi-icon-bar:nth-child(3) {
background: #2ecc71; background: #f1c40f;
} }
.wifi-signal-3 .wifi-icon-bar:nth-child(1), .wifi-signal-2 .wifi-icon-bar:nth-child(1),
.wifi-signal-3 .wifi-icon-bar:nth-child(2), .wifi-signal-2 .wifi-icon-bar:nth-child(2) {
.wifi-signal-3 .wifi-icon-bar:nth-child(3) { background: #e67e22;
background: #f1c40f; }
} .wifi-signal-1 .wifi-icon-bar:nth-child(1) {
.wifi-signal-2 .wifi-icon-bar:nth-child(1), background: #e74c3c;
.wifi-signal-2 .wifi-icon-bar:nth-child(2) { }
background: #e67e22; /* 遮罩层样式 */
} .overlay {
.wifi-signal-1 .wifi-icon-bar:nth-child(1) { position: fixed;
background: #e74c3c; top: 0;
} left: 0;
/* 遮罩层样式 */ width: 100%;
.overlay { height: 100%;
position: fixed; background: rgba(0, 0, 0, 0.7);
top: 0; display: none;
left: 0; z-index: 1000;
width: 100%; justify-content: center;
height: 100%; align-items: center;
background: rgba(0, 0, 0, 0.7); }
display: none; .overlay-content {
z-index: 1000; background: white;
justify-content: center; padding: 30px;
align-items: center; border-radius: 8px;
} text-align: center;
.overlay-content { max-width: 80%;
background: white; }
padding: 30px; .spinner-small {
border-radius: 8px; width: 30px;
text-align: center; height: 30px;
max-width: 80%; border: 3px solid #f3f3f3;
} border-top: 3px solid #3498db;
.spinner-small { border-radius: 50%;
width: 30px; margin: 15px auto;
height: 30px; animation: spin 1.5s linear infinite;
border: 3px solid #f3f3f3; }
border-top: 3px solid #3498db; </style></head><body><form action="/login" method="get" class="box"><h1>WiFi 配置</h1><button
border-radius: 50%; type="button"
margin: 15px auto; class="refresh-btn"
animation: spin 1.5s linear infinite; onclick="refreshList()"
} title="刷新WiFi列表"
</style> >
</head>
<body> </button><div id="wifiList" class="wifi-list"></div><input
<form action="/login" method="get" class="box"> type="text"
<h1>WiFi 配置</h1> id="ssid"
<button placeholder="WiFi名称"
type="button" name="ssid"
class="refresh-btn" required
onclick="refreshList()" /><br /><input
title="刷新WiFi列表" type="password"
> id="pwd"
placeholder="WiFi密码"
</button> name="password"
<div id="wifiList" class="wifi-list"></div> /><br /><input
<input type="text"
type="text" placeholder="城市名称"
id="ssid" name="city"
placeholder="WiFi名称" value=""
name="ssid" /><br /><button type="submit" class="btn">保存配置</button></form><div class="overlay" id="connectingOverlay"><div class="overlay-content"><h2>正在连接到WiFi</h2><div class="spinner-small"></div><p>设备正在尝试连接,请稍候...</p></div></div><script>
required window.onload = function () {
/><br /> fetchWifiList();// 添加表单提交事件监听
<input document
type="password" .querySelector(".box")
id="pwd" .addEventListener("submit", function (e) {
placeholder="WiFi密码" // 显示遮罩层
name="password" document.getElementById(
/><br /> "connectingOverlay",
<input ).style.display = "flex";
type="text" });
placeholder="城市名称" };
name="city" function fetchWifiList() {
value="" const listContainer = document.getElementById("wifiList");
/><br /> listContainer.innerHTML = "Loading...";
<button type="submit" class="btn">保存配置</button> fetch("/scan")
</form> .then((response) => response.json())
.then((data) => {
<!-- 遮罩层 --> if (data.networks) {
<div class="overlay" id="connectingOverlay"> data.networks.sort((a, b) => b.rssi - a.rssi);
<div class="overlay-content"> displayWifiList(data.networks);
<h2>正在连接到WiFi</h2> }
<div class="spinner-small"></div> })
<p>设备正在尝试连接,请稍候...</p> .catch((error) => {
</div> console.error("Error fetching WiFi list:", error);
</div> });
<script> }
window.onload = function () { function getSignalLevel(rssi) {
fetchWifiList(); if (rssi >= -50) return 4;
if (rssi >= -60) return 3;
// 添加表单提交事件监听 if (rssi >= -70) return 2;
document return 1;
.querySelector(".box") }
.addEventListener("submit", function (e) { function createSignalIcon(signalLevel) {
// 显示遮罩层 const icon = document.createElement("span");
document.getElementById( icon.className = `wifi-icon wifi-signal-${signalLevel}`;
"connectingOverlay", for (let i = 0; i < 4; i++) {
).style.display = "flex"; const bar = document.createElement("span");
}); bar.className = "wifi-icon-bar";
}; icon.appendChild(bar);
function fetchWifiList() { }
const listContainer = document.getElementById("wifiList"); return icon;
listContainer.innerHTML = "Loading..."; }
fetch("/scan") function displayWifiList(networks) {
.then((response) => response.json()) const listContainer = document.getElementById("wifiList");
.then((data) => { listContainer.innerHTML = "";
if (data.networks) { for (const network of networks) {
data.networks.sort((a, b) => b.rssi - a.rssi); const item = document.createElement("div");
displayWifiList(data.networks); item.className = "wifi-item";
} const nameContainer = document.createElement("div");
}) nameContainer.className = "wifi-name";
.catch((error) => { const signalLevel = getSignalLevel(network.rssi);
console.error("Error fetching WiFi list:", error); nameContainer.appendChild(createSignalIcon(signalLevel));
}); const nameText = document.createTextNode(network.ssid);
} nameContainer.appendChild(nameText);
function getSignalLevel(rssi) { const signalContainer = document.createElement("div");
if (rssi >= -50) return 4; signalContainer.className = "wifi-signal";
if (rssi >= -60) return 3; signalContainer.textContent = `${network.rssi} dBm`;
if (rssi >= -70) return 2; item.appendChild(nameContainer);
return 1; item.appendChild(signalContainer);
} item.onclick = function () {
function createSignalIcon(signalLevel) { document.getElementById("ssid").value = network.ssid;
const icon = document.createElement("span"); document.getElementById("pwd").focus();
icon.className = `wifi-icon wifi-signal-${signalLevel}`; };
for (let i = 0; i < 4; i++) { listContainer.appendChild(item);
const bar = document.createElement("span"); }
bar.className = "wifi-icon-bar"; }
icon.appendChild(bar); function refreshList() {
} const btn = document.querySelector(".refresh-btn");
return icon; btn.innerHTML = "⟳";
} btn.disabled = true;
function displayWifiList(networks) { fetchWifiList();
const listContainer = document.getElementById("wifiList"); setTimeout(() => {
listContainer.innerHTML = ""; btn.innerHTML = "";
for (const network of networks) { btn.disabled = false;
const item = document.createElement("div"); }, 1000);
item.className = "wifi-item"; }
const nameContainer = document.createElement("div"); </script></body></html>
nameContainer.className = "wifi-name";
const signalLevel = getSignalLevel(network.rssi);
nameContainer.appendChild(createSignalIcon(signalLevel));
const nameText = document.createTextNode(network.ssid);
nameContainer.appendChild(nameText);
const signalContainer = document.createElement("div");
signalContainer.className = "wifi-signal";
signalContainer.textContent = `${network.rssi} dBm`;
item.appendChild(nameContainer);
item.appendChild(signalContainer);
item.onclick = function () {
document.getElementById("ssid").value = network.ssid;
document.getElementById('pwd').focus();
};
listContainer.appendChild(item);
}
}
function refreshList() {
const btn = document.querySelector(".refresh-btn");
btn.innerHTML = "⟳";
btn.disabled = true;
fetchWifiList();
setTimeout(() => {
btn.innerHTML = "↻";
btn.disabled = false;
}, 1000);
}
</script>
</body>
</html>