GitHub 仓库选择菜单:安装仓库列表 + PATCH 补仓库 + 控制台下拉

This commit is contained in:
host committed 2026-10-27 05:43:56 +08:00
1 parent 5ba4d35839
commit 6ba671e051
4 files changed
+343

No files matched your search

+58
View File
@@ -107,6 +107,7 @@
</div>
<div class="bar">
<input id="newProjectName" type="text" placeholder="新项目名">
<select id="newProjectRepoSelect"><option value="">(从 GitHub App 安装仓库里选,或手动输入)</option></select>
<input id="newProjectRepo" type="text" placeholder="repo_url(可选)">
<button id="createProject">新建项目</button>
</div>
@@ -136,6 +137,12 @@
</select>
<button id="createEnvironment">新建环境</button>
</div>
<div class="bar"><span id="envRepoLine" class="muted"></span></div>
<div class="bar" id="envRepoBar" style="display:none">
<select id="envRepoSelect"><option value="">(从 GitHub App 安装仓库里选)</option></select>
<button id="saveEnvRepo">保存仓库</button>
</div>
<span id="envRepoMsg" class="muted"></span>
<span id="envMsg" class="muted"></span>
</section>
@@ -343,9 +350,29 @@ async function loadQuota() {
} catch (e) { el.textContent = "配额加载失败:" + e.message; }
}
var projectsCache = [];
var githubReposCache = [];
async function loadGithubRepos() {
try {
var d = await api("/github/repos", "GET");
githubReposCache = d.repos || [];
var opts = "<option value=''>(从 GitHub App 安装仓库里选,或手动输入)</option>" +
githubReposCache.map(function (r) {
return "<option value='" + esc(r.clone_url) + "'>" + esc(r.repo_full_name) + "</option>";
}).join("");
var s1 = $("#newProjectRepoSelect"); if (s1) s1.innerHTML = opts;
var s2 = $("#envRepoSelect");
if (s2) s2.innerHTML = "<option value=''>(从 GitHub App 安装仓库里选)</option>" +
githubReposCache.map(function (r) {
return "<option value='" + esc(r.clone_url) + "'>" + esc(r.repo_full_name) + "</option>";
}).join("");
} catch (e) { /* 未登录或无安装记录时只留手动输入,不报错 */ }
}
async function loadProjects() {
try {
var d = await api("/projects", "GET");
projectsCache = d.projects || [];
var sel = $("#projectSelect");
var cur = sel.value;
sel.innerHTML = "";
@@ -412,6 +439,20 @@ async function loadEnvironments() {
sel.appendChild(o);
});
if (cur && Array.prototype.some.call(sel.options, function (o) { return o.value === cur && !o.disabled; })) sel.value = cur;
// 项目仓库行:有仓库就显示;没仓库就亮出补仓库的下拉(截图里
// 那个 400 的死结就卡在这里——不先补仓库,环境永远建不出来)。
var proj = null;
for (var i = 0; i < projectsCache.length; i++) { if (projectsCache[i].id === pid) { proj = projectsCache[i]; break; } }
if (proj && proj.repo_url) {
$("#envRepoLine").textContent = "仓库:" + proj.repo_url;
$("#envRepoBar").style.display = "none";
} else if (proj) {
$("#envRepoLine").textContent = "该项目未绑定仓库,环境无法创建——先选一个仓库保存";
$("#envRepoBar").style.display = "";
} else {
$("#envRepoLine").textContent = "";
$("#envRepoBar").style.display = "none";
}
} catch (e) {
$("#envList").innerHTML = "<span class='err'>加载失败:" + esc(e.message) + "</span>";
}
@@ -630,6 +671,7 @@ $("#saveKey").onclick = function () {
if ($("#projectSelect").value) { loadTasks(); loadEnvironments(); }
if (getKey()) loadRelayModels();
loadQuota();
loadGithubRepos();
};
$("#clearKey").onclick = function () { localStorage.removeItem(KEY_STORE); setKeyState(); };
$("#refreshHealth").onclick = loadHealth;
@@ -669,6 +711,21 @@ $("#createEnvironment").onclick = async function () {
loadEnvironments();
} catch (e) { $("#envMsg").innerHTML = "<span class='err'>新建失败:" + esc(e.message) + "</span>"; }
};
$("#newProjectRepoSelect").onchange = function () {
var v = this.value;
if (v) $("#newProjectRepo").value = v;
};
$("#saveEnvRepo").onclick = async function () {
var pid = $("#projectSelect").value;
var repo = $("#envRepoSelect").value;
if (!pid) { $("#envRepoMsg").textContent = "先选项目"; return; }
if (!repo) { $("#envRepoMsg").textContent = "先选一个仓库"; return; }
try {
await api("/projects/" + encodeURIComponent(pid), "PATCH", { repo_url: repo });
$("#envRepoMsg").innerHTML = "<span class='ok'>仓库已保存,现在可以建环境了</span>";
loadProjects(); loadEnvironments();
} catch (e) { $("#envRepoMsg").innerHTML = "<span class='err'>保存失败:" + esc(e.message) + "</span>"; }
};
function gatherAttachments() {
// 三路输入合并成 [{path, file}]:文件路用文件名,文件夹路用
// webkitRelativePath(含子目录),图片路用文件名;同路径只留
@@ -810,6 +867,7 @@ loadHealth();
loadProjects();
loadWorkers();
loadQuota();
loadGithubRepos();
// 回访用户 key 已在 localStorage 里:初始化也要加载模型列表,
// 否则下拉永远只有默认项(此前只在点“保存”时调一次,
// 2026-10-27 实测:存过 key 后重开页面模型选不了)。