feat: console spacing/cards polish, create card, drop kids/jump, borderless entry
This commit is contained in:
@@ -372,8 +372,8 @@ async function coldPreviewOf(face: any): Promise<string> {
|
||||
for (const b of blocks) {
|
||||
const s = typeof b?.text === 'string' ? b.text.trim().replace(/\s+/g, ' ') : ''
|
||||
if (!s) continue
|
||||
if (b?.type === 'text') return s.slice(0, 140)
|
||||
if (!fallback) fallback = s.slice(0, 140)
|
||||
if (b?.type === 'text') return s.slice(0, 220)
|
||||
if (!fallback) fallback = s.slice(0, 220)
|
||||
}
|
||||
return fallback
|
||||
}
|
||||
@@ -986,6 +986,16 @@ function WorktableSection(props: any) {
|
||||
return cards
|
||||
}
|
||||
|
||||
/** 打开「添加项目」面板(侧栏 + 与控制室创建卡共用):默认父目录 = 当前会话工作目录 */
|
||||
const openAddPanel = () => {
|
||||
setAddOpen(true)
|
||||
setViewOptionsOpen(false)
|
||||
if (!wsFolderParent) {
|
||||
const cwd = sessionScopeStore.snapshot?.cwd ?? ''
|
||||
if (cwd) setWsFolderParent(cwd)
|
||||
}
|
||||
}
|
||||
|
||||
// 会话作用域(当前会话 + 工作目录)与后台任务:注入分栏引擎环境
|
||||
// 注意:不走 props.useSessions hook(其宿主包装在部分版本会触发 useSyncExternalStore
|
||||
// 崩溃),改为 apply 里订阅 ctx.sessions.list 后写入模块级 store,此处直接读取。
|
||||
@@ -1046,6 +1056,7 @@ function WorktableSection(props: any) {
|
||||
if (previewTimer != null) { window.clearTimeout(previewTimer); previewTimer = null }
|
||||
sweepPreviews()
|
||||
},
|
||||
onAdd: () => openAddPanel(),
|
||||
onOpen: (id) => {
|
||||
if (id === CONSOLE_ID) return
|
||||
const pr = projectsRef.current.projects
|
||||
|
||||
@@ -138,6 +138,7 @@ export const zh = {
|
||||
'console.createBind': '新建并绑定',
|
||||
'console.bindFail': '创建失败,请重试',
|
||||
'console.noSessions': '没有可用对话',
|
||||
'console.addProject': '添加项目',
|
||||
'pane.wip': '开发中(后续版本接入)',
|
||||
'pane.explorerNoCwd': '当前会话没有工作目录',
|
||||
'pane.openLater': '该类型暂不支持预览',
|
||||
@@ -299,6 +300,7 @@ export const en = {
|
||||
'console.createBind': 'Create & bind',
|
||||
'console.bindFail': 'Creation failed, try again',
|
||||
'console.noSessions': 'No sessions available',
|
||||
'console.addProject': 'Add project',
|
||||
'pane.wip': 'Coming in a later version',
|
||||
'pane.explorerNoCwd': 'No working directory for the current session',
|
||||
'pane.openLater': 'Preview not supported for this type',
|
||||
|
||||
@@ -232,6 +232,8 @@ type SplitEnv = {
|
||||
onAck: (id: string) => void
|
||||
/** 冷会话消息预热(打开控制室时拉最近消息) */
|
||||
refreshPreviews: () => void
|
||||
/** 创建卡片:打开「添加项目」流程(同侧栏 +) */
|
||||
onAdd: () => void
|
||||
getTheme: () => 'dark' | 'light' | 'system'
|
||||
setTheme: (th: 'dark' | 'light' | 'system') => void
|
||||
}
|
||||
@@ -1055,27 +1057,27 @@ function ConsolePane() {
|
||||
<span className="dsh-wt_consoleName">{c.name}</span>
|
||||
<span className={'dsh-wt_consoleDot dsh-wt_consoleDot-' + c.status} aria-hidden />
|
||||
</div>
|
||||
<div className="dsh-wt_consoleDivider" aria-hidden />
|
||||
<div className="dsh-wt_consoleStatusRow">
|
||||
<span className={'dsh-wt_consoleStatus dsh-wt_consoleStatus-' + c.status}>{statusLabel[c.status]}</span>
|
||||
{c.runtimeMs != null && <span className="dsh-wt_consoleRuntime">⏱ {fmtDur(c.runtimeMs)}</span>}
|
||||
</div>
|
||||
<div className="dsh-wt_consoleBadges">
|
||||
<span className="dsh-wt_consoleBadge">{T('console.kids')} {c.kids}</span>
|
||||
</div>
|
||||
<div className={'dsh-wt_consolePreview' + (c.preview ? '' : ' dsh-wt_consolePreviewNone')} title={c.preview}>
|
||||
{c.preview || (c.bound ? T('console.noPreview') : T('console.unboundShort'))}
|
||||
</div>
|
||||
{c.bound && !c.self && (
|
||||
<button
|
||||
type="button"
|
||||
className="dsh-wt_consoleJump"
|
||||
title={T('console.jump')}
|
||||
aria-label={T('console.jump')}
|
||||
onClick={(e) => { e.stopPropagation(); env?.onJump(c.id) }}
|
||||
>💬</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{/* 创建卡片:永远最后一位;点击 = 侧栏工作台「添加项目」同款流程 */}
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
className="dsh-wt_consoleCard dsh-wt_consoleAdd"
|
||||
title={T('console.addProject')}
|
||||
onClick={() => env?.onAdd?.()}
|
||||
>
|
||||
<span className="dsh-wt_consoleAddPlus" aria-hidden>+</span>
|
||||
<span className="dsh-wt_consoleAddLabel">{T('console.addProject')}</span>
|
||||
</div>
|
||||
</div>
|
||||
{cards.length === 0 && <div className="dsh-wt_consoleEmpty">{T('console.empty')}</div>}
|
||||
</div>
|
||||
|
||||
@@ -390,26 +390,25 @@ export const css = xtermCss + '\n' + [
|
||||
'.dsh-wt_consoleThemeBtn{flex:none;padding:3px 9px;border:none;border-radius:999px;background:transparent;color:var(--wt-text3);font:inherit;font-size:12px;line-height:18px;cursor:pointer;opacity:.85}',
|
||||
'.dsh-wt_consoleThemeBtn:hover{opacity:1;background:var(--wt-chip)}',
|
||||
'.dsh-wt_consoleThemeBtnOn{background:var(--wt-chip);color:var(--wt-text);opacity:1}',
|
||||
'.dsh-wt_consoleGrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:16px;align-content:start;max-width:720px;margin:0 auto}',
|
||||
'.dsh-wt_consoleCard{position:relative;display:flex;flex-direction:column;gap:10px;aspect-ratio:1/1;min-height:150px;padding:16px;background:var(--wt-card);border:1px solid var(--wt-border);border-radius:14px;cursor:pointer;transition:transform .12s ease,border-color .12s ease,box-shadow .12s ease;overflow:hidden}',
|
||||
'.dsh-wt_consoleGrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:64px;align-content:start;margin-top:clamp(32px,9vh,110px)}',
|
||||
'.dsh-wt_consoleCard{position:relative;display:flex;flex-direction:column;gap:12px;aspect-ratio:1/1;min-height:170px;padding:19px;background:var(--wt-card);border:1px solid var(--wt-border);border-radius:14px;cursor:pointer;transition:transform .12s ease,border-color .12s ease,box-shadow .12s ease;overflow:hidden}',
|
||||
'.dsh-wt_consoleCard:hover{transform:translateY(-2px);border-color:var(--wt-borderHover);box-shadow:var(--wt-shadow)}',
|
||||
'.dsh-wt_consoleCardSelf{cursor:default;opacity:.97}',
|
||||
'.dsh-wt_consoleCardHead{display:flex;align-items:center;gap:9px;min-width:0}',
|
||||
'.dsh-wt_consoleIcon{flex:none;font-size:24px;line-height:1}',
|
||||
'.dsh-wt_consoleName{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14.5px;font-weight:700;line-height:22px;color:var(--wt-text)}',
|
||||
'.dsh-wt_consoleDot{flex:none;width:9px;height:9px;border-radius:50%;background:var(--wt-text3)}',
|
||||
'.dsh-wt_consoleCardHead{display:flex;align-items:center;gap:10px;min-width:0}',
|
||||
'.dsh-wt_consoleIcon{flex:none;font-size:28px;line-height:1}',
|
||||
'.dsh-wt_consoleName{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:17.5px;font-weight:700;line-height:26px;color:var(--wt-text)}',
|
||||
'.dsh-wt_consoleDivider{flex:none;height:1px;background:var(--wt-border)}',
|
||||
'.dsh-wt_consoleDot{flex:none;width:10px;height:10px;border-radius:50%;background:var(--wt-text3)}',
|
||||
'.dsh-wt_consoleDot-busy{background:var(--dsw-alias-state-accent-primary,#4f8ef7);box-shadow:0 0 0 4px rgba(79,142,247,.16)}',
|
||||
'.dsh-wt_consoleDot-need{background:var(--dsw-alias-state-warning,#d29922);box-shadow:0 0 0 4px rgba(210,153,34,.16)}',
|
||||
'.dsh-wt_consoleDot-done{background:var(--dsw-alias-state-success,#3fb950);box-shadow:0 0 0 4px rgba(63,185,80,.16)}',
|
||||
'.dsh-wt_consoleStatusRow{display:flex;align-items:baseline;gap:8px;min-width:0}',
|
||||
'.dsh-wt_consoleStatus{flex:none;font-size:17px;font-weight:700;line-height:24px;color:var(--wt-text2)}',
|
||||
'.dsh-wt_consoleStatusRow{display:flex;align-items:baseline;gap:9px;min-width:0}',
|
||||
'.dsh-wt_consoleStatus{flex:none;font-size:20px;font-weight:700;line-height:28px;color:var(--wt-text2)}',
|
||||
'.dsh-wt_consoleStatus-busy{color:var(--dsw-alias-state-accent-primary,#4f8ef7)}',
|
||||
'.dsh-wt_consoleStatus-need{color:var(--dsw-alias-state-warning,#d29922)}',
|
||||
'.dsh-wt_consoleStatus-done{color:var(--dsw-alias-state-success,#3fb950)}',
|
||||
'.dsh-wt_consoleRuntime{flex:none;font-size:13px;font-weight:600;line-height:20px;color:var(--wt-text2);font-variant-numeric:tabular-nums}',
|
||||
'.dsh-wt_consoleBadges{display:flex;align-items:center;gap:6px;flex-wrap:wrap}',
|
||||
'.dsh-wt_consoleBadge{flex:none;padding:2px 9px;border-radius:999px;font-size:12px;font-weight:600;line-height:18px;color:var(--wt-text2);background:var(--wt-chip)}',
|
||||
'.dsh-wt_consolePreview{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;font-size:12.5px;line-height:18px;color:var(--wt-text2);word-break:break-word}',
|
||||
'.dsh-wt_consoleRuntime{flex:none;font-size:15px;font-weight:600;line-height:24px;color:var(--wt-text2);font-variant-numeric:tabular-nums}',
|
||||
'.dsh-wt_consolePreview{display:-webkit-box;-webkit-line-clamp:4;-webkit-box-orient:vertical;overflow:hidden;font-size:11px;line-height:16px;color:var(--wt-text2);word-break:break-word}',
|
||||
'.dsh-wt_consolePreviewNone{color:var(--wt-text3);font-style:italic;-webkit-line-clamp:1}',
|
||||
// 三色光效:整卡霓虹描边光晕(像侧栏双圆点的发光质感)——完成=绿、待决=黄;工作=蓝色描边顺时针旋转
|
||||
'.dsh-wt_consoleCard-glowDone{border-color:rgba(63,185,80,.9);box-shadow:0 0 8px rgba(63,185,80,.5),0 0 26px rgba(63,185,80,.3),inset 0 0 16px rgba(63,185,80,.07)}',
|
||||
@@ -418,14 +417,18 @@ export const css = xtermCss + '\n' + [
|
||||
'.dsh-wt_consoleCard-busy{box-shadow:0 0 14px rgba(79,142,247,.28)}',
|
||||
'.dsh-wt_consoleCard-busy::before{content:"";position:absolute;inset:-2px;border-radius:16px;padding:2px;background:conic-gradient(from var(--consoleAngle),transparent 0deg,rgba(79,142,247,0) 20deg,#5aa0ff 80deg,rgba(79,142,247,0) 140deg,transparent 200deg);-webkit-mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask:linear-gradient(#000 0 0) content-box,linear-gradient(#000 0 0);mask-composite:exclude;animation:consoleAngleSpin 1.6s linear infinite;pointer-events:none}',
|
||||
'@keyframes consoleAngleSpin{to{--consoleAngle:360deg}}',
|
||||
'.dsh-wt_consoleJump{position:absolute;top:12px;right:12px;width:24px;height:24px;padding:0;border:none;border-radius:7px;background:transparent;color:var(--wt-text3);font-size:13px;line-height:1;cursor:pointer;opacity:0;transition:opacity .12s ease}',
|
||||
'.dsh-wt_consoleCard:hover .dsh-wt_consoleJump{opacity:1}',
|
||||
'.dsh-wt_consoleJump:hover{color:var(--dsw-alias-state-accent-primary,#4f8ef7);background:var(--wt-chip)}',
|
||||
'.dsh-wt_consoleEmpty{padding:40px 0;text-align:center;font-size:12px;color:var(--wt-text3)}',
|
||||
// 控制室入口卡:统筹主程序的差异化(渐变底 + 青色描边 + 微光,克制不喧宾夺主)
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry{background:linear-gradient(135deg,rgba(79,142,247,.14),rgba(139,92,246,.10));border-color:rgba(79,142,247,.4);box-shadow:0 0 12px rgba(79,142,247,.14)}',
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry:hover{background:linear-gradient(135deg,rgba(79,142,247,.2),rgba(139,92,246,.14));border-color:rgba(79,142,247,.6);box-shadow:0 0 16px rgba(79,142,247,.22)}',
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry[data-on=true]{border-color:rgba(79,142,247,.7);box-shadow:0 0 16px rgba(79,142,247,.28)}',
|
||||
// 创建卡片:虚线 + 居中加号,永远最后一位
|
||||
'.dsh-wt_consoleAdd{justify-content:center;align-items:center;gap:8px;background:transparent;border:1.5px dashed var(--wt-borderHover)}',
|
||||
'.dsh-wt_consoleAdd:hover{border-color:var(--dsw-alias-state-accent-primary,#4f8ef7);background:var(--wt-chip)}',
|
||||
'.dsh-wt_consoleAddPlus{font-size:30px;line-height:1;color:var(--wt-text2);font-weight:400}',
|
||||
'.dsh-wt_consoleAdd:hover .dsh-wt_consoleAddPlus{color:var(--dsw-alias-state-accent-primary,#4f8ef7)}',
|
||||
'.dsh-wt_consoleAddLabel{font-size:13px;font-weight:600;color:var(--wt-text2)}',
|
||||
'.dsh-wt_consoleAdd:hover .dsh-wt_consoleAddLabel{color:var(--dsw-alias-state-accent-primary,#4f8ef7)}',
|
||||
// 控制室入口卡:统筹主程序的差异化(渐变底 + 微光;无描边,颜色更亮更饱和)
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry{background:linear-gradient(135deg,rgba(109,164,255,.30),rgba(167,130,255,.22));border-color:transparent;box-shadow:0 0 14px rgba(96,150,255,.22)}',
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry:hover{background:linear-gradient(135deg,rgba(109,164,255,.42),rgba(167,130,255,.32));box-shadow:0 0 18px rgba(96,150,255,.32)}',
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry[data-on=true]{background:linear-gradient(135deg,rgba(109,164,255,.38),rgba(167,130,255,.28));box-shadow:0 0 18px rgba(96,150,255,.34)}',
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry .dsh-wt_layoutIcon{font-size:15px}',
|
||||
'.dsh-wt_projects .dsh-wt_consoleEntry .dsh-wt_layoutName{font-weight:600;color:var(--dsw-alias-label-primary,#e6e8eb)}',
|
||||
// 控制室强制绑定弹窗:左加入现有 / 右新建对话
|
||||
|
||||
@@ -1231,3 +1231,21 @@
|
||||
- 验证:probe-batch16 healTabs=1、healType='console' ✓,全流程 ✓;functional-diag
|
||||
全 20 STEP ERROR_COUNT: 0。
|
||||
- 备注:纯客户端改动,F5 即生效;用户 F5 后坏存档自动修复,点「控制室」卡片即恢复面板。
|
||||
|
||||
## 补记(控制室第三轮打磨:下沉居中 + 4 倍间距 + 1.2 倍卡片 + 创建卡 + 去子代理/💬 + 入口无描边)
|
||||
|
||||
- 用户反馈:① 卡片太靠上 → 网格下沉(margin-top clamp(32px,9vh,110px),接近画面中部);
|
||||
② 卡间距太小 → gap 16→64px(4 倍);③ 卡片整体放大 1.2 倍(padding 19/图标 28/
|
||||
名字 17.5/状态 20/时长 15);④ 删掉右上角隐藏的 💬 跳转按钮(无意义);⑤ 网格最后
|
||||
一位永远是一张「创建卡片」(虚线 + 居中加号),点击 = 侧栏工作台「添加项目」同款流程
|
||||
(openAddPanel 共用:setAddOpen + 默认父目录取当前会话 cwd);⑥ 侧栏控制室入口卡去掉
|
||||
描边(border transparent),渐变颜色提亮提饱和(rgba(109,164,255,.30)→
|
||||
rgba(167,130,255,.22)),保留微光;⑦ 子代理徽章全删(都是 0 无信息);⑧ 卡片名字下方
|
||||
加横向分隔线(标题/状态/预览层次分明);⑨ 预览字改小(11px)行数提到 4 行,抓取切
|
||||
220 字符;⑩ 名字字号变大且**所有卡片共用类名**——以后新建的项目卡片自动同字号。
|
||||
- 验证(probe-batch16 更新):gridGap 64px / gridMarginTop 72px ✓、nameFont 17.5px /
|
||||
previewFont 11px / statusFont 20px ✓、dividerExists ✓、kidsGone/jumpGone ✓、
|
||||
addCardLast(+)且点击开添加面板(addPopOpened)✓、入口 border rgba(0,0,0,0) +
|
||||
渐变 ✓、真实运行会话 busy 旋转光弧动效生效 ✓;全流程 + 主题 ✓;functional-diag
|
||||
全 20 STEP ERROR_COUNT: 0。
|
||||
- 备注:纯客户端改动,F5 即生效。
|
||||
|
||||
@@ -135,16 +135,31 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
out.gridFound = !!grid;
|
||||
if (grid) {
|
||||
out.gridCols = getComputedStyle(grid).gridTemplateColumns.split(' ').length;
|
||||
out.gridGap = getComputedStyle(grid).columnGap;
|
||||
out.gridMarginTop = getComputedStyle(grid).marginTop;
|
||||
var cards = grid.querySelectorAll('.dsh-wt_consoleCard');
|
||||
out.cardCount = cards.length;
|
||||
var c0 = cards[0];
|
||||
out.firstCardSelf = !!(c0 && c0.classList.contains('dsh-wt_consoleCardSelf'));
|
||||
out.firstCardIcon = c0 ? c0.querySelector('.dsh-wt_consoleIcon').textContent : null;
|
||||
out.firstCardDot = c0 && c0.querySelector('.dsh-wt_consoleDot') ? c0.querySelector('.dsh-wt_consoleDot').className.replace('dsh-wt_consoleDot','').trim() : null;
|
||||
out.firstCardBadges = c0 ? c0.querySelectorAll('.dsh-wt_consoleBadge').length : 0;
|
||||
out.nameFont = c0 && c0.querySelector('.dsh-wt_consoleName') ? getComputedStyle(c0.querySelector('.dsh-wt_consoleName')).fontSize : null;
|
||||
out.dividerExists = !!(c0 && c0.querySelector('.dsh-wt_consoleDivider'));
|
||||
out.kidsGone = !(c0 && c0.querySelector('.dsh-wt_consoleBadge'));
|
||||
out.jumpGone = !(c0 && c0.querySelector('.dsh-wt_consoleJump'));
|
||||
out.previewFont = c0 && c0.querySelector('.dsh-wt_consolePreview') ? getComputedStyle(c0.querySelector('.dsh-wt_consolePreview')).fontSize : null;
|
||||
out.firstCardHasPreview = !!(c0 && c0.querySelector('.dsh-wt_consolePreview'));
|
||||
out.anyLayoutCard = [].slice.call(cards).some(function(c){ return (c.textContent||'').indexOf('绑定测试') >= 0; });
|
||||
out.layoutCardHasJump = [].slice.call(cards).some(function(c){ return (c.textContent||'').indexOf('绑定测试') >= 0 && !!c.querySelector('.dsh-wt_consoleJump'); });
|
||||
// 创建卡片永远最后一位;点击打开「添加项目」面板
|
||||
var addCard = grid.lastElementChild;
|
||||
out.addCardLast = !!(addCard && addCard.classList.contains('dsh-wt_consoleAdd'));
|
||||
out.addPlus = addCard && addCard.querySelector('.dsh-wt_consoleAddPlus') ? addCard.querySelector('.dsh-wt_consoleAddPlus').textContent : null;
|
||||
if (addCard) { addCard.dispatchEvent(new MouseEvent('click', {bubbles:true, cancelable:true})); }
|
||||
await sleep(500);
|
||||
out.addPopOpened = !!vis('.dsh-wt_add');
|
||||
var bd = vis('.dsh-wt_popBackdrop');
|
||||
if (bd) { bd.dispatchEvent(new MouseEvent('click', {bubbles:true, cancelable:true})); }
|
||||
await sleep(300);
|
||||
// 新版 UI:正方形比例、大字号状态、光效 CSS 接线(注入类验证,不依赖真实会话状态)
|
||||
var cardEl = c0;
|
||||
if (cardEl) {
|
||||
@@ -226,13 +241,8 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
out.bindPopNotShown = !vis('.dsh-wt_consoleBindPop');
|
||||
var grid = vis('.dsh-wt_consoleGrid');
|
||||
var lc = grid && [].slice.call(grid.querySelectorAll('.dsh-wt_consoleCard')).find(function(c){ return (c.textContent||'').indexOf('绑定测试') >= 0; });
|
||||
out.layoutJumpBtn = !!(lc && lc.querySelector('.dsh-wt_consoleJump'));
|
||||
out.jumpBtnGone = !(lc && lc.querySelector('.dsh-wt_consoleJump'));
|
||||
out.layoutCardStatus = lc && lc.querySelector('.dsh-wt_consoleDot') ? lc.querySelector('.dsh-wt_consoleDot').className.replace('dsh-wt_consoleDot','').trim() : null;
|
||||
if (lc && lc.querySelector('.dsh-wt_consoleJump')) {
|
||||
lc.querySelector('.dsh-wt_consoleJump').dispatchEvent(new MouseEvent('click', {bubbles:true, cancelable:true}));
|
||||
await sleep(700);
|
||||
out.specAfterJump = st.active && st.spec ? st.spec.id : null;
|
||||
}
|
||||
st.close(); await sleep(300);
|
||||
} catch (e) { out.err = String(e && e.stack || e); }
|
||||
return out;
|
||||
|
||||
@@ -84,12 +84,11 @@ node --check lib/index.js
|
||||
建空会话 sessions.create 后自动绑定并打开控制室)。绑定也走 projects.v1.bindings。
|
||||
- 控制室面板(split.tsx ConsolePane):卡片网格每行 3 张、超出换行;每卡 = 图标/名称/
|
||||
三态圆点(need>done>busy>idle,不过滤 ack,永远显示事实状态)/运行时长(后台任务
|
||||
JobView.startedAt 或会话面 turnTimings 未结束轮次)/子代理数(byId.parentId +
|
||||
subagentsByParent 双通道计数)/最近消息预览(会话面快照 nodes 末条文本,纯读内存
|
||||
零 Token)。数据组装 = index.tsx getConsoleCards(env.console 注入),刷新走
|
||||
consoleListeners(项目/会话快照变化推送)+ 面板每秒 tick。
|
||||
- 卡片动作:点卡片 = 打开该项目(openSplit 或入驻项目切绑定对话);💬 = 跳绑定对话
|
||||
(markPluginSessionOpen 豁免联动,控制室保持打开);工作台自己的卡片点击无操作。
|
||||
JobView.startedAt 或会话面 turnTimings 未结束轮次)/最近消息预览(会话面快照 nodes
|
||||
末条文本,纯读内存零 Token)。数据组装 = index.tsx getConsoleCards(env.console 注入),
|
||||
刷新走 consoleListeners(项目/会话快照变化推送)+ 面板每秒 tick。
|
||||
- 卡片动作:点卡片 = 打开该项目(openSplit 或入驻项目切绑定对话);工作台自己的卡片
|
||||
点击无操作。💬 跳转按钮已删除(用户定案无意义)。
|
||||
- 主题:面板三选一开关(图标按钮 🌙/☀️/🖥️,title/aria 保留文字;存 view.v1 consoleTheme);
|
||||
system 读宿主 html 的 color-scheme(DSH 深色/白色/跟随系统设置都会反映到它)+
|
||||
prefers-color-scheme 兜底;落成 .dsh-wt_console[data-wt-theme=dark|light] 作用域变量
|
||||
@@ -104,8 +103,10 @@ node --check lib/index.js
|
||||
「控制室」(console.name/console.title locale,工作台的控制室)。
|
||||
- 控制室标签不可关:PaneBody 对 content.type==='console' 的标签 locked(不渲染 ✕、
|
||||
禁拖拽)——关掉会退化成窗格选择器,不可逆。
|
||||
- 布局尺度:网格 max-width 720px 居中、gap 16px、面板 padding 22px;卡片 1:1(实测
|
||||
~229px 宽),保持留白。
|
||||
- 布局尺度:网格 gap 64px(4 倍间距)、margin-top clamp(32px,9vh,110px) 下沉居中;
|
||||
卡片 1:1 整体 1.2 倍(名字 17.5px/状态 20px/预览 11px 四行截断);标题下横向分隔线;
|
||||
无子代理徽章、无 💬 跳转按钮(已删);网格最后一位恒为「创建卡片」(虚线+),点击 =
|
||||
侧栏「添加项目」同款 openAddPanel 流程;入口卡无描边(透明 border + 提亮渐变 + 微光)。
|
||||
- 冷会话消息预览(方案 A):binding() 对冷会话不载入文本;预热走 face.history({maxMessages:2})
|
||||
(运行期内建方法、非公开接口,只读无副作用)尾部扫 user/message 与 assistant/message 的
|
||||
text 块 → previewCache;sweepPreviews 在打开控制室时 + 控制室开着且会话快照变化防抖 6s
|
||||
|
||||
Reference in New Issue
Block a user