printbench 0.6.5 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -91,7 +91,8 @@ function onExported(payload: PrintBenchExportedPayload) {
91
91
  | `bedSizeMm` | `{ x, y, z }` | — | 宿主默认打印床体积(mm:X/Z 床面,Y 高度)。挂载时写入设置一次,之后仍可在布局区/设置中修改 |
92
92
  | `showBedVolume` | `boolean` | — | 宿主默认是否显示打印床线框。挂载时写入设置一次,之后仍可开关(未传时默认隐藏) |
93
93
  | `diagnosisZIndex` | `number` | `100` | 诊断浮层 `z-index`。也可在外层设 CSS 变量 `--printbench-diagnosis-z` |
94
- | `features` | `{ numeric?, primitives?, split?, autoSplit?, drafts?, extras?, restore?, layout?, importUnit?, hideEmpty?, hideTour?, hideStatusBar?, hidePanelModeToggle?, hidePreviewLighting?, … }` | 能力项默认 `false` | 进阶能力。缺省精简:左栏仅导入 / 零件 / 导出 / 快照。未开 `drafts` 时不读不写自动草稿。导入单位优先用文件声明,否则按包围盒尺寸推测 mm/cm/m 再换算到内部毫米;开 `importUnit` 时可再确认。`split` 为切面拆件;`autoSplit` 为「自动拆件」按钮(默认隐藏,需显式打开)。`restore` 为「复原到导入状态」按钮(默认隐藏,宿主需显式打开;完整工作台预设已开启)。`layout` 打开贴地 / 镜像 / 目标尺寸缩放 / 选面朝下与打印床体积。`hideEmpty` / `hideTour` / `hideStatusBar` / `hidePanelModeToggle` / `hidePreviewLighting` 为 `true` 时分别隐藏空画布提示、首次引导 Tour(可与 `extras` 同开)、底栏状态条、零件栏悬浮/通栏切换按钮、预览模式左上角灯光模式控件(默认显示)。 |
94
+ | `annotations` | `Annotation[]` \| `AnnotationDocument` \| `string` | — | 模型批注(世界坐标 mm)。需同时打开 `features.annotations` 才能编辑;详见下方「批注」 |
95
+ | `features` | `{ numeric?, primitives?, split?, autoSplit?, drafts?, extras?, restore?, layout?, importUnit?, hideEmpty?, hideTour?, hideStatusBar?, hidePanelModeToggle?, hidePreviewLighting?, annotations?, … }` | 能力项默认 `false` | 进阶能力。缺省精简:左栏仅导入 / 零件 / 导出 / 快照。未开 `drafts` 时不读不写自动草稿。导入单位优先用文件声明,否则按包围盒尺寸推测 mm/cm/m 再换算到内部毫米;开 `importUnit` 时可再确认。`split` 为切面拆件;`autoSplit` 为「自动拆件」按钮(默认隐藏,需显式打开)。`restore` 为「复原到导入状态」按钮(默认隐藏,宿主需显式打开;完整工作台预设已开启)。`layout` 打开贴地 / 镜像 / 目标尺寸缩放 / 选面朝下与打印床体积。`annotations` 打开模型批注(默认关闭,`PRINTBENCH_FULL_FEATURES` 也不含该项)。`hideEmpty` / `hideTour` / `hideStatusBar` / `hidePanelModeToggle` / `hidePreviewLighting` 为 `true` 时分别隐藏空画布提示、首次引导 Tour(可与 `extras` 同开)、底栏状态条、零件栏悬浮/通栏切换按钮、预览模式左上角灯光模式控件(默认显示)。 |
95
96
 
96
97
 
97
98
  嵌入预览示例(宿主列表 + 色板 + 自定义导出 + 按最长边缩放):
@@ -183,6 +184,7 @@ async function upload() {
183
184
  | `bbox` | `{ min, max, size, initialSize, unit, parts }` | 整模包围盒(含 `initialSize`)并附带同上的 `parts` |
184
185
  | `select-part` | `{ id, index, additive }` | 画布或零件树点选 |
185
186
  | `part-colors-change` | `Record<string, string>` | 工作台内改色时抛出(嵌入预览以 `partColors` 为准) |
187
+ | `annotations-change` | `{ schema, version, unit, coordinateSpace, fileName?, generatedAt, annotations, reason }` | 批注新增 / 修改 / 删除时抛出(`reason`: `add` \| `update` \| `remove`)。仅在 `features.annotations` 开启时触发 |
186
188
 
187
189
 
188
190
  `exported` 的 `format` 为 `'stl' | '3mf' | 'glb'`;多零件 STL 时 `fileName` 为 zip,`blob` 为打包后的文件。GLB 为单文件,零件色写入材质。
@@ -199,6 +201,59 @@ async function upload() {
199
201
  | `autoSplit(options?)` | 多零件接触面自动装配(≥2 件)。检测接触后一端保留凸起、一端挖槽,再加卡扣。`connector`: `'ballSnap'` \| `'sphere'` \| `'square'`(默认 `ballSnap` 爪扣);`connectorSize` 可选;`silent: true` 时不弹修复确认,未封闭则返回 `{ ok: false, needsRepair: true, repairPartNames }`。成功 `{ ok: true }`。 |
200
202
  | `getPartBounds()` | 同步返回与 `@parts` 相同结构的零件列表(含 `initialSize` / `size`)。无模型时为 `[]`。 |
201
203
  | `getBBox()` | 同步返回与 `@bbox` 相同结构的整模载荷(含 `parts`)。尚无诊断包围盒时为 `null`。 |
204
+ | `getAnnotations()` | 返回 `AnnotationDocument`(`schema: 'printbench.annotations'`)。功能关闭时仍会规范化 `annotations` prop 后返回,便于宿主随时开启。 |
205
+ | `exportAnnotations()` | 上面文档的格式化 JSON 字符串。 |
206
+ | `setAnnotations(input)` | 用数组 / 文档 / JSON 字符串替换批注列表。 |
207
+ | `addAnnotation(input)` | 以编程方式添加一条批注,返回新 `Annotation`;功能未开启时返回 `null`。 |
208
+
209
+ ### 批注(默认关闭)
210
+
211
+ 批注是**独立旁路数据**:只做锚点渲染与 JSON 序列化,不进入网格、不进入 STL / 3MF / GLB 导出,也不影响诊断结果。默认隐藏,需显式开启:
212
+
213
+ ```vue
214
+ <PrintBench
215
+ :features="{ annotations: true }"
216
+ :annotations="notes"
217
+ @annotations-change="notes = $event"
218
+ />
219
+ ```
220
+
221
+ 开启后右栏出现「检查」页签(诊断 / 批注),可点「放置批注」后在模型表面点上标注,支持级别、标题、说明与已解决标记。
222
+
223
+ 锚点使用**内部毫米世界坐标**(Y 轴向上)加 `partId`、命中面法线;零件被移动 / 旋转 / 镜像后仍可按 `partId` 重新挂接,`partId` 消失(拆件 / 布尔 / 合并)时标记为 `orphaned` 并保留原位置显示。
224
+
225
+ JSON 结构:
226
+
227
+ ```json
228
+ {
229
+ "schema": "printbench.annotations",
230
+ "version": 1,
231
+ "unit": "mm",
232
+ "coordinateSpace": "world",
233
+ "fileName": "part.glb",
234
+ "generatedAt": "2026-01-01T00:00:00.000Z",
235
+ "annotations": [
236
+ {
237
+ "id": "note_ab12cd34",
238
+ "position": [12.5, 8.0, -3.25],
239
+ "normal": [0, 1, 0],
240
+ "partId": "mesh_xxx",
241
+ "partName": "外壳",
242
+ "title": "批注 1",
243
+ "body": "此处壁厚不足",
244
+ "severity": "yellow",
245
+ "status": "open",
246
+ "createdAt": "2026-01-01T00:00:00.000Z",
247
+ "updatedAt": "2026-01-01T00:00:00.000Z",
248
+ "extra": { "ticket": 42 }
249
+ }
250
+ ]
251
+ }
252
+ ```
253
+
254
+ `severity` 取 `red` / `yellow` / `green` / `info`,`status` 取 `open` / `resolved`;`extra` 为宿主自定义字段,原样回传。
255
+
256
+ `@annotations-change` 在批注被新增 / 修改 / 删除时触发,`reason` 分别为 `add` / `update` / `remove`;把 payload 原样写回 `annotations` prop 不会造成回环。开启 `features.drafts` 时批注随草稿一起保存(关闭该特性时不写入草稿)。「审核报告」的 JSON / HTML 也会带出批注。
202
257
 
203
258
 
204
259
 
@@ -222,7 +277,7 @@ async function upload() {
222
277
  | --- | ------------------------------------------------------ |
223
278
  | 左栏 | 导入、导出、快照、零件树、上色、移动/旋转/缩放;`features` 打开后才有数值变换、布局(贴地/镜像/缩放/选面朝下)、基本体、拆件、草稿与观察工具 |
224
279
  | 画布 | 轨道旋转缩放;双击或 **F** 自适应;**复位视角** 回默认相机;开启 `layout` 后可在布局区/设置中显示打印床线框(默认隐藏) |
225
- | 右栏 | 诊断与测量浮层(右上,默认 `z-index: 100`),默认收起 |
280
+ | 右栏 | 诊断与测量浮层(右上,默认 `z-index: 100`),默认收起;开启 `features.annotations` 后标题变为「检查」,多出「批注」页签 |
226
281
  | 底栏 | 包围盒、内部单位 mm、体积、文件名;超床时提示超出轴 |
227
282
 
228
283
 
@@ -1 +1 @@
1
- .pb-select{position:relative;display:block;min-width:0;width:100%}.pb-select-trigger{display:flex;align-items:center;gap:6px;width:100%;min-width:0;margin:0;padding:5px 8px;background:var(--panel-2);color:var(--text);border:1px solid var(--border);border-radius:6px;font:inherit;font-size:12px;line-height:1.3;text-align:left;cursor:pointer;color-scheme:dark}.pb-select-trigger:hover:not(:disabled){border-color:var(--accent)}.pb-select-trigger:disabled{opacity:.45;cursor:not-allowed}.pb-select-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pb-select-chevron{flex:none;width:12px;height:12px;opacity:.75}.pb-select.open .pb-select-chevron{transform:rotate(180deg)}.pb-select-menu{position:fixed;z-index:80;margin:0;padding:4px;list-style:none;overflow:auto;background:var(--panel-2);color:var(--text);border:1px solid var(--border);border-radius:8px;box-shadow:var(--shadow);color-scheme:dark;font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;font-size:12px}.pb-select-option{padding:6px 8px;border-radius:5px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pb-select-option:hover,.pb-select-option.active{background:#5b8def2e}.pb-select-option.selected{color:var(--accent)}.unit-row>span[data-v-d70135e8]{flex:none;white-space:nowrap}.unit-row[data-v-d70135e8] .pb-select{flex:1;min-width:0}.settings-host[data-v-04a6df4b] .dialog{width:min(420px,calc(100% - 24px),92vw)}.row[data-v-04a6df4b]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 0;font-size:13px}.row .label[data-v-04a6df4b]{flex:1;min-width:0;color:var(--text)}.row[data-v-04a6df4b] .pb-select,.row>input[type=number][data-v-04a6df4b]{flex:0 0 auto;width:140px;max-width:46%}.row>input[type=number][data-v-04a6df4b]{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 8px;color:var(--text);color-scheme:dark}.section[data-v-04a6df4b]{margin:12px 0;padding-top:10px;border-top:1px solid var(--border)}.section-title[data-v-04a6df4b]{font-size:12px;font-weight:600;color:var(--muted, #9aa3b2);margin-bottom:8px}.section-title .unit[data-v-04a6df4b]{font-weight:400;opacity:.85}.checks[data-v-04a6df4b]{display:grid;grid-template-columns:1fr 1fr;gap:8px 12px;margin-bottom:8px;font-size:13px}.checks label[data-v-04a6df4b]{display:flex;align-items:center;gap:6px;min-width:0}.bed-xyz[data-v-04a6df4b]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.axis[data-v-04a6df4b]{display:flex;flex-direction:column;gap:4px;min-width:0;font-size:11px;color:var(--muted, #9aa3b2)}.axis input[data-v-04a6df4b]{width:100%;box-sizing:border-box;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 6px;color:var(--text);color-scheme:dark}.bed-presets[data-v-04a6df4b]{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}.preset[data-v-04a6df4b]{font-size:12px;padding:4px 8px;white-space:nowrap}.warn[data-v-b085aeeb]{color:#e07040;font-weight:600}:root{--bg: #0e1116;--panel: #171b22;--panel-2: #1e242e;--border: #2c3440;--text: #e8edf4;--muted: #8b95a5;--accent: #5b8def;--danger: #ff5c5c;--warn: #f0b429;--ok: #3dcc7a;--shadow: 0 8px 32px rgba(0, 0, 0, .35);font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root,.printbench-root *{box-sizing:border-box}.printbench-root{height:100%;min-height:0;background:var(--bg);color:var(--text);color-scheme:dark;font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root button,.printbench-root input,.printbench-root textarea{font:inherit;color:inherit;color-scheme:dark}.workbench{position:relative;display:grid;grid-template-rows:1fr 28px;grid-template-columns:292px 1fr;height:100%}.workbench.no-left{grid-template-columns:36px 1fr}.workbench.left-float{grid-template-columns:1fr}.workbench.left-float>.panel.parts{position:absolute;left:12px;top:12px;width:280px;max-height:calc(100% - 52px);z-index:12;grid-column:1;grid-row:1;border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);background:color-mix(in srgb,var(--panel) 94%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.workbench.left-float>.panel.parts.collapsed{width:36px;max-height:none;bottom:40px}.workbench.left-float>.canvas-wrap{grid-column:1;grid-row:1;min-width:0}.workbench.preview-shell{grid-template-rows:1fr;grid-template-columns:1fr}.item input.swatch{flex:none;width:22px;height:18px;padding:0;border:1px solid var(--border);border-radius:4px;background:transparent;cursor:pointer}.statusbar{grid-column:1 / -1}.panel{background:var(--panel);border-right:1px solid var(--border);display:flex;flex-direction:column;min-height:0}.workbench>.panel.right{position:absolute;right:12px;top:12px;width:280px;max-height:calc(100% - 52px);z-index:var(--printbench-diagnosis-z, 100);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);background:color-mix(in srgb,var(--panel) 94%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-right:1px solid var(--border);border-left:1px solid var(--border)}.workbench>.panel.right.collapsed{width:36px;max-height:none}.panel-hd{display:flex;align-items:center;gap:6px;padding:10px 12px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--border)}.panel-hd .ttl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.panel-toggle{flex:none;width:24px;height:24px;padding:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;color:var(--text);cursor:pointer;line-height:1;font-size:16px;display:inline-flex;align-items:center;justify-content:center}.panel-toggle:hover{border-color:var(--accent);color:var(--accent)}.panel-toggle .ico{width:14px;height:14px;display:block}.panel.collapsed .panel-hd{flex-direction:column;height:100%;padding:8px 4px;border-bottom:none;justify-content:flex-start}.panel.collapsed .panel-toggle{order:-1}.panel.collapsed .ttl{writing-mode:vertical-rl;flex:none;letter-spacing:.2em}.panel-bd{padding:10px;overflow:auto;flex:1;display:flex;flex-direction:column;gap:8px}.btn{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 10px;cursor:pointer}.btn:hover{border-color:var(--accent)}.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}.btn.danger{border-color:var(--danger);color:var(--danger)}.btn:disabled{opacity:.45;cursor:not-allowed}.canvas-wrap{position:relative;min-width:0;min-height:0;background:#12151c}.canvas-wrap canvas{width:100%;height:100%;display:block}.empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;color:var(--muted);text-align:center}.empty h2{color:var(--text);margin:0 0 8px;font-weight:600}.steps{display:flex;gap:18px;margin-top:16px;font-size:13px}.steps b{color:var(--accent)}.tree{display:flex;flex-direction:column;gap:2px;background:var(--panel-2);border:1px solid var(--border);border-radius:8px;padding:4px;min-height:120px;overflow-y:auto}.tree-empty{margin:0;padding:14px 8px;text-align:center;font-size:12px;color:var(--muted)}.item{position:relative;display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:6px;cursor:pointer}.item:hover{background:#5b8def14}.item.active{background:#263044}.item .idx{flex:none;width:18px;font-size:11px;color:var(--muted);text-align:right}.item .grow{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.item .rename-btn{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:auto;padding:2px 6px;font-size:11px;line-height:1.3;color:var(--text);opacity:0;pointer-events:none}.item:hover .rename-btn,.item:focus-within .rename-btn{opacity:1;pointer-events:auto}.item:hover .grow,.item:focus-within .grow{padding-right:40px}.item input[type=checkbox]{accent-color:var(--accent);margin:0}.hint{margin:0;font-size:11px;line-height:1.45;color:var(--muted)}.sec{margin:4px 0 0;padding:10px 0 2px;border-top:1px solid var(--border);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}.btn-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}.btn-grid .btn,.btn-row .btn{width:100%;font-size:12px;padding:6px 8px}.btn-grid.core-actions.compact,.btn-grid.tool-mode.compact{gap:4px}.btn-grid.core-actions.icon-text{grid-template-columns:1fr 1fr}.btn-grid.core-actions.icons-only{grid-template-columns:repeat(5,1fr)}.btn-grid.tool-mode{grid-template-columns:repeat(3,1fr)}.btn-grid.core-actions .btn.icon-btn,.btn-grid.tool-mode .btn.icon-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:4px 6px;font-size:11px;min-height:28px}.btn-grid.core-actions.icons-only .btn.icon-btn,.btn-grid.tool-mode.icons-only .btn.icon-btn{padding:4px}.btn-grid.core-actions .btn.icon-btn .ico,.btn-grid.tool-mode .btn.icon-btn .ico{width:14px;height:14px;flex:none;display:block}.btn-grid.core-actions .btn.icon-btn span,.btn-grid.tool-mode .btn.icon-btn span{line-height:1.2;white-space:nowrap}.btn-grid .pb-select{width:100%;min-width:0}.btn-row{display:flex;gap:6px}.split-list{display:flex;flex-direction:column;gap:6px}.split-list .btn-row .btn:first-child{flex:1;width:auto}.split-list .btn-row .btn.danger{flex:none;width:auto}.xyz{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;align-items:center;font-size:12px}.xyz>span{color:var(--muted)}.xyz input,.xyz .pb-select .pb-select-trigger{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 5px;color:var(--text);color-scheme:dark}.xyz input{text-align:center}.xyz .pb-select{grid-column:2 / -1;width:100%;min-width:0}.scale-row{display:flex;align-items:center;gap:6px;font-size:12px}.scale-row>span{color:var(--muted);flex:none}.scale-row input,.scale-row .pb-select .pb-select-trigger{min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 5px;color:var(--text);color-scheme:dark}.scale-row input{width:4.5rem;flex:none;text-align:center}.scale-row .pb-select{flex:1;min-width:0}.xyz-hd{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;font-size:10px;color:var(--muted);text-align:center;margin-bottom:-2px}.stack{display:flex;flex-direction:column;gap:6px}.stack .pb-select,.stack input[type=number]{width:100%;min-width:0}.stack input[type=number]{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 8px}.check{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}.diag{border-left:3px solid var(--border);padding:8px 10px;margin-bottom:8px;background:var(--panel-2);border-radius:0 6px 6px 0;cursor:pointer}.diag.red{border-color:var(--danger)}.diag.yellow{border-color:var(--warn)}.diag.green{border-color:var(--ok)}.diag h4{margin:0 0 4px;font-size:13px}.diag p{margin:0;font-size:12px;color:var(--muted)}.statusbar{display:flex;align-items:center;gap:16px;padding:0 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}.overlay{position:absolute;inset:0;background:#0000008c;display:flex;align-items:center;justify-content:center;z-index:40}.workbench>.overlay{grid-column:1 / -1;grid-row:1 / -1}.dialog{width:min(480px,calc(100% - 24px),92vw);max-width:100%;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);padding:18px}.dialog h3{margin:0 0 10px}.dialog .row{margin:10px 0;display:flex;gap:8px;align-items:center}.dialog .pb-select{min-width:0}.dialog .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:16px}.dialog .actions>.btn{flex:0 0 auto;white-space:nowrap}.dialog.help{width:min(640px,94vw);max-height:min(82vh,720px);overflow:auto}.dialog.help p{font-size:13px;line-height:1.55}.dialog .url-input{width:100%;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:8px 10px}.dialog .snapshot-preview{display:block;width:100%;max-height:min(52vh,420px);object-fit:contain;background:#12151c;border:1px solid var(--border);border-radius:8px}.toasts{position:fixed;top:16px;left:50%;transform:translate(-50%);display:flex;flex-direction:column;align-items:center;gap:8px;z-index:50;pointer-events:none}.toast{pointer-events:auto;padding:10px 14px;border-radius:8px;background:#1e242e;border:1px solid var(--border);color:var(--text);box-shadow:var(--shadow)}.toast.ok{background:#15261c;border-color:var(--ok)}.toast.fail{background:#2a1518;border-color:var(--danger)}.toast.info{background:#1e242e}.busy{position:absolute;inset:0;background:#0e11168c;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;cursor:wait;-webkit-user-select:none;user-select:none}.bar{width:180px;height:4px;background:#2a303c;border-radius:4px;overflow:hidden}.bar i{display:block;height:100%;width:40%;background:var(--accent);animation:slide 1s infinite}@keyframes slide{0%{transform:translate(-100%)}to{transform:translate(280%)}}.field{display:flex;align-items:center;gap:8px;margin:6px 0;font-size:13px}.field input,.field .pb-select{background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 6px;width:90px}.field .pb-select{padding:0;background:transparent;border:none}.field .pb-select .pb-select-trigger{padding:4px 6px;border-radius:4px}.tour{position:absolute;left:50%;top:72px;transform:translate(-50%);background:var(--panel);border:1px solid var(--accent);border-radius:10px;padding:14px 16px;z-index:8;width:360px}.preview-lighting{position:absolute;top:10px;left:10px;z-index:6;display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:8px;background:color-mix(in srgb,var(--panel) 92%,transparent);border:1px solid var(--border);box-shadow:var(--shadow);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);font-size:12px;color:var(--text);pointer-events:auto}.preview-lighting label{display:flex;align-items:center;gap:6px;margin:0;white-space:nowrap}.preview-lighting .pb-select{max-width:9.5em}.preview-lighting .pb-select .pb-select-trigger{padding:4px 8px}.preview-tag{position:absolute;top:10px;left:10px;background:#1d3a24;color:#9dffb0;padding:4px 8px;border-radius:4px;font-size:12px}.preview-tag.below-lighting{top:52px}.marquee{position:absolute;border:1px dashed var(--accent);background:#5b8def1f;pointer-events:none}.ctx{position:fixed;z-index:60;background:var(--panel);border:1px solid var(--border);border-radius:6px;min-width:140px;padding:4px}.ctx button{display:block;width:100%;text-align:left;background:none;border:none;padding:6px 8px;cursor:pointer}.ctx button:hover{background:var(--panel-2)}.clip-slider{position:absolute;top:12px;left:50%;transform:translate(-50%);background:#141820e0;padding:8px 12px;border-radius:8px;font-size:12px;display:flex;align-items:center;gap:8px;z-index:4}.clip-slider input{width:180px}.diag.active{outline:1px solid var(--accent)}.live-read{position:absolute;left:12px;bottom:12px;background:#141820d9;padding:6px 10px;border-radius:6px;font-size:13px;color:#ffe08a}
1
+ .pb-select{position:relative;display:block;min-width:0;width:100%}.pb-select-trigger{display:flex;align-items:center;gap:6px;width:100%;min-width:0;margin:0;padding:5px 8px;background:var(--panel-2);color:var(--text);border:1px solid var(--border);border-radius:6px;font:inherit;font-size:12px;line-height:1.3;text-align:left;cursor:pointer;color-scheme:dark}.pb-select-trigger:hover:not(:disabled){border-color:var(--accent)}.pb-select-trigger:disabled{opacity:.45;cursor:not-allowed}.pb-select-label{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.pb-select-chevron{flex:none;width:12px;height:12px;opacity:.75}.pb-select.open .pb-select-chevron{transform:rotate(180deg)}.pb-select-menu{position:fixed;z-index:9999;margin:0;padding:4px;list-style:none;overflow:auto;background:var(--panel-2);color:var(--text);border:1px solid var(--border);border-radius:8px;box-shadow:var(--shadow);color-scheme:dark;font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif;font-size:12px}.pb-select-option{padding:6px 8px;border-radius:5px;cursor:pointer;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.pb-select-option:hover,.pb-select-option.active{background:#5b8def2e}.pb-select-option.selected{color:var(--accent)}.unit-row>span[data-v-d70135e8]{flex:none;white-space:nowrap}.unit-row[data-v-d70135e8] .pb-select{flex:1;min-width:0}.settings-host[data-v-04a6df4b] .dialog{width:min(420px,calc(100% - 24px),92vw)}.row[data-v-04a6df4b]{display:flex;align-items:center;justify-content:space-between;gap:12px;margin:8px 0;font-size:13px}.row .label[data-v-04a6df4b]{flex:1;min-width:0;color:var(--text)}.row[data-v-04a6df4b] .pb-select,.row>input[type=number][data-v-04a6df4b]{flex:0 0 auto;width:140px;max-width:46%}.row>input[type=number][data-v-04a6df4b]{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 8px;color:var(--text);color-scheme:dark}.section[data-v-04a6df4b]{margin:12px 0;padding-top:10px;border-top:1px solid var(--border)}.section-title[data-v-04a6df4b]{font-size:12px;font-weight:600;color:var(--muted, #9aa3b2);margin-bottom:8px}.section-title .unit[data-v-04a6df4b]{font-weight:400;opacity:.85}.checks[data-v-04a6df4b]{display:grid;grid-template-columns:1fr 1fr;gap:8px 12px;margin-bottom:8px;font-size:13px}.checks label[data-v-04a6df4b]{display:flex;align-items:center;gap:6px;min-width:0}.bed-xyz[data-v-04a6df4b]{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:8px}.axis[data-v-04a6df4b]{display:flex;flex-direction:column;gap:4px;min-width:0;font-size:11px;color:var(--muted, #9aa3b2)}.axis input[data-v-04a6df4b]{width:100%;box-sizing:border-box;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 6px;color:var(--text);color-scheme:dark}.bed-presets[data-v-04a6df4b]{display:flex;flex-wrap:wrap;gap:6px;margin-top:10px}.preset[data-v-04a6df4b]{font-size:12px;padding:4px 8px;white-space:nowrap}.anno{display:flex;flex-direction:column;gap:8px}.anno-toolbar{display:flex;align-items:center;gap:8px}.anno-count{font-size:12px;color:var(--muted)}.anno-hint{margin:0;font-size:12px;color:var(--muted);line-height:1.5}.anno-item{border-left:3px solid var(--border);padding:8px 10px;background:var(--panel-2);border-radius:0 6px 6px 0;cursor:pointer}.anno-item.red{border-color:var(--danger)}.anno-item.yellow{border-color:var(--warn)}.anno-item.green{border-color:var(--ok)}.anno-item.info{border-color:var(--accent)}.anno-item.active{outline:1px solid var(--accent)}.anno-item-hd{display:flex;align-items:center;gap:6px;font-size:13px}.anno-item-hd b{font-weight:600;color:var(--muted)}.anno-dot{width:8px;height:8px;flex:none;border-radius:50%;background:var(--accent)}.anno-item.red .anno-dot{background:var(--danger)}.anno-item.yellow .anno-dot{background:var(--warn)}.anno-item.green .anno-dot{background:var(--ok)}.anno-title{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.anno-badge{flex:none;font-size:10px;padding:1px 5px;border-radius:4px;border:1px solid var(--border);color:var(--muted)}.anno-badge.ok{color:var(--ok);border-color:var(--ok)}.anno-badge.warn{color:var(--warn);border-color:var(--warn)}.anno-body{margin:4px 0 0;font-size:12px;color:var(--text);line-height:1.45;white-space:pre-wrap;word-break:break-word}.anno-meta{margin:4px 0 0;font-size:11px;color:var(--muted)}.anno-editor{display:flex;flex-direction:column;gap:6px;padding:8px;border:1px solid var(--border);border-radius:6px;background:var(--panel-2)}.anno-editor label{display:flex;flex-direction:column;gap:3px;font-size:11px;color:var(--muted)}.anno-editor input,.anno-editor textarea,.anno-editor select{width:100%;box-sizing:border-box;padding:5px 7px;font:inherit;font-size:12px;color:var(--text);background:var(--panel);border:1px solid var(--border);border-radius:5px;color-scheme:dark;resize:vertical}.anno-editor-actions{display:flex;gap:6px;flex-wrap:wrap}.diag-tabs{display:flex;gap:4px;margin-bottom:8px}.diag-tab{flex:1;padding:5px 8px;font:inherit;font-size:12px;color:var(--muted);background:var(--panel-2);border:1px solid var(--border);border-radius:6px;cursor:pointer}.diag-tab:hover{border-color:var(--accent)}.diag-tab.active{color:var(--text);border-color:var(--accent);background:color-mix(in srgb,var(--accent) 18%,var(--panel-2))}.diag-tab-count{margin-left:4px;font-size:10px;padding:0 4px;border-radius:8px;background:var(--accent);color:#0d1117}.warn[data-v-b085aeeb]{color:#e07040;font-weight:600}:root{--bg: #0e1116;--panel: #171b22;--panel-2: #1e242e;--border: #2c3440;--text: #e8edf4;--muted: #8b95a5;--accent: #5b8def;--danger: #ff5c5c;--warn: #f0b429;--ok: #3dcc7a;--shadow: 0 8px 32px rgba(0, 0, 0, .35);font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root,.printbench-root *{box-sizing:border-box}.printbench-root{height:100%;min-height:0;background:var(--bg);color:var(--text);color-scheme:dark;font-family:Segoe UI,PingFang SC,Microsoft YaHei,sans-serif}.printbench-root button,.printbench-root input,.printbench-root textarea{font:inherit;color:inherit;color-scheme:dark}.workbench{position:relative;display:grid;grid-template-rows:1fr 28px;grid-template-columns:292px 1fr;height:100%}.workbench.no-left{grid-template-columns:36px 1fr}.workbench.left-float{grid-template-columns:1fr}.workbench.left-float>.panel.parts{position:absolute;left:12px;top:12px;width:280px;max-height:calc(100% - 52px);z-index:12;grid-column:1;grid-row:1;border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);background:color-mix(in srgb,var(--panel) 94%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}.workbench.left-float>.panel.parts.collapsed{width:36px;max-height:none;bottom:40px}.workbench.left-float>.canvas-wrap{grid-column:1;grid-row:1;min-width:0}.workbench.preview-shell{grid-template-rows:1fr;grid-template-columns:1fr}.item input.swatch{flex:none;width:22px;height:18px;padding:0;border:1px solid var(--border);border-radius:4px;background:transparent;cursor:pointer}.statusbar{grid-column:1 / -1}.panel{background:var(--panel);border-right:1px solid var(--border);display:flex;flex-direction:column;min-height:0}.workbench>.panel.right{position:absolute;right:12px;top:12px;width:280px;max-height:calc(100% - 52px);z-index:var(--printbench-diagnosis-z, 100);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);background:color-mix(in srgb,var(--panel) 94%,transparent);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);border-right:1px solid var(--border);border-left:1px solid var(--border)}.workbench>.panel.right.collapsed{width:36px;max-height:none}.panel-hd{display:flex;align-items:center;gap:6px;padding:10px 12px;font-size:12px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted);border-bottom:1px solid var(--border)}.panel-hd .ttl{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.panel-toggle{flex:none;width:24px;height:24px;padding:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;color:var(--text);cursor:pointer;line-height:1;font-size:16px;display:inline-flex;align-items:center;justify-content:center}.panel-toggle:hover{border-color:var(--accent);color:var(--accent)}.panel-toggle .ico{width:14px;height:14px;display:block}.panel.collapsed .panel-hd{flex-direction:column;height:100%;padding:8px 4px;border-bottom:none;justify-content:flex-start}.panel.collapsed .panel-toggle{order:-1}.panel.collapsed .ttl{writing-mode:vertical-rl;flex:none;letter-spacing:.2em}.panel-bd{padding:10px;overflow:auto;flex:1;display:flex;flex-direction:column;gap:8px}.btn{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 10px;cursor:pointer}.btn:hover{border-color:var(--accent)}.btn.primary{background:var(--accent);border-color:var(--accent);color:#fff}.btn.danger{border-color:var(--danger);color:var(--danger)}.btn:disabled{opacity:.45;cursor:not-allowed}.canvas-wrap{position:relative;min-width:0;min-height:0;background:#12151c}.canvas-wrap canvas{width:100%;height:100%;display:block}.empty{position:absolute;inset:0;display:flex;flex-direction:column;align-items:center;justify-content:center;pointer-events:none;color:var(--muted);text-align:center}.empty h2{color:var(--text);margin:0 0 8px;font-weight:600}.steps{display:flex;gap:18px;margin-top:16px;font-size:13px}.steps b{color:var(--accent)}.tree{display:flex;flex-direction:column;gap:2px;background:var(--panel-2);border:1px solid var(--border);border-radius:8px;padding:4px;min-height:120px;overflow-y:auto}.tree-empty{margin:0;padding:14px 8px;text-align:center;font-size:12px;color:var(--muted)}.item{position:relative;display:flex;align-items:center;gap:8px;padding:7px 8px;border-radius:6px;cursor:pointer}.item:hover{background:#5b8def14}.item.active{background:#263044}.item .idx{flex:none;width:18px;font-size:11px;color:var(--muted);text-align:right}.item .grow{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font-size:13px}.item .rename-btn{position:absolute;right:6px;top:50%;transform:translateY(-50%);width:auto;padding:2px 6px;font-size:11px;line-height:1.3;color:var(--text);opacity:0;pointer-events:none}.item:hover .rename-btn,.item:focus-within .rename-btn{opacity:1;pointer-events:auto}.item:hover .grow,.item:focus-within .grow{padding-right:40px}.item input[type=checkbox]{accent-color:var(--accent);margin:0}.hint{margin:0;font-size:11px;line-height:1.45;color:var(--muted)}.sec{margin:4px 0 0;padding:10px 0 2px;border-top:1px solid var(--border);font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--muted)}.btn-grid{display:grid;grid-template-columns:1fr 1fr;gap:6px}.btn-grid .btn,.btn-row .btn{width:100%;font-size:12px;padding:6px 8px}.btn-grid.core-actions.compact,.btn-grid.tool-mode.compact{gap:4px}.btn-grid.core-actions.icon-text{grid-template-columns:1fr 1fr}.btn-grid.core-actions.icons-only{grid-template-columns:repeat(5,1fr)}.btn-grid.tool-mode{grid-template-columns:repeat(3,1fr)}.btn-grid.core-actions .btn.icon-btn,.btn-grid.tool-mode .btn.icon-btn{display:inline-flex;align-items:center;justify-content:center;gap:4px;padding:4px 6px;font-size:11px;min-height:28px}.btn-grid.core-actions.icons-only .btn.icon-btn,.btn-grid.tool-mode.icons-only .btn.icon-btn{padding:4px}.btn-grid.core-actions .btn.icon-btn .ico,.btn-grid.tool-mode .btn.icon-btn .ico{width:14px;height:14px;flex:none;display:block}.btn-grid.core-actions .btn.icon-btn span,.btn-grid.tool-mode .btn.icon-btn span{line-height:1.2;white-space:nowrap}.btn-grid .pb-select{width:100%;min-width:0}.btn-row{display:flex;gap:6px}.split-list{display:flex;flex-direction:column;gap:6px}.split-list .btn-row .btn:first-child{flex:1;width:auto}.split-list .btn-row .btn.danger{flex:none;width:auto}.xyz{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;align-items:center;font-size:12px}.xyz>span{color:var(--muted)}.xyz input,.xyz .pb-select .pb-select-trigger{width:100%;min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 5px;color:var(--text);color-scheme:dark}.xyz input{text-align:center}.xyz .pb-select{grid-column:2 / -1;width:100%;min-width:0}.scale-row{display:flex;align-items:center;gap:6px;font-size:12px}.scale-row>span{color:var(--muted);flex:none}.scale-row input,.scale-row .pb-select .pb-select-trigger{min-width:0;background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 5px;color:var(--text);color-scheme:dark}.scale-row input{width:4.5rem;flex:none;text-align:center}.scale-row .pb-select{flex:1;min-width:0}.xyz-hd{display:grid;grid-template-columns:48px 1fr 1fr 1fr;gap:4px;font-size:10px;color:var(--muted);text-align:center;margin-bottom:-2px}.stack{display:flex;flex-direction:column;gap:6px}.stack .pb-select,.stack input[type=number]{width:100%;min-width:0}.stack input[type=number]{background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:5px 8px}.check{display:flex;align-items:center;gap:6px;font-size:12px;color:var(--muted)}.diag{border-left:3px solid var(--border);padding:8px 10px;margin-bottom:8px;background:var(--panel-2);border-radius:0 6px 6px 0;cursor:pointer}.diag.red{border-color:var(--danger)}.diag.yellow{border-color:var(--warn)}.diag.green{border-color:var(--ok)}.diag h4{margin:0 0 4px;font-size:13px}.diag p{margin:0;font-size:12px;color:var(--muted)}.statusbar{display:flex;align-items:center;gap:16px;padding:0 12px;font-size:12px;color:var(--muted);background:var(--panel);border-top:1px solid var(--border)}.overlay{position:absolute;inset:0;background:#0000008c;display:flex;align-items:center;justify-content:center;z-index:40}.workbench>.overlay{grid-column:1 / -1;grid-row:1 / -1}.dialog{width:min(480px,calc(100% - 24px),92vw);max-width:100%;background:var(--panel);border:1px solid var(--border);border-radius:10px;box-shadow:var(--shadow);padding:18px}.dialog h3{margin:0 0 10px}.dialog .row{margin:10px 0;display:flex;gap:8px;align-items:center}.dialog .pb-select{min-width:0}.dialog .actions{display:flex;flex-wrap:wrap;justify-content:flex-end;gap:8px;margin-top:16px}.dialog .actions>.btn{flex:0 0 auto;white-space:nowrap}.dialog.help{width:min(640px,94vw);max-height:min(82vh,720px);overflow:auto}.dialog.help p{font-size:13px;line-height:1.55}.dialog .url-input{width:100%;background:var(--panel-2);border:1px solid var(--border);border-radius:6px;padding:8px 10px}.dialog .snapshot-preview{display:block;width:100%;max-height:min(52vh,420px);object-fit:contain;background:#12151c;border:1px solid var(--border);border-radius:8px}.toasts{position:fixed;top:16px;left:50%;transform:translate(-50%);display:flex;flex-direction:column;align-items:center;gap:8px;z-index:50;pointer-events:none}.toast{pointer-events:auto;padding:10px 14px;border-radius:8px;background:#1e242e;border:1px solid var(--border);color:var(--text);box-shadow:var(--shadow)}.toast.ok{background:#15261c;border-color:var(--ok)}.toast.fail{background:#2a1518;border-color:var(--danger)}.toast.info{background:#1e242e}.busy{position:absolute;inset:0;background:#0e11168c;display:flex;flex-direction:column;align-items:center;justify-content:center;z-index:30;cursor:wait;-webkit-user-select:none;user-select:none}.bar{width:180px;height:4px;background:#2a303c;border-radius:4px;overflow:hidden}.bar i{display:block;height:100%;width:40%;background:var(--accent);animation:slide 1s infinite}@keyframes slide{0%{transform:translate(-100%)}to{transform:translate(280%)}}.field{display:flex;align-items:center;gap:8px;margin:6px 0;font-size:13px}.field input,.field .pb-select{background:var(--panel-2);border:1px solid var(--border);border-radius:4px;padding:4px 6px;width:90px}.field .pb-select{padding:0;background:transparent;border:none}.field .pb-select .pb-select-trigger{padding:4px 6px;border-radius:4px}.tour{position:absolute;left:50%;top:72px;transform:translate(-50%);background:var(--panel);border:1px solid var(--accent);border-radius:10px;padding:14px 16px;z-index:8;width:360px}.preview-lighting{position:absolute;top:10px;left:10px;z-index:6;display:flex;align-items:center;gap:6px;padding:6px 8px;border-radius:8px;background:color-mix(in srgb,var(--panel) 92%,transparent);border:1px solid var(--border);box-shadow:var(--shadow);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);font-size:12px;color:var(--text);pointer-events:auto}.preview-lighting label{display:flex;align-items:center;gap:6px;margin:0;white-space:nowrap}.preview-lighting .pb-select{max-width:9.5em}.preview-lighting .pb-select .pb-select-trigger{padding:4px 8px}.preview-tag{position:absolute;top:10px;left:10px;background:#1d3a24;color:#9dffb0;padding:4px 8px;border-radius:4px;font-size:12px}.preview-tag.below-lighting{top:52px}.marquee{position:absolute;border:1px dashed var(--accent);background:#5b8def1f;pointer-events:none}.ctx{position:fixed;z-index:60;background:var(--panel);border:1px solid var(--border);border-radius:6px;min-width:140px;padding:4px}.ctx button{display:block;width:100%;text-align:left;background:none;border:none;padding:6px 8px;cursor:pointer}.ctx button:hover{background:var(--panel-2)}.clip-slider{position:absolute;top:12px;left:50%;transform:translate(-50%);background:#141820e0;padding:8px 12px;border-radius:8px;font-size:12px;display:flex;align-items:center;gap:8px;z-index:4}.clip-slider input{width:180px}.diag.active{outline:1px solid var(--accent)}.live-read{position:absolute;left:12px;bottom:12px;background:#141820d9;padding:6px 10px;border-radius:6px;font-size:13px;color:#ffe08a}