Initial release: CPCHECK cloud port detection tool
Web-based TCP/UDP port checker with firewall/GFW diagnosis, PM2 deployment config, and Ubuntu one-click install script. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
const DIAGNOSIS_CONFIG = {
|
||||
port_open: { title: "端口开放", icon: "✓", class: "success" },
|
||||
port_not_open: { title: "端口未开放", icon: "✗", class: "danger" },
|
||||
likely_firewall: { title: "可能被防火墙拦截", icon: "⚠", class: "warning" },
|
||||
likely_blocked: { title: "可能被墙或过滤", icon: "⊘", class: "danger" },
|
||||
host_unreachable: { title: "主机不可达", icon: "✗", class: "danger" },
|
||||
dns_failed: { title: "DNS 解析失败", icon: "✗", class: "danger" },
|
||||
udp_ambiguous: { title: "UDP 状态不确定", icon: "?", class: "info" },
|
||||
};
|
||||
|
||||
const STATUS_LABELS = {
|
||||
open: { text: "开放", class: "status-open" },
|
||||
closed: { text: "关闭", class: "status-closed" },
|
||||
filtered: { text: "被过滤", class: "status-filtered" },
|
||||
unknown: { text: "不确定", class: "status-unknown" },
|
||||
};
|
||||
|
||||
const form = document.getElementById("checkForm");
|
||||
const submitBtn = document.getElementById("submitBtn");
|
||||
const btnText = submitBtn.querySelector(".btn-text");
|
||||
const btnLoading = submitBtn.querySelector(".btn-loading");
|
||||
const errorBox = document.getElementById("errorBox");
|
||||
const resultBox = document.getElementById("resultBox");
|
||||
|
||||
form.addEventListener("submit", async (e) => {
|
||||
e.preventDefault();
|
||||
hideError();
|
||||
resultBox.hidden = true;
|
||||
setLoading(true);
|
||||
|
||||
const host = document.getElementById("host").value.trim();
|
||||
const port = parseInt(document.getElementById("port").value, 10);
|
||||
const protocol = document.getElementById("protocol").value;
|
||||
|
||||
try {
|
||||
const resp = await fetch("/api/check", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ host, port, protocol }),
|
||||
});
|
||||
|
||||
const json = await resp.json();
|
||||
|
||||
if (!resp.ok) {
|
||||
throw new Error(json.detail || json.error || "请求失败");
|
||||
}
|
||||
|
||||
if (!json.success || !json.data) {
|
||||
throw new Error(json.error || "检测失败");
|
||||
}
|
||||
|
||||
renderResult(json.data);
|
||||
} catch (err) {
|
||||
showError(err.message || "网络错误,请稍后重试");
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
});
|
||||
|
||||
function setLoading(loading) {
|
||||
submitBtn.disabled = loading;
|
||||
btnText.hidden = loading;
|
||||
btnLoading.hidden = !loading;
|
||||
}
|
||||
|
||||
function showError(msg) {
|
||||
errorBox.textContent = msg;
|
||||
errorBox.hidden = false;
|
||||
}
|
||||
|
||||
function hideError() {
|
||||
errorBox.hidden = true;
|
||||
}
|
||||
|
||||
function renderResult(data) {
|
||||
const diag = DIAGNOSIS_CONFIG[data.diagnosis] || DIAGNOSIS_CONFIG.udp_ambiguous;
|
||||
const status = STATUS_LABELS[data.port_status] || STATUS_LABELS.unknown;
|
||||
|
||||
const card = document.getElementById("diagnosisCard");
|
||||
card.className = `diagnosis-card ${diag.class}`;
|
||||
document.getElementById("diagnosisIcon").textContent = diag.icon;
|
||||
document.getElementById("diagnosisTitle").textContent = diag.title;
|
||||
document.getElementById("diagnosisMessage").textContent = data.diagnosis_message;
|
||||
|
||||
document.getElementById("elapsed").textContent = `耗时 ${data.elapsed_ms}ms`;
|
||||
document.getElementById("infoTarget").textContent = `${data.host}:${data.port} (${data.protocol.toUpperCase()})`;
|
||||
document.getElementById("infoIp").textContent = data.resolved_ip || "-";
|
||||
document.getElementById("infoStatus").innerHTML =
|
||||
`<span class="${status.class}">${status.text}</span>`;
|
||||
document.getElementById("infoReachable").textContent = data.host_reachable ? "是" : "否";
|
||||
document.getElementById("infoLatency").textContent =
|
||||
data.latency_ms != null ? `${data.latency_ms} ms` : "-";
|
||||
|
||||
const list = document.getElementById("detailsList");
|
||||
list.innerHTML = "";
|
||||
(data.details || []).forEach((d) => {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = d;
|
||||
list.appendChild(li);
|
||||
});
|
||||
|
||||
resultBox.hidden = false;
|
||||
}
|
||||
Reference in New Issue
Block a user