Initial release: cloud browser with auth and one-click deploy on port 32450

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dekun
2026-06-27 10:57:37 +08:00
commit 65f5caf4d9
20 changed files with 2118 additions and 0 deletions
+163
View File
@@ -0,0 +1,163 @@
const loginSection = document.getElementById("login-section");
const mainSection = document.getElementById("main-section");
const settingsSection = document.getElementById("settings-section");
const loginForm = document.getElementById("login-form");
const loginError = document.getElementById("login-error");
const welcomeUser = document.getElementById("welcome-user");
const settingsForm = document.getElementById("settings-form");
const settingsError = document.getElementById("settings-error");
const settingsSuccess = document.getElementById("settings-success");
const form = document.getElementById("start-form");
const urlInput = document.getElementById("url-input");
const startBtn = document.getElementById("start-btn");
const errorMsg = document.getElementById("error-msg");
function show(el) {
el.classList.remove("hidden");
}
function hide(el) {
el.classList.add("hidden");
}
function showPanelError(el, message) {
el.textContent = message;
show(el);
}
function hidePanelError(el) {
hide(el);
}
function showMain(username) {
hide(loginSection);
hide(settingsSection);
show(mainSection);
welcomeUser.textContent = `当前用户:${username}`;
document.getElementById("cur-user").value = username;
urlInput.focus();
}
function showLogin() {
hide(mainSection);
hide(settingsSection);
show(loginSection);
}
async function init() {
const user = await AUTH.me();
if (user) {
showMain(user.username);
} else {
showLogin();
}
}
loginForm.addEventListener("submit", async (e) => {
e.preventDefault();
hidePanelError(loginError);
const username = document.getElementById("login-user").value.trim();
const password = document.getElementById("login-pass").value;
try {
const data = await AUTH.login(username, password);
showMain(data.username);
} catch (err) {
showPanelError(loginError, err.message);
}
});
document.getElementById("btn-logout").addEventListener("click", async () => {
await AUTH.logout();
showLogin();
});
document.getElementById("btn-settings").addEventListener("click", () => {
hide(mainSection);
hidePanelError(settingsError);
hide(settingsSuccess);
show(settingsSection);
});
document.getElementById("btn-settings-cancel").addEventListener("click", () => {
const user = welcomeUser.textContent.replace("当前用户:", "");
showMain(user);
});
settingsForm.addEventListener("submit", async (e) => {
e.preventDefault();
hidePanelError(settingsError);
hide(settingsSuccess);
try {
const data = await AUTH.changeCredentials({
current_username: document.getElementById("cur-user").value.trim(),
current_password: document.getElementById("cur-pass").value,
new_username: document.getElementById("new-user").value.trim(),
new_password: document.getElementById("new-pass").value,
});
document.getElementById("cur-pass").value = "";
document.getElementById("new-pass").value = "";
settingsSuccess.textContent = "账号已更新,请使用新凭据登录";
show(settingsSuccess);
setTimeout(async () => {
await AUTH.logout();
showLogin();
}, 1500);
welcomeUser.textContent = `当前用户:${data.username}`;
} catch (err) {
showPanelError(settingsError, err.message);
}
});
function showError(message) {
errorMsg.textContent = message;
show(errorMsg);
}
function hideError() {
hide(errorMsg);
}
form.addEventListener("submit", async (event) => {
event.preventDefault();
hideError();
const url = urlInput.value.trim();
if (!url) {
showError("请输入网址");
return;
}
startBtn.disabled = true;
startBtn.textContent = "启动中...";
try {
const response = await fetch("/api/session", {
method: "POST",
credentials: "include",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ url }),
});
const data = await response.json().catch(() => ({}));
if (response.status === 401) {
showLogin();
showPanelError(loginError, "登录已过期,请重新登录");
return;
}
if (!response.ok) {
showError(data.detail || "创建会话失败");
return;
}
window.location.href = `/view/${data.session_id}`;
} catch (err) {
showError("网络错误,请稍后重试");
} finally {
startBtn.disabled = false;
startBtn.textContent = "进入";
}
});
init();