mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-09 21:47:59 +08:00
245 lines
9.1 KiB
JavaScript
245 lines
9.1 KiB
JavaScript
'use strict';
|
|
'require view';
|
|
'require rpc';
|
|
'require poll';
|
|
'require ui';
|
|
'require dom';
|
|
|
|
var callGetStatus = rpc.declare({
|
|
object: 'luci.cf-optimizer',
|
|
method: 'get_status'
|
|
});
|
|
|
|
var callRunOnce = rpc.declare({
|
|
object: 'luci.cf-optimizer',
|
|
method: 'run_once'
|
|
});
|
|
|
|
var callServiceAction = rpc.declare({
|
|
object: 'luci.cf-optimizer',
|
|
method: 'service_action',
|
|
params: [ 'action' ]
|
|
});
|
|
|
|
return view.extend({
|
|
handleSaveApply: null,
|
|
handleSave: null,
|
|
handleReset: null,
|
|
|
|
load: function() {
|
|
return callGetStatus();
|
|
},
|
|
|
|
handleRunOnce: function(ev) {
|
|
ui.showModal(_('执行优选'), [
|
|
E('p', { 'class': 'spinning' }, _('正在后台启动优选探测测速任务,请稍候...'))
|
|
]);
|
|
return callRunOnce().then(function() {
|
|
setTimeout(function() {
|
|
ui.hideModal();
|
|
window.location.reload();
|
|
}, 3000);
|
|
}).catch(function(e) {
|
|
ui.addNotification(null, E('p', {}, e.message));
|
|
ui.hideModal();
|
|
});
|
|
},
|
|
|
|
handleServiceAction: function(action, ev) {
|
|
ui.showModal(_('服务操作'), [
|
|
E('p', { 'class': 'spinning' }, _('正在执行操作,请稍候...'))
|
|
]);
|
|
return callServiceAction(action).then(function() {
|
|
setTimeout(function() {
|
|
ui.hideModal();
|
|
window.location.reload();
|
|
}, 1500);
|
|
}).catch(function(e) {
|
|
ui.addNotification(null, E('p', {}, e.message));
|
|
ui.hideModal();
|
|
});
|
|
},
|
|
|
|
render: function(data) {
|
|
data = data || {};
|
|
|
|
var container = E('div', { 'class': 'cbi-map' }, [
|
|
E('h2', {}, _('Cloudflare 优选加速') + ' - ' + _('状态概览')),
|
|
E('div', { 'class': 'cbi-map-descr' }, _('监控当前生效的 Cloudflare 优选节点状态,展示各代理域名定向情况与最新测速排行榜。'))
|
|
]);
|
|
|
|
// 服务状态卡片
|
|
var isRunning = data.service_running === true;
|
|
var statusText = isRunning ? (_('运行中') + (data.service_pid ? ' [PID: ' + data.service_pid + ']' : '')) : _('已停止');
|
|
var statusColor = isRunning ? '#059669' : '#64748b';
|
|
|
|
var statusSection = E('fieldset', { 'class': 'cbi-section' }, [
|
|
E('legend', {}, _('服务状态')),
|
|
E('div', { 'class': 'cbi-section-node' }, [
|
|
E('table', { 'class': 'table cbi-section-table' }, [
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left', 'width': '25%' }, _('服务状态')),
|
|
E('td', { 'class': 'td left' }, [
|
|
E('span', { 'id': 'cf-service-status', 'style': 'font-weight:bold; color:' + statusColor + '; margin-right:15px;' }, statusText),
|
|
E('button', {
|
|
'class': 'btn cbi-button cbi-button-action',
|
|
'style': 'margin-right:10px;',
|
|
'click': ui.createHandlerFn(this, 'handleRunOnce')
|
|
}, _('立即执行优选')),
|
|
E('button', {
|
|
'class': 'btn cbi-button cbi-button-reload',
|
|
'click': ui.createHandlerFn(this, 'handleServiceAction', 'restart')
|
|
}, _('重启服务'))
|
|
])
|
|
]),
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left' }, _('上次更新时间')),
|
|
E('td', { 'class': 'td left', 'id': 'cf-last-update' }, data.last_update || '-')
|
|
]),
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left' }, _('生效优选 IP')),
|
|
E('td', { 'class': 'td left', 'id': 'cf-best-ip', 'style': 'font-weight:bold;' }, data.best_ip || '-')
|
|
]),
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left' }, _('次优备选 IP')),
|
|
E('td', { 'class': 'td left', 'id': 'cf-standby-ip' }, data.standby_ip ? (data.standby_ip + ' (' + (data.standby_colo || '-') + ')') : _('暂无备选'))
|
|
]),
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left' }, _('健康看门狗')),
|
|
E('td', { 'class': 'td left', 'id': 'cf-watchdog-status', 'style': 'font-weight:bold; color:' + ((data.watchdog_status && data.watchdog_status.indexOf('倒换') !== -1) ? '#d97706' : '#059669') }, data.watchdog_status || _('未运行'))
|
|
]),
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left' }, _('数据中心')),
|
|
E('td', { 'class': 'td left', 'id': 'cf-best-colo' }, data.best_colo || '-')
|
|
]),
|
|
E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td left' }, _('测速延迟')),
|
|
E('td', { 'class': 'td left', 'id': 'cf-best-latency' }, [
|
|
E('span', { 'style': 'color:#2563eb; font-weight:bold;' }, data.best_tcp_lat ? 'TCP: ' + data.best_tcp_lat : '-'),
|
|
E('span', { 'style': 'margin:0 8px; color:#cbd5e1;' }, '|'),
|
|
E('span', { 'style': 'color:#059669; font-weight:bold;' }, data.best_tls_lat ? 'TLS: ' + data.best_tls_lat : '-')
|
|
])
|
|
])
|
|
])
|
|
])
|
|
]);
|
|
|
|
// 域名定向列表
|
|
var domainRows = [];
|
|
if (Array.isArray(data.domains) && data.domains.length > 0) {
|
|
for (var i = 0; i < data.domains.length; i++) {
|
|
var d = data.domains[i];
|
|
domainRows.push(E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td' }, E('strong', {}, d.domain)),
|
|
E('td', { 'class': 'td' }, d.ip || '-'),
|
|
E('td', { 'class': 'td' }, d.colo || '-'),
|
|
E('td', { 'class': 'td' }, d.tcp_lat || '-'),
|
|
E('td', { 'class': 'td' }, d.tls_lat || '-'),
|
|
E('td', { 'class': 'td' }, E('span', { 'style': 'color:#059669; font-weight:bold;' }, d.status || _('正常')))
|
|
]));
|
|
}
|
|
} else {
|
|
domainRows.push(E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td', 'colspan': '6', 'style': 'text-align:center; color:#94a3b8;' }, _('暂无生效的域名定向记录,请在参数配置中添加域名并启动服务。'))
|
|
]));
|
|
}
|
|
|
|
var domainSection = E('fieldset', { 'class': 'cbi-section' }, [
|
|
E('legend', {}, _('域名定向列表')),
|
|
E('div', { 'class': 'cbi-section-node' }, [
|
|
E('table', { 'class': 'table cbi-section-table', 'id': 'cf-domain-table' }, [
|
|
E('tr', { 'class': 'tr table-titles' }, [
|
|
E('th', { 'class': 'th' }, _('目标域名')),
|
|
E('th', { 'class': 'th' }, _('生效优选 IP')),
|
|
E('th', { 'class': 'th' }, _('数据中心')),
|
|
E('th', { 'class': 'th' }, _('TCP 延迟')),
|
|
E('th', { 'class': 'th' }, _('TLS 延迟')),
|
|
E('th', { 'class': 'th' }, _('状态'))
|
|
])
|
|
].concat(domainRows))
|
|
])
|
|
]);
|
|
|
|
// 优选候选排行榜
|
|
var rankingRows = [];
|
|
if (Array.isArray(data.rankings) && data.rankings.length > 0) {
|
|
for (var j = 0; j < data.rankings.length; j++) {
|
|
var r = data.rankings[j];
|
|
rankingRows.push(E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td' }, r.rank),
|
|
E('td', { 'class': 'td' }, E('strong', {}, r.ip)),
|
|
E('td', { 'class': 'td' }, r.colo || '-'),
|
|
E('td', { 'class': 'td', 'style': 'color:#059669; font-weight:bold;' }, r.avg_lat),
|
|
E('td', { 'class': 'td' }, r.lat_range || '-'),
|
|
E('td', { 'class': 'td' }, r.loss_rate || '0.0%')
|
|
]));
|
|
}
|
|
} else {
|
|
rankingRows.push(E('tr', { 'class': 'tr' }, [
|
|
E('td', { 'class': 'td', 'colspan': '6', 'style': 'text-align:center; color:#94a3b8;' }, _('暂无排行榜数据'))
|
|
]));
|
|
}
|
|
|
|
var rankingSection = E('fieldset', { 'class': 'cbi-section' }, [
|
|
E('legend', {}, _('优选候选节点排行榜')),
|
|
E('div', { 'class': 'cbi-section-node' }, [
|
|
E('table', { 'class': 'table cbi-section-table', 'id': 'cf-ranking-table' }, [
|
|
E('tr', { 'class': 'tr table-titles' }, [
|
|
E('th', { 'class': 'th' }, _('排名')),
|
|
E('th', { 'class': 'th' }, _('候选 IP')),
|
|
E('th', { 'class': 'th' }, _('数据中心')),
|
|
E('th', { 'class': 'th' }, _('平均延迟')),
|
|
E('th', { 'class': 'th' }, _('时延范围')),
|
|
E('th', { 'class': 'th' }, _('丢包率'))
|
|
])
|
|
].concat(rankingRows))
|
|
])
|
|
]);
|
|
|
|
container.appendChild(statusSection);
|
|
container.appendChild(domainSection);
|
|
container.appendChild(rankingSection);
|
|
|
|
// 定时轮询更新
|
|
poll.add(function() {
|
|
return callGetStatus().then(function(res) {
|
|
res = res || {};
|
|
var running = res.service_running === true;
|
|
var stEl = document.getElementById('cf-service-status');
|
|
if (stEl) {
|
|
stEl.textContent = running ? (_('运行中') + (res.service_pid ? ' [PID: ' + res.service_pid + ']' : '')) : _('已停止');
|
|
stEl.style.color = running ? '#059669' : '#64748b';
|
|
}
|
|
var upEl = document.getElementById('cf-last-update');
|
|
if (upEl) upEl.textContent = res.last_update || '-';
|
|
|
|
var ipEl = document.getElementById('cf-best-ip');
|
|
if (ipEl) ipEl.textContent = res.best_ip || '-';
|
|
|
|
var sbEl = document.getElementById('cf-standby-ip');
|
|
if (sbEl) sbEl.textContent = res.standby_ip ? (res.standby_ip + ' (' + (res.standby_colo || '-') + ')') : _('暂无备选');
|
|
|
|
var wdEl = document.getElementById('cf-watchdog-status');
|
|
if (wdEl) {
|
|
wdEl.textContent = res.watchdog_status || _('未运行');
|
|
wdEl.style.color = (res.watchdog_status && res.watchdog_status.indexOf('倒换') !== -1) ? '#d97706' : '#059669';
|
|
}
|
|
|
|
var coloEl = document.getElementById('cf-best-colo');
|
|
if (coloEl) coloEl.textContent = res.best_colo || '-';
|
|
|
|
var latEl = document.getElementById('cf-best-latency');
|
|
if (latEl) {
|
|
dom.content(latEl, [
|
|
E('span', { 'style': 'color:#2563eb; font-weight:bold;' }, res.best_tcp_lat ? 'TCP: ' + res.best_tcp_lat : '-'),
|
|
E('span', { 'style': 'margin:0 8px; color:#cbd5e1;' }, '|'),
|
|
E('span', { 'style': 'color:#059669; font-weight:bold;' }, res.best_tls_lat ? 'TLS: ' + res.best_tls_lat : '-')
|
|
]);
|
|
}
|
|
});
|
|
}, 3);
|
|
|
|
return container;
|
|
}
|
|
});
|