mirror of
https://github.com/Youzini-afk/ST-Bionic-Memory-Ecology.git
synced 2026-05-15 22:30:38 +08:00
fix(panel): memory list layout and formatted metrics
Made-with: Cursor
This commit is contained in:
86
panel.js
86
panel.js
@@ -1069,7 +1069,7 @@ function _refreshMemoryBrowser() {
|
||||
const fragment = document.createDocumentFragment();
|
||||
nodes.slice(0, 100).forEach((node) => {
|
||||
const name = getNodeDisplayName(node);
|
||||
const snippet = _getNodeSnippet(node);
|
||||
const snippetText = _getNodeSnippet(node);
|
||||
const li = document.createElement("li");
|
||||
li.className = "bme-memory-item";
|
||||
li.dataset.nodeId = String(node.id || "");
|
||||
@@ -1077,40 +1077,59 @@ function _refreshMemoryBrowser() {
|
||||
const badge = document.createElement("span");
|
||||
badge.className = `bme-type-badge ${_safeCssToken(node.type)}`;
|
||||
badge.textContent = _typeLabel(node.type);
|
||||
li.appendChild(badge);
|
||||
|
||||
const scopeBadge = document.createElement("span");
|
||||
scopeBadge.className = "bme-type-badge";
|
||||
scopeBadge.textContent = buildScopeBadgeText(node.scope);
|
||||
li.appendChild(scopeBadge);
|
||||
|
||||
const content = document.createElement("div");
|
||||
const title = document.createElement("div");
|
||||
title.className = "bme-memory-name";
|
||||
title.textContent = name;
|
||||
const badgesWrap = document.createElement("div");
|
||||
badgesWrap.className = "bme-memory-badges";
|
||||
badgesWrap.append(badge, scopeBadge);
|
||||
|
||||
const body = document.createElement("div");
|
||||
body.className = "bme-memory-content";
|
||||
body.textContent = snippet;
|
||||
body.className = "bme-memory-body";
|
||||
|
||||
const titleEl = document.createElement("div");
|
||||
titleEl.className = "bme-memory-name";
|
||||
titleEl.textContent = name;
|
||||
|
||||
const snippetEl = document.createElement("div");
|
||||
snippetEl.className = "bme-memory-content";
|
||||
snippetEl.textContent = snippetText;
|
||||
|
||||
const meta = document.createElement("div");
|
||||
meta.className = "bme-memory-meta";
|
||||
["imp", "acc", "seq"].forEach((key, index) => {
|
||||
const span = document.createElement("span");
|
||||
span.textContent =
|
||||
index === 0
|
||||
? `imp: ${node.importance || 5}`
|
||||
: index === 1
|
||||
? `acc: ${node.accessCount || 0}`
|
||||
: `seq: ${node.seqRange?.[1] ?? node.seq ?? 0}`;
|
||||
meta.appendChild(span);
|
||||
});
|
||||
|
||||
const impSpan = document.createElement("span");
|
||||
impSpan.className = "bme-memory-metric";
|
||||
impSpan.textContent = `重要度 ${_formatMemoryMetricNumber(node.importance, {
|
||||
fallback: 5,
|
||||
maxFrac: 2,
|
||||
})}`;
|
||||
|
||||
const accSpan = document.createElement("span");
|
||||
accSpan.className = "bme-memory-metric";
|
||||
accSpan.textContent = `访问 ${_formatMemoryInt(node.accessCount, 0)}`;
|
||||
|
||||
const seqSpan = document.createElement("span");
|
||||
seqSpan.className = "bme-memory-metric";
|
||||
seqSpan.textContent = `序列 ${_formatMemoryInt(
|
||||
node.seqRange?.[1] ?? node.seq,
|
||||
0,
|
||||
)}`;
|
||||
|
||||
meta.append(impSpan, accSpan, seqSpan);
|
||||
|
||||
const regionMeta = _buildScopeMetaText(node);
|
||||
if (regionMeta) {
|
||||
const scopeSpan = document.createElement("span");
|
||||
scopeSpan.className = "bme-memory-regionline";
|
||||
scopeSpan.textContent = regionMeta;
|
||||
meta.appendChild(scopeSpan);
|
||||
}
|
||||
content.append(title, body, meta);
|
||||
li.appendChild(content);
|
||||
|
||||
body.append(titleEl, snippetEl, meta);
|
||||
li.append(badgesWrap, body);
|
||||
fragment.appendChild(li);
|
||||
});
|
||||
listEl.replaceChildren(fragment);
|
||||
@@ -5548,12 +5567,31 @@ function _buildScopeMetaText(node) {
|
||||
parts.push(
|
||||
`${scope.ownerType === "user" ? "用户 POV" : "角色 POV"}: ${scope.ownerName || scope.ownerId || "未命名"}`,
|
||||
);
|
||||
} else {
|
||||
parts.push("客观层");
|
||||
}
|
||||
const regionLine = buildRegionLine(scope);
|
||||
if (regionLine) parts.push(regionLine);
|
||||
return parts.join(" | ");
|
||||
return parts.join(" · ");
|
||||
}
|
||||
|
||||
/** 记忆列表等指标:避免浮点误差打出 9.499999999999998 */
|
||||
function _formatMemoryMetricNumber(value, { fallback = 0, maxFrac = 2 } = {}) {
|
||||
const x =
|
||||
value === undefined || value === null || value === ""
|
||||
? Number(fallback)
|
||||
: Number(value);
|
||||
if (!Number.isFinite(x)) return "—";
|
||||
const rounded = Number.parseFloat(x.toFixed(maxFrac));
|
||||
if (Object.is(rounded, -0)) return "0";
|
||||
return String(rounded);
|
||||
}
|
||||
|
||||
function _formatMemoryInt(value, fallback = 0) {
|
||||
const x =
|
||||
value === undefined || value === null || value === ""
|
||||
? Number(fallback)
|
||||
: Number(value);
|
||||
if (!Number.isFinite(x)) return "—";
|
||||
return String(Math.trunc(x));
|
||||
}
|
||||
|
||||
function _typeLabel(type) {
|
||||
|
||||
72
style.css
72
style.css
@@ -710,6 +710,7 @@
|
||||
/* --- Memory Browser Tab --- */
|
||||
.bme-search-bar {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
@@ -743,6 +744,8 @@
|
||||
font-size: 11px;
|
||||
color: var(--bme-on-surface);
|
||||
outline: none;
|
||||
min-width: 7rem;
|
||||
flex: 1 1 8rem;
|
||||
}
|
||||
|
||||
.bme-memory-list {
|
||||
@@ -751,13 +754,40 @@
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.bme-memory-badges {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
gap: 4px;
|
||||
flex-shrink: 0;
|
||||
max-width: min(11rem, 42%);
|
||||
}
|
||||
|
||||
.bme-memory-badges .bme-type-badge {
|
||||
margin-top: 0;
|
||||
max-width: 100%;
|
||||
white-space: normal;
|
||||
word-break: break-word;
|
||||
line-height: 1.25;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.bme-memory-body {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: stretch;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.bme-memory-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 8px;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 3px;
|
||||
gap: 10px;
|
||||
padding: 10px 8px;
|
||||
border-radius: 6px;
|
||||
margin-bottom: 4px;
|
||||
cursor: pointer;
|
||||
transition: background 0.1s;
|
||||
border: 1px solid transparent;
|
||||
@@ -777,28 +807,50 @@
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
color: var(--bme-on-surface);
|
||||
line-height: 1.35;
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.bme-memory-content {
|
||||
font-size: 11px;
|
||||
color: var(--bme-on-surface-dim);
|
||||
margin-top: 2px;
|
||||
line-height: 1.3;
|
||||
line-height: 1.45;
|
||||
display: -webkit-box;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
-webkit-line-clamp: 3;
|
||||
line-clamp: 3;
|
||||
-webkit-box-orient: vertical;
|
||||
overflow: hidden;
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
.bme-memory-meta {
|
||||
display: flex;
|
||||
gap: 8px;
|
||||
margin-top: 4px;
|
||||
flex-wrap: wrap;
|
||||
align-items: baseline;
|
||||
gap: 6px 10px;
|
||||
margin-top: 2px;
|
||||
font-size: 10px;
|
||||
color: var(--bme-on-surface-dim);
|
||||
}
|
||||
|
||||
.bme-memory-metric {
|
||||
flex: 0 0 auto;
|
||||
white-space: nowrap;
|
||||
font-variant-numeric: tabular-nums;
|
||||
}
|
||||
|
||||
.bme-memory-regionline {
|
||||
flex: 1 1 100%;
|
||||
min-width: 0;
|
||||
white-space: normal;
|
||||
line-height: 1.35;
|
||||
opacity: 0.92;
|
||||
word-break: break-word;
|
||||
overflow-wrap: anywhere;
|
||||
}
|
||||
|
||||
/* --- Injection Preview Tab --- */
|
||||
.bme-injection-preview {
|
||||
font-family: "Cascadia Code", "Fira Code", monospace;
|
||||
|
||||
Reference in New Issue
Block a user