From 381b45502f1f7a2a463d4b9265260d3682f285be Mon Sep 17 00:00:00 2001 From: Aisland Date: Wed, 19 Aug 2026 21:00:22 +0800 Subject: [PATCH] polish: circle gap 4px + center layout-card arrow vertically with title --- 01_content/src/client/styles.ts | 5 +- .../worklogs/2026-08-16_worktable-v2.md | 12 +++ 04_test/arrow-mini.cjs | 74 +++++++++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 04_test/arrow-mini.cjs diff --git a/01_content/src/client/styles.ts b/01_content/src/client/styles.ts index c1245a3..1226197 100644 --- a/01_content/src/client/styles.ts +++ b/01_content/src/client/styles.ts @@ -164,7 +164,7 @@ export const css = [ '.dsh-wt_bindCircles{position:absolute;left:50%;top:50%;width:17px;height:7px;transform:translate(-50%,-50%)}', '.dsh-wt_bindCircles::before,.dsh-wt_bindCircles::after{content:\'\';position:absolute;top:50%;width:6px;height:6px;margin-top:-3px;border-radius:50%;box-sizing:border-box;border:1.2px solid currentColor;background:transparent}', '.dsh-wt_bindCircles::before{left:0}', - '.dsh-wt_bindCircles::after{left:11px}', + '.dsh-wt_bindCircles::after{left:10px}', '.dsh-wt_bindBtn[data-bound=true] .dsh-wt_bindCircles::before,.dsh-wt_bindBtn[data-bound=true] .dsh-wt_bindCircles::after{background:currentColor}', // 布局条目卡片 @@ -175,7 +175,8 @@ export const css = [ '.dsh-wt_layoutIcon{flex:none;font-size:15px}', '.dsh-wt_layoutText{flex:1;min-width:0;display:flex;flex-direction:column;gap:0}', '.dsh-wt_layoutName{font-size:12px;font-weight:400;line-height:17px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}', - '.dsh-wt_layoutArrow{flex:none;color:var(--dsw-alias-label-tertiary,#6e7683);font-size:14px;line-height:20px}', + // 箭头与项目名同一行高 + 字面中心对齐 + '.dsh-wt_layoutArrow{flex:none;display:inline-flex;align-items:center;height:18px;color:var(--dsw-alias-label-tertiary,#6e7683);font-size:14px;line-height:18px}', // 项目卡片统一:所有入驻项目卡片(data-wt-id 通用标记)与布局卡片同款常显框 '.dsh-wt_projects [data-wt-id]{border-color:var(--dsw-alias-border-l1,#262b36);background:var(--dsw-alias-fill-l1,rgba(255,255,255,.02))}', '.dsh-wt_projects [data-wt-id]:hover{border-color:var(--dsw-alias-state-accent-primary,#4f8ef7);background:var(--dsw-alias-fill-l1,rgba(255,255,255,.05))}', diff --git a/02_process/worklogs/2026-08-16_worktable-v2.md b/02_process/worklogs/2026-08-16_worktable-v2.md index 4e35179..510f300 100644 --- a/02_process/worklogs/2026-08-16_worktable-v2.md +++ b/02_process/worklogs/2026-08-16_worktable-v2.md @@ -814,6 +814,18 @@ functional-diag ERROR_COUNT: 0。 - 备注:纯客户端改动,F5 即生效。 +## 补记(圆点间距 4px + 布局卡箭头垂直对齐) + +- 用户反馈:① ○○/●● 间距再收一点(5px → 4px);② 布局卡右侧 › 箭头纵坐标偏下, + 要对齐项目标签栏中心。 +- 处理:圆点 second circle left 11px → 10px;箭头由 line-height 20px 裸文本改为 + inline-flex + align-items:center + height/line-height 18px(与项目名同高), + 去掉字形下沉带来的下偏(先试 translateY(-1px) 过矫 1.5px 偏高,去掉后误差 -0.5px)。 +- 验证(arrow-mini.cjs):gap=4 ✓;箭头字面中心 531.5 vs 卡片/项目名中心 532(偏差 -0.5px, + 亚像素级);functional-diag ERROR_COUNT: 0。 +- 备注:纯客户端改动,F5 即生效。 + + diff --git a/04_test/arrow-mini.cjs b/04_test/arrow-mini.cjs new file mode 100644 index 0000000..d7c086f --- /dev/null +++ b/04_test/arrow-mini.cjs @@ -0,0 +1,74 @@ +// arrow-mini.cjs — 箭头字面中心与卡片/项目名中心对齐 + 圆点间距 4px +const http = require('http'); +const { spawn } = require('child_process'); +const WebSocket = require('ws'); +const PORT = 9347; +const proc = spawn('C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe', [ + '--headless=new', '--disable-gpu', '--no-first-run', '--no-default-browser-check', + '--window-size=1440,900', '--force-device-scale-factor=1', + '--remote-debugging-port=' + PORT, + '--user-data-dir=C:\\Users\\SJL\\AppData\\Local\\Temp\\wt-chrome-arrow', + 'about:blank', +], { stdio: 'ignore' }); +const getJSON = (p) => new Promise((res, rej) => { + http.get({ host: '127.0.0.1', port: PORT, path: p }, (r) => { let d=''; r.on('data',c=>d+=c); r.on('end',()=>{try{res(JSON.parse(d))}catch(e){rej(e)}}) }).on('error', rej); +}); +const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); +(async () => { + let list = null; + for (let i = 0; i < 40; i++) { try { list = await getJSON('/json/list'); if (list && list.length) break; } catch {} await sleep(500); } + const target = list.find((t) => t.type === 'page') || list[0]; + const ws = new WebSocket(target.webSocketDebuggerUrl); + let id = 0; const pending = new Map(); + const send = (method, params) => new Promise((res) => { const mid = ++id; pending.set(mid, res); ws.send(JSON.stringify({ id: mid, method, params })); }); + ws.on('message', (raw) => { const m = JSON.parse(String(raw)); if (m.id && pending.has(m.id)) { pending.get(m.id)(m); pending.delete(m.id); } }); + await new Promise((r) => ws.on('open', r)); + await send('Runtime.enable'); + await send('Page.enable'); + await send('Page.addScriptToEvaluateOnNewDocument', { + source: "try{ if(window===window.top && location.origin==='http://127.0.0.1:3080'){ localStorage.setItem('dsh.worktable.projects.v1', JSON.stringify({order:[],lastUsed:{},hidden:[],nameOverrides:{},shortcuts:[],layouts:[{id:'t-layout',title:'L',top:null,left:null,main:[{id:'p1',title:'W',min:200,content:null}],chatWidth:{default:320,min:240,max:600},chatSide:'right',chatFullHeight:false}],bindings:{}})); } }catch(e){}", + }); + await send('Page.navigate', { url: 'http://127.0.0.1:3080/' }); + const evaluate = async (expr) => { + const r = await send('Runtime.evaluate', { expression: expr, returnByValue: true, awaitPromise: true }); + if (r.result && r.result.exceptionDetails) return { __error: (r.result.exceptionDetails.exception || {}).description || r.result.exceptionDetails.text }; + return r.result && r.result.result ? r.result.result.value : undefined; + }; + let ready = null; + for (let i = 0; i < 30; i++) { await sleep(1000); ready = await evaluate("!!window.__dshWorktable"); if (ready === true) break; } + await sleep(1500); + const step = await evaluate(`(function(){ + var out = {}; + try { + var card = document.querySelector('.dsh-wt_layout'); + var arrow = card && card.querySelector('.dsh-wt_layoutArrow'); + var name = card && card.querySelector('.dsh-wt_layoutName'); + var centerOf = function(r){ return (r.top + r.bottom) / 2; }; + if (card && arrow && name) { + var cr = card.getBoundingClientRect(); + var nr = name.getBoundingClientRect(); + // 字面(glyph)真实矩形:Range 选箭头文本节点 + var range = document.createRange(); + range.selectNodeContents(arrow); + var ar = range.getBoundingClientRect(); + out.cardCenter = Math.round(centerOf(cr) * 10) / 10; + out.nameCenter = Math.round(centerOf(nr) * 10) / 10; + out.arrowGlyphCenter = Math.round(centerOf(ar) * 10) / 10; + out.arrowDeltaFromCard = Math.round((centerOf(ar) - centerOf(cr)) * 10) / 10; + out.arrowDeltaFromName = Math.round((centerOf(ar) - centerOf(nr)) * 10) / 10; + var cs = getComputedStyle(arrow); + out.arrowLineHeight = cs.lineHeight; out.arrowFontSize = cs.fontSize; + } + // 圆点间距 + var btn = card && card.querySelector('.dsh-wt_bindBtn'); + if (btn) { + var b4 = getComputedStyle(btn.querySelector('.dsh-wt_bindCircles'), '::before'); + var b5 = getComputedStyle(btn.querySelector('.dsh-wt_bindCircles'), '::after'); + out.gap = (parseFloat(b5.left)||0) - (parseFloat(b4.width)||0); + } + } catch(e) { out.err = String(e); } + return JSON.stringify(out); + })()`); + console.log('ARROW:', JSON.stringify(step)); + ws.close(); proc.kill(); process.exit(0); +})().catch((e) => { console.error('FATAL', e && e.stack || e); try { proc.kill(); } catch {} process.exit(1); });