fix: console cards 80%, single title, stronger busy glow, thinner dividers
This commit is contained in:
@@ -118,7 +118,7 @@ type SplitState = {
|
||||
}
|
||||
|
||||
const clamp = (v: number, lo: number, hi: number) => Math.min(Math.max(v, lo), hi)
|
||||
const DIVIDER = 6
|
||||
const DIVIDER = 4
|
||||
const BAR_H = 26
|
||||
const PERSIST_KEY = 'dsh.worktable.split.v2'
|
||||
|
||||
@@ -1021,7 +1021,6 @@ function ConsolePane() {
|
||||
return (
|
||||
<div className="dsh-wt_console" data-wt-theme={resolvedTheme}>
|
||||
<div className="dsh-wt_consoleHead">
|
||||
<span className="dsh-wt_consoleTitle">🖥️ {T('console.title')}</span>
|
||||
<div className="dsh-wt_consoleTheme" role="group" aria-label={T('console.themeLabel')}>
|
||||
{themeOpts.map((o) => (
|
||||
<button
|
||||
@@ -1741,8 +1740,11 @@ function PaneBody(props: { pane: SplitPane; row: PaneRow; index: number }) {
|
||||
setReloadKeys((m) => ({ ...m, [t.id]: (m[t.id] ?? 0) + 1 }))
|
||||
splitStore.setActiveTab(row, index, t.id)
|
||||
}
|
||||
// 唯一标签是控制室 → 整个标签栏不渲染(不可关、不可换,标签栏无信息价值;去掉顶部多余标题)
|
||||
const singleConsole = tabs.length === 1 && tabs[0].content?.kind === 'builtin' && tabs[0].content.type === 'console'
|
||||
return (
|
||||
<>
|
||||
{!singleConsole && (
|
||||
<div className="dsh-wt_tabBar">
|
||||
{tabs.map((t, i) => {
|
||||
// 控制室标签不可关闭:关掉后窗格变选择器,用户回不到控制室(不可逆操作)
|
||||
@@ -1779,6 +1781,7 @@ function PaneBody(props: { pane: SplitPane; row: PaneRow; index: number }) {
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
<PaneTabBody tab={tabs[active]} row={row} index={index} paneTitle={pane.title} reloadKey={reloadKeys[tabs[active].id] ?? 0} />
|
||||
</>
|
||||
)
|
||||
@@ -1909,7 +1912,7 @@ function WorkspaceLayer(props: { spec: LayoutSpec; geom: Geom | null; chatW: num
|
||||
<>
|
||||
{/* 标题栏 */}
|
||||
<div className="dsh-wt_splitBar" style={{ position: 'fixed', left: g.left, top: barTop, width: hasLeft || chatFull ? contentW : (hasTop ? colW : contentW), zIndex: 70 }}>
|
||||
<span className="dsh-wt_splitTitle">{spec.title}</span>
|
||||
{spec.id !== 'wt-console' && <span className="dsh-wt_splitTitle">{spec.title}</span>}
|
||||
{!hasLeft && (
|
||||
<button
|
||||
type="button"
|
||||
|
||||
@@ -384,44 +384,44 @@ export const css = xtermCss + '\n' + [
|
||||
// 主题变量自带作用域:dark 缺省;data-wt-theme=light 换浅色;system 由面板读宿主 color-scheme 落成 dark/light。
|
||||
'.dsh-wt_console{--wt-bg:#10141b;--wt-card:#171c25;--wt-cardHover:#1d232e;--wt-border:#2a3140;--wt-borderHover:#39445a;--wt-text:#e6e8eb;--wt-text2:#9aa4b2;--wt-text3:#6e7683;--wt-chip:rgba(255,255,255,.06);--wt-shadow:0 6px 20px rgba(0,0,0,.35);flex:1;min-height:0;overflow:auto;padding:22px;background:var(--wt-bg)}',
|
||||
'.dsh-wt_console[data-wt-theme=light]{--wt-bg:#f2f4f7;--wt-card:#ffffff;--wt-cardHover:#f7f9fb;--wt-border:#d8dee6;--wt-borderHover:#b9c4d2;--wt-text:#1c2128;--wt-text2:#57606a;--wt-text3:#8b949e;--wt-chip:rgba(27,31,36,.07);--wt-shadow:0 6px 20px rgba(31,41,55,.10)}',
|
||||
'.dsh-wt_consoleHead{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:12px}',
|
||||
'.dsh-wt_consoleHead{display:flex;align-items:center;justify-content:flex-end;gap:10px;margin-bottom:12px}',
|
||||
'.dsh-wt_consoleTitle{font-size:14px;font-weight:700;line-height:20px;color:var(--wt-text)}',
|
||||
'.dsh-wt_consoleTheme{display:inline-flex;align-items:center;padding:2px;border:1px solid var(--wt-border);border-radius:999px;background:var(--wt-card)}',
|
||||
'.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: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_consoleGrid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:64px;align-content:start;margin-top:clamp(32px,9vh,110px);max-width:640px;margin-left:auto;margin-right:auto}',
|
||||
'.dsh-wt_consoleCard{position:relative;display:flex;flex-direction:column;gap:10px;aspect-ratio:1/1;min-height:136px;padding:15px;background:var(--wt-card);border:1px solid var(--wt-border);border-radius:12px;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: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_consoleIcon{flex:none;font-size:22px;line-height:1}',
|
||||
'.dsh-wt_consoleName{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:14px;font-weight:700;line-height:21px;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{flex:none;width:8px;height:8px;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:9px;min-width:0}',
|
||||
'.dsh-wt_consoleStatus{flex:none;font-size:20px;font-weight:700;line-height:28px;color:var(--wt-text2)}',
|
||||
'.dsh-wt_consoleStatusRow{display:flex;align-items:baseline;gap:7px;min-width:0}',
|
||||
'.dsh-wt_consoleStatus{flex:none;font-size:16px;font-weight:700;line-height:22px;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: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_consoleRuntime{flex:none;font-size:12px;font-weight:600;line-height:19px;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:10px;line-height:14px;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)}',
|
||||
'.dsh-wt_consoleCard-glowNeed{border-color:rgba(210,153,34,.95);box-shadow:0 0 8px rgba(210,153,34,.5),0 0 26px rgba(210,153,34,.3),inset 0 0 16px rgba(210,153,34,.08)}',
|
||||
'@property --consoleAngle{syntax:"<angle>";initial-value:0deg;inherits:false}',
|
||||
'.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}',
|
||||
'.dsh-wt_consoleCard-busy{box-shadow:0 0 10px rgba(94,160,255,.55),0 0 34px rgba(79,142,247,.4)}',
|
||||
'.dsh-wt_consoleCard-busy::before{content:"";position:absolute;inset:-3px;border-radius:14px;padding:3px;background:conic-gradient(from var(--consoleAngle),transparent 0deg,rgba(94,160,255,0) 15deg,#8fc0ff 85deg,rgba(94,160,255,0) 155deg,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.4s linear infinite;pointer-events:none}',
|
||||
'@keyframes consoleAngleSpin{to{--consoleAngle:360deg}}',
|
||||
'.dsh-wt_consoleEmpty{padding:40px 0;text-align:center;font-size:12px;color:var(--wt-text3)}',
|
||||
// 创建卡片:虚线 + 居中加号,永远最后一位
|
||||
'.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_consoleAddPlus{font-size:24px;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)}',
|
||||
|
||||
@@ -1249,3 +1249,21 @@
|
||||
渐变 ✓、真实运行会话 busy 旋转光弧动效生效 ✓;全流程 + 主题 ✓;functional-diag
|
||||
全 20 STEP ERROR_COUNT: 0。
|
||||
- 备注:纯客户端改动,F5 即生效。
|
||||
|
||||
## 补记(控制室第四轮:卡片 80% + 顶部只留一个「控制室」+ 工作光效增强 + 分隔线变细)
|
||||
|
||||
- 用户反馈:① 卡片再缩到 80%(间距不变,两侧向中间收);② 顶部出现四个「控制室」
|
||||
(分栏标题栏 / 标签栏 / 面板内标题 / 侧栏入口卡)——尽量去掉只留一个;③ 「工作中」
|
||||
旋转光效几乎看不到,要外层描边、更明显;④ 分栏可拖分隔线太粗(DIVIDER 6→4)。
|
||||
- 实现:① 网格 max-width 640px + 左右 auto(间距 64px 不变,卡片 171px≈80%),卡片
|
||||
内部同步 0.8(min-height 136/padding 15/图标 22/名字 14/状态 16/时长 12/预览 10);
|
||||
② 顶部三处标题全去:分栏标题栏对 wt-console 不渲染 title(保留 ⇄/✕)、PaneBody
|
||||
singleConsole(唯一标签是 console)整个标签栏不渲染、ConsolePane 头去掉标题只留
|
||||
主题开关(右对齐)——现在全页只剩侧栏入口卡一个「控制室」;③ busy 光效增强:描边
|
||||
环加厚(inset -3/padding 3)、峰值 #8fc0ff、光弧 140°、外发光双层 10px+34px 高亮;
|
||||
④ DIVIDER 常量 6→4(split 分隔线/抓取条变细)。
|
||||
- 验证(probe-batch16 更新):consoleTabBarGone/splitTitleGone/paneTitleGone ✓、
|
||||
cardWidth 171 / nameFont 14 / statusFont 16 / previewFont 10 ✓、gridGap 64px 不变 ✓、
|
||||
busyShadow 双层外发光(10px .55 + 34px .4)+ 新配色 ✓、dividerH=4 ✓;全流程 + 主题 +
|
||||
自愈 ✓;functional-diag 全 20 STEP ERROR_COUNT: 0。
|
||||
- 备注:纯客户端改动,F5 即生效。
|
||||
|
||||
@@ -121,12 +121,10 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
}
|
||||
out.bindPopClosed = !vis('.dsh-wt_consoleBindPop');
|
||||
out.specId = st.active && st.spec ? st.spec.id : null;
|
||||
// 控制室标签关不掉:标签栏存在但该标签无 ✕
|
||||
var tabBar = vis('.dsh-wt_tabBar');
|
||||
var ctab = tabBar && tabBar.querySelector('.dsh-wt_tab');
|
||||
out.consoleTabExists = !!ctab;
|
||||
out.consoleTabCloseGone = !!(ctab && !ctab.querySelector('.dsh-wt_tabClose'));
|
||||
out.consoleTabTitle = ctab ? (ctab.textContent || '').trim() : null;
|
||||
// 顶部只留一个「控制室」(侧栏入口卡):分栏标题栏 / 标签栏 / 面板内标题全部不再显示
|
||||
out.consoleTabBarGone = !vis('.dsh-wt_tabBar');
|
||||
out.splitTitleGone = !document.querySelector('.dsh-wt_splitTitle');
|
||||
out.paneTitleGone = !vis('.dsh-wt_consoleTitle');
|
||||
out.mainType = st.spec && st.spec.main[0] && st.spec.main[0].tabs && st.spec.main[0].tabs[0] ? st.spec.main[0].tabs[0].content.type : null;
|
||||
var saved = JSON.parse(localStorage.getItem('dsh.worktable.projects.v1'));
|
||||
out.savedConsoleBinding = saved.bindings['wt-console'];
|
||||
@@ -169,9 +167,11 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
var statusEl = cardEl.querySelector('.dsh-wt_consoleStatus');
|
||||
out.statusFont = statusEl ? getComputedStyle(statusEl).fontSize : null;
|
||||
cardEl.classList.add('dsh-wt_consoleCard-busy');
|
||||
await sleep(300);
|
||||
var bs = getComputedStyle(cardEl, '::before');
|
||||
out.busyBgImage = bs.backgroundImage ? bs.backgroundImage.slice(0, 60) : null;
|
||||
out.busyAnim = bs.animationName;
|
||||
out.busyShadow = getComputedStyle(cardEl).boxShadow.slice(0, 90);
|
||||
cardEl.classList.remove('dsh-wt_consoleCard-busy');
|
||||
cardEl.classList.add('dsh-wt_consoleCard-glowDone');
|
||||
await sleep(300);
|
||||
@@ -215,6 +215,12 @@ const sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
||||
var vis = function(sel){ return [].slice.call(document.querySelectorAll(sel)).find(function(el){ return (getComputedStyle(el).visibility!=='hidden'&&el.getBoundingClientRect().height>0); }); };
|
||||
var st = window.__dshWorktable.splitStore;
|
||||
try {
|
||||
// 分隔线粗细:开一个带顶行的临时布局量高度(DIVIDER 6→4)
|
||||
st.open({id:'t-div',title:'d',top:[{id:'tp',title:'t',min:60,content:{kind:'builtin',type:'browser'}}],main:[{id:'mp',title:'m',min:60,content:null}],chatWidth:{default:320,min:240,max:600}});
|
||||
await sleep(500);
|
||||
var dv = vis('.dsh-wt_splitDividerH');
|
||||
out.dividerH = dv ? Math.round(dv.getBoundingClientRect().height) : null;
|
||||
st.close(); await sleep(300);
|
||||
var tcard = [].slice.call(document.querySelectorAll('.dsh-wt_projects .dsh-wt_layout')).find(function(b){ return (b.textContent||'').indexOf('绑定测试') >= 0; });
|
||||
out.tCardFound = !!tcard;
|
||||
var bb = tcard && tcard.querySelector('.dsh-wt_bindBtn');
|
||||
|
||||
@@ -96,17 +96,20 @@ node --check lib/index.js
|
||||
不受其影响)。
|
||||
- 状态光效(整卡霓虹描边,参考侧栏双圆点发光质感):工作=蓝色描边光晕顺时针绕卡旋转
|
||||
(.dsh-wt_consoleCard-busy ::before conic-gradient + @property --consoleAngle +
|
||||
consoleAngleSpin,峰值 #5aa0ff);完成=绿光、待决=黄光(-glowDone/-glowNeed:亮色描边
|
||||
+ 双层外发光 + 微弱内辉光;glow 字段 = done/need 且本轮未 ack,点卡片先 onAck 熄光
|
||||
再进入,与提醒 ack 生命周期一致)。
|
||||
consoleAngleSpin;环 inset -3/padding 3、峰值 #8fc0ff、外发光双层 10px+34px);完成=绿光、
|
||||
待决=黄光(-glowDone/-glowNeed:亮色描边 + 双层外发光 + 微弱内辉光;glow 字段 = done/need
|
||||
且本轮未 ack,点卡片先 onAck 熄光再进入,与提醒 ack 生命周期一致)。
|
||||
- 命名:侧栏区块标题 = 「工作台」(title locale,整个插件);默认项目卡名与面板标题 =
|
||||
「控制室」(console.name/console.title locale,工作台的控制室)。
|
||||
- 控制室标签不可关:PaneBody 对 content.type==='console' 的标签 locked(不渲染 ✕、
|
||||
禁拖拽)——关掉会退化成窗格选择器,不可逆。
|
||||
- 布局尺度:网格 gap 64px(4 倍间距)、margin-top clamp(32px,9vh,110px) 下沉居中;
|
||||
卡片 1:1 整体 1.2 倍(名字 17.5px/状态 20px/预览 11px 四行截断);标题下横向分隔线;
|
||||
无子代理徽章、无 💬 跳转按钮(已删);网格最后一位恒为「创建卡片」(虚线+),点击 =
|
||||
侧栏「添加项目」同款 openAddPanel 流程;入口卡无描边(透明 border + 提亮渐变 + 微光)。
|
||||
- 布局尺度:网格 gap 64px(4 倍间距)不变、max-width 640px 左右居中(卡片 80%,实测
|
||||
171px 1:1:名字 14/状态 16/预览 10 四行截断);标题下横向分隔线;无子代理徽章、无
|
||||
💬 跳转按钮;网格最后一位恒为「创建卡片」(虚线+)→ openAddPanel;入口卡无描边。
|
||||
- 顶部标题克制:控制室页只保留侧栏入口卡一个「控制室」——分栏标题栏对 wt-console
|
||||
不渲染 title(保留 ⇄/✕)、PaneBody singleConsole 不渲染标签栏、ConsolePane 头只留
|
||||
主题开关(右对齐)。
|
||||
- 分隔线:DIVIDER=4(分栏可拖分隔条更细)。
|
||||
- 冷会话消息预览(方案 A):binding() 对冷会话不载入文本;预热走 face.history({maxMessages:2})
|
||||
(运行期内建方法、非公开接口,只读无副作用)尾部扫 user/message 与 assistant/message 的
|
||||
text 块 → previewCache;sweepPreviews 在打开控制室时 + 控制室开着且会话快照变化防抖 6s
|
||||
|
||||
Reference in New Issue
Block a user