function WirelessRepeater({}) {
// 模拟扫描到的无线网络数据
const initialScanData = {
scanning: false,
networks: [
{ ssid: "HomeWiFi_5G", bssid: "11:22:33:44:55:66", signal: 85, security: "wpa2", band: "5GHz", channel: 36 },
{ ssid: "Office_Network", bssid: "66:55:44:33:22:11", signal: 72, security: "wpa2", band: "2.4GHz", channel: 6 },
{ ssid: "GuestWiFi", bssid: "aa:bb:cc:dd:ee:ff", signal: 45, security: "open", band: "2.4GHz", channel: 1 },
{ ssid: "TP-Link_1234", bssid: "12:34:56:78:90:ab", signal: 68, security: "wpa2", band: "5GHz", channel: 149 }
],
selectedNetwork: null,
reconnectInterval: 300
};
// 中继配置状态
const initialRepeaterConfig = {
enabled: false,
ssid: "Repeater_Ext",
security: "wpa2",
password: "",
band: "auto",
channel_width: "20MHz",
tx_power: "80%",
hidden: false
};
const [scanData, setScanData] = useState(null);
const [repeaterConfig, setRepeaterConfig] = useState(null);
const [saveResult, setSaveResult] = useState(null);
const [isScanning, setIsScanning] = useState(false);
const [showAdvanced, setShowAdvanced] = useState(false);
// 模拟扫描无线网络
const scanNetworks = () => {
setIsScanning(true);
return new Promise(resolve => {
setTimeout(() => {
// 模拟扫描过程中信号强度的随机变化
const updatedNetworks = initialScanData.networks.map(network => ({
...network,
signal: Math.max(20, Math.min(95, network.signal + (Math.random() * 20 - 10)))
}));
setScanData({
...initialScanData,
networks: updatedNetworks,
scanning: false
});
setIsScanning(false);
resolve();
}, 2000);
});
};
// 初始化配置
const refresh = () => {
return new Promise(resolve => {
setTimeout(() => {
setScanData(initialScanData);
setRepeaterConfig(initialRepeaterConfig);
resolve();
}, 300);
});
};
// 选择网络进行中继
const selectNetwork = (network) => {
setScanData(prev => ({
...prev,
selectedNetwork: network
}));
// 自动填充中继配置
setRepeaterConfig(prev => ({
...prev,
ssid: `${network.ssid}_Repeater`
}));
};
// 配置更新函数
const setRepeaterConfigFn = (key) => (value) => {
setRepeaterConfig(prev => ({
...prev,
[key]: value
}));
};
// 保存中继配置
const saveRepeaterConfig = (ev) => {
ev.preventDefault();
fetch('api/repeater/set', {
method: 'post',
body: JSON.stringify({
config: repeaterConfig,
targetNetwork: scanData.selectedNetwork
})
})
.then(r => r.json())
.then(r => {
setSaveResult(r);
// 保存成功后重新扫描网络状态
setTimeout(refresh, 1000);
})
.catch(err => {
setSaveResult({ status: false, message: '保存失败: ' + err.message });
});
};
// 启动中继功能
const startRepeater = () => {
if (!scanData.selectedNetwork) {
setSaveResult({ status: false, message: '请先选择要中继的网络' });
return;
}
setRepeaterConfig(prev => ({ ...prev, enabled: true }));
saveRepeaterConfig(new Event('submit'));
};
// 停止中继功能
const stopRepeater = () => {
setRepeaterConfig(prev => ({ ...prev, enabled: false }));
fetch('api/repeater/stop', { method: 'post' })
.then(r => r.json())
.then(r => setSaveResult(r))
.then(refresh);
};
// 组件初始化
useEffect(() => {
refresh();
}, []);
if (!scanData || !repeaterConfig) return '加载中...';
return html`
<div class="m-4 grid grid-cols-1 gap-6 lg:grid-cols-2">
<!-- 网络扫描区域 -->
<div class="py-1 divide-y border rounded bg-white flex flex-col">
<div class="font-light uppercase flex items-center justify-between text-gray-600 px-4 py-2">
<span>无线网络扫描</span>
<div class="flex gap-2">
<${Button}
icon=${Icons.refresh}
onclick=${scanNetworks}
disabled=${isScanning}
title="重新扫描"
variant="outline"
/>
<${Button}
icon=${Icons.wifi}
onclick=${repeaterConfig.enabled ? stopRepeater : startRepeater}
variant=${repeaterConfig.enabled ? "danger" : "primary"}
title=${repeaterConfig.enabled ? "停止中继" : "启动中继"}
/>
</div>
</div>
<div class="py-2 px-4 flex-1 flex flex-col">
${saveResult && html`<${Notification}
ok=${saveResult.status}
text=${saveResult.message}
close=${() => setSaveResult(null)}
/>`}
<!-- 扫描状态指示 -->
<div class="mb-4 p-3 bg-gray-50 rounded flex items-center justify-between">
<span class="text-sm text-gray-600">
${isScanning ? '扫描中...' : `找到 ${scanData.networks.length} 个网络`}
</span>
<div class="flex items-center gap-2">
<div class="w-2 h-2 rounded-full ${repeaterConfig.enabled ? 'bg-green-500' : 'bg-gray-400'}"></div>
<span class="text-xs">${repeaterConfig.enabled ? '中继运行中' : '中继已停止'}</span>
</div>
</div>
<!-- 网络列表 -->
<div class="space-y-2 max-h-96 overflow-y-auto">
${scanData.networks.map((network, index) => html`
<div key=${network.bssid}
class="p-3 border rounded cursor-pointer transition-all hover:bg-blue-50
${scanData.selectedNetwork?.bssid === network.bssid ? 'border-blue-500 bg-blue-50' : 'border-gray-200'}"
onclick=${() => selectNetwork(network)}>
<div class="flex items-center justify-between">
<div class="flex items-center gap-3">
<div class="w-8 h-8 flex items-center justify-center bg-gray-100 rounded">
${network.security === 'open' ? html`<${Icons.unlock} />` : html`<${Icons.lock} />`}
</div>
<div>
<div class="font-medium">${network.ssid}</div>
<div class="text-xs text-gray-500">${network.bssid}</div>
</div>
</div>
<div class="text-right">
<div class="flex items-center gap-1">
<${SignalStrength} strength=${network.signal} />
<span class="text-sm font-mono">${network.signal}%</span>
</div>
<div class="text-xs text-gray-500">${network.band} · 信道 ${network.channel}</div>
</div>
</div>
</div>
`)}
</div>
</div>
</div>
<!-- 中继配置区域 -->
<div class="py-1 divide-y border rounded bg-white flex flex-col">
<div class="font-light uppercase flex items-center justify-between text-gray-600 px-4 py-2">
<span>中继配置</span>
<${Button}
icon=${Icons.settings}
onclick=${() => setShowAdvanced(!showAdvanced)}
title=${showAdvanced ? "隐藏高级设置" : "显示高级设置"}
variant="outline"
/>
</div>
<div class="py-2 px-4 flex-1 flex flex-col">
${scanData.selectedNetwork ? html`
<div class="mb-4 p-3 bg-green-50 border border-green-200 rounded">
<div class="font-medium text-green-800">已选择网络中继</div>
<div class="text-sm text-green-600">${scanData.selectedNetwork.ssid}</div>
</div>
` : html`
<div class="mb-4 p-3 bg-yellow-50 border border-yellow-200 rounded">
<div class="text-sm text-yellow-800">请从左侧列表选择要中继的网络</div>
</div>
`}
<${Setting}
title="启用无线中继"
value=${repeaterConfig.enabled}
setfn=${setRepeaterConfigFn('enabled')}
type="switch"
/>
<${Setting}
title="中继SSID"
value=${repeaterConfig.ssid}
setfn=${setRepeaterConfigFn('ssid')}
type="text"
disabled=${!scanData.selectedNetwork}
description="中继后网络的名称"
/>
<${Setting}
title="安全模式"
value=${repeaterConfig.security}
setfn=${setRepeaterConfigFn('security')}
type="select"
options=${['open', 'wpa', 'wpa2', 'wpa3']}
disabled=${!scanData.selectedNetwork}
/>
<${Setting}
title="无线密码"
value=${repeaterConfig.password}
setfn=${setRepeaterConfigFn('password')}
type="password"
disabled=${!scanData.selectedNetwork || repeaterConfig.security === 'open'}
placeholder=${repeaterConfig.security === 'open' ? '开放网络无需密码' : '输入无线密码'}
/>
${showAdvanced && html`
<div class="border-t pt-3 mt-3">
<div class="text-sm font-medium text-gray-700 mb-3">高级设置</div>
<${Setting}
title="频段选择"
value=${repeaterConfig.band}
setfn=${setRepeaterConfigFn('band')}
type="select"
options=${['auto', '2.4GHz', '5GHz']}
/>
<${Setting}
title="信道宽度"
value=${repeaterConfig.channel_width}
setfn=${setRepeaterConfigFn('channel_width')}
type="select"
options=${['20MHz', '40MHz', '80MHz']}
/>
<${Setting}
title="发射功率"
value=${repeaterConfig.tx_power}
setfn=${setRepeaterConfigFn('tx_power')}
type="select"
options=${['25%', '50%', '80%', '100%']}
/>
<${Setting}
title="隐藏网络"
value=${repeaterConfig.hidden}
setfn=${setRepeaterConfigFn('hidden')}
type="switch"
/>
</div>
`}
<div class="mb-1 mt-3 flex place-content-end gap-2">
<${Button}
icon=${Icons.refresh}
onclick=${refresh}
title="重置配置"
variant="outline"
/>
<${Button}
icon=${Icons.save}
onclick=${saveRepeaterConfig}
title="保存设置"
disabled=${!scanData.selectedNetwork}
/>
</div>
</div>
</div>
</div>
<!-- 状态信息栏 -->
${repeaterConfig.enabled && scanData.selectedNetwork && html`
<div class="mt-4 p-3 bg-blue-50 border border-blue-200 rounded">
<div class="flex items-center justify-between">
<div>
<div class="font-medium text-blue-800">无线中继运行中</div>
<div class="text-sm text-blue-600">
中继网络: ${scanData.selectedNetwork.ssid} → ${repeaterConfig.ssid}
</div>
</div>
<${Button}
icon=${Icons.stop}
onclick=${stopRepeater}
title="停止中继"
variant="danger"
size="sm"
/>
</div>
</div>
`}
`;
} 这个卡在
正在从服务器加载无线中继配置...
模拟API请求中 怎么解决
最新发布