Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions media/console/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
state.schemas = message.schemas || state.schemas;
renderTasks(message.tasks || []);
Console.refreshDrawer();
Console.renderHealth();
// 多账户存储概要随 tasks 消息一起到达(probe 探测结果);store 数据保持独立状态
Console.renderMultiAccount(message.multiAccount || state.multiAccount, state.accountStore);
break;
Expand All @@ -31,13 +32,15 @@
Console.renderMultiAccount(message.multiAccount || state.multiAccount, state.accountStore);
renderTasks(state.currentTasks);
Console.refreshDrawer();
Console.renderHealth();
break;
case 'taskConfigs':
state.taskConfigs = message.configs || {};
// UI 折叠状态(启动设置区/配置分组/卡片)随任务配置一起下发,重开面板复用
if (message.uiState) state.uiState = message.uiState;
renderTasks(state.currentTasks);
Console.refreshDrawer();
Console.renderHealth();
break;
// 配置接管:全局配置组 + 快照(配置分段数据源)
case 'globalGroups':
Expand All @@ -55,6 +58,7 @@
};
renderTasks(state.currentTasks);
Console.refreshDrawer();
Console.renderHealth();
} else if (message.target === 'global') {
state.globalSnapshots[message.name] = message.values || {};
Console.renderConfig(state.globalGroups, state.globalSnapshots, state.expandedGlobalGroups || []);
Expand Down
223 changes: 223 additions & 0 deletions media/console/console.css
Original file line number Diff line number Diff line change
Expand Up @@ -1098,6 +1098,229 @@ button.secondary:hover:not(:disabled) { background: var(--vscode-button-secondar
.config-section-title--toggle { cursor: pointer; user-select: none; }
.config-section-title__chev { display: inline-block; width: 11px; margin-right: 2px; color: var(--muted); }

/* ═══ 主从双栏 shell(侧栏导航 + 主内容) ═════════════════════ */
.shell { display: flex; gap: 10px; align-items: stretch; }
.lay-side {
position: sticky;
top: 0;
align-self: flex-start;
display: flex;
flex-direction: column;
gap: 2px;
width: 158px;
flex: 0 0 auto;
max-height: 100vh;
padding: 6px 6px 6px 0;
border-right: 1px solid var(--border);
background: var(--vscode-editor-background);
}
.lay-side__item {
position: relative;
display: flex;
align-items: center;
gap: 8px;
padding: 7px 12px;
border-radius: var(--radius-sm);
color: var(--muted);
font-size: 13px;
cursor: pointer;
user-select: none;
}
.lay-side__item:hover { background: var(--surface-hover); color: var(--vscode-editor-foreground); }
.lay-side__item.is-active {
background: var(--surface-hover);
color: var(--vscode-editor-foreground);
box-shadow: inset 2px 0 0 var(--border-strong);
}
.lay-side__ico {
width: 14px; height: 14px;
flex: 0 0 auto;
border-radius: 4px;
background: var(--border-strong);
opacity: .7;
}
.lay-side__item.is-active .lay-side__ico { opacity: 1; }
.lay-side__foot { margin-top: auto; padding: 10px 12px; font-size: 11px; color: var(--muted); }
.lay-main { flex: 1; min-width: 0; }

/* ═══ 配置健康度条(任务分段顶部,真实快照数据) ══════════════ */
.rc-health {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 18px;
margin: 0 0 10px;
padding: 9px 12px;
border: 1px solid var(--border);
border-radius: var(--radius-md);
background: var(--surface);
}
.rc-health__head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 18px; flex: 1; min-width: 0; }
.rc-health__title { font-size: 12px; font-weight: 700; }
.rc-health__cells { display: flex; gap: 8px; flex: 1; min-width: 0; }
.rc-cell { flex: 1; min-width: 96px; padding: 6px 12px; border-radius: var(--radius-sm); background: var(--surface-hover); }
.rc-cell__label { font-size: 10px; color: var(--muted); }
.rc-cell__value { font-size: 16px; font-weight: 700; }
.rc-cell.is-ok .rc-cell__value { color: var(--ok); }
.rc-cell.is-warn .rc-cell__value { color: var(--warn); }

/* ═══ 执行队列条(一次性队列可视化) ══════════════════════════ */
.rc-queue {
display: flex;
flex-wrap: wrap;
align-items: center;
gap: 8px 12px;
margin: 0 0 10px;
padding: 8px 12px;
border: 1px dashed var(--border-strong);
border-radius: var(--radius-md);
background: var(--surface);
}
.rc-queue__head { display: flex; align-items: baseline; gap: 8px; }
.rc-queue__head b { font-size: 12px; }
.rc-queue__chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; flex: 1; min-width: 0; }
.rc-queue__chip {
padding: 3px 10px;
border: 1px solid var(--border);
border-radius: 999px;
background: var(--surface-hover);
font-size: 11px;
}

/* ═══ 运行状态灯(任务卡标题行) ══════════════════════════════ */
.rc-dot {
flex: 0 0 auto;
width: 8px; height: 8px;
border-radius: 50%;
background: color-mix(in srgb, var(--muted) 55%, transparent);
}
.task-card[data-run="running"] .rc-dot,
.task-card[data-run="polling"] .rc-dot {
background: var(--run);
box-shadow: 0 0 0 3px color-mix(in srgb, var(--run) 18%, transparent);
animation: gbar-pulse 1.8s ease-in-out infinite;
}
.task-card[data-run="queued"] .rc-dot,
.task-card[data-run="enqueued"] .rc-dot { background: var(--warn); }
.task-card[data-run="armed"] .rc-dot { background: var(--ok); opacity: .75; }

/* ═══ 任务卡悬停弹出:body 级固定定位(滚动容器裁剪免疫 · 毛玻璃 · 只读) ═══ */
.task-card--pop:hover { border-color: color-mix(in srgb, var(--run) 40%, var(--border-strong)); }

.gpop {
position: fixed;
z-index: 9999;
width: 250px;
max-height: min(58vh, 420px);
overflow-y: auto;
padding: 10px 12px;
border: 1px solid var(--border-strong);
border-radius: 10px;
background: color-mix(in srgb, var(--surface-raised, var(--surface)) 88%, transparent);
backdrop-filter: blur(18px) saturate(1.5);
-webkit-backdrop-filter: blur(18px) saturate(1.5);
box-shadow: 0 14px 38px color-mix(in srgb, #000 40%, transparent);
opacity: 0;
visibility: hidden;
transform: translateY(4px) scale(.98);
pointer-events: none;
transition: opacity .16s ease, transform .16s cubic-bezier(.2,.9,.3,1.2), visibility 0s linear .16s;
}
.gpop.is-visible {
opacity: 1;
visibility: visible;
transform: none;
pointer-events: auto; /* 内容超高时允许内部滚动 */
transition: opacity .16s ease, transform .16s cubic-bezier(.2,.9,.3,1.2), visibility 0s;
}
/* 弹层内部滚动条(内容超高时全量翻阅) */
.gpop::-webkit-scrollbar { width: 8px; }
.gpop::-webkit-scrollbar-thumb {
background: color-mix(in srgb, var(--border-strong) 80%, transparent);
border-radius: 4px;
}
.gpop::-webkit-scrollbar-thumb:hover { background: var(--border-strong); }
.gpop::-webkit-scrollbar-track { background: transparent; }
/* 条件组(field.type.sub_configs 显隐组):与静态组一视同仁,蓝色系区分语义 */
.gpop .grp-tag {
padding: 1px 7px;
border-radius: 999px;
font-size: 10px;
background: color-mix(in srgb, var(--vscode-charts-blue, #3794ff) 16%, transparent);
color: var(--vscode-charts-blue, #3794ff);
}
.gpop .it--rule {
border-left-color: var(--vscode-charts-blue, #3794ff);
background: color-mix(in srgb, var(--vscode-charts-blue, #3794ff) 10%, transparent);
font-weight: 600;
}
/* 条件组内的嵌套子组(条件组套条件组 / 静态组)保持节奏一致的间距 */
.gpop .grp-body .grp { margin: 6px 0 2px; }
@keyframes popfade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }
.gpop .pop-title {
display: flex; align-items: baseline; justify-content: space-between;
margin-bottom: 2px; font-size: 12px; font-weight: 700;
animation: popfade .24s ease both;
}
.gpop .pop-sub { font-size: 10px; font-weight: 400; color: var(--muted); }
.gpop .grp { margin: 8px 0; animation: popfade .24s ease both; }
.gpop .grp-head {
display: flex; align-items: center; justify-content: space-between;
padding: 0 2px 2px;
font-size: 10px; letter-spacing: .08em; color: var(--muted);
}
.gpop .grp-head b { font-size: 12px; font-weight: 600; letter-spacing: 0; color: var(--vscode-editor-foreground); }
.gpop .grp-head .cnt {
padding: 1px 8px; border-radius: 999px;
background: color-mix(in srgb, var(--run) 14%, transparent);
color: var(--run); font-size: 10px;
}
.gpop .grp-body { position: relative; margin: 2px 0 0 8px; padding-left: 12px; }
.gpop .grp-body::before {
content: '';
position: absolute;
top: 2px; bottom: 6px; left: 0;
width: 2px; border-radius: 1px;
background: linear-gradient(180deg, var(--border-strong), transparent);
}
.gpop .it {
position: relative;
display: flex; align-items: center;
margin: 4px 0; padding: 4px 9px;
border-left: 2px solid var(--border-strong);
border-radius: 6px;
background: color-mix(in srgb, var(--surface-hover) 72%, transparent);
font-size: 12px; overflow: hidden;
}
.gpop .it::before {
content: '';
position: absolute;
top: 50%; left: -12px;
width: 10px; height: 1px;
background: var(--border-strong); opacity: .7;
}
.gpop .it > span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* 拍平行(嵌套到 cap 后第 3 层起):字段名 + 条件摘要徽标换行平铺,蓝系对齐条件组语义。
特异性必须压过上方 .gpop .it > span 的 nowrap/ellipsis,否则长徽标被裁成一行 */
.gpop .it--flat { flex-wrap: wrap; row-gap: 1px; }
.gpop .it--flat > .it__cond {
flex: 1 1 100%;
min-width: 0;
display: block;
font-size: 10px;
line-height: 1.4;
max-height: 2.8em; /* 最长两条规则摘要封顶两行 */
color: var(--vscode-charts-blue, #3794ff);
white-space: normal;
word-break: break-all;
overflow: hidden;
}

/* 分段切换内容淡入重放(弹出层规范配套:切 Tab 后 1.2s 抑制弹出 + 内容重放淡入) */
.page.is-entering { animation: pagefade .26s ease both; }
@keyframes pagefade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }



/* hidden 属性兜底:作者样式里的 display(.config-fields 的 grid、卡片 body 的 flex 等)
会覆盖 UA 的 [hidden]{display:none},导致所有基于 hidden 的折叠/显隐在真机上失效
Expand Down
Loading
Loading