feat: 项目自动选中、重命名接口与长配置值展开;页面显示版本号 v1.0.<commit> build <时间>
build-and-deploy / build-and-deploy (push) Successful in 28s

This commit is contained in:
jif2.zhang
2026-09-14 09:47:59 +08:00
parent 1765caba50
commit 37c781e6b9
14 changed files with 383 additions and 66 deletions
+4
View File
@@ -71,6 +71,10 @@ const API = {
return this.request(`/api/projects/${id}/mappings`, { method: "PUT", body: mappings });
},
updateProject(id, data) {
return this.request(`/api/projects/${id}`, { method: "PUT", body: data });
},
// ========== 配置 ==========
getConfigs(projectId) {
+67 -22
View File
@@ -290,17 +290,48 @@ function renderConfigTable(configs, path) {
* @param {boolean} exists - 是否存在
* @returns {string} 值列 HTML
*/
function buildValueCell(cfg, exists) {
if (!exists) return '<span class="value-missing">—</span>';
const value = String(cfg.value);
if (value.trim() !== "") return escapeHtml(value);
const hasDefault =
cfg.defaultValue !== undefined && cfg.defaultValue !== null && String(cfg.defaultValue).trim() !== "";
if (hasDefault) {
return `<span class="value-default" title="配置值为空,回退展示默认值">默认 ${escapeHtml(String(cfg.defaultValue))}</span>`;
}
return "";
}
function buildValueCell(cfg, exists) {
if (!exists) return '<span class="value-missing">—</span>';
const value = String(cfg.value);
if (value.trim() !== "") {
if (value.length > 40) {
return (
`<span class="value-truncated" data-full="${escapeHtml(value)}">${escapeHtml(value.slice(0, 40))}…</span>` +
`<button type="button" class="value-more-btn" title="显示完整值">更多</button>`
);
}
return escapeHtml(value);
}
const hasDefault =
cfg.defaultValue !== undefined && cfg.defaultValue !== null && String(cfg.defaultValue).trim() !== "";
if (hasDefault) {
return `<span class="value-default" title="配置值为空,回退展示默认值">默认 ${escapeHtml(String(cfg.defaultValue))}</span>`;
}
return "";
}
/**
* 值列"更多"按钮:展开/收起完整值(事件委托,仅在长值单元格内生效)
* @param {Event} e - 点击事件
* @returns {void}
*/
function onValueMoreClick(e) {
const btn = e.target.closest(".value-more-btn");
if (!btn) return;
const span = btn.previousElementSibling;
if (!span || !span.classList.contains("value-truncated")) return;
if (btn.dataset.expanded === "1") {
span.innerHTML = escapeHtml(span.dataset.full.slice(0, 40)) + "…";
btn.textContent = "更多";
btn.dataset.expanded = "";
} else {
span.innerHTML = escapeHtml(span.dataset.full);
btn.textContent = "收起";
btn.dataset.expanded = "1";
}
}
document.addEventListener("click", onValueMoreClick);
/**
* 根据当前项目维度开关,控制配置模态框中维度字段的显示
@@ -849,17 +880,31 @@ function bindResizer() {
* 应用初始化入口
* @returns {Promise<void>}
*/
async function init() {
bindEvents();
try {
const modeData = await API.getMode();
state.mode = modeData.mode;
} catch {
state.mode = "edit";
}
applyMode();
await loadProjects();
setStatus("就绪");
async function init() {
bindEvents();
try {
const modeData = await API.getMode();
state.mode = modeData.mode;
} catch {
state.mode = "edit";
}
applyMode();
await loadProjects();
// 从项目列表跳转进入时,依据 URL 参数或上次选中项自动选中项目
const params = new URLSearchParams(window.location.search);
let projectId = params.get("project");
if (!projectId) {
try { projectId = localStorage.getItem("registry_selected_project"); } catch (e) {}
}
if (projectId && state.projects.some((p) => p.id === projectId)) {
const selector = document.getElementById("project-selector");
if (selector) selector.value = projectId;
try { localStorage.setItem("registry_selected_project", projectId); } catch (e) {}
await selectProject(projectId);
} else {
setStatus("就绪");
}
}
// 页面加载完成后启动
+26
View File
@@ -0,0 +1,26 @@
/**
* 版本号加载器
* 读取 /api/version 并将版本号填充到页面元素的 #version-text(或 .statusbar-version)
*/
(function () {
function fill(text) {
var el = document.getElementById("version-text");
if (!el) el = document.querySelector(".statusbar-version");
if (!el) return;
el.textContent = text;
}
try {
fetch("/api/version")
.then(function (r) {
if (!r.ok) throw new Error("bad status");
return r.json();
})
.then(function (data) {
if (data && data.success && data.data) {
fill(data.data.version || "");
}
})
.catch(function () {});
} catch (e) {}
})();