op-packages/luci-app-netspeedtest/htdocs/luci-static/resources/view/netspeedtest/onlinespeedtest.js
github-actions[bot] 9f83df92e8 🚀 Sync 2026-03-08 00:54:34
2026-03-08 00:54:34 +08:00

193 lines
6.5 KiB
JavaScript

/* Copyright (C) 2021-2026 sirpdboy herboy2008@gmail.com https://github.com/sirpdboy/luci-app-netspeedtest */
'use strict';
'require view';
'require uci';
'require form';
return view.extend({
load() {
return Promise.all([
uci.load('netspeedtest')
]);
},
render(res) {
let m, s, o;
m = new form.Map('netspeedtest', _('Online SpeedTest'));
let currentSpeedTestUrl = uci.get('netspeedtest', 'config', 'speedtest_site') || 'https://plugin.speedtest.cn/taste#/?t=1767018285493';
if (!currentSpeedTestUrl) {
currentSpeedTestUrl = 'https://plugin.speedtest.cn/taste#/?t=1767018285493';
uci.set('netspeedtest', 'config', 'speedtest_site', currentSpeedTestUrl);
uci.save();
}
s = m.section(form.NamedSection, 'config', 'netspeedtest');
s.anonymous = true;
// 下拉选择
o = s.option(form.DummyValue, '_speedtest_select');
o.textvalue = function() {
return '';
};
o.render = function(section_id) {
const sites = [
{url: 'https://plugin.speedtest.cn/taste#/?t=1767018285493', name: 'speedtest.cn'},
{url: 'https://static.hdslb.com/', name: 'hdslb.com'},
{url: 'https://test.ustc.edu.cn/', name: 'ustc.edu.cn'},
{url: 'https://www1.szu.edu.cn/nc/speedtest/', name: 'szu.edu.cn'},
{url: 'https://10000.gd.cn/#/speed', name: 'gd.cn'},
{url: 'https://speed.cloudflare.com/', name: 'cloudflare.com'},
{url: 'https://fast.com/', name: 'Netflix fast.com'},
{url: '//openspeedtest.com/speedtest', name: 'openspeedtest.com'}
];
const container = E('div', {
class: 'cbi-value'
});
const label = E('label', {
class: 'cbi-value-title',
for: 'speedtest-site-select'
}, _('Select speed measurement station'));
const field = E('div', {
class: 'cbi-value-field',
});
const select = E('select', {
id: 'speedtest-site-select',
class: 'cbi-input-select'
});
sites.forEach(site => {
const option = E('option', {
value: site.url,
selected: currentSpeedTestUrl === site.url ? 'selected' : null
}, site.name);
select.appendChild(option);
});
function saveConfig(url) {
try {
uci.set('netspeedtest', 'config', 'speedtest_site', url);
uci.save();
} catch (e) {
}
}
select.addEventListener('change', function() {
const iframe = document.getElementById('speedtest-iframe');
if (iframe && this.value) {
currentSpeedTestUrl = this.value;
iframe.src = this.value;
saveConfig(this.value);
}
});
field.appendChild(select);
container.appendChild(label);
container.appendChild(field);
const saveStatus = E('small', {
id: 'save-status',
style: 'display: block; margin-top: 5px; color: #28a745; opacity: 0; transition: opacity 0.3s;'
});
field.appendChild(saveStatus);
return container;
};
s = m.section(form.NamedSection, '_iframe');
s.anonymous = true;
s.render = function(section_id) {
const container = E('div', {
class: 'speedtest-wrapper mobiliframe',
style: 'width:100%;height:550px;position:relative;overflow:hidden;margin-top:20px;'
});
const header = E('div', {
style: 'display:flex;justify-content:space-between;align-items:center;padding: 0.5rem 1rem;'
}, [
E('span', {
style: 'font-weight:bold;'
}, _('NetSpeedtest')),
]);
const iframeContainer = E('div', {
style: 'height: calc(100% - 33px);'
});
const iframe = E('iframe', {
id: 'speedtest-iframe',
src: currentSpeedTestUrl,
style: 'width:100%;height:100%;border:none;background: #fff'
});
iframeContainer.appendChild(iframe);
const style = E('style', {}, `
.speedtest-wrapper {
transition: all 0.3s ease;
}
.speedtest-wrapper:hover {
box-shadow: 0 4px 20px rgba(0,0,0,0.15);
}
#save-status {
transition: opacity 0.3s ease;
}
@media (prefers-color-scheme: dark) {
.speedtest-wrapper {
background: #2d2d2d;
}
.speedtest-wrapper > div:first-child {
background: #3d3d3d;
border-color: #555;
}
.speedtest-wrapper > div:first-child span {
color: #e0e0e0;
}
}
@media (max-width: 768px) {
.speedtest-wrapper {
height: 500px;
}
.cbi-value-title {
width: 100% !important;
margin-bottom: 5px;
}
.cbi-value-field {
width: 100% !important;
}
#speedtest-site-select {
max-width: 100%;
}
}
`);
container.appendChild(header);
container.appendChild(iframeContainer);
container.appendChild(style);
return container;
};
return m.render();
},
handleSaveApply: null,
handleSave: null,
handleReset: null
});